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:
Cameron McCormack 2019-05-31 11:42:42 +00:00
Родитель e52ded1092
Коммит 112bcc43db
2 изменённых файлов: 65 добавлений и 23 удалений

Просмотреть файл

@ -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 */);