Bug 1342951, part 2 - Allow SVGTextFrame's CharIterator helper to be used before reflow. r=heycam
authorJonathan Watt <jwatt@jwatt.org>
Thu, 17 Aug 2017 16:11:43 +0100
changeset 429101 af56ade91b5ed63fbb4b53c89ff397300af6372f
parent 429100 545efe0fed92454e52c94e146295a69f8b8e02ef
child 429102 f574c304f748b44a501a0cde67e4d34174b348a2
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1342951
milestone57.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 1342951, part 2 - Allow SVGTextFrame's CharIterator helper to be used before reflow. r=heycam MozReview-Commit-ID: Hs4uno5RZMu
layout/svg/SVGTextFrame.cpp
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -2139,17 +2139,18 @@ public:
    * @param aSVGTextFrame The SVGTextFrame whose characters to iterate
    *   through.
    * @param aFilter Indicates which characters to iterate over.
    * @param aSubtree A content subtree to track whether the current character
    *   is within.
    */
   CharIterator(SVGTextFrame* aSVGTextFrame,
                CharacterFilter aFilter,
-               nsIContent* aSubtree = nullptr);
+               nsIContent* aSubtree,
+               bool aPostReflow = true);
 
   /**
    * Returns whether the iterator is finished.
    */
   bool AtEnd() const
   {
     return !mFrameIterator.Current();
   }
@@ -2412,29 +2413,37 @@ private:
    */
   uint32_t mGlyphUndisplayedCharacters;
 
   /**
    * The scale factor to apply to glyph advances returned by
    * GetGlyphAdvance etc. to take into account textLength="".
    */
   float mLengthAdjustScaleFactor;
+
+  /**
+   * Whether the instance of this class is being used after reflow has occurred
+   * or not.
+   */
+  bool mPostReflow;
 };
 
 CharIterator::CharIterator(SVGTextFrame* aSVGTextFrame,
                            CharIterator::CharacterFilter aFilter,
-                           nsIContent* aSubtree)
+                           nsIContent* aSubtree,
+                           bool aPostReflow)
   : mFilter(aFilter),
     mFrameIterator(FrameIfAnonymousChildReflowed(aSVGTextFrame), aSubtree),
     mFrameForTrimCheck(nullptr),
     mTrimmedOffset(0),
     mTrimmedLength(0),
     mTextElementCharIndex(0),
     mGlyphStartTextElementCharIndex(0),
     mLengthAdjustScaleFactor(aSVGTextFrame->mLengthAdjustScaleFactor)
+  , mPostReflow(aPostReflow)
 {
   if (!AtEnd()) {
     mSkipCharsIterator = TextFrame()->EnsureTextRun(nsTextFrame::eInflated);
     mTextRun = TextFrame()->GetTextRun(nsTextFrame::eInflated);
     mTextElementCharIndex = mFrameIterator.UndisplayedCharacters();
     UpdateGlyphStartTextElementCharIndex();
     if (!MatchesFilter()) {
       Next();
@@ -2545,17 +2554,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(),
+                                            /* aTrimAfter */ true,
+                                            mPostReflow);
     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();
@@ -4522,17 +4533,17 @@ SVGTextFrame::ResolvePositionsForNode(ns
 
 bool
 SVGTextFrame::ResolvePositions(nsTArray<gfxPoint>& aDeltas,
                                bool aRunPerGlyph)
 {
   NS_ASSERTION(mPositions.IsEmpty(), "expected mPositions to be empty");
   RemoveStateBits(NS_STATE_SVG_POSITIONING_MAY_USE_PERCENTAGES);
 
-  CharIterator it(this, CharIterator::eOriginal);
+  CharIterator it(this, CharIterator::eOriginal, /* aSubtree */ nullptr);
   if (it.AtEnd()) {
     return false;
   }
 
   // We assume the first character position is (0,0) unless we later see
   // otherwise, and note it as unaddressable if it is.
   bool firstCharUnaddressable = it.IsOriginalCharUnaddressable();
   mPositions.AppendElement(CharPosition::Unspecified(firstCharUnaddressable));
@@ -4722,32 +4733,33 @@ ShiftAnchoredChunk(nsTArray<mozilla::Cha
 void
 SVGTextFrame::AdjustChunksForLineBreaks()
 {
   nsBlockFrame* block = nsLayoutUtils::GetAsBlock(PrincipalChildList().FirstChild());
   NS_ASSERTION(block, "expected block frame");
 
   nsBlockFrame::LineIterator line = block->LinesBegin();
 
-  CharIterator it(this, CharIterator::eOriginal);
+  CharIterator it(this, CharIterator::eOriginal, /* aSubtree */ nullptr);
   while (!it.AtEnd() && line != block->LinesEnd()) {
     if (it.TextFrame() == line->mFirstChild) {
       mPositions[it.TextElementCharIndex()].mStartOfChunk = true;
       line++;
     }
     it.AdvancePastCurrentFrame();
   }
 }
 
 void
 SVGTextFrame::AdjustPositionsForClusters()
 {
   nsPresContext* presContext = PresContext();
 
-  CharIterator it(this, CharIterator::eClusterOrLigatureGroupMiddle);
+  CharIterator it(this, CharIterator::eClusterOrLigatureGroupMiddle,
+                  /* aSubtree */ nullptr);
   while (!it.AtEnd()) {
     // Find the start of the cluster/ligature group.
     uint32_t charIndex = it.TextElementCharIndex();
     uint32_t startIndex = it.GlyphStartTextElementCharIndex();
 
     mPositions[charIndex].mClusterOrLigatureGroupMiddle = true;
 
     // Don't allow different rotations on ligature parts.
@@ -4888,17 +4900,18 @@ SVGTextFrame::GetStartOffset(nsIFrame* a
   return length->GetAnimValue(tp) * GetOffsetScale(aTextPathFrame);
 }
 
 void
 SVGTextFrame::DoTextPathLayout()
 {
   nsPresContext* context = PresContext();
 
-  CharIterator it(this, CharIterator::eClusterAndLigatureGroupStart);
+  CharIterator it(this, CharIterator::eClusterAndLigatureGroupStart,
+                  /* aSubtree */ nullptr);
   while (!it.AtEnd()) {
     nsIFrame* textPathFrame = it.TextPathFrame();
     if (!textPathFrame) {
       // Skip past this frame if we're not in a text path.
       it.AdvancePastCurrentFrame();
       continue;
     }
 
@@ -4958,17 +4971,17 @@ SVGTextFrame::DoTextPathLayout()
   }
 }
 
 void
 SVGTextFrame::DoAnchoring()
 {
   nsPresContext* presContext = PresContext();
 
-  CharIterator it(this, CharIterator::eOriginal);
+  CharIterator it(this, CharIterator::eOriginal, /* aSubtree */ nullptr);
 
   // Don't need to worry about skipped or trimmed characters.
   while (!it.AtEnd() &&
          (it.IsOriginalCharSkipped() || it.IsOriginalCharTrimmed())) {
     it.Next();
   }
 
   bool vertical = GetWritingMode().IsVertical();