From ee2694c97df376d65bfc24e59f07872d93e9d50c Mon Sep 17 00:00:00 2001 From: Greg Tatum Date: Wed, 20 Oct 2021 14:01:21 +0000 Subject: [PATCH] Bug 1719546 - Replace nsBidi with mozilla::intl::Bidi; r=platform-i18n-reviewers,dminor Differential Revision: https://phabricator.services.mozilla.com/D128793 --- dom/base/Selection.cpp | 41 +++++--- dom/canvas/CanvasRenderingContext2D.cpp | 13 ++- dom/canvas/CanvasRenderingContext2D.h | 5 +- editor/libeditor/EditorBase.cpp | 42 ++++---- editor/libeditor/EditorBase.h | 4 +- intl/unicharutil/util/nsBidiUtils.h | 19 ---- layout/base/nsBidiPresUtils.cpp | 134 ++++++++++++++---------- layout/base/nsBidiPresUtils.h | 112 +++++++++----------- layout/base/nsCaret.cpp | 61 ++++++----- layout/base/nsCaret.h | 4 +- layout/base/nsLayoutUtils.cpp | 12 ++- layout/base/nsPresContext.cpp | 5 +- layout/base/nsPresContext.h | 6 +- layout/generic/WritingModes.h | 5 +- layout/generic/nsFrameList.cpp | 19 ++-- layout/generic/nsFrameSelection.cpp | 35 ++++--- layout/generic/nsFrameSelection.h | 22 ++-- layout/generic/nsGfxScrollFrame.cpp | 4 +- layout/generic/nsIFrame.cpp | 14 ++- layout/generic/nsIFrame.h | 88 +++------------- layout/generic/nsImageFrame.cpp | 13 +-- layout/generic/nsTextFrame.cpp | 5 +- layout/xul/nsTextBoxFrame.cpp | 4 +- 23 files changed, 329 insertions(+), 338 deletions(-) diff --git a/dom/base/Selection.cpp b/dom/base/Selection.cpp index 271488305146..98abf607d0c0 100644 --- a/dom/base/Selection.cpp +++ b/dom/base/Selection.cpp @@ -9,6 +9,7 @@ */ #include "mozilla/dom/Selection.h" +#include "mozilla/intl/Bidi.h" #include "mozilla/AccessibleCaretEventHub.h" #include "mozilla/AsyncEventDispatcher.h" @@ -385,7 +386,9 @@ Nullable Selection::GetCaretBidiLevel( aRv.Throw(NS_ERROR_NOT_INITIALIZED); return Nullable(); } - nsBidiLevel caretBidiLevel = mFrameSelection->GetCaretBidiLevel(); + mozilla::intl::Bidi::EmbeddingLevel caretBidiLevel = + static_cast( + mFrameSelection->GetCaretBidiLevel()); return (caretBidiLevel & BIDI_LEVEL_UNDEFINED) ? Nullable() : Nullable(caretBidiLevel); @@ -403,7 +406,7 @@ void Selection::SetCaretBidiLevel(const Nullable& aCaretBidiLevel, mFrameSelection->UndefineCaretBidiLevel(); } else { mFrameSelection->SetCaretBidiLevelAndMaybeSchedulePaint( - aCaretBidiLevel.Value()); + mozilla::intl::Bidi::EmbeddingLevel(aCaretBidiLevel.Value())); } } @@ -1357,7 +1360,8 @@ nsIFrame* Selection::GetPrimaryOrCaretFrameForNodeOffset(nsIContent* aContent, CaretAssociationHint hint = mFrameSelection->GetHint(); if (aVisual) { - nsBidiLevel caretBidiLevel = mFrameSelection->GetCaretBidiLevel(); + mozilla::intl::Bidi::EmbeddingLevel caretBidiLevel = + mFrameSelection->GetCaretBidiLevel(); return nsCaret::GetCaretFrameForNodeOffset( mFrameSelection, aContent, aOffset, hint, caretBidiLevel, @@ -3298,9 +3302,10 @@ void Selection::Modify(const nsAString& aAlter, const nsAString& aDirection, // If the paragraph direction of the focused frame is right-to-left, // we may have to swap the direction of movement. if (nsIFrame* frame = GetPrimaryFrameForFocusNode(visual)) { - nsBidiDirection paraDir = nsBidiPresUtils::ParagraphDirection(frame); + mozilla::intl::Bidi::Direction paraDir = + nsBidiPresUtils::ParagraphDirection(frame); - if (paraDir == NSBIDI_RTL && visual) { + if (paraDir == mozilla::intl::Bidi::Direction::RTL && visual) { if (amount == eSelectBeginLine) { amount = eSelectEndLine; forward = !forward; @@ -3474,7 +3479,9 @@ nsresult Selection::SelectionLanguageChange(bool aLangRTL) { RefPtr frameSelection = mFrameSelection; // if the direction of the language hasn't changed, nothing to do - nsBidiLevel kbdBidiLevel = aLangRTL ? NSBIDI_RTL : NSBIDI_LTR; + mozilla::intl::Bidi::EmbeddingLevel kbdBidiLevel = + aLangRTL ? mozilla::intl::Bidi::EmbeddingLevel::RTL() + : mozilla::intl::Bidi::EmbeddingLevel::LTR(); if (kbdBidiLevel == frameSelection->mKbdBidiLevel) { return NS_OK; } @@ -3488,12 +3495,12 @@ nsresult Selection::SelectionLanguageChange(bool aLangRTL) { auto [frameStart, frameEnd] = focusFrame->GetOffsets(); RefPtr context = GetPresContext(); - nsBidiLevel levelBefore, levelAfter; + mozilla::intl::Bidi::EmbeddingLevel levelBefore, levelAfter; if (!context) { return NS_ERROR_FAILURE; } - nsBidiLevel level = focusFrame->GetEmbeddingLevel(); + mozilla::intl::Bidi::EmbeddingLevel level = focusFrame->GetEmbeddingLevel(); int32_t focusOffset = static_cast(FocusOffset()); if ((focusOffset != frameStart) && (focusOffset != frameEnd)) // the cursor is not at a frame boundary, so the level of both the @@ -3511,26 +3518,30 @@ nsresult Selection::SelectionLanguageChange(bool aLangRTL) { levelAfter = levels.mLevelAfter; } - if (IS_SAME_DIRECTION(levelBefore, levelAfter)) { + if (levelBefore.IsSameDirection(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)) + if ((level != levelBefore) && (level != levelAfter)) { level = std::min(levelBefore, levelAfter); - if (IS_SAME_DIRECTION(level, kbdBidiLevel)) + } + if (level.IsSameDirection(kbdBidiLevel)) { frameSelection->SetCaretBidiLevelAndMaybeSchedulePaint(level); - else - frameSelection->SetCaretBidiLevelAndMaybeSchedulePaint(level + 1); + } else { + frameSelection->SetCaretBidiLevelAndMaybeSchedulePaint( + mozilla::intl::Bidi::EmbeddingLevel(level + 1)); + } } 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 (IS_SAME_DIRECTION(levelBefore, kbdBidiLevel)) + if (levelBefore.IsSameDirection(kbdBidiLevel)) { frameSelection->SetCaretBidiLevelAndMaybeSchedulePaint(levelBefore); - else + } else { frameSelection->SetCaretBidiLevelAndMaybeSchedulePaint(levelAfter); + } } // The caret might have moved, so invalidate the desired position diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp index ec2528458c60..22a8b8a8abf6 100644 --- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -12,6 +12,7 @@ #include "nsContentUtils.h" +#include "mozilla/intl/Bidi.h" #include "mozilla/PresShell.h" #include "mozilla/PresShellInlines.h" #include "mozilla/SVGImageContext.h" @@ -3503,11 +3504,11 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor using ContextState = CanvasRenderingContext2D::ContextState; virtual void SetText(const char16_t* aText, int32_t aLength, - nsBidiDirection aDirection) override { + mozilla::intl::Bidi::Direction aDirection) override { mFontgrp->UpdateUserFonts(); // ensure user font generation is current // adjust flags for current direction run gfx::ShapedTextFlags flags = mTextRunFlags; - if (aDirection == NSBIDI_RTL) { + if (aDirection == mozilla::intl::Bidi::Direction::RTL) { flags |= gfx::ShapedTextFlags::TEXT_IS_RTL; } else { flags &= ~gfx::ShapedTextFlags::TEXT_IS_RTL; @@ -3873,7 +3874,9 @@ TextMetrics* CanvasRenderingContext2D::DrawOrMeasureText( // calls bidi algo twice since it needs the full text width and the // bounding boxes before rendering anything aError = nsBidiPresUtils::ProcessText( - textToDraw.get(), textToDraw.Length(), isRTL ? NSBIDI_RTL : NSBIDI_LTR, + textToDraw.get(), textToDraw.Length(), + isRTL ? mozilla::intl::Bidi::EmbeddingLevel::RTL() + : mozilla::intl::Bidi::EmbeddingLevel::LTR(), presShell->GetPresContext(), processor, nsBidiPresUtils::MODE_MEASURE, nullptr, 0, &totalWidthCoord, &mBidiEngine); if (aError.Failed()) { @@ -4014,7 +4017,9 @@ TextMetrics* CanvasRenderingContext2D::DrawOrMeasureText( processor.mDoMeasureBoundingBox = false; aError = nsBidiPresUtils::ProcessText( - textToDraw.get(), textToDraw.Length(), isRTL ? NSBIDI_RTL : NSBIDI_LTR, + textToDraw.get(), textToDraw.Length(), + isRTL ? mozilla::intl::Bidi::EmbeddingLevel::RTL() + : mozilla::intl::Bidi::EmbeddingLevel::LTR(), presShell->GetPresContext(), processor, nsBidiPresUtils::MODE_DRAW, nullptr, 0, nullptr, &mBidiEngine); diff --git a/dom/canvas/CanvasRenderingContext2D.h b/dom/canvas/CanvasRenderingContext2D.h index 0b33d0245e75..8b4e61ef0ac1 100644 --- a/dom/canvas/CanvasRenderingContext2D.h +++ b/dom/canvas/CanvasRenderingContext2D.h @@ -9,6 +9,7 @@ #include "mozilla/dom/BasicRenderingContext2D.h" #include "mozilla/dom/CanvasRenderingContext2DBinding.h" #include "mozilla/dom/HTMLCanvasElement.h" +#include "mozilla/intl/Bidi.h" #include "mozilla/gfx/Rect.h" #include "mozilla/gfx/2D.h" #include "mozilla/Attributes.h" @@ -19,8 +20,8 @@ #include "FilterDescription.h" #include "gfx2DGlue.h" #include "nsICanvasRenderingContextInternal.h" -#include "nsBidi.h" #include "nsColor.h" +#include "nsIFrame.h" class gfxFontGroup; class nsGlobalWindowInner; @@ -797,7 +798,7 @@ class CanvasRenderingContext2D final : public nsICanvasRenderingContextInternal, nsTArray mHitRegionsOptions; - nsBidi mBidiEngine; + mozilla::intl::Bidi mBidiEngine; /** * Returns true if a shadow should be drawn along with a diff --git a/editor/libeditor/EditorBase.cpp b/editor/libeditor/EditorBase.cpp index 030af0297d49..cadb2c54ad7b 100644 --- a/editor/libeditor/EditorBase.cpp +++ b/editor/libeditor/EditorBase.cpp @@ -10,22 +10,23 @@ #include // for nullptr, stdout #include // for strcmp -#include "ChangeAttributeTransaction.h" // for ChangeAttributeTransaction -#include "CompositionTransaction.h" // for CompositionTransaction -#include "CreateElementTransaction.h" // for CreateElementTransaction -#include "DeleteNodeTransaction.h" // for DeleteNodeTransaction -#include "DeleteRangeTransaction.h" // for DeleteRangeTransaction -#include "DeleteTextTransaction.h" // for DeleteTextTransaction -#include "EditAggregateTransaction.h" // for EditAggregateTransaction -#include "EditTransactionBase.h" // for EditTransactionBase -#include "EditorEventListener.h" // for EditorEventListener -#include "gfxFontUtils.h" // for gfxFontUtils -#include "HTMLEditUtils.h" // for HTMLEditUtils -#include "InsertNodeTransaction.h" // for InsertNodeTransaction -#include "InsertTextTransaction.h" // for InsertTextTransaction -#include "JoinNodeTransaction.h" // for JoinNodeTransaction -#include "PlaceholderTransaction.h" // for PlaceholderTransaction -#include "SplitNodeTransaction.h" // for SplitNodeTransaction +#include "ChangeAttributeTransaction.h" // for ChangeAttributeTransaction +#include "CompositionTransaction.h" // for CompositionTransaction +#include "CreateElementTransaction.h" // for CreateElementTransaction +#include "DeleteNodeTransaction.h" // for DeleteNodeTransaction +#include "DeleteRangeTransaction.h" // for DeleteRangeTransaction +#include "DeleteTextTransaction.h" // for DeleteTextTransaction +#include "EditAggregateTransaction.h" // for EditAggregateTransaction +#include "EditTransactionBase.h" // for EditTransactionBase +#include "EditorEventListener.h" // for EditorEventListener +#include "gfxFontUtils.h" // for gfxFontUtils +#include "HTMLEditUtils.h" // for HTMLEditUtils +#include "InsertNodeTransaction.h" // for InsertNodeTransaction +#include "InsertTextTransaction.h" // for InsertTextTransaction +#include "JoinNodeTransaction.h" // for JoinNodeTransaction +#include "PlaceholderTransaction.h" // for PlaceholderTransaction +#include "SplitNodeTransaction.h" // for SplitNodeTransaction +#include "mozilla/intl/Bidi.h" #include "mozilla/BasePrincipal.h" // for BasePrincipal #include "mozilla/CheckedInt.h" // for CheckedInt #include "mozilla/ComposerCommandsUpdater.h" // for ComposerCommandsUpdater @@ -5765,12 +5766,13 @@ EditorBase::AutoCaretBidiLevelManager::AutoCaretBidiLevelManager( nsPrevNextBidiLevels levels = frameSelection->GetPrevNextBidiLevels( aPointAtCaret.GetContainerAsContent(), aPointAtCaret.Offset(), true); - nsBidiLevel levelBefore = levels.mLevelBefore; - nsBidiLevel levelAfter = levels.mLevelAfter; + mozilla::intl::Bidi::EmbeddingLevel levelBefore = levels.mLevelBefore; + mozilla::intl::Bidi::EmbeddingLevel levelAfter = levels.mLevelAfter; - nsBidiLevel currentCaretLevel = frameSelection->GetCaretBidiLevel(); + mozilla::intl::Bidi::EmbeddingLevel currentCaretLevel = + frameSelection->GetCaretBidiLevel(); - nsBidiLevel levelOfDeletion; + mozilla::intl::Bidi::EmbeddingLevel levelOfDeletion; levelOfDeletion = (nsIEditor::eNext == aDirectionAndAmount || nsIEditor::eNextWord == aDirectionAndAmount) ? levelAfter diff --git a/editor/libeditor/EditorBase.h b/editor/libeditor/EditorBase.h index 80f6e0e6c4a5..0fbcd169cddc 100644 --- a/editor/libeditor/EditorBase.h +++ b/editor/libeditor/EditorBase.h @@ -6,6 +6,7 @@ #ifndef mozilla_EditorBase_h #define mozilla_EditorBase_h +#include "mozilla/intl/Bidi.h" #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc. #include "mozilla/EditAction.h" // for EditAction and EditSubAction #include "mozilla/EditorDOMPoint.h" // for EditorDOMPoint @@ -28,7 +29,6 @@ #include "nsGkAtoms.h" #include "nsIContentInlines.h" // for nsINode::IsEditable() #include "nsIEditor.h" // for nsIEditor, etc. -#include "nsIFrame.h" // for nsBidiLevel #include "nsISelectionController.h" // for nsISelectionController constants #include "nsISelectionListener.h" // for nsISelectionListener #include "nsISupportsImpl.h" // for EditorBase::Release, etc. @@ -1985,7 +1985,7 @@ class EditorBase : public nsIEditor, void MaybeUpdateCaretBidiLevel(const EditorBase& aEditorBase) const; private: - Maybe mNewCaretBidiLevel; + Maybe mNewCaretBidiLevel; bool mFailed = false; bool mCanceled = false; }; diff --git a/intl/unicharutil/util/nsBidiUtils.h b/intl/unicharutil/util/nsBidiUtils.h index 21a7ee7ffa81..14f95ec998b0 100644 --- a/intl/unicharutil/util/nsBidiUtils.h +++ b/intl/unicharutil/util/nsBidiUtils.h @@ -51,25 +51,6 @@ 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 8a1567e2dbc1..d367a93e0e64 100644 --- a/layout/base/nsBidiPresUtils.cpp +++ b/layout/base/nsBidiPresUtils.cpp @@ -6,6 +6,8 @@ #include "nsBidiPresUtils.h" +#include "mozilla/intl/Bidi.h" +#include "mozilla/Casting.h" #include "mozilla/IntegerRange.h" #include "mozilla/Maybe.h" #include "mozilla/PresShell.h" @@ -39,6 +41,7 @@ #undef REALLY_NOISY_BIDI using namespace mozilla; +using EmbeddingLevel = mozilla::intl::Bidi::EmbeddingLevel; static const char16_t kSpace = 0x0020; static const char16_t kZWSP = 0x200B; @@ -163,7 +166,7 @@ struct MOZ_STACK_CLASS BidiParagraphData { nsPresContext* mPresContext; bool mIsVisual; bool mRequiresBidi; - nsBidiLevel mParaLevel; + EmbeddingLevel mParaLevel; nsIContent* mPrevContent; /** @@ -335,37 +338,49 @@ struct MOZ_STACK_CLASS BidiParagraphData { } nsresult SetPara() { - return mPresContext->GetBidiEngine().SetPara(mBuffer.get(), BufferLength(), - mParaLevel); + if (mPresContext->GetBidiEngine() + .SetParagraph(mBuffer, mParaLevel) + .isErr()) { + return NS_ERROR_FAILURE; + }; + return NS_OK; } /** - * mParaLevel can be NSBIDI_DEFAULT_LTR as well as NSBIDI_LTR or NSBIDI_RTL. - * GetParaLevel() returns the actual (resolved) paragraph level which is - * always either NSBIDI_LTR or NSBIDI_RTL + * mParaLevel can be intl::Bidi::Direction::LTR as well as + * intl::Bidi::Direction::LTR or intl::Bidi::Direction::RTL. + * GetParagraphEmbeddingLevel() returns the actual (resolved) paragraph level + * which is always either intl::Bidi::Direction::LTR or + * intl::Bidi::Direction::RTL */ - nsBidiLevel GetParaLevel() { - nsBidiLevel paraLevel = mParaLevel; - if (paraLevel == NSBIDI_DEFAULT_LTR || paraLevel == NSBIDI_DEFAULT_RTL) { - paraLevel = mPresContext->GetBidiEngine().GetParaLevel(); + EmbeddingLevel GetParagraphEmbeddingLevel() { + EmbeddingLevel paraLevel = mParaLevel; + if (paraLevel == EmbeddingLevel::DefaultLTR() || + paraLevel == EmbeddingLevel::DefaultRTL()) { + paraLevel = mPresContext->GetBidiEngine().GetParagraphEmbeddingLevel(); } return paraLevel; } - nsBidiDirection GetDirection() { - return mPresContext->GetBidiEngine().GetDirection(); + intl::Bidi::ParagraphDirection GetParagraphDirection() { + return mPresContext->GetBidiEngine().GetParagraphDirection(); } nsresult CountRuns(int32_t* runCount) { - return mPresContext->GetBidiEngine().CountRuns(runCount); + auto result = mPresContext->GetBidiEngine().CountRuns(); + if (result.isErr()) { + return NS_ERROR_FAILURE; + } + *runCount = result.unwrap(); + return NS_OK; } void GetLogicalRun(int32_t aLogicalStart, int32_t* aLogicalLimit, - nsBidiLevel* aLevel) { + EmbeddingLevel* aLevel) { mPresContext->GetBidiEngine().GetLogicalRun(aLogicalStart, aLogicalLimit, aLevel); if (mIsVisual) { - *aLevel = GetParaLevel(); + *aLevel = GetParagraphEmbeddingLevel(); } } @@ -465,7 +480,7 @@ struct MOZ_STACK_CLASS BidiLineData { AutoTArray mLogicalFrames; AutoTArray mVisualFrames; AutoTArray mIndexMap; - AutoTArray mLevels; + AutoTArray mLevels; bool mIsReordered; BidiLineData(nsIFrame* aFirstFrameOnLine, int32_t aNumFramesOnLine) { @@ -477,11 +492,11 @@ struct MOZ_STACK_CLASS BidiLineData { bool hasRTLFrames = false; bool hasVirtualControls = false; - auto appendFrame = [&](nsIFrame* frame, nsBidiLevel level) { + auto appendFrame = [&](nsIFrame* frame, EmbeddingLevel level) { mLogicalFrames.AppendElement(frame); mLevels.AppendElement(level); mIndexMap.AppendElement(0); - if (IS_LEVEL_RTL(level)) { + if (level.IsRTL()) { hasRTLFrames = true; } }; @@ -502,8 +517,8 @@ struct MOZ_STACK_CLASS BidiLineData { } // Reorder the line - nsBidi::ReorderVisual(mLevels.Elements(), FrameCount(), - mIndexMap.Elements()); + mozilla::intl::Bidi::ReorderVisual(mLevels.Elements(), FrameCount(), + mIndexMap.Elements()); // Strip virtual frames if (hasVirtualControls) { @@ -865,7 +880,8 @@ nsresult nsBidiPresUtils::ResolveParagraph(BidiParagraphData* aBpd) { nsresult rv = aBpd->SetPara(); NS_ENSURE_SUCCESS(rv, rv); - nsBidiLevel embeddingLevel = aBpd->GetParaLevel(); + intl::Bidi::EmbeddingLevel embeddingLevel = + aBpd->GetParagraphEmbeddingLevel(); rv = aBpd->CountRuns(&runCount); NS_ENSURE_SUCCESS(rv, rv); @@ -897,8 +913,9 @@ nsresult nsBidiPresUtils::ResolveParagraph(BidiParagraphData* aBpd) { # endif #endif - if (runCount == 1 && frameCount == 1 && aBpd->GetDirection() == NSBIDI_LTR && - aBpd->GetParaLevel() == 0) { + if (runCount == 1 && frameCount == 1 && + aBpd->GetParagraphDirection() == intl::Bidi::ParagraphDirection::LTR && + aBpd->GetParagraphEmbeddingLevel() == 0) { // We have a single left-to-right frame in a left-to-right paragraph, // without bidi isolation from the surrounding text. // Make sure that the embedding level and base level frame properties aren't @@ -920,13 +937,13 @@ nsresult nsBidiPresUtils::ResolveParagraph(BidiParagraphData* aBpd) { } BidiParagraphData::FrameInfo lastRealFrame; - nsBidiLevel lastEmbeddingLevel = kBidiLevelNone; - nsBidiLevel precedingControl = kBidiLevelNone; + EmbeddingLevel lastEmbeddingLevel = kBidiLevelNone; + EmbeddingLevel precedingControl = kBidiLevelNone; auto storeBidiDataToFrame = [&]() { FrameBidiData bidiData; bidiData.embeddingLevel = embeddingLevel; - bidiData.baseLevel = aBpd->GetParaLevel(); + bidiData.baseLevel = aBpd->GetParagraphEmbeddingLevel(); // If a control character doesn't have a lower embedding level than // both the preceding and the following frame, it isn't something // needed for getting the correct result. This optimization should @@ -1506,11 +1523,11 @@ FrameBidiData nsBidiPresUtils::GetFrameBidiData(nsIFrame* aFrame) { return GetFirstLeaf(aFrame)->GetBidiData(); } -nsBidiLevel nsBidiPresUtils::GetFrameEmbeddingLevel(nsIFrame* aFrame) { +EmbeddingLevel nsBidiPresUtils::GetFrameEmbeddingLevel(nsIFrame* aFrame) { return GetFirstLeaf(aFrame)->GetEmbeddingLevel(); } -nsBidiLevel nsBidiPresUtils::GetFrameBaseLevel(const nsIFrame* aFrame) { +EmbeddingLevel nsBidiPresUtils::GetFrameBaseLevel(const nsIFrame* aFrame) { const nsIFrame* firstLeaf = aFrame; while (!IsBidiLeaf(firstLeaf)) { firstLeaf = firstLeaf->PrincipalChildList().FirstChild(); @@ -1871,7 +1888,7 @@ nscoord nsBidiPresUtils::RepositionInlineFrames(BidiLineData* aBld, for (; index != limit; index += step) { frame = aBld->VisualFrameAt(index); start += RepositionFrame( - frame, !(IS_LEVEL_RTL(aBld->mLevels[aBld->mIndexMap[index]])), start, + frame, !(aBld->mLevels[aBld->mIndexMap[index]].IsRTL()), start, &continuationStates, aLineWM, false, aContainerSize); } return start; @@ -2079,7 +2096,7 @@ RemoveDiacritics(char16_t* aText, } #endif -void nsBidiPresUtils::CalculateCharType(nsBidi* aBidiEngine, +void nsBidiPresUtils::CalculateCharType(intl::Bidi* aBidiEngine, const char16_t* aText, int32_t& aOffset, int32_t aCharTypeLimit, int32_t& aRunLimit, int32_t& aRunLength, @@ -2143,27 +2160,29 @@ void nsBidiPresUtils::CalculateCharType(nsBidi* aBidiEngine, aOffset = offset; } -nsresult nsBidiPresUtils::ProcessText(const char16_t* aText, int32_t aLength, - nsBidiLevel aBaseLevel, +nsresult nsBidiPresUtils::ProcessText(const char16_t* aText, size_t aLength, + EmbeddingLevel aBaseLevel, nsPresContext* aPresContext, BidiProcessor& aprocessor, Mode aMode, nsBidiPositionResolve* aPosResolve, int32_t aPosResolveCount, nscoord* aWidth, - nsBidi* aBidiEngine) { + mozilla::intl::Bidi* aBidiEngine) { NS_ASSERTION((aPosResolve == nullptr) != (aPosResolveCount > 0), "Incorrect aPosResolve / aPosResolveCount arguments"); - int32_t runCount; - nsAutoString textBuffer(aText, aLength); textBuffer.ReplaceChar(kSeparators, kSpace); const char16_t* text = textBuffer.get(); - nsresult rv = aBidiEngine->SetPara(text, aLength, aBaseLevel); - if (NS_FAILED(rv)) return rv; + if (aBidiEngine->SetParagraph(Span(text, aLength), aBaseLevel).isErr()) { + return NS_ERROR_FAILURE; + } - rv = aBidiEngine->CountRuns(&runCount); - if (NS_FAILED(rv)) return rv; + auto result = aBidiEngine->CountRuns(); + if (result.isErr()) { + return NS_ERROR_FAILURE; + } + int32_t runCount = result.unwrap(); nscoord xOffset = 0; nscoord width, xEndRun = 0; @@ -2180,15 +2199,16 @@ nsresult nsBidiPresUtils::ProcessText(const char16_t* aText, int32_t aLength, } for (i = 0; i < runCount; i++) { - nsBidiDirection dir = aBidiEngine->GetVisualRun(i, &start, &length); + mozilla::intl::Bidi::Direction dir = + aBidiEngine->GetVisualRun(i, &start, &length); - nsBidiLevel level; + EmbeddingLevel level; aBidiEngine->GetLogicalRun(start, &limit, &level); - dir = DIRECTION_FROM_LEVEL(level); + dir = level.Direction(); int32_t subRunLength = limit - start; int32_t lineOffset = start; - int32_t typeLimit = std::min(limit, aLength); + int32_t typeLimit = std::min(limit, AssertedCast(aLength)); int32_t subRunCount = 1; int32_t subRunLimit = typeLimit; @@ -2204,8 +2224,9 @@ nsresult nsBidiPresUtils::ProcessText(const char16_t* aText, int32_t aLength, * x-coordinate of the end of the run for the start of the next run. */ - if (dir == NSBIDI_RTL) { - aprocessor.SetText(text + start, subRunLength, dir); + if (dir == intl::Bidi::Direction::RTL) { + aprocessor.SetText(text + start, subRunLength, + intl::Bidi::Direction::RTL); width = aprocessor.GetWidth(); xOffset += width; xEndRun = xOffset; @@ -2227,7 +2248,7 @@ nsresult nsBidiPresUtils::ProcessText(const char16_t* aText, int32_t aLength, aprocessor.SetText(runVisualText.get(), subRunLength, dir); width = aprocessor.GetWidth(); totalWidth += width; - if (dir == NSBIDI_RTL) { + if (dir == mozilla::intl::Bidi::Direction::RTL) { xOffset -= width; } if (aMode == MODE_DRAW) { @@ -2297,7 +2318,7 @@ nsresult nsBidiPresUtils::ProcessText(const char16_t* aText, int32_t aLength, // The position in the text where this run's "left part" begins. const char16_t* visualLeftPart; const char16_t* visualRightSide; - if (dir == NSBIDI_RTL) { + if (dir == mozilla::intl::Bidi::Direction::RTL) { // One day, son, this could all be replaced with // mPresContext->GetBidiEngine().GetVisualIndex() ... posResolve->visualIndex = @@ -2326,7 +2347,7 @@ nsresult nsBidiPresUtils::ProcessText(const char16_t* aText, int32_t aLength, } } - if (dir == NSBIDI_LTR) { + if (dir == intl::Bidi::Direction::LTR) { xOffset += width; } @@ -2335,7 +2356,7 @@ nsresult nsBidiPresUtils::ProcessText(const char16_t* aText, int32_t aLength, subRunLimit = typeLimit; subRunLength = typeLimit - lineOffset; } // while - if (dir == NSBIDI_RTL) { + if (dir == intl::Bidi::Direction::RTL) { xOffset = xEndRun; } @@ -2367,8 +2388,8 @@ class MOZ_STACK_CLASS nsIRenderingContextBidiProcessor final ~nsIRenderingContextBidiProcessor() { mFontMetrics->SetTextRunRTL(false); } virtual void SetText(const char16_t* aText, int32_t aLength, - nsBidiDirection aDirection) override { - mFontMetrics->SetTextRunRTL(aDirection == NSBIDI_RTL); + intl::Bidi::Direction aDirection) override { + mFontMetrics->SetTextRunRTL(aDirection == intl::Bidi::Direction::RTL); mText = aText; mLength = aLength; } @@ -2399,7 +2420,7 @@ class MOZ_STACK_CLASS nsIRenderingContextBidiProcessor final }; nsresult nsBidiPresUtils::ProcessTextForRenderingContext( - const char16_t* aText, int32_t aLength, nsBidiLevel aBaseLevel, + const char16_t* aText, int32_t aLength, EmbeddingLevel aBaseLevel, nsPresContext* aPresContext, gfxContext& aRenderingContext, DrawTarget* aTextRunConstructionDrawTarget, nsFontMetrics& aFontMetrics, Mode aMode, nscoord aX, nscoord aY, nsBidiPositionResolve* aPosResolve, @@ -2413,15 +2434,16 @@ nsresult nsBidiPresUtils::ProcessTextForRenderingContext( } /* static */ -nsBidiLevel nsBidiPresUtils::BidiLevelFromStyle(ComputedStyle* aComputedStyle) { +EmbeddingLevel nsBidiPresUtils::BidiLevelFromStyle( + ComputedStyle* aComputedStyle) { if (aComputedStyle->StyleTextReset()->mUnicodeBidi & NS_STYLE_UNICODE_BIDI_PLAINTEXT) { - return NSBIDI_DEFAULT_LTR; + return EmbeddingLevel::DefaultLTR(); } if (aComputedStyle->StyleVisibility()->mDirection == StyleDirection::Rtl) { - return NSBIDI_RTL; + return EmbeddingLevel::RTL(); } - return NSBIDI_LTR; + return EmbeddingLevel::LTR(); } diff --git a/layout/base/nsBidiPresUtils.h b/layout/base/nsBidiPresUtils.h index 09fec0a7608c..5c6877f052ec 100644 --- a/layout/base/nsBidiPresUtils.h +++ b/layout/base/nsBidiPresUtils.h @@ -8,7 +8,7 @@ #define nsBidiPresUtils_h___ #include "gfxContext.h" -#include "nsBidi.h" +#include "mozilla/intl/Bidi.h" #include "nsBidiUtils.h" #include "nsHashKeys.h" #include "nsCoord.h" @@ -164,7 +164,7 @@ class nsBidiPresUtils { * mixed direction. */ virtual void SetText(const char16_t* aText, int32_t aLength, - nsBidiDirection aDirection) = 0; + mozilla::intl::Bidi::Direction aDirection) = 0; /** * Returns the measured width of the text given in SetText. If SetText was @@ -229,15 +229,6 @@ class nsBidiPresUtils { * @param[in] aText the string to be rendered (in logical order) * @param aLength the number of characters in the string * @param aBaseLevel the base embedding level of the string - * odd values are right-to-left; even values are left-to-right, plus special - * constants as follows (defined in nsBidi.h) - * NSBIDI_LTR - left-to-right string - * NSBIDI_RTL - right-to-left string - * NSBIDI_DEFAULT_LTR - auto direction determined by first strong character, - * default is left-to-right - * NSBIDI_DEFAULT_RTL - auto direction determined by first strong character, - * default is right-to-left - * * @param aPresContext the presentation context * @param aRenderingContext the rendering context to render to * @param aTextRunConstructionContext the rendering context to be used to @@ -248,23 +239,26 @@ class nsBidiPresUtils { * visual positions; can be nullptr if this functionality is not required * @param aPosResolveCount number of items in the aPosResolve array */ - static nsresult RenderText( - const char16_t* aText, int32_t aLength, nsBidiLevel aBaseLevel, - nsPresContext* aPresContext, gfxContext& aRenderingContext, - DrawTarget* aTextRunConstructionDrawTarget, nsFontMetrics& aFontMetrics, - nscoord aX, nscoord aY, nsBidiPositionResolve* aPosResolve = nullptr, - int32_t aPosResolveCount = 0) { + static nsresult RenderText(const char16_t* aText, int32_t aLength, + mozilla::intl::Bidi::EmbeddingLevel aBaseLevel, + nsPresContext* aPresContext, + gfxContext& aRenderingContext, + DrawTarget* aTextRunConstructionDrawTarget, + nsFontMetrics& aFontMetrics, nscoord aX, + nscoord aY, + nsBidiPositionResolve* aPosResolve = nullptr, + int32_t aPosResolveCount = 0) { return ProcessTextForRenderingContext( aText, aLength, aBaseLevel, aPresContext, aRenderingContext, aTextRunConstructionDrawTarget, aFontMetrics, MODE_DRAW, aX, aY, aPosResolve, aPosResolveCount, nullptr); } - static nscoord MeasureTextWidth(const char16_t* aText, int32_t aLength, - nsBidiLevel aBaseLevel, - nsPresContext* aPresContext, - gfxContext& aRenderingContext, - nsFontMetrics& aFontMetrics) { + static nscoord MeasureTextWidth( + const char16_t* aText, int32_t aLength, + mozilla::intl::Bidi::EmbeddingLevel aBaseLevel, + nsPresContext* aPresContext, gfxContext& aRenderingContext, + nsFontMetrics& aFontMetrics) { nscoord length; nsresult rv = ProcessTextForRenderingContext( aText, aLength, aBaseLevel, aPresContext, aRenderingContext, @@ -317,31 +311,32 @@ class nsBidiPresUtils { /** * Get the bidi embedding level of the given (inline) frame. */ - static nsBidiLevel GetFrameEmbeddingLevel(nsIFrame* aFrame); + static mozilla::intl::Bidi::EmbeddingLevel GetFrameEmbeddingLevel( + nsIFrame* aFrame); /** * Get the bidi base level of the given (inline) frame. */ - static nsBidiLevel GetFrameBaseLevel(const nsIFrame* aFrame); + static mozilla::intl::Bidi::EmbeddingLevel GetFrameBaseLevel( + const nsIFrame* aFrame); /** - * Get an nsBidiDirection representing the direction implied by the - * bidi base level of the frame. - * @return NSBIDI_LTR (left-to-right) or NSBIDI_RTL (right-to-left) - * NSBIDI_MIXED will never be returned. + * Get a mozilla::intl::Bidi::Direction representing the direction implied by + * the bidi base level of the frame. + * @return mozilla::intl::Bidi::Direction */ - static nsBidiDirection ParagraphDirection(const nsIFrame* aFrame) { - return DIRECTION_FROM_LEVEL(GetFrameBaseLevel(aFrame)); + static mozilla::intl::Bidi::Direction ParagraphDirection( + const nsIFrame* aFrame) { + return GetFrameBaseLevel(aFrame).Direction(); } /** - * Get an nsBidiDirection representing the direction implied by the - * bidi embedding level of the frame. - * @return NSBIDI_LTR (left-to-right) or NSBIDI_RTL (right-to-left) - * NSBIDI_MIXED will never be returned. + * Get a mozilla::intl::Bidi::Direction representing the direction implied by + * the bidi embedding level of the frame. + * @return mozilla::intl::Bidi::Direction */ - static nsBidiDirection FrameDirection(nsIFrame* aFrame) { - return DIRECTION_FROM_LEVEL(GetFrameEmbeddingLevel(aFrame)); + static mozilla::intl::Bidi::Direction FrameDirection(nsIFrame* aFrame) { + return GetFrameEmbeddingLevel(aFrame).Direction(); } static bool IsFrameInParagraphDirection(nsIFrame* aFrame) { @@ -353,7 +348,7 @@ class nsBidiPresUtils { // the leaf frame. static bool IsReversedDirectionFrame(const nsIFrame* aFrame) { mozilla::FrameBidiData bidiData = aFrame->GetBidiData(); - return !IS_SAME_DIRECTION(bidiData.embeddingLevel, bidiData.baseLevel); + return !bidiData.embeddingLevel.IsSameDirection(bidiData.baseLevel); } enum Mode { MODE_DRAW, MODE_MEASURE }; @@ -365,15 +360,6 @@ class nsBidiPresUtils { * @param[in] aText the string to be processed (in logical order) * @param aLength the number of characters in the string * @param aBaseLevel the base embedding level of the string - * odd values are right-to-left; even values are left-to-right, plus special - * constants as follows (defined in nsBidi.h) - * NSBIDI_LTR - left-to-right string - * NSBIDI_RTL - right-to-left string - * NSBIDI_DEFAULT_LTR - auto direction determined by first strong character, - * default is left-to-right - * NSBIDI_DEFAULT_RTL - auto direction determined by first strong character, - * default is right-to-left - * * @param aPresContext the presentation context * @param aprocessor the bidi processor * @param aMode the operation to process @@ -385,31 +371,33 @@ class nsBidiPresUtils { * @param aPosResolveCount number of items in the aPosResolve array * @param[out] aWidth Pointer to where the width will be stored (may be null) */ - static nsresult ProcessText(const char16_t* aText, int32_t aLength, - nsBidiLevel aBaseLevel, + static nsresult ProcessText(const char16_t* aText, size_t aLength, + mozilla::intl::Bidi::EmbeddingLevel aBaseLevel, nsPresContext* aPresContext, BidiProcessor& aprocessor, Mode aMode, nsBidiPositionResolve* aPosResolve, int32_t aPosResolveCount, nscoord* aWidth, - nsBidi* aBidiEngine); + mozilla::intl::Bidi* aBidiEngine); /** * Use style attributes to determine the base paragraph level to pass to the * bidi algorithm. * - * If |unicode-bidi| is set to "[-moz-]plaintext", returns NSBIDI_DEFAULT_LTR, - * in other words the direction is determined from the first strong character - * in the text according to rules P2 and P3 of the bidi algorithm, or LTR if - * there is no strong character. + * If |unicode-bidi| is set to "[-moz-]plaintext", returns + * EmbeddingLevel::DefaultLTR, in other words the direction is determined from + * the first strong character in the text according to rules P2 and P3 of the + * bidi algorithm, or LTR if there is no strong character. * - * Otherwise returns NSBIDI_LTR or NSBIDI_RTL depending on the value of - * |direction| + * Otherwise returns EmbeddingLevel::LTR or EmbeddingLevel::RTL depending on + * the value of |direction| */ - static nsBidiLevel BidiLevelFromStyle(mozilla::ComputedStyle* aComputedStyle); + static mozilla::intl::Bidi::EmbeddingLevel BidiLevelFromStyle( + mozilla::ComputedStyle* aComputedStyle); private: static nsresult ProcessTextForRenderingContext( - const char16_t* aText, int32_t aLength, nsBidiLevel aBaseLevel, + const char16_t* aText, int32_t aLength, + mozilla::intl::Bidi::EmbeddingLevel aBaseLevel, nsPresContext* aPresContext, gfxContext& aRenderingContext, DrawTarget* aTextRunConstructionDrawTarget, nsFontMetrics& aFontMetrics, Mode aMode, @@ -572,11 +560,11 @@ class nsBidiPresUtils { */ static void RemoveBidiContinuation(BidiParagraphData* aBpd, nsIFrame* aFrame, int32_t aFirstIndex, int32_t aLastIndex); - static void CalculateCharType(nsBidi* aBidiEngine, const char16_t* aText, - int32_t& aOffset, int32_t aCharTypeLimit, - int32_t& aRunLimit, int32_t& aRunLength, - int32_t& aRunCount, uint8_t& aCharType, - uint8_t& aPrevCharType); + static void CalculateCharType(mozilla::intl::Bidi* aBidiEngine, + const char16_t* aText, int32_t& aOffset, + int32_t aCharTypeLimit, int32_t& aRunLimit, + int32_t& aRunLength, int32_t& aRunCount, + uint8_t& aCharType, uint8_t& aPrevCharType); static void StripBidiControlCharacters(char16_t* aText, int32_t& aTextLength); }; diff --git a/layout/base/nsCaret.cpp b/layout/base/nsCaret.cpp index 1c6bcfcf1e2b..f593b5683da7 100644 --- a/layout/base/nsCaret.cpp +++ b/layout/base/nsCaret.cpp @@ -12,6 +12,7 @@ #include "gfxUtils.h" #include "mozilla/gfx/2D.h" +#include "mozilla/intl/Bidi.h" #include "nsCOMPtr.h" #include "nsFontMetrics.h" #include "nsITimer.h" @@ -39,6 +40,8 @@ using namespace mozilla; using namespace mozilla::dom; using namespace mozilla::gfx; +using EmbeddingLevel = mozilla::intl::Bidi::EmbeddingLevel; + // The bidi indicator hangs off the caret to one side, to show which // direction the typing is in. It needs to be at least 2x2 to avoid looking like // an insignificant dot @@ -389,7 +392,8 @@ nsIFrame* nsCaret::GetFrameAndOffset(const Selection* aSelection, nsIContent* contentNode = focusNode->AsContent(); nsFrameSelection* frameSelection = aSelection->GetFrameSelection(); - nsBidiLevel bidiLevel = frameSelection->GetCaretBidiLevel(); + mozilla::intl::Bidi::EmbeddingLevel bidiLevel = + frameSelection->GetCaretBidiLevel(); return nsCaret::GetCaretFrameForNodeOffset( frameSelection, contentNode, focusOffset, frameSelection->GetHint(), @@ -644,7 +648,8 @@ void nsCaret::StopBlinking() { nsIFrame* nsCaret::GetCaretFrameForNodeOffset( nsFrameSelection* aFrameSelection, nsIContent* aContentNode, - int32_t aOffset, CaretAssociationHint aFrameHint, nsBidiLevel aBidiLevel, + int32_t aOffset, CaretAssociationHint aFrameHint, + mozilla::intl::Bidi::EmbeddingLevel aBidiLevel, nsIFrame** aReturnUnadjustedFrame, int32_t* aReturnOffset) { if (!aFrameSelection) { return nullptr; @@ -696,8 +701,10 @@ nsIFrame* nsCaret::GetCaretFrameForNodeOffset( nsIFrame* frameBefore; nsIFrame* frameAfter; - nsBidiLevel levelBefore; // Bidi level of the character before the caret - nsBidiLevel levelAfter; // Bidi level of the character after the caret + mozilla::intl::Bidi::EmbeddingLevel + levelBefore; // Bidi level of the character before the caret + mozilla::intl::Bidi::EmbeddingLevel + levelAfter; // Bidi level of the character after the caret auto [start, end] = theFrame->GetOffsets(); if (start == 0 || end == 0 || start == theFrameOffset || @@ -720,9 +727,9 @@ nsIFrame* nsCaret::GetCaretFrameForNodeOffset( std::max(levelBefore, levelAfter)); // rule c4 if (aBidiLevel == levelBefore || // rule c1 (aBidiLevel > levelBefore && aBidiLevel < levelAfter && - IS_SAME_DIRECTION(aBidiLevel, levelBefore)) || // rule c5 + aBidiLevel.IsSameDirection(levelBefore)) || // rule c5 (aBidiLevel < levelBefore && aBidiLevel > levelAfter && - IS_SAME_DIRECTION(aBidiLevel, levelBefore))) // rule c9 + aBidiLevel.IsSameDirection(levelBefore))) // rule c9 { if (theFrame != frameBefore) { if (frameBefore) { // if there is a frameBefore, move into it @@ -735,7 +742,8 @@ nsIFrame* nsCaret::GetCaretFrameForNodeOffset( // the first frame on the line has a different Bidi level from // the paragraph level, there is no real frame for the caret to // be in. We have to find the visually first frame on the line. - nsBidiLevel baseLevel = frameAfter->GetBaseLevel(); + mozilla::intl::Bidi::EmbeddingLevel baseLevel = + frameAfter->GetBaseLevel(); if (baseLevel != levelAfter) { nsPeekOffsetStruct pos(eSelectBeginLine, eDirPrevious, 0, nsPoint(0, 0), false, true, false, @@ -749,9 +757,9 @@ nsIFrame* nsCaret::GetCaretFrameForNodeOffset( } } else if (aBidiLevel == levelAfter || // rule c2 (aBidiLevel > levelBefore && aBidiLevel < levelAfter && - IS_SAME_DIRECTION(aBidiLevel, levelAfter)) || // rule c6 + aBidiLevel.IsSameDirection(levelAfter)) || // rule c6 (aBidiLevel < levelBefore && aBidiLevel > levelAfter && - IS_SAME_DIRECTION(aBidiLevel, levelAfter))) // rule c10 + aBidiLevel.IsSameDirection(levelAfter))) // rule c10 { if (theFrame != frameAfter) { if (frameAfter) { @@ -766,7 +774,8 @@ nsIFrame* nsCaret::GetCaretFrameForNodeOffset( // Bidi level from the paragraph level, there is no real frame // for the caret to be in. We have to find the visually last // frame on the line. - nsBidiLevel baseLevel = frameBefore->GetBaseLevel(); + mozilla::intl::Bidi::EmbeddingLevel baseLevel = + frameBefore->GetBaseLevel(); if (baseLevel != levelBefore) { nsPeekOffsetStruct pos(eSelectEndLine, eDirNext, 0, nsPoint(0, 0), false, true, false, @@ -781,34 +790,38 @@ nsIFrame* nsCaret::GetCaretFrameForNodeOffset( } else if (aBidiLevel > levelBefore && aBidiLevel < levelAfter && // rule c7/8 // before and after have the same parity - IS_SAME_DIRECTION(levelBefore, levelAfter) && + levelBefore.IsSameDirection(levelAfter) && // caret has different parity - !IS_SAME_DIRECTION(aBidiLevel, levelAfter)) { + !aBidiLevel.IsSameDirection(levelAfter)) { if (NS_SUCCEEDED(aFrameSelection->GetFrameFromLevel( frameAfter, eDirNext, aBidiLevel, &theFrame))) { std::tie(start, end) = theFrame->GetOffsets(); levelAfter = theFrame->GetEmbeddingLevel(); - 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 = IS_LEVEL_RTL(levelAfter) ? end : start; + if (aBidiLevel.IsRTL()) { + // c8: caret to the right of the rightmost character + theFrameOffset = levelAfter.IsRTL() ? start : end; + } else { + // c7: caret to the left of the leftmost character + theFrameOffset = levelAfter.IsRTL() ? end : start; + } } } else if (aBidiLevel < levelBefore && aBidiLevel > levelAfter && // rule c11/12 // before and after have the same parity - IS_SAME_DIRECTION(levelBefore, levelAfter) && + levelBefore.IsSameDirection(levelAfter) && // caret has different parity - !IS_SAME_DIRECTION(aBidiLevel, levelAfter)) { + !aBidiLevel.IsSameDirection(levelAfter)) { if (NS_SUCCEEDED(aFrameSelection->GetFrameFromLevel( frameBefore, eDirPrevious, aBidiLevel, &theFrame))) { std::tie(start, end) = theFrame->GetOffsets(); levelBefore = theFrame->GetEmbeddingLevel(); - 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 = IS_LEVEL_RTL(levelBefore) ? start : end; + if (aBidiLevel.IsRTL()) { + // c12: caret to the left of the leftmost character + theFrameOffset = levelBefore.IsRTL() ? end : start; + } else { + // c11: caret to the right of the rightmost character + theFrameOffset = levelBefore.IsRTL() ? start : end; + } } } } diff --git a/layout/base/nsCaret.h b/layout/base/nsCaret.h index 5c66472b3436..f2b2167b2ebd 100644 --- a/layout/base/nsCaret.h +++ b/layout/base/nsCaret.h @@ -9,6 +9,7 @@ #ifndef nsCaret_h__ #define nsCaret_h__ +#include "mozilla/intl/Bidi.h" #include "mozilla/MemoryReporting.h" #include "mozilla/dom/Selection.h" #include "nsCoord.h" @@ -179,7 +180,8 @@ class nsCaret final : public nsISelectionListener { nsRect* aRect); static nsIFrame* GetCaretFrameForNodeOffset( nsFrameSelection* aFrameSelection, nsIContent* aContentNode, - int32_t aOffset, CaretAssociationHint aFrameHint, uint8_t aBidiLevel, + int32_t aOffset, CaretAssociationHint aFrameHint, + mozilla::intl::Bidi::EmbeddingLevel aBidiLevel, nsIFrame** aReturnUnadjustedFrame, int32_t* aReturnOffset); static nsRect GetGeometryForFrame(nsIFrame* aFrame, int32_t aFrameOffset, nscoord* aBidiIndicatorSize); diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 668efec3a785..179651959c7e 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -52,6 +52,7 @@ #include "mozilla/dom/KeyframeEffect.h" #include "mozilla/dom/SVGViewportElement.h" #include "mozilla/dom/UIEvent.h" +#include "mozilla/intl/Bidi.h" #include "mozilla/EffectCompositor.h" #include "mozilla/EffectSet.h" #include "mozilla/EventDispatcher.h" @@ -1542,7 +1543,10 @@ nsRect nsLayoutUtils::GetScrolledRect(nsIFrame* aScrolledFrame, WritingMode wm = aScrolledFrame->GetWritingMode(); // Potentially override the frame's direction to use the direction found // by ScrollFrameHelper::GetScrolledFrameDir() - wm.SetDirectionFromBidiLevel(aDirection == StyleDirection::Rtl ? 1 : 0); + wm.SetDirectionFromBidiLevel( + aDirection == StyleDirection::Rtl + ? mozilla::intl::Bidi::EmbeddingLevel::RTL() + : mozilla::intl::Bidi::EmbeddingLevel::LTR()); nscoord x1 = aScrolledFrameOverflowArea.x, x2 = aScrolledFrameOverflowArea.XMost(), @@ -5552,7 +5556,8 @@ nscoord nsLayoutUtils::AppUnitWidthOfStringBidi(const char16_t* aString, gfxContext& aContext) { nsPresContext* presContext = aFrame->PresContext(); if (presContext->BidiEnabled()) { - nsBidiLevel level = nsBidiPresUtils::BidiLevelFromStyle(aFrame->Style()); + mozilla::intl::Bidi::EmbeddingLevel level = + nsBidiPresUtils::BidiLevelFromStyle(aFrame->Style()); return nsBidiPresUtils::MeasureTextWidth( aString, aLength, level, presContext, aContext, aFontMetrics); } @@ -5631,7 +5636,8 @@ void nsLayoutUtils::DrawString(const nsIFrame* aFrame, nsPresContext* presContext = aFrame->PresContext(); if (presContext->BidiEnabled()) { - nsBidiLevel level = nsBidiPresUtils::BidiLevelFromStyle(aComputedStyle); + mozilla::intl::Bidi::EmbeddingLevel level = + nsBidiPresUtils::BidiLevelFromStyle(aComputedStyle); rv = nsBidiPresUtils::RenderText(aString, aLength, level, presContext, *aContext, aContext->GetDrawTarget(), aFontMetrics, aPoint.x, aPoint.y); diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index ada10f7e45d9..cc1cbfee8673 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -100,7 +100,6 @@ #include "nsBidiUtils.h" #include "nsServiceManagerUtils.h" -#include "nsBidi.h" #include "mozilla/dom/URL.h" #include "mozilla/ServoCSSParser.h" @@ -2683,11 +2682,11 @@ uint64_t nsPresContext::GetUndisplayedRestyleGeneration() const { return mRestyleManager->GetUndisplayedRestyleGeneration(); } -nsBidi& nsPresContext::GetBidiEngine() { +mozilla::intl::Bidi& nsPresContext::GetBidiEngine() { MOZ_ASSERT(NS_IsMainThread()); if (!mBidiEngine) { - mBidiEngine.reset(new nsBidi()); + mBidiEngine.reset(new mozilla::intl::Bidi()); } return *mBidiEngine; } diff --git a/layout/base/nsPresContext.h b/layout/base/nsPresContext.h index 7f9f43fbe36b..779d8fed6f26 100644 --- a/layout/base/nsPresContext.h +++ b/layout/base/nsPresContext.h @@ -9,6 +9,7 @@ #ifndef nsPresContext_h___ #define nsPresContext_h___ +#include "mozilla/intl/Bidi.h" #include "mozilla/AppUnits.h" #include "mozilla/Attributes.h" #include "mozilla/EnumeratedArray.h" @@ -43,7 +44,6 @@ #include "nsThreadUtils.h" #include "Units.h" -class nsBidi; class nsIPrintSettings; class nsDocShell; class nsIDocShell; @@ -1079,7 +1079,7 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr { mHasWarnedAboutTooLargeDashedOrDottedRadius = true; } - nsBidi& GetBidiEngine(); + mozilla::intl::Bidi& GetBidiEngine(); gfxFontFeatureValueSet* GetFontFeatureValuesLookup() const { return mFontFeatureValuesLookup; @@ -1207,7 +1207,7 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr { nsCOMPtr mTheme; nsCOMPtr mPrintSettings; - mozilla::UniquePtr mBidiEngine; + mozilla::UniquePtr mBidiEngine; AutoTArray mTransactions; diff --git a/layout/generic/WritingModes.h b/layout/generic/WritingModes.h index c943f8f95144..4a81b4f0ab51 100644 --- a/layout/generic/WritingModes.h +++ b/layout/generic/WritingModes.h @@ -9,6 +9,7 @@ #include +#include "mozilla/intl/Bidi.h" #include "mozilla/ComputedStyle.h" #include "mozilla/EnumeratedRange.h" @@ -524,8 +525,8 @@ class WritingMode { * * XXX change uint8_t to UBiDiLevel after bug 924851 */ - void SetDirectionFromBidiLevel(uint8_t level) { - if (IS_LEVEL_RTL(level) == IsBidiLTR()) { + void SetDirectionFromBidiLevel(mozilla::intl::Bidi::EmbeddingLevel level) { + if (level.IsRTL() == IsBidiLTR()) { mWritingMode ^= StyleWritingMode::RTL | StyleWritingMode::INLINE_REVERSED; } } diff --git a/layout/generic/nsFrameList.cpp b/layout/generic/nsFrameList.cpp index a1c9e08c4d5f..df8e75f018b9 100644 --- a/layout/generic/nsFrameList.cpp +++ b/layout/generic/nsFrameList.cpp @@ -6,6 +6,7 @@ #include "nsFrameList.h" +#include "mozilla/intl/Bidi.h" #include "mozilla/ArenaObjectID.h" #include "mozilla/PresShell.h" #include "nsBidiPresUtils.h" @@ -305,7 +306,8 @@ nsIFrame* nsFrameList::GetPrevVisualFor(nsIFrame* aFrame) const { nsIFrame* parent = mFirstChild->GetParent(); if (!parent) return aFrame ? aFrame->GetPrevSibling() : LastChild(); - nsBidiDirection paraDir = nsBidiPresUtils::ParagraphDirection(mFirstChild); + mozilla::intl::Bidi::Direction paraDir = + nsBidiPresUtils::ParagraphDirection(mFirstChild); nsAutoLineIterator iter = parent->GetLineIterator(); if (!iter) { @@ -313,7 +315,7 @@ nsIFrame* nsFrameList::GetPrevVisualFor(nsIFrame* aFrame) const { if (parent->IsLineFrame()) { // Line frames are not bidi-splittable, so need to consider bidi // reordering - if (paraDir == NSBIDI_LTR) { + if (paraDir == mozilla::intl::Bidi::Direction::LTR) { return nsBidiPresUtils::GetFrameToLeftOf(aFrame, mFirstChild, -1); } else { // RTL return nsBidiPresUtils::GetFrameToRightOf(aFrame, mFirstChild, -1); @@ -345,7 +347,7 @@ nsIFrame* nsFrameList::GetPrevVisualFor(nsIFrame* aFrame) const { if (aFrame) { auto line = iter->GetLine(thisLine).unwrap(); - if (paraDir == NSBIDI_LTR) { + if (paraDir == mozilla::intl::Bidi::Direction::LTR) { frame = nsBidiPresUtils::GetFrameToLeftOf(aFrame, line.mFirstFrameOnLine, line.mNumFramesOnLine); } else { // RTL @@ -358,7 +360,7 @@ nsIFrame* nsFrameList::GetPrevVisualFor(nsIFrame* aFrame) const { // Get the last frame of the previous line auto line = iter->GetLine(thisLine - 1).unwrap(); - if (paraDir == NSBIDI_LTR) { + if (paraDir == mozilla::intl::Bidi::Direction::LTR) { frame = nsBidiPresUtils::GetFrameToLeftOf(nullptr, line.mFirstFrameOnLine, line.mNumFramesOnLine); } else { // RTL @@ -375,7 +377,8 @@ nsIFrame* nsFrameList::GetNextVisualFor(nsIFrame* aFrame) const { nsIFrame* parent = mFirstChild->GetParent(); if (!parent) return aFrame ? aFrame->GetPrevSibling() : mFirstChild; - nsBidiDirection paraDir = nsBidiPresUtils::ParagraphDirection(mFirstChild); + mozilla::intl::Bidi::Direction paraDir = + nsBidiPresUtils::ParagraphDirection(mFirstChild); nsAutoLineIterator iter = parent->GetLineIterator(); if (!iter) { @@ -383,7 +386,7 @@ nsIFrame* nsFrameList::GetNextVisualFor(nsIFrame* aFrame) const { if (parent->IsLineFrame()) { // Line frames are not bidi-splittable, so need to consider bidi // reordering - if (paraDir == NSBIDI_LTR) { + if (paraDir == mozilla::intl::Bidi::Direction::LTR) { return nsBidiPresUtils::GetFrameToRightOf(aFrame, mFirstChild, -1); } else { // RTL return nsBidiPresUtils::GetFrameToLeftOf(aFrame, mFirstChild, -1); @@ -415,7 +418,7 @@ nsIFrame* nsFrameList::GetNextVisualFor(nsIFrame* aFrame) const { if (aFrame) { auto line = iter->GetLine(thisLine).unwrap(); - if (paraDir == NSBIDI_LTR) { + if (paraDir == mozilla::intl::Bidi::Direction::LTR) { frame = nsBidiPresUtils::GetFrameToRightOf(aFrame, line.mFirstFrameOnLine, line.mNumFramesOnLine); } else { // RTL @@ -429,7 +432,7 @@ nsIFrame* nsFrameList::GetNextVisualFor(nsIFrame* aFrame) const { // Get the first frame of the next line auto line = iter->GetLine(thisLine + 1).unwrap(); - if (paraDir == NSBIDI_LTR) { + if (paraDir == mozilla::intl::Bidi::Direction::LTR) { frame = nsBidiPresUtils::GetFrameToRightOf( nullptr, line.mFirstFrameOnLine, line.mNumFramesOnLine); } else { // RTL diff --git a/layout/generic/nsFrameSelection.cpp b/layout/generic/nsFrameSelection.cpp index 6c67dd744270..4806a100a947 100644 --- a/layout/generic/nsFrameSelection.cpp +++ b/layout/generic/nsFrameSelection.cpp @@ -10,6 +10,7 @@ #include "nsFrameSelection.h" +#include "mozilla/intl/Bidi.h" #include "mozilla/Attributes.h" #include "mozilla/AutoRestore.h" #include "mozilla/BasePrincipal.h" @@ -599,7 +600,7 @@ nsresult nsFrameSelection::ConstrainFrameAndPointToAnchorSubtree( } void nsFrameSelection::SetCaretBidiLevelAndMaybeSchedulePaint( - nsBidiLevel aLevel) { + mozilla::intl::Bidi::EmbeddingLevel aLevel) { // If the current level is undefined, we have just inserted new text. // In this case, we don't want to reset the keyboard language mCaret.mBidiLevel = aLevel; @@ -610,12 +611,14 @@ void nsFrameSelection::SetCaretBidiLevelAndMaybeSchedulePaint( } } -nsBidiLevel nsFrameSelection::GetCaretBidiLevel() const { +mozilla::intl::Bidi::EmbeddingLevel nsFrameSelection::GetCaretBidiLevel() + const { return mCaret.mBidiLevel; } void nsFrameSelection::UndefineCaretBidiLevel() { - mCaret.mBidiLevel |= BIDI_LEVEL_UNDEFINED; + mCaret.mBidiLevel = mozilla::intl::Bidi::EmbeddingLevel(mCaret.mBidiLevel | + BIDI_LEVEL_UNDEFINED); } #ifdef PRINT_RANGE @@ -662,9 +665,10 @@ static nsINode* GetClosestInclusiveTableCellAncestor(nsINode* aDomNode) { static nsDirection GetCaretDirection(const nsIFrame& aFrame, nsDirection aDirection, bool aVisualMovement) { - const nsBidiDirection paragraphDirection = + const mozilla::intl::Bidi::Direction paragraphDirection = nsBidiPresUtils::ParagraphDirection(&aFrame); - return (aVisualMovement && paragraphDirection == NSBIDI_RTL) + return (aVisualMovement && + paragraphDirection == mozilla::intl::Bidi::Direction::RTL) ? nsDirection(1 - aDirection) : aDirection; } @@ -928,7 +932,8 @@ nsPrevNextBidiLevels nsFrameSelection::GetPrevNextBidiLevels( nsDirection direction; nsPrevNextBidiLevels levels{}; - levels.SetData(nullptr, nullptr, 0, 0); + levels.SetData(nullptr, nullptr, mozilla::intl::Bidi::EmbeddingLevel::LTR(), + mozilla::intl::Bidi::EmbeddingLevel::LTR()); currentFrame = GetFrameForNodeOffset( aNode, static_cast(aContentOffset), aHint, ¤tOffset); @@ -947,7 +952,8 @@ nsPrevNextBidiLevels nsFrameSelection::GetPrevNextBidiLevels( } else { // we are neither at the beginning nor at the end of the frame, so we have // no worries - nsBidiLevel currentLevel = currentFrame->GetEmbeddingLevel(); + mozilla::intl::Bidi::EmbeddingLevel currentLevel = + currentFrame->GetEmbeddingLevel(); levels.SetData(currentFrame, currentFrame, currentLevel, currentLevel); return levels; } @@ -958,8 +964,8 @@ nsPrevNextBidiLevels nsFrameSelection::GetPrevNextBidiLevels( .mFrame; FrameBidiData currentBidi = currentFrame->GetBidiData(); - nsBidiLevel currentLevel = currentBidi.embeddingLevel; - nsBidiLevel newLevel = + mozilla::intl::Bidi::EmbeddingLevel currentLevel = currentBidi.embeddingLevel; + mozilla::intl::Bidi::EmbeddingLevel newLevel = newFrame ? newFrame->GetEmbeddingLevel() : currentBidi.baseLevel; // If not jumping lines, disregard br frames, since they might be positioned @@ -984,12 +990,13 @@ nsPrevNextBidiLevels nsFrameSelection::GetPrevNextBidiLevels( return levels; } -nsresult nsFrameSelection::GetFrameFromLevel(nsIFrame* aFrameIn, - nsDirection aDirection, - nsBidiLevel aBidiLevel, - nsIFrame** aFrameOut) const { +nsresult nsFrameSelection::GetFrameFromLevel( + nsIFrame* aFrameIn, nsDirection aDirection, + mozilla::intl::Bidi::EmbeddingLevel aBidiLevel, + nsIFrame** aFrameOut) const { NS_ENSURE_STATE(mPresShell); - nsBidiLevel foundLevel = 0; + mozilla::intl::Bidi::EmbeddingLevel foundLevel = + mozilla::intl::Bidi::EmbeddingLevel::LTR(); nsIFrame* foundFrame = aFrameIn; nsCOMPtr frameTraversal; diff --git a/layout/generic/nsFrameSelection.h b/layout/generic/nsFrameSelection.h index bf912a18e62b..4cd087180d4f 100644 --- a/layout/generic/nsFrameSelection.h +++ b/layout/generic/nsFrameSelection.h @@ -7,6 +7,7 @@ #ifndef nsFrameSelection_h___ #define nsFrameSelection_h___ +#include "mozilla/intl/Bidi.h" #include "mozilla/Assertions.h" #include "mozilla/Attributes.h" #include "mozilla/EventForwards.h" @@ -25,7 +26,7 @@ class nsRange; -#define BIDI_LEVEL_UNDEFINED 0x80 +#define BIDI_LEVEL_UNDEFINED mozilla::intl::Bidi::EmbeddingLevel(0x80) //---------------------------------------------------------------------- @@ -172,7 +173,8 @@ struct MOZ_STACK_CLASS nsPeekOffsetStruct { struct nsPrevNextBidiLevels { void SetData(nsIFrame* aFrameBefore, nsIFrame* aFrameAfter, - nsBidiLevel aLevelBefore, nsBidiLevel aLevelAfter) { + mozilla::intl::Bidi::EmbeddingLevel aLevelBefore, + mozilla::intl::Bidi::EmbeddingLevel aLevelAfter) { mFrameBefore = aFrameBefore; mFrameAfter = aFrameAfter; mLevelBefore = aLevelBefore; @@ -180,8 +182,8 @@ struct nsPrevNextBidiLevels { } nsIFrame* mFrameBefore; nsIFrame* mFrameAfter; - nsBidiLevel mLevelBefore; - nsBidiLevel mLevelAfter; + mozilla::intl::Bidi::EmbeddingLevel mLevelBefore; + mozilla::intl::Bidi::EmbeddingLevel mLevelAfter; }; namespace mozilla { @@ -475,12 +477,13 @@ class nsFrameSelection final { void SetHint(CaretAssociateHint aHintRight) { mCaret.mHint = aHintRight; } CaretAssociateHint GetHint() const { return mCaret.mHint; } - void SetCaretBidiLevelAndMaybeSchedulePaint(nsBidiLevel aLevel); + void SetCaretBidiLevelAndMaybeSchedulePaint( + mozilla::intl::Bidi::EmbeddingLevel aLevel); /** * GetCaretBidiLevel gets the caret bidi level. */ - nsBidiLevel GetCaretBidiLevel() const; + mozilla::intl::Bidi::EmbeddingLevel GetCaretBidiLevel() const; /** * UndefineCaretBidiLevel sets the caret bidi level to "undefined". @@ -695,7 +698,7 @@ class nsFrameSelection final { * @param aFrameOut will hold the frame returned */ nsresult GetFrameFromLevel(nsIFrame* aFrameIn, nsDirection aDirection, - nsBidiLevel aBidiLevel, + mozilla::intl::Bidi::EmbeddingLevel aBidiLevel, nsIFrame** aFrameOut) const; /** @@ -1040,7 +1043,7 @@ class nsFrameSelection final { // Hint to tell if the selection is at the end of this line or beginning of // next. CaretAssociateHint mHint = mozilla::CARET_ASSOCIATE_BEFORE; - nsBidiLevel mBidiLevel = BIDI_LEVEL_UNDEFINED; + mozilla::intl::Bidi::EmbeddingLevel mBidiLevel = BIDI_LEVEL_UNDEFINED; bool IsVisualMovement(bool aContinueSelection, CaretMovementStyle aMovementStyle) const; @@ -1048,7 +1051,8 @@ class nsFrameSelection final { Caret mCaret; - nsBidiLevel mKbdBidiLevel = NSBIDI_LTR; + mozilla::intl::Bidi::EmbeddingLevel mKbdBidiLevel = + mozilla::intl::Bidi::EmbeddingLevel::LTR(); class DesiredCaretPos { public: diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 1ae9cf7f00a5..62783af48a0e 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -21,6 +21,7 @@ #include "nsContainerFrame.h" #include "nsGkAtoms.h" #include "nsNameSpaceManager.h" +#include "mozilla/intl/Bidi.h" #include "mozilla/dom/DocumentInlines.h" #include "mozilla/gfx/gfxVars.h" #include "nsFontMetrics.h" @@ -7117,7 +7118,8 @@ StyleDirection ScrollFrameHelper::GetScrolledFrameDir() const { if (mScrolledFrame->StyleTextReset()->mUnicodeBidi & NS_STYLE_UNICODE_BIDI_PLAINTEXT) { if (nsIFrame* child = mScrolledFrame->PrincipalChildList().FirstChild()) { - return nsBidiPresUtils::ParagraphDirection(child) == NSBIDI_LTR + return nsBidiPresUtils::ParagraphDirection(child) == + mozilla::intl::Bidi::Direction::LTR ? StyleDirection::Ltr : StyleDirection::Rtl; } diff --git a/layout/generic/nsIFrame.cpp b/layout/generic/nsIFrame.cpp index f0c1bd3d4a93..31aa9f31906c 100644 --- a/layout/generic/nsIFrame.cpp +++ b/layout/generic/nsIFrame.cpp @@ -25,6 +25,7 @@ #include "mozilla/gfx/2D.h" #include "mozilla/gfx/gfxVars.h" #include "mozilla/gfx/PathHelpers.h" +#include "mozilla/intl/Bidi.h" #include "mozilla/PresShell.h" #include "mozilla/PresShellInlines.h" #include "mozilla/ResultExtensions.h" @@ -1697,7 +1698,8 @@ WritingMode nsIFrame::WritingModeForLine(WritingMode aSelfWM, WritingMode writingMode = aSelfWM; if (StyleTextReset()->mUnicodeBidi & NS_STYLE_UNICODE_BIDI_PLAINTEXT) { - nsBidiLevel frameLevel = nsBidiPresUtils::GetFrameBaseLevel(aSubFrame); + mozilla::intl::Bidi::EmbeddingLevel frameLevel = + nsBidiPresUtils::GetFrameBaseLevel(aSubFrame); writingMode.SetDirectionFromBidiLevel(frameLevel); } @@ -7923,8 +7925,9 @@ void nsIFrame::ListGeneric(nsACString& aTo, const char* aPrefix, } if (HasProperty(BidiDataProperty())) { FrameBidiData bidi = GetBidiData(); - aTo += nsPrintfCString(" bidi(%d,%d,%d)", bidi.baseLevel, - bidi.embeddingLevel, bidi.precedingControl); + aTo += nsPrintfCString(" bidi(%d,%d,%d)", bidi.baseLevel.Value(), + bidi.embeddingLevel.Value(), + bidi.precedingControl.Value()); } if (IsTransformed()) { aTo += nsPrintfCString(" transformed"); @@ -8105,7 +8108,7 @@ nsresult nsIFrame::GetPointFromOffset(int32_t inOffset, nsPoint* outPoint) { bool hasBidiData; FrameBidiData bidiData = GetProperty(BidiDataProperty(), &hasBidiData); bool isRTL = hasBidiData - ? IS_LEVEL_RTL(bidiData.embeddingLevel) + ? bidiData.embeddingLevel.IsRTL() : StyleVisibility()->mDirection == StyleDirection::Rtl; if ((!isRTL && inOffset > newOffset) || (isRTL && inOffset <= newOffset)) { @@ -9102,7 +9105,8 @@ Result nsIFrame::IsVisuallyAtLineEdge( return true; } - bool frameIsRTL = (nsBidiPresUtils::FrameDirection(*framePtr) == NSBIDI_RTL); + bool frameIsRTL = (nsBidiPresUtils::FrameDirection(*framePtr) == + mozilla::intl::Bidi::Direction::RTL); if ((frameIsRTL == lineIsRTL) == (aDirection == eDirPrevious)) { nsIFrame::GetFirstLeaf(framePtr); } else { diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index bab7ce99fa71..1c6fbe7847d4 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -78,6 +78,7 @@ #include "mozilla/gfx/2D.h" #include "mozilla/gfx/CompositorHitTestInfo.h" #include "mozilla/gfx/MatrixFwd.h" +#include "mozilla/intl/Bidi.h" #include "nsDisplayItemTypes.h" #include "nsPresContext.h" #include "nsTHashSet.h" @@ -359,76 +360,6 @@ class nsReflowStatus final { // Convert nsReflowStatus to a human-readable string. std::ostream& operator<<(std::ostream& aStream, const nsReflowStatus& aStatus); -/** - * nsBidiLevel is the type of the level values in our Unicode Bidi - * implementation. - * It holds an embedding level and indicates the visual direction - * by its bit 0 (even/odd value).

- * - *

  • aParaLevel can be set to the - * pseudo-level values NSBIDI_DEFAULT_LTR - * and NSBIDI_DEFAULT_RTL.
  • - * - * @see nsBidi::SetPara - * - *

    The related constants are not real, valid level values. - * NSBIDI_DEFAULT_XXX can be used to specify - * a default for the paragraph level for - * when the SetPara function - * shall determine it but there is no - * strongly typed character in the input.

    - * - * Note that the value for NSBIDI_DEFAULT_LTR is even - * and the one for NSBIDI_DEFAULT_RTL is odd, - * just like with normal LTR and RTL level values - - * these special values are designed that way. Also, the implementation - * assumes that NSBIDI_MAX_EXPLICIT_LEVEL is odd. - * - * @see NSBIDI_DEFAULT_LTR - * @see NSBIDI_DEFAULT_RTL - * @see NSBIDI_LEVEL_OVERRIDE - * @see NSBIDI_MAX_EXPLICIT_LEVEL - */ -typedef uint8_t nsBidiLevel; - -/** - * Paragraph level setting. - * If there is no strong character, then set the paragraph level to 0 - * (left-to-right). - */ -#define NSBIDI_DEFAULT_LTR 0xfe - -/** - * Paragraph level setting. - * If there is no strong character, then set the paragraph level to 1 - * (right-to-left). - */ -#define NSBIDI_DEFAULT_RTL 0xff - -/** - * Maximum explicit embedding level. - * (The maximum resolved level can be up to - * NSBIDI_MAX_EXPLICIT_LEVEL+1). - */ -#define NSBIDI_MAX_EXPLICIT_LEVEL 125 - -/** Bit flag for level input. - * Overrides directional properties. - */ -#define NSBIDI_LEVEL_OVERRIDE 0x80 - -/** - * nsBidiDirection values indicate the text direction. - */ -enum nsBidiDirection { - /** All left-to-right text This is a 0 value. */ - NSBIDI_LTR, - /** All right-to-left text This is a 1 value. */ - NSBIDI_RTL, - /** Mixed-directional text. */ - NSBIDI_MIXED -}; - namespace mozilla { // https://drafts.csswg.org/css-align-3/#baseline-sharing-group @@ -473,15 +404,16 @@ struct IntrinsicSize { }; // Pseudo bidi embedding level indicating nonexistence. -static const nsBidiLevel kBidiLevelNone = 0xff; +static const mozilla::intl::Bidi::EmbeddingLevel kBidiLevelNone = + mozilla::intl::Bidi::EmbeddingLevel(0xff); struct FrameBidiData { - nsBidiLevel baseLevel; - nsBidiLevel embeddingLevel; + mozilla::intl::Bidi::EmbeddingLevel baseLevel; + mozilla::intl::Bidi::EmbeddingLevel embeddingLevel; // The embedding level of virtual bidi formatting character before // this frame if any. kBidiLevelNone is used to indicate nonexistence // or unnecessity of such virtual character. - nsBidiLevel precedingControl; + mozilla::intl::Bidi::EmbeddingLevel precedingControl; }; } // namespace mozilla @@ -1398,9 +1330,13 @@ class nsIFrame : public nsQueryFrame { return bidiData; } - nsBidiLevel GetBaseLevel() const { return GetBidiData().baseLevel; } + mozilla::intl::Bidi::EmbeddingLevel GetBaseLevel() const { + return GetBidiData().baseLevel; + } - nsBidiLevel GetEmbeddingLevel() const { return GetBidiData().embeddingLevel; } + mozilla::intl::Bidi::EmbeddingLevel GetEmbeddingLevel() const { + return GetBidiData().embeddingLevel; + } /** * Return the distance between the border edge of the frame and the diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index 6f9eab3f8a36..d7703eb69e7e 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -12,6 +12,7 @@ #include "gfx2DGlue.h" #include "gfxContext.h" #include "gfxUtils.h" +#include "mozilla/intl/Bidi.h" #include "mozilla/ComputedStyle.h" #include "mozilla/DebugOnly.h" #include "mozilla/Encoding.h" @@ -1434,31 +1435,31 @@ void nsImageFrame::DisplayAltText(nsPresContext* aPresContext, nsresult rv = NS_ERROR_FAILURE; if (aPresContext->BidiEnabled()) { - nsBidiDirection dir; + mozilla::intl::Bidi::EmbeddingLevel level; nscoord x, y; if (isVertical) { x = pt.x + maxDescent; if (wm.IsBidiLTR()) { y = aRect.y; - dir = NSBIDI_LTR; + level = mozilla::intl::Bidi::EmbeddingLevel::LTR(); } else { y = aRect.YMost() - strWidth; - dir = NSBIDI_RTL; + level = mozilla::intl::Bidi::EmbeddingLevel::RTL(); } } else { y = pt.y + maxAscent; if (wm.IsBidiLTR()) { x = aRect.x; - dir = NSBIDI_LTR; + level = mozilla::intl::Bidi::EmbeddingLevel::LTR(); } else { x = aRect.XMost() - strWidth; - dir = NSBIDI_RTL; + level = mozilla::intl::Bidi::EmbeddingLevel::RTL(); } } rv = nsBidiPresUtils::RenderText( - str, maxFit, dir, aPresContext, aRenderingContext, + str, maxFit, level, aPresContext, aRenderingContext, aRenderingContext.GetDrawTarget(), *fm, x, y); } if (NS_FAILED(rv)) { diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index 206df8ac397d..1e21933e0a4a 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -69,6 +69,7 @@ #include "nsContentUtils.h" #include "nsLineBreaker.h" #include "nsIFrameInlines.h" +#include "mozilla/intl/Bidi.h" #include "mozilla/intl/WordBreaker.h" #include "mozilla/ServoStyleSet.h" @@ -1935,7 +1936,7 @@ bool BuildTextRunsScanner::ContinueTextRunAcrossFrames(nsTextFrame* aFrame1, Side side2 = wm.PhysicalSide(eLogicalSideIStart); // If the frames have an embedding level that is opposite to the writing // mode, we need to swap which sides we're checking. - if (IS_LEVEL_RTL(aFrame1->GetEmbeddingLevel()) == wm.IsBidiLTR()) { + if (aFrame1->GetEmbeddingLevel().IsRTL() == wm.IsBidiLTR()) { std::swap(side1, side2); } @@ -2396,7 +2397,7 @@ already_AddRefed BuildTextRunsScanner::BuildTextRunForFrames( if (flags2 & nsTextFrameUtils::Flags::HasShy) { flags |= gfx::ShapedTextFlags::TEXT_ENABLE_HYPHEN_BREAKS; } - if (mBidiEnabled && (IS_LEVEL_RTL(firstFrame->GetEmbeddingLevel()))) { + if (mBidiEnabled && (firstFrame->GetEmbeddingLevel().IsRTL())) { flags |= gfx::ShapedTextFlags::TEXT_IS_RTL; } if (mNextRunContextInfo & nsTextFrameUtils::INCOMING_WHITESPACE) { diff --git a/layout/xul/nsTextBoxFrame.cpp b/layout/xul/nsTextBoxFrame.cpp index 9970d2f72c12..2418e3597ae2 100644 --- a/layout/xul/nsTextBoxFrame.cpp +++ b/layout/xul/nsTextBoxFrame.cpp @@ -8,6 +8,7 @@ #include "gfx2DGlue.h" #include "gfxUtils.h" +#include "mozilla/intl/Bidi.h" #include "mozilla/Attributes.h" #include "mozilla/ComputedStyle.h" #include "mozilla/Preferences.h" @@ -484,7 +485,8 @@ void nsTextBoxFrame::DrawText(gfxContext& aRenderingContext, if (mState & NS_FRAME_IS_BIDI) { presContext->SetBidiEnabled(); - nsBidiLevel level = nsBidiPresUtils::BidiLevelFromStyle(Style()); + mozilla::intl::Bidi::EmbeddingLevel level = + nsBidiPresUtils::BidiLevelFromStyle(Style()); if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) { // We let the RenderText function calculate the mnemonic's // underline position for us.