From 1e55ae83f625292970bbb39d0c4247a820551c36 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 18 Dec 2008 16:05:16 +1300 Subject: [PATCH] Backed out changeset dcd1ad7a918e --- gfx/thebes/public/gfxTextRunWordCache.h | 3 +- gfx/thebes/src/gfxFont.cpp | 4 -- layout/generic/crashtests/430332-1.html | 17 ----- layout/generic/crashtests/crashtests.list | 1 - layout/generic/nsTextFrameThebes.cpp | 42 +++-------- layout/generic/nsTextFrameUtils.h | 5 +- layout/generic/nsTextRunTransformations.cpp | 106 +++++++++++++++++++++++++--- layout/generic/nsTextRunTransformations.h | 29 ++++---- 8 files changed, 120 insertions(+), 87 deletions(-) delete mode 100644 layout/generic/crashtests/430332-1.html diff --git a/gfx/thebes/public/gfxTextRunWordCache.h b/gfx/thebes/public/gfxTextRunWordCache.h index cf2d22fd4a..99015a821f 100644 --- a/gfx/thebes/public/gfxTextRunWordCache.h +++ b/gfx/thebes/public/gfxTextRunWordCache.h @@ -46,8 +46,7 @@ */ class THEBES_API gfxTextRunWordCache { public: - enum { TEXT_IN_CACHE = 0x10000000, - TEXT_UNUSED_FLAGS = 0xE0000000 }; + enum { TEXT_IN_CACHE = 0x10000000 }; /** * Create a textrun using cached words. diff --git a/gfx/thebes/src/gfxFont.cpp b/gfx/thebes/src/gfxFont.cpp index 77ddfad369..b5ec902a92 100644 --- a/gfx/thebes/src/gfxFont.cpp +++ b/gfx/thebes/src/gfxFont.cpp @@ -1395,10 +1395,6 @@ gfxTextRun::~gfxTextRun() #ifdef DEBUG_TEXT_RUN_STORAGE_METRICS AccountStorageForTextRun(this, -1); #endif -#ifdef DEBUG - // Make it easy to detect a dead text run - mFlags = 0xFFFFFFFF; -#endif NS_RELEASE(mFontGroup); MOZ_COUNT_DTOR(gfxTextRun); } diff --git a/layout/generic/crashtests/430332-1.html b/layout/generic/crashtests/430332-1.html deleted file mode 100644 index c9ba002299..0000000000 --- a/layout/generic/crashtests/430332-1.html +++ /dev/null @@ -1,17 +0,0 @@ - - - -ab cd -ab cd -ab cd -ab cd -ab cd -ab cd -ab cd -ab cdef - - - diff --git a/layout/generic/crashtests/crashtests.list b/layout/generic/crashtests/crashtests.list index 844891bd56..27e2217195 100644 --- a/layout/generic/crashtests/crashtests.list +++ b/layout/generic/crashtests/crashtests.list @@ -153,7 +153,6 @@ load 425253-1.html load 426272-1.html load 428263-1.html load 429981-1.html -load 430332-1.html load 430352-1.html load 437156-1.html load 438259-1.html diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index fe981547d3..63c1b5890f 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -725,18 +725,6 @@ public: aCapitalize, mContext); } - void Finish() { - NS_ASSERTION(!(mTextRun->GetFlags() & - (gfxTextRunWordCache::TEXT_UNUSED_FLAGS | - nsTextFrameUtils::TEXT_UNUSED_FLAG)), - "Flag set that should never be set! (memory safety error?)"); - if (mTextRun->GetFlags() & nsTextFrameUtils::TEXT_IS_TRANSFORMED) { - nsTransformedTextRun* transformedTextRun = - static_cast(mTextRun); - transformedTextRun->FinishSettingProperties(mContext); - } - } - gfxTextRun* mTextRun; gfxContext* mContext; PRUint32 mOffsetIntoTextRun; @@ -748,7 +736,6 @@ private: nsAutoTArray mMappedFlows; nsAutoTArray mLineBreakBeforeFrames; nsAutoTArray,10> mBreakSinks; - nsAutoTArray mTextRunsToDelete; nsLineBreaker mLineBreaker; gfxTextRun* mCurrentFramesAllSameTextRun; gfxContext* mContext; @@ -1172,23 +1159,14 @@ void BuildTextRunsScanner::FlushFrames(PRBool aFlushLineBreaks, PRBool aSuppress if (NS_SUCCEEDED(rv) && trailingLineBreak && textRun && !aSuppressTrailingBreak) { textRun->SetFlagBits(nsTextFrameUtils::TEXT_HAS_TRAILING_BREAK); } - PRUint32 i; for (i = 0; i < mBreakSinks.Length(); ++i) { if (!mBreakSinks[i]->mExistingTextRun || mBreakSinks[i]->mChangedBreaks) { // TODO cause frames associated with the textrun to be reflowed, if they // aren't being reflowed already! } - mBreakSinks[i]->Finish(); } mBreakSinks.Clear(); - - for (i = 0; i < mTextRunsToDelete.Length(); ++i) { - gfxTextRun* textRun = mTextRunsToDelete[i]; - gTextRuns->RemoveFromCache(textRun); - delete textRun; - } - mTextRunsToDelete.Clear(); } mCanStopOnThisLine = PR_TRUE; @@ -1504,18 +1482,15 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer) TextRunMappedFlow dummyMappedFlow; TextRunUserData* userData; - TextRunUserData* userDataToDestroy; // If the situation is particularly simple (and common) we don't need to // allocate userData. if (mMappedFlows.Length() == 1 && !mMappedFlows[0].mEndFrame && mMappedFlows[0].mStartFrame->GetContentOffset() == 0) { userData = &dummyData; - userDataToDestroy = nsnull; dummyData.mMappedFlows = &dummyMappedFlow; } else { userData = static_cast (nsMemory::Alloc(sizeof(TextRunUserData) + mMappedFlows.Length()*sizeof(TextRunMappedFlow))); - userDataToDestroy = userData; userData->mMappedFlows = reinterpret_cast(userData + 1); } userData->mMappedFlowCount = mMappedFlows.Length(); @@ -1592,7 +1567,7 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer) // then expand. nsAutoTArray tempBuf; if (!tempBuf.AppendElements(contentLength)) { - DestroyUserData(userDataToDestroy); + DestroyUserData(userData); return nsnull; } PRUint8* bufStart = tempBuf.Elements(); @@ -1622,7 +1597,7 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer) // Check for out-of-memory in gfxSkipCharsBuilder if (!builder.IsOK()) { - DestroyUserData(userDataToDestroy); + DestroyUserData(userData); return nsnull; } @@ -1657,7 +1632,7 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer) nsTextFrame* firstFrame = mMappedFlows[0].mStartFrame; gfxFontGroup* fontGroup = GetFontGroupForFrame(firstFrame); if (!fontGroup) { - DestroyUserData(userDataToDestroy); + DestroyUserData(userData); return nsnull; } @@ -1764,7 +1739,7 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer) } } if (!textRun) { - DestroyUserData(userDataToDestroy); + DestroyUserData(userData); return nsnull; } @@ -1777,10 +1752,11 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer) if (mSkipIncompleteTextRuns) { mSkipIncompleteTextRuns = !TextContainsLineBreakerWhiteSpace(textPtr, transformedLength, mDoubleByteText); - // Arrange for this textrun to be deleted the next time the linebreaker - // is flushed out - mTextRunsToDelete.AppendElement(textRun); - DestroyUserData(userDataToDestroy); + + // Nuke the textrun + gTextRuns->RemoveFromCache(textRun); + delete textRun; + DestroyUserData(userData); return nsnull; } diff --git a/layout/generic/nsTextFrameUtils.h b/layout/generic/nsTextFrameUtils.h index a11184e277..ea411745c7 100644 --- a/layout/generic/nsTextFrameUtils.h +++ b/layout/generic/nsTextFrameUtils.h @@ -78,10 +78,7 @@ public: // We normally don't use this break opportunity because the following text // will have a break opportunity at the start, but it's useful for line // layout to know about it in case the following content is not text - TEXT_HAS_TRAILING_BREAK = 0x4000000, - - // We don't currently use these flgas - TEXT_UNUSED_FLAG = 0x8000000 + TEXT_HAS_TRAILING_BREAK = 0x4000000 }; /** diff --git a/layout/generic/nsTextRunTransformations.cpp b/layout/generic/nsTextRunTransformations.cpp index 53023e4cc6..34f6fb5b9f 100644 --- a/layout/generic/nsTextRunTransformations.cpp +++ b/layout/generic/nsTextRunTransformations.cpp @@ -72,7 +72,7 @@ nsTransformedTextRun::SetCapitalization(PRUint32 aStart, PRUint32 aLength, memset(mCapitalize.Elements(), 0, GetLength()*sizeof(PRPackedBool)); } memcpy(mCapitalize.Elements() + aStart, aCapitalization, aLength*sizeof(PRPackedBool)); - mNeedsRebuild = PR_TRUE; + mFactory->RebuildTextRun(this, aRefContext); } PRBool @@ -82,20 +82,76 @@ nsTransformedTextRun::SetPotentialLineBreaks(PRUint32 aStart, PRUint32 aLength, { PRBool changed = gfxTextRun::SetPotentialLineBreaks(aStart, aLength, aBreakBefore, aRefContext); - if (changed) { - mNeedsRebuild = PR_TRUE; - } + mFactory->RebuildTextRun(this, aRefContext); return changed; } +PRBool +nsTransformedTextRun::SetLineBreaks(PRUint32 aStart, PRUint32 aLength, + PRBool aLineBreakBefore, PRBool aLineBreakAfter, + gfxFloat* aAdvanceWidthDelta, + gfxContext* aRefContext) +{ + nsTArray newBreaks; + PRUint32 i; + PRBool changed = PR_FALSE; + for (i = 0; i < mLineBreaks.Length(); ++i) { + PRUint32 pos = mLineBreaks[i]; + if (pos >= aStart) + break; + newBreaks.AppendElement(pos); + } + if (aLineBreakBefore != (i < mLineBreaks.Length() && + mLineBreaks[i] == aStart)) { + changed = PR_TRUE; + } + if (aLineBreakBefore) { + nsTextFrameUtils::AppendLineBreakOffset(&newBreaks, aStart); + } + if (aLineBreakAfter != (i + 1 < mLineBreaks.Length() && + mLineBreaks[i + 1] == aStart + aLength)) { + changed = PR_TRUE; + } + if (aLineBreakAfter) { + nsTextFrameUtils::AppendLineBreakOffset(&newBreaks, aStart + aLength); + } + for (; i < mLineBreaks.Length(); ++i) { + if (mLineBreaks[i] > aStart + aLength) + break; + changed = PR_TRUE; + } + if (!changed) { + if (aAdvanceWidthDelta) { + *aAdvanceWidthDelta = 0; + } + return PR_FALSE; + } + + newBreaks.AppendElements(mLineBreaks.Elements() + i, mLineBreaks.Length() - i); + mLineBreaks.SwapElements(newBreaks); + + gfxFloat currentAdvance = GetAdvanceWidth(aStart, aLength, nsnull); + mFactory->RebuildTextRun(this, aRefContext); + if (aAdvanceWidthDelta) { + *aAdvanceWidthDelta = GetAdvanceWidth(aStart, aLength, nsnull) - currentAdvance; + } + return PR_TRUE; +} + gfxTextRun* nsTransformingTextRunFactory::MakeTextRun(const PRUnichar* aString, PRUint32 aLength, const gfxTextRunFactory::Parameters* aParams, gfxFontGroup* aFontGroup, PRUint32 aFlags, nsStyleContext** aStyles, PRBool aOwnsFactory) { - return nsTransformedTextRun::Create(aParams, this, aFontGroup, - aString, aLength, aFlags, aStyles, aOwnsFactory); + nsTransformedTextRun* textRun = + nsTransformedTextRun::Create(aParams, this, aFontGroup, + aString, aLength, aFlags, aStyles, aOwnsFactory); + if (!textRun) + return nsnull; + + RebuildTextRun(textRun, aParams->mContext); + return textRun; } gfxTextRun* @@ -215,7 +271,7 @@ GetParametersForInner(nsTransformedTextRun* aTextRun, PRUint32* aFlags, { gfxTextRunFactory::Parameters params = { aRefContext, nsnull, nsnull, - nsnull, 0, aTextRun->GetAppUnitsPerDevUnit() + nsnull, nsnull, aTextRun->GetAppUnitsPerDevUnit() }; *aFlags = aTextRun->GetFlags() & ~gfxFontGroup::TEXT_IS_PERSISTENT; return params; @@ -257,9 +313,17 @@ nsFontVariantTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun, PRBool runIsLowercase = PR_FALSE; nsAutoTArray styleArray; nsAutoTArray canBreakBeforeArray; + nsAutoTArray lineBreakBeforeArray; + PRUint32 nextLineBreak = 0; PRUint32 i; for (i = 0; i <= length; ++i) { + if (nextLineBreak < aTextRun->mLineBreaks.Length() && + aTextRun->mLineBreaks[nextLineBreak] == i) { + lineBreakBeforeArray.AppendElement(i - runStart); + ++nextLineBreak; + } + PRBool isLowercase = PR_FALSE; if (i < length) { // Characters that aren't the start of a cluster are ignored here. They @@ -282,7 +346,9 @@ nsFontVariantTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun, nsAutoPtr transformedChild; gfxTextRunCache::AutoTextRun cachedChild; gfxTextRun* child; - + // Setup actual line break data for child (which may affect shaping) + innerParams.mInitialBreaks = lineBreakBeforeArray.Elements(); + innerParams.mInitialBreakCount = lineBreakBeforeArray.Length(); if (runIsLowercase) { transformedChild = uppercaseFactory.MakeTextRun(str + runStart, i - runStart, &innerParams, smallFont, flags, styleArray.Elements(), PR_FALSE); @@ -306,6 +372,10 @@ nsFontVariantTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun, runStart = i; styleArray.Clear(); canBreakBeforeArray.Clear(); + lineBreakBeforeArray.Clear(); + if (nextLineBreak > 0 && aTextRun->mLineBreaks[nextLineBreak - 1] == i) { + lineBreakBeforeArray.AppendElement(0); + } } if (i < length) { @@ -314,6 +384,8 @@ nsFontVariantTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun, canBreakBeforeArray.AppendElement(aTextRun->CanBreakLineBefore(i)); } } + NS_ASSERTION(nextLineBreak == aTextRun->mLineBreaks.Length(), + "lost track of line breaks somehow"); } void @@ -332,6 +404,8 @@ nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun, nsAutoTArray charsToMergeArray; nsAutoTArray styleArray; nsAutoTArray canBreakBeforeArray; + nsAutoTArray lineBreakBeforeArray; + PRUint32 nextLineBreak = 0; PRUint32 extraCharsCount = 0; PRUint32 i; @@ -341,6 +415,11 @@ nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun, charsToMergeArray.AppendElement(PR_FALSE); styleArray.AppendElement(styles[i]); canBreakBeforeArray.AppendElement(aTextRun->CanBreakLineBefore(i)); + if (nextLineBreak < aTextRun->mLineBreaks.Length() && + aTextRun->mLineBreaks[nextLineBreak] == i) { + lineBreakBeforeArray.AppendElement(i + extraCharsCount); + ++nextLineBreak; + } PRUint8 style = mAllUppercase ? NS_STYLE_TEXT_TRANSFORM_UPPERCASE : styles[i]->GetStyleText()->mTextTransform; @@ -382,6 +461,13 @@ nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun, canBreakBeforeArray.AppendElement(PR_FALSE); } } + if (nextLineBreak < aTextRun->mLineBreaks.Length() && + aTextRun->mLineBreaks[nextLineBreak] == length) { + lineBreakBeforeArray.AppendElement(length + extraCharsCount); + ++nextLineBreak; + } + NS_ASSERTION(nextLineBreak == aTextRun->mLineBreaks.Length(), + "lost track of line breaks somehow"); PRUint32 flags; gfxTextRunFactory::Parameters innerParams = @@ -391,7 +477,9 @@ nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun, nsAutoPtr transformedChild; gfxTextRunCache::AutoTextRun cachedChild; gfxTextRun* child; - + // Setup actual line break data for child (which may affect shaping) + innerParams.mInitialBreaks = lineBreakBeforeArray.Elements(); + innerParams.mInitialBreakCount = lineBreakBeforeArray.Length(); if (mInnerTransformingTextRunFactory) { transformedChild = mInnerTransformingTextRunFactory->MakeTextRun( convertedString.BeginReading(), convertedString.Length(), diff --git a/layout/generic/nsTextRunTransformations.h b/layout/generic/nsTextRunTransformations.h index cd9baa21ab..86c09f7960 100644 --- a/layout/generic/nsTextRunTransformations.h +++ b/layout/generic/nsTextRunTransformations.h @@ -113,30 +113,22 @@ public: } } - void SetCapitalization(PRUint32 aStart, PRUint32 aLength, - PRPackedBool* aCapitalization, - gfxContext* aRefContext); + virtual void SetCapitalization(PRUint32 aStart, PRUint32 aLength, + PRPackedBool* aCapitalization, + gfxContext* aRefContext); virtual PRBool SetPotentialLineBreaks(PRUint32 aStart, PRUint32 aLength, PRPackedBool* aBreakBefore, gfxContext* aRefContext); - /** - * Called after SetCapitalization and SetPotentialLineBreaks - * are done and before we request any data from the textrun. Also always - * called after a Create. - */ - void FinishSettingProperties(gfxContext* aRefContext) - { - if (mNeedsRebuild) { - mNeedsRebuild = PR_FALSE; - mFactory->RebuildTextRun(this, aRefContext); - } - } + virtual PRBool SetLineBreaks(PRUint32 aStart, PRUint32 aLength, + PRBool aLineBreakBefore, PRBool aLineBreakAfter, + gfxFloat* aAdvanceWidthDelta, + gfxContext* aRefContext); nsTransformingTextRunFactory *mFactory; + nsTArray mLineBreaks; nsTArray > mStyles; nsTArray mCapitalize; PRPackedBool mOwnsFactory; - PRPackedBool mNeedsRebuild; private: nsTransformedTextRun(const gfxTextRunFactory::Parameters* aParams, @@ -146,12 +138,15 @@ private: const PRUint32 aFlags, nsStyleContext** aStyles, PRBool aOwnsFactory) : gfxTextRun(aParams, aString, aLength, aFontGroup, aFlags, sizeof(nsTransformedTextRun)), - mFactory(aFactory), mOwnsFactory(aOwnsFactory), mNeedsRebuild(PR_TRUE) + mFactory(aFactory), mOwnsFactory(aOwnsFactory) { PRUint32 i; for (i = 0; i < aLength; ++i) { mStyles.AppendElement(aStyles[i]); } + for (i = 0; i < aParams->mInitialBreakCount; ++i) { + mLineBreaks.AppendElement(aParams->mInitialBreaks[i]); + } } }; -- 2.11.4.GIT