From ad766a1fcb5b351b2607dd0935af38647a64cf6d Mon Sep 17 00:00:00 2001 From: Simon Montagu Date: Thu, 20 Nov 2014 12:45:22 +0200 Subject: [PATCH] Bug 1100071 patch 2: add macros for common tests whether bidi level is odd and whether two bidi levels have the same parity, r=dholbert --- dom/canvas/CanvasRenderingContext2D.cpp | 2 +- intl/unicharutil/util/nsBidiUtils.h | 19 +++++++++++ layout/base/nsBidiPresUtils.cpp | 45 +++++++++++++------------ layout/base/nsBidiPresUtils.h | 12 +++---- layout/base/nsCaret.cpp | 34 ++++++++++--------- layout/generic/WritingModes.h | 7 ++-- layout/generic/nsFrame.cpp | 24 +++++++------ layout/generic/nsFrameList.cpp | 6 ++-- layout/generic/nsSelection.cpp | 12 +++---- layout/generic/nsTextFrame.cpp | 2 +- 10 files changed, 95 insertions(+), 68 deletions(-) diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp index 3f0b2113ab75..4165fac89869 100644 --- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -3253,7 +3253,7 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor : public nsBidiPresUtils::BidiProcess mFontgrp->UpdateUserFonts(); // ensure user font generation is current // adjust flags for current direction run uint32_t flags = mTextRunFlags; - if (direction & 1) { + if (direction == NSBIDI_RTL) { flags |= gfxTextRunFactory::TEXT_IS_RTL; } else { flags &= ~gfxTextRunFactory::TEXT_IS_RTL; diff --git a/intl/unicharutil/util/nsBidiUtils.h b/intl/unicharutil/util/nsBidiUtils.h index a220bb9af0d7..6e2f5c4d4191 100644 --- a/intl/unicharutil/util/nsBidiUtils.h +++ b/intl/unicharutil/util/nsBidiUtils.h @@ -45,6 +45,25 @@ enum nsCharType { */ typedef enum nsCharType nsCharType; +/** + * Find the direction of an embedding level or paragraph level set by + * the Unicode Bidi Algorithm. (Even levels are left-to-right, odd + * levels right-to-left. + */ +#define IS_LEVEL_RTL(level) (((level) & 1) == 1) + +/** + * Check whether two bidi levels have the same parity and thus the same + * directionality + */ +#define IS_SAME_DIRECTION(level1, level2) (((level1 ^ level2) & 1) == 0) + +/** + * Convert from nsBidiLevel to nsBidiDirection + */ +#define DIRECTION_FROM_LEVEL(level) ((IS_LEVEL_RTL(level)) \ + ? NSBIDI_RTL : NSBIDI_LTR) + /** * definitions of bidirection character types by category */ diff --git a/layout/base/nsBidiPresUtils.cpp b/layout/base/nsBidiPresUtils.cpp index bc4ef7b123b2..1207b0138c63 100644 --- a/layout/base/nsBidiPresUtils.cpp +++ b/layout/base/nsBidiPresUtils.cpp @@ -361,7 +361,7 @@ struct BidiLineData { nsBidiLevel level = nsBidiPresUtils::GetFrameEmbeddingLevel(frame); mLevels.AppendElement(level); mIndexMap.AppendElement(0); - if (level & 1) { + if (IS_LEVEL_RTL(level)) { hasRTLFrames = true; } } @@ -1539,7 +1539,7 @@ nsBidiPresUtils::RepositionInlineFrames(BidiLineData *aBld, for (; index != limit; index += step) { frame = aBld->VisualFrameAt(index); RepositionFrame(frame, - !(aBld->mLevels[aBld->mIndexMap[index]] & 1), + !(IS_LEVEL_RTL(aBld->mLevels[aBld->mIndexMap[index]])), start, &continuationStates, aLineWM, @@ -1675,9 +1675,9 @@ nsBidiPresUtils::RemoveBidiContinuation(BidiParagraphData *aBpd, nsresult nsBidiPresUtils::FormatUnicodeText(nsPresContext* aPresContext, char16_t* aText, - int32_t& aTextLength, - nsCharType aCharType, - bool aIsOddLevel) + int32_t& aTextLength, + nsCharType aCharType, + nsBidiDirection aDir) { nsresult rv = NS_OK; // ahmed @@ -1877,8 +1877,7 @@ nsresult nsBidiPresUtils::ProcessText(const char16_t* aText, uint32_t visualStart = 0; uint8_t charType; uint8_t prevType = eCharType_LeftToRight; - nsBidiLevel level; - + for(int nPosResolve=0; nPosResolve < aPosResolveCount; ++nPosResolve) { aPosResolve[nPosResolve].visualIndex = kNotFound; @@ -1892,10 +1891,12 @@ nsresult nsBidiPresUtils::ProcessText(const char16_t* aText, if (NS_FAILED(rv)) return rv; + nsBidiLevel level; rv = aBidiEngine->GetLogicalRun(start, &limit, &level); if (NS_FAILED(rv)) return rv; + dir = DIRECTION_FROM_LEVEL(level); int32_t subRunLength = limit - start; int32_t lineOffset = start; int32_t typeLimit = std::min(limit, aLength); @@ -1914,8 +1915,8 @@ nsresult nsBidiPresUtils::ProcessText(const char16_t* aText, * x-coordinate of the end of the run for the start of the next run. */ - if (level & 1) { - aprocessor.SetText(aText + start, subRunLength, nsBidiDirection(level & 1)); + if (dir == NSBIDI_RTL) { + aprocessor.SetText(aText + start, subRunLength, dir); width = aprocessor.GetWidth(); xOffset += width; xEndRun = xOffset; @@ -1925,18 +1926,18 @@ nsresult nsBidiPresUtils::ProcessText(const char16_t* aText, // CalculateCharType can increment subRunCount if the run // contains mixed character types CalculateCharType(aBidiEngine, aText, lineOffset, typeLimit, subRunLimit, subRunLength, subRunCount, charType, prevType); - + nsAutoString runVisualText; runVisualText.Assign(aText + start, subRunLength); if (int32_t(runVisualText.Length()) < subRunLength) return NS_ERROR_OUT_OF_MEMORY; - FormatUnicodeText(aPresContext, runVisualText.BeginWriting(), subRunLength, - (nsCharType)charType, level & 1); + FormatUnicodeText(aPresContext, runVisualText.BeginWriting(), + subRunLength, (nsCharType)charType, dir); - aprocessor.SetText(runVisualText.get(), subRunLength, nsBidiDirection(level & 1)); + aprocessor.SetText(runVisualText.get(), subRunLength, dir); width = aprocessor.GetWidth(); totalWidth += width; - if (level & 1) { + if (dir == NSBIDI_RTL) { xOffset -= width; } if (aMode == MODE_DRAW) { @@ -2007,7 +2008,7 @@ nsresult nsBidiPresUtils::ProcessText(const char16_t* aText, // The position in the text where this run's "left part" begins. const char16_t* visualLeftPart; const char16_t* visualRightSide; - if (level & 1) { + if (dir == NSBIDI_RTL) { // One day, son, this could all be replaced with mBidiEngine.GetVisualIndex ... posResolve->visualIndex = visualStart + (subRunLength - (posResolve->logicalIndex + 1 - start)); // Skipping to the "left part". @@ -2024,16 +2025,16 @@ nsresult nsBidiPresUtils::ProcessText(const char16_t* aText, } // The delta between the start of the run and the left part's end. int32_t visualLeftLength = posResolve->visualIndex - visualStart; - aprocessor.SetText(visualLeftPart, visualLeftLength, nsBidiDirection(level & 1)); + aprocessor.SetText(visualLeftPart, visualLeftLength, dir); subWidth = aprocessor.GetWidth(); - aprocessor.SetText(visualRightSide, visualLeftLength + 1, nsBidiDirection(level & 1)); + aprocessor.SetText(visualRightSide, visualLeftLength + 1, dir); posResolve->visualLeftTwips = xOffset + subWidth; posResolve->visualWidth = aprocessor.GetWidth() - subWidth; } } } - if (!(level & 1)) { + if (dir == NSBIDI_LTR) { xOffset += width; } @@ -2042,10 +2043,10 @@ nsresult nsBidiPresUtils::ProcessText(const char16_t* aText, subRunLimit = typeLimit; subRunLength = typeLimit - lineOffset; } // while - if (level & 1) { + if (dir == NSBIDI_RTL) { xOffset = xEndRun; } - + visualStart += length; } // for @@ -2075,8 +2076,8 @@ public: } virtual void SetText(const char16_t* aText, - int32_t aLength, - nsBidiDirection aDirection) MOZ_OVERRIDE + int32_t aLength, + nsBidiDirection aDirection) MOZ_OVERRIDE { mFontMetrics->SetTextRunRTL(aDirection==NSBIDI_RTL); mText = aText; diff --git a/layout/base/nsBidiPresUtils.h b/layout/base/nsBidiPresUtils.h index e866daea8482..43f3e277dde1 100644 --- a/layout/base/nsBidiPresUtils.h +++ b/layout/base/nsBidiPresUtils.h @@ -107,15 +107,15 @@ public: * @remark The reason that the function gives a string instead of an index * is that ProcessText copies and modifies the string passed to it, so * passing an index would be impossible. - * + * * @param aText The string of text. * @param aLength The length of the string of text. * @param aDirection The direction of the text. The string will never have * mixed direction. */ virtual void SetText(const char16_t* aText, - int32_t aLength, - nsBidiDirection aDirection) = 0; + int32_t aLength, + nsBidiDirection aDirection) = 0; /** * Returns the measured width of the text given in SetText. If SetText was @@ -171,11 +171,11 @@ public: * * @lina 06/18/2000 */ - static nsresult FormatUnicodeText(nsPresContext* aPresContext, - char16_t* aText, + static nsresult FormatUnicodeText(nsPresContext* aPresContext, + char16_t* aText, int32_t& aTextLength, nsCharType aCharType, - bool aIsOddLevel); + nsBidiDirection aDir); /** * Reorder plain text using the Unicode Bidi algorithm and send it to diff --git a/layout/base/nsCaret.cpp b/layout/base/nsCaret.cpp index c5a023305e74..5d2d30609ef0 100644 --- a/layout/base/nsCaret.cpp +++ b/layout/base/nsCaret.cpp @@ -678,8 +678,10 @@ nsCaret::GetCaretFrameForNodeOffset(nsFrameSelection* aFrameSelection, aBidiLevel = std::max(aBidiLevel, std::min(levelBefore, levelAfter)); // rule c3 aBidiLevel = std::min(aBidiLevel, std::max(levelBefore, levelAfter)); // rule c4 if (aBidiLevel == levelBefore // rule c1 - || (aBidiLevel > levelBefore && aBidiLevel < levelAfter && !((aBidiLevel ^ levelBefore) & 1)) // rule c5 - || (aBidiLevel < levelBefore && aBidiLevel > levelAfter && !((aBidiLevel ^ levelBefore) & 1))) // rule c9 + || (aBidiLevel > levelBefore && aBidiLevel < levelAfter && + IS_SAME_DIRECTION(aBidiLevel, levelBefore)) // rule c5 + || (aBidiLevel < levelBefore && aBidiLevel > levelAfter && + IS_SAME_DIRECTION(aBidiLevel, levelBefore))) // rule c9 { if (theFrame != frameBefore) { @@ -708,8 +710,10 @@ nsCaret::GetCaretFrameForNodeOffset(nsFrameSelection* aFrameSelection, } } else if (aBidiLevel == levelAfter // rule c2 - || (aBidiLevel > levelBefore && aBidiLevel < levelAfter && !((aBidiLevel ^ levelAfter) & 1)) // rule c6 - || (aBidiLevel < levelBefore && aBidiLevel > levelAfter && !((aBidiLevel ^ levelAfter) & 1))) // rule c10 + || (aBidiLevel > levelBefore && aBidiLevel < levelAfter && + IS_SAME_DIRECTION(aBidiLevel, levelAfter)) // rule c6 + || (aBidiLevel < levelBefore && aBidiLevel > levelAfter && + IS_SAME_DIRECTION(aBidiLevel, levelAfter))) // rule c10 { if (theFrame != frameAfter) { @@ -739,33 +743,33 @@ nsCaret::GetCaretFrameForNodeOffset(nsFrameSelection* aFrameSelection, } } else if (aBidiLevel > levelBefore && aBidiLevel < levelAfter // rule c7/8 - && !((levelBefore ^ levelAfter) & 1) // before and after have the same parity - && ((aBidiLevel ^ levelAfter) & 1)) // caret has different parity + && IS_SAME_DIRECTION(levelBefore, levelAfter) // before and after have the same parity + && !IS_SAME_DIRECTION(aBidiLevel, levelAfter)) // caret has different parity { if (NS_SUCCEEDED(aFrameSelection->GetFrameFromLevel(frameAfter, eDirNext, aBidiLevel, &theFrame))) { theFrame->GetOffsets(start, end); levelAfter = NS_GET_EMBEDDING_LEVEL(theFrame); - if (aBidiLevel & 1) // c8: caret to the right of the rightmost character - theFrameOffset = (levelAfter & 1) ? start : end; + if (IS_LEVEL_RTL(aBidiLevel)) // c8: caret to the right of the rightmost character + theFrameOffset = IS_LEVEL_RTL(levelAfter) ? start : end; else // c7: caret to the left of the leftmost character - theFrameOffset = (levelAfter & 1) ? end : start; + theFrameOffset = IS_LEVEL_RTL(levelAfter) ? end : start; } } else if (aBidiLevel < levelBefore && aBidiLevel > levelAfter // rule c11/12 - && !((levelBefore ^ levelAfter) & 1) // before and after have the same parity - && ((aBidiLevel ^ levelAfter) & 1)) // caret has different parity + && IS_SAME_DIRECTION(levelBefore, levelAfter) // before and after have the same parity + && !IS_SAME_DIRECTION(aBidiLevel, levelAfter)) // caret has different parity { if (NS_SUCCEEDED(aFrameSelection->GetFrameFromLevel(frameBefore, eDirPrevious, aBidiLevel, &theFrame))) { theFrame->GetOffsets(start, end); levelBefore = NS_GET_EMBEDDING_LEVEL(theFrame); - if (aBidiLevel & 1) // c12: caret to the left of the leftmost character - theFrameOffset = (levelBefore & 1) ? end : start; + if (IS_LEVEL_RTL(aBidiLevel)) // c12: caret to the left of the leftmost character + theFrameOffset = IS_LEVEL_RTL(levelBefore) ? end : start; else // c11: caret to the right of the rightmost character - theFrameOffset = (levelBefore & 1) ? start : end; + theFrameOffset = IS_LEVEL_RTL(levelBefore) ? start : end; } - } + } } } } diff --git a/layout/generic/WritingModes.h b/layout/generic/WritingModes.h index d9c3f331070a..5ba139012a44 100644 --- a/layout/generic/WritingModes.h +++ b/layout/generic/WritingModes.h @@ -8,6 +8,7 @@ #include "nsRect.h" #include "nsStyleContext.h" +#include "nsBidiUtils.h" // If WRITING_MODE_VERTICAL_ENABLED is defined, we will attempt to support // the vertical writing-mode values; if it is not defined, then @@ -309,11 +310,11 @@ public: //XXX change uint8_t to UBiDiLevel after bug 924851 void SetDirectionFromBidiLevel(uint8_t level) { - if (level & 1) { - // odd level, set RTL + if (IS_LEVEL_RTL(level)) { + // set RTL mWritingMode |= eBidiMask; } else { - // even level, set LTR + // set LTR mWritingMode &= ~eBidiMask; } } diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 9728205e42df..eb304ecc3b9c 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -130,6 +130,11 @@ struct nsContentAndOffset #define FORCE_SELECTION_UPDATE 1 #define CALC_DEBUG 0 +// This is faster than nsBidiPresUtils::IsFrameInParagraphDirection, +// because it uses the frame pointer passed in without drilling down to +// the leaf frame. +#define REVERSED_DIRECTION_FRAME(frame) \ + (!IS_SAME_DIRECTION(NS_GET_EMBEDDING_LEVEL(frame), NS_GET_BASE_LEVEL(frame))) #include "nsILineIterator.h" @@ -5910,7 +5915,7 @@ nsFrame::GetPointFromOffset(int32_t inOffset, nsPoint* outPoint) NS_PTR_TO_INT32(Properties().Get(nsIFrame::EmbeddingLevelProperty(), &hasEmbeddingLevel)); bool isRTL = hasEmbeddingLevel - ? (embeddingLevel & 1) == 1 + ? IS_LEVEL_RTL(embeddingLevel) : StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL; if ((!isRTL && inOffset > newOffset) || (isRTL && inOffset <= newOffset)) { @@ -6354,8 +6359,7 @@ nsIFrame::PeekOffsetParagraph(nsPeekOffsetStruct *aPos) // Determine movement direction relative to frame static bool IsMovingInFrameDirection(nsIFrame* frame, nsDirection aDirection, bool aVisual) { - bool isReverseDirection = aVisual ? - (NS_GET_EMBEDDING_LEVEL(frame) & 1) != (NS_GET_BASE_LEVEL(frame) & 1) : false; + bool isReverseDirection = aVisual && REVERSED_DIRECTION_FRAME(frame); return aDirection == (isReverseDirection ? eDirPrevious : eDirNext); } @@ -6652,7 +6656,7 @@ nsIFrame::PeekOffset(nsPeekOffsetStruct* aPos) nsBidiLevel embeddingLevel = nsBidiPresUtils::GetFrameEmbeddingLevel(baseFrame); // If the direction of the frame on the edge is opposite to that of the line, // we'll need to drill down to its opposite end, so reverse endOfLine. - if ((embeddingLevel & 1) == !lineIsRTL) + if (IS_LEVEL_RTL(embeddingLevel) == !lineIsRTL) endOfLine = !endOfLine; } } else { @@ -6875,8 +6879,8 @@ nsIFrame::GetFrameFromDirection(nsDirection aDirection, bool aVisual, nsIFrame** framePtr = aDirection == eDirPrevious ? &firstFrame : &lastFrame; if (*framePtr) { nsBidiLevel embeddingLevel = nsBidiPresUtils::GetFrameEmbeddingLevel(*framePtr); - if ((((embeddingLevel & 1) && lineIsRTL) || (!(embeddingLevel & 1) && !lineIsRTL)) == - (aDirection == eDirPrevious)) { + bool frameIsRTL = IS_LEVEL_RTL(embeddingLevel); + if ((frameIsRTL == lineIsRTL) == (aDirection == eDirPrevious)) { nsFrame::GetFirstLeaf(presContext, framePtr); } else { nsFrame::GetLastLeaf(presContext, framePtr); @@ -6945,11 +6949,9 @@ nsIFrame::GetFrameFromDirection(nsDirection aDirection, bool aVisual, *aOutOffset = (aDirection == eDirNext) ? 0 : -1; - if (aVisual) { - uint8_t newLevel = NS_GET_EMBEDDING_LEVEL(traversedFrame); - uint8_t newBaseLevel = NS_GET_BASE_LEVEL(traversedFrame); - if ((newLevel & 1) != (newBaseLevel & 1)) // The new frame is reverse-direction, go to the other end - *aOutOffset = -1 - *aOutOffset; + if (aVisual && REVERSED_DIRECTION_FRAME(traversedFrame)) { + // The new frame is reverse-direction, go to the other end + *aOutOffset = -1 - *aOutOffset; } *aOutFrame = traversedFrame; return NS_OK; diff --git a/layout/generic/nsFrameList.cpp b/layout/generic/nsFrameList.cpp index a38ccecb6caf..ace8493a0aa1 100644 --- a/layout/generic/nsFrameList.cpp +++ b/layout/generic/nsFrameList.cpp @@ -367,11 +367,11 @@ nsFrameList::GetPrevVisualFor(nsIFrame* aFrame) const } else { // Just get the next or prev sibling, depending on block and frame direction. nsBidiLevel frameEmbeddingLevel = nsBidiPresUtils::GetFrameEmbeddingLevel(mFirstChild); - if ((frameEmbeddingLevel & 1) == (baseLevel & 1)) { + if (IS_SAME_DIRECTION(frameEmbeddingLevel, baseLevel)) { return aFrame ? aFrame->GetPrevSibling() : LastChild(); } else { return aFrame ? aFrame->GetNextSibling() : mFirstChild; - } + } } } @@ -441,7 +441,7 @@ nsFrameList::GetNextVisualFor(nsIFrame* aFrame) const } else { // Just get the next or prev sibling, depending on block and frame direction. nsBidiLevel frameEmbeddingLevel = nsBidiPresUtils::GetFrameEmbeddingLevel(mFirstChild); - if ((frameEmbeddingLevel & 1) == (baseLevel & 1)) { + if (IS_SAME_DIRECTION(frameEmbeddingLevel, baseLevel)) { return aFrame ? aFrame->GetNextSibling() : mFirstChild; } else { return aFrame ? aFrame->GetPrevSibling() : LastChild(); diff --git a/layout/generic/nsSelection.cpp b/layout/generic/nsSelection.cpp index 7ad6e3f2d100..911e54814adb 100644 --- a/layout/generic/nsSelection.cpp +++ b/layout/generic/nsSelection.cpp @@ -876,11 +876,11 @@ nsFrameSelection::MoveCaret(uint32_t aKeycode, switch (aKeycode){ case nsIDOMKeyEvent::DOM_VK_RIGHT : InvalidateDesiredX(); - pos.mDirection = (baseLevel & 1) ? eDirPrevious : eDirNext; + pos.mDirection = IS_LEVEL_RTL(baseLevel) ? eDirPrevious : eDirNext; break; case nsIDOMKeyEvent::DOM_VK_LEFT : InvalidateDesiredX(); - pos.mDirection = (baseLevel & 1) ? eDirNext : eDirPrevious; + pos.mDirection = IS_LEVEL_RTL(baseLevel) ? eDirNext : eDirPrevious; break; case nsIDOMKeyEvent::DOM_VK_DELETE : InvalidateDesiredX(); @@ -5833,7 +5833,7 @@ Selection::Modify(const nsAString& aAlter, const nsAString& aDirection, if (NS_SUCCEEDED(rv) && frame) { nsBidiLevel baseLevel = nsBidiPresUtils::GetFrameBaseLevel(frame); - if (baseLevel & 1) { + if (IS_LEVEL_RTL(baseLevel)) { if (!visual && keycode == nsIDOMKeyEvent::DOM_VK_RIGHT) { keycode = nsIDOMKeyEvent::DOM_VK_LEFT; } @@ -5908,14 +5908,14 @@ Selection::SelectionLanguageChange(bool aLangRTL) levelAfter = levels.mLevelAfter; } - if ((levelBefore & 1) == (levelAfter & 1)) { + if (IS_SAME_DIRECTION(levelBefore, levelAfter)) { // if cursor is between two characters with the same orientation, changing the keyboard language // must toggle the cursor level between the level of the character with the lowest level // (if the new language corresponds to the orientation of that character) and this level plus 1 // (if the new language corresponds to the opposite orientation) if ((level != levelBefore) && (level != levelAfter)) level = std::min(levelBefore, levelAfter); - if ((level & 1) == aLangRTL) + if (IS_LEVEL_RTL(level) == aLangRTL) mFrameSelection->SetCaretBidiLevel(level); else mFrameSelection->SetCaretBidiLevel(level + 1); @@ -5923,7 +5923,7 @@ Selection::SelectionLanguageChange(bool aLangRTL) else { // if cursor is between characters with opposite orientations, changing the keyboard language must change // the cursor level to that of the adjacent character with the orientation corresponding to the new language. - if ((levelBefore & 1) == aLangRTL) + if (IS_LEVEL_RTL(levelBefore) == aLangRTL) mFrameSelection->SetCaretBidiLevel(levelBefore); else mFrameSelection->SetCaretBidiLevel(levelAfter); diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index 96516309db42..521e10bb4a20 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -2059,7 +2059,7 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer) if (textFlags & nsTextFrameUtils::TEXT_HAS_SHY) { textFlags |= gfxTextRunFactory::TEXT_ENABLE_HYPHEN_BREAKS; } - if (mBidiEnabled && (NS_GET_EMBEDDING_LEVEL(firstFrame) & 1)) { + if (mBidiEnabled && (IS_LEVEL_RTL(NS_GET_EMBEDDING_LEVEL(firstFrame)))) { textFlags |= gfxTextRunFactory::TEXT_IS_RTL; } if (mNextRunContextInfo & nsTextFrameUtils::INCOMING_WHITESPACE) {