diff --git a/dom/base/nsGenericDOMDataNode.h b/dom/base/nsGenericDOMDataNode.h index 76351c2c1c54..6f3194e00df8 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/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index 16b6457893c0..0a7b87411807 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -64,7 +64,6 @@ #include "nsContentUtils.h" #include "nsLineBreaker.h" #include "nsIWordBreaker.h" -#include "nsGenericDOMDataNode.h" #include "nsIFrameInlines.h" #include "mozilla/StyleSetHandle.h" #include "mozilla/StyleSetHandleInlines.h" @@ -736,7 +735,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 @@ -764,6 +765,7 @@ int32_t nsTextFrame::GetInFlowContentLength() { delete flowLength; flowLength = nullptr; } + mContent->SetFlags(NS_HAS_FLOWLENGTH_PROPERTY); } if (flowLength) { flowLength->mStartOffset = mContentOffset; @@ -4380,9 +4382,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. @@ -4830,9 +4836,13 @@ nsTextFrame::DisconnectTextRuns() nsresult nsTextFrame::CharacterDataChanged(CharacterDataChangeInfo* aInfo) { - mContent->DeleteProperty(nsGkAtoms::newline); - if (PresContext()->BidiEnabled()) { + 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 @@ -9278,7 +9288,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)) { @@ -9763,6 +9775,7 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, delete cachedNewlineOffset; cachedNewlineOffset = nullptr; } + mContent->SetFlags(NS_HAS_NEWLINE_PROPERTY); } if (cachedNewlineOffset) { cachedNewlineOffset->mStartOffset = offset; @@ -9770,6 +9783,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 @@ -10252,7 +10266,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 3639bc7a7f59..e92c592d8e52 100644 --- a/layout/generic/nsTextFrame.h +++ b/layout/generic/nsTextFrame.h @@ -12,6 +12,7 @@ #include "mozilla/UniquePtr.h" #include "nsFrame.h" #include "nsFrameSelection.h" +#include "nsGenericDOMDataNode.h" #include "nsSplittableFrame.h" #include "nsLineBox.h" #include "gfxSkipChars.h" @@ -96,7 +97,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); + } } nsIFrame* GetNextInFlowVirtual() const override { return GetNextInFlow(); } nsTextFrame* GetNextInFlow() const @@ -119,7 +123,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);