Bug 1679645 - Cache the selection state in nsTextFrame rather than in nsDisplayText r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D108646
This commit is contained in:
Miko Mynttinen 2021-03-23 18:21:02 +00:00
Родитель 51a69dce6a
Коммит 40648350fd
4 изменённых файлов: 31 добавлений и 33 удалений

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

@ -4899,12 +4899,10 @@ void nsTextFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
bool isTextTransparent =
NS_GET_A(st->mWebkitTextFillColor.CalcColor(this)) == 0 &&
NS_GET_A(st->mWebkitTextStrokeColor.CalcColor(this)) == 0;
Maybe<bool> isSelected;
if ((HasAnyStateBits(TEXT_NO_RENDERED_GLYPHS) ||
(isTextTransparent && !StyleText()->HasTextShadow())) &&
aBuilder->IsForPainting() && !SVGUtils::IsInSVGTextSubtree(this)) {
isSelected.emplace(IsSelected());
if (!isSelected.value()) {
if (!IsSelected()) {
TextDecorations textDecs;
GetTextDecorations(PresContext(), eResolvedColors, textDecs);
if (!textDecs.HasDecorationLines()) {
@ -4916,7 +4914,7 @@ void nsTextFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
}
}
aLists.Content()->AppendNewToTop<nsDisplayText>(aBuilder, this, isSelected);
aLists.Content()->AppendNewToTop<nsDisplayText>(aBuilder, this);
}
UniquePtr<SelectionDetails> nsTextFrame::GetSelectionDetails() {
@ -7430,7 +7428,14 @@ bool nsTextFrame::CombineSelectionUnderlineRect(nsPresContext* aPresContext,
bool nsTextFrame::IsFrameSelected() const {
NS_ASSERTION(!GetContent() || GetContent()->IsMaybeSelected(),
"use the public IsSelected() instead");
return GetContent()->IsSelected(GetContentOffset(), GetContentEnd());
if (mIsSelected == nsTextFrame::SelectionState::Unknown) {
const bool isSelected =
GetContent()->IsSelected(GetContentOffset(), GetContentEnd());
mIsSelected = isSelected ? nsTextFrame::SelectionState::Selected
: nsTextFrame::SelectionState::NotSelected;
}
return mIsSelected == nsTextFrame::SelectionState::Selected;
}
void nsTextFrame::SelectionStateChanged(uint32_t aStart, uint32_t aEnd,
@ -7440,6 +7445,8 @@ void nsTextFrame::SelectionStateChanged(uint32_t aStart, uint32_t aEnd,
"Should only be called for primary frame");
DEBUG_VERIFY_NOT_DIRTY(mState);
mIsSelected = nsTextFrame::SelectionState::Unknown;
// Selection is collapsed, which can't affect text frame rendering
if (aStart == aEnd) return;
@ -9049,6 +9056,7 @@ void nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
DrawTarget* aDrawTarget, ReflowOutput& aMetrics,
nsReflowStatus& aStatus) {
MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
mIsSelected = nsTextFrame::SelectionState::Unknown;
#ifdef NOISY_REFLOW
ListTag(stdout);

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

@ -202,7 +202,8 @@ class nsTextFrame : public nsIFrame {
mNextContinuation(nullptr),
mContentOffset(0),
mContentLengthHint(0),
mAscent(0) {}
mAscent(0),
mIsSelected(SelectionState::Unknown) {}
NS_DECL_FRAMEARENA_HELPERS(nsTextFrame)
@ -802,6 +803,14 @@ class nsTextFrame : public nsIFrame {
int32_t mContentLengthHint;
nscoord mAscent;
// Cached selection state.
enum class SelectionState : uint8_t {
Unknown,
Selected,
NotSelected,
};
mutable SelectionState mIsSelected;
/**
* Return true if the frame is part of a Selection.
* Helper method to implement the public IsSelected() API.

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

@ -8752,25 +8752,24 @@ bool nsDisplayPerspective::ComputeVisibility(nsDisplayListBuilder* aBuilder,
}
nsDisplayText::nsDisplayText(nsDisplayListBuilder* aBuilder,
nsTextFrame* aFrame,
const Maybe<bool>& aIsSelected)
nsTextFrame* aFrame)
: nsPaintedDisplayItem(aBuilder, aFrame),
mOpacity(1.0f),
mVisIStartEdge(0),
mVisIEndEdge(0) {
MOZ_COUNT_CTOR(nsDisplayText);
mIsFrameSelected = aIsSelected;
mBounds = mFrame->InkOverflowRectRelativeToSelf() + ToReferenceFrame();
// Bug 748228
mBounds.Inflate(mFrame->PresContext()->AppUnitsPerDevPixel());
}
bool nsDisplayText::CanApplyOpacity() const {
if (IsSelected()) {
auto* f = static_cast<nsTextFrame*>(mFrame);
if (f->IsSelected()) {
return false;
}
nsTextFrame* f = static_cast<nsTextFrame*>(mFrame);
const nsStyleText* textStyle = f->StyleText();
if (textStyle->HasTextShadow()) {
return false;
@ -8841,7 +8840,7 @@ bool nsDisplayText::CreateWebRenderCommands(
// view. Also if we're selected we might have some shadows from the
// ::selected and ::inctive-selected pseudo-selectors. So don't do this
// optimization if we have shadows or a selection.
if (!(IsSelected() || f->StyleText()->HasTextShadow())) {
if (!(f->IsSelected() || f->StyleText()->HasTextShadow())) {
nsRect visible = GetPaintRect();
visible.Inflate(3 * appUnitsPerDevPixel);
bounds = bounds.Intersect(visible);
@ -8927,23 +8926,13 @@ void nsDisplayText::RenderToContext(gfxContext* aCtx,
}
f->PaintText(params, mVisIStartEdge, mVisIEndEdge, ToReferenceFrame(),
IsSelected(), mOpacity);
f->IsSelected(), mOpacity);
if (willClip) {
aCtx->PopClip();
}
}
bool nsDisplayText::IsSelected() const {
if (mIsFrameSelected.isNothing()) {
MOZ_ASSERT((nsTextFrame*)do_QueryFrame(mFrame));
auto* f = static_cast<nsTextFrame*>(mFrame);
mIsFrameSelected.emplace(f->IsSelected());
}
return mIsFrameSelected.value();
}
class nsDisplayTextGeometry : public nsDisplayItemGenericGeometry {
public:
nsDisplayTextGeometry(nsDisplayText* aItem, nsDisplayListBuilder* aBuilder)

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

@ -7119,19 +7119,16 @@ class nsDisplayPerspective : public nsPaintedDisplayItem {
*/
class nsDisplayText final : public nsPaintedDisplayItem {
public:
nsDisplayText(nsDisplayListBuilder* aBuilder, nsTextFrame* aFrame,
const mozilla::Maybe<bool>& aIsSelected);
nsDisplayText(nsDisplayListBuilder* aBuilder, nsTextFrame* aFrame);
MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayText)
NS_DISPLAY_DECL_NAME("Text", TYPE_TEXT)
bool RestoreState() final {
if (!nsPaintedDisplayItem::RestoreState() && mIsFrameSelected.isNothing() &&
mOpacity == 1.0f) {
if (!nsPaintedDisplayItem::RestoreState() && mOpacity == 1.0f) {
return false;
}
mIsFrameSelected.reset();
mOpacity = 1.0f;
return true;
}
@ -7195,8 +7192,6 @@ class nsDisplayText final : public nsPaintedDisplayItem {
: nullptr;
}
bool IsSelected() const;
struct ClipEdges {
ClipEdges(const nsIFrame* aFrame, const nsPoint& aToReferenceFrame,
nscoord aVisIStartEdge, nscoord aVisIEndEdge) {
@ -7237,9 +7232,6 @@ class nsDisplayText final : public nsPaintedDisplayItem {
// regardless of bidi directionality; top and bottom in vertical modes).
nscoord mVisIStartEdge;
nscoord mVisIEndEdge;
// Cached result of mFrame->IsSelected(). Only initialized when needed.
mutable mozilla::Maybe<bool> mIsFrameSelected;
};
/**