Correct a regression in Bidi ordering and simplify the way in which we determine whether Arabic shaping needs to be performed depending on the capabilities of the system and whether we are rendering character by character. Bug 192919, r/sr=rbs.

This commit is contained in:
smontagu%netscape.com 2003-03-07 20:56:03 +00:00
parent 6bde6f9da6
commit c27c3fff25
6 changed files with 104 additions and 102 deletions

View File

@ -667,7 +667,8 @@ public:
PRIntn PrepareUnicodeText(nsTextTransformer& aTransformer, PRIntn PrepareUnicodeText(nsTextTransformer& aTransformer,
nsAutoIndexBuffer* aIndexBuffer, nsAutoIndexBuffer* aIndexBuffer,
nsAutoTextBuffer* aTextBuffer, nsAutoTextBuffer* aTextBuffer,
PRInt32* aTextLen); PRInt32* aTextLen,
PRBool aForceArabicShaping = PR_FALSE);
void ComputeExtraJustificationSpacing(nsIRenderingContext& aRenderingContext, void ComputeExtraJustificationSpacing(nsIRenderingContext& aRenderingContext,
TextStyle& aTextStyle, TextStyle& aTextStyle,
PRUnichar* aBuffer, PRInt32 aLength, PRInt32 aNumSpaces); PRUnichar* aBuffer, PRInt32 aLength, PRInt32 aNumSpaces);
@ -1523,13 +1524,14 @@ PRIntn
nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX, nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
nsAutoIndexBuffer* aIndexBuffer, nsAutoIndexBuffer* aIndexBuffer,
nsAutoTextBuffer* aTextBuffer, nsAutoTextBuffer* aTextBuffer,
PRInt32* aTextLen) PRInt32* aTextLen,
PRBool aForceArabicShaping)
{ {
PRIntn numSpaces = 0; PRIntn numSpaces = 0;
// Setup transform to operate starting in the content at our content // Setup transform to operate starting in the content at our content
// offset // offset
aTX.Init(this, mContent, mContentOffset); aTX.Init(this, mContent, mContentOffset, aForceArabicShaping);
PRInt32 strInx = mContentOffset; PRInt32 strInx = mContentOffset;
PRInt32* indexp = aIndexBuffer ? aIndexBuffer->mBuffer : nsnull; PRInt32* indexp = aIndexBuffer ? aIndexBuffer->mBuffer : nsnull;
@ -2559,16 +2561,7 @@ nsTextFrame::GetPositionSlowly(nsIPresContext* aPresContext,
PRInt32 textLength; PRInt32 textLength;
PRInt32 numSpaces; PRInt32 numSpaces;
#ifdef IBMBIDI numSpaces = PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength, PR_TRUE);
// Simulate a non-Bidi system for char by char measuring
PRBool isBidiSystem = PR_FALSE;
aPresContext->GetIsBidiSystem(isBidiSystem);
aPresContext->SetIsBidiSystem(PR_FALSE);
#endif
numSpaces = PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
#ifdef IBMBIDI
aPresContext->SetIsBidiSystem(isBidiSystem);
#endif
if (textLength <= 0) { if (textLength <= 0) {
// If we've already assigned aNewContent, make sure to 0 it out here. // If we've already assigned aNewContent, make sure to 0 it out here.
// aNewContent is undefined in the case that we return a failure, // aNewContent is undefined in the case that we return a failure,
@ -3000,17 +2993,8 @@ nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext,
nsTextTransformer tx(lb, nsnull, aPresContext); nsTextTransformer tx(lb, nsnull, aPresContext);
PRInt32 numSpaces; PRInt32 numSpaces;
#ifdef IBMBIDI
// Simulate a non-Bidi system for char by char painting
PRBool isBidiSystem = PR_FALSE;
aPresContext->GetIsBidiSystem(isBidiSystem);
aPresContext->SetIsBidiSystem(PR_FALSE);
#endif
numSpaces = PrepareUnicodeText(tx, (displaySelection ? &indexBuffer : nsnull), numSpaces = PrepareUnicodeText(tx, (displaySelection ? &indexBuffer : nsnull),
&paintBuffer, &textLength); &paintBuffer, &textLength, PR_TRUE);
#ifdef IBMBIDI
aPresContext->SetIsBidiSystem(isBidiSystem);
#endif
PRInt32* ip = indexBuffer.mBuffer; PRInt32* ip = indexBuffer.mBuffer;
PRUnichar* text = paintBuffer.mBuffer; PRUnichar* text = paintBuffer.mBuffer;
@ -5341,31 +5325,24 @@ nsTextFrame::Reflow(nsIPresContext* aPresContext,
nsLineLayout& lineLayout = *aReflowState.mLineLayout; nsLineLayout& lineLayout = *aReflowState.mLineLayout;
TextStyle ts(aPresContext, *aReflowState.rendContext, mStyleContext); TextStyle ts(aPresContext, *aReflowState.rendContext, mStyleContext);
#ifdef IBMBIDI
if ( (mContentLength > 0) && (mState & NS_FRAME_IS_BIDI) ) { if ( (mContentLength > 0) && (mState & NS_FRAME_IS_BIDI) ) {
startingOffset = mContentOffset; startingOffset = mContentOffset;
} }
if (ts.mSmallCaps || (0 != ts.mWordSpacing) || (0 != ts.mLetterSpacing)
|| ts.mJustifying) { PRBool bidiEnabled;
// simulate a non-Bidi system for char-by-char measuring and aPresContext->GetBidiEnabled(&bidiEnabled);
// rendering if (bidiEnabled) {
aPresContext->SetIsBidiSystem(PR_FALSE); nsCharType charType = eCharType_LeftToRight;
} PRUint32 hints = 0;
else { aReflowState.rendContext->GetHints(hints);
PRBool bidiEnabled; GetBidiProperty(aPresContext, nsLayoutAtoms::charType, (void**)&charType, sizeof(charType));
aPresContext->GetBidiEnabled(&bidiEnabled); if ((eCharType_RightToLeftArabic == charType &&
if (bidiEnabled) { (hints & NS_RENDERING_HINT_ARABIC_SHAPING) == NS_RENDERING_HINT_ARABIC_SHAPING) ||
nsCharType charType = eCharType_LeftToRight; (eCharType_RightToLeft == charType &&
PRUint32 hints = 0; (hints & NS_RENDERING_HINT_BIDI_REORDERING) == NS_RENDERING_HINT_BIDI_REORDERING)) {
aReflowState.rendContext->GetHints(hints); aPresContext->SetIsBidiSystem(PR_TRUE);
GetBidiProperty(aPresContext, nsLayoutAtoms::charType, (void**)&charType, sizeof(charType));
PRBool isBidiSystem = (eCharType_RightToLeftArabic == charType) ?
(hints & NS_RENDERING_HINT_ARABIC_SHAPING) :
(hints & NS_RENDERING_HINT_BIDI_REORDERING);
aPresContext->SetIsBidiSystem(isBidiSystem);
} }
} }
#endif //IBMBIDI
// Clear out the reflow state flags in mState (without destroying // Clear out the reflow state flags in mState (without destroying
// the TEXT_BLINK_ON bit). // the TEXT_BLINK_ON bit).
@ -5406,11 +5383,15 @@ nsTextFrame::Reflow(nsIPresContext* aPresContext,
} }
nsCOMPtr<nsILineBreaker> lb; nsCOMPtr<nsILineBreaker> lb;
doc->GetLineBreaker(getter_AddRefs(lb)); doc->GetLineBreaker(getter_AddRefs(lb));
PRBool forceArabicShaping = (ts.mSmallCaps ||
(0 != ts.mWordSpacing) ||
(0 != ts.mLetterSpacing) ||
ts.mJustifying);
nsTextTransformer tx(lb, nsnull, aPresContext); nsTextTransformer tx(lb, nsnull, aPresContext);
// Keep the text in ascii if possible. Note that if we're measuring small // Keep the text in ascii if possible. Note that if we're measuring small
// caps text then transform to Unicode because the helper function only // caps text then transform to Unicode because the helper function only
// accepts Unicode text // accepts Unicode text
nsresult rv = tx.Init(this, mContent, startingOffset, !ts.mSmallCaps); nsresult rv = tx.Init(this, mContent, startingOffset, forceArabicShaping, !ts.mSmallCaps);
if (NS_OK != rv) { if (NS_OK != rv) {
return rv; return rv;
} }
@ -5536,7 +5517,7 @@ nsTextFrame::Reflow(nsIPresContext* aPresContext,
// there because of the need to repair counts when wrapped words are backed out. // 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, // So I do it via PrepareUnicodeText ... a little slower perhaps, but a lot saner,
// and it localizes the counting logic to one place. // and it localizes the counting logic to one place.
numSpaces = PrepareUnicodeText(tx, nsnull, nsnull, &textLength); numSpaces = PrepareUnicodeText(tx, nsnull, nsnull, &textLength, PR_TRUE);
lineLayout.SetTextJustificationWeights(numSpaces, textLength - numSpaces); lineLayout.SetTextJustificationWeights(numSpaces, textLength - numSpaces);
} }

View File

@ -203,23 +203,42 @@ nsresult
nsTextTransformer::Init(nsIFrame* aFrame, nsTextTransformer::Init(nsIFrame* aFrame,
nsIContent* aContent, nsIContent* aContent,
PRInt32 aStartingOffset, PRInt32 aStartingOffset,
PRBool aForceArabicShaping,
PRBool aLeaveAsAscii) PRBool aLeaveAsAscii)
{ {
#ifdef IBMBIDI /*
* If the document has Bidi content, check whether we need to do
* Arabic shaping.
*
* Does the frame contains Arabic characters
* (mCharType == eCharType_RightToLeftArabic)?
* Are we rendering character by character (aForceArabicShaping ==
* PR_TRUE)? If so, we always do our own Arabic shaping, even if
* the platform has native shaping support. Otherwise, we only do
* shaping if the platform has no shaping support.
*
* We do numeric shaping in all Bidi documents.
*/
PRBool bidiEnabled; PRBool bidiEnabled;
mPresContext->GetBidiEnabled(&bidiEnabled); mPresContext->GetBidiEnabled(&bidiEnabled);
if (bidiEnabled) { if (bidiEnabled) {
PRBool isBidiSystem;
aFrame->GetBidiProperty(mPresContext, nsLayoutAtoms::charType, aFrame->GetBidiProperty(mPresContext, nsLayoutAtoms::charType,
(void**)&mCharType, sizeof(mCharType)); (void**)&mCharType, sizeof(mCharType));
mPresContext->GetIsBidiSystem(isBidiSystem); if (mCharType == eCharType_RightToLeftArabic) {
if (mCharType == eCharType_RightToLeftArabic && !isBidiSystem) { if (aForceArabicShaping) {
SetNeedsArabicShaping(PR_TRUE); SetNeedsArabicShaping(PR_TRUE);
}
else {
PRBool isBidiSystem;
mPresContext->GetIsBidiSystem(isBidiSystem);
if (!isBidiSystem) {
SetNeedsArabicShaping(PR_TRUE);
}
}
} }
SetNeedsNumericShaping(PR_TRUE); SetNeedsNumericShaping(PR_TRUE);
} }
#endif
// Get the contents text content // Get the contents text content
nsresult rv; nsresult rv;

View File

@ -162,6 +162,7 @@ public:
nsresult Init(nsIFrame* aFrame, nsresult Init(nsIFrame* aFrame,
nsIContent* aContent, nsIContent* aContent,
PRInt32 aStartingOffset, PRInt32 aStartingOffset,
PRBool aForceArabicShaping = PR_FALSE,
PRBool aLeaveAsAscii = PR_FALSE); PRBool aLeaveAsAscii = PR_FALSE);
PRInt32 GetContentLength() const { PRInt32 GetContentLength() const {

View File

@ -667,7 +667,8 @@ public:
PRIntn PrepareUnicodeText(nsTextTransformer& aTransformer, PRIntn PrepareUnicodeText(nsTextTransformer& aTransformer,
nsAutoIndexBuffer* aIndexBuffer, nsAutoIndexBuffer* aIndexBuffer,
nsAutoTextBuffer* aTextBuffer, nsAutoTextBuffer* aTextBuffer,
PRInt32* aTextLen); PRInt32* aTextLen,
PRBool aForceArabicShaping = PR_FALSE);
void ComputeExtraJustificationSpacing(nsIRenderingContext& aRenderingContext, void ComputeExtraJustificationSpacing(nsIRenderingContext& aRenderingContext,
TextStyle& aTextStyle, TextStyle& aTextStyle,
PRUnichar* aBuffer, PRInt32 aLength, PRInt32 aNumSpaces); PRUnichar* aBuffer, PRInt32 aLength, PRInt32 aNumSpaces);
@ -1523,13 +1524,14 @@ PRIntn
nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX, nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
nsAutoIndexBuffer* aIndexBuffer, nsAutoIndexBuffer* aIndexBuffer,
nsAutoTextBuffer* aTextBuffer, nsAutoTextBuffer* aTextBuffer,
PRInt32* aTextLen) PRInt32* aTextLen,
PRBool aForceArabicShaping)
{ {
PRIntn numSpaces = 0; PRIntn numSpaces = 0;
// Setup transform to operate starting in the content at our content // Setup transform to operate starting in the content at our content
// offset // offset
aTX.Init(this, mContent, mContentOffset); aTX.Init(this, mContent, mContentOffset, aForceArabicShaping);
PRInt32 strInx = mContentOffset; PRInt32 strInx = mContentOffset;
PRInt32* indexp = aIndexBuffer ? aIndexBuffer->mBuffer : nsnull; PRInt32* indexp = aIndexBuffer ? aIndexBuffer->mBuffer : nsnull;
@ -2559,16 +2561,7 @@ nsTextFrame::GetPositionSlowly(nsIPresContext* aPresContext,
PRInt32 textLength; PRInt32 textLength;
PRInt32 numSpaces; PRInt32 numSpaces;
#ifdef IBMBIDI numSpaces = PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength, PR_TRUE);
// Simulate a non-Bidi system for char by char measuring
PRBool isBidiSystem = PR_FALSE;
aPresContext->GetIsBidiSystem(isBidiSystem);
aPresContext->SetIsBidiSystem(PR_FALSE);
#endif
numSpaces = PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
#ifdef IBMBIDI
aPresContext->SetIsBidiSystem(isBidiSystem);
#endif
if (textLength <= 0) { if (textLength <= 0) {
// If we've already assigned aNewContent, make sure to 0 it out here. // If we've already assigned aNewContent, make sure to 0 it out here.
// aNewContent is undefined in the case that we return a failure, // aNewContent is undefined in the case that we return a failure,
@ -3000,17 +2993,8 @@ nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext,
nsTextTransformer tx(lb, nsnull, aPresContext); nsTextTransformer tx(lb, nsnull, aPresContext);
PRInt32 numSpaces; PRInt32 numSpaces;
#ifdef IBMBIDI
// Simulate a non-Bidi system for char by char painting
PRBool isBidiSystem = PR_FALSE;
aPresContext->GetIsBidiSystem(isBidiSystem);
aPresContext->SetIsBidiSystem(PR_FALSE);
#endif
numSpaces = PrepareUnicodeText(tx, (displaySelection ? &indexBuffer : nsnull), numSpaces = PrepareUnicodeText(tx, (displaySelection ? &indexBuffer : nsnull),
&paintBuffer, &textLength); &paintBuffer, &textLength, PR_TRUE);
#ifdef IBMBIDI
aPresContext->SetIsBidiSystem(isBidiSystem);
#endif
PRInt32* ip = indexBuffer.mBuffer; PRInt32* ip = indexBuffer.mBuffer;
PRUnichar* text = paintBuffer.mBuffer; PRUnichar* text = paintBuffer.mBuffer;
@ -5341,31 +5325,24 @@ nsTextFrame::Reflow(nsIPresContext* aPresContext,
nsLineLayout& lineLayout = *aReflowState.mLineLayout; nsLineLayout& lineLayout = *aReflowState.mLineLayout;
TextStyle ts(aPresContext, *aReflowState.rendContext, mStyleContext); TextStyle ts(aPresContext, *aReflowState.rendContext, mStyleContext);
#ifdef IBMBIDI
if ( (mContentLength > 0) && (mState & NS_FRAME_IS_BIDI) ) { if ( (mContentLength > 0) && (mState & NS_FRAME_IS_BIDI) ) {
startingOffset = mContentOffset; startingOffset = mContentOffset;
} }
if (ts.mSmallCaps || (0 != ts.mWordSpacing) || (0 != ts.mLetterSpacing)
|| ts.mJustifying) { PRBool bidiEnabled;
// simulate a non-Bidi system for char-by-char measuring and aPresContext->GetBidiEnabled(&bidiEnabled);
// rendering if (bidiEnabled) {
aPresContext->SetIsBidiSystem(PR_FALSE); nsCharType charType = eCharType_LeftToRight;
} PRUint32 hints = 0;
else { aReflowState.rendContext->GetHints(hints);
PRBool bidiEnabled; GetBidiProperty(aPresContext, nsLayoutAtoms::charType, (void**)&charType, sizeof(charType));
aPresContext->GetBidiEnabled(&bidiEnabled); if ((eCharType_RightToLeftArabic == charType &&
if (bidiEnabled) { (hints & NS_RENDERING_HINT_ARABIC_SHAPING) == NS_RENDERING_HINT_ARABIC_SHAPING) ||
nsCharType charType = eCharType_LeftToRight; (eCharType_RightToLeft == charType &&
PRUint32 hints = 0; (hints & NS_RENDERING_HINT_BIDI_REORDERING) == NS_RENDERING_HINT_BIDI_REORDERING)) {
aReflowState.rendContext->GetHints(hints); aPresContext->SetIsBidiSystem(PR_TRUE);
GetBidiProperty(aPresContext, nsLayoutAtoms::charType, (void**)&charType, sizeof(charType));
PRBool isBidiSystem = (eCharType_RightToLeftArabic == charType) ?
(hints & NS_RENDERING_HINT_ARABIC_SHAPING) :
(hints & NS_RENDERING_HINT_BIDI_REORDERING);
aPresContext->SetIsBidiSystem(isBidiSystem);
} }
} }
#endif //IBMBIDI
// Clear out the reflow state flags in mState (without destroying // Clear out the reflow state flags in mState (without destroying
// the TEXT_BLINK_ON bit). // the TEXT_BLINK_ON bit).
@ -5406,11 +5383,15 @@ nsTextFrame::Reflow(nsIPresContext* aPresContext,
} }
nsCOMPtr<nsILineBreaker> lb; nsCOMPtr<nsILineBreaker> lb;
doc->GetLineBreaker(getter_AddRefs(lb)); doc->GetLineBreaker(getter_AddRefs(lb));
PRBool forceArabicShaping = (ts.mSmallCaps ||
(0 != ts.mWordSpacing) ||
(0 != ts.mLetterSpacing) ||
ts.mJustifying);
nsTextTransformer tx(lb, nsnull, aPresContext); nsTextTransformer tx(lb, nsnull, aPresContext);
// Keep the text in ascii if possible. Note that if we're measuring small // Keep the text in ascii if possible. Note that if we're measuring small
// caps text then transform to Unicode because the helper function only // caps text then transform to Unicode because the helper function only
// accepts Unicode text // accepts Unicode text
nsresult rv = tx.Init(this, mContent, startingOffset, !ts.mSmallCaps); nsresult rv = tx.Init(this, mContent, startingOffset, forceArabicShaping, !ts.mSmallCaps);
if (NS_OK != rv) { if (NS_OK != rv) {
return rv; return rv;
} }
@ -5536,7 +5517,7 @@ nsTextFrame::Reflow(nsIPresContext* aPresContext,
// there because of the need to repair counts when wrapped words are backed out. // 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, // So I do it via PrepareUnicodeText ... a little slower perhaps, but a lot saner,
// and it localizes the counting logic to one place. // and it localizes the counting logic to one place.
numSpaces = PrepareUnicodeText(tx, nsnull, nsnull, &textLength); numSpaces = PrepareUnicodeText(tx, nsnull, nsnull, &textLength, PR_TRUE);
lineLayout.SetTextJustificationWeights(numSpaces, textLength - numSpaces); lineLayout.SetTextJustificationWeights(numSpaces, textLength - numSpaces);
} }

View File

@ -203,23 +203,42 @@ nsresult
nsTextTransformer::Init(nsIFrame* aFrame, nsTextTransformer::Init(nsIFrame* aFrame,
nsIContent* aContent, nsIContent* aContent,
PRInt32 aStartingOffset, PRInt32 aStartingOffset,
PRBool aForceArabicShaping,
PRBool aLeaveAsAscii) PRBool aLeaveAsAscii)
{ {
#ifdef IBMBIDI /*
* If the document has Bidi content, check whether we need to do
* Arabic shaping.
*
* Does the frame contains Arabic characters
* (mCharType == eCharType_RightToLeftArabic)?
* Are we rendering character by character (aForceArabicShaping ==
* PR_TRUE)? If so, we always do our own Arabic shaping, even if
* the platform has native shaping support. Otherwise, we only do
* shaping if the platform has no shaping support.
*
* We do numeric shaping in all Bidi documents.
*/
PRBool bidiEnabled; PRBool bidiEnabled;
mPresContext->GetBidiEnabled(&bidiEnabled); mPresContext->GetBidiEnabled(&bidiEnabled);
if (bidiEnabled) { if (bidiEnabled) {
PRBool isBidiSystem;
aFrame->GetBidiProperty(mPresContext, nsLayoutAtoms::charType, aFrame->GetBidiProperty(mPresContext, nsLayoutAtoms::charType,
(void**)&mCharType, sizeof(mCharType)); (void**)&mCharType, sizeof(mCharType));
mPresContext->GetIsBidiSystem(isBidiSystem); if (mCharType == eCharType_RightToLeftArabic) {
if (mCharType == eCharType_RightToLeftArabic && !isBidiSystem) { if (aForceArabicShaping) {
SetNeedsArabicShaping(PR_TRUE); SetNeedsArabicShaping(PR_TRUE);
}
else {
PRBool isBidiSystem;
mPresContext->GetIsBidiSystem(isBidiSystem);
if (!isBidiSystem) {
SetNeedsArabicShaping(PR_TRUE);
}
}
} }
SetNeedsNumericShaping(PR_TRUE); SetNeedsNumericShaping(PR_TRUE);
} }
#endif
// Get the contents text content // Get the contents text content
nsresult rv; nsresult rv;

View File

@ -162,6 +162,7 @@ public:
nsresult Init(nsIFrame* aFrame, nsresult Init(nsIFrame* aFrame,
nsIContent* aContent, nsIContent* aContent,
PRInt32 aStartingOffset, PRInt32 aStartingOffset,
PRBool aForceArabicShaping = PR_FALSE,
PRBool aLeaveAsAscii = PR_FALSE); PRBool aLeaveAsAscii = PR_FALSE);
PRInt32 GetContentLength() const { PRInt32 GetContentLength() const {