Backed out 3 changesets (bug 1719546) for causing SM bustages at Bidi.h. CLOSED TREE

Backed out changeset c4d6ffc7e445 (bug 1719546)
Backed out changeset a1f7ed6c4251 (bug 1719546)
Backed out changeset e69fc596f2c3 (bug 1719546)
This commit is contained in:
Butkovits Atila
2021-10-19 21:09:47 +03:00
parent 0cea1606ce
commit b4ce43ec95
31 changed files with 590 additions and 1014 deletions

View File

@@ -9,7 +9,6 @@
*/
#include "mozilla/dom/Selection.h"
#include "mozilla/intl/Bidi.h"
#include "mozilla/AccessibleCaretEventHub.h"
#include "mozilla/AsyncEventDispatcher.h"
@@ -386,9 +385,7 @@ Nullable<int16_t> Selection::GetCaretBidiLevel(
aRv.Throw(NS_ERROR_NOT_INITIALIZED);
return Nullable<int16_t>();
}
mozilla::intl::Bidi::EmbeddingLevel caretBidiLevel =
static_cast<mozilla::intl::Bidi::EmbeddingLevel>(
mFrameSelection->GetCaretBidiLevel());
nsBidiLevel caretBidiLevel = mFrameSelection->GetCaretBidiLevel();
return (caretBidiLevel & BIDI_LEVEL_UNDEFINED)
? Nullable<int16_t>()
: Nullable<int16_t>(caretBidiLevel);
@@ -406,7 +403,7 @@ void Selection::SetCaretBidiLevel(const Nullable<int16_t>& aCaretBidiLevel,
mFrameSelection->UndefineCaretBidiLevel();
} else {
mFrameSelection->SetCaretBidiLevelAndMaybeSchedulePaint(
mozilla::intl::Bidi::EmbeddingLevel(aCaretBidiLevel.Value()));
aCaretBidiLevel.Value());
}
}
@@ -1360,8 +1357,7 @@ nsIFrame* Selection::GetPrimaryOrCaretFrameForNodeOffset(nsIContent* aContent,
CaretAssociationHint hint = mFrameSelection->GetHint();
if (aVisual) {
mozilla::intl::Bidi::EmbeddingLevel caretBidiLevel =
mFrameSelection->GetCaretBidiLevel();
nsBidiLevel caretBidiLevel = mFrameSelection->GetCaretBidiLevel();
return nsCaret::GetCaretFrameForNodeOffset(
mFrameSelection, aContent, aOffset, hint, caretBidiLevel,
@@ -3302,10 +3298,9 @@ 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)) {
mozilla::intl::Bidi::Direction paraDir =
nsBidiPresUtils::ParagraphDirection(frame);
nsBidiDirection paraDir = nsBidiPresUtils::ParagraphDirection(frame);
if (paraDir == mozilla::intl::Bidi::Direction::RTL && visual) {
if (paraDir == NSBIDI_RTL && visual) {
if (amount == eSelectBeginLine) {
amount = eSelectEndLine;
forward = !forward;
@@ -3479,9 +3474,7 @@ nsresult Selection::SelectionLanguageChange(bool aLangRTL) {
RefPtr<nsFrameSelection> frameSelection = mFrameSelection;
// if the direction of the language hasn't changed, nothing to do
mozilla::intl::Bidi::EmbeddingLevel kbdBidiLevel =
aLangRTL ? mozilla::intl::Bidi::EmbeddingLevel::RTL()
: mozilla::intl::Bidi::EmbeddingLevel::LTR();
nsBidiLevel kbdBidiLevel = aLangRTL ? NSBIDI_RTL : NSBIDI_LTR;
if (kbdBidiLevel == frameSelection->mKbdBidiLevel) {
return NS_OK;
}
@@ -3495,12 +3488,12 @@ nsresult Selection::SelectionLanguageChange(bool aLangRTL) {
auto [frameStart, frameEnd] = focusFrame->GetOffsets();
RefPtr<nsPresContext> context = GetPresContext();
mozilla::intl::Bidi::EmbeddingLevel levelBefore, levelAfter;
nsBidiLevel levelBefore, levelAfter;
if (!context) {
return NS_ERROR_FAILURE;
}
mozilla::intl::Bidi::EmbeddingLevel level = focusFrame->GetEmbeddingLevel();
nsBidiLevel level = focusFrame->GetEmbeddingLevel();
int32_t focusOffset = static_cast<int32_t>(FocusOffset());
if ((focusOffset != frameStart) && (focusOffset != frameEnd))
// the cursor is not at a frame boundary, so the level of both the
@@ -3518,31 +3511,27 @@ nsresult Selection::SelectionLanguageChange(bool aLangRTL) {
levelAfter = levels.mLevelAfter;
}
if (levelBefore.IsSameDirection(levelAfter)) {
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)) {
if ((level != levelBefore) && (level != levelAfter))
level = std::min(levelBefore, levelAfter);
}
if (level.IsSameDirection(kbdBidiLevel)) {
if (IS_SAME_DIRECTION(level, kbdBidiLevel))
frameSelection->SetCaretBidiLevelAndMaybeSchedulePaint(level);
} else {
frameSelection->SetCaretBidiLevelAndMaybeSchedulePaint(
mozilla::intl::Bidi::EmbeddingLevel(level + 1));
}
else
frameSelection->SetCaretBidiLevelAndMaybeSchedulePaint(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 (levelBefore.IsSameDirection(kbdBidiLevel)) {
if (IS_SAME_DIRECTION(levelBefore, kbdBidiLevel))
frameSelection->SetCaretBidiLevelAndMaybeSchedulePaint(levelBefore);
} else {
else
frameSelection->SetCaretBidiLevelAndMaybeSchedulePaint(levelAfter);
}
}
// The caret might have moved, so invalidate the desired position
// for future usages of up-arrow or down-arrow

View File

@@ -12,7 +12,6 @@
#include "nsContentUtils.h"
#include "mozilla/intl/Bidi.h"
#include "mozilla/PresShell.h"
#include "mozilla/PresShellInlines.h"
#include "mozilla/SVGImageContext.h"
@@ -3504,11 +3503,11 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor
using ContextState = CanvasRenderingContext2D::ContextState;
virtual void SetText(const char16_t* aText, int32_t aLength,
mozilla::intl::Bidi::Direction aDirection) override {
nsBidiDirection aDirection) override {
mFontgrp->UpdateUserFonts(); // ensure user font generation is current
// adjust flags for current direction run
gfx::ShapedTextFlags flags = mTextRunFlags;
if (aDirection == mozilla::intl::Bidi::Direction::RTL) {
if (aDirection == NSBIDI_RTL) {
flags |= gfx::ShapedTextFlags::TEXT_IS_RTL;
} else {
flags &= ~gfx::ShapedTextFlags::TEXT_IS_RTL;
@@ -3874,9 +3873,7 @@ 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 ? mozilla::intl::Bidi::EmbeddingLevel::RTL()
: mozilla::intl::Bidi::EmbeddingLevel::LTR(),
textToDraw.get(), textToDraw.Length(), isRTL ? NSBIDI_RTL : NSBIDI_LTR,
presShell->GetPresContext(), processor, nsBidiPresUtils::MODE_MEASURE,
nullptr, 0, &totalWidthCoord, &mBidiEngine);
if (aError.Failed()) {
@@ -4017,9 +4014,7 @@ TextMetrics* CanvasRenderingContext2D::DrawOrMeasureText(
processor.mDoMeasureBoundingBox = false;
aError = nsBidiPresUtils::ProcessText(
textToDraw.get(), textToDraw.Length(),
isRTL ? mozilla::intl::Bidi::EmbeddingLevel::RTL()
: mozilla::intl::Bidi::EmbeddingLevel::LTR(),
textToDraw.get(), textToDraw.Length(), isRTL ? NSBIDI_RTL : NSBIDI_LTR,
presShell->GetPresContext(), processor, nsBidiPresUtils::MODE_DRAW,
nullptr, 0, nullptr, &mBidiEngine);

View File

@@ -9,7 +9,6 @@
#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"
@@ -20,8 +19,8 @@
#include "FilterDescription.h"
#include "gfx2DGlue.h"
#include "nsICanvasRenderingContextInternal.h"
#include "nsBidi.h"
#include "nsColor.h"
#include "nsIFrame.h"
class gfxFontGroup;
class nsGlobalWindowInner;
@@ -798,7 +797,7 @@ class CanvasRenderingContext2D final : public nsICanvasRenderingContextInternal,
nsTArray<RegionInfo> mHitRegionsOptions;
mozilla::intl::Bidi mBidiEngine;
nsBidi mBidiEngine;
/**
* Returns true if a shadow should be drawn along with a

View File

@@ -26,7 +26,6 @@
#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
@@ -5768,13 +5767,12 @@ EditorBase::AutoCaretBidiLevelManager::AutoCaretBidiLevelManager(
nsPrevNextBidiLevels levels = frameSelection->GetPrevNextBidiLevels(
aPointAtCaret.GetContainerAsContent(), aPointAtCaret.Offset(), true);
mozilla::intl::Bidi::EmbeddingLevel levelBefore = levels.mLevelBefore;
mozilla::intl::Bidi::EmbeddingLevel levelAfter = levels.mLevelAfter;
nsBidiLevel levelBefore = levels.mLevelBefore;
nsBidiLevel levelAfter = levels.mLevelAfter;
mozilla::intl::Bidi::EmbeddingLevel currentCaretLevel =
frameSelection->GetCaretBidiLevel();
nsBidiLevel currentCaretLevel = frameSelection->GetCaretBidiLevel();
mozilla::intl::Bidi::EmbeddingLevel levelOfDeletion;
nsBidiLevel levelOfDeletion;
levelOfDeletion = (nsIEditor::eNext == aDirectionAndAmount ||
nsIEditor::eNextWord == aDirectionAndAmount)
? levelAfter

View File

@@ -6,7 +6,6 @@
#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
@@ -29,6 +28,7 @@
#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<mozilla::intl::Bidi::EmbeddingLevel> mNewCaretBidiLevel;
Maybe<nsBidiLevel> mNewCaretBidiLevel;
bool mFailed = false;
bool mCanceled = false;
};

View File

@@ -1,278 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gtest/gtest.h"
#include "mozilla/intl/Bidi.h"
#include "mozilla/Span.h"
namespace mozilla::intl {
struct VisualRun {
Span<const char16_t> string;
Bidi::Direction direction;
};
/**
* An iterator for visual runs in a paragraph. See Bug 1736597 for integrating
* this into the public API.
*/
class MOZ_STACK_CLASS VisualRunIter {
public:
VisualRunIter(Bidi& aBidi, Span<const char16_t> aParagraph,
Bidi::EmbeddingLevel aLevel)
: mBidi(aBidi), mParagraph(aParagraph) {
// Crash in case of errors by calling unwrap. If this were a real API, this
// would be a TryCreate call.
mBidi.SetParagraph(aParagraph, aLevel).unwrap();
mRunCount = mBidi.CountRuns().unwrap();
}
Maybe<VisualRun> Next() {
if (mRunIndex >= mRunCount) {
return Nothing();
}
int32_t stringIndex = -1;
int32_t stringLength = -1;
Bidi::Direction direction =
mBidi.GetVisualRun(mRunIndex, &stringIndex, &stringLength);
Span<const char16_t> string(mParagraph.Elements() + stringIndex,
stringLength);
mRunIndex++;
return Some(VisualRun{string, direction});
}
private:
Bidi& mBidi;
Span<const char16_t> mParagraph = Span<const char16_t>();
int32_t mRunIndex = 0;
int32_t mRunCount = 0;
};
struct LogicalRun {
Span<const char16_t> string;
Bidi::EmbeddingLevel embeddingLevel;
};
/**
* An iterator for logical runs in a paragraph. See Bug 1736597 for integrating
* this into the public API.
*/
class MOZ_STACK_CLASS LogicalRunIter {
public:
LogicalRunIter(Bidi& aBidi, Span<const char16_t> aParagraph,
Bidi::EmbeddingLevel aLevel)
: mBidi(aBidi), mParagraph(aParagraph) {
// Crash in case of errors by calling unwrap. If this were a real API, this
// would be a TryCreate call.
mBidi.SetParagraph(aParagraph, aLevel).unwrap();
mBidi.CountRuns().unwrap();
}
Maybe<LogicalRun> Next() {
if (mRunIndex >= static_cast<int32_t>(mParagraph.Length())) {
return Nothing();
}
int32_t logicalLimit;
Bidi::EmbeddingLevel embeddingLevel;
mBidi.GetLogicalRun(mRunIndex, &logicalLimit, &embeddingLevel);
Span<const char16_t> string(mParagraph.Elements() + mRunIndex,
logicalLimit - mRunIndex);
mRunIndex = logicalLimit;
return Some(LogicalRun{string, embeddingLevel});
}
private:
Bidi& mBidi;
Span<const char16_t> mParagraph = Span<const char16_t>();
int32_t mRunIndex = 0;
};
TEST(IntlBidi, SimpleLTR)
{
Bidi bidi{};
LogicalRunIter logicalRunIter(bidi, MakeStringSpan(u"this is a paragraph"),
Bidi::EmbeddingLevel::DefaultLTR());
ASSERT_EQ(bidi.GetParagraphEmbeddingLevel(), 0);
ASSERT_EQ(bidi.GetParagraphDirection(), Bidi::ParagraphDirection::LTR);
{
auto logicalRun = logicalRunIter.Next();
ASSERT_TRUE(logicalRun.isSome());
ASSERT_EQ(logicalRun->string, MakeStringSpan(u"this is a paragraph"));
ASSERT_EQ(logicalRun->embeddingLevel, 0);
ASSERT_EQ(logicalRun->embeddingLevel.Direction(), Bidi::Direction::LTR);
}
{
auto logicalRun = logicalRunIter.Next();
ASSERT_TRUE(logicalRun.isNothing());
}
}
TEST(IntlBidi, SimpleRTL)
{
Bidi bidi{};
LogicalRunIter logicalRunIter(bidi, MakeStringSpan(u"فايرفوكس رائع"),
Bidi::EmbeddingLevel::DefaultLTR());
ASSERT_EQ(bidi.GetParagraphEmbeddingLevel(), 1);
ASSERT_EQ(bidi.GetParagraphDirection(), Bidi::ParagraphDirection::RTL);
{
auto logicalRun = logicalRunIter.Next();
ASSERT_TRUE(logicalRun.isSome());
ASSERT_EQ(logicalRun->string, MakeStringSpan(u"فايرفوكس رائع"));
ASSERT_EQ(logicalRun->embeddingLevel.Direction(), Bidi::Direction::RTL);
ASSERT_EQ(logicalRun->embeddingLevel, 1);
}
{
auto logicalRun = logicalRunIter.Next();
ASSERT_TRUE(logicalRun.isNothing());
}
}
TEST(IntlBidi, MultiLevel)
{
Bidi bidi{};
LogicalRunIter logicalRunIter(
bidi, MakeStringSpan(u"Firefox is awesome: رائع Firefox"),
Bidi::EmbeddingLevel::DefaultLTR());
ASSERT_EQ(bidi.GetParagraphEmbeddingLevel(), 0);
ASSERT_EQ(bidi.GetParagraphDirection(), Bidi::ParagraphDirection::Mixed);
{
auto logicalRun = logicalRunIter.Next();
ASSERT_TRUE(logicalRun.isSome());
ASSERT_EQ(logicalRun->string, MakeStringSpan(u"Firefox is awesome: "));
ASSERT_EQ(logicalRun->embeddingLevel, 0);
}
{
auto logicalRun = logicalRunIter.Next();
ASSERT_TRUE(logicalRun.isSome());
ASSERT_EQ(logicalRun->string, MakeStringSpan(u"رائع"));
ASSERT_EQ(logicalRun->embeddingLevel, 1);
}
{
auto logicalRun = logicalRunIter.Next();
ASSERT_TRUE(logicalRun.isSome());
ASSERT_EQ(logicalRun->string, MakeStringSpan(u" Firefox"));
ASSERT_EQ(logicalRun->embeddingLevel, 0);
}
{
auto logicalRun = logicalRunIter.Next();
ASSERT_TRUE(logicalRun.isNothing());
}
}
TEST(IntlBidi, RtlOverride)
{
Bidi bidi{};
// Set the paragraph using the RTL embedding mark U+202B, and the LTR
// embedding mark U+202A to increase the embedding level. This mark switches
// the weakly directional character "_". This demonstrates that embedding
// levels can be computed.
LogicalRunIter logicalRunIter(
bidi, MakeStringSpan(u"ltr\u202b___رائع___\u202a___ltr__"),
Bidi::EmbeddingLevel::DefaultLTR());
ASSERT_EQ(bidi.GetParagraphEmbeddingLevel(), 0);
ASSERT_EQ(bidi.GetParagraphDirection(), Bidi::ParagraphDirection::Mixed);
{
auto logicalRun = logicalRunIter.Next();
ASSERT_TRUE(logicalRun.isSome());
ASSERT_EQ(logicalRun->string, MakeStringSpan(u"ltr"));
ASSERT_EQ(logicalRun->embeddingLevel, 0);
ASSERT_EQ(logicalRun->embeddingLevel.Direction(), Bidi::Direction::LTR);
}
{
auto logicalRun = logicalRunIter.Next();
ASSERT_TRUE(logicalRun.isSome());
ASSERT_EQ(logicalRun->string, MakeStringSpan(u"\u202b___رائع___"));
ASSERT_EQ(logicalRun->embeddingLevel, 1);
ASSERT_EQ(logicalRun->embeddingLevel.Direction(), Bidi::Direction::RTL);
}
{
auto logicalRun = logicalRunIter.Next();
ASSERT_TRUE(logicalRun.isSome());
ASSERT_EQ(logicalRun->string, MakeStringSpan(u"\u202a___ltr__"));
ASSERT_EQ(logicalRun->embeddingLevel, 2);
ASSERT_EQ(logicalRun->embeddingLevel.Direction(), Bidi::Direction::LTR);
}
{
auto logicalRun = logicalRunIter.Next();
ASSERT_TRUE(logicalRun.isNothing());
}
}
TEST(IntlBidi, VisualRuns)
{
Bidi bidi{};
VisualRunIter visualRunIter(
bidi,
MakeStringSpan(
u"first visual run التشغيل البصري الثاني third visual run"),
Bidi::EmbeddingLevel::DefaultLTR());
{
Maybe<VisualRun> run = visualRunIter.Next();
ASSERT_TRUE(run.isSome());
ASSERT_EQ(run->string, MakeStringSpan(u"first visual run "));
ASSERT_EQ(run->direction, Bidi::Direction::LTR);
}
{
Maybe<VisualRun> run = visualRunIter.Next();
ASSERT_TRUE(run.isSome());
ASSERT_EQ(run->string, MakeStringSpan(u"التشغيل البصري الثاني"));
ASSERT_EQ(run->direction, Bidi::Direction::RTL);
}
{
Maybe<VisualRun> run = visualRunIter.Next();
ASSERT_TRUE(run.isSome());
ASSERT_EQ(run->string, MakeStringSpan(u" third visual run"));
ASSERT_EQ(run->direction, Bidi::Direction::LTR);
}
{
Maybe<VisualRun> run = visualRunIter.Next();
ASSERT_TRUE(run.isNothing());
}
}
TEST(IntlBidi, VisualRunsWithEmbeds)
{
// Compare this test to the logical order test.
Bidi bidi{};
VisualRunIter visualRunIter(
bidi, MakeStringSpan(u"ltr\u202b___رائع___\u202a___ltr___"),
Bidi::EmbeddingLevel::DefaultLTR());
{
Maybe<VisualRun> run = visualRunIter.Next();
ASSERT_TRUE(run.isSome());
ASSERT_EQ(run->string, MakeStringSpan(u"ltr"));
ASSERT_EQ(run->direction, Bidi::Direction::LTR);
}
{
Maybe<VisualRun> run = visualRunIter.Next();
ASSERT_TRUE(run.isSome());
ASSERT_EQ(run->string, MakeStringSpan(u"\u202a___ltr___"));
ASSERT_EQ(run->direction, Bidi::Direction::LTR);
}
{
Maybe<VisualRun> run = visualRunIter.Next();
ASSERT_TRUE(run.isSome());
ASSERT_EQ(run->string, MakeStringSpan(u"\u202b___رائع___"));
ASSERT_EQ(run->direction, Bidi::Direction::RTL);
}
{
Maybe<VisualRun> run = visualRunIter.Next();
ASSERT_TRUE(run.isNothing());
}
}
} // namespace mozilla::intl

View File

@@ -5,7 +5,6 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
UNIFIED_SOURCES += [
"TestBidi.cpp",
"TestCalendar.cpp",
"TestCollator.cpp",
"TestCurrency.cpp",

View File

@@ -4,7 +4,6 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXPORTS.mozilla.intl = [
"src/Bidi.h",
"src/Calendar.h",
"src/Collator.h",
"src/Currency.h",
@@ -28,7 +27,6 @@ EXPORTS.mozilla.intl = [
]
UNIFIED_SOURCES += [
"src/Bidi.cpp",
"src/Calendar.cpp",
"src/Collator.cpp",
"src/Currency.cpp",

View File

@@ -1,163 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/intl/Bidi.h"
#include "mozilla/Casting.h"
#include "mozilla/intl/ICU4CGlue.h"
#include "unicode/ubidi.h"
namespace mozilla::intl {
Bidi::Bidi() { mBidi = ubidi_open(); }
Bidi::~Bidi() { ubidi_close(mBidi.GetMut()); }
ICUResult Bidi::SetParagraph(Span<const char16_t> aParagraph,
Bidi::EmbeddingLevel aLevel) {
// Do not allow any reordering of the runs, as this can change the
// performance characteristics of working with runs. In the default mode,
// the levels can be iterated over directly, rather than relying on computing
// logical runs on the fly. This can have negative performance characteristics
// compared to iterating over the levels.
//
// In the UBIDI_REORDER_RUNS_ONLY the levels are encoded with additional
// information which can be safely ignored in this Bidi implementation.
// Note that this check is here since setting the mode must be done before
// calls to setting the paragraph.
MOZ_ASSERT(ubidi_getReorderingMode(mBidi.GetMut()) == UBIDI_REORDER_DEFAULT);
UErrorCode status = U_ZERO_ERROR;
ubidi_setPara(mBidi.GetMut(), aParagraph.Elements(),
AssertedCast<int32_t>(aParagraph.Length()), aLevel, nullptr,
&status);
mLevels = nullptr;
return ToICUResult(status);
}
Bidi::ParagraphDirection Bidi::GetParagraphDirection() const {
switch (ubidi_getDirection(mBidi.GetConst())) {
case UBIDI_LTR:
return Bidi::ParagraphDirection::LTR;
case UBIDI_RTL:
return Bidi::ParagraphDirection::RTL;
case UBIDI_MIXED:
return Bidi::ParagraphDirection::Mixed;
case UBIDI_NEUTRAL:
// This is only used in `ubidi_getBaseDirection` which is unused in this
// API.
MOZ_ASSERT_UNREACHABLE("Unexpected UBiDiDirection value.");
};
return Bidi::ParagraphDirection::Mixed;
}
/* static */
void Bidi::ReorderVisual(const EmbeddingLevel* aLevels, int32_t aLength,
int32_t* aIndexMap) {
ubidi_reorderVisual(reinterpret_cast<const uint8_t*>(aLevels), aLength,
aIndexMap);
}
static Bidi::Direction ToBidiDirection(UBiDiDirection aDirection) {
switch (aDirection) {
case UBIDI_LTR:
return Bidi::Direction::LTR;
case UBIDI_RTL:
return Bidi::Direction::RTL;
case UBIDI_MIXED:
case UBIDI_NEUTRAL:
MOZ_ASSERT_UNREACHABLE("Unexpected UBiDiDirection value.");
}
return Bidi::Direction::LTR;
}
Result<int32_t, ICUError> Bidi::CountRuns() {
UErrorCode status = U_ZERO_ERROR;
int32_t runCount = ubidi_countRuns(mBidi.GetMut(), &status);
if (U_FAILURE(status)) {
return Err(ToICUError(status));
}
mLength = ubidi_getProcessedLength(mBidi.GetConst());
mLevels = mLength > 0 ? reinterpret_cast<const Bidi::EmbeddingLevel*>(
ubidi_getLevels(mBidi.GetMut(), &status))
: nullptr;
if (U_FAILURE(status)) {
return Err(ToICUError(status));
}
return runCount;
}
void Bidi::GetLogicalRun(int32_t aLogicalStart, int32_t* aLogicalLimitOut,
Bidi::EmbeddingLevel* aLevelOut) {
MOZ_ASSERT(mLevels, "CountRuns hasn't been run?");
MOZ_RELEASE_ASSERT(aLogicalStart < mLength, "Out of bound");
EmbeddingLevel level = mLevels[aLogicalStart];
int32_t limit;
for (limit = aLogicalStart + 1; limit < mLength; limit++) {
if (mLevels[limit] != level) {
break;
}
}
*aLogicalLimitOut = limit;
*aLevelOut = level;
}
bool Bidi::EmbeddingLevel::IsDefaultLTR() const {
return mValue == UBIDI_DEFAULT_LTR;
};
bool Bidi::EmbeddingLevel::IsDefaultRTL() const {
return mValue == UBIDI_DEFAULT_RTL;
};
bool Bidi::EmbeddingLevel::IsRTL() const {
// If the least significant bit is 1, then the embedding level
// is right-to-left.
// If the least significant bit is 0, then the embedding level
// is left-to-right.
return (mValue & 0x1) == 1;
};
bool Bidi::EmbeddingLevel::IsLTR() const { return !IsRTL(); };
bool Bidi::EmbeddingLevel::IsSameDirection(EmbeddingLevel aOther) const {
return (((mValue ^ aOther) & 1) == 0);
}
Bidi::EmbeddingLevel Bidi::EmbeddingLevel::LTR() {
return Bidi::EmbeddingLevel(0);
};
Bidi::EmbeddingLevel Bidi::EmbeddingLevel::RTL() {
return Bidi::EmbeddingLevel(1);
};
Bidi::EmbeddingLevel Bidi::EmbeddingLevel::DefaultLTR() {
return Bidi::EmbeddingLevel(UBIDI_DEFAULT_LTR);
};
Bidi::EmbeddingLevel Bidi::EmbeddingLevel::DefaultRTL() {
return Bidi::EmbeddingLevel(UBIDI_DEFAULT_RTL);
};
Bidi::Direction Bidi::EmbeddingLevel::Direction() {
return IsRTL() ? Direction::RTL : Direction::LTR;
};
uint8_t Bidi::EmbeddingLevel::Value() const { return mValue; }
Bidi::EmbeddingLevel Bidi::GetParagraphEmbeddingLevel() const {
return Bidi::EmbeddingLevel(ubidi_getParaLevel(mBidi.GetConst()));
}
Bidi::Direction Bidi::GetVisualRun(int32_t aRunIndex, int32_t* aLogicalStart,
int32_t* aLength) {
return ToBidiDirection(
ubidi_getVisualRun(mBidi.GetMut(), aRunIndex, aLogicalStart, aLength));
}
} // namespace mozilla::intl

View File

@@ -1,241 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef intl_components_Bidi_h_
#define intl_components_Bidi_h_
#include "mozilla/intl/ICU4CGlue.h"
struct UBiDi;
namespace mozilla::intl {
/**
* This component is a Mozilla-focused API for working with bidirectional (bidi)
* text. Text is commonly displayed left to right (LTR), especially for
* Latin-based alphabets. However, languages like Arabic and Hebrew displays
* text right to left (RTL). When displaying text, LTR and RTL text can be
* combined together in the same paragraph. This class gives tools for working
* with unidirectional, and mixed direction paragraphs.
*
* See the Unicode Bidirectional Algorithm document for implementation details:
* https://unicode.org/reports/tr9/
*/
class Bidi final {
public:
Bidi();
~Bidi();
// Not copyable or movable
Bidi(const Bidi&) = delete;
Bidi& operator=(const Bidi&) = delete;
/**
* This enum unambiguously classifies text runs as either being left to right,
* or right to left.
*/
enum class Direction : uint8_t {
// Left to right text.
LTR = 0,
// Right to left text.
RTL = 1,
};
/**
* This enum indicates the text direction for the set paragraph. Some
* paragraphs are unidirectional, where they only have one direction, or a
* paragraph could use both LTR and RTL. In this case the paragraph's
* direction would be mixed.
*/
enum ParagraphDirection { LTR, RTL, Mixed };
/**
* Embedding levels are numbers that indicate how deeply the bidi text is
* embedded, and the direction of text on that embedding level. When switching
* between strongly LTR code points and strongly RTL code points the embedding
* level normally switches between an embedding level of 0 (LTR) and 1 (RTL).
* The only time the embedding level increases is if the embedding code points
* are used. This is the Left-to-Right Embedding (LRE) code point (U+202A), or
* the Right-to-Left Embedding (RLE) code point (U+202B). The minimum
* embedding level of text is zero, and the maximum explicit depth is 125.
*
* The most significant bit is reserved for additional meaning. It can be used
* to signify in certain APIs that the text should by default be LTR or RTL if
* no strongly directional code points are found.
*
* Bug 1736595: At the time of this writing, some places in Gecko code use a 1
* in the most significant bit to indicate that an embedding level has not
* been set. This leads to an ambiguous understanding of what the most
* significant bit actually means.
*/
class EmbeddingLevel {
public:
explicit EmbeddingLevel(uint8_t aValue) : mValue(aValue) {}
explicit EmbeddingLevel(int aValue)
: mValue(static_cast<uint8_t>(aValue)) {}
EmbeddingLevel() = default;
// Enable the copy operators, but disable move as this is only a uint8_t.
EmbeddingLevel(const EmbeddingLevel& other) = default;
EmbeddingLevel& operator=(const EmbeddingLevel& other) = default;
/**
* Determine the direction of the embedding level by looking at the least
* significant bit. If it is 0, then it is LTR. If it is 1, then it is RTL.
*/
Direction Direction();
/**
* Create a left-to-right embedding level.
*/
static EmbeddingLevel LTR();
/**
* Create an right-to-left embedding level.
*/
static EmbeddingLevel RTL();
/**
* When passed into `SetParagraph`, the direction is determined by first
* strongly directional character, with the default set to left-to-right if
* none is found.
*
* This is encoded with the highest bit set to 1.
*/
static EmbeddingLevel DefaultLTR();
/**
* When passed into `SetParagraph`, the direction is determined by first
* strongly directional character, with the default set to right-to-left if
* none is found.
*
* * This is encoded with the highest and lowest bits set to 1.
*/
static EmbeddingLevel DefaultRTL();
bool IsDefaultLTR() const;
bool IsDefaultRTL() const;
bool IsLTR() const;
bool IsRTL() const;
bool IsSameDirection(EmbeddingLevel aOther) const;
/**
* Get the underlying value as a uint8_t.
*/
uint8_t Value() const;
/**
* Implicitly convert to the underlying value.
*/
operator uint8_t() const { return mValue; }
private:
uint8_t mValue = 0;
};
/**
* Set the current paragraph of text to analyze for its bidi properties. This
* performs the Unicode bidi algorithm as specified by:
* https://unicode.org/reports/tr9/
*
* After setting the text, the other getter methods can be used to find out
* the directionality of the paragraph text.
*/
ICUResult SetParagraph(Span<const char16_t> aParagraph,
EmbeddingLevel aLevel);
/**
* Get the embedding level for the paragraph that was set by SetParagraph.
*/
EmbeddingLevel GetParagraphEmbeddingLevel() const;
/**
* Get the directionality of the paragraph text that was set by SetParagraph.
*/
ParagraphDirection GetParagraphDirection() const;
/**
* Get the number of runs. This function may invoke the actual reordering on
* the Bidi object, after SetParagraph may have resolved only the levels of
* the text. Therefore, `CountRuns` may have to allocate memory, and may fail
* doing so.
*/
Result<int32_t, ICUError> CountRuns();
/**
* Get the next logical run. The logical runs are a run of text that has the
* same directionality and embedding level. These runs are in memory order,
* and not in display order.
*
* Important! `Bidi::CountRuns` must be called before calling this method.
*
* @param aLogicalStart is the offset into the paragraph text that marks the
* logical start of the text.
* @param aLogicalLimitOut is an out param that is the length of the string
* that makes up the logical run.
* @param aLevelOut is an out parameter that returns the embedding level for
* the run
*/
void GetLogicalRun(int32_t aLogicalStart, int32_t* aLogicalLimitOut,
EmbeddingLevel* aLevelOut);
/**
* This is a convenience function that does not use the ICU Bidi object.
* It is intended to be used for when an application has determined the
* embedding levels of objects (character sequences) and just needs to have
* them reordered (L2).
*
* @param aLevels is an array with `aLength` levels that have been
* determined by the application.
*
* @param aLength is the number of levels in the array, or, semantically,
* the number of objects to be reordered. It must be greater than 0.
*
* @param aIndexMap is a pointer to an array of `aLength`
* indexes which will reflect the reordering of the characters.
* The array does not need to be initialized.
* The index map will result in
* `aIndexMap[aVisualIndex]==aLogicalIndex`.
*/
static void ReorderVisual(const EmbeddingLevel* aLevels, int32_t aLength,
int32_t* aIndexMap);
/**
* Get one run's logical start, length, and directionality. In an RTL run, the
* character at the logical start is visually on the right of the displayed
* run. The length is the number of characters in the run.
* `Bidi::CountRuns` should be called before the runs are retrieved.
*
* @param aRunIndex is the number of the run in visual order, in the
* range `[0..CountRuns-1]`.
*
* @param aLogicalStart is the first logical character index in the text.
* The pointer may be `nullptr` if this index is not needed.
*
* @param aLength is the number of characters (at least one) in the run.
* The pointer may be `nullptr` if this is not needed.
*
* Note that in right-to-left runs, the code places modifier letters before
* base characters and second surrogates before first ones.
*/
Direction GetVisualRun(int32_t aRunIndex, int32_t* aLogicalStart,
int32_t* aLength);
private:
ICUPointer<UBiDi> mBidi = ICUPointer<UBiDi>(nullptr);
/**
* An array of levels that is the same length as the paragraph from
* `Bidi::SetParagraph`.
*/
const EmbeddingLevel* mLevels = nullptr;
/**
* The length of the paragraph from `Bidi::SetParagraph`.
*/
int32_t mLength = 0;
};
} // namespace mozilla::intl
#endif

View File

@@ -51,6 +51,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
*/

View File

@@ -39,6 +39,7 @@ EXPORTS += [
"LayoutLogging.h",
"MobileViewportManager.h",
"nsAutoLayoutPhase.h",
"nsBidi.h",
"nsBidiPresUtils.h",
"nsCaret.h",
"nsChangeHint.h",
@@ -108,6 +109,7 @@ UNIFIED_SOURCES += [
"LayoutTelemetryTools.cpp",
"MobileViewportManager.cpp",
"MotionPathUtils.cpp",
"nsBidi.cpp",
"nsBidiPresUtils.cpp",
"nsCaret.cpp",
"nsCounterManager.cpp",

42
layout/base/nsBidi.cpp Normal file
View File

@@ -0,0 +1,42 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsBidi.h"
nsresult nsBidi::CountRuns(int32_t* aRunCount) {
UErrorCode errorCode = U_ZERO_ERROR;
*aRunCount = ubidi_countRuns(mBiDi, &errorCode);
if (U_SUCCESS(errorCode)) {
mLength = ubidi_getProcessedLength(mBiDi);
mLevels = mLength > 0 ? ubidi_getLevels(mBiDi, &errorCode) : nullptr;
}
return ICUUtils::UErrorToNsResult(errorCode);
}
void nsBidi::GetLogicalRun(int32_t aLogicalStart, int32_t* aLogicalLimit,
nsBidiLevel* aLevel) {
MOZ_ASSERT(mLevels, "CountRuns hasn't been run?");
MOZ_RELEASE_ASSERT(aLogicalStart < mLength, "Out of bound");
// This function implements an alternative approach to get logical
// run that is based on levels of characters, which would avoid O(n^2)
// performance issue when used in a loop over runs.
// Per comment in ubidi_getLogicalRun, that function doesn't use this
// approach because levels have special interpretation when reordering
// mode is UBIDI_REORDER_RUNS_ONLY. Since we don't use this mode in
// Gecko, it should be safe to just use levels for this function.
MOZ_ASSERT(ubidi_getReorderingMode(mBiDi) != UBIDI_REORDER_RUNS_ONLY,
"Don't support UBIDI_REORDER_RUNS_ONLY mode");
nsBidiLevel level = mLevels[aLogicalStart];
int32_t limit;
for (limit = aLogicalStart + 1; limit < mLength; limit++) {
if (mLevels[limit] != level) {
break;
}
}
*aLogicalLimit = limit;
*aLevel = level;
}

208
layout/base/nsBidi.h Normal file
View File

@@ -0,0 +1,208 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsBidi_h__
#define nsBidi_h__
#include "unicode/ubidi.h"
#include "ICUUtils.h"
#include "nsIFrame.h" // for nsBidiLevel/nsBidiDirection declarations
// nsBidi implemented as a simple wrapper around the bidi reordering engine
// from ICU.
// We could eliminate this and let callers use the ICU functions directly
// once we no longer care about building without ICU available.
class nsBidi {
public:
/** @brief Default constructor.
*
* The nsBidi object is initially empty. It is assigned
* the Bidi properties of a paragraph by <code>SetPara()</code>.
*/
nsBidi() { mBiDi = ubidi_open(); }
/** @brief Destructor. */
~nsBidi() { ubidi_close(mBiDi); }
/**
* Perform the Unicode Bidi algorithm.
*
* @param aText is a pointer to the single-paragraph text that the
* Bidi algorithm will be performed on
* (step (P1) of the algorithm is performed externally).
* <strong>The text must be (at least) <code>aLength</code> long.
* </strong>
*
* @param aLength is the length of the text; if <code>aLength==-1</code> then
* the text must be zero-terminated.
*
* @param aParaLevel specifies the default level for the paragraph;
* it is typically 0 (LTR) or 1 (RTL).
* If the function shall determine the paragraph level from the text,
* then <code>aParaLevel</code> can be set to
* either <code>NSBIDI_DEFAULT_LTR</code>
* or <code>NSBIDI_DEFAULT_RTL</code>;
* if there is no strongly typed character, then
* the desired default is used (0 for LTR or 1 for RTL).
* Any other value between 0 and <code>NSBIDI_MAX_EXPLICIT_LEVEL</code>
* is also valid, with odd levels indicating RTL.
*/
nsresult SetPara(const char16_t* aText, int32_t aLength,
nsBidiLevel aParaLevel) {
UErrorCode error = U_ZERO_ERROR;
ubidi_setPara(mBiDi, reinterpret_cast<const UChar*>(aText), aLength,
aParaLevel, nullptr, &error);
return ICUUtils::UErrorToNsResult(error);
}
/**
* Get the directionality of the text.
*
* @param aDirection receives a <code>NSBIDI_XXX</code> value that indicates
* if the entire text represented by this object is unidirectional,
* and which direction, or if it is mixed-directional.
*
* @see nsBidiDirection
*/
nsBidiDirection GetDirection() {
return nsBidiDirection(ubidi_getDirection(mBiDi));
}
/**
* Get the paragraph level of the text.
*
* @param aParaLevel receives a <code>NSBIDI_XXX</code> value indicating
* the paragraph level
*
* @see nsBidiLevel
*/
nsBidiLevel GetParaLevel() { return ubidi_getParaLevel(mBiDi); }
/**
* Get a logical run.
* This function returns information about a run and is used
* to retrieve runs in logical order.<p>
* This is especially useful for line-breaking on a paragraph.
* <code>CountRuns</code> should be called before this.
* before the runs are retrieved.
*
* @param aLogicalStart is the first character of the run.
*
* @param aLogicalLimit will receive the limit of the run.
* The l-value that you point to here may be the
* same expression (variable) as the one for
* <code>aLogicalStart</code>.
* This pointer cannot be <code>nullptr</code>.
*
* @param aLevel will receive the level of the run.
* This pointer cannot be <code>nullptr</code>.
*/
void GetLogicalRun(int32_t aLogicalStart, int32_t* aLogicalLimit,
nsBidiLevel* aLevel);
/**
* Get the number of runs.
* This function may invoke the actual reordering on the
* <code>nsBidi</code> object, after <code>SetPara</code>
* may have resolved only the levels of the text. Therefore,
* <code>CountRuns</code> may have to allocate memory,
* and may fail doing so.
*
* @param aRunCount will receive the number of runs.
*/
nsresult CountRuns(int32_t* aRunCount);
/**
* Get one run's logical start, length, and directionality,
* which can be 0 for LTR or 1 for RTL.
* In an RTL run, the character at the logical start is
* visually on the right of the displayed run.
* The length is the number of characters in the run.<p>
* <code>CountRuns</code> should be called
* before the runs are retrieved.
*
* @param aRunIndex is the number of the run in visual order, in the
* range <code>[0..CountRuns-1]</code>.
*
* @param aLogicalStart is the first logical character index in the text.
* The pointer may be <code>nullptr</code> if this index is not needed.
*
* @param aLength is the number of characters (at least one) in the run.
* The pointer may be <code>nullptr</code> if this is not needed.
*
* @returns the directionality of the run,
* <code>NSBIDI_LTR==0</code> or <code>NSBIDI_RTL==1</code>,
* never <code>NSBIDI_MIXED</code>.
*
* @see CountRuns<p>
*
* Example:
* @code
* int32_t i, count, logicalStart, visualIndex=0, length;
* nsBidiDirection dir;
* pBidi->CountRuns(&count);
* for(i=0; i<count; ++i) {
* dir = pBidi->GetVisualRun(i, &logicalStart, &length);
* if(NSBIDI_LTR==dir) {
* do { // LTR
* show_char(text[logicalStart++], visualIndex++);
* } while(--length>0);
* } else {
* logicalStart+=length; // logicalLimit
* do { // RTL
* show_char(text[--logicalStart], visualIndex++);
* } while(--length>0);
* }
* }
* @endcode
*
* Note that in right-to-left runs, code like this places
* modifier letters before base characters and second surrogates
* before first ones.
*/
nsBidiDirection GetVisualRun(int32_t aRunIndex, int32_t* aLogicalStart,
int32_t* aLength) {
return nsBidiDirection(
ubidi_getVisualRun(mBiDi, aRunIndex, aLogicalStart, aLength));
}
/**
* This is a convenience function that does not use a nsBidi object.
* It is intended to be used for when an application has determined the levels
* of objects (character sequences) and just needs to have them reordered
* (L2). This is equivalent to using <code>GetVisualMap</code> on a
* <code>nsBidi</code> object.
*
* @param aLevels is an array with <code>aLength</code> levels that have been
* determined by the application.
*
* @param aLength is the number of levels in the array, or, semantically,
* the number of objects to be reordered.
* It must be <code>aLength>0</code>.
*
* @param aIndexMap is a pointer to an array of <code>aLength</code>
* indexes which will reflect the reordering of the characters.
* The array does not need to be initialized.<p>
* The index map will result in
* <code>aIndexMap[aVisualIndex]==aLogicalIndex</code>.
*/
static void ReorderVisual(const nsBidiLevel* aLevels, int32_t aLength,
int32_t* aIndexMap) {
ubidi_reorderVisual(aLevels, aLength, aIndexMap);
}
private:
nsBidi(const nsBidi&) = delete;
void operator=(const nsBidi&) = delete;
UBiDi* mBiDi;
// The two fields below are updated when CountRuns is called.
const nsBidiLevel* mLevels = nullptr;
int32_t mLength = 0;
};
#endif // _nsBidi_h_

View File

@@ -6,8 +6,6 @@
#include "nsBidiPresUtils.h"
#include "mozilla/intl/Bidi.h"
#include "mozilla/Casting.h"
#include "mozilla/IntegerRange.h"
#include "mozilla/Maybe.h"
#include "mozilla/PresShell.h"
@@ -41,7 +39,6 @@
#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;
@@ -166,7 +163,7 @@ struct MOZ_STACK_CLASS BidiParagraphData {
nsPresContext* mPresContext;
bool mIsVisual;
bool mRequiresBidi;
EmbeddingLevel mParaLevel;
nsBidiLevel mParaLevel;
nsIContent* mPrevContent;
/**
@@ -338,49 +335,37 @@ struct MOZ_STACK_CLASS BidiParagraphData {
}
nsresult SetPara() {
if (mPresContext->GetBidiEngine()
.SetParagraph(mBuffer, mParaLevel)
.isErr()) {
return NS_ERROR_FAILURE;
};
return NS_OK;
return mPresContext->GetBidiEngine().SetPara(mBuffer.get(), BufferLength(),
mParaLevel);
}
/**
* 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
* 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
*/
EmbeddingLevel GetParagraphEmbeddingLevel() {
EmbeddingLevel paraLevel = mParaLevel;
if (paraLevel == EmbeddingLevel::DefaultLTR() ||
paraLevel == EmbeddingLevel::DefaultRTL()) {
paraLevel = mPresContext->GetBidiEngine().GetParagraphEmbeddingLevel();
nsBidiLevel GetParaLevel() {
nsBidiLevel paraLevel = mParaLevel;
if (paraLevel == NSBIDI_DEFAULT_LTR || paraLevel == NSBIDI_DEFAULT_RTL) {
paraLevel = mPresContext->GetBidiEngine().GetParaLevel();
}
return paraLevel;
}
intl::Bidi::ParagraphDirection GetParagraphDirection() {
return mPresContext->GetBidiEngine().GetParagraphDirection();
nsBidiDirection GetDirection() {
return mPresContext->GetBidiEngine().GetDirection();
}
nsresult CountRuns(int32_t* runCount) {
auto result = mPresContext->GetBidiEngine().CountRuns();
if (result.isErr()) {
return NS_ERROR_FAILURE;
}
*runCount = result.unwrap();
return NS_OK;
return mPresContext->GetBidiEngine().CountRuns(runCount);
}
void GetLogicalRun(int32_t aLogicalStart, int32_t* aLogicalLimit,
EmbeddingLevel* aLevel) {
nsBidiLevel* aLevel) {
mPresContext->GetBidiEngine().GetLogicalRun(aLogicalStart, aLogicalLimit,
aLevel);
if (mIsVisual) {
*aLevel = GetParagraphEmbeddingLevel();
*aLevel = GetParaLevel();
}
}
@@ -480,7 +465,7 @@ struct MOZ_STACK_CLASS BidiLineData {
AutoTArray<nsIFrame*, 16> mLogicalFrames;
AutoTArray<nsIFrame*, 16> mVisualFrames;
AutoTArray<int32_t, 16> mIndexMap;
AutoTArray<EmbeddingLevel, 16> mLevels;
AutoTArray<uint8_t, 16> mLevels;
bool mIsReordered;
BidiLineData(nsIFrame* aFirstFrameOnLine, int32_t aNumFramesOnLine) {
@@ -492,11 +477,11 @@ struct MOZ_STACK_CLASS BidiLineData {
bool hasRTLFrames = false;
bool hasVirtualControls = false;
auto appendFrame = [&](nsIFrame* frame, EmbeddingLevel level) {
auto appendFrame = [&](nsIFrame* frame, nsBidiLevel level) {
mLogicalFrames.AppendElement(frame);
mLevels.AppendElement(level);
mIndexMap.AppendElement(0);
if (level.IsRTL()) {
if (IS_LEVEL_RTL(level)) {
hasRTLFrames = true;
}
};
@@ -517,7 +502,7 @@ struct MOZ_STACK_CLASS BidiLineData {
}
// Reorder the line
mozilla::intl::Bidi::ReorderVisual(mLevels.Elements(), FrameCount(),
nsBidi::ReorderVisual(mLevels.Elements(), FrameCount(),
mIndexMap.Elements());
// Strip virtual frames
@@ -880,8 +865,7 @@ nsresult nsBidiPresUtils::ResolveParagraph(BidiParagraphData* aBpd) {
nsresult rv = aBpd->SetPara();
NS_ENSURE_SUCCESS(rv, rv);
intl::Bidi::EmbeddingLevel embeddingLevel =
aBpd->GetParagraphEmbeddingLevel();
nsBidiLevel embeddingLevel = aBpd->GetParaLevel();
rv = aBpd->CountRuns(&runCount);
NS_ENSURE_SUCCESS(rv, rv);
@@ -913,9 +897,8 @@ nsresult nsBidiPresUtils::ResolveParagraph(BidiParagraphData* aBpd) {
# endif
#endif
if (runCount == 1 && frameCount == 1 &&
aBpd->GetParagraphDirection() == intl::Bidi::ParagraphDirection::LTR &&
aBpd->GetParagraphEmbeddingLevel() == 0) {
if (runCount == 1 && frameCount == 1 && aBpd->GetDirection() == NSBIDI_LTR &&
aBpd->GetParaLevel() == 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
@@ -937,13 +920,13 @@ nsresult nsBidiPresUtils::ResolveParagraph(BidiParagraphData* aBpd) {
}
BidiParagraphData::FrameInfo lastRealFrame;
EmbeddingLevel lastEmbeddingLevel = kBidiLevelNone;
EmbeddingLevel precedingControl = kBidiLevelNone;
nsBidiLevel lastEmbeddingLevel = kBidiLevelNone;
nsBidiLevel precedingControl = kBidiLevelNone;
auto storeBidiDataToFrame = [&]() {
FrameBidiData bidiData;
bidiData.embeddingLevel = embeddingLevel;
bidiData.baseLevel = aBpd->GetParagraphEmbeddingLevel();
bidiData.baseLevel = aBpd->GetParaLevel();
// 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
@@ -1523,11 +1506,11 @@ FrameBidiData nsBidiPresUtils::GetFrameBidiData(nsIFrame* aFrame) {
return GetFirstLeaf(aFrame)->GetBidiData();
}
EmbeddingLevel nsBidiPresUtils::GetFrameEmbeddingLevel(nsIFrame* aFrame) {
nsBidiLevel nsBidiPresUtils::GetFrameEmbeddingLevel(nsIFrame* aFrame) {
return GetFirstLeaf(aFrame)->GetEmbeddingLevel();
}
EmbeddingLevel nsBidiPresUtils::GetFrameBaseLevel(const nsIFrame* aFrame) {
nsBidiLevel nsBidiPresUtils::GetFrameBaseLevel(const nsIFrame* aFrame) {
const nsIFrame* firstLeaf = aFrame;
while (!IsBidiLeaf(firstLeaf)) {
firstLeaf = firstLeaf->PrincipalChildList().FirstChild();
@@ -1888,7 +1871,7 @@ nscoord nsBidiPresUtils::RepositionInlineFrames(BidiLineData* aBld,
for (; index != limit; index += step) {
frame = aBld->VisualFrameAt(index);
start += RepositionFrame(
frame, !(aBld->mLevels[aBld->mIndexMap[index]].IsRTL()), start,
frame, !(IS_LEVEL_RTL(aBld->mLevels[aBld->mIndexMap[index]])), start,
&continuationStates, aLineWM, false, aContainerSize);
}
return start;
@@ -2096,7 +2079,7 @@ RemoveDiacritics(char16_t* aText,
}
#endif
void nsBidiPresUtils::CalculateCharType(intl::Bidi* aBidiEngine,
void nsBidiPresUtils::CalculateCharType(nsBidi* aBidiEngine,
const char16_t* aText, int32_t& aOffset,
int32_t aCharTypeLimit,
int32_t& aRunLimit, int32_t& aRunLength,
@@ -2160,29 +2143,27 @@ void nsBidiPresUtils::CalculateCharType(intl::Bidi* aBidiEngine,
aOffset = offset;
}
nsresult nsBidiPresUtils::ProcessText(const char16_t* aText, size_t aLength,
EmbeddingLevel aBaseLevel,
nsresult nsBidiPresUtils::ProcessText(const char16_t* aText, int32_t aLength,
nsBidiLevel aBaseLevel,
nsPresContext* aPresContext,
BidiProcessor& aprocessor, Mode aMode,
nsBidiPositionResolve* aPosResolve,
int32_t aPosResolveCount, nscoord* aWidth,
mozilla::intl::Bidi* aBidiEngine) {
nsBidi* 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();
if (aBidiEngine->SetParagraph(Span(text, aLength), aBaseLevel).isErr()) {
return NS_ERROR_FAILURE;
}
nsresult rv = aBidiEngine->SetPara(text, aLength, aBaseLevel);
if (NS_FAILED(rv)) return rv;
auto result = aBidiEngine->CountRuns();
if (result.isErr()) {
return NS_ERROR_FAILURE;
}
int32_t runCount = result.unwrap();
rv = aBidiEngine->CountRuns(&runCount);
if (NS_FAILED(rv)) return rv;
nscoord xOffset = 0;
nscoord width, xEndRun = 0;
@@ -2199,16 +2180,15 @@ nsresult nsBidiPresUtils::ProcessText(const char16_t* aText, size_t aLength,
}
for (i = 0; i < runCount; i++) {
mozilla::intl::Bidi::Direction dir =
aBidiEngine->GetVisualRun(i, &start, &length);
nsBidiDirection dir = aBidiEngine->GetVisualRun(i, &start, &length);
EmbeddingLevel level;
nsBidiLevel level;
aBidiEngine->GetLogicalRun(start, &limit, &level);
dir = level.Direction();
dir = DIRECTION_FROM_LEVEL(level);
int32_t subRunLength = limit - start;
int32_t lineOffset = start;
int32_t typeLimit = std::min(limit, AssertedCast<int32_t>(aLength));
int32_t typeLimit = std::min(limit, aLength);
int32_t subRunCount = 1;
int32_t subRunLimit = typeLimit;
@@ -2224,9 +2204,8 @@ nsresult nsBidiPresUtils::ProcessText(const char16_t* aText, size_t aLength,
* x-coordinate of the end of the run for the start of the next run.
*/
if (dir == intl::Bidi::Direction::RTL) {
aprocessor.SetText(text + start, subRunLength,
intl::Bidi::Direction::RTL);
if (dir == NSBIDI_RTL) {
aprocessor.SetText(text + start, subRunLength, dir);
width = aprocessor.GetWidth();
xOffset += width;
xEndRun = xOffset;
@@ -2248,7 +2227,7 @@ nsresult nsBidiPresUtils::ProcessText(const char16_t* aText, size_t aLength,
aprocessor.SetText(runVisualText.get(), subRunLength, dir);
width = aprocessor.GetWidth();
totalWidth += width;
if (dir == mozilla::intl::Bidi::Direction::RTL) {
if (dir == NSBIDI_RTL) {
xOffset -= width;
}
if (aMode == MODE_DRAW) {
@@ -2318,7 +2297,7 @@ nsresult nsBidiPresUtils::ProcessText(const char16_t* aText, size_t aLength,
// The position in the text where this run's "left part" begins.
const char16_t* visualLeftPart;
const char16_t* visualRightSide;
if (dir == mozilla::intl::Bidi::Direction::RTL) {
if (dir == NSBIDI_RTL) {
// One day, son, this could all be replaced with
// mPresContext->GetBidiEngine().GetVisualIndex() ...
posResolve->visualIndex =
@@ -2347,7 +2326,7 @@ nsresult nsBidiPresUtils::ProcessText(const char16_t* aText, size_t aLength,
}
}
if (dir == intl::Bidi::Direction::LTR) {
if (dir == NSBIDI_LTR) {
xOffset += width;
}
@@ -2356,7 +2335,7 @@ nsresult nsBidiPresUtils::ProcessText(const char16_t* aText, size_t aLength,
subRunLimit = typeLimit;
subRunLength = typeLimit - lineOffset;
} // while
if (dir == intl::Bidi::Direction::RTL) {
if (dir == NSBIDI_RTL) {
xOffset = xEndRun;
}
@@ -2388,8 +2367,8 @@ class MOZ_STACK_CLASS nsIRenderingContextBidiProcessor final
~nsIRenderingContextBidiProcessor() { mFontMetrics->SetTextRunRTL(false); }
virtual void SetText(const char16_t* aText, int32_t aLength,
intl::Bidi::Direction aDirection) override {
mFontMetrics->SetTextRunRTL(aDirection == intl::Bidi::Direction::RTL);
nsBidiDirection aDirection) override {
mFontMetrics->SetTextRunRTL(aDirection == NSBIDI_RTL);
mText = aText;
mLength = aLength;
}
@@ -2420,7 +2399,7 @@ class MOZ_STACK_CLASS nsIRenderingContextBidiProcessor final
};
nsresult nsBidiPresUtils::ProcessTextForRenderingContext(
const char16_t* aText, int32_t aLength, EmbeddingLevel aBaseLevel,
const char16_t* aText, int32_t aLength, nsBidiLevel aBaseLevel,
nsPresContext* aPresContext, gfxContext& aRenderingContext,
DrawTarget* aTextRunConstructionDrawTarget, nsFontMetrics& aFontMetrics,
Mode aMode, nscoord aX, nscoord aY, nsBidiPositionResolve* aPosResolve,
@@ -2434,16 +2413,15 @@ nsresult nsBidiPresUtils::ProcessTextForRenderingContext(
}
/* static */
EmbeddingLevel nsBidiPresUtils::BidiLevelFromStyle(
ComputedStyle* aComputedStyle) {
nsBidiLevel nsBidiPresUtils::BidiLevelFromStyle(ComputedStyle* aComputedStyle) {
if (aComputedStyle->StyleTextReset()->mUnicodeBidi &
NS_STYLE_UNICODE_BIDI_PLAINTEXT) {
return EmbeddingLevel::DefaultLTR();
return NSBIDI_DEFAULT_LTR;
}
if (aComputedStyle->StyleVisibility()->mDirection == StyleDirection::Rtl) {
return EmbeddingLevel::RTL();
return NSBIDI_RTL;
}
return EmbeddingLevel::LTR();
return NSBIDI_LTR;
}

View File

@@ -8,7 +8,7 @@
#define nsBidiPresUtils_h___
#include "gfxContext.h"
#include "mozilla/intl/Bidi.h"
#include "nsBidi.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,
mozilla::intl::Bidi::Direction aDirection) = 0;
nsBidiDirection aDirection) = 0;
/**
* Returns the measured width of the text given in SetText. If SetText was
@@ -229,6 +229,15 @@ 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
@@ -239,14 +248,11 @@ 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,
mozilla::intl::Bidi::EmbeddingLevel aBaseLevel,
nsPresContext* aPresContext,
gfxContext& aRenderingContext,
DrawTarget* aTextRunConstructionDrawTarget,
nsFontMetrics& aFontMetrics, nscoord aX,
nscoord aY,
nsBidiPositionResolve* aPosResolve = nullptr,
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) {
return ProcessTextForRenderingContext(
aText, aLength, aBaseLevel, aPresContext, aRenderingContext,
@@ -254,10 +260,10 @@ class nsBidiPresUtils {
aPosResolve, aPosResolveCount, nullptr);
}
static nscoord MeasureTextWidth(
const char16_t* aText, int32_t aLength,
mozilla::intl::Bidi::EmbeddingLevel aBaseLevel,
nsPresContext* aPresContext, gfxContext& aRenderingContext,
static nscoord MeasureTextWidth(const char16_t* aText, int32_t aLength,
nsBidiLevel aBaseLevel,
nsPresContext* aPresContext,
gfxContext& aRenderingContext,
nsFontMetrics& aFontMetrics) {
nscoord length;
nsresult rv = ProcessTextForRenderingContext(
@@ -311,32 +317,31 @@ class nsBidiPresUtils {
/**
* Get the bidi embedding level of the given (inline) frame.
*/
static mozilla::intl::Bidi::EmbeddingLevel GetFrameEmbeddingLevel(
nsIFrame* aFrame);
static nsBidiLevel GetFrameEmbeddingLevel(nsIFrame* aFrame);
/**
* Get the bidi base level of the given (inline) frame.
*/
static mozilla::intl::Bidi::EmbeddingLevel GetFrameBaseLevel(
const nsIFrame* aFrame);
static nsBidiLevel GetFrameBaseLevel(const nsIFrame* aFrame);
/**
* Get a mozilla::intl::Bidi::Direction representing the direction implied by
* the bidi base level of the frame.
* @return mozilla::intl::Bidi::Direction
* 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.
*/
static mozilla::intl::Bidi::Direction ParagraphDirection(
const nsIFrame* aFrame) {
return GetFrameBaseLevel(aFrame).Direction();
static nsBidiDirection ParagraphDirection(const nsIFrame* aFrame) {
return DIRECTION_FROM_LEVEL(GetFrameBaseLevel(aFrame));
}
/**
* Get a mozilla::intl::Bidi::Direction representing the direction implied by
* the bidi embedding level of the frame.
* @return mozilla::intl::Bidi::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.
*/
static mozilla::intl::Bidi::Direction FrameDirection(nsIFrame* aFrame) {
return GetFrameEmbeddingLevel(aFrame).Direction();
static nsBidiDirection FrameDirection(nsIFrame* aFrame) {
return DIRECTION_FROM_LEVEL(GetFrameEmbeddingLevel(aFrame));
}
static bool IsFrameInParagraphDirection(nsIFrame* aFrame) {
@@ -348,7 +353,7 @@ class nsBidiPresUtils {
// the leaf frame.
static bool IsReversedDirectionFrame(const nsIFrame* aFrame) {
mozilla::FrameBidiData bidiData = aFrame->GetBidiData();
return !bidiData.embeddingLevel.IsSameDirection(bidiData.baseLevel);
return !IS_SAME_DIRECTION(bidiData.embeddingLevel, bidiData.baseLevel);
}
enum Mode { MODE_DRAW, MODE_MEASURE };
@@ -360,6 +365,15 @@ 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
@@ -371,33 +385,31 @@ 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, size_t aLength,
mozilla::intl::Bidi::EmbeddingLevel aBaseLevel,
static nsresult ProcessText(const char16_t* aText, int32_t aLength,
nsBidiLevel aBaseLevel,
nsPresContext* aPresContext,
BidiProcessor& aprocessor, Mode aMode,
nsBidiPositionResolve* aPosResolve,
int32_t aPosResolveCount, nscoord* aWidth,
mozilla::intl::Bidi* aBidiEngine);
nsBidi* 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
* 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.
* 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.
*
* Otherwise returns EmbeddingLevel::LTR or EmbeddingLevel::RTL depending on
* the value of |direction|
* Otherwise returns NSBIDI_LTR or NSBIDI_RTL depending on the value of
* |direction|
*/
static mozilla::intl::Bidi::EmbeddingLevel BidiLevelFromStyle(
mozilla::ComputedStyle* aComputedStyle);
static nsBidiLevel BidiLevelFromStyle(mozilla::ComputedStyle* aComputedStyle);
private:
static nsresult ProcessTextForRenderingContext(
const char16_t* aText, int32_t aLength,
mozilla::intl::Bidi::EmbeddingLevel aBaseLevel,
const char16_t* aText, int32_t aLength, nsBidiLevel aBaseLevel,
nsPresContext* aPresContext, gfxContext& aRenderingContext,
DrawTarget* aTextRunConstructionDrawTarget, nsFontMetrics& aFontMetrics,
Mode aMode,
@@ -560,11 +572,11 @@ class nsBidiPresUtils {
*/
static void RemoveBidiContinuation(BidiParagraphData* aBpd, nsIFrame* aFrame,
int32_t aFirstIndex, int32_t aLastIndex);
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 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 StripBidiControlCharacters(char16_t* aText, int32_t& aTextLength);
};

View File

@@ -12,7 +12,6 @@
#include "gfxUtils.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/intl/Bidi.h"
#include "nsCOMPtr.h"
#include "nsFontMetrics.h"
#include "nsITimer.h"
@@ -40,8 +39,6 @@ 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
@@ -392,8 +389,7 @@ nsIFrame* nsCaret::GetFrameAndOffset(const Selection* aSelection,
nsIContent* contentNode = focusNode->AsContent();
nsFrameSelection* frameSelection = aSelection->GetFrameSelection();
mozilla::intl::Bidi::EmbeddingLevel bidiLevel =
frameSelection->GetCaretBidiLevel();
nsBidiLevel bidiLevel = frameSelection->GetCaretBidiLevel();
return nsCaret::GetCaretFrameForNodeOffset(
frameSelection, contentNode, focusOffset, frameSelection->GetHint(),
@@ -648,8 +644,7 @@ void nsCaret::StopBlinking() {
nsIFrame* nsCaret::GetCaretFrameForNodeOffset(
nsFrameSelection* aFrameSelection, nsIContent* aContentNode,
int32_t aOffset, CaretAssociationHint aFrameHint,
mozilla::intl::Bidi::EmbeddingLevel aBidiLevel,
int32_t aOffset, CaretAssociationHint aFrameHint, nsBidiLevel aBidiLevel,
nsIFrame** aReturnUnadjustedFrame, int32_t* aReturnOffset) {
if (!aFrameSelection) {
return nullptr;
@@ -701,10 +696,8 @@ nsIFrame* nsCaret::GetCaretFrameForNodeOffset(
nsIFrame* frameBefore;
nsIFrame* frameAfter;
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
nsBidiLevel levelBefore; // Bidi level of the character before the caret
nsBidiLevel levelAfter; // Bidi level of the character after the caret
auto [start, end] = theFrame->GetOffsets();
if (start == 0 || end == 0 || start == theFrameOffset ||
@@ -727,9 +720,9 @@ nsIFrame* nsCaret::GetCaretFrameForNodeOffset(
std::max(levelBefore, levelAfter)); // rule c4
if (aBidiLevel == levelBefore || // rule c1
(aBidiLevel > levelBefore && aBidiLevel < levelAfter &&
aBidiLevel.IsSameDirection(levelBefore)) || // rule c5
IS_SAME_DIRECTION(aBidiLevel, levelBefore)) || // rule c5
(aBidiLevel < levelBefore && aBidiLevel > levelAfter &&
aBidiLevel.IsSameDirection(levelBefore))) // rule c9
IS_SAME_DIRECTION(aBidiLevel, levelBefore))) // rule c9
{
if (theFrame != frameBefore) {
if (frameBefore) { // if there is a frameBefore, move into it
@@ -742,8 +735,7 @@ 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.
mozilla::intl::Bidi::EmbeddingLevel baseLevel =
frameAfter->GetBaseLevel();
nsBidiLevel baseLevel = frameAfter->GetBaseLevel();
if (baseLevel != levelAfter) {
nsPeekOffsetStruct pos(eSelectBeginLine, eDirPrevious, 0,
nsPoint(0, 0), false, true, false,
@@ -757,9 +749,9 @@ nsIFrame* nsCaret::GetCaretFrameForNodeOffset(
}
} else if (aBidiLevel == levelAfter || // rule c2
(aBidiLevel > levelBefore && aBidiLevel < levelAfter &&
aBidiLevel.IsSameDirection(levelAfter)) || // rule c6
IS_SAME_DIRECTION(aBidiLevel, levelAfter)) || // rule c6
(aBidiLevel < levelBefore && aBidiLevel > levelAfter &&
aBidiLevel.IsSameDirection(levelAfter))) // rule c10
IS_SAME_DIRECTION(aBidiLevel, levelAfter))) // rule c10
{
if (theFrame != frameAfter) {
if (frameAfter) {
@@ -774,8 +766,7 @@ 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.
mozilla::intl::Bidi::EmbeddingLevel baseLevel =
frameBefore->GetBaseLevel();
nsBidiLevel baseLevel = frameBefore->GetBaseLevel();
if (baseLevel != levelBefore) {
nsPeekOffsetStruct pos(eSelectEndLine, eDirNext, 0,
nsPoint(0, 0), false, true, false,
@@ -790,38 +781,34 @@ nsIFrame* nsCaret::GetCaretFrameForNodeOffset(
} else if (aBidiLevel > levelBefore &&
aBidiLevel < levelAfter && // rule c7/8
// before and after have the same parity
levelBefore.IsSameDirection(levelAfter) &&
IS_SAME_DIRECTION(levelBefore, levelAfter) &&
// caret has different parity
!aBidiLevel.IsSameDirection(levelAfter)) {
!IS_SAME_DIRECTION(aBidiLevel, levelAfter)) {
if (NS_SUCCEEDED(aFrameSelection->GetFrameFromLevel(
frameAfter, eDirNext, aBidiLevel, &theFrame))) {
std::tie(start, end) = theFrame->GetOffsets();
levelAfter = theFrame->GetEmbeddingLevel();
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;
}
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;
}
} else if (aBidiLevel < levelBefore &&
aBidiLevel > levelAfter && // rule c11/12
// before and after have the same parity
levelBefore.IsSameDirection(levelAfter) &&
IS_SAME_DIRECTION(levelBefore, levelAfter) &&
// caret has different parity
!aBidiLevel.IsSameDirection(levelAfter)) {
!IS_SAME_DIRECTION(aBidiLevel, levelAfter)) {
if (NS_SUCCEEDED(aFrameSelection->GetFrameFromLevel(
frameBefore, eDirPrevious, aBidiLevel, &theFrame))) {
std::tie(start, end) = theFrame->GetOffsets();
levelBefore = theFrame->GetEmbeddingLevel();
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;
}
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;
}
}
}

View File

@@ -9,7 +9,6 @@
#ifndef nsCaret_h__
#define nsCaret_h__
#include "mozilla/intl/Bidi.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/dom/Selection.h"
#include "nsCoord.h"
@@ -180,8 +179,7 @@ class nsCaret final : public nsISelectionListener {
nsRect* aRect);
static nsIFrame* GetCaretFrameForNodeOffset(
nsFrameSelection* aFrameSelection, nsIContent* aContentNode,
int32_t aOffset, CaretAssociationHint aFrameHint,
mozilla::intl::Bidi::EmbeddingLevel aBidiLevel,
int32_t aOffset, CaretAssociationHint aFrameHint, uint8_t aBidiLevel,
nsIFrame** aReturnUnadjustedFrame, int32_t* aReturnOffset);
static nsRect GetGeometryForFrame(nsIFrame* aFrame, int32_t aFrameOffset,
nscoord* aBidiIndicatorSize);

View File

@@ -52,7 +52,6 @@
#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"
@@ -1543,10 +1542,7 @@ 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
? mozilla::intl::Bidi::EmbeddingLevel::RTL()
: mozilla::intl::Bidi::EmbeddingLevel::LTR());
wm.SetDirectionFromBidiLevel(aDirection == StyleDirection::Rtl ? 1 : 0);
nscoord x1 = aScrolledFrameOverflowArea.x,
x2 = aScrolledFrameOverflowArea.XMost(),
@@ -5556,8 +5552,7 @@ nscoord nsLayoutUtils::AppUnitWidthOfStringBidi(const char16_t* aString,
gfxContext& aContext) {
nsPresContext* presContext = aFrame->PresContext();
if (presContext->BidiEnabled()) {
mozilla::intl::Bidi::EmbeddingLevel level =
nsBidiPresUtils::BidiLevelFromStyle(aFrame->Style());
nsBidiLevel level = nsBidiPresUtils::BidiLevelFromStyle(aFrame->Style());
return nsBidiPresUtils::MeasureTextWidth(
aString, aLength, level, presContext, aContext, aFontMetrics);
}
@@ -5636,8 +5631,7 @@ void nsLayoutUtils::DrawString(const nsIFrame* aFrame,
nsPresContext* presContext = aFrame->PresContext();
if (presContext->BidiEnabled()) {
mozilla::intl::Bidi::EmbeddingLevel level =
nsBidiPresUtils::BidiLevelFromStyle(aComputedStyle);
nsBidiLevel level = nsBidiPresUtils::BidiLevelFromStyle(aComputedStyle);
rv = nsBidiPresUtils::RenderText(aString, aLength, level, presContext,
*aContext, aContext->GetDrawTarget(),
aFontMetrics, aPoint.x, aPoint.y);

View File

@@ -100,6 +100,7 @@
#include "nsBidiUtils.h"
#include "nsServiceManagerUtils.h"
#include "nsBidi.h"
#include "mozilla/dom/URL.h"
#include "mozilla/ServoCSSParser.h"
@@ -2682,11 +2683,11 @@ uint64_t nsPresContext::GetUndisplayedRestyleGeneration() const {
return mRestyleManager->GetUndisplayedRestyleGeneration();
}
mozilla::intl::Bidi& nsPresContext::GetBidiEngine() {
nsBidi& nsPresContext::GetBidiEngine() {
MOZ_ASSERT(NS_IsMainThread());
if (!mBidiEngine) {
mBidiEngine.reset(new mozilla::intl::Bidi());
mBidiEngine.reset(new nsBidi());
}
return *mBidiEngine;
}

View File

@@ -9,7 +9,6 @@
#ifndef nsPresContext_h___
#define nsPresContext_h___
#include "mozilla/intl/Bidi.h"
#include "mozilla/AppUnits.h"
#include "mozilla/Attributes.h"
#include "mozilla/EnumeratedArray.h"
@@ -44,6 +43,7 @@
#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;
}
mozilla::intl::Bidi& GetBidiEngine();
nsBidi& GetBidiEngine();
gfxFontFeatureValueSet* GetFontFeatureValuesLookup() const {
return mFontFeatureValuesLookup;
@@ -1207,7 +1207,7 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
nsCOMPtr<nsITheme> mTheme;
nsCOMPtr<nsIPrintSettings> mPrintSettings;
mozilla::UniquePtr<mozilla::intl::Bidi> mBidiEngine;
mozilla::UniquePtr<nsBidi> mBidiEngine;
AutoTArray<TransactionInvalidations, 4> mTransactions;

View File

@@ -9,7 +9,6 @@
#include <ostream>
#include "mozilla/intl/Bidi.h"
#include "mozilla/ComputedStyle.h"
#include "mozilla/EnumeratedRange.h"
@@ -525,8 +524,8 @@ class WritingMode {
*
* XXX change uint8_t to UBiDiLevel after bug 924851
*/
void SetDirectionFromBidiLevel(mozilla::intl::Bidi::EmbeddingLevel level) {
if (level.IsRTL() == IsBidiLTR()) {
void SetDirectionFromBidiLevel(uint8_t level) {
if (IS_LEVEL_RTL(level) == IsBidiLTR()) {
mWritingMode ^= StyleWritingMode::RTL | StyleWritingMode::INLINE_REVERSED;
}
}

View File

@@ -6,7 +6,6 @@
#include "nsFrameList.h"
#include "mozilla/intl/Bidi.h"
#include "mozilla/ArenaObjectID.h"
#include "mozilla/PresShell.h"
#include "nsBidiPresUtils.h"
@@ -306,8 +305,7 @@ nsIFrame* nsFrameList::GetPrevVisualFor(nsIFrame* aFrame) const {
nsIFrame* parent = mFirstChild->GetParent();
if (!parent) return aFrame ? aFrame->GetPrevSibling() : LastChild();
mozilla::intl::Bidi::Direction paraDir =
nsBidiPresUtils::ParagraphDirection(mFirstChild);
nsBidiDirection paraDir = nsBidiPresUtils::ParagraphDirection(mFirstChild);
nsAutoLineIterator iter = parent->GetLineIterator();
if (!iter) {
@@ -315,7 +313,7 @@ nsIFrame* nsFrameList::GetPrevVisualFor(nsIFrame* aFrame) const {
if (parent->IsLineFrame()) {
// Line frames are not bidi-splittable, so need to consider bidi
// reordering
if (paraDir == mozilla::intl::Bidi::Direction::LTR) {
if (paraDir == NSBIDI_LTR) {
return nsBidiPresUtils::GetFrameToLeftOf(aFrame, mFirstChild, -1);
} else { // RTL
return nsBidiPresUtils::GetFrameToRightOf(aFrame, mFirstChild, -1);
@@ -347,7 +345,7 @@ nsIFrame* nsFrameList::GetPrevVisualFor(nsIFrame* aFrame) const {
if (aFrame) {
auto line = iter->GetLine(thisLine).unwrap();
if (paraDir == mozilla::intl::Bidi::Direction::LTR) {
if (paraDir == NSBIDI_LTR) {
frame = nsBidiPresUtils::GetFrameToLeftOf(aFrame, line.mFirstFrameOnLine,
line.mNumFramesOnLine);
} else { // RTL
@@ -360,7 +358,7 @@ nsIFrame* nsFrameList::GetPrevVisualFor(nsIFrame* aFrame) const {
// Get the last frame of the previous line
auto line = iter->GetLine(thisLine - 1).unwrap();
if (paraDir == mozilla::intl::Bidi::Direction::LTR) {
if (paraDir == NSBIDI_LTR) {
frame = nsBidiPresUtils::GetFrameToLeftOf(nullptr, line.mFirstFrameOnLine,
line.mNumFramesOnLine);
} else { // RTL
@@ -377,8 +375,7 @@ nsIFrame* nsFrameList::GetNextVisualFor(nsIFrame* aFrame) const {
nsIFrame* parent = mFirstChild->GetParent();
if (!parent) return aFrame ? aFrame->GetPrevSibling() : mFirstChild;
mozilla::intl::Bidi::Direction paraDir =
nsBidiPresUtils::ParagraphDirection(mFirstChild);
nsBidiDirection paraDir = nsBidiPresUtils::ParagraphDirection(mFirstChild);
nsAutoLineIterator iter = parent->GetLineIterator();
if (!iter) {
@@ -386,7 +383,7 @@ nsIFrame* nsFrameList::GetNextVisualFor(nsIFrame* aFrame) const {
if (parent->IsLineFrame()) {
// Line frames are not bidi-splittable, so need to consider bidi
// reordering
if (paraDir == mozilla::intl::Bidi::Direction::LTR) {
if (paraDir == NSBIDI_LTR) {
return nsBidiPresUtils::GetFrameToRightOf(aFrame, mFirstChild, -1);
} else { // RTL
return nsBidiPresUtils::GetFrameToLeftOf(aFrame, mFirstChild, -1);
@@ -418,7 +415,7 @@ nsIFrame* nsFrameList::GetNextVisualFor(nsIFrame* aFrame) const {
if (aFrame) {
auto line = iter->GetLine(thisLine).unwrap();
if (paraDir == mozilla::intl::Bidi::Direction::LTR) {
if (paraDir == NSBIDI_LTR) {
frame = nsBidiPresUtils::GetFrameToRightOf(aFrame, line.mFirstFrameOnLine,
line.mNumFramesOnLine);
} else { // RTL
@@ -432,7 +429,7 @@ nsIFrame* nsFrameList::GetNextVisualFor(nsIFrame* aFrame) const {
// Get the first frame of the next line
auto line = iter->GetLine(thisLine + 1).unwrap();
if (paraDir == mozilla::intl::Bidi::Direction::LTR) {
if (paraDir == NSBIDI_LTR) {
frame = nsBidiPresUtils::GetFrameToRightOf(
nullptr, line.mFirstFrameOnLine, line.mNumFramesOnLine);
} else { // RTL

View File

@@ -10,7 +10,6 @@
#include "nsFrameSelection.h"
#include "mozilla/intl/Bidi.h"
#include "mozilla/Attributes.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/BasePrincipal.h"
@@ -600,7 +599,7 @@ nsresult nsFrameSelection::ConstrainFrameAndPointToAnchorSubtree(
}
void nsFrameSelection::SetCaretBidiLevelAndMaybeSchedulePaint(
mozilla::intl::Bidi::EmbeddingLevel aLevel) {
nsBidiLevel 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;
@@ -611,14 +610,12 @@ void nsFrameSelection::SetCaretBidiLevelAndMaybeSchedulePaint(
}
}
mozilla::intl::Bidi::EmbeddingLevel nsFrameSelection::GetCaretBidiLevel()
const {
nsBidiLevel nsFrameSelection::GetCaretBidiLevel() const {
return mCaret.mBidiLevel;
}
void nsFrameSelection::UndefineCaretBidiLevel() {
mCaret.mBidiLevel = mozilla::intl::Bidi::EmbeddingLevel(mCaret.mBidiLevel |
BIDI_LEVEL_UNDEFINED);
mCaret.mBidiLevel |= BIDI_LEVEL_UNDEFINED;
}
#ifdef PRINT_RANGE
@@ -665,10 +662,9 @@ static nsINode* GetClosestInclusiveTableCellAncestor(nsINode* aDomNode) {
static nsDirection GetCaretDirection(const nsIFrame& aFrame,
nsDirection aDirection,
bool aVisualMovement) {
const mozilla::intl::Bidi::Direction paragraphDirection =
const nsBidiDirection paragraphDirection =
nsBidiPresUtils::ParagraphDirection(&aFrame);
return (aVisualMovement &&
paragraphDirection == mozilla::intl::Bidi::Direction::RTL)
return (aVisualMovement && paragraphDirection == NSBIDI_RTL)
? nsDirection(1 - aDirection)
: aDirection;
}
@@ -932,8 +928,7 @@ nsPrevNextBidiLevels nsFrameSelection::GetPrevNextBidiLevels(
nsDirection direction;
nsPrevNextBidiLevels levels{};
levels.SetData(nullptr, nullptr, mozilla::intl::Bidi::EmbeddingLevel::LTR(),
mozilla::intl::Bidi::EmbeddingLevel::LTR());
levels.SetData(nullptr, nullptr, 0, 0);
currentFrame = GetFrameForNodeOffset(
aNode, static_cast<int32_t>(aContentOffset), aHint, &currentOffset);
@@ -952,8 +947,7 @@ nsPrevNextBidiLevels nsFrameSelection::GetPrevNextBidiLevels(
} else {
// we are neither at the beginning nor at the end of the frame, so we have
// no worries
mozilla::intl::Bidi::EmbeddingLevel currentLevel =
currentFrame->GetEmbeddingLevel();
nsBidiLevel currentLevel = currentFrame->GetEmbeddingLevel();
levels.SetData(currentFrame, currentFrame, currentLevel, currentLevel);
return levels;
}
@@ -964,8 +958,8 @@ nsPrevNextBidiLevels nsFrameSelection::GetPrevNextBidiLevels(
.mFrame;
FrameBidiData currentBidi = currentFrame->GetBidiData();
mozilla::intl::Bidi::EmbeddingLevel currentLevel = currentBidi.embeddingLevel;
mozilla::intl::Bidi::EmbeddingLevel newLevel =
nsBidiLevel currentLevel = currentBidi.embeddingLevel;
nsBidiLevel newLevel =
newFrame ? newFrame->GetEmbeddingLevel() : currentBidi.baseLevel;
// If not jumping lines, disregard br frames, since they might be positioned
@@ -990,13 +984,12 @@ nsPrevNextBidiLevels nsFrameSelection::GetPrevNextBidiLevels(
return levels;
}
nsresult nsFrameSelection::GetFrameFromLevel(
nsIFrame* aFrameIn, nsDirection aDirection,
mozilla::intl::Bidi::EmbeddingLevel aBidiLevel,
nsresult nsFrameSelection::GetFrameFromLevel(nsIFrame* aFrameIn,
nsDirection aDirection,
nsBidiLevel aBidiLevel,
nsIFrame** aFrameOut) const {
NS_ENSURE_STATE(mPresShell);
mozilla::intl::Bidi::EmbeddingLevel foundLevel =
mozilla::intl::Bidi::EmbeddingLevel::LTR();
nsBidiLevel foundLevel = 0;
nsIFrame* foundFrame = aFrameIn;
nsCOMPtr<nsIFrameEnumerator> frameTraversal;

View File

@@ -7,7 +7,6 @@
#ifndef nsFrameSelection_h___
#define nsFrameSelection_h___
#include "mozilla/intl/Bidi.h"
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/EventForwards.h"
@@ -26,7 +25,7 @@
class nsRange;
#define BIDI_LEVEL_UNDEFINED mozilla::intl::Bidi::EmbeddingLevel(0x80)
#define BIDI_LEVEL_UNDEFINED 0x80
//----------------------------------------------------------------------
@@ -173,8 +172,7 @@ struct MOZ_STACK_CLASS nsPeekOffsetStruct {
struct nsPrevNextBidiLevels {
void SetData(nsIFrame* aFrameBefore, nsIFrame* aFrameAfter,
mozilla::intl::Bidi::EmbeddingLevel aLevelBefore,
mozilla::intl::Bidi::EmbeddingLevel aLevelAfter) {
nsBidiLevel aLevelBefore, nsBidiLevel aLevelAfter) {
mFrameBefore = aFrameBefore;
mFrameAfter = aFrameAfter;
mLevelBefore = aLevelBefore;
@@ -182,8 +180,8 @@ struct nsPrevNextBidiLevels {
}
nsIFrame* mFrameBefore;
nsIFrame* mFrameAfter;
mozilla::intl::Bidi::EmbeddingLevel mLevelBefore;
mozilla::intl::Bidi::EmbeddingLevel mLevelAfter;
nsBidiLevel mLevelBefore;
nsBidiLevel mLevelAfter;
};
namespace mozilla {
@@ -477,13 +475,12 @@ class nsFrameSelection final {
void SetHint(CaretAssociateHint aHintRight) { mCaret.mHint = aHintRight; }
CaretAssociateHint GetHint() const { return mCaret.mHint; }
void SetCaretBidiLevelAndMaybeSchedulePaint(
mozilla::intl::Bidi::EmbeddingLevel aLevel);
void SetCaretBidiLevelAndMaybeSchedulePaint(nsBidiLevel aLevel);
/**
* GetCaretBidiLevel gets the caret bidi level.
*/
mozilla::intl::Bidi::EmbeddingLevel GetCaretBidiLevel() const;
nsBidiLevel GetCaretBidiLevel() const;
/**
* UndefineCaretBidiLevel sets the caret bidi level to "undefined".
@@ -698,7 +695,7 @@ class nsFrameSelection final {
* @param aFrameOut will hold the frame returned
*/
nsresult GetFrameFromLevel(nsIFrame* aFrameIn, nsDirection aDirection,
mozilla::intl::Bidi::EmbeddingLevel aBidiLevel,
nsBidiLevel aBidiLevel,
nsIFrame** aFrameOut) const;
/**
@@ -1043,7 +1040,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;
mozilla::intl::Bidi::EmbeddingLevel mBidiLevel = BIDI_LEVEL_UNDEFINED;
nsBidiLevel mBidiLevel = BIDI_LEVEL_UNDEFINED;
bool IsVisualMovement(bool aContinueSelection,
CaretMovementStyle aMovementStyle) const;
@@ -1051,8 +1048,7 @@ class nsFrameSelection final {
Caret mCaret;
mozilla::intl::Bidi::EmbeddingLevel mKbdBidiLevel =
mozilla::intl::Bidi::EmbeddingLevel::LTR();
nsBidiLevel mKbdBidiLevel = NSBIDI_LTR;
class DesiredCaretPos {
public:

View File

@@ -21,7 +21,6 @@
#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"
@@ -7118,8 +7117,7 @@ StyleDirection ScrollFrameHelper::GetScrolledFrameDir() const {
if (mScrolledFrame->StyleTextReset()->mUnicodeBidi &
NS_STYLE_UNICODE_BIDI_PLAINTEXT) {
if (nsIFrame* child = mScrolledFrame->PrincipalChildList().FirstChild()) {
return nsBidiPresUtils::ParagraphDirection(child) ==
mozilla::intl::Bidi::Direction::LTR
return nsBidiPresUtils::ParagraphDirection(child) == NSBIDI_LTR
? StyleDirection::Ltr
: StyleDirection::Rtl;
}

View File

@@ -25,7 +25,6 @@
#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"
@@ -1698,8 +1697,7 @@ WritingMode nsIFrame::WritingModeForLine(WritingMode aSelfWM,
WritingMode writingMode = aSelfWM;
if (StyleTextReset()->mUnicodeBidi & NS_STYLE_UNICODE_BIDI_PLAINTEXT) {
mozilla::intl::Bidi::EmbeddingLevel frameLevel =
nsBidiPresUtils::GetFrameBaseLevel(aSubFrame);
nsBidiLevel frameLevel = nsBidiPresUtils::GetFrameBaseLevel(aSubFrame);
writingMode.SetDirectionFromBidiLevel(frameLevel);
}
@@ -7925,9 +7923,8 @@ void nsIFrame::ListGeneric(nsACString& aTo, const char* aPrefix,
}
if (HasProperty(BidiDataProperty())) {
FrameBidiData bidi = GetBidiData();
aTo += nsPrintfCString(" bidi(%d,%d,%d)", bidi.baseLevel.Value(),
bidi.embeddingLevel.Value(),
bidi.precedingControl.Value());
aTo += nsPrintfCString(" bidi(%d,%d,%d)", bidi.baseLevel,
bidi.embeddingLevel, bidi.precedingControl);
}
if (IsTransformed()) {
aTo += nsPrintfCString(" transformed");
@@ -8108,7 +8105,7 @@ nsresult nsIFrame::GetPointFromOffset(int32_t inOffset, nsPoint* outPoint) {
bool hasBidiData;
FrameBidiData bidiData = GetProperty(BidiDataProperty(), &hasBidiData);
bool isRTL = hasBidiData
? bidiData.embeddingLevel.IsRTL()
? IS_LEVEL_RTL(bidiData.embeddingLevel)
: StyleVisibility()->mDirection == StyleDirection::Rtl;
if ((!isRTL && inOffset > newOffset) ||
(isRTL && inOffset <= newOffset)) {
@@ -9105,8 +9102,7 @@ Result<bool, nsresult> nsIFrame::IsVisuallyAtLineEdge(
return true;
}
bool frameIsRTL = (nsBidiPresUtils::FrameDirection(*framePtr) ==
mozilla::intl::Bidi::Direction::RTL);
bool frameIsRTL = (nsBidiPresUtils::FrameDirection(*framePtr) == NSBIDI_RTL);
if ((frameIsRTL == lineIsRTL) == (aDirection == eDirPrevious)) {
nsIFrame::GetFirstLeaf(framePtr);
} else {

View File

@@ -78,7 +78,6 @@
#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"
@@ -360,6 +359,76 @@ 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).<p>
*
* <li><code>aParaLevel</code> can be set to the
* pseudo-level values <code>NSBIDI_DEFAULT_LTR</code>
* and <code>NSBIDI_DEFAULT_RTL</code>.</li></ul>
*
* @see nsBidi::SetPara
*
* <p>The related constants are not real, valid level values.
* <code>NSBIDI_DEFAULT_XXX</code> can be used to specify
* a default for the paragraph level for
* when the <code>SetPara</code> function
* shall determine it but there is no
* strongly typed character in the input.<p>
*
* Note that the value for <code>NSBIDI_DEFAULT_LTR</code> is even
* and the one for <code>NSBIDI_DEFAULT_RTL</code> 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
* <code>NSBIDI_MAX_EXPLICIT_LEVEL+1</code>).
*/
#define NSBIDI_MAX_EXPLICIT_LEVEL 125
/** Bit flag for level input.
* Overrides directional properties.
*/
#define NSBIDI_LEVEL_OVERRIDE 0x80
/**
* <code>nsBidiDirection</code> 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
@@ -404,16 +473,15 @@ struct IntrinsicSize {
};
// Pseudo bidi embedding level indicating nonexistence.
static const mozilla::intl::Bidi::EmbeddingLevel kBidiLevelNone =
mozilla::intl::Bidi::EmbeddingLevel(0xff);
static const nsBidiLevel kBidiLevelNone = 0xff;
struct FrameBidiData {
mozilla::intl::Bidi::EmbeddingLevel baseLevel;
mozilla::intl::Bidi::EmbeddingLevel embeddingLevel;
nsBidiLevel baseLevel;
nsBidiLevel 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.
mozilla::intl::Bidi::EmbeddingLevel precedingControl;
nsBidiLevel precedingControl;
};
} // namespace mozilla
@@ -1330,13 +1398,9 @@ class nsIFrame : public nsQueryFrame {
return bidiData;
}
mozilla::intl::Bidi::EmbeddingLevel GetBaseLevel() const {
return GetBidiData().baseLevel;
}
nsBidiLevel GetBaseLevel() const { return GetBidiData().baseLevel; }
mozilla::intl::Bidi::EmbeddingLevel GetEmbeddingLevel() const {
return GetBidiData().embeddingLevel;
}
nsBidiLevel GetEmbeddingLevel() const { return GetBidiData().embeddingLevel; }
/**
* Return the distance between the border edge of the frame and the

View File

@@ -12,7 +12,6 @@
#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"
@@ -1435,31 +1434,31 @@ void nsImageFrame::DisplayAltText(nsPresContext* aPresContext,
nsresult rv = NS_ERROR_FAILURE;
if (aPresContext->BidiEnabled()) {
mozilla::intl::Bidi::EmbeddingLevel level;
nsBidiDirection dir;
nscoord x, y;
if (isVertical) {
x = pt.x + maxDescent;
if (wm.IsBidiLTR()) {
y = aRect.y;
level = mozilla::intl::Bidi::EmbeddingLevel::LTR();
dir = NSBIDI_LTR;
} else {
y = aRect.YMost() - strWidth;
level = mozilla::intl::Bidi::EmbeddingLevel::RTL();
dir = NSBIDI_RTL;
}
} else {
y = pt.y + maxAscent;
if (wm.IsBidiLTR()) {
x = aRect.x;
level = mozilla::intl::Bidi::EmbeddingLevel::LTR();
dir = NSBIDI_LTR;
} else {
x = aRect.XMost() - strWidth;
level = mozilla::intl::Bidi::EmbeddingLevel::RTL();
dir = NSBIDI_RTL;
}
}
rv = nsBidiPresUtils::RenderText(
str, maxFit, level, aPresContext, aRenderingContext,
str, maxFit, dir, aPresContext, aRenderingContext,
aRenderingContext.GetDrawTarget(), *fm, x, y);
}
if (NS_FAILED(rv)) {

View File

@@ -69,7 +69,6 @@
#include "nsContentUtils.h"
#include "nsLineBreaker.h"
#include "nsIFrameInlines.h"
#include "mozilla/intl/Bidi.h"
#include "mozilla/intl/WordBreaker.h"
#include "mozilla/ServoStyleSet.h"
@@ -1936,7 +1935,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 (aFrame1->GetEmbeddingLevel().IsRTL() == wm.IsBidiLTR()) {
if (IS_LEVEL_RTL(aFrame1->GetEmbeddingLevel()) == wm.IsBidiLTR()) {
std::swap(side1, side2);
}
@@ -2397,7 +2396,7 @@ already_AddRefed<gfxTextRun> BuildTextRunsScanner::BuildTextRunForFrames(
if (flags2 & nsTextFrameUtils::Flags::HasShy) {
flags |= gfx::ShapedTextFlags::TEXT_ENABLE_HYPHEN_BREAKS;
}
if (mBidiEnabled && (firstFrame->GetEmbeddingLevel().IsRTL())) {
if (mBidiEnabled && (IS_LEVEL_RTL(firstFrame->GetEmbeddingLevel()))) {
flags |= gfx::ShapedTextFlags::TEXT_IS_RTL;
}
if (mNextRunContextInfo & nsTextFrameUtils::INCOMING_WHITESPACE) {

View File

@@ -8,7 +8,6 @@
#include "gfx2DGlue.h"
#include "gfxUtils.h"
#include "mozilla/intl/Bidi.h"
#include "mozilla/Attributes.h"
#include "mozilla/ComputedStyle.h"
#include "mozilla/Preferences.h"
@@ -485,8 +484,7 @@ void nsTextBoxFrame::DrawText(gfxContext& aRenderingContext,
if (mState & NS_FRAME_IS_BIDI) {
presContext->SetBidiEnabled();
mozilla::intl::Bidi::EmbeddingLevel level =
nsBidiPresUtils::BidiLevelFromStyle(Style());
nsBidiLevel level = nsBidiPresUtils::BidiLevelFromStyle(Style());
if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) {
// We let the RenderText function calculate the mnemonic's
// underline position for us.