зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
51a69dce6a
Коммит
40648350fd
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Загрузка…
Ссылка в новой задаче