Bug 1056516 - use AutoTArray for spacingBuffer and hyphenBuffer in BreakAndMeasureText.
MozReview-Commit-ID: CnSfpZqoYpE
--- 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;
}
}