bug 588 (text justification) for Robert O'Callahan <roc+moz@cs.cmu.edu>

r=buster

bug 18545 ([FLOAT] Problem Centering <TABLE> with <DIV> tag)
r=troy

bugs 18827, 19579, 22327 24782, 26512, 30124, 31849, 32846 (floater behavior wrong)
The primary change here is to determine if a block is impacted by a floater, and if so
mark the block's lines dirty when appropriate.
r=troy

no bug number.  performance work.  reduced the size of some reflow data structures by
collapsing multiple fields into a single bit field.
r=troy


git-svn-id: svn://10.0.0.236/trunk@66201 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
buster%netscape.com
2000-04-17 14:40:46 +00:00
parent 4d9893911c
commit 2fa9ad90e8
22 changed files with 2222 additions and 1088 deletions

View File

@@ -19,6 +19,7 @@
*
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
* Robert O'Callahan <roc+moz@cs.cmu.edu>
*/
#include "nsCOMPtr.h"
#include "nsHTMLParts.h"
@@ -458,9 +459,10 @@ public:
nscoord mAveCharWidth;
PRBool mJustifying;
PRBool mPreformatted;
PRIntn mNumSpaces;
PRInt32 mNumSpacesToRender;
PRInt32 mNumSpacesToMeasure;
nscoord mExtraSpacePerSpace;
nscoord mRemainingExtraSpace;
PRInt32 mNumSpacesReceivingExtraJot;
TextStyle(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
@@ -521,20 +523,25 @@ public:
// Get the word and letter spacing
mWordSpacing = 0;
mLetterSpacing = 0;
PRIntn unit = mText->mWordSpacing.GetUnit();
if (eStyleUnit_Coord == unit) {
mWordSpacing = mText->mWordSpacing.GetCoordValue();
}
mLetterSpacing = 0;
unit = mText->mLetterSpacing.GetUnit();
if (eStyleUnit_Coord == unit) {
mLetterSpacing = mText->mLetterSpacing.GetCoordValue();
}
mNumSpaces = 0;
mRemainingExtraSpace = 0;
mNumSpacesToRender = 0;
mNumSpacesToMeasure = 0;
mNumSpacesReceivingExtraJot = 0;
mExtraSpacePerSpace = 0;
mPreformatted = (NS_STYLE_WHITESPACE_PRE == mText->mWhiteSpace) ||
(NS_STYLE_WHITESPACE_MOZ_PRE_WRAP == mText->mWhiteSpace);
mJustifying = (NS_STYLE_TEXT_ALIGN_JUSTIFY == mText->mTextAlign) &&
!mPreformatted;
}
~TextStyle() {
@@ -590,6 +597,9 @@ public:
nsAutoIndexBuffer* aIndexBuffer,
nsAutoTextBuffer* aTextBuffer,
PRInt32* aTextLen);
void ComputeExtraJustificationSpacing(nsIRenderingContext& aRenderingContext,
TextStyle& aTextStyle,
PRUnichar* aBuffer, PRInt32 aLength, PRInt32 aNumSpaces);
void PaintTextDecorations(nsIRenderingContext& aRenderingContext,
nsIStyleContext* aStyleContext,
@@ -1192,7 +1202,8 @@ nsTextFrame::Paint(nsIPresContext* aPresContext,
sc->GetStyleData(eStyleStruct_Display);
if (disp->IsVisible()) {
TextStyle ts(aPresContext, aRenderingContext, mStyleContext);
if (ts.mSmallCaps || (0 != ts.mWordSpacing) || (0 != ts.mLetterSpacing)) {
if (ts.mSmallCaps || (0 != ts.mWordSpacing) || (0 != ts.mLetterSpacing)
|| ts.mJustifying) {
PaintTextSlowly(aPresContext, aRenderingContext, sc, ts, 0, 0);
}
else {
@@ -1261,7 +1272,9 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
PRBool isWhitespace, wasTransformed;
PRInt32 wordLen, contentLen;
aTX.GetNextWord(PR_FALSE, &wordLen, &contentLen, &isWhitespace, &wasTransformed);
NS_ASSERTION(isWhitespace, "mState and content are out of sync");
// we trip this assertion in bug 31053, but I think it's unnecessary
//NS_ASSERTION(isWhitespace, "mState and content are out of sync");
if (isWhitespace) {
if (nsnull != indexp) {
// Point mapping indicies at the same content index since
@@ -1301,7 +1314,6 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
}
inWord = PR_FALSE;
if (isWhitespace) {
numSpaces++;
if ('\t' == bp[0]) {
PRInt32 spaces = 8 - (7 & column);
PRUnichar* tp = bp;
@@ -1339,20 +1351,30 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
}
}
}
numSpaces += wordLen;
}
else {
PRInt32 i;
if (nsnull != indexp) {
// Point mapping indicies at each content index in the word
PRInt32 i = contentLen;
i = contentLen;
while (--i >= 0) {
*indexp++ = strInx++;
}
}
// Nonbreaking spaces count as spaces, not letters
PRUnichar* tp = bp;
i = wordLen;
while (--i >= 0) {
if (*tp++ == ' ') {
numSpaces++;
}
}
}
// Grow the buffer before we run out of room. The only time this
// happens is because of tab expansion.
if (dstOffset + wordLen > aTextBuffer->mBufferLen) {
if (aTextBuffer != nsnull && dstOffset + wordLen > aTextBuffer->mBufferLen) {
nsresult rv = aTextBuffer->GrowBy(wordLen);
if (NS_FAILED(rv)) {
break;
@@ -1362,8 +1384,10 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
column += wordLen;
textLength += wordLen;
n -= contentLen;
nsCRT::memcpy(aTextBuffer->mBuffer + dstOffset, bp,
sizeof(PRUnichar)*wordLen);
if (aTextBuffer != nsnull) {
nsCRT::memcpy(aTextBuffer->mBuffer + dstOffset, bp,
sizeof(PRUnichar)*wordLen);
}
dstOffset += wordLen;
}
@@ -1372,19 +1396,24 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
NS_ASSERTION(indexp <= aIndexBuffer->mBuffer + aIndexBuffer->mBufferLen,
"yikes - we just overwrote memory");
}
NS_ASSERTION(dstOffset <= aTextBuffer->mBufferLen,
"yikes - we just overwrote memory");
if (aTextBuffer) {
NS_ASSERTION(dstOffset <= aTextBuffer->mBufferLen,
"yikes - we just overwrote memory");
}
#endif
// Remove trailing whitespace if it was trimmed after reflow
if (TEXT_TRIMMED_WS & mState) {
NS_ASSERTION(aTextBuffer != nsnull,
"Nonexistent text buffer should only occur during reflow, i.e. before whitespace is trimmed");
if (--dstOffset >= 0) {
PRUnichar ch = aTextBuffer->mBuffer[dstOffset];
if (XP_IS_SPACE(ch)) {
textLength--;
numSpaces--;
}
}
numSpaces--;
}
if (aIndexBuffer) {
@@ -1716,6 +1745,7 @@ nsTextFrame::PaintUnicodeText(nsIPresContext* aPresContext,
doc->GetLineBreaker(getter_AddRefs(lb));
nsTextTransformer tx(lb, nsnull);
PRInt32 textLength;
// no need to worry about justification, that's always on the slow path
PrepareUnicodeText(tx, (displaySelection ? &indexBuffer : nsnull),
&paintBuffer, &textLength);
@@ -1833,7 +1863,7 @@ nsTextFrame::GetPositionSlowly(nsIPresContext* aPresContext,
}
TextStyle ts(aPresContext, *aRendContext, mStyleContext);
if (!ts.mSmallCaps && !ts.mWordSpacing && !ts.mLetterSpacing) {
if (!ts.mSmallCaps && !ts.mWordSpacing && !ts.mLetterSpacing && !ts.mJustifying) {
return NS_ERROR_INVALID_ARG;
}
nsIView * view;
@@ -1861,12 +1891,16 @@ nsTextFrame::GetPositionSlowly(nsIPresContext* aPresContext,
doc->GetLineBreaker(getter_AddRefs(lb));
nsTextTransformer tx(lb, nsnull);
PRInt32 textLength;
PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
PRInt32 numSpaces;
numSpaces = PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
if (textLength <= 0) {
return NS_ERROR_FAILURE;
}
//IF STYLE SAYS TO SELCT TO END OF FRAME HERE...
ComputeExtraJustificationSpacing(*aRendContext, ts, paintBuffer.mBuffer, textLength, numSpaces);
//IF STYLE SAYS TO SELECT TO END OF FRAME HERE...
nsCOMPtr<nsIPref> prefs;
PRInt32 prefInt = 0;
rv = nsServiceManager::GetService(kPrefCID,
@@ -1929,7 +1963,7 @@ nsTextFrame::RenderString(nsIRenderingContext& aRenderingContext,
PRUnichar* bp = bp0;
PRBool spacing = (0 != aTextStyle.mLetterSpacing) ||
(0 != aTextStyle.mWordSpacing);
(0 != aTextStyle.mWordSpacing) || aTextStyle.mJustifying;
nscoord spacingMem[TEXT_BUF_SIZE];
PRIntn* sp0 = spacingMem;
if (spacing && (aLength > TEXT_BUF_SIZE)) {
@@ -1977,12 +2011,12 @@ nsTextFrame::RenderString(nsIRenderingContext& aRenderingContext,
else if (ch == ' ') {
nextFont = aTextStyle.mNormalFont;
nextY = aY;
glyphWidth = aTextStyle.mSpaceWidth + aTextStyle.mWordSpacing;
nscoord extra = aTextStyle.mExtraSpacePerSpace;
if (--aTextStyle.mNumSpaces == 0) {
extra += aTextStyle.mRemainingExtraSpace;
glyphWidth = aTextStyle.mSpaceWidth + aTextStyle.mWordSpacing
+ aTextStyle.mExtraSpacePerSpace;
if ((PRUint32)--aTextStyle.mNumSpacesToRender <
(PRUint32)aTextStyle.mNumSpacesReceivingExtraJot) {
glyphWidth++;
}
glyphWidth += extra;
}
else {
if (lastFont != aTextStyle.mNormalFont) {
@@ -2096,12 +2130,12 @@ nsTextFrame::GetWidthOrLength(nsIRenderingContext& aRenderingContext,
glyphWidth = charWidth + aStyle.mLetterSpacing;
}
else if (ch == ' ') {
glyphWidth = aStyle.mSpaceWidth + aStyle.mWordSpacing;
nscoord extra = aStyle.mExtraSpacePerSpace;
if (--aStyle.mNumSpaces == 0) {
extra += aStyle.mRemainingExtraSpace;
glyphWidth = aStyle.mSpaceWidth + aStyle.mWordSpacing
+ aStyle.mExtraSpacePerSpace;
if ((PRUint32)--aStyle.mNumSpacesToMeasure
< (PRUint32)aStyle.mNumSpacesReceivingExtraJot) {
glyphWidth++;
}
glyphWidth += extra;
}
else {
if (lastFont != aStyle.mNormalFont) {
@@ -2147,6 +2181,45 @@ nsTextFrame::GetLengthSlowly(nsIRenderingContext& aRenderingContext,
return GetWidthOrLength(aRenderingContext,aStyle,aBuffer,aLength,&aWidth,PR_FALSE);
}
void
nsTextFrame::ComputeExtraJustificationSpacing(nsIRenderingContext& aRenderingContext,
TextStyle& aTextStyle,
PRUnichar* aBuffer, PRInt32 aLength,
PRInt32 aNumSpaces)
{
if (aTextStyle.mJustifying) {
nscoord trueWidth;
// OK, so this is a bit ugly. The problem is that to get the right margin
// nice and clean, we have to apply a little extra space to *some* of the
// spaces. It has to be the same ones every time or things will go haywire.
// This implies that the GetWidthOrLength and RenderString functions depend
// on a little bit of secret state: which part of the prepared text they are
// looking at. It turns out that they get called in a regular way: they look
// at the text from the beginning to the end. So we just count which spaces
// we're up to, for each context.
// This is not a great solution, but a perfect solution requires much more
// widespread changes, to explicitly annotate all the transformed text fragments
// that are passed around with their position in the transformed text
// for the entire frame.
aTextStyle.mNumSpacesToMeasure = 0;
aTextStyle.mExtraSpacePerSpace = 0;
aTextStyle.mNumSpacesReceivingExtraJot = 0;
GetWidth(aRenderingContext, aTextStyle, aBuffer, aLength, &trueWidth);
aTextStyle.mNumSpacesToMeasure = aNumSpaces;
aTextStyle.mNumSpacesToRender = aNumSpaces;
nscoord extraSpace = mRect.width - trueWidth;
if (extraSpace > 0 && aNumSpaces > 0) {
aTextStyle.mExtraSpacePerSpace = extraSpace/aNumSpaces;
aTextStyle.mNumSpacesReceivingExtraJot =
extraSpace - aTextStyle.mExtraSpacePerSpace*aNumSpaces;
}
}
}
void
nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext,
@@ -2173,10 +2246,11 @@ nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext,
nsCOMPtr<nsILineBreaker> lb;
doc->GetLineBreaker(getter_AddRefs(lb));
nsTextTransformer tx(lb, nsnull);
aTextStyle.mNumSpaces = PrepareUnicodeText(tx,
(displaySelection
? &indexBuffer : nsnull),
&paintBuffer, &textLength);
PRInt32 numSpaces;
numSpaces = PrepareUnicodeText(tx, (displaySelection ? &indexBuffer : nsnull),
&paintBuffer, &textLength);
PRInt32* ip = indexBuffer.mBuffer;
PRUnichar* text = paintBuffer.mBuffer;
@@ -2185,6 +2259,7 @@ nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext,
GetFrameState(&frameState);
isSelected = (frameState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT;
if (0 != textLength) {
ComputeExtraJustificationSpacing(aRenderingContext, aTextStyle, text, textLength, numSpaces);
if (!displaySelection || !isSelected) {
// When there is no selection showing, use the fastest and
// simplest rendering approach
@@ -2550,8 +2625,7 @@ nsTextFrame::GetPosition(nsIPresContext* aCX,
rv = shell->CreateRenderingContext(this, getter_AddRefs(acx));
if (NS_SUCCEEDED(rv)) {
TextStyle ts(aCX, *acx, mStyleContext);
if (ts.mSmallCaps || ts.mWordSpacing || ts.mLetterSpacing) {
if (ts.mSmallCaps || ts.mWordSpacing || ts.mLetterSpacing || ts.mJustifying) {
nsresult result = GetPositionSlowly(aCX, acx, aPoint, aNewContent,
aContentOffset);
aContentOffsetEnd = aContentOffset;
@@ -2582,6 +2656,7 @@ nsTextFrame::GetPosition(nsIPresContext* aCX,
doc->GetLineBreaker(getter_AddRefs(lb));
nsTextTransformer tx(lb, nsnull);
PRInt32 textLength;
// no need to worry about justification, that's always on the slow path
PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
if (textLength <=0) {
@@ -2593,7 +2668,7 @@ nsTextFrame::GetPosition(nsIPresContext* aCX,
nsIView * view;
GetOffsetFromView(aCX, origin, &view);
//IF SYLE SAYS TO SELCT TO END OF FRAME HERE...
//IF STYLE SAYS TO SELECT TO END OF FRAME HERE...
nsCOMPtr<nsIPref> prefs;
PRInt32 prefInt = 0;
rv = nsServiceManager::GetService(kPrefCID,
@@ -2880,7 +2955,12 @@ nsTextFrame::GetPointFromOffset(nsIPresContext* aPresContext,
doc->GetLineBreaker(getter_AddRefs(lb));
nsTextTransformer tx(lb, nsnull);
PRInt32 textLength;
PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
PRInt32 numSpaces;
numSpaces = PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
ComputeExtraJustificationSpacing(*inRendContext, ts, paintBuffer.mBuffer, textLength, numSpaces);
PRInt32* ip = indexBuffer.mBuffer;
if (inOffset > mContentLength){
@@ -2889,7 +2969,7 @@ nsTextFrame::GetPointFromOffset(nsIPresContext* aPresContext,
}
nscoord width = mRect.width;
if (ts.mSmallCaps || (0 != ts.mWordSpacing) || (0 != ts.mLetterSpacing))
if (ts.mSmallCaps || (0 != ts.mWordSpacing) || (0 != ts.mLetterSpacing) || ts.mJustifying)
{
GetWidth(*inRendContext, ts,
paintBuffer.mBuffer, ip[inOffset]-mContentOffset,
@@ -2907,7 +2987,8 @@ nsTextFrame::GetPointFromOffset(nsIPresContext* aPresContext,
// to the total width, so the caret appears
// in the proper place!
//
width += ts.mSpaceWidth;
// NOTE: the trailing whitespace includes the word spacing!!
width += ts.mSpaceWidth + ts.mWordSpacing;
}
outPoint->x = width;
@@ -3502,6 +3583,7 @@ nsTextFrame::MeasureText(nsIPresContext* aPresContext,
#ifdef _WIN32
PRBool measureTextRuns = !aTextData.mComputeMaxWordWidth && !aTs.mPreformatted &&
!aTs.mSmallCaps && !aTs.mWordSpacing && !aTs.mLetterSpacing;
// Don't measure text runs with letter spacing active, it doesn't work
#else
PRBool measureTextRuns = PR_FALSE;
#endif
@@ -3579,10 +3661,17 @@ nsTextFrame::MeasureText(nsIPresContext* aPresContext,
mState |= TEXT_SKIP_LEADING_WS;
continue;
}
// NOTE: Even if the textRun absorbs the whitespace below, we still
// want to remember that we're breakable.
aTextData.mIsBreakable = PR_TRUE;
aTextData.mFirstLetterOK = PR_FALSE;
if ('\t' == firstChar) {
// Expand tabs to the proper width
wordLen = 8 - (7 & column);
width = aTs.mSpaceWidth * wordLen;
// Apply word spacing to every space derived from a tab
width = (aTs.mSpaceWidth + aTs.mWordSpacing)*wordLen;
// Because we have to expand the tab when rendering consider that
// a transformation of the text
@@ -3594,10 +3683,9 @@ nsTextFrame::MeasureText(nsIPresContext* aPresContext,
continue;
}
else {
width = (wordLen * aTs.mSpaceWidth) + aTs.mWordSpacing;// XXX simplistic
// Apply word spacing to every space, if there's more than one
width = wordLen*(aTs.mWordSpacing + aTs.mSpaceWidth);// XXX simplistic
}
aTextData.mIsBreakable = PR_TRUE;
aTextData.mFirstLetterOK = PR_FALSE;
if (aTextData.mMeasureText) {
// See if there is room for the text
@@ -3612,7 +3700,6 @@ nsTextFrame::MeasureText(nsIPresContext* aPresContext,
endsInWhitespace = PR_TRUE;
prevOffset = aTextData.mOffset;
aTextData.mOffset += contentLen;
} else {
// See if the first thing in the section of text is a
// non-breaking space (html nbsp entity). If it is then make
@@ -3704,6 +3791,7 @@ nsTextFrame::MeasureText(nsIPresContext* aPresContext,
MeasureTextRun:
#ifdef _WIN32
PRInt32 numCharsFit;
// These calls can return numCharsFit not positioned at a break in the textRun. Beware.
if (aTx.TransformedTextIsAscii()) {
aReflowState.rendContext->GetWidth((char*)aTx.GetWordBuffer(), textRun.mTotalNumChars,
maxWidth - aTextData.mX,
@@ -3722,22 +3810,43 @@ nsTextFrame::MeasureText(nsIPresContext* aPresContext,
}
// Find the index of the last segment that fit
PRInt32 lastSegment = textRun.mNumSegments - 1;
if (numCharsFit != textRun.mTotalNumChars) {
PRInt32 lastSegment;
if (numCharsFit == textRun.mTotalNumChars) { // fast path, normal case
lastSegment = textRun.mNumSegments - 1;
} else {
for (lastSegment = 0; textRun.mBreaks[lastSegment] < numCharsFit; lastSegment++) ;
NS_ASSERTION(lastSegment < textRun.mNumSegments, "failed to find segment");
// now we have textRun.mBreaks[lastSegment] >= numCharsFit
/* O'Callahan XXX: This snippet together with the snippet below prevents mail from loading
Justification seems to work just fine without these changes.
We get into trouble in a case where lastSegment gets set to -1
if (textRun.mBreaks[lastSegment] > numCharsFit) {
// NOTE: this segment did not actually fit!
lastSegment--;
}
*/
}
/* O'Callahan XXX: This snippet together with the snippet above prevents mail from loading
if (lastSegment < 0) {
// no segments fit
break;
} else */
if (lastSegment == 0) {
// Only one segment fit
prevColumn = column;
prevOffset = aTextData.mOffset;
} else {
// The previous state is for the next to last word
prevColumn = textRun.mBreaks[lastSegment - 1];
prevOffset = textRun.mSegments[lastSegment - 1].ContentLen();
// NOTE: The textRun data are relative to the last updated column and offset!
prevColumn = column + textRun.mBreaks[lastSegment - 1];
prevOffset = aTextData.mOffset + textRun.mSegments[lastSegment - 1].ContentLen();
}
aTextData.mX += width;
column += numCharsFit;
aTextData.mOffset += textRun.mSegments[lastSegment].ContentLen();
@@ -3775,7 +3884,8 @@ nsTextFrame::MeasureText(nsIPresContext* aPresContext,
aTextData.mX = mRect.width;
if (mState & TEXT_TRIMMED_WS) {
// Add back in the width of a space since it was trimmed away last time
aTextData.mX += aTs.mSpaceWidth;
// NOTE: Trailing whitespace includes word spacing!
aTextData.mX += aTs.mSpaceWidth + aTs.mWordSpacing;
}
}
@@ -4056,19 +4166,22 @@ nsTextFrame::Reflow(nsIPresContext* aPresContext,
// current frame width -or-
// we're not wrapping text and we're at the same column as before (this is
// an issue for preformatted tabbed text only)
// - AND we aren't justified (in which case the frame width has already been tweaked and can't be used)
if ((eReflowReason_Resize == aReflowState.reason) &&
(0 == (mState & NS_FRAME_IS_DIRTY))) {
nscoord realWidth = mRect.width;
if (mState & TEXT_TRIMMED_WS) {
realWidth += ts.mSpaceWidth;
// NOTE: Trailing whitespace includes word spacing!
realWidth += ts.mSpaceWidth + ts.mWordSpacing;
}
if (!mNextInFlow &&
(mState & TEXT_OPTIMIZE_RESIZE) &&
!aMetrics.maxElementSize &&
(lastTimeWeSkippedLeadingWS == skipWhitespace) &&
((wrapping && (maxWidth >= realWidth)) ||
(!wrapping && (prevColumn == column)))) {
(!wrapping && (prevColumn == column))) &&
!ts.mJustifying) {
// We can skip measuring of text and use the value from our
// previous reflow
measureText = PR_FALSE;
@@ -4120,6 +4233,23 @@ nsTextFrame::Reflow(nsIPresContext* aPresContext,
mContentOffset = startingOffset;
mContentLength = textData.mOffset - startingOffset;
// Compute space and letter counts for justification, if required
if (ts.mJustifying) {
PRInt32 numSpaces;
PRInt32 textLength;
// This will include a space for trailing whitespace, if any is present.
// This is corrected for in nsLineLayout::TrimWhiteSpaceIn.
// This work could be done in MeasureText, but it's complex to do accurately
// there because of the need to repair counts when wrapped words are backed out.
// So I do it via PrepareUnicodeText ... a little slower perhaps, but a lot saner,
// and it localizes the counting logic to one place.
numSpaces = PrepareUnicodeText(tx, nsnull, nsnull, &textLength);
lineLayout.SetTextJustificationWeights(numSpaces, textLength - numSpaces);
}
#ifdef MOZ_MATHML
// Simple minded code to also return the bounding metrics if the caller wants it...
// More consolidation is needed -- a better approach is to follow what is done by
@@ -4226,6 +4356,11 @@ nsTextFrame::TrimTrailingWhiteSpace(nsIPresContext* aPresContext,
mStyleContext->GetStyleData(eStyleStruct_Font);
aRC.SetFont(fontStyle->mFont);
aRC.GetWidth(' ', dw);
// NOTE: Trailing whitespace includes word spacing!
PRIntn unit = textStyle->mWordSpacing.GetUnit();
if (eStyleUnit_Coord == unit) {
dw += textStyle->mWordSpacing.GetCoordValue();
}
}
}
}
@@ -4406,6 +4541,8 @@ nsTextFrame::ComputeWordFragmentWidth(nsIPresContext* aPresContext,
}
else {
rc.GetWidth(bp, wordLen, width);
// NOTE: Don't forget to add letter spacing for the word fragment!
width += wordLen*ts.mLetterSpacing;
}
rc.SetFont(oldfm);