Bug 1241631. Make nsTextFrame::GetTrimmedOffsets take a flags word parameter. r=mats draft
authorRobert O'Callahan <robert@ocallahan.org>
Tue, 01 Mar 2016 11:49:30 +1300
changeset 335611 db74d44704ea55d419ef257fdaf0f5948dcbd456
parent 335327 faa614e2ad4eff5e04c9886bd39f63ebe20fe00c
child 335612 64140aa868694af281be8ff9ef3986ee7dea418b
push id11833
push userrocallahan@mozilla.com
push dateTue, 01 Mar 2016 00:44:12 +0000
reviewersmats
bugs1241631
milestone47.0a1
Bug 1241631. Make nsTextFrame::GetTrimmedOffsets take a flags word parameter. r=mats MozReview-Commit-ID: CD601keACDq
layout/generic/nsTextFrame.cpp
layout/generic/nsTextFrame.h
layout/svg/SVGTextFrame.cpp
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -2779,21 +2779,20 @@ GetEndOfTrimmedText(const nsTextFragment
     aIterator->AdvanceSkipped(-1);
     if (!IsTrimmableSpace(aFrag, aIterator->GetOriginalOffset(), aStyleText))
       return aIterator->GetSkippedOffset() + 1;
   }
   return aStart;
 }
 
 nsTextFrame::TrimmedOffsets
-nsTextFrame::GetTrimmedOffsets(const nsTextFragment* aFrag,
-                               bool aTrimAfter, bool aPostReflow)
+nsTextFrame::GetTrimmedOffsets(const nsTextFragment* aFrag, uint32_t aFlags)
 {
   NS_ASSERTION(mTextRun, "Need textrun here");
-  if (aPostReflow) {
+  if (aFlags & TRIM_POST_REFLOW) {
     // This should not be used during reflow. We need our TEXT_REFLOW_FLAGS
     // to be set correctly.  If our parent wasn't reflowed due to the frame
     // tree being too deep then the return value doesn't matter.
     NS_ASSERTION(!(GetStateBits() & NS_FRAME_FIRST_REFLOW) ||
                  (GetParent()->GetStateBits() &
                   NS_FRAME_TOO_DEEP_IN_FRAME_TREE),
                  "Can only call this on frames that have been reflowed");
     NS_ASSERTION(!(GetStateBits() & NS_FRAME_IN_REFLOW),
@@ -2802,25 +2801,27 @@ nsTextFrame::GetTrimmedOffsets(const nsT
 
   TrimmedOffsets offsets = { GetContentOffset(), GetContentLength() };
   const nsStyleText* textStyle = StyleText();
   // Note that pre-line newlines should still allow us to trim spaces
   // for display
   if (textStyle->WhiteSpaceIsSignificant())
     return offsets;
 
-  if (!aPostReflow || (GetStateBits() & TEXT_START_OF_LINE)) {
+  if ((aFlags & TRIM_BEFORE) &&
+      (!(aFlags & TRIM_POST_REFLOW) || (GetStateBits() & TEXT_START_OF_LINE))) {
     int32_t whitespaceCount =
       GetTrimmableWhitespaceCount(aFrag,
                                   offsets.mStart, offsets.mLength, 1);
     offsets.mStart += whitespaceCount;
     offsets.mLength -= whitespaceCount;
   }
 
-  if (aTrimAfter && (!aPostReflow || (GetStateBits() & TEXT_END_OF_LINE))) {
+  if ((aFlags & TRIM_AFTER) &&
+      (!(aFlags & TRIM_POST_REFLOW) || (GetStateBits() & TEXT_END_OF_LINE))) {
     // This treats a trailing 'pre-line' newline as trimmable. That's fine,
     // it's actually what we want since we want whitespace before it to
     // be trimmed.
     int32_t whitespaceCount =
       GetTrimmableWhitespaceCount(aFrag,
                                   offsets.GetEnd() - 1, offsets.mLength, -1);
     offsets.mLength -= whitespaceCount;
   }
@@ -3475,27 +3476,30 @@ PropertyProvider::GetHyphenationBreaks(u
     }
   }
 }
 
 void
 PropertyProvider::InitializeForDisplay(bool aTrimAfter)
 {
   nsTextFrame::TrimmedOffsets trimmed =
-    mFrame->GetTrimmedOffsets(mFrag, aTrimAfter);
+    mFrame->GetTrimmedOffsets(mFrag, nsTextFrame::TRIM_BEFORE |
+        (aTrimAfter ? nsTextFrame::TRIM_AFTER : 0) |
+        nsTextFrame::TRIM_POST_REFLOW);
   mStart.SetOriginalOffset(trimmed.mStart);
   mLength = trimmed.mLength;
   SetupJustificationSpacing(true);
 }
 
 void
 PropertyProvider::InitializeForMeasure()
 {
   nsTextFrame::TrimmedOffsets trimmed =
-    mFrame->GetTrimmedOffsets(mFrag, true, false);
+    mFrame->GetTrimmedOffsets(mFrag, nsTextFrame::TRIM_BEFORE |
+        nsTextFrame::TRIM_AFTER);
   mStart.SetOriginalOffset(trimmed.mStart);
   mLength = trimmed.mLength;
   SetupJustificationSpacing(false);
 }
 
 
 static uint32_t GetSkippedDistance(const gfxSkipCharsIterator& aStart,
                                    const gfxSkipCharsIterator& aEnd)
@@ -3511,17 +3515,19 @@ PropertyProvider::SetupJustificationSpac
   if (!(mFrame->GetStateBits() & TEXT_JUSTIFICATION_ENABLED))
     return;
 
   gfxSkipCharsIterator start(mStart), end(mStart);
   // We can't just use our mLength here; when InitializeForDisplay is
   // called with false for aTrimAfter, we still shouldn't be assigning
   // justification space to any trailing whitespace.
   nsTextFrame::TrimmedOffsets trimmed =
-    mFrame->GetTrimmedOffsets(mFrag, true, aPostReflow);
+    mFrame->GetTrimmedOffsets(mFrag, nsTextFrame::TRIM_BEFORE |
+        nsTextFrame::TRIM_AFTER |
+        (aPostReflow ? nsTextFrame::TRIM_POST_REFLOW : 0));
   end.AdvanceOriginal(trimmed.mLength);
   gfxSkipCharsIterator realEnd(end);
   ComputeJustification(start.GetOriginalOffset(),
                        end.GetOriginalOffset() - start.GetOriginalOffset());
 
   auto assign = mFrame->GetJustificationAssignment();
   mTotalJustificationGaps =
     JustificationUtils::CountGaps(mJustificationInfo, assign);
@@ -7262,17 +7268,18 @@ nsIFrame::FrameSearchResult
 nsTextFrame::PeekOffsetNoAmount(bool aForward, int32_t* aOffset)
 {
   NS_ASSERTION(aOffset && *aOffset <= GetContentLength(), "aOffset out of range");
 
   gfxSkipCharsIterator iter = EnsureTextRun(nsTextFrame::eInflated);
   if (!mTextRun)
     return CONTINUE_EMPTY;
 
-  TrimmedOffsets trimmed = GetTrimmedOffsets(mContent->GetText(), true);
+  TrimmedOffsets trimmed = GetTrimmedOffsets(mContent->GetText(),
+      TRIM_BEFORE | TRIM_AFTER | TRIM_POST_REFLOW);
   // Check whether there are nonskipped characters in the trimmmed range
   return (iter.ConvertOriginalToSkipped(trimmed.GetEnd()) >
          iter.ConvertOriginalToSkipped(trimmed.mStart)) ? FOUND : CONTINUE;
 }
 
 /**
  * This class iterates through the clusters before or after the given
  * aPosition (which is a content offset). You can test each cluster
@@ -7364,17 +7371,18 @@ nsTextFrame::PeekOffsetCharacter(bool aF
   IsSelectable(&selectable, &selectStyle);
   if (selectStyle == NS_STYLE_USER_SELECT_ALL)
     return CONTINUE_UNSELECTABLE;
 
   gfxSkipCharsIterator iter = EnsureTextRun(nsTextFrame::eInflated);
   if (!mTextRun)
     return CONTINUE_EMPTY;
 
-  TrimmedOffsets trimmed = GetTrimmedOffsets(mContent->GetText(), false);
+  TrimmedOffsets trimmed = GetTrimmedOffsets(mContent->GetText(),
+      TRIM_BEFORE | TRIM_POST_REFLOW);
 
   // A negative offset means "end of frame".
   int32_t startOffset = GetContentOffset() + (*aOffset < 0 ? contentLength : *aOffset);
 
   if (!aForward) {
     // If at the beginning of the line, look at the previous continuation
     for (int32_t i = std::min(trimmed.GetEnd(), startOffset) - 1;
          i >= trimmed.mStart; --i) {
@@ -7499,17 +7507,18 @@ ClusterIterator::ClusterIterator(nsTextF
   mIterator = aTextFrame->EnsureTextRun(nsTextFrame::eInflated);
   if (!aTextFrame->GetTextRun(nsTextFrame::eInflated)) {
     mDirection = 0; // signal failure
     return;
   }
   mIterator.SetOriginalOffset(aPosition);
 
   mFrag = aTextFrame->GetContent()->GetText();
-  mTrimmed = aTextFrame->GetTrimmedOffsets(mFrag, true);
+  mTrimmed = aTextFrame->GetTrimmedOffsets(mFrag, nsTextFrame::TRIM_BEFORE |
+      nsTextFrame::TRIM_AFTER | nsTextFrame::TRIM_POST_REFLOW);
 
   int32_t textOffset = aTextFrame->GetContentOffset();
   int32_t textLen = aTextFrame->GetContentLength();
   if (!mWordBreaks.AppendElements(textLen + 1)) {
     mDirection = 0; // signal failure
     return;
   }
   memset(mWordBreaks.Elements(), false, (textLen + 1)*sizeof(bool));
@@ -9071,17 +9080,18 @@ nsTextFrame::TrimTrailingWhiteSpace(Draw
 
   gfxSkipCharsIterator start =
     EnsureTextRun(nsTextFrame::eInflated, aDrawTarget);
   NS_ENSURE_TRUE(mTextRun, result);
 
   uint32_t trimmedStart = start.GetSkippedOffset();
 
   const nsTextFragment* frag = mContent->GetText();
-  TrimmedOffsets trimmed = GetTrimmedOffsets(frag, true);
+  TrimmedOffsets trimmed = GetTrimmedOffsets(frag,
+      TRIM_BEFORE | TRIM_AFTER | TRIM_POST_REFLOW);
   gfxSkipCharsIterator trimmedEndIter = start;
   const nsStyleText* textStyle = StyleText();
   gfxFloat delta = 0;
   uint32_t trimmedEnd = trimmedEndIter.ConvertOriginalToSkipped(trimmed.GetEnd());
   
   if (!(GetStateBits() & TEXT_TRIMMED_TRAILING_WHITESPACE) &&
       trimmed.GetEnd() < GetContentEnd()) {
     gfxSkipCharsIterator end = trimmedEndIter;
@@ -9245,19 +9255,23 @@ nsTextFrame::GetRenderedText(uint32_t aS
     gfxSkipCharsIterator iter =
       textFrame->EnsureTextRun(nsTextFrame::eInflated);
     if (!textFrame->mTextRun) {
       break;
     }
     gfxSkipCharsIterator tmpIter = iter;
 
     // Skip to the start of the text run, past ignored chars at start of line
-    TrimmedOffsets trimmedOffsets = textFrame->GetTrimmedOffsets(textFrag,
-       textFrame->IsAtEndOfLine() && LineEndsInHardLineBreak(textFrame) &&
-       aTrimTrailingWhitespace == TrailingWhitespace::TRIM_TRAILING_WHITESPACE);
+    uint32_t flags = TRIM_BEFORE | TRIM_POST_REFLOW;
+    if (textFrame->IsAtEndOfLine() && LineEndsInHardLineBreak(textFrame) &&
+        aTrimTrailingWhitespace == TrailingWhitespace::TRIM_TRAILING_WHITESPACE) {
+      flags |= TRIM_AFTER;
+    }
+    TrimmedOffsets trimmedOffsets =
+        textFrame->GetTrimmedOffsets(textFrag, flags);
     bool trimmedSignificantNewline =
         trimmedOffsets.GetEnd() < GetContentEnd() &&
         HasSignificantTerminalNewline();
     uint32_t skippedToRenderedStringOffset = offsetInRenderedString -
         tmpIter.ConvertOriginalToSkipped(trimmedOffsets.mStart);
     uint32_t nextOffsetInRenderedString =
         tmpIter.ConvertOriginalToSkipped(trimmedOffsets.GetEnd()) +
         (trimmedSignificantNewline ? 1 : 0) + skippedToRenderedStringOffset;
--- a/layout/generic/nsTextFrame.h
+++ b/layout/generic/nsTextFrame.h
@@ -535,18 +535,23 @@ public:
   // Get the DOM content range mapped by this frame after excluding
   // whitespace subject to start-of-line and end-of-line trimming.
   // The textrun must have been created before calling this.
   struct TrimmedOffsets {
     int32_t mStart;
     int32_t mLength;
     int32_t GetEnd() const { return mStart + mLength; }
   };
+  enum {
+    TRIM_BEFORE = 0x01,
+    TRIM_AFTER = 0x02,
+    TRIM_POST_REFLOW = 0x04
+  };
   TrimmedOffsets GetTrimmedOffsets(const nsTextFragment* aFrag,
-                                   bool aTrimAfter, bool aPostReflow = true);
+                                   uint32_t aFlags);
 
   // Similar to Reflow(), but for use from nsLineLayout
   void ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
                   DrawTarget* aDrawTarget,
                   nsHTMLReflowMetrics& aMetrics, nsReflowStatus& aStatus);
 
   bool IsFloatingFirstLetterChild() const;
 
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -1066,17 +1066,19 @@ TextRenderedRun::GetClipEdges(nscoord& a
   // Get the offset/length of the whole nsTextFrame.
   frameOffset = mFrame->GetContentOffset();
   frameLength = mFrame->GetContentLength();
 
   // Trim the whole-nsTextFrame offset/length to remove any leading/trailing
   // white space, as the nsTextFrame when painting does not include them when
   // interpreting clip edges.
   nsTextFrame::TrimmedOffsets trimmedOffsets =
-    mFrame->GetTrimmedOffsets(mFrame->GetContent()->GetText(), true);
+    mFrame->GetTrimmedOffsets(mFrame->GetContent()->GetText(),
+        nsTextFrame::TRIM_BEFORE | nsTextFrame::TRIM_AFTER |
+        nsTextFrame::TRIM_POST_REFLOW);
   TrimOffsets(frameOffset, frameLength, trimmedOffsets);
 
   // Convert the trimmed whole-nsTextFrame offset/length into skipped
   // characters.
   ConvertOriginalToSkipped(it, frameOffset, frameLength);
 
   // Measure the advance width in the text run between the start of
   // frame's content and the start of the rendered run's content,
@@ -2054,17 +2056,19 @@ TextRenderedRunIterator::Next()
                                    frame->GetTextRun(nsTextFrame::eInflated),
                                    mFrameIterator.DominantBaseline(),
                                    mFontSizeScaleFactor);
 
     // Trim the offset/length to remove any leading/trailing white space.
     uint32_t untrimmedOffset = offset;
     uint32_t untrimmedLength = length;
     nsTextFrame::TrimmedOffsets trimmedOffsets =
-      frame->GetTrimmedOffsets(frame->GetContent()->GetText(), true);
+      frame->GetTrimmedOffsets(frame->GetContent()->GetText(),
+          nsTextFrame::TRIM_BEFORE | nsTextFrame::TRIM_AFTER |
+          nsTextFrame::TRIM_POST_REFLOW);
     TrimOffsets(offset, length, trimmedOffsets);
     charIndex += offset - untrimmedOffset;
 
     // Get the position and rotation of the character that begins this
     // rendered run.
     pt = Root()->mPositions[charIndex].mPosition;
     rotate = Root()->mPositions[charIndex].mAngle;
 
@@ -2571,17 +2575,19 @@ CharIterator::IsOriginalCharTrimmed() co
   if (mFrameForTrimCheck != TextFrame()) {
     // Since we do a lot of trim checking, we cache the trimmed offsets and
     // lengths while we are in the same frame.
     mFrameForTrimCheck = TextFrame();
     uint32_t offset = mFrameForTrimCheck->GetContentOffset();
     uint32_t length = mFrameForTrimCheck->GetContentLength();
     nsIContent* content = mFrameForTrimCheck->GetContent();
     nsTextFrame::TrimmedOffsets trim =
-      mFrameForTrimCheck->GetTrimmedOffsets(content->GetText(), true);
+      mFrameForTrimCheck->GetTrimmedOffsets(content->GetText(),
+          nsTextFrame::TRIM_BEFORE | nsTextFrame::TRIM_AFTER |
+          nsTextFrame::TRIM_POST_REFLOW);
     TrimOffsets(offset, length, trim);
     mTrimmedOffset = offset;
     mTrimmedLength = length;
   }
 
   // A character is trimmed if it is outside the mTrimmedOffset/mTrimmedLength
   // range and it is not a significant newline character.
   uint32_t index = mSkipCharsIterator.GetOriginalOffset();
@@ -4704,17 +4710,19 @@ SVGTextFrame::DetermineCharPositions(nsT
 
     // Any characters not in a frame, e.g. when display:none.
     for (uint32_t i = 0; i < frit.UndisplayedCharacters(); i++) {
       aPositions.AppendElement(position);
     }
 
     // Any white space characters trimmed at the start of the line of text.
     nsTextFrame::TrimmedOffsets trimmedOffsets =
-      frame->GetTrimmedOffsets(frame->GetContent()->GetText(), true);
+      frame->GetTrimmedOffsets(frame->GetContent()->GetText(),
+          nsTextFrame::TRIM_BEFORE | nsTextFrame::TRIM_AFTER |
+          nsTextFrame::TRIM_POST_REFLOW);
     while (it.GetOriginalOffset() < trimmedOffsets.mStart) {
       aPositions.AppendElement(position);
       it.AdvanceOriginal(1);
     }
 
     // If a ligature was started in the previous frame, we should record
     // the ligature's start position, not any partial position.
     while (it.GetOriginalOffset() < frame->GetContentEnd() &&