author | James Kitchener <jkitch.bug@gmail.com> |
Fri, 04 Apr 2014 17:54:00 +0200 | |
changeset 177553 | 86bb1d3444bf87f77cc76d76eea17355bd7777b2 |
parent 177552 | 8eef124486621bf0d089dddcc9c1882dcabf773d |
child 177554 | 05826bb1b9a9ecba6eb3f1b48fc2f8de5c59a60a |
push id | 26556 |
push user | ryanvm@gmail.com |
push date | Tue, 08 Apr 2014 22:16:57 +0000 |
treeherder | mozilla-central@5811efc11011 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | fredw |
bugs | 875563 |
milestone | 31.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/layout/mathml/nsIMathMLFrame.h +++ b/layout/mathml/nsIMathMLFrame.h @@ -195,16 +195,23 @@ public: uint32_t aWhichFlags) = 0; // If aFrame is a child frame, returns the script increment which this frame // imposes on the specified frame, ignoring any artificial adjustments to // scriptlevel. // Returns 0 if the specified frame isn't a child frame. virtual uint8_t ScriptIncrement(nsIFrame* aFrame) = 0; + + // Returns true if the frame is considered to be an mrow for layout purposes. + // This includes inferred mrows, but excludes <mrow> elements with a single + // child. In the latter case, the child is to be treated as if it wasn't + // within an mrow, so we pretend the mrow isn't mrow-like. + virtual bool + IsMrowLike() = 0; }; // struct used by a container frame to keep track of its embellishments. // By convention, the data that we keep here is bubbled from the embellished // hierarchy, and it remains unchanged unless we have to recover from a change // that occurs in the embellished hierarchy. The struct remains in its nil // state in those frames that are not part of the embellished hierarchy. struct nsEmbellishData {
--- a/layout/mathml/nsMathMLContainerFrame.cpp +++ b/layout/mathml/nsMathMLContainerFrame.cpp @@ -1595,15 +1595,23 @@ NS_NewMathMLmathBlockFrame(nsIPresShell* { nsMathMLmathBlockFrame* it = new (aPresShell) nsMathMLmathBlockFrame(aContext); it->SetFlags(aFlags); return it; } NS_IMPL_FRAMEARENA_HELPERS(nsMathMLmathBlockFrame) +NS_QUERYFRAME_HEAD(nsMathMLmathBlockFrame) + NS_QUERYFRAME_ENTRY(nsMathMLmathBlockFrame) +NS_QUERYFRAME_TAIL_INHERITING(nsBlockFrame) + nsIFrame* NS_NewMathMLmathInlineFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) { return new (aPresShell) nsMathMLmathInlineFrame(aContext); } NS_IMPL_FRAMEARENA_HELPERS(nsMathMLmathInlineFrame) + +NS_QUERYFRAME_HEAD(nsMathMLmathInlineFrame) + NS_QUERYFRAME_ENTRY(nsIMathMLFrame) +NS_QUERYFRAME_TAIL_INHERITING(nsInlineFrame)
--- a/layout/mathml/nsMathMLContainerFrame.h +++ b/layout/mathml/nsMathMLContainerFrame.h @@ -403,16 +403,18 @@ private: // simply mapping to nsBlockFrame or nsInlineFrame. // A separate implemention needs to provide: // 1) line-breaking // 2) proper inter-frame spacing // 3) firing of Stretch() (in which case FinalizeReflow() would have to be cleaned) // Issues: If/when mathml becomes a pluggable component, the separation will be needed. class nsMathMLmathBlockFrame : public nsBlockFrame { public: + NS_DECL_QUERYFRAME_TARGET(nsMathMLmathBlockFrame) + NS_DECL_QUERYFRAME NS_DECL_FRAMEARENA_HELPERS friend nsIFrame* NS_NewMathMLmathBlockFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, nsFrameState aFlags); // beware, mFrames is not set by nsBlockFrame // cannot use mFrames{.FirstChild()|.etc} since the block code doesn't set mFrames virtual nsresult @@ -463,29 +465,38 @@ public: return rv; } virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE { return nsBlockFrame::IsFrameOfType(aFlags & ~(nsIFrame::eMathML | nsIFrame::eExcludesIgnorableWhitespace)); } + // See nsIMathMLFrame.h + bool IsMrowLike() { + return mFrames.FirstChild() != mFrames.LastChild() || + !mFrames.FirstChild(); + } + protected: nsMathMLmathBlockFrame(nsStyleContext* aContext) : nsBlockFrame(aContext) { // We should always have a float manager. Not that things can really try // to float out of us anyway, but we need one for line layout. AddStateBits(NS_BLOCK_FLOAT_MGR); } virtual ~nsMathMLmathBlockFrame() {} }; // -------------- -class nsMathMLmathInlineFrame : public nsInlineFrame { +class nsMathMLmathInlineFrame : public nsInlineFrame, + public nsMathMLFrame { public: + NS_DECL_QUERYFRAME_TARGET(nsMathMLmathInlineFrame) + NS_DECL_QUERYFRAME NS_DECL_FRAMEARENA_HELPERS friend nsIFrame* NS_NewMathMLmathInlineFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); virtual nsresult SetInitialChildList(ChildListID aListID, nsFrameList& aChildList) MOZ_OVERRIDE { @@ -533,14 +544,20 @@ public: return rv; } virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE { return nsInlineFrame::IsFrameOfType(aFlags & ~(nsIFrame::eMathML | nsIFrame::eExcludesIgnorableWhitespace)); } + bool + IsMrowLike() MOZ_OVERRIDE { + return mFrames.FirstChild() != mFrames.LastChild() || + !mFrames.FirstChild(); + } + protected: nsMathMLmathInlineFrame(nsStyleContext* aContext) : nsInlineFrame(aContext) {} virtual ~nsMathMLmathInlineFrame() {} }; #endif /* nsMathMLContainerFrame_h___ */
--- a/layout/mathml/nsMathMLFrame.h +++ b/layout/mathml/nsMathMLFrame.h @@ -93,16 +93,22 @@ public: } uint8_t ScriptIncrement(nsIFrame* aFrame) MOZ_OVERRIDE { return 0; } + bool + IsMrowLike() MOZ_OVERRIDE + { + return false; + } + // helper to give a style context suitable for doing the stretching to the // MathMLChar. Frame classes that use this should make the extra style contexts // accessible to the Style System via Get/Set AdditionalStyleContext. static void ResolveMathMLCharStyle(nsPresContext* aPresContext, nsIContent* aContent, nsStyleContext* aParenStyleContext, nsMathMLChar* aMathMLChar,
--- a/layout/mathml/nsMathMLmencloseFrame.h +++ b/layout/mathml/nsMathMLmencloseFrame.h @@ -76,16 +76,22 @@ public: InheritAutomaticData(nsIFrame* aParent) MOZ_OVERRIDE; NS_IMETHOD TransmitAutomaticData() MOZ_OVERRIDE; virtual nscoord FixInterFrameSpacing(nsHTMLReflowMetrics& aDesiredSize) MOZ_OVERRIDE; + bool + IsMrowLike() MOZ_OVERRIDE { + return mFrames.FirstChild() != mFrames.LastChild() || + !mFrames.FirstChild(); + } + protected: nsMathMLmencloseFrame(nsStyleContext* aContext); virtual ~nsMathMLmencloseFrame(); nsresult PlaceInternal(nsRenderingContext& aRenderingContext, bool aPlaceOrigin, nsHTMLReflowMetrics& aDesiredSize, bool aWidthOnly);
--- a/layout/mathml/nsMathMLmfencedFrame.h +++ b/layout/mathml/nsMathMLmfencedFrame.h @@ -75,16 +75,27 @@ public: bool aRTL); static void PlaceChar(nsMathMLChar* aMathMLChar, nscoord aDesiredSize, nsBoundingMetrics& bm, nscoord& dx); + virtual bool + IsMrowLike() MOZ_OVERRIDE + { + // Always treated as an mrow with > 1 child as + // <mfenced> <mo>%</mo> </mfenced> + // renders equivalently to + // <mrow> <mo> ( </mo> <mo>%</mo> <mo> ) </mo> </mrow> + // This also holds with multiple children. (MathML3 3.3.8.1) + return true; + } + protected: nsMathMLmfencedFrame(nsStyleContext* aContext) : nsMathMLContainerFrame(aContext) {} virtual ~nsMathMLmfencedFrame(); nsMathMLChar* mOpenChar; nsMathMLChar* mCloseChar; nsMathMLChar* mSeparatorsChar; int32_t mSeparatorsCount;
--- a/layout/mathml/nsMathMLmoFrame.cpp +++ b/layout/mathml/nsMathMLmoFrame.cpp @@ -305,21 +305,33 @@ nsMathMLmoFrame::ProcessOperatorData() mFlags &= ~NS_MATHML_OPERATOR_EMBELLISH_ANCESTOR; // find the position of our outermost embellished container w.r.t // its siblings. nsIFrame* nextSibling = embellishAncestor->GetNextSibling(); nsIFrame* prevSibling = embellishAncestor->GetPrevSibling(); - // flag to distinguish from a real infix - if (!prevSibling && !nextSibling) + // flag to distinguish from a real infix. Set for (embellished) operators + // that live in (inferred) mrows. + nsIMathMLFrame* mathAncestor = do_QueryFrame(parentAncestor); + bool zeroSpacing = false; + if (mathAncestor) { + zeroSpacing = !mathAncestor->IsMrowLike(); + } else { + nsMathMLmathBlockFrame* blockFrame = do_QueryFrame(parentAncestor); + if (blockFrame) { + zeroSpacing = !blockFrame->IsMrowLike(); + } + } + if (zeroSpacing) { mFlags |= NS_MATHML_OPERATOR_EMBELLISH_ISOLATED; - else + } else { mFlags &= ~NS_MATHML_OPERATOR_EMBELLISH_ISOLATED; + } // find our form form = NS_MATHML_OPERATOR_FORM_INFIX; mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::form, value); if (!value.IsEmpty()) { if (value.EqualsLiteral("prefix")) form = NS_MATHML_OPERATOR_FORM_PREFIX; else if (value.EqualsLiteral("postfix")) @@ -339,40 +351,37 @@ nsMathMLmoFrame::ProcessOperatorData() // http://www.w3.org/TR/MathML/chapter3.html#presm.mo.attrs // thickmathspace = 5/18em float lspace = 5.0f/18.0f; float rspace = 5.0f/18.0f; // lookup the operator dictionary nsAutoString data; mMathMLChar.GetData(data); nsMathMLOperators::LookupOperator(data, form, &mFlags, &lspace, &rspace); - if (lspace || rspace) { + // Spacing is zero if our outermost embellished operator is not in an + // inferred mrow. + if (!NS_MATHML_OPERATOR_EMBELLISH_IS_ISOLATED(mFlags) && + (lspace || rspace)) { // Cache the default values of lspace and rspace. // since these values are relative to the 'em' unit, convert to twips now nscoord em; nsRefPtr<nsFontMetrics> fm; nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm)); GetEmHeight(fm, em); mEmbellishData.leadingSpace = NSToCoordRound(lspace * em); mEmbellishData.trailingSpace = NSToCoordRound(rspace * em); // tuning if we don't want too much extra space when we are a script. // (with its fonts, TeX sets lspace=0 & rspace=0 as soon as scriptlevel>0. // Our fonts can be anything, so...) - if (StyleFont()->mScriptLevel > 0) { - if (NS_MATHML_OPERATOR_EMBELLISH_IS_ISOLATED(mFlags)) { - // could be an isolated accent or script, e.g., x^{+}, just zero out - mEmbellishData.leadingSpace = 0; - mEmbellishData.trailingSpace = 0; - } - else if (!NS_MATHML_OPERATOR_HAS_EMBELLISH_ANCESTOR(mFlags)) { - mEmbellishData.leadingSpace /= 2; - mEmbellishData.trailingSpace /= 2; - } + if (StyleFont()->mScriptLevel > 0 && + !NS_MATHML_OPERATOR_HAS_EMBELLISH_ANCESTOR(mFlags)) { + mEmbellishData.leadingSpace /= 2; + mEmbellishData.trailingSpace /= 2; } } } // If we are an accent without explicit lspace="." or rspace=".", // we will ignore our default leading/trailing space // lspace
--- a/layout/mathml/nsMathMLmpaddedFrame.h +++ b/layout/mathml/nsMathMLmpaddedFrame.h @@ -33,16 +33,22 @@ public: const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) MOZ_OVERRIDE; virtual nsresult Place(nsRenderingContext& aRenderingContext, bool aPlaceOrigin, nsHTMLReflowMetrics& aDesiredSize) MOZ_OVERRIDE; + bool + IsMrowLike() MOZ_OVERRIDE { + return mFrames.FirstChild() != mFrames.LastChild() || + !mFrames.FirstChild(); + } + protected: nsMathMLmpaddedFrame(nsStyleContext* aContext) : nsMathMLContainerFrame(aContext) {} virtual ~nsMathMLmpaddedFrame(); virtual nsresult MeasureForWidth(nsRenderingContext& aRenderingContext, nsHTMLReflowMetrics& aDesiredSize) MOZ_OVERRIDE;
--- a/layout/mathml/nsMathMLmphantomFrame.h +++ b/layout/mathml/nsMathMLmphantomFrame.h @@ -26,15 +26,21 @@ public: TransmitAutomaticData() MOZ_OVERRIDE { return TransmitAutomaticDataForMrowLikeElement(); } virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, const nsDisplayListSet& aLists) MOZ_OVERRIDE {} + bool + IsMrowLike() MOZ_OVERRIDE { + return mFrames.FirstChild() != mFrames.LastChild() || + !mFrames.FirstChild(); + } + protected: nsMathMLmphantomFrame(nsStyleContext* aContext) : nsMathMLContainerFrame(aContext) {} virtual ~nsMathMLmphantomFrame(); }; #endif /* nsMathMLmphantomFrame_h___ */
--- a/layout/mathml/nsMathMLmrowFrame.h +++ b/layout/mathml/nsMathMLmrowFrame.h @@ -27,14 +27,23 @@ public: NS_IMETHOD InheritAutomaticData(nsIFrame* aParent) MOZ_OVERRIDE; NS_IMETHOD TransmitAutomaticData() MOZ_OVERRIDE { return TransmitAutomaticDataForMrowLikeElement(); } + bool + IsMrowLike() MOZ_OVERRIDE { + // <mrow> elements with a single child are treated identically to the case + // where the child wasn't within an mrow, so we pretend the mrow isn't an + // mrow in that situation. + return mFrames.FirstChild() != mFrames.LastChild() || + !mFrames.FirstChild(); + } + protected: nsMathMLmrowFrame(nsStyleContext* aContext) : nsMathMLContainerFrame(aContext) {} virtual ~nsMathMLmrowFrame(); }; #endif /* nsMathMLmrowFrame_h___ */
--- a/layout/mathml/nsMathMLmsqrtFrame.h +++ b/layout/mathml/nsMathMLmsqrtFrame.h @@ -47,15 +47,22 @@ public: NS_IMETHOD InheritAutomaticData(nsIFrame* aParent) MOZ_OVERRIDE; virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsIAtom* aAttribute, int32_t aModType) MOZ_OVERRIDE; + virtual bool + IsMrowLike() MOZ_OVERRIDE + { + return mFrames.FirstChild() != mFrames.LastChild() || + !mFrames.FirstChild(); + } + protected: nsMathMLmsqrtFrame(nsStyleContext* aContext); virtual ~nsMathMLmsqrtFrame(); }; #endif /* nsMathMLmsqrtFrame_h___ */
--- a/layout/mathml/nsMathMLmtableFrame.h +++ b/layout/mathml/nsMathMLmtableFrame.h @@ -246,16 +246,22 @@ public: { return nsBlockFrame::IsFrameOfType(aFlags & ~(nsIFrame::eMathML | nsIFrame::eExcludesIgnorableWhitespace)); } virtual const nsStyleText* StyleTextForLineLayout() MOZ_OVERRIDE; virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) MOZ_OVERRIDE; + bool + IsMrowLike() MOZ_OVERRIDE { + return mFrames.FirstChild() != mFrames.LastChild() || + !mFrames.FirstChild(); + } + protected: nsMathMLmtdInnerFrame(nsStyleContext* aContext); virtual ~nsMathMLmtdInnerFrame(); nsStyleText* mUniqueStyleText; }; // class nsMathMLmtdInnerFrame