diff --git a/dom/base/nsGenericDOMDataNode.h b/dom/base/nsGenericDOMDataNode.h index 3eae37347..0b60860bc 100644 --- a/dom/base/nsGenericDOMDataNode.h +++ b/dom/base/nsGenericDOMDataNode.h @@ -47,10 +47,18 @@ enum { // bit is set, and if so it indicates whether we're only whitespace or // not. NS_TEXT_IS_ONLY_WHITESPACE = DATA_NODE_FLAG_BIT(3), + + // This bit is set if there is a NewlineProperty attached to the node + // (used by nsTextFrame). + NS_HAS_NEWLINE_PROPERTY = DATA_NODE_FLAG_BIT(4), + + // This bit is set if there is a FlowLengthProperty attached to the node + // (used by nsTextFrame). + NS_HAS_FLOWLENGTH_PROPERTY = DATA_NODE_FLAG_BIT(5), }; // Make sure we have enough space for those bits -ASSERT_NODE_FLAGS_SPACE(NODE_TYPE_SPECIFIC_BITS_OFFSET + 4); +ASSERT_NODE_FLAGS_SPACE(NODE_TYPE_SPECIFIC_BITS_OFFSET + 6); #undef DATA_NODE_FLAG_BIT diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build index 5f656c245..74cecfa26 100644 --- a/gfx/layers/moz.build +++ b/gfx/layers/moz.build @@ -398,6 +398,7 @@ include('/ipc/chromium/chromium-config.mozbuild') LOCAL_INCLUDES += [ '/docshell/base', # for nsDocShell.h + '/dom/base', # for nsDocument.h '/layout/base', # for TouchManager.h '/layout/generic', # for nsTextFrame.h ] diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index 00c7ed34a..d4e0e5d65 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -62,7 +62,6 @@ #include "nsContentUtils.h" #include "nsLineBreaker.h" #include "nsIWordBreaker.h" -#include "nsGenericDOMDataNode.h" #include "nsIFrameInlines.h" #include @@ -637,7 +636,9 @@ int32_t nsTextFrame::GetInFlowContentLength() { } FlowLengthProperty* flowLength = - static_cast(mContent->GetProperty(nsGkAtoms::flowlength)); + mContent->HasFlag(NS_HAS_FLOWLENGTH_PROPERTY) + ? static_cast(mContent->GetProperty(nsGkAtoms::flowlength)) + : nullptr; /** * This frame must start inside the cached flow. If the flow starts at @@ -665,6 +666,7 @@ int32_t nsTextFrame::GetInFlowContentLength() { delete flowLength; flowLength = nullptr; } + mContent->SetFlags(NS_HAS_FLOWLENGTH_PROPERTY); } if (flowLength) { flowLength->mStartOffset = mContentOffset; @@ -4073,9 +4075,13 @@ nsTextFrame::Init(nsIContent* aContent, // Remove any NewlineOffsetProperty or InFlowContentLengthProperty since they // might be invalid if the content was modified while there was no frame - aContent->DeleteProperty(nsGkAtoms::newline); - if (PresContext()->BidiEnabled()) { + if (aContent->HasFlag(NS_HAS_NEWLINE_PROPERTY)) { + aContent->DeleteProperty(nsGkAtoms::newline); + aContent->UnsetFlags(NS_HAS_NEWLINE_PROPERTY); + } + if (aContent->HasFlag(NS_HAS_FLOWLENGTH_PROPERTY)) { aContent->DeleteProperty(nsGkAtoms::flowlength); + aContent->UnsetFlags(NS_HAS_FLOWLENGTH_PROPERTY); } // Since our content has a frame now, this flag is no longer needed. @@ -4572,11 +4578,15 @@ nsTextFrame::DisconnectTextRuns() nsresult nsTextFrame::CharacterDataChanged(CharacterDataChangeInfo* aInfo) { - mContent->DeleteProperty(nsGkAtoms::newline); - if (PresContext()->BidiEnabled()) { - mContent->DeleteProperty(nsGkAtoms::flowlength); + if (mContent->HasFlag(NS_HAS_NEWLINE_PROPERTY)) { + mContent->DeleteProperty(nsGkAtoms::newline); + mContent->UnsetFlags(NS_HAS_NEWLINE_PROPERTY); } - + if (mContent->HasFlag(NS_HAS_FLOWLENGTH_PROPERTY)) { + mContent->DeleteProperty(nsGkAtoms::flowlength); + mContent->UnsetFlags(NS_HAS_FLOWLENGTH_PROPERTY); + } + // Find the first frame whose text has changed. Frames that are entirely // before the text change are completely unaffected. nsTextFrame* next; @@ -8588,7 +8598,9 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, NewlineProperty* cachedNewlineOffset = nullptr; if (textStyle->NewlineIsSignificant(this)) { cachedNewlineOffset = - static_cast(mContent->GetProperty(nsGkAtoms::newline)); + mContent->HasFlag(NS_HAS_NEWLINE_PROPERTY) + ? static_cast(mContent->GetProperty(nsGkAtoms::newline)) + : nullptr; if (cachedNewlineOffset && cachedNewlineOffset->mStartOffset <= offset && (cachedNewlineOffset->mNewlineOffset == -1 || cachedNewlineOffset->mNewlineOffset >= offset)) { @@ -9039,6 +9051,7 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, delete cachedNewlineOffset; cachedNewlineOffset = nullptr; } + mContent->SetFlags(NS_HAS_NEWLINE_PROPERTY); } if (cachedNewlineOffset) { cachedNewlineOffset->mStartOffset = offset; @@ -9046,6 +9059,7 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, } } else if (cachedNewlineOffset) { mContent->DeleteProperty(nsGkAtoms::newline); + mContent->UnsetFlags(NS_HAS_NEWLINE_PROPERTY); } // Compute space and letter counts for justification, if required @@ -9496,7 +9510,10 @@ void nsTextFrame::AdjustOffsetsForBidi(int32_t aStart, int32_t aEnd) { AddStateBits(NS_FRAME_IS_BIDI); - mContent->DeleteProperty(nsGkAtoms::flowlength); + if (mContent->HasFlag(NS_HAS_FLOWLENGTH_PROPERTY)) { + mContent->DeleteProperty(nsGkAtoms::flowlength); + mContent->UnsetFlags(NS_HAS_FLOWLENGTH_PROPERTY); + } /* * After Bidi resolution we may need to reassign text runs. diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h index ec8964117..9a237b187 100644 --- a/layout/generic/nsTextFrame.h +++ b/layout/generic/nsTextFrame.h @@ -10,6 +10,7 @@ #include "mozilla/EventForwards.h" #include "mozilla/gfx/2D.h" #include "nsFrame.h" +#include "nsGenericDOMDataNode.h" #include "nsSplittableFrame.h" #include "nsLineBox.h" #include "gfxSkipChars.h" @@ -92,7 +93,10 @@ public: aNextContinuation->RemoveStateBits(NS_FRAME_IS_FLUID_CONTINUATION); // Setting a non-fluid continuation might affect our flow length (they're // quite rare so we assume it always does) so we delete our cached value: - GetContent()->DeleteProperty(nsGkAtoms::flowlength); + if (GetContent()->HasFlag(NS_HAS_FLOWLENGTH_PROPERTY)) { + GetContent()->DeleteProperty(nsGkAtoms::flowlength); + GetContent()->UnsetFlags(NS_HAS_FLOWLENGTH_PROPERTY); + } } virtual nsIFrame* GetNextInFlowVirtual() const override { return GetNextInFlow(); } nsIFrame* GetNextInFlow() const { @@ -109,7 +113,10 @@ public: !mNextContinuation->HasAnyStateBits(NS_FRAME_IS_FLUID_CONTINUATION)) { // Changing from non-fluid to fluid continuation might affect our flow // length, so we delete our cached value: - GetContent()->DeleteProperty(nsGkAtoms::flowlength); + if (GetContent()->HasFlag(NS_HAS_FLOWLENGTH_PROPERTY)) { + GetContent()->DeleteProperty(nsGkAtoms::flowlength); + GetContent()->UnsetFlags(NS_HAS_FLOWLENGTH_PROPERTY); + } } if (aNextInFlow) { aNextInFlow->AddStateBits(NS_FRAME_IS_FLUID_CONTINUATION);