get rid of the previous check-in (I didn't realize that the tree was frozen. I'm sorry)

This commit is contained in:
jshin%mailaps.org 2004-11-19 03:32:28 +00:00
parent 89253ca032
commit 7f32280119
6 changed files with 158 additions and 292 deletions

View File

@ -210,9 +210,6 @@ LAYOUT_ATOM(onDOMCharacterDataModified, "onDOMCharacterDataModified")
// Alphabetical list of languages for lang-specific transforms
LAYOUT_ATOM(Japanese, "ja")
LAYOUT_ATOM(Chinese, "zh-CN")
LAYOUT_ATOM(Taiwanese, "zh-TW")
LAYOUT_ATOM(HongKongChinese, "zh-HK")
LAYOUT_ATOM(Unicode, "x-unicode")
// other

View File

@ -210,9 +210,6 @@ LAYOUT_ATOM(onDOMCharacterDataModified, "onDOMCharacterDataModified")
// Alphabetical list of languages for lang-specific transforms
LAYOUT_ATOM(Japanese, "ja")
LAYOUT_ATOM(Chinese, "zh-CN")
LAYOUT_ATOM(Taiwanese, "zh-TW")
LAYOUT_ATOM(HongKongChinese, "zh-HK")
LAYOUT_ATOM(Unicode, "x-unicode")
// other

View File

@ -2720,7 +2720,9 @@ nsLineLayout::ApplyFrameJustification(PerSpanData* aPSD, FrameJustificationState
if (PR_TRUE == pfd->GetFlag(PFD_ISTEXTFRAME)) {
if (aState->mTotalWidthForSpaces > 0 &&
aState->mTotalNumSpaces > 0) {
aState->mTotalNumSpaces > 0 && // we divide by this value, so must be non-zero
aState->mTotalNumLetters >0 // we divide by this value, so must be non-zero
) {
aState->mNumSpacesProcessed += pfd->mJustificationNumSpaces;
nscoord newAllocatedWidthForSpaces =
@ -2732,8 +2734,7 @@ nsLineLayout::ApplyFrameJustification(PerSpanData* aPSD, FrameJustificationState
aState->mWidthForSpacesProcessed = newAllocatedWidthForSpaces;
}
if (aState->mTotalWidthForLetters > 0 &&
aState->mTotalNumLetters > 0) {
if (aState->mTotalWidthForLetters > 0) {
aState->mNumLettersProcessed += pfd->mJustificationNumLetters;
nscoord newAllocatedWidthForLetters =

View File

@ -513,10 +513,10 @@ public:
nscoord mAveCharWidth;
PRBool mJustifying;
PRBool mPreformatted;
PRInt32 mNumJustifiableCharacterToRender;
PRInt32 mNumJustifiableCharacterToMeasure;
nscoord mExtraSpacePerJustifiableCharacter;
PRInt32 mNumJustifiableCharacterReceivingExtraJot;
PRInt32 mNumSpacesToRender;
PRInt32 mNumSpacesToMeasure;
nscoord mExtraSpacePerSpace;
PRInt32 mNumSpacesReceivingExtraJot;
TextStyle(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
@ -570,10 +570,10 @@ public:
mLetterSpacing = 0;
}
mNumJustifiableCharacterToRender = 0;
mNumJustifiableCharacterToMeasure = 0;
mNumJustifiableCharacterReceivingExtraJot = 0;
mExtraSpacePerJustifiableCharacter = 0;
mNumSpacesToRender = 0;
mNumSpacesToMeasure = 0;
mNumSpacesReceivingExtraJot = 0;
mExtraSpacePerSpace = 0;
mPreformatted = (NS_STYLE_WHITESPACE_PRE == mText->mWhiteSpace) ||
(NS_STYLE_WHITESPACE_MOZ_PRE_WRAP == mText->mWhiteSpace);
@ -657,15 +657,14 @@ public:
nsIDocument* GetDocument(nsPresContext* aPresContext);
void PrepareUnicodeText(nsTextTransformer& aTransformer,
nsAutoIndexBuffer* aIndexBuffer,
nsAutoTextBuffer* aTextBuffer,
PRInt32* aTextLen,
PRBool aForceArabicShaping = PR_FALSE,
PRIntn* aJustifiableCharCount = nsnull);
PRIntn PrepareUnicodeText(nsTextTransformer& aTransformer,
nsAutoIndexBuffer* aIndexBuffer,
nsAutoTextBuffer* aTextBuffer,
PRInt32* aTextLen,
PRBool aForceArabicShaping = PR_FALSE);
void ComputeExtraJustificationSpacing(nsIRenderingContext& aRenderingContext,
TextStyle& aTextStyle,
PRUnichar* aBuffer, PRInt32 aLength, PRInt32 aNumJustifiableCharacter);
PRUnichar* aBuffer, PRInt32 aLength, PRInt32 aNumSpaces);
void PaintTextDecorations(nsIRenderingContext& aRenderingContext,
nsStyleContext* aStyleContext,
@ -798,9 +797,6 @@ protected:
PRBool isBidiSystem);
void SetOffsets(PRInt32 start, PRInt32 end);
PRBool IsChineseJapaneseLangGroup();
PRBool IsJustifiableCharacter(PRUnichar aChar, PRBool aLangIsCJ);
};
#ifdef ACCESSIBILITY
@ -1487,64 +1483,21 @@ nsTextFrame::Paint(nsPresContext* aPresContext,
return NS_OK;
}
PRBool
nsTextFrame::IsChineseJapaneseLangGroup()
{
const nsStyleVisibility* visibility = mStyleContext->GetStyleVisibility();
if (visibility->mLangGroup == nsLayoutAtoms::Japanese
|| visibility->mLangGroup == nsLayoutAtoms::Chinese
|| visibility->mLangGroup == nsLayoutAtoms::Taiwanese
|| visibility->mLangGroup == nsLayoutAtoms::HongKongChinese)
return PR_TRUE;
return PR_FALSE;
}
/*
* XXX Currently only Unicode characters in the BMP (below U+10000) have their
* spacing modified by justification.
*/
inline PRBool
nsTextFrame::IsJustifiableCharacter(PRUnichar aChar, PRBool aLangIsCJ)
{
if (0x20u == aChar || 0xa0u == aChar)
return PR_TRUE;
if (aChar < 0x2150u)
return PR_FALSE;
if (aLangIsCJ && (
(0x2150u <= aChar && aChar <= 0x22ffu) || // Number Forms, Arrows, Mathematical Operators
(0x2460u <= aChar && aChar <= 0x24ffu) || // Enclosed Alphanumerics
(0x2580u <= aChar && aChar <= 0x27bfu) || // Block Elements, Geometric Shapes, Miscellaneous Symbols, Dingbats
(0x27f0u <= aChar && aChar <= 0x2bffu) || // Supplemental Arrows-A, Braille Patterns, Supplemental Arrows-B,
// Miscellaneous Mathematical Symbols-B, Supplemental Mathematical Operators,
// Miscellaneous Symbols and Arrows
(0x2e80u <= aChar && aChar <= 0x312fu) || // CJK Radicals Supplement, CJK Radicals Supplement,
// Ideographic Description Characters, CJK Symbols and Punctuation,
// Hiragana, Katakana, Bopomofo
(0x3190u <= aChar && aChar <= 0xabffu) || // Kanbun, Bopomofo Extended, Katakana Phonetic Extensions,
// Enclosed CJK Letters and Months, CJK Compatibility,
// CJK Unified Ideographs Extension A, Yijing Hexagram Symbols,
// CJK Unified Ideographs, Yi Syllables, Yi Radicals
(0xf900u <= aChar && aChar <= 0xfaffu) || // CJK Compatibility Ideographs
(0xff5eu <= aChar && aChar <= 0xff9fu) // Halfwidth and Fullwidth Forms(a part)
))
return PR_TRUE;
return PR_FALSE;
}
/**
* Prepare the text in the content for rendering. If aIndexes is not nsnull
* then fill in aIndexes's with the mapping from the original input to
* the prepared output.
*/
void
PRIntn
nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
nsAutoIndexBuffer* aIndexBuffer,
nsAutoTextBuffer* aTextBuffer,
PRInt32* aTextLen,
PRBool aForceArabicShaping,
PRIntn* aJustifiableCharCount)
PRBool aForceArabicShaping)
{
PRIntn numSpaces = 0;
// Setup transform to operate starting in the content at our content
// offset
aTX.Init(this, mContent, mContentOffset, aForceArabicShaping);
@ -1592,12 +1545,6 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
PRInt32 column = mColumn;
PRInt32 textLength = 0;
PRInt32 dstOffset = 0;
nsAutoTextBuffer tmpTextBuffer;
nsAutoTextBuffer* textBuffer = aTextBuffer;
if (!textBuffer && aJustifiableCharCount)
textBuffer = &tmpTextBuffer;
while (0 != n) {
PRUnichar* bp;
PRBool isWhitespace, wasTransformed;
@ -1663,6 +1610,7 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
}
}
}
numSpaces += wordLen;
}
else {
PRInt32 i;
@ -1683,12 +1631,20 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
}
}
}
// 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 (textBuffer != nsnull && dstOffset + wordLen > textBuffer->mBufferLen) {
nsresult rv = textBuffer->GrowBy(wordLen);
if (aTextBuffer != nsnull && dstOffset + wordLen > aTextBuffer->mBufferLen) {
nsresult rv = aTextBuffer->GrowBy(wordLen);
if (NS_FAILED(rv)) {
break;
}
@ -1697,8 +1653,8 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
column += wordLen;
textLength += wordLen;
n -= contentLen;
if (textBuffer != nsnull) {
memcpy(textBuffer->mBuffer + dstOffset, bp,
if (aTextBuffer != nsnull) {
memcpy(aTextBuffer->mBuffer + dstOffset, bp,
sizeof(PRUnichar)*wordLen);
}
dstOffset += wordLen;
@ -1709,8 +1665,8 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
NS_ASSERTION(indexp <= aIndexBuffer->mBuffer + aIndexBuffer->mBufferLen,
"yikes - we just overwrote memory");
}
if (textBuffer) {
NS_ASSERTION(dstOffset <= textBuffer->mBufferLen,
if (aTextBuffer) {
NS_ASSERTION(dstOffset <= aTextBuffer->mBufferLen,
"yikes - we just overwrote memory");
}
@ -1719,11 +1675,13 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
// Remove trailing whitespace if it was trimmed after reflow
// TEXT_TRIMMED_WS can be set in measureText during reflow, and
// nonexitent text buffer may occur in this situation.
if (TEXT_TRIMMED_WS & mState && textBuffer) {
if (TEXT_TRIMMED_WS & mState && aTextBuffer) {
if (--dstOffset >= 0) {
PRUnichar ch = textBuffer->mBuffer[dstOffset];
if (XP_IS_SPACE(ch))
PRUnichar ch = aTextBuffer->mBuffer[dstOffset];
if (XP_IS_SPACE(ch)) {
textLength--;
numSpaces--;
}
}
}
@ -1737,16 +1695,7 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
}
*aTextLen = textLength;
if (aJustifiableCharCount && textBuffer) {
PRBool isCJ = IsChineseJapaneseLangGroup();
PRIntn numJustifiableCharacter = 0;
for (PRInt32 i = 0; i < textLength; i++) {
if (IsJustifiableCharacter(textBuffer->mBuffer[i], isCJ))
numJustifiableCharacter++;
}
*aJustifiableCharCount = numJustifiableCharacter;
}
return numSpaces;
}
@ -2554,9 +2503,9 @@ nsTextFrame::GetPositionSlowly(nsPresContext* aPresContext,
// Transform text from content into renderable form
nsTextTransformer tx(doc->GetLineBreaker(), nsnull, aPresContext);
PRInt32 textLength;
PRIntn numJustifiableCharacter;
PRInt32 numSpaces;
PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength, PR_TRUE, &numJustifiableCharacter);
numSpaces = PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength, PR_TRUE);
if (textLength <= 0) {
// If we've already assigned aNewContent, make sure to 0 it out here.
// aNewContent is undefined in the case that we return a failure,
@ -2580,7 +2529,7 @@ nsTextFrame::GetPositionSlowly(nsPresContext* aPresContext,
}
#endif // IBMBIDI
ComputeExtraJustificationSpacing(*aRendContext, ts, paintBuffer.mBuffer, textLength, numJustifiableCharacter);
ComputeExtraJustificationSpacing(*aRendContext, ts, paintBuffer.mBuffer, textLength, numSpaces);
//IF STYLE SAYS TO SELECT TO END OF FRAME HERE...
PRInt32 prefInt =
@ -2650,11 +2599,6 @@ nsTextFrame::RenderString(nsIRenderingContext& aRenderingContext,
PRBool spacing = (0 != aTextStyle.mLetterSpacing) ||
(0 != aTextStyle.mWordSpacing) || aTextStyle.mJustifying;
PRBool justifying = aTextStyle.mJustifying &&
(aTextStyle.mNumJustifiableCharacterReceivingExtraJot != 0 || aTextStyle.mExtraSpacePerJustifiableCharacter != 0);
PRBool isCJ = IsChineseJapaneseLangGroup();
//German 0x00df might expand to "SS", but no need to count it for speed reason
if (aTextStyle.mSmallCaps) {
if (aLength*2 > TEXT_BUF_SIZE) {
@ -2710,7 +2654,12 @@ nsTextFrame::RenderString(nsIRenderingContext& aRenderingContext,
}
else if (ch == ' ') {
nextFont = aTextStyle.mNormalFont;
glyphWidth = aTextStyle.mSpaceWidth + aTextStyle.mWordSpacing + aTextStyle.mLetterSpacing;
glyphWidth = aTextStyle.mSpaceWidth + aTextStyle.mWordSpacing + aTextStyle.mLetterSpacing
+ aTextStyle.mExtraSpacePerSpace;
if ((PRUint32)--aTextStyle.mNumSpacesToRender <
(PRUint32)aTextStyle.mNumSpacesReceivingExtraJot) {
glyphWidth++;
}
}
else {
if (lastFont != aTextStyle.mNormalFont) {
@ -2744,13 +2693,6 @@ nsTextFrame::RenderString(nsIRenderingContext& aRenderingContext,
}
nextFont = aTextStyle.mNormalFont;
}
if (justifying && IsJustifiableCharacter(ch, isCJ)) {
glyphWidth += aTextStyle.mExtraSpacePerJustifiableCharacter;
if ((PRUint32)--aTextStyle.mNumJustifiableCharacterToRender
< (PRUint32)aTextStyle.mNumJustifiableCharacterReceivingExtraJot) {
glyphWidth++;
}
}
if (nextFont != lastFont) {
pendingCount = bp - runStart;
if (0 != pendingCount) {
@ -2837,10 +2779,6 @@ nsTextFrame::GetTextDimensionsOrLength(nsIRenderingContext& aRenderingContext,
nsIFontMetrics* lastFont = aStyle.mLastFont;
nsTextDimensions sum, glyphDimensions;
PRBool justifying = aStyle.mJustifying &&
(aStyle.mNumJustifiableCharacterReceivingExtraJot != 0 || aStyle.mExtraSpacePerJustifiableCharacter != 0);
PRBool isCJ = IsChineseJapaneseLangGroup();
while (--length >= 0) {
PRUnichar ch = *inBuffer++;
if (aStyle.mSmallCaps &&
@ -2862,7 +2800,11 @@ nsTextFrame::GetTextDimensionsOrLength(nsIRenderingContext& aRenderingContext,
}
else if (ch == ' ') {
glyphDimensions.width = aStyle.mSpaceWidth + aStyle.mLetterSpacing
+ aStyle.mWordSpacing;
+ aStyle.mWordSpacing + aStyle.mExtraSpacePerSpace;
if ((PRUint32)--aStyle.mNumSpacesToMeasure
< (PRUint32)aStyle.mNumSpacesReceivingExtraJot) {
++glyphDimensions.width;
}
}
else {
if (lastFont != aStyle.mNormalFont) {
@ -2872,13 +2814,6 @@ nsTextFrame::GetTextDimensionsOrLength(nsIRenderingContext& aRenderingContext,
aRenderingContext.GetTextDimensions(&ch, (PRUint32)1, glyphDimensions);
glyphDimensions.width += aStyle.mLetterSpacing;
}
if (justifying && IsJustifiableCharacter(ch, isCJ)) {
glyphDimensions.width += aStyle.mExtraSpacePerJustifiableCharacter;
if ((PRUint32)--aStyle.mNumJustifiableCharacterToMeasure
< (PRUint32)aStyle.mNumJustifiableCharacterReceivingExtraJot) {
++glyphDimensions.width;
}
}
sum.Combine(glyphDimensions);
*bp++ = ch;
if (!aGetTextDimensions && sum.width >= aDimensionsResult->width) {
@ -2920,38 +2855,38 @@ void
nsTextFrame::ComputeExtraJustificationSpacing(nsIRenderingContext& aRenderingContext,
TextStyle& aTextStyle,
PRUnichar* aBuffer, PRInt32 aLength,
PRInt32 aNumJustifiableCharacter)
PRInt32 aNumSpaces)
{
if (aTextStyle.mJustifying) {
nsTextDimensions trueDimensions;
// 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
// justifiable characters. It has to be the same ones every time or things will go haywire.
// spaces. It has to be the same ones every time or things will go haywire.
// This implies that the GetTextDimensionsOrLength 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 justifiable character
// 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.mNumJustifiableCharacterToMeasure = 0;
aTextStyle.mExtraSpacePerJustifiableCharacter = 0;
aTextStyle.mNumJustifiableCharacterReceivingExtraJot = 0;
aTextStyle.mNumSpacesToMeasure = 0;
aTextStyle.mExtraSpacePerSpace = 0;
aTextStyle.mNumSpacesReceivingExtraJot = 0;
GetTextDimensions(aRenderingContext, aTextStyle, aBuffer, aLength, &trueDimensions);
aTextStyle.mNumJustifiableCharacterToMeasure = aNumJustifiableCharacter;
aTextStyle.mNumJustifiableCharacterToRender = aNumJustifiableCharacter;
aTextStyle.mNumSpacesToMeasure = aNumSpaces;
aTextStyle.mNumSpacesToRender = aNumSpaces;
nscoord extraSpace = mRect.width - trueDimensions.width;
if (extraSpace > 0 && aNumJustifiableCharacter > 0) {
aTextStyle.mExtraSpacePerJustifiableCharacter = extraSpace/aNumJustifiableCharacter;
aTextStyle.mNumJustifiableCharacterReceivingExtraJot =
extraSpace - aTextStyle.mExtraSpacePerJustifiableCharacter*aNumJustifiableCharacter;
if (extraSpace > 0 && aNumSpaces > 0) {
aTextStyle.mExtraSpacePerSpace = extraSpace/aNumSpaces;
aTextStyle.mNumSpacesReceivingExtraJot =
extraSpace - aTextStyle.mExtraSpacePerSpace*aNumSpaces;
}
}
}
@ -2997,10 +2932,10 @@ nsTextFrame::PaintTextSlowly(nsPresContext* aPresContext,
PRInt32 textLength;
nsTextTransformer tx(lb, nsnull, aPresContext);
PRIntn numJustifiableCharacter;
PRInt32 numSpaces;
PrepareUnicodeText(tx, (displaySelection ? &indexBuffer : nsnull),
&paintBuffer, &textLength, PR_TRUE, &numJustifiableCharacter);
numSpaces = PrepareUnicodeText(tx, (displaySelection ? &indexBuffer : nsnull),
&paintBuffer, &textLength, PR_TRUE);
PRInt32* ip = indexBuffer.mBuffer;
PRUnichar* text = paintBuffer.mBuffer;
@ -3026,7 +2961,7 @@ nsTextFrame::PaintTextSlowly(nsPresContext* aPresContext,
}
}
#endif // IBMBIDI
ComputeExtraJustificationSpacing(aRenderingContext, aTextStyle, text, textLength, numJustifiableCharacter);
ComputeExtraJustificationSpacing(aRenderingContext, aTextStyle, text, textLength, numSpaces);
if (!displaySelection || !isSelected) {
// When there is no selection showing, use the fastest and
// simplest rendering approach
@ -3791,11 +3726,11 @@ nsTextFrame::GetPointFromOffset(nsPresContext* aPresContext,
nsIDocument *doc = GetDocument(aPresContext);
nsTextTransformer tx(doc->GetLineBreaker(), nsnull, aPresContext);
PRInt32 textLength;
PRIntn numJustifiableCharacter;
PRInt32 numSpaces;
PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength, PR_FALSE, &numJustifiableCharacter);
numSpaces = PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
ComputeExtraJustificationSpacing(*inRendContext, ts, paintBuffer.mBuffer, textLength, numJustifiableCharacter);
ComputeExtraJustificationSpacing(*inRendContext, ts, paintBuffer.mBuffer, textLength, numSpaces);
PRInt32* ip = indexBuffer.mBuffer;
@ -5456,7 +5391,7 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
// Compute space and letter counts for justification, if required
if (ts.mJustifying) {
PRIntn numJustifiableCharacter;
PRInt32 numSpaces;
PRInt32 textLength;
// This will include a space for trailing whitespace, if any is present.
@ -5466,8 +5401,8 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
// 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.
PrepareUnicodeText(tx, nsnull, nsnull, &textLength, PR_TRUE, &numJustifiableCharacter);
lineLayout.SetTextJustificationWeights(numJustifiableCharacter, textLength - numJustifiableCharacter);
numSpaces = PrepareUnicodeText(tx, nsnull, nsnull, &textLength, PR_TRUE);
lineLayout.SetTextJustificationWeights(numSpaces, textLength - numSpaces);
}

View File

@ -2720,7 +2720,9 @@ nsLineLayout::ApplyFrameJustification(PerSpanData* aPSD, FrameJustificationState
if (PR_TRUE == pfd->GetFlag(PFD_ISTEXTFRAME)) {
if (aState->mTotalWidthForSpaces > 0 &&
aState->mTotalNumSpaces > 0) {
aState->mTotalNumSpaces > 0 && // we divide by this value, so must be non-zero
aState->mTotalNumLetters >0 // we divide by this value, so must be non-zero
) {
aState->mNumSpacesProcessed += pfd->mJustificationNumSpaces;
nscoord newAllocatedWidthForSpaces =
@ -2732,8 +2734,7 @@ nsLineLayout::ApplyFrameJustification(PerSpanData* aPSD, FrameJustificationState
aState->mWidthForSpacesProcessed = newAllocatedWidthForSpaces;
}
if (aState->mTotalWidthForLetters > 0 &&
aState->mTotalNumLetters > 0) {
if (aState->mTotalWidthForLetters > 0) {
aState->mNumLettersProcessed += pfd->mJustificationNumLetters;
nscoord newAllocatedWidthForLetters =

View File

@ -513,10 +513,10 @@ public:
nscoord mAveCharWidth;
PRBool mJustifying;
PRBool mPreformatted;
PRInt32 mNumJustifiableCharacterToRender;
PRInt32 mNumJustifiableCharacterToMeasure;
nscoord mExtraSpacePerJustifiableCharacter;
PRInt32 mNumJustifiableCharacterReceivingExtraJot;
PRInt32 mNumSpacesToRender;
PRInt32 mNumSpacesToMeasure;
nscoord mExtraSpacePerSpace;
PRInt32 mNumSpacesReceivingExtraJot;
TextStyle(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
@ -570,10 +570,10 @@ public:
mLetterSpacing = 0;
}
mNumJustifiableCharacterToRender = 0;
mNumJustifiableCharacterToMeasure = 0;
mNumJustifiableCharacterReceivingExtraJot = 0;
mExtraSpacePerJustifiableCharacter = 0;
mNumSpacesToRender = 0;
mNumSpacesToMeasure = 0;
mNumSpacesReceivingExtraJot = 0;
mExtraSpacePerSpace = 0;
mPreformatted = (NS_STYLE_WHITESPACE_PRE == mText->mWhiteSpace) ||
(NS_STYLE_WHITESPACE_MOZ_PRE_WRAP == mText->mWhiteSpace);
@ -657,15 +657,14 @@ public:
nsIDocument* GetDocument(nsPresContext* aPresContext);
void PrepareUnicodeText(nsTextTransformer& aTransformer,
nsAutoIndexBuffer* aIndexBuffer,
nsAutoTextBuffer* aTextBuffer,
PRInt32* aTextLen,
PRBool aForceArabicShaping = PR_FALSE,
PRIntn* aJustifiableCharCount = nsnull);
PRIntn PrepareUnicodeText(nsTextTransformer& aTransformer,
nsAutoIndexBuffer* aIndexBuffer,
nsAutoTextBuffer* aTextBuffer,
PRInt32* aTextLen,
PRBool aForceArabicShaping = PR_FALSE);
void ComputeExtraJustificationSpacing(nsIRenderingContext& aRenderingContext,
TextStyle& aTextStyle,
PRUnichar* aBuffer, PRInt32 aLength, PRInt32 aNumJustifiableCharacter);
PRUnichar* aBuffer, PRInt32 aLength, PRInt32 aNumSpaces);
void PaintTextDecorations(nsIRenderingContext& aRenderingContext,
nsStyleContext* aStyleContext,
@ -798,9 +797,6 @@ protected:
PRBool isBidiSystem);
void SetOffsets(PRInt32 start, PRInt32 end);
PRBool IsChineseJapaneseLangGroup();
PRBool IsJustifiableCharacter(PRUnichar aChar, PRBool aLangIsCJ);
};
#ifdef ACCESSIBILITY
@ -1487,64 +1483,21 @@ nsTextFrame::Paint(nsPresContext* aPresContext,
return NS_OK;
}
PRBool
nsTextFrame::IsChineseJapaneseLangGroup()
{
const nsStyleVisibility* visibility = mStyleContext->GetStyleVisibility();
if (visibility->mLangGroup == nsLayoutAtoms::Japanese
|| visibility->mLangGroup == nsLayoutAtoms::Chinese
|| visibility->mLangGroup == nsLayoutAtoms::Taiwanese
|| visibility->mLangGroup == nsLayoutAtoms::HongKongChinese)
return PR_TRUE;
return PR_FALSE;
}
/*
* XXX Currently only Unicode characters in the BMP (below U+10000) have their
* spacing modified by justification.
*/
inline PRBool
nsTextFrame::IsJustifiableCharacter(PRUnichar aChar, PRBool aLangIsCJ)
{
if (0x20u == aChar || 0xa0u == aChar)
return PR_TRUE;
if (aChar < 0x2150u)
return PR_FALSE;
if (aLangIsCJ && (
(0x2150u <= aChar && aChar <= 0x22ffu) || // Number Forms, Arrows, Mathematical Operators
(0x2460u <= aChar && aChar <= 0x24ffu) || // Enclosed Alphanumerics
(0x2580u <= aChar && aChar <= 0x27bfu) || // Block Elements, Geometric Shapes, Miscellaneous Symbols, Dingbats
(0x27f0u <= aChar && aChar <= 0x2bffu) || // Supplemental Arrows-A, Braille Patterns, Supplemental Arrows-B,
// Miscellaneous Mathematical Symbols-B, Supplemental Mathematical Operators,
// Miscellaneous Symbols and Arrows
(0x2e80u <= aChar && aChar <= 0x312fu) || // CJK Radicals Supplement, CJK Radicals Supplement,
// Ideographic Description Characters, CJK Symbols and Punctuation,
// Hiragana, Katakana, Bopomofo
(0x3190u <= aChar && aChar <= 0xabffu) || // Kanbun, Bopomofo Extended, Katakana Phonetic Extensions,
// Enclosed CJK Letters and Months, CJK Compatibility,
// CJK Unified Ideographs Extension A, Yijing Hexagram Symbols,
// CJK Unified Ideographs, Yi Syllables, Yi Radicals
(0xf900u <= aChar && aChar <= 0xfaffu) || // CJK Compatibility Ideographs
(0xff5eu <= aChar && aChar <= 0xff9fu) // Halfwidth and Fullwidth Forms(a part)
))
return PR_TRUE;
return PR_FALSE;
}
/**
* Prepare the text in the content for rendering. If aIndexes is not nsnull
* then fill in aIndexes's with the mapping from the original input to
* the prepared output.
*/
void
PRIntn
nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
nsAutoIndexBuffer* aIndexBuffer,
nsAutoTextBuffer* aTextBuffer,
PRInt32* aTextLen,
PRBool aForceArabicShaping,
PRIntn* aJustifiableCharCount)
PRBool aForceArabicShaping)
{
PRIntn numSpaces = 0;
// Setup transform to operate starting in the content at our content
// offset
aTX.Init(this, mContent, mContentOffset, aForceArabicShaping);
@ -1592,12 +1545,6 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
PRInt32 column = mColumn;
PRInt32 textLength = 0;
PRInt32 dstOffset = 0;
nsAutoTextBuffer tmpTextBuffer;
nsAutoTextBuffer* textBuffer = aTextBuffer;
if (!textBuffer && aJustifiableCharCount)
textBuffer = &tmpTextBuffer;
while (0 != n) {
PRUnichar* bp;
PRBool isWhitespace, wasTransformed;
@ -1663,6 +1610,7 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
}
}
}
numSpaces += wordLen;
}
else {
PRInt32 i;
@ -1683,12 +1631,20 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
}
}
}
// 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 (textBuffer != nsnull && dstOffset + wordLen > textBuffer->mBufferLen) {
nsresult rv = textBuffer->GrowBy(wordLen);
if (aTextBuffer != nsnull && dstOffset + wordLen > aTextBuffer->mBufferLen) {
nsresult rv = aTextBuffer->GrowBy(wordLen);
if (NS_FAILED(rv)) {
break;
}
@ -1697,8 +1653,8 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
column += wordLen;
textLength += wordLen;
n -= contentLen;
if (textBuffer != nsnull) {
memcpy(textBuffer->mBuffer + dstOffset, bp,
if (aTextBuffer != nsnull) {
memcpy(aTextBuffer->mBuffer + dstOffset, bp,
sizeof(PRUnichar)*wordLen);
}
dstOffset += wordLen;
@ -1709,8 +1665,8 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
NS_ASSERTION(indexp <= aIndexBuffer->mBuffer + aIndexBuffer->mBufferLen,
"yikes - we just overwrote memory");
}
if (textBuffer) {
NS_ASSERTION(dstOffset <= textBuffer->mBufferLen,
if (aTextBuffer) {
NS_ASSERTION(dstOffset <= aTextBuffer->mBufferLen,
"yikes - we just overwrote memory");
}
@ -1719,11 +1675,13 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
// Remove trailing whitespace if it was trimmed after reflow
// TEXT_TRIMMED_WS can be set in measureText during reflow, and
// nonexitent text buffer may occur in this situation.
if (TEXT_TRIMMED_WS & mState && textBuffer) {
if (TEXT_TRIMMED_WS & mState && aTextBuffer) {
if (--dstOffset >= 0) {
PRUnichar ch = textBuffer->mBuffer[dstOffset];
if (XP_IS_SPACE(ch))
PRUnichar ch = aTextBuffer->mBuffer[dstOffset];
if (XP_IS_SPACE(ch)) {
textLength--;
numSpaces--;
}
}
}
@ -1737,16 +1695,7 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
}
*aTextLen = textLength;
if (aJustifiableCharCount && textBuffer) {
PRBool isCJ = IsChineseJapaneseLangGroup();
PRIntn numJustifiableCharacter = 0;
for (PRInt32 i = 0; i < textLength; i++) {
if (IsJustifiableCharacter(textBuffer->mBuffer[i], isCJ))
numJustifiableCharacter++;
}
*aJustifiableCharCount = numJustifiableCharacter;
}
return numSpaces;
}
@ -2554,9 +2503,9 @@ nsTextFrame::GetPositionSlowly(nsPresContext* aPresContext,
// Transform text from content into renderable form
nsTextTransformer tx(doc->GetLineBreaker(), nsnull, aPresContext);
PRInt32 textLength;
PRIntn numJustifiableCharacter;
PRInt32 numSpaces;
PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength, PR_TRUE, &numJustifiableCharacter);
numSpaces = PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength, PR_TRUE);
if (textLength <= 0) {
// If we've already assigned aNewContent, make sure to 0 it out here.
// aNewContent is undefined in the case that we return a failure,
@ -2580,7 +2529,7 @@ nsTextFrame::GetPositionSlowly(nsPresContext* aPresContext,
}
#endif // IBMBIDI
ComputeExtraJustificationSpacing(*aRendContext, ts, paintBuffer.mBuffer, textLength, numJustifiableCharacter);
ComputeExtraJustificationSpacing(*aRendContext, ts, paintBuffer.mBuffer, textLength, numSpaces);
//IF STYLE SAYS TO SELECT TO END OF FRAME HERE...
PRInt32 prefInt =
@ -2650,11 +2599,6 @@ nsTextFrame::RenderString(nsIRenderingContext& aRenderingContext,
PRBool spacing = (0 != aTextStyle.mLetterSpacing) ||
(0 != aTextStyle.mWordSpacing) || aTextStyle.mJustifying;
PRBool justifying = aTextStyle.mJustifying &&
(aTextStyle.mNumJustifiableCharacterReceivingExtraJot != 0 || aTextStyle.mExtraSpacePerJustifiableCharacter != 0);
PRBool isCJ = IsChineseJapaneseLangGroup();
//German 0x00df might expand to "SS", but no need to count it for speed reason
if (aTextStyle.mSmallCaps) {
if (aLength*2 > TEXT_BUF_SIZE) {
@ -2710,7 +2654,12 @@ nsTextFrame::RenderString(nsIRenderingContext& aRenderingContext,
}
else if (ch == ' ') {
nextFont = aTextStyle.mNormalFont;
glyphWidth = aTextStyle.mSpaceWidth + aTextStyle.mWordSpacing + aTextStyle.mLetterSpacing;
glyphWidth = aTextStyle.mSpaceWidth + aTextStyle.mWordSpacing + aTextStyle.mLetterSpacing
+ aTextStyle.mExtraSpacePerSpace;
if ((PRUint32)--aTextStyle.mNumSpacesToRender <
(PRUint32)aTextStyle.mNumSpacesReceivingExtraJot) {
glyphWidth++;
}
}
else {
if (lastFont != aTextStyle.mNormalFont) {
@ -2744,13 +2693,6 @@ nsTextFrame::RenderString(nsIRenderingContext& aRenderingContext,
}
nextFont = aTextStyle.mNormalFont;
}
if (justifying && IsJustifiableCharacter(ch, isCJ)) {
glyphWidth += aTextStyle.mExtraSpacePerJustifiableCharacter;
if ((PRUint32)--aTextStyle.mNumJustifiableCharacterToRender
< (PRUint32)aTextStyle.mNumJustifiableCharacterReceivingExtraJot) {
glyphWidth++;
}
}
if (nextFont != lastFont) {
pendingCount = bp - runStart;
if (0 != pendingCount) {
@ -2837,10 +2779,6 @@ nsTextFrame::GetTextDimensionsOrLength(nsIRenderingContext& aRenderingContext,
nsIFontMetrics* lastFont = aStyle.mLastFont;
nsTextDimensions sum, glyphDimensions;
PRBool justifying = aStyle.mJustifying &&
(aStyle.mNumJustifiableCharacterReceivingExtraJot != 0 || aStyle.mExtraSpacePerJustifiableCharacter != 0);
PRBool isCJ = IsChineseJapaneseLangGroup();
while (--length >= 0) {
PRUnichar ch = *inBuffer++;
if (aStyle.mSmallCaps &&
@ -2862,7 +2800,11 @@ nsTextFrame::GetTextDimensionsOrLength(nsIRenderingContext& aRenderingContext,
}
else if (ch == ' ') {
glyphDimensions.width = aStyle.mSpaceWidth + aStyle.mLetterSpacing
+ aStyle.mWordSpacing;
+ aStyle.mWordSpacing + aStyle.mExtraSpacePerSpace;
if ((PRUint32)--aStyle.mNumSpacesToMeasure
< (PRUint32)aStyle.mNumSpacesReceivingExtraJot) {
++glyphDimensions.width;
}
}
else {
if (lastFont != aStyle.mNormalFont) {
@ -2872,13 +2814,6 @@ nsTextFrame::GetTextDimensionsOrLength(nsIRenderingContext& aRenderingContext,
aRenderingContext.GetTextDimensions(&ch, (PRUint32)1, glyphDimensions);
glyphDimensions.width += aStyle.mLetterSpacing;
}
if (justifying && IsJustifiableCharacter(ch, isCJ)) {
glyphDimensions.width += aStyle.mExtraSpacePerJustifiableCharacter;
if ((PRUint32)--aStyle.mNumJustifiableCharacterToMeasure
< (PRUint32)aStyle.mNumJustifiableCharacterReceivingExtraJot) {
++glyphDimensions.width;
}
}
sum.Combine(glyphDimensions);
*bp++ = ch;
if (!aGetTextDimensions && sum.width >= aDimensionsResult->width) {
@ -2920,38 +2855,38 @@ void
nsTextFrame::ComputeExtraJustificationSpacing(nsIRenderingContext& aRenderingContext,
TextStyle& aTextStyle,
PRUnichar* aBuffer, PRInt32 aLength,
PRInt32 aNumJustifiableCharacter)
PRInt32 aNumSpaces)
{
if (aTextStyle.mJustifying) {
nsTextDimensions trueDimensions;
// 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
// justifiable characters. It has to be the same ones every time or things will go haywire.
// spaces. It has to be the same ones every time or things will go haywire.
// This implies that the GetTextDimensionsOrLength 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 justifiable character
// 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.mNumJustifiableCharacterToMeasure = 0;
aTextStyle.mExtraSpacePerJustifiableCharacter = 0;
aTextStyle.mNumJustifiableCharacterReceivingExtraJot = 0;
aTextStyle.mNumSpacesToMeasure = 0;
aTextStyle.mExtraSpacePerSpace = 0;
aTextStyle.mNumSpacesReceivingExtraJot = 0;
GetTextDimensions(aRenderingContext, aTextStyle, aBuffer, aLength, &trueDimensions);
aTextStyle.mNumJustifiableCharacterToMeasure = aNumJustifiableCharacter;
aTextStyle.mNumJustifiableCharacterToRender = aNumJustifiableCharacter;
aTextStyle.mNumSpacesToMeasure = aNumSpaces;
aTextStyle.mNumSpacesToRender = aNumSpaces;
nscoord extraSpace = mRect.width - trueDimensions.width;
if (extraSpace > 0 && aNumJustifiableCharacter > 0) {
aTextStyle.mExtraSpacePerJustifiableCharacter = extraSpace/aNumJustifiableCharacter;
aTextStyle.mNumJustifiableCharacterReceivingExtraJot =
extraSpace - aTextStyle.mExtraSpacePerJustifiableCharacter*aNumJustifiableCharacter;
if (extraSpace > 0 && aNumSpaces > 0) {
aTextStyle.mExtraSpacePerSpace = extraSpace/aNumSpaces;
aTextStyle.mNumSpacesReceivingExtraJot =
extraSpace - aTextStyle.mExtraSpacePerSpace*aNumSpaces;
}
}
}
@ -2997,10 +2932,10 @@ nsTextFrame::PaintTextSlowly(nsPresContext* aPresContext,
PRInt32 textLength;
nsTextTransformer tx(lb, nsnull, aPresContext);
PRIntn numJustifiableCharacter;
PRInt32 numSpaces;
PrepareUnicodeText(tx, (displaySelection ? &indexBuffer : nsnull),
&paintBuffer, &textLength, PR_TRUE, &numJustifiableCharacter);
numSpaces = PrepareUnicodeText(tx, (displaySelection ? &indexBuffer : nsnull),
&paintBuffer, &textLength, PR_TRUE);
PRInt32* ip = indexBuffer.mBuffer;
PRUnichar* text = paintBuffer.mBuffer;
@ -3026,7 +2961,7 @@ nsTextFrame::PaintTextSlowly(nsPresContext* aPresContext,
}
}
#endif // IBMBIDI
ComputeExtraJustificationSpacing(aRenderingContext, aTextStyle, text, textLength, numJustifiableCharacter);
ComputeExtraJustificationSpacing(aRenderingContext, aTextStyle, text, textLength, numSpaces);
if (!displaySelection || !isSelected) {
// When there is no selection showing, use the fastest and
// simplest rendering approach
@ -3791,11 +3726,11 @@ nsTextFrame::GetPointFromOffset(nsPresContext* aPresContext,
nsIDocument *doc = GetDocument(aPresContext);
nsTextTransformer tx(doc->GetLineBreaker(), nsnull, aPresContext);
PRInt32 textLength;
PRIntn numJustifiableCharacter;
PRInt32 numSpaces;
PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength, PR_FALSE, &numJustifiableCharacter);
numSpaces = PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
ComputeExtraJustificationSpacing(*inRendContext, ts, paintBuffer.mBuffer, textLength, numJustifiableCharacter);
ComputeExtraJustificationSpacing(*inRendContext, ts, paintBuffer.mBuffer, textLength, numSpaces);
PRInt32* ip = indexBuffer.mBuffer;
@ -5456,7 +5391,7 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
// Compute space and letter counts for justification, if required
if (ts.mJustifying) {
PRIntn numJustifiableCharacter;
PRInt32 numSpaces;
PRInt32 textLength;
// This will include a space for trailing whitespace, if any is present.
@ -5466,8 +5401,8 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
// 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.
PrepareUnicodeText(tx, nsnull, nsnull, &textLength, PR_TRUE, &numJustifiableCharacter);
lineLayout.SetTextJustificationWeights(numJustifiableCharacter, textLength - numJustifiableCharacter);
numSpaces = PrepareUnicodeText(tx, nsnull, nsnull, &textLength, PR_TRUE);
lineLayout.SetTextJustificationWeights(numSpaces, textLength - numSpaces);
}