diff --git a/gfx/public/nsIRenderingContext.h b/gfx/public/nsIRenderingContext.h index ab338d704ce..114d58e6338 100644 --- a/gfx/public/nsIRenderingContext.h +++ b/gfx/public/nsIRenderingContext.h @@ -765,6 +765,15 @@ public: #endif +#ifdef IBMBIDI + /** + * Let the device context know whether we want text reordered with + * right-to-left base direction + */ + NS_IMETHOD SetRightToLeftText(PRBool aIsRTL) = 0; +#endif // IBMBIDI + + #ifdef USE_IMG2 /* [noscript] void drawImage (in imgIContainer aImage, [const] in nsRect aSrcRect, [const] in nsPoint aDestPoint); */ NS_IMETHOD DrawImage(imgIContainer *aImage, const nsRect * aSrcRect, const nsPoint * aDestPoint) = 0; @@ -803,6 +812,18 @@ public: */ #define NS_RENDERING_HINT_REMOTE_RENDERING 0x2 +/** + * This bit, when set, indicates that the system provides support for + * the reordering of bidirectional text + */ +#define NS_RENDERING_HINT_BIDI_REORDERING 0x4 + +/** + * This bit, when set, indicates that the system provides support for + * Arabic shaping + */ +#define NS_RENDERING_HINT_ARABIC_SHAPING 0x8 + //flags for copy CopyOffScreenBits //when performing the blit, use the region, if any, diff --git a/gfx/public/nsRenderingContextImpl.h b/gfx/public/nsRenderingContextImpl.h index 2985e9e13b7..472f78b6576 100644 --- a/gfx/public/nsRenderingContextImpl.h +++ b/gfx/public/nsRenderingContextImpl.h @@ -91,6 +91,14 @@ public: */ NS_IMETHOD FillStdPolygon(const nsPoint aPoints[], PRInt32 aNumPoints) { return NS_OK; } +#ifdef IBMBIDI + /** + * Let the device context know whether we want text reordered with + * right-to-left base direction + */ + NS_IMETHOD SetRightToLeftText(PRBool aIsRTL); +#endif // IBMBIDI + #ifdef USE_IMG2 NS_IMETHOD DrawImage(imgIContainer *aImage, const nsRect * aSrcRect, const nsPoint * aDestPoint); NS_IMETHOD DrawScaledImage(imgIContainer *aImage, const nsRect * aSrcRect, const nsRect * aDestRect); diff --git a/gfx/src/nsRenderingContextImpl.cpp b/gfx/src/nsRenderingContextImpl.cpp index d215730a30a..a269196acca 100644 --- a/gfx/src/nsRenderingContextImpl.cpp +++ b/gfx/src/nsRenderingContextImpl.cpp @@ -427,6 +427,18 @@ PRInt32 flag = NS_COPYBITS_TO_BACK_BUFFER | NS_COPYBITS_XFORM_DEST_VALUES; } } +#ifdef IBMBIDI +/** + * Let the device context know whether we want text reordered with + * right-to-left base direction + */ +NS_IMETHODIMP +nsRenderingContextImpl::SetRightToLeftText(PRBool aIsRTL) +{ + return NS_OK; +} +#endif // IBMBIDI + /** --------------------------------------------------- * See documentation in nsRenderingContextImpl.h * @update 3/29/00 dwc diff --git a/gfx/src/shared/nsRenderingContextImpl.cpp b/gfx/src/shared/nsRenderingContextImpl.cpp index d215730a30a..a269196acca 100644 --- a/gfx/src/shared/nsRenderingContextImpl.cpp +++ b/gfx/src/shared/nsRenderingContextImpl.cpp @@ -427,6 +427,18 @@ PRInt32 flag = NS_COPYBITS_TO_BACK_BUFFER | NS_COPYBITS_XFORM_DEST_VALUES; } } +#ifdef IBMBIDI +/** + * Let the device context know whether we want text reordered with + * right-to-left base direction + */ +NS_IMETHODIMP +nsRenderingContextImpl::SetRightToLeftText(PRBool aIsRTL) +{ + return NS_OK; +} +#endif // IBMBIDI + /** --------------------------------------------------- * See documentation in nsRenderingContextImpl.h * @update 3/29/00 dwc diff --git a/gfx/src/windows/nsRenderingContextWin.cpp b/gfx/src/windows/nsRenderingContextWin.cpp index 3a232590521..37ceae16a8f 100644 --- a/gfx/src/windows/nsRenderingContextWin.cpp +++ b/gfx/src/windows/nsRenderingContextWin.cpp @@ -151,6 +151,11 @@ GraphicsState :: ~GraphicsState() #define NOT_SETUP 0x33 static PRBool gIsWIN95 = NOT_SETUP; +#ifdef IBMBIDI +#define DONT_INIT 0 +static DWORD gBidiInfo = NOT_SETUP; +#endif // IBMBIDI + // A few of the stock objects are needed all the time, so we just get them // once static HFONT gStockSystemFont = (HFONT)::GetStockObject(SYSTEM_FONT); @@ -173,6 +178,24 @@ nsRenderingContextWin :: nsRenderingContextWin() } else { gIsWIN95 = PR_TRUE; + +#ifdef IBMBIDI + if ( (os.dwMajorVersion < 4) + || ( (os.dwMajorVersion == 4) && (os.dwMinorVersion == 0) ) ) { + // Windows 95 or earlier: assume it's not Bidi + gBidiInfo = DONT_INIT; + } + else if (os.dwMajorVersion >= 4) { + // Windows 98 or later + UINT cp = ::GetACP(); + if (1256 == cp) { + gBidiInfo = GCP_REORDER | GCP_GLYPHSHAPE; + } + else if (1255 == cp) { + gBidiInfo = GCP_REORDER; + } + } +#endif // IBMBIDI } } @@ -197,6 +220,9 @@ nsRenderingContextWin :: nsRenderingContextWin() mMainSurface = nsnull; mStateCache = new nsVoidArray(); +#ifdef IBMBIDI + mRightToLeftText = PR_FALSE; +#endif //create an initial GraphicsState @@ -597,6 +623,16 @@ nsRenderingContextWin :: GetHints(PRUint32& aResult) if (gIsWIN95) result |= NS_RENDERING_HINT_FAST_8BIT_TEXT; +#ifdef IBMBIDI + if (NOT_SETUP == gBidiInfo) { + InitBidiInfo(); + } + if (GCP_REORDER == (gBidiInfo & GCP_REORDER) ) + result |= NS_RENDERING_HINT_BIDI_REORDERING; + if (GCP_GLYPHSHAPE == (gBidiInfo & GCP_GLYPHSHAPE) ) + result |= NS_RENDERING_HINT_ARABIC_SHAPING; +#endif // IBMBIDI + aResult = result; return NS_OK; @@ -1501,6 +1537,16 @@ NS_IMETHODIMP nsRenderingContextWin :: GetWidth(PRUnichar ch, nscoord &aWidth, P { PRUnichar buf[1]; buf[0] = ch; +#ifdef IBMBIDI + WORD charType; + ::GetStringTypeW(CT_CTYPE3, &ch, 1, &charType); + if ((charType & C3_DIACRITIC) && !(charType & C3_ALPHA)) { +// aWidth = 0; + GetWidth(buf, 1, aWidth, aFontID); + aWidth *=-1; + return NS_OK; + } +#endif return GetWidth(buf, 1, aWidth, aFontID); } @@ -2149,6 +2195,13 @@ NS_IMETHODIMP nsRenderingContextWin :: DrawString(const PRUnichar *aString, PRUi PRUint32 start = 0; for (PRUint32 i = 0; i < aLength; i++) { PRUnichar c = pstr[i]; + +#ifdef IBMBIDI + if (mRightToLeftText) { + c = pstr[aLength - i - 1]; + } +#endif // IBMBIDI + nsFontWin* currFont = nsnull; nsFontWin** font = metrics->mLoadedFonts; nsFontWin** end = &metrics->mLoadedFonts[metrics->mLoadedFontsCount]; @@ -2187,6 +2240,13 @@ FoundFont: } } else { +#ifdef IBMBIDI + if (mRightToLeftText) { + prevFont->DrawString(mDC, x, y, &pstr[aLength - i], i - start); + x += prevFont->GetWidth(mDC, &pstr[aLength - i], i - start); + } + else +#endif // IBMBIDI { prevFont->DrawString(mDC, x, y, &pstr[start], i - start); x += prevFont->GetWidth(mDC, &pstr[start], i - start); @@ -2227,6 +2287,12 @@ FoundFont: } } else { +#ifdef IBMBIDI + if (mRightToLeftText) { + prevFont->DrawString(mDC, x, y, &pstr[aLength - i], i - start); + } + else +#endif // IBMBIDI { prevFont->DrawString(mDC, x, y, &pstr[start], i - start); } @@ -3461,5 +3527,84 @@ nsRenderingContextWin::ConditionRect(nsRect& aSrcRect, RECT& aDestRect) : (aSrcRect.x+aSrcRect.width); } +#ifdef IBMBIDI +/** + * Let the device context know whether we want text reordered with + * right-to-left base direction. The Windows implementation does this + * by setting the fuOptions parameter to ETO_RTLREADING in calls to + * ExtTextOut() + */ +NS_IMETHODIMP +nsRenderingContextWin::SetRightToLeftText(PRBool aIsRTL) +{ + // Only call SetTextAlign if the new value is different from the + // current value + if (aIsRTL != mRightToLeftText) { + UINT flags = ::GetTextAlign(mDC); + if (aIsRTL) { + flags |= TA_RTLREADING; + } + else { + flags &= (~TA_RTLREADING); + } + ::SetTextAlign(mDC, flags); + } + + mRightToLeftText = aIsRTL; + return NS_OK; +} + +/** + * Init gBidiInfo with reordering and shaping + * capabilities of the system + */ +void +nsRenderingContextWin::InitBidiInfo() +{ + if (NOT_SETUP == gBidiInfo) { + gBidiInfo = DONT_INIT; + + const PRUnichar araAin = 0x0639; + const PRUnichar one = 0x0031; + + int distanceArray[2]; + PRUnichar glyphArray[2]; + PRUnichar outStr[] = {0, 0}; + + GCP_RESULTSW gcpResult; + gcpResult.lStructSize = sizeof(GCP_RESULTS); + gcpResult.lpOutString = outStr; // Output string + gcpResult.lpOrder = nsnull; // Ordering indices + gcpResult.lpDx = distanceArray; // Distances between character cells + gcpResult.lpCaretPos = nsnull; // Caret positions + gcpResult.lpClass = nsnull; // Character classifications + gcpResult.lpGlyphs = glyphArray; // Character glyphs + gcpResult.nGlyphs = 2; // Array size + + PRUnichar inStr[] = {araAin, one}; + + if (::GetCharacterPlacementW(mDC, inStr, 2, 0, &gcpResult, GCP_REORDER) + && (inStr[0] == outStr[1]) ) { + gBidiInfo = GCP_REORDER | GCP_GLYPHSHAPE; +#ifdef NS_DEBUG + printf("System has shaping\n"); +#endif + } + else { + const PRUnichar hebAlef = 0x05D0; + inStr[0] = hebAlef; + inStr[1] = one; + if (::GetCharacterPlacementW(mDC, inStr, 2, 0, &gcpResult, GCP_REORDER) + && (inStr[0] == outStr[1]) ) { + gBidiInfo = GCP_REORDER; +#ifdef NS_DEBUG + printf("System has Bidi\n"); +#endif + } + } + } +} +#endif // IBMBIDI + diff --git a/gfx/src/windows/nsRenderingContextWin.h b/gfx/src/windows/nsRenderingContextWin.h index 36a555fc1ac..c25197c7c32 100644 --- a/gfx/src/windows/nsRenderingContextWin.h +++ b/gfx/src/windows/nsRenderingContextWin.h @@ -199,6 +199,10 @@ public: PRInt32* aFontID); #endif +#ifdef IBMBIDI + NS_IMETHOD SetRightToLeftText(PRBool aIsRTL); +#endif // IBMBIDI + protected: void SetupFontAndColor(void); @@ -224,6 +228,9 @@ private: HPEN SetupDashedPen(void); HPEN SetupDottedPen(void); void PushClipState(void); +#ifdef IBMBIDI + void InitBidiInfo(void); +#endif // IBMBIDI protected: nscolor mCurrentColor; @@ -260,6 +267,9 @@ protected: #ifdef NS_DEBUG PRBool mInitialized; #endif +#ifdef IBMBIDI + PRBool mRightToLeftText; +#endif // IBMBIDI };