Bug 1056516 - use AutoTArray for spacingBuffer and hyphenBuffer in BreakAndMeasureText. draft
authorJeremy Chen <jeremychen@mozilla.com>
Sun, 19 Feb 2017 17:36:55 +0800
changeset 486700 0d3884ccad2a986f04f3a1952b6150d87a73d76b
parent 486570 698de2db1b16a5ef3c6a39f0f72885e69aee4022
child 486701 95f62f8176cffe20e2b3633ee0858b8050519cd8
push id46037
push userjichen@mozilla.com
push dateSun, 19 Feb 2017 09:37:40 +0000
bugs1056516
milestone54.0a1
Bug 1056516 - use AutoTArray for spacingBuffer and hyphenBuffer in BreakAndMeasureText. MozReview-Commit-ID: CnSfpZqoYpE
gfx/src/nsFontMetrics.cpp
gfx/thebes/gfxTextRun.cpp
gfx/thebes/gfxTextRun.h
layout/generic/nsTextFrame.cpp
--- a/gfx/src/nsFontMetrics.cpp
+++ b/gfx/src/nsFontMetrics.cpp
@@ -79,17 +79,17 @@ private:
     }
 
     RefPtr<gfxTextRun> mTextRun;
 };
 
 class StubPropertyProvider : public gfxTextRun::PropertyProvider {
 public:
     virtual void GetHyphenationBreaks(gfxTextRun::Range aRange,
-                                      bool* aBreakBefore) {
+                                      nsTArray<bool>& aBreakBefore) {
         NS_ERROR("This shouldn't be called because we never call BreakAndMeasureText");
     }
     virtual mozilla::StyleHyphens GetHyphensOption() {
         NS_ERROR("This shouldn't be called because we never call BreakAndMeasureText");
         return mozilla::StyleHyphens::None;
     }
     virtual gfxFloat GetHyphenWidth() {
         NS_ERROR("This shouldn't be called because we never enable hyphens");
--- a/gfx/thebes/gfxTextRun.cpp
+++ b/gfx/thebes/gfxTextRun.cpp
@@ -828,18 +828,16 @@ gfxTextRun::MeasureText(Range aRange,
             font, Range(ligatureRange.end, end),
             aBoundingBoxType, aRefDrawTarget, aProvider,
             iter.GetGlyphRun()->mOrientation, &accumulatedMetrics);
     }
 
     return accumulatedMetrics;
 }
 
-#define MEASUREMENT_BUFFER_SIZE 100
-
 uint32_t
 gfxTextRun::BreakAndMeasureText(uint32_t aStart, uint32_t aMaxLength,
                                 bool aLineBreakBefore, gfxFloat aWidth,
                                 PropertyProvider *aProvider,
                                 SuppressBreak aSuppressBreak,
                                 gfxFloat *aTrimWhitespace,
                                 bool aWhitespaceCanHang,
                                 Metrics *aMetrics,
@@ -849,24 +847,25 @@ gfxTextRun::BreakAndMeasureText(uint32_t
                                 uint32_t *aLastBreak,
                                 bool aCanWordWrap,
                                 gfxBreakPriority *aBreakPriority)
 {
     aMaxLength = std::min(aMaxLength, GetLength() - aStart);
 
     NS_ASSERTION(aStart + aMaxLength <= GetLength(), "Substring out of range");
 
-    Range bufferRange(aStart, aStart +
-        std::min<uint32_t>(aMaxLength, MEASUREMENT_BUFFER_SIZE));
-    PropertyProvider::Spacing spacingBuffer[MEASUREMENT_BUFFER_SIZE];
+    Range bufferRange(aStart, aStart + aMaxLength);
+    AutoTArray<PropertyProvider::Spacing, 100> spacingBuffer;
+    spacingBuffer.AppendElements(bufferRange.Length());
     bool haveSpacing = aProvider && (mFlags & gfxTextRunFactory::TEXT_ENABLE_SPACING) != 0;
     if (haveSpacing) {
-        GetAdjustedSpacing(this, bufferRange, aProvider, spacingBuffer);
+        GetAdjustedSpacing(this, bufferRange, aProvider, spacingBuffer.Elements());
     }
-    bool hyphenBuffer[MEASUREMENT_BUFFER_SIZE];
+    AutoTArray<bool, 100> hyphenBuffer;
+    hyphenBuffer.AppendElements(bufferRange.Length());
     bool haveHyphenation = aProvider &&
         (aProvider->GetHyphensOption() == StyleHyphens::Auto ||
          (aProvider->GetHyphensOption() == StyleHyphens::Manual &&
           (mFlags & gfxTextRunFactory::TEXT_ENABLE_HYPHEN_BREAKS) != 0));
     if (haveHyphenation) {
         aProvider->GetHyphenationBreaks(bufferRange, hyphenBuffer);
     }
 
@@ -883,29 +882,16 @@ gfxTextRun::BreakAndMeasureText(uint32_t
     uint32_t end = aStart + aMaxLength;
     bool lastBreakUsedHyphenation = false;
 
     Range ligatureRange(aStart, end);
     ShrinkToLigatureBoundaries(&ligatureRange);
 
     uint32_t i;
     for (i = aStart; i < end; ++i) {
-        if (i >= bufferRange.end) {
-            // Fetch more spacing and hyphenation data
-            bufferRange.start = i;
-            bufferRange.end = std::min(aStart + aMaxLength,
-                                       i + MEASUREMENT_BUFFER_SIZE);
-            if (haveSpacing) {
-                GetAdjustedSpacing(this, bufferRange, aProvider, spacingBuffer);
-            }
-            if (haveHyphenation) {
-                aProvider->GetHyphenationBreaks(bufferRange, hyphenBuffer);
-            }
-        }
-
         // There can't be a word-wrap break opportunity at the beginning of the
         // line: if the width is too small for even one character to fit, it
         // could be the first and last break opportunity on the line, and that
         // would trigger an infinite loop.
         if (aSuppressBreak != eSuppressAllBreaks &&
             (aSuppressBreak != eSuppressInitialBreak || i > aStart)) {
             bool atNaturalBreak = mCharacterGlyphs[i].CanBreakBefore() == 1;
             bool atHyphenationBreak = !atNaturalBreak &&
--- a/gfx/thebes/gfxTextRun.h
+++ b/gfx/thebes/gfxTextRun.h
@@ -184,17 +184,18 @@ public:
      * NOTE that requested spacing may not actually be applied, if the textrun
      * is unable to apply it in some context. Exception: spacing around a
      * whitespace character MUST always be applied.
      */
     class PropertyProvider {
     public:
         // Detect hyphenation break opportunities in the given range; breaks
         // not at cluster boundaries will be ignored.
-        virtual void GetHyphenationBreaks(Range aRange, bool *aBreakBefore) = 0;
+        virtual void GetHyphenationBreaks(Range aRange,
+                                          nsTArray<bool>& aBreakBefore) = 0;
 
         // Returns the provider's hyphenation setting, so callers can decide
         // whether it is necessary to call GetHyphenationBreaks.
         // Result is an StyleHyphens value.
         virtual mozilla::StyleHyphens GetHyphensOption() = 0;
 
         // Returns the extra width that will be consumed by a hyphen. This should
         // be constant for a given textrun.
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -3136,17 +3136,17 @@ public:
 
   // Call this after construction if you're not going to reflow the text
   void InitializeForDisplay(bool aTrimAfter);
 
   void InitializeForMeasure();
 
   virtual void GetSpacing(Range aRange, Spacing* aSpacing);
   virtual gfxFloat GetHyphenWidth();
-  virtual void GetHyphenationBreaks(Range aRange, bool* aBreakBefore);
+  virtual void GetHyphenationBreaks(Range aRange, nsTArray<bool>& aBreakBefore);
   virtual StyleHyphens GetHyphensOption() {
     return mTextStyle->mHyphens;
   }
 
   virtual already_AddRefed<DrawTarget> GetDrawTarget() {
     return CreateReferenceDrawTarget(GetFrame());
   }
 
@@ -3574,25 +3574,25 @@ PropertyProvider::GetHyphenWidth()
 {
   if (mHyphenWidth < 0) {
     mHyphenWidth = GetFontGroup()->GetHyphenWidth(this);
   }
   return mHyphenWidth + mLetterSpacing;
 }
 
 void
-PropertyProvider::GetHyphenationBreaks(Range aRange, bool* aBreakBefore)
+PropertyProvider::GetHyphenationBreaks(Range aRange, nsTArray<bool>& aBreakBefore)
 {
   NS_PRECONDITION(IsInBounds(mStart, mLength, aRange), "Range out of bounds");
   NS_PRECONDITION(mLength != INT32_MAX, "Can't call this with undefined length");
 
   if (!mTextStyle->WhiteSpaceCanWrap(mFrame) ||
       mTextStyle->mHyphens == StyleHyphens::None)
   {
-    memset(aBreakBefore, false, aRange.Length() * sizeof(bool));
+    memset(aBreakBefore.Elements(), false, aRange.Length() * sizeof(bool));
     return;
   }
 
   // Iterate through the original-string character runs
   nsSkipCharsRunIterator run(
       mStart, nsSkipCharsRunIterator::LENGTH_UNSKIPPED_ONLY, aRange.Length());
   run.SetSkippedOffset(aRange.start);
   // We need to visit skipped characters so that we can detect SHY
@@ -3609,17 +3609,18 @@ PropertyProvider::GetHyphenationBreaks(R
     if (run.IsSkipped()) {
       // Check if there's a soft hyphen which would let us hyphenate before
       // the next non-skipped character. Don't look at soft hyphens followed
       // by other skipped characters, we won't use them.
       allowHyphenBreakBeforeNextChar =
         mFrag->CharAt(run.GetOriginalOffset() + run.GetRunLength() - 1) == CH_SHY;
     } else {
       int32_t runOffsetInSubstring = run.GetSkippedOffset() - aRange.start;
-      memset(aBreakBefore + runOffsetInSubstring, false, run.GetRunLength()*sizeof(bool));
+      memset(aBreakBefore.Elements() + runOffsetInSubstring, false,
+             run.GetRunLength() * sizeof(bool));
       // Don't allow hyphen breaks at the start of the line
       aBreakBefore[runOffsetInSubstring] = allowHyphenBreakBeforeNextChar &&
           (!(mFrame->GetStateBits() & TEXT_START_OF_LINE) ||
            run.GetSkippedOffset() > mStart.GetSkippedOffset());
       allowHyphenBreakBeforeNextChar = false;
     }
   }
 
@@ -8365,39 +8366,34 @@ nsTextFrame::AddInlineMinISizeForFlow(ns
       aData->OptionallyBreak();
     }
     aData->mCurrentLine += provider.GetFontMetrics()->EmHeight();
     aData->mTrailingWhitespace = 0;
     return;
   }
 
   AutoTArray<bool,BIG_TEXT_NODE_SIZE> hyphBuffer;
-  bool *hyphBreakBefore = nullptr;
-  if (hyphenating) {
-    hyphBreakBefore = hyphBuffer.AppendElements(flowEndInTextRun - start,
-                                                fallible);
-    if (hyphBreakBefore) {
-      provider.GetHyphenationBreaks(Range(start, flowEndInTextRun),
-                                    hyphBreakBefore);
-    }
+  if (hyphenating &&
+      hyphBuffer.AppendElements(flowEndInTextRun - start, fallible)) {
+    provider.GetHyphenationBreaks(Range(start, flowEndInTextRun), hyphBuffer);
   }
 
   for (uint32_t i = start, wordStart = start; i <= flowEndInTextRun; ++i) {
     bool preformattedNewline = false;
     bool preformattedTab = false;
     if (i < flowEndInTextRun) {
       // XXXldb Shouldn't we be including the newline as part of the
       // segment that it ends rather than part of the segment that it
       // starts?
       preformattedNewline = preformatNewlines && textRun->CharIsNewline(i);
       preformattedTab = preformatTabs && textRun->CharIsTab(i);
       if (!textRun->CanBreakLineBefore(i) &&
           !preformattedNewline &&
           !preformattedTab &&
-          (!hyphBreakBefore || !hyphBreakBefore[i - start]))
+          (hyphBuffer.IsEmpty() || !hyphBuffer[i - start]))
       {
         // we can't break here (and it's not the end of the flow)
         continue;
       }
     }
 
     if (i > wordStart) {
       nscoord width = NSToCoordCeilClamped(
@@ -8434,18 +8430,18 @@ nsTextFrame::AddInlineMinISizeForFlow(ns
         AdvanceToNextTab(aData->mCurrentLine, this, textRun, tabWidth);
       aData->mCurrentLine = nscoord(afterTab + spacing.mAfter);
       wordStart = i + 1;
     } else if (i < flowEndInTextRun ||
         (i == textRun->GetLength() &&
          (textRun->GetFlags() & nsTextFrameUtils::TEXT_HAS_TRAILING_BREAK))) {
       if (preformattedNewline) {
         aData->ForceBreak();
-      } else if (i < flowEndInTextRun && hyphBreakBefore &&
-                 hyphBreakBefore[i - start]) {
+      } else if (i < flowEndInTextRun && !hyphBuffer.IsEmpty() &&
+                 hyphBuffer[i - start]) {
         aData->OptionallyBreak(NSToCoordRound(provider.GetHyphenWidth()));
       } else {
         aData->OptionallyBreak();
       }
       wordStart = i;
     }
   }