Bug 380692. Change gfxTextRun API so the textrun copies text, if necessary, instead of the caller having to do it. r=vlad

This commit is contained in:
roc+@cs.cmu.edu 2007-05-14 20:56:47 -07:00
Родитель b9c2535e4d
Коммит e7e11676c0
8 изменённых файлов: 64 добавлений и 87 удалений

Просмотреть файл

@ -796,8 +796,8 @@ public:
// The caller is responsible for initializing our glyphs after construction.
// Initially all glyphs are such that GetCharacterGlyphs()[i].IsMissing() is true.
// We take ownership of aText, which must have been allocated by new[] (it
// may be null if aLength is zero).
// If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
// textrun will copy it.
gfxTextRun(const gfxTextRunFactory::Parameters *aParams, const void *aText,
PRUint32 aLength, gfxFontGroup *aFontGroup, PRUint32 aFlags);
@ -805,7 +805,8 @@ public:
// glyph data is copied, so the text and length must be the same as this
// textrun's. If there's a problem, return null. Actual linebreaks will
// be set as per aParams; there will be no potential linebreaks.
// If successful, we take ownership of aText, which must have been allocated by new[].
// If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
// textrun will copy it.
virtual gfxTextRun *Clone(const gfxTextRunFactory::Parameters *aParams, const void *aText,
PRUint32 aLength, gfxFontGroup *aFontGroup, PRUint32 aFlags);
@ -1143,16 +1144,16 @@ public:
gfxTextRun *MakeSpaceTextRun(const Parameters *aParams, PRUint32 aFlags);
/**
* Make a textrun for a given string. Takes ownership of aString unless
* aFlags & TEXT_IS_PERSISTENT --- in that case, the caller must destroy
* the textrun before aString dies.
* Make a textrun for a given string.
* If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
* textrun will copy it.
*/
virtual gfxTextRun *MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
const Parameters *aParams, PRUint32 aFlags) = 0;
/**
* Make a textrun for a given string. Takes ownership of aString unless
* aFlags & TEXT_IS_PERSISTENT --- in that case, the caller must destroy
* the textrun before aString dies.
* Make a textrun for a given string.
* If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
* textrun will copy it.
*/
virtual gfxTextRun *MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
const Parameters *aParams, PRUint32 aFlags) = 0;

Просмотреть файл

@ -633,8 +633,28 @@ gfxTextRun::gfxTextRun(const gfxTextRunFactory::Parameters *aParams, const void
}
if (mFlags & gfxTextRunFactory::TEXT_IS_8BIT) {
mText.mSingle = NS_STATIC_CAST(const PRUint8 *, aText);
if (!(mFlags & gfxTextRunFactory::TEXT_IS_PERSISTENT)) {
PRUint8 *newText = new PRUint8[aLength];
if (!newText) {
// indicate textrun failure
mCharacterGlyphs = nsnull;
} else {
memcpy(newText, aText, aLength);
}
mText.mSingle = newText;
}
} else {
mText.mDouble = NS_STATIC_CAST(const PRUnichar *, aText);
if (!(mFlags & gfxTextRunFactory::TEXT_IS_PERSISTENT)) {
PRUnichar *newText = new PRUnichar[aLength];
if (!newText) {
// indicate textrun failure
mCharacterGlyphs = nsnull;
} else {
memcpy(newText, aText, aLength*sizeof(PRUnichar));
}
mText.mDouble = newText;
}
}
}

Просмотреть файл

@ -96,34 +96,6 @@ static void *GetCacheKeyFontOrGroup(gfxTextRun *aTextRun)
: NS_STATIC_CAST(void *, fontGroup);
}
static const PRUnichar *
CloneText(const PRUnichar *aText, PRUint32 aLength,
nsAutoArrayPtr<PRUnichar> *aBuffer, PRUint32 aFlags)
{
if (*aBuffer == aText || (aFlags & gfxFontGroup::TEXT_IS_PERSISTENT))
return aText;
PRUnichar *newText = new PRUnichar[aLength];
if (!newText)
return nsnull;
memcpy(newText, aText, aLength*sizeof(PRUnichar));
*aBuffer = newText;
return newText;
}
static const PRUint8 *
CloneText(const PRUint8 *aText, PRUint32 aLength,
nsAutoArrayPtr<PRUint8> *aBuffer, PRUint32 aFlags)
{
if (*aBuffer == aText || (aFlags & gfxFontGroup::TEXT_IS_PERSISTENT))
return aText;
PRUint8 *newText = new PRUint8[aLength];
if (!newText)
return nsnull;
memcpy(newText, aText, aLength);
*aBuffer = newText;
return newText;
}
gfxTextRun *
gfxTextRunCache::GetOrMakeTextRun(const PRUnichar *aText, PRUint32 aLength,
gfxFontGroup *aFontGroup,
@ -152,30 +124,22 @@ gfxTextRunCache::GetOrMakeTextRun(const PRUnichar *aText, PRUint32 aLength,
key.mFontOrGroup = aFontGroup;
entry = mCache.GetEntry(key);
}
nsAutoArrayPtr<PRUnichar> text;
if (entry) {
gfxTextRun *textRun = entry->mTextRun;
if (aCallerOwns) {
*aCallerOwns = PR_FALSE;
return textRun;
}
aText = CloneText(aText, aLength, &text, aFlags);
if (!aText)
return nsnull;
gfxTextRun *newRun =
textRun->Clone(aParams, aText, aLength, aFontGroup, aFlags);
if (newRun) {
newRun->SetHashCode(hashCode);
entry->mTextRun = newRun;
NotifyRemovedFromCache(textRun);
text.forget();
return newRun;
}
}
aText = CloneText(aText, aLength, &text, aFlags);
if (!aText)
return nsnull;
gfxTextRun *newRun =
aFontGroup->MakeTextRun(aText, aLength, aParams, aFlags);
if (newRun) {
@ -188,7 +152,6 @@ gfxTextRunCache::GetOrMakeTextRun(const PRUnichar *aText, PRUint32 aLength,
NS_ASSERTION(!entry || entry == mCache.GetEntry(GetKeyForTextRun(newRun)),
"Inconsistent hashing");
}
text.forget();
return newRun;
}
@ -220,16 +183,13 @@ gfxTextRunCache::GetOrMakeTextRun(const PRUint8 *aText, PRUint32 aLength,
key.mFontOrGroup = aFontGroup;
entry = mCache.GetEntry(key);
}
nsAutoArrayPtr<PRUint8> text;
if (entry) {
gfxTextRun *textRun = entry->mTextRun;
if (aCallerOwns) {
*aCallerOwns = PR_FALSE;
return textRun;
}
aText = CloneText(aText, aLength, &text, aFlags);
if (!aText)
return nsnull;
gfxTextRun *newRun =
textRun->Clone(aParams, aText, aLength,
aFontGroup, aFlags);
@ -237,14 +197,10 @@ gfxTextRunCache::GetOrMakeTextRun(const PRUint8 *aText, PRUint32 aLength,
newRun->SetHashCode(hashCode);
entry->mTextRun = newRun;
NotifyRemovedFromCache(textRun);
text.forget();
return newRun;
}
}
aText = CloneText(aText, aLength, &text, aFlags);
if (!aText)
return nsnull;
gfxTextRun *newRun =
aFontGroup->MakeTextRun(aText, aLength, aParams, aFlags);
if (newRun) {
@ -257,7 +213,6 @@ gfxTextRunCache::GetOrMakeTextRun(const PRUint8 *aText, PRUint32 aLength,
NS_ASSERTION(!entry || entry == mCache.GetEntry(GetKeyForTextRun(newRun)),
"Inconsistent hashing");
}
text.forget();
return newRun;
}

Просмотреть файл

@ -169,7 +169,7 @@ CPPSRCS += \
endif
# set this to 1 to enable the new text frame
MOZ_ENABLE_NEW_TEXT_FRAME =
MOZ_ENABLE_NEW_TEXT_FRAME = 1
ifdef MOZ_ENABLE_NEW_TEXT_FRAME
CPPSRCS += \

Просмотреть файл

@ -1488,6 +1488,7 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
textRun = transformingFactory->MakeTextRun(text, transformedLength, &params,
fontGroup, textFlags, styles.Elements());
if (textRun) {
// ownership of the factory has passed to the textrun
transformingFactory.forget();
}
} else {
@ -1504,6 +1505,7 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
textRun = transformingFactory->MakeTextRun(text, transformedLength, &params,
fontGroup, textFlags, styles.Elements());
if (textRun) {
// ownership of the factory has passed to the textrun
transformingFactory.forget();
}
} else {

Просмотреть файл

@ -58,9 +58,11 @@ public:
nsTransformingTextRunFactory* aFactory,
gfxFontGroup* aFontGroup,
const PRUnichar* aString, PRUint32 aLength,
const PRUint32 aFlags, nsStyleContext** aStyles)
const PRUint32 aFlags, nsStyleContext** aStyles,
PRBool aOwnsFactory)
: gfxTextRun(aParams, aString, aLength, aFontGroup, aFlags),
mFactory(aFactory), mRefContext(aParams->mContext)
mFactory(aFactory), mRefContext(aParams->mContext),
mOwnsFactory(aOwnsFactory)
{
PRUint32 i;
for (i = 0; i < aLength; ++i) {
@ -70,6 +72,12 @@ public:
mLineBreaks.AppendElement(aParams->mInitialBreaks[i]);
}
}
~nsTransformedTextRun() {
if (mOwnsFactory) {
delete mFactory;
}
}
virtual PRBool SetPotentialLineBreaks(PRUint32 aStart, PRUint32 aLength,
PRPackedBool* aBreakBefore)
@ -82,10 +90,11 @@ public:
PRBool aLineBreakBefore, PRBool aLineBreakAfter,
gfxFloat* aAdvanceWidthDelta);
nsAutoPtr<nsTransformingTextRunFactory> mFactory;
nsRefPtr<gfxContext> mRefContext;
nsTArray<PRUint32> mLineBreaks;
nsTArray<nsRefPtr<nsStyleContext> > mStyles;
nsTransformingTextRunFactory *mFactory;
nsRefPtr<gfxContext> mRefContext;
nsTArray<PRUint32> mLineBreaks;
nsTArray<nsRefPtr<nsStyleContext> > mStyles;
PRPackedBool mOwnsFactory;
};
PRBool
@ -143,22 +152,14 @@ gfxTextRun*
nsTransformingTextRunFactory::MakeTextRun(const PRUnichar* aString, PRUint32 aLength,
const gfxTextRunFactory::Parameters* aParams,
gfxFontGroup* aFontGroup, PRUint32 aFlags,
nsStyleContext** aStyles)
nsStyleContext** aStyles, PRBool aOwnsFactory)
{
PRUnichar* text = nsnull;
if (!(aFlags & gfxFontGroup::TEXT_IS_PERSISTENT)) {
text = new PRUnichar[aLength];
if (!text)
return nsnull;
memcpy(text, aString, aLength*sizeof(PRUnichar));
}
nsTransformedTextRun* textRun =
new nsTransformedTextRun(aParams, this, aFontGroup,
text ? text : aString, aLength, aFlags, aStyles);
if (!textRun) {
delete[] text;
aString, aLength, aFlags, aStyles, aOwnsFactory);
if (!textRun)
return nsnull;
}
RebuildTextRun(textRun);
return textRun;
}
@ -167,14 +168,14 @@ gfxTextRun*
nsTransformingTextRunFactory::MakeTextRun(const PRUint8* aString, PRUint32 aLength,
const gfxTextRunFactory::Parameters* aParams,
gfxFontGroup* aFontGroup, PRUint32 aFlags,
nsStyleContext** aStyles)
nsStyleContext** aStyles, PRBool aOwnsFactory)
{
// We'll only have a Unicode code path to minimize the amount of code needed
// for these rarely used features
NS_ConvertASCIItoUTF16 unicodeString(NS_REINTERPRET_CAST(const char*, aString), aLength);
return MakeTextRun(unicodeString.get(), aLength, aParams, aFontGroup,
aFlags & ~(gfxFontGroup::TEXT_IS_PERSISTENT | gfxFontGroup::TEXT_IS_8BIT),
aStyles);
aStyles, aOwnsFactory);
}
static PRUint32
@ -335,12 +336,15 @@ nsFontVariantTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun)
PRUint32 flags;
gfxTextRunFactory::Parameters innerParams = GetParametersForInner(aTextRun, &flags);
// The text outlives the child and inner textruns
flags |= gfxFontGroup::TEXT_IS_PERSISTENT;
PRUint32 length = aTextRun->GetLength();
const PRUnichar* str = aTextRun->GetTextUnicode();
nsRefPtr<nsStyleContext>* styles = aTextRun->mStyles.Elements();
// Create a textrun so we can check cluster-start properties
nsAutoPtr<gfxTextRun> inner;
// This text is going to outlive the inner text run
inner = fontGroup->MakeTextRun(str, length, &innerParams, flags);
if (!inner)
return;
@ -388,8 +392,7 @@ nsFontVariantTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun)
innerParams.mInitialBreakCount = lineBreakBeforeArray.Length();
if (runIsLowercase) {
child = uppercaseFactory.MakeTextRun(str + runStart, i - runStart,
&innerParams, smallFont, flags,
styleArray.Elements());
&innerParams, smallFont, flags, styleArray.Elements(), PR_FALSE);
} else {
child = fontGroup->
MakeTextRun(str + runStart, i - runStart, &innerParams, flags);
@ -515,7 +518,7 @@ nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun)
if (mInnerTransformingTextRunFactory) {
child = mInnerTransformingTextRunFactory->MakeTextRun(
convertedString.BeginReading(), convertedString.Length(),
&innerParams, fontGroup, flags, styleArray.Elements());
&innerParams, fontGroup, flags, styleArray.Elements(), PR_FALSE);
} else {
child = fontGroup->MakeTextRun(
convertedString.BeginReading(), convertedString.Length(), &innerParams,

Просмотреть файл

@ -51,11 +51,11 @@ public:
gfxTextRun* MakeTextRun(const PRUint8* aString, PRUint32 aLength,
const gfxFontGroup::Parameters* aParams,
gfxFontGroup* aFontGroup, PRUint32 aFlags,
nsStyleContext** aStyles);
nsStyleContext** aStyles, PRBool aOwnsFactory = PR_TRUE);
gfxTextRun* MakeTextRun(const PRUnichar* aString, PRUint32 aLength,
const gfxFontGroup::Parameters* aParams,
gfxFontGroup* aFontGroup, PRUint32 aFlags,
nsStyleContext** aStyles);
nsStyleContext** aStyles, PRBool aOwnsFactory = PR_TRUE);
virtual void RebuildTextRun(nsTransformedTextRun* aTextRun) = 0;
};
@ -81,6 +81,7 @@ public:
// just convert the string to uppercase or lowercase and create the textrun
// via the fontgroup.
// Takes ownership of aInnerTransformTextRunFactory
nsCaseTransformTextRunFactory(nsTransformingTextRunFactory* aInnerTransformingTextRunFactory,
PRBool aAllUppercase = PR_FALSE)
: mInnerTransformingTextRunFactory(aInnerTransformingTextRunFactory),

Просмотреть файл

@ -1359,12 +1359,7 @@ nsSVGGlyphFrame::GetTextRun(gfxContext *aCtx, const nsString &aText)
if (!mFontGroup)
return nsnull;
PRUnichar* text = new PRUnichar[aText.Length()];
if (!text)
return nsnull;
memcpy(text, aText.get(), sizeof(PRUnichar)*aText.Length());
return mFontGroup->MakeTextRun(text, aText.Length(), &params, 0);
return mFontGroup->MakeTextRun(aText.get(), aText.Length(), &params, 0);
}
//----------------------------------------------------------------------