зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1554461 - Use an array to store nsContinuationStates when the number of them is low. r=jfkthame
Differential Revision: https://phabricator.services.mozilla.com/D32617 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
e52ded1092
Коммит
112bcc43db
|
@ -1356,10 +1356,11 @@ nsBidiLevel nsBidiPresUtils::GetFrameBaseLevel(nsIFrame* aFrame) {
|
|||
return firstLeaf->GetBaseLevel();
|
||||
}
|
||||
|
||||
void nsBidiPresUtils::IsFirstOrLast(
|
||||
nsIFrame* aFrame, const nsContinuationStates* aContinuationStates,
|
||||
bool aSpanDirMatchesLineDir, bool& aIsFirst /* out */,
|
||||
bool& aIsLast /* out */) {
|
||||
void nsBidiPresUtils::IsFirstOrLast(nsIFrame* aFrame,
|
||||
nsContinuationStates* aContinuationStates,
|
||||
bool aSpanDirMatchesLineDir,
|
||||
bool& aIsFirst /* out */,
|
||||
bool& aIsLast /* out */) {
|
||||
/*
|
||||
* Since we lay out frames in the line's direction, visiting a frame with
|
||||
* 'mFirstVisualFrame == nullptr', means it's the first appearance of one
|
||||
|
@ -1372,7 +1373,7 @@ void nsBidiPresUtils::IsFirstOrLast(
|
|||
*/
|
||||
|
||||
bool firstInLineOrder, lastInLineOrder;
|
||||
nsFrameContinuationState* frameState = aContinuationStates->GetEntry(aFrame);
|
||||
nsFrameContinuationState* frameState = aContinuationStates->Get(aFrame);
|
||||
nsFrameContinuationState* firstFrameState;
|
||||
|
||||
if (!frameState->mFirstVisualFrame) {
|
||||
|
@ -1390,7 +1391,7 @@ void nsBidiPresUtils::IsFirstOrLast(
|
|||
*/
|
||||
// Traverse continuation chain backward
|
||||
for (frame = aFrame->GetPrevContinuation();
|
||||
frame && (contState = aContinuationStates->GetEntry(frame));
|
||||
frame && (contState = aContinuationStates->Get(frame));
|
||||
frame = frame->GetPrevContinuation()) {
|
||||
frameState->mFrameCount++;
|
||||
contState->mFirstVisualFrame = aFrame;
|
||||
|
@ -1399,7 +1400,7 @@ void nsBidiPresUtils::IsFirstOrLast(
|
|||
|
||||
// Traverse continuation chain forward
|
||||
for (frame = aFrame->GetNextContinuation();
|
||||
frame && (contState = aContinuationStates->GetEntry(frame));
|
||||
frame && (contState = aContinuationStates->Get(frame));
|
||||
frame = frame->GetNextContinuation()) {
|
||||
frameState->mFrameCount++;
|
||||
contState->mFirstVisualFrame = aFrame;
|
||||
|
@ -1411,8 +1412,7 @@ void nsBidiPresUtils::IsFirstOrLast(
|
|||
} else {
|
||||
// aFrame is not the first visual frame of its continuation chain
|
||||
firstInLineOrder = false;
|
||||
firstFrameState =
|
||||
aContinuationStates->GetEntry(frameState->mFirstVisualFrame);
|
||||
firstFrameState = aContinuationStates->Get(frameState->mFirstVisualFrame);
|
||||
}
|
||||
|
||||
lastInLineOrder = (firstFrameState->mFrameCount == 1);
|
||||
|
@ -1507,7 +1507,7 @@ void nsBidiPresUtils::RepositionRubyContentFrame(
|
|||
|
||||
/* static */
|
||||
nscoord nsBidiPresUtils::RepositionRubyFrame(
|
||||
nsIFrame* aFrame, const nsContinuationStates* aContinuationStates,
|
||||
nsIFrame* aFrame, nsContinuationStates* aContinuationStates,
|
||||
const WritingMode aContainerWM, const LogicalMargin& aBorderPadding) {
|
||||
LayoutFrameType frameType = aFrame->Type();
|
||||
MOZ_ASSERT(RubyUtils::IsRubyBox(frameType));
|
||||
|
@ -1570,7 +1570,7 @@ nscoord nsBidiPresUtils::RepositionRubyFrame(
|
|||
/* static */
|
||||
nscoord nsBidiPresUtils::RepositionFrame(
|
||||
nsIFrame* aFrame, bool aIsEvenLevel, nscoord aStartOrEnd,
|
||||
const nsContinuationStates* aContinuationStates, WritingMode aContainerWM,
|
||||
nsContinuationStates* aContinuationStates, WritingMode aContainerWM,
|
||||
bool aContainerReverseDir, const nsSize& aContainerSize) {
|
||||
nscoord lineSize =
|
||||
aContainerWM.IsVertical() ? aContainerSize.height : aContainerSize.width;
|
||||
|
@ -1671,7 +1671,7 @@ nscoord nsBidiPresUtils::RepositionFrame(
|
|||
|
||||
void nsBidiPresUtils::InitContinuationStates(
|
||||
nsIFrame* aFrame, nsContinuationStates* aContinuationStates) {
|
||||
aContinuationStates->PutEntry(aFrame);
|
||||
aContinuationStates->Insert(aFrame);
|
||||
if (!IsBidiLeaf(aFrame) || RubyUtils::IsRubyBox(aFrame->Type())) {
|
||||
// Continue for child frames
|
||||
for (nsIFrame* frame : aFrame->PrincipalChildList()) {
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "nsBidiUtils.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsCoord.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
#ifdef DrawText
|
||||
# undef DrawText
|
||||
|
@ -68,10 +69,50 @@ struct nsFrameContinuationState : public nsVoidPtrHashKey {
|
|||
bool mHasContOnNextLines{false};
|
||||
};
|
||||
|
||||
/*
|
||||
* Following type is used to pass needed hashtable to reordering methods
|
||||
*/
|
||||
typedef nsTHashtable<nsFrameContinuationState> nsContinuationStates;
|
||||
// A table of nsFrameContinuationState objects.
|
||||
//
|
||||
// This state is used between calls to nsBidiPresUtils::IsFirstOrLast.
|
||||
struct nsContinuationStates {
|
||||
static constexpr size_t kArrayMax = 32;
|
||||
|
||||
// We use the array to gather up all the continuation state objects. If in
|
||||
// the end there are more than kArrayMax of them, we convert it to a hash
|
||||
// table for faster lookup.
|
||||
bool mUseTable = false;
|
||||
AutoTArray<nsFrameContinuationState, kArrayMax> mValues;
|
||||
nsTHashtable<nsFrameContinuationState> mTable;
|
||||
|
||||
void Insert(nsIFrame* aFrame) {
|
||||
if (MOZ_UNLIKELY(mUseTable)) {
|
||||
mTable.PutEntry(aFrame);
|
||||
return;
|
||||
}
|
||||
if (MOZ_LIKELY(mValues.Length() < kArrayMax)) {
|
||||
mValues.AppendElement(aFrame);
|
||||
return;
|
||||
}
|
||||
for (const auto& entry : mValues) {
|
||||
mTable.PutEntry(entry.GetKey());
|
||||
}
|
||||
mTable.PutEntry(aFrame);
|
||||
mValues.Clear();
|
||||
mUseTable = true;
|
||||
}
|
||||
|
||||
nsFrameContinuationState* Get(nsIFrame* aFrame) {
|
||||
MOZ_ASSERT(mValues.IsEmpty() != mTable.IsEmpty(),
|
||||
"expect entries to either be in mValues or in mTable");
|
||||
if (mUseTable) {
|
||||
return mTable.GetEntry(aFrame);
|
||||
}
|
||||
for (size_t i = 0, len = mValues.Length(); i != len; ++i) {
|
||||
if (mValues[i].GetKey() == aFrame) {
|
||||
return &mValues[i];
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A structure representing a logical position which should be resolved
|
||||
|
@ -409,7 +450,7 @@ class nsBidiPresUtils {
|
|||
* Position ruby frames. Called from RepositionFrame.
|
||||
*/
|
||||
static nscoord RepositionRubyFrame(
|
||||
nsIFrame* aFrame, const nsContinuationStates* aContinuationStates,
|
||||
nsIFrame* aFrame, nsContinuationStates* aContinuationStates,
|
||||
const mozilla::WritingMode aContainerWM,
|
||||
const mozilla::LogicalMargin& aBorderPadding);
|
||||
|
||||
|
@ -430,11 +471,12 @@ class nsBidiPresUtils {
|
|||
* nsFrameContinuationState
|
||||
* @return The isize aFrame takes, including margins.
|
||||
*/
|
||||
static nscoord RepositionFrame(
|
||||
nsIFrame* aFrame, bool aIsEvenLevel, nscoord aStartOrEnd,
|
||||
const nsContinuationStates* aContinuationStates,
|
||||
mozilla::WritingMode aContainerWM, bool aContainerReverseOrder,
|
||||
const nsSize& aContainerSize);
|
||||
static nscoord RepositionFrame(nsIFrame* aFrame, bool aIsEvenLevel,
|
||||
nscoord aStartOrEnd,
|
||||
nsContinuationStates* aContinuationStates,
|
||||
mozilla::WritingMode aContainerWM,
|
||||
bool aContainerReverseOrder,
|
||||
const nsSize& aContainerSize);
|
||||
|
||||
/*
|
||||
* Initialize the continuation state(nsFrameContinuationState) to
|
||||
|
@ -473,7 +515,7 @@ class nsBidiPresUtils {
|
|||
* or continuation
|
||||
*/
|
||||
static void IsFirstOrLast(nsIFrame* aFrame,
|
||||
const nsContinuationStates* aContinuationStates,
|
||||
nsContinuationStates* aContinuationStates,
|
||||
bool aSpanInLineOrder /* in */,
|
||||
bool& aIsFirst /* out */, bool& aIsLast /* out */);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче