From 5fdb0cc854dccc9e666e804f9849fd4da53eae61 Mon Sep 17 00:00:00 2001 From: "roc+@cs.cmu.edu" Date: Wed, 27 Feb 2008 01:29:46 -0800 Subject: [PATCH] Bug 419531. Don't wipe out stored tab widths during text intrinsic size calculation. r+sr=dbaron --- layout/generic/nsTextFrameThebes.cpp | 81 +++++++++++++++------------- 1 file changed, 43 insertions(+), 38 deletions(-) diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index 4029bc6c7ccf..eb979a8fd6ca 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -2081,7 +2081,11 @@ protected: nsTextFrame* mFrame; gfxSkipCharsIterator mStart; // Offset in original and transformed string gfxSkipCharsIterator mTempIterator; - nsTArray* mTabWidths; // widths for each transformed string character + + // Widths for each transformed string character, 0 for non-tab characters. + // Either null, or pointing to the frame's tabWidthProperty. + nsTArray* mTabWidths; + PRInt32 mLength; // DOM string length, may be PR_INT32_MAX gfxFloat mWordSpacing; // space for each whitespace char gfxFloat mLetterSpacing; // space for each letter @@ -2266,6 +2270,16 @@ PropertyProvider::GetTabWidths(PRUint32 aStart, PRUint32 aLength) return nsnull; } } else { + if (!mLineContainer) { + // Intrinsic width computation, no way to compute real tab widths + // (and we wouldn't want to use it if we could, because it depends + // on layout). Don't wipe out existing tab widths that might still + // be useful for painting. Just return null which uses zero for + // all tab widths. + NS_WARNING("Preformatted tabs encountered in intrinsic width situation"); + return nsnull; + } + nsAutoPtr > tabs(new nsTArray()); if (!tabs) return nsnull; @@ -2288,47 +2302,38 @@ PropertyProvider::GetTabWidths(PRUint32 aStart, PRUint32 aLength) if (!mTabWidths->AppendElements(aStart + aLength - tabsEnd)) return nsnull; - PRUint32 i; - if (!mLineContainer) { - NS_WARNING("Tabs encountered in a situation where we don't support tabbing"); - for (i = tabsEnd; i < aStart + aLength; ++i) { + gfxFloat tabWidth = NS_round(8*mTextRun->GetAppUnitsPerDevUnit()* + GetFontMetrics(GetFontGroupForFrame(mLineContainer)).spaceWidth); + for (PRUint32 i = tabsEnd; i < aStart + aLength; ++i) { + Spacing spacing; + GetSpacingInternal(i, 1, &spacing, PR_TRUE); + mOffsetFromBlockOriginForTabs += spacing.mBefore; + + if (mTextRun->GetChar(i) != '\t') { (*mTabWidths)[i - startOffset] = 0; - } - } else { - gfxFloat tabWidth = NS_round(8*mTextRun->GetAppUnitsPerDevUnit()* - GetFontMetrics(GetFontGroupForFrame(mLineContainer)).spaceWidth); - - for (i = tabsEnd; i < aStart + aLength; ++i) { - Spacing spacing; - GetSpacingInternal(i, 1, &spacing, PR_TRUE); - mOffsetFromBlockOriginForTabs += spacing.mBefore; - - if (mTextRun->GetChar(i) != '\t') { - (*mTabWidths)[i - startOffset] = 0; - if (mTextRun->IsClusterStart(i)) { - PRUint32 clusterEnd = i + 1; - while (clusterEnd < mTextRun->GetLength() && - !mTextRun->IsClusterStart(clusterEnd)) { - ++clusterEnd; - } - mOffsetFromBlockOriginForTabs += - mTextRun->GetAdvanceWidth(i, clusterEnd - i, nsnull); + if (mTextRun->IsClusterStart(i)) { + PRUint32 clusterEnd = i + 1; + while (clusterEnd < mTextRun->GetLength() && + !mTextRun->IsClusterStart(clusterEnd)) { + ++clusterEnd; } - } else { - // Advance mOffsetFromBlockOriginForTabs to the next multiple of tabWidth - // Ensure that if it's just epsilon less than a multiple of tabWidth, we still - // advance by tabWidth. - static const double EPSILON = 0.000001; - double nextTab = NS_ceil(mOffsetFromBlockOriginForTabs/tabWidth)*tabWidth; - if (nextTab < mOffsetFromBlockOriginForTabs + EPSILON) { - nextTab += tabWidth; - } - (*mTabWidths)[i - startOffset] = nextTab - mOffsetFromBlockOriginForTabs; - mOffsetFromBlockOriginForTabs = nextTab; + mOffsetFromBlockOriginForTabs += + mTextRun->GetAdvanceWidth(i, clusterEnd - i, nsnull); } - - mOffsetFromBlockOriginForTabs += spacing.mAfter; + } else { + // Advance mOffsetFromBlockOriginForTabs to the next multiple of tabWidth + // Ensure that if it's just epsilon less than a multiple of tabWidth, we still + // advance by tabWidth. + static const double EPSILON = 0.000001; + double nextTab = NS_ceil(mOffsetFromBlockOriginForTabs/tabWidth)*tabWidth; + if (nextTab < mOffsetFromBlockOriginForTabs + EPSILON) { + nextTab += tabWidth; + } + (*mTabWidths)[i - startOffset] = nextTab - mOffsetFromBlockOriginForTabs; + mOffsetFromBlockOriginForTabs = nextTab; } + + mOffsetFromBlockOriginForTabs += spacing.mAfter; } }