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 @@
+
+
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 @@
+
+
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 @@
+
+
+
+
+
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 @@
+
+
+
+
+