diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index d2a98959a5fb..bbb7b32013e8 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -244,6 +244,10 @@ typedef uint64_t nsFrameState; // placeholder. This can happen for two reasons: (1) the float was // split, and this piece is the continuation, or (2) the entire float // didn't fit on the page. +// Note that this bit is also shared by text frames for +// TEXT_FORCE_TRIM_WHITESPACE. That's OK because we only check the +// NS_FRAME_IS_PUSHED_FLOAT bit on frames which we already know are +// out-of-flow. #define NS_FRAME_IS_PUSHED_FLOAT NS_FRAME_STATE_BIT(32) // This bit acts as a loop flag for recursive paint server drawing. diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h index 6fb4a838ef77..7dfe39f3311b 100644 --- a/layout/generic/nsTextFrame.h +++ b/layout/generic/nsTextFrame.h @@ -21,6 +21,10 @@ class PropertyProvider; // reflow #define TEXT_HAS_NONCOLLAPSED_CHARACTERS NS_FRAME_STATE_BIT(31) +// This state bit is set on frames which are forced to trim their leading and +// trailing whitespaces +#define TEXT_FORCE_TRIM_WHITESPACE NS_FRAME_STATE_BIT(32) + #define TEXT_HAS_FONT_INFLATION NS_FRAME_STATE_BIT(61) typedef nsFrame nsTextFrameBase; diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index adfdfa6d22b9..9420e292afa4 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -196,6 +196,9 @@ NS_DECLARE_FRAME_PROPERTY(FontSizeInflationProperty, nullptr) // nsTextFrame.h has // #define TEXT_HAS_NONCOLLAPSED_CHARACTERS NS_FRAME_STATE_BIT(31) +// nsTextFrame.h has +// #define TEXT_FORCE_TRIM_WHITESPACE NS_FRAME_STATE_BIT(32) + // Set when this text frame is mentioned in the userdata for the // uninflated textrun property #define TEXT_IN_UNINFLATED_TEXTRUN_USER_DATA NS_FRAME_STATE_BIT(60) @@ -7612,7 +7615,8 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, length = newLineOffset + 1 - offset; } } - if (atStartOfLine && !textStyle->WhiteSpaceIsSignificant()) { + if ((atStartOfLine && !textStyle->WhiteSpaceIsSignificant()) || + (GetStateBits() & TEXT_FORCE_TRIM_WHITESPACE)) { // Skip leading whitespace. Make sure we don't skip a 'pre-line' // newline if there is one. int32_t skipLength = newLineOffset >= 0 ? length - 1 : length; @@ -7770,7 +7774,8 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, bool usedHyphenation; gfxFloat trimmedWidth = 0; gfxFloat availWidth = aAvailableWidth; - bool canTrimTrailingWhitespace = !textStyle->WhiteSpaceIsSignificant(); + bool canTrimTrailingWhitespace = !textStyle->WhiteSpaceIsSignificant() || + (GetStateBits() & TEXT_FORCE_TRIM_WHITESPACE); int32_t unusedOffset; gfxBreakPriority breakPriority; aLineLayout.GetLastOptionalBreakPosition(&unusedOffset, &breakPriority); @@ -7839,11 +7844,12 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, // the line. (If we actually do end up at the end of the line, we'll have // to trim it off again in TrimTrailingWhiteSpace, and we'd like to avoid // having to re-do it.) - if (brokeText) { + if (brokeText || + (GetStateBits() & TEXT_FORCE_TRIM_WHITESPACE)) { // We're definitely going to break so our trailing whitespace should - // definitely be timmed. Record that we've already done it. + // definitely be trimmed. Record that we've already done it. AddStateBits(TEXT_TRIMMED_TRAILING_WHITESPACE); - } else { + } else if (!(GetStateBits() & TEXT_FORCE_TRIM_WHITESPACE)) { // We might not be at the end of the line. (Note that even if this frame // ends in breakable whitespace, it might not be at the end of the line // because it might be followed by breakable, but preformatted, whitespace.) diff --git a/layout/mathml/nsMathMLTokenFrame.cpp b/layout/mathml/nsMathMLTokenFrame.cpp index dddd671981e7..a38436d27f44 100644 --- a/layout/mathml/nsMathMLTokenFrame.cpp +++ b/layout/mathml/nsMathMLTokenFrame.cpp @@ -11,6 +11,7 @@ #include "nsContentUtils.h" #include "nsCSSFrameConstructor.h" #include "nsMathMLTokenFrame.h" +#include "nsTextFrame.h" nsIFrame* NS_NewMathMLTokenFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) @@ -68,6 +69,7 @@ nsMathMLTokenFrame::GetMathMLFrameType() else if(style.EqualsLiteral("invariant")) { nsAutoString data; nsContentUtils::GetNodeTextContent(mContent, false, data); + data.CompressWhitespace(); eMATHVARIANT variant = nsMathMLOperators::LookupInvariantChar(data); switch (variant) { @@ -85,35 +87,19 @@ nsMathMLTokenFrame::GetMathMLFrameType() return eMathMLFrameType_UprightIdentifier; } -static void -CompressWhitespace(nsIContent* aContent) +void +nsMathMLTokenFrame::ForceTrimChildTextFrames() { - uint32_t numKids = aContent->GetChildCount(); - for (uint32_t kid = 0; kid < numKids; kid++) { - nsIContent* cont = aContent->GetChildAt(kid); - if (cont && cont->IsNodeOfType(nsINode::eTEXT)) { - nsAutoString text; - cont->AppendTextTo(text); - text.CompressWhitespace(); - cont->SetText(text, false); // not meant to be used if notify is needed + // Set flags on child text frames to force them to trim their leading and + // trailing whitespaces. + for (nsIFrame* childFrame = GetFirstPrincipalChild(); childFrame; + childFrame = childFrame->GetNextSibling()) { + if (childFrame->GetType() == nsGkAtoms::textFrame) { + childFrame->AddStateBits(TEXT_FORCE_TRIM_WHITESPACE); } } } -NS_IMETHODIMP -nsMathMLTokenFrame::Init(nsIContent* aContent, - nsIFrame* aParent, - nsIFrame* aPrevInFlow) -{ - // leading and trailing whitespace doesn't count -- bug 15402 - // brute force removal for people who do a instead of a - // XXX the best fix is to skip these in nsTextFrame - CompressWhitespace(aContent); - - // let the base class do its Init() - return nsMathMLContainerFrame::Init(aContent, aParent, aPrevInFlow); -} - NS_IMETHODIMP nsMathMLTokenFrame::SetInitialChildList(ChildListID aListID, nsFrameList& aChildList) @@ -123,11 +109,41 @@ nsMathMLTokenFrame::SetInitialChildList(ChildListID aListID, if (NS_FAILED(rv)) return rv; + ForceTrimChildTextFrames(); + SetQuotes(false); ProcessTextData(); return rv; } +NS_IMETHODIMP +nsMathMLTokenFrame::AppendFrames(ChildListID aListID, + nsFrameList& aChildList) +{ + nsresult rv = nsMathMLContainerFrame::AppendFrames(aListID, aChildList); + if (NS_FAILED(rv)) + return rv; + + ForceTrimChildTextFrames(); + + return rv; +} + +NS_IMETHODIMP +nsMathMLTokenFrame::InsertFrames(ChildListID aListID, + nsIFrame* aPrevFrame, + nsFrameList& aChildList) +{ + nsresult rv = nsMathMLContainerFrame::InsertFrames(aListID, aPrevFrame, + aChildList); + if (NS_FAILED(rv)) + return rv; + + ForceTrimChildTextFrames(); + + return rv; +} + nsresult nsMathMLTokenFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -297,6 +313,7 @@ nsMathMLTokenFrame::SetTextStyle() // Get the text content that we enclose and its length nsAutoString data; nsContentUtils::GetNodeTextContent(mContent, false, data); + data.CompressWhitespace(); int32_t length = data.Length(); if (!length) return false; diff --git a/layout/mathml/nsMathMLTokenFrame.h b/layout/mathml/nsMathMLTokenFrame.h index 828ac4db64bb..6bc8939bc13e 100644 --- a/layout/mathml/nsMathMLTokenFrame.h +++ b/layout/mathml/nsMathMLTokenFrame.h @@ -34,15 +34,19 @@ public: virtual eMathMLFrameType GetMathMLFrameType(); - NS_IMETHOD - Init(nsIContent* aContent, - nsIFrame* aParent, - nsIFrame* aPrevInFlow); - NS_IMETHOD SetInitialChildList(ChildListID aListID, nsFrameList& aChildList); + NS_IMETHOD + AppendFrames(ChildListID aListID, + nsFrameList& aChildList); + + NS_IMETHOD + InsertFrames(ChildListID aListID, + nsIFrame* aPrevFrame, + nsFrameList& aChildList); + NS_IMETHOD Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -83,6 +87,8 @@ protected: // helper to set the quotes of void SetQuotes(bool aNotify); + + void ForceTrimChildTextFrames(); }; #endif /* nsMathMLTokentFrame_h___ */ diff --git a/layout/mathml/nsMathMLmoFrame.cpp b/layout/mathml/nsMathMLmoFrame.cpp index 116887d4b2a6..1d7361220a7a 100644 --- a/layout/mathml/nsMathMLmoFrame.cpp +++ b/layout/mathml/nsMathMLmoFrame.cpp @@ -122,6 +122,7 @@ nsMathMLmoFrame::ProcessTextData() nsAutoString data; nsContentUtils::GetNodeTextContent(mContent, false, data); + data.CompressWhitespace(); int32_t length = data.Length(); PRUnichar ch = (length == 0) ? kNullCh : data[0]; diff --git a/layout/reftests/mathml/reftest.list b/layout/reftests/mathml/reftest.list index 5e4750d9b7dd..26a40fbaf541 100644 --- a/layout/reftests/mathml/reftest.list +++ b/layout/reftests/mathml/reftest.list @@ -104,3 +104,8 @@ fails == mstyle-5.xhtml mstyle-5-ref.xhtml # See bug 569125#c29 == maction-dynamic-2.html maction-dynamic-2-ref.html == mo-lspace-rspace.html mo-lspace-rspace-ref.html == maction-dynamic-3.html maction-dynamic-3-ref.html +== whitespace-trim-1.html whitespace-trim-1-ref.html +== whitespace-trim-2.html whitespace-trim-2-ref.html +== whitespace-trim-3.html whitespace-trim-3-ref.html +fails == whitespace-trim-4.html whitespace-trim-4-ref.html # Bug 560100 +== whitespace-trim-5.html whitespace-trim-5-ref.html diff --git a/layout/reftests/mathml/whitespace-trim-1-ref.html b/layout/reftests/mathml/whitespace-trim-1-ref.html new file mode 100644 index 000000000000..b2145dedf0bf --- /dev/null +++ b/layout/reftests/mathml/whitespace-trim-1-ref.html @@ -0,0 +1,2 @@ + +( diff --git a/layout/reftests/mathml/whitespace-trim-1.html b/layout/reftests/mathml/whitespace-trim-1.html new file mode 100644 index 000000000000..59aeb9af8be8 --- /dev/null +++ b/layout/reftests/mathml/whitespace-trim-1.html @@ -0,0 +1,2 @@ + + ( diff --git a/layout/reftests/mathml/whitespace-trim-2-ref.html b/layout/reftests/mathml/whitespace-trim-2-ref.html new file mode 100644 index 000000000000..8b8f7b8129b2 --- /dev/null +++ b/layout/reftests/mathml/whitespace-trim-2-ref.html @@ -0,0 +1,2 @@ + +( diff --git a/layout/reftests/mathml/whitespace-trim-2.html b/layout/reftests/mathml/whitespace-trim-2.html new file mode 100644 index 000000000000..d1c27c698dae --- /dev/null +++ b/layout/reftests/mathml/whitespace-trim-2.html @@ -0,0 +1,2 @@ + + ( diff --git a/layout/reftests/mathml/whitespace-trim-3-ref.html b/layout/reftests/mathml/whitespace-trim-3-ref.html new file mode 100644 index 000000000000..4a9928a69fee --- /dev/null +++ b/layout/reftests/mathml/whitespace-trim-3-ref.html @@ -0,0 +1,2 @@ + + diff --git a/layout/reftests/mathml/whitespace-trim-3.html b/layout/reftests/mathml/whitespace-trim-3.html new file mode 100644 index 000000000000..61f16888a160 --- /dev/null +++ b/layout/reftests/mathml/whitespace-trim-3.html @@ -0,0 +1,2 @@ + + diff --git a/layout/reftests/mathml/whitespace-trim-4-ref.html b/layout/reftests/mathml/whitespace-trim-4-ref.html new file mode 100644 index 000000000000..f5951467cbcc --- /dev/null +++ b/layout/reftests/mathml/whitespace-trim-4-ref.html @@ -0,0 +1,2 @@ + +x diff --git a/layout/reftests/mathml/whitespace-trim-4.html b/layout/reftests/mathml/whitespace-trim-4.html new file mode 100644 index 000000000000..01120098c959 --- /dev/null +++ b/layout/reftests/mathml/whitespace-trim-4.html @@ -0,0 +1,2 @@ + + x diff --git a/layout/reftests/mathml/whitespace-trim-5-ref.html b/layout/reftests/mathml/whitespace-trim-5-ref.html new file mode 100644 index 000000000000..560259c86fc9 --- /dev/null +++ b/layout/reftests/mathml/whitespace-trim-5-ref.html @@ -0,0 +1,5 @@ + +|x| +|x| +|x| +|x| diff --git a/layout/reftests/mathml/whitespace-trim-5.html b/layout/reftests/mathml/whitespace-trim-5.html new file mode 100644 index 000000000000..7b06950559de --- /dev/null +++ b/layout/reftests/mathml/whitespace-trim-5.html @@ -0,0 +1,5 @@ + +| x | +| x | +| x | +| x |