From 166233b82fd39073cd01e0325e9ede328644c184 Mon Sep 17 00:00:00 2001 From: "karlt+%karlt.net" Date: Tue, 26 Feb 2008 04:19:36 +0000 Subject: [PATCH] don't use frame origin offsets to store ascents. b=363240, r+sr=roc --- content/base/src/nsGkAtomList.h | 3 + layout/mathml/base/src/nsIMathMLFrame.h | 27 ++-- .../base/src/nsMathMLContainerFrame.cpp | 151 ++++++++++-------- .../mathml/base/src/nsMathMLContainerFrame.h | 27 +++- layout/mathml/base/src/nsMathMLTokenFrame.cpp | 14 +- .../mathml/base/src/nsMathMLmactionFrame.cpp | 4 +- .../mathml/base/src/nsMathMLmfencedFrame.cpp | 52 +++--- layout/mathml/base/src/nsMathMLmfencedFrame.h | 2 +- 8 files changed, 156 insertions(+), 124 deletions(-) diff --git a/content/base/src/nsGkAtomList.h b/content/base/src/nsGkAtomList.h index 5dfd9bcc489..2adad746a5a 100755 --- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -1491,6 +1491,9 @@ GK_ATOM(changeListProperty, "ChangeListProperty") // void* GK_ATOM(collapseOffsetProperty, "CollapseOffsetProperty") // nsPoint* GK_ATOM(computedOffsetProperty, "ComputedOffsetProperty") // nsPoint* GK_ATOM(generatedContent, "GeneratedContentProperty") // nsCOMArray* +#ifdef MOZ_MATHML +GK_ATOM(HTMLReflowMetricsProperty, "HTMLReflowMetricsProperty") // nsHTMLReflowMetrics* +#endif GK_ATOM(IBSplitSpecialPrevSibling, "IBSplitSpecialPrevSibling")// nsIFrame* GK_ATOM(IBSplitSpecialSibling, "IBSplitSpecialSibling") // nsIFrame* GK_ATOM(lineCursorProperty, "LineCursorProperty") // nsLineBox* diff --git a/layout/mathml/base/src/nsIMathMLFrame.h b/layout/mathml/base/src/nsIMathMLFrame.h index e758c8bbd90..38a7045afe9 100644 --- a/layout/mathml/base/src/nsIMathMLFrame.h +++ b/layout/mathml/base/src/nsIMathMLFrame.h @@ -125,12 +125,13 @@ public: /* Place : * This method is used before returning from Reflow(), or when a MathML frame - * has just been stretched. It is called to fine-tune the positions of the elements. + * has just been stretched. It is called to fine-tune the positions of the + * child frames, and other elements. + * + * IMPORTANT: For nsMathMLContainerFrames this method uses + * GetReflowAndBoundingMetricsFor() which must have been set up with + * SaveReflowAndBoundingMetricsFor(). * - * IMPORTANT: This method uses the origin of child frames (rect.x and rect.y) as - * placeholders between calls: On invocation, child->GetRect(rect) should give a - * rect such that rect.x holds the child's descent, rect.y holds the child's ascent, - * (rect.width should give the width, and rect.height should give the height). * The Place() method will use this information to compute the desired size * of the frame. * @@ -357,42 +358,42 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIMathMLFrame, NS_IMATHMLFRAME_IID) // The bit merely tells the context of the frame. In the context of // displaystyle="false", it is intended to slightly alter how the // rendering is done in inline mode. -#define NS_MATHML_DISPLAYSTYLE 0x00000001 +#define NS_MATHML_DISPLAYSTYLE 0x00000001U // This bit is used to emulate TeX rendering. // Internal use only, cannot be set by the user with an attribute. -#define NS_MATHML_COMPRESSED 0x00000002 +#define NS_MATHML_COMPRESSED 0x00000002U // This bit is set if the frame will fire a vertical stretch // command on all its (non-empty) children. // Tags like (or an inferred mrow), mpadded, etc, will fire a // vertical stretch command on all their non-empty children -#define NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY 0x00000004 +#define NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY 0x00000004U // This bit is set if the frame will fire a horizontal stretch // command on all its (non-empty) children. // Tags like munder, mover, munderover, will fire a // horizontal stretch command on all their non-empty children -#define NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY 0x00000008 +#define NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY 0x00000008U // This bit is set if the frame has the explicit attribute // displaystyle="true" or "false". It is only relevant to and // because they are the only tags where the attribute is allowed by the spec. -#define NS_MATHML_EXPLICIT_DISPLAYSTYLE 0x00000020 +#define NS_MATHML_EXPLICIT_DISPLAYSTYLE 0x00000020U // This bit is set when the frame cannot be formatted due to an // error (e.g., invalid markup such as a without an overscript). // When set, a visual feedback will be provided to the user. -#define NS_MATHML_ERROR 0x80000000 +#define NS_MATHML_ERROR 0x80000000U // a bit used for debug -#define NS_MATHML_STRETCH_DONE 0x20000000 +#define NS_MATHML_STRETCH_DONE 0x20000000U // This bit is used for visual debug. When set, the bounding box // of your frame is painted. This visual debug enable to ensure that // you have properly filled your mReference and mBoundingMetrics in // Place(). -#define NS_MATHML_SHOW_BOUNDING_METRICS 0x10000000 +#define NS_MATHML_SHOW_BOUNDING_METRICS 0x10000000U // Macros that retrieve those bits diff --git a/layout/mathml/base/src/nsMathMLContainerFrame.cpp b/layout/mathml/base/src/nsMathMLContainerFrame.cpp index de0fbfbfd7b..5fecd6b4e9a 100644 --- a/layout/mathml/base/src/nsMathMLContainerFrame.cpp +++ b/layout/mathml/base/src/nsMathMLContainerFrame.cpp @@ -58,7 +58,6 @@ #include "nsGkAtoms.h" #include "nsMathMLParts.h" -#include "nsMathMLChar.h" #include "nsMathMLContainerFrame.h" #include "nsAutoPtr.h" #include "nsStyleSet.h" @@ -166,8 +165,35 @@ void nsDisplayMathMLError::Paint(nsDisplayListBuilder* aBuilder, * ============================================================================= */ +static PRBool +IsForeignChild(const nsIFrame* aFrame) +{ + // This counts nsMathMLmathBlockFrame as a foreign child, because it + // uses block reflow + return !(aFrame->IsFrameOfType(nsIFrame::eMathML)) || + aFrame->GetType() == nsGkAtoms::blockFrame; +} + +static void +DeleteHTMLReflowMetrics(void *aObject, nsIAtom *aPropertyName, + void *aPropertyValue, void *aData) +{ + delete static_cast(aPropertyValue); +} + +/* static */ void +nsMathMLContainerFrame::SaveReflowAndBoundingMetricsFor(nsIFrame* aFrame, + const nsHTMLReflowMetrics& aReflowMetrics, + const nsBoundingMetrics& aBoundingMetrics) +{ + nsHTMLReflowMetrics *metrics = new nsHTMLReflowMetrics(aReflowMetrics); + metrics->mBoundingMetrics = aBoundingMetrics; + aFrame->SetProperty(nsGkAtoms::HTMLReflowMetricsProperty, metrics, + DeleteHTMLReflowMetrics); +} + // helper method to facilitate getting the reflow and bounding metrics -void +/* static */ void nsMathMLContainerFrame::GetReflowAndBoundingMetricsFor(nsIFrame* aFrame, nsHTMLReflowMetrics& aReflowMetrics, nsBoundingMetrics& aBoundingMetrics, @@ -175,35 +201,40 @@ nsMathMLContainerFrame::GetReflowAndBoundingMetricsFor(nsIFrame* aFra { NS_PRECONDITION(aFrame, "null arg"); + nsHTMLReflowMetrics *metrics = static_cast + (aFrame->GetProperty(nsGkAtoms::HTMLReflowMetricsProperty)); + // IMPORTANT: This function is only meant to be called in Place() methods - // where it is assumed that the frame's rect is still acting as place holder - // for the frame's ascent and descent information - - nsRect rect = aFrame->GetRect(); - aReflowMetrics.ascent = rect.y; - aReflowMetrics.width = rect.width; - aReflowMetrics.height = rect.height; - nscoord descent = aReflowMetrics.height - aReflowMetrics.ascent; - - if (aFrame->IsFrameOfType(nsIFrame::eMathML)) { - nsIMathMLFrame* mathMLFrame; - CallQueryInterface(aFrame, &mathMLFrame); - if (mathMLFrame) { - mathMLFrame->GetBoundingMetrics(aBoundingMetrics); - if (aMathMLFrameType) - *aMathMLFrameType = mathMLFrame->GetMathMLFrameType(); - - return; - } + // where it is assumed that SaveReflowAndBoundingMetricsFor has recorded the + // information. + NS_ASSERTION(metrics, "Didn't SaveReflowAndBoundingMetricsFor frame!"); + if (metrics) { + aReflowMetrics = *metrics; + aBoundingMetrics = metrics->mBoundingMetrics; } - // aFrame is not a MathML frame, just return the reflow metrics - aBoundingMetrics.descent = descent; - aBoundingMetrics.ascent = aReflowMetrics.ascent; - aBoundingMetrics.width = aReflowMetrics.width; - aBoundingMetrics.rightBearing = aReflowMetrics.width; - if (aMathMLFrameType) - *aMathMLFrameType = eMathMLFrameType_UNKNOWN; + if (aMathMLFrameType) { + if (!IsForeignChild(aFrame)) { + nsIMathMLFrame* mathMLFrame; + CallQueryInterface(aFrame, &mathMLFrame); + if (mathMLFrame) { + *aMathMLFrameType = mathMLFrame->GetMathMLFrameType(); + return; + } + } + *aMathMLFrameType = eMathMLFrameType_UNKNOWN; + } + +} + +void +nsMathMLContainerFrame::ClearSavedChildMetrics() +{ + nsIFrame* childFrame = mFrames.FirstChild(); + while (childFrame) { + childFrame->DeleteProperty(nsGkAtoms::HTMLReflowMetricsProperty); + childFrame = childFrame->GetNextSibling(); + } } // helper to get the preferred size that a container frame should use to fire @@ -236,13 +267,6 @@ nsMathMLContainerFrame::GetPreferredStretchSize(nsIRenderingContext& aRenderingC nsIFrame* childFrame = GetFirstChild(nsnull); while (childFrame) { // initializations in case this child happens not to be a MathML frame - nsRect rect = childFrame->GetRect(); - bmChild.ascent = rect.y; - bmChild.descent = rect.x; - bmChild.width = rect.width; - bmChild.rightBearing = rect.width; - bmChild.leftBearing = 0; - nsIMathMLFrame* mathMLFrame; childFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); if (mathMLFrame) { @@ -254,6 +278,8 @@ nsMathMLContainerFrame::GetPreferredStretchSize(nsIRenderingContext& aRenderingC embellishData.direction == aStretchDirection && presentationData.baseFrame) { // embellishements are not included, only consider the inner first child itself + // XXXkt Does that mean the core descendent frame should be used + // instead of the base child? nsIMathMLFrame* mathMLchildFrame; presentationData.baseFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLchildFrame); if (mathMLchildFrame) { @@ -262,6 +288,10 @@ nsMathMLContainerFrame::GetPreferredStretchSize(nsIRenderingContext& aRenderingC } mathMLFrame->GetBoundingMetrics(bmChild); } + else { + nsHTMLReflowMetrics unused; + GetReflowAndBoundingMetricsFor(childFrame, unused, bmChild); + } if (firstTime) { firstTime = PR_FALSE; @@ -361,11 +391,10 @@ nsMathMLContainerFrame::Stretch(nsIRenderingContext& aRenderingContext, // do the stretching... mathMLFrame->Stretch(aRenderingContext, mEmbellishData.direction, containerSize, childSize); - // store the updated metrics - baseFrame->SetRect(nsRect(0, childSize.ascent, - childSize.width, childSize.height)); - + SaveReflowAndBoundingMetricsFor(baseFrame, childSize, + childSize.mBoundingMetrics); + // Remember the siblings which were _deferred_. // Now that this embellished child may have changed, we need to // fire the stretch on its siblings using our updated size @@ -391,8 +420,8 @@ nsMathMLContainerFrame::Stretch(nsIRenderingContext& aRenderingContext, mathMLFrame->Stretch(aRenderingContext, stretchDir, containerSize, childSize); // store the updated metrics - childFrame->SetRect(nsRect(0, childSize.ascent, - childSize.width, childSize.height)); + SaveReflowAndBoundingMetricsFor(childFrame, childSize, + childSize.mBoundingMetrics); } } childFrame = childFrame->GetNextSibling(); @@ -441,6 +470,8 @@ nsMathMLContainerFrame::Stretch(nsIRenderingContext& aRenderingContext, } } + // Finished with these: + ClearSavedChildMetrics(); // Set our overflow area GatherAndStoreOverflow(&aDesiredStretchSize); } @@ -490,11 +521,11 @@ nsMathMLContainerFrame::FinalizeReflow(nsIRenderingContext& aRenderingContext, return rv; } + PRBool parentWillFireStretch = PR_FALSE; if (!placeOrigin) { // This means the rect.x and rect.y of our children were not set!! // Don't go without checking to see if our parent will later fire a Stretch() command // targeted at us. The Stretch() will cause the rect.x and rect.y to clear... - PRBool parentWillFireStretch = PR_FALSE; nsIMathMLFrame* mathMLFrame; mParent->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); if (mathMLFrame) { @@ -550,8 +581,11 @@ nsMathMLContainerFrame::FinalizeReflow(nsIRenderingContext& aRenderingContext, // Also return our bounding metrics aDesiredSize.mBoundingMetrics = mBoundingMetrics; - if (placeOrigin) { - // Not expecting a stretch. Set our overflow area. + if (!parentWillFireStretch) { + // Not expecting a stretch. + // Finished with these: + ClearSavedChildMetrics(); + // Set our overflow area. GatherAndStoreOverflow(&aDesiredSize); } @@ -844,15 +878,6 @@ nsMathMLContainerFrame::GatherAndStoreOverflow(nsHTMLReflowMetrics* aMetrics) FinishAndStoreOverflow(aMetrics); } -static PRBool -IsForeignChild(nsIFrame* aFrame) -{ - // This counts nsMathMLmathBlockFrame as a foreign child, because it - // uses block reflow - return !(aFrame->IsFrameOfType(nsIFrame::eMathML)) || - aFrame->GetType() == nsGkAtoms::blockFrame; -} - nsresult nsMathMLContainerFrame::ReflowChild(nsIFrame* aChildFrame, nsPresContext* aPresContext, @@ -876,13 +901,13 @@ nsMathMLContainerFrame::ReflowChild(nsIFrame* aChildFrame, NS_ASSERTION(!inlineFrame, "Inline frames should be wrapped in blocks"); #endif - // XXX should we do something here to compute good bounding metrics for - // the child? - nsresult rv = nsHTMLContainerFrame:: ReflowChild(aChildFrame, aPresContext, aDesiredSize, aReflowState, 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); + if (NS_FAILED(rv)) + return rv; + if (aDesiredSize.ascent == nsHTMLReflowMetrics::ASK_FOR_BASELINE) { // This will be suitable for inline frames, which are wrapped in a block. if(!nsLayoutUtils::GetLastLineBaseline(aChildFrame, @@ -893,8 +918,7 @@ nsMathMLContainerFrame::ReflowChild(nsIFrame* aChildFrame, aDesiredSize.ascent = aDesiredSize.height; } } - if (IsForeignChild(aChildFrame) && - (aDesiredSize.mFlags | NS_REFLOW_CALC_BOUNDING_METRICS)) { + if (IsForeignChild(aChildFrame)) { // use ComputeTightBounds API as aDesiredSize.mBoundingMetrics is not set. nsRect r = aChildFrame->ComputeTightBounds(aReflowState.rendContext->ThebesContext()); aDesiredSize.mBoundingMetrics.leftBearing = r.x; @@ -936,11 +960,8 @@ nsMathMLContainerFrame::Reflow(nsPresContext* aPresContext, return rv; } - // At this stage, the origin points of the children have no use, so we will use the - // origins as placeholders to store the child's ascent and descent. Later on, - // we should set the origins so as to overwrite what we are storing there now. - childFrame->SetRect(nsRect(0, childDesiredSize.ascent, - childDesiredSize.width, childDesiredSize.height)); + SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize, + childDesiredSize.mBoundingMetrics); childFrame = childFrame->GetNextSibling(); } @@ -983,8 +1004,8 @@ nsMathMLContainerFrame::Reflow(nsPresContext* aPresContext, mathMLFrame->Stretch(*aReflowState.rendContext, stretchDir, containerSize, childDesiredSize); // store the updated metrics - childFrame->SetRect(nsRect(0, childDesiredSize.ascent, - childDesiredSize.width, childDesiredSize.height)); + SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize, + childDesiredSize.mBoundingMetrics); } childFrame = childFrame->GetNextSibling(); } diff --git a/layout/mathml/base/src/nsMathMLContainerFrame.h b/layout/mathml/base/src/nsMathMLContainerFrame.h index ce256264bd5..94f17c6b719 100644 --- a/layout/mathml/base/src/nsMathMLContainerFrame.h +++ b/layout/mathml/base/src/nsMathMLContainerFrame.h @@ -119,6 +119,8 @@ public: nsHTMLContainerFrame::IsFrameOfType(aFlags & ~(nsIFrame::eMathML)); } + virtual PRIntn GetSkipSides() const { return 0; } + NS_IMETHOD AppendFrames(nsIAtom* aListName, nsIFrame* aFrameList); @@ -229,18 +231,29 @@ public: FinalizeReflow(nsIRenderingContext& aRenderingContext, nsHTMLReflowMetrics& aDesiredSize); - // helper method to facilitate getting the reflow and bounding metrics. - // The argument aMathMLFrameType, when non null, will return the 'type' of - // the frame, which is used to determine the inter-frame spacing. - // IMPORTANT: This function is only meant to be called in Place() methods - // where it is assumed that the frame's rect is still acting as place holder - // for the frame's ascent and descent information + // Record metrics of a child frame for recovery through the following method + static void + SaveReflowAndBoundingMetricsFor(nsIFrame* aFrame, + const nsHTMLReflowMetrics& aReflowMetrics, + const nsBoundingMetrics& aBoundingMetrics); + + // helper method to facilitate getting the reflow and bounding metrics of a + // child frame. The argument aMathMLFrameType, when non null, will return + // the 'type' of the frame, which is used to determine the inter-frame + // spacing. + // IMPORTANT: This function is only meant to be called in Place() methods as + // the information is available only when set up with the above method + // during Reflow/Stretch() and GetPrefWidth(). static void GetReflowAndBoundingMetricsFor(nsIFrame* aFrame, nsHTMLReflowMetrics& aReflowMetrics, nsBoundingMetrics& aBoundingMetrics, eMathMLFrameType* aMathMLFrameType = nsnull); + // helper method to clear metrics saved with + // SaveReflowAndBoundingMetricsFor() from all child frames. + void ClearSavedChildMetrics(); + // helper to let the update of presentation data pass through // a subtree that may contain non-MathML container frames static void @@ -284,8 +297,6 @@ public: ReLayoutChildren(nsIFrame* aParentFrame, nsFrameState aBits); protected: - virtual PRIntn GetSkipSides() const { return 0; } - // Helper method which positions child frames as an on given baseline // y = aBaseline starting from x = aOffsetX, calling FinishReflowChild() // on the frames. diff --git a/layout/mathml/base/src/nsMathMLTokenFrame.cpp b/layout/mathml/base/src/nsMathMLTokenFrame.cpp index e57cf8d31f9..c681ff90973 100644 --- a/layout/mathml/base/src/nsMathMLTokenFrame.cpp +++ b/layout/mathml/base/src/nsMathMLTokenFrame.cpp @@ -145,9 +145,8 @@ nsMathMLTokenFrame::Reflow(nsPresContext* aPresContext, return rv; } - // origins are used as placeholders to store the child's ascent. - childFrame->SetRect(nsRect(0, childDesiredSize.ascent, - childDesiredSize.width, childDesiredSize.height)); + SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize, + childDesiredSize.mBoundingMetrics); // compute and cache the bounding metrics aDesiredSize.mBoundingMetrics += childDesiredSize.mBoundingMetrics; @@ -189,15 +188,14 @@ nsMathMLTokenFrame::Place(nsIRenderingContext& aRenderingContext, nscoord dy, dx = 0; nsIFrame* childFrame = GetFirstChild(nsnull); while (childFrame) { - nsRect rect = childFrame->GetRect(); nsHTMLReflowMetrics childSize; - childSize.width = rect.width; - childSize.height = rect.height; + GetReflowAndBoundingMetricsFor(childFrame, childSize, + childSize.mBoundingMetrics); // place and size the child; (dx,0) makes the caret happy - bug 188146 - dy = rect.IsEmpty() ? 0 : aDesiredSize.ascent - rect.y; + dy = childSize.height == 0 ? 0 : aDesiredSize.ascent - childSize.ascent; FinishReflowChild(childFrame, PresContext(), nsnull, childSize, dx, dy, 0); - dx += rect.width; + dx += childSize.width; childFrame = childFrame->GetNextSibling(); } } diff --git a/layout/mathml/base/src/nsMathMLmactionFrame.cpp b/layout/mathml/base/src/nsMathMLmactionFrame.cpp index 3ab2f235c04..30e3d10c34f 100644 --- a/layout/mathml/base/src/nsMathMLmactionFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmactionFrame.cpp @@ -288,8 +288,8 @@ nsMathMLmactionFrame::Reflow(nsPresContext* aPresContext, childFrame, availSize); rv = ReflowChild(childFrame, aPresContext, aDesiredSize, childReflowState, aStatus); - childFrame->SetRect(nsRect(0,aDesiredSize.ascent, - aDesiredSize.width,aDesiredSize.height)); + SaveReflowAndBoundingMetricsFor(childFrame, aDesiredSize, + aDesiredSize.mBoundingMetrics); mBoundingMetrics = aDesiredSize.mBoundingMetrics; } FinalizeReflow(*aReflowState.rendContext, aDesiredSize); diff --git a/layout/mathml/base/src/nsMathMLmfencedFrame.cpp b/layout/mathml/base/src/nsMathMLmfencedFrame.cpp index 486fdde0206..68a000fe8ab 100644 --- a/layout/mathml/base/src/nsMathMLmfencedFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmfencedFrame.cpp @@ -250,7 +250,7 @@ nsMathMLmfencedFrame::doReflow(nsPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsHTMLReflowMetrics& aDesiredSize, nsReflowStatus& aStatus, - nsIFrame* aForFrame, + nsMathMLContainerFrame* aForFrame, nsMathMLChar* aOpenChar, nsMathMLChar* aCloseChar, nsMathMLChar* aSeparatorsChar, @@ -262,9 +262,6 @@ nsMathMLmfencedFrame::doReflow(nsPresContext* aPresContext, aDesiredSize.ascent = 0; aDesiredSize.mBoundingMetrics.Clear(); - nsMathMLContainerFrame* mathMLFrame = - static_cast(aForFrame); - PRInt32 i; nsCOMPtr fm; const nsStyleFont* font = aForFrame->GetStyleFont(); @@ -304,20 +301,17 @@ nsMathMLmfencedFrame::doReflow(nsPresContext* aPresContext, | NS_REFLOW_CALC_BOUNDING_METRICS); nsHTMLReflowState childReflowState(aPresContext, aReflowState, childFrame, availSize); - rv = mathMLFrame->ReflowChild(childFrame, aPresContext, childDesiredSize, - childReflowState, childStatus); + rv = aForFrame->ReflowChild(childFrame, aPresContext, childDesiredSize, + childReflowState, childStatus); //NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status"); if (NS_FAILED(rv)) { // Call DidReflow() for the child frames we successfully did reflow. - mathMLFrame->DidReflowChildren(firstChild, childFrame); + aForFrame->DidReflowChildren(firstChild, childFrame); return rv; } - // At this stage, the origin points of the children have no use, so we will use the - // origins as placeholders to store the child's ascent and descent. Later on, - // we should set the origins so as to overwrite what we are storing there now. - childFrame->SetRect(nsRect(0, childDesiredSize.ascent, - childDesiredSize.width, childDesiredSize.height)); + SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize, + childDesiredSize.mBoundingMetrics); // compute the bounding metrics right now for mfrac nscoord childDescent = childDesiredSize.height - childDesiredSize.ascent; @@ -337,16 +331,16 @@ nsMathMLmfencedFrame::doReflow(nsPresContext* aPresContext, nsStretchDirection stretchDir = NS_STRETCH_DIRECTION_VERTICAL; nsPresentationData presentationData; - mathMLFrame->GetPresentationData(presentationData); + aForFrame->GetPresentationData(presentationData); if (!NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(presentationData.flags)) { // case when the call is made for mfrac, we only need to stretch the '/' separator containerSize = aDesiredSize.mBoundingMetrics; // computed earlier } else { // case when the call is made for mfenced - mathMLFrame->GetPreferredStretchSize(*aReflowState.rendContext, - 0, /* i.e., without embellishments */ - stretchDir, containerSize); + aForFrame->GetPreferredStretchSize(*aReflowState.rendContext, + 0, /* i.e., without embellishments */ + stretchDir, containerSize); childFrame = firstChild; while (childFrame) { nsIMathMLFrame* mathmlChild; @@ -354,13 +348,14 @@ nsMathMLmfencedFrame::doReflow(nsPresContext* aPresContext, if (mathmlChild) { nsHTMLReflowMetrics childDesiredSize; // retrieve the metrics that was stored at the previous pass - GetReflowAndBoundingMetricsFor(childFrame, childDesiredSize, childDesiredSize.mBoundingMetrics); + GetReflowAndBoundingMetricsFor(childFrame, childDesiredSize, + childDesiredSize.mBoundingMetrics); mathmlChild->Stretch(*aReflowState.rendContext, stretchDir, containerSize, childDesiredSize); // store the updated metrics - childFrame->SetRect(nsRect(0, childDesiredSize.ascent, - childDesiredSize.width, childDesiredSize.height)); + SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize, + childDesiredSize.mBoundingMetrics); nscoord childDescent = childDesiredSize.height - childDesiredSize.ascent; if (descent < childDescent) @@ -371,9 +366,9 @@ nsMathMLmfencedFrame::doReflow(nsPresContext* aPresContext, childFrame = childFrame->GetNextSibling(); } // bug 121748: for surrounding fences & separators, use a size that covers everything - mathMLFrame->GetPreferredStretchSize(*aReflowState.rendContext, - STRETCH_CONSIDER_EMBELLISHMENTS, - stretchDir, containerSize); + aForFrame->GetPreferredStretchSize(*aReflowState.rendContext, + STRETCH_CONSIDER_EMBELLISHMENTS, + stretchDir, containerSize); } ////////////////////////////////////////// @@ -431,7 +426,7 @@ nsMathMLmfencedFrame::doReflow(nsPresContext* aPresContext, else aDesiredSize.mBoundingMetrics += bm; - mathMLFrame->FinishReflowChild(childFrame, aPresContext, nsnull, childSize, + aForFrame->FinishReflowChild(childFrame, aPresContext, nsnull, childSize, dx, ascent - childSize.ascent, 0); dx += childSize.width; @@ -456,14 +451,17 @@ nsMathMLmfencedFrame::doReflow(nsPresContext* aPresContext, aDesiredSize.height = ascent + descent; aDesiredSize.ascent = ascent; - mathMLFrame->SetBoundingMetrics(aDesiredSize.mBoundingMetrics); - mathMLFrame->SetReference(nsPoint(0, aDesiredSize.ascent)); + aForFrame->SetBoundingMetrics(aDesiredSize.mBoundingMetrics); + aForFrame->SetReference(nsPoint(0, aDesiredSize.ascent)); // see if we should fix the spacing - mathMLFrame->FixInterFrameSpacing(aDesiredSize); + aForFrame->FixInterFrameSpacing(aDesiredSize); + + // Finished with these: + aForFrame->ClearSavedChildMetrics(); // Set our overflow area - mathMLFrame->GatherAndStoreOverflow(&aDesiredSize); + aForFrame->GatherAndStoreOverflow(&aDesiredSize); aStatus = NS_FRAME_COMPLETE; NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); diff --git a/layout/mathml/base/src/nsMathMLmfencedFrame.h b/layout/mathml/base/src/nsMathMLmfencedFrame.h index 046b13251a0..f018de4ad9d 100644 --- a/layout/mathml/base/src/nsMathMLmfencedFrame.h +++ b/layout/mathml/base/src/nsMathMLmfencedFrame.h @@ -94,7 +94,7 @@ public: const nsHTMLReflowState& aReflowState, nsHTMLReflowMetrics& aDesiredSize, nsReflowStatus& aStatus, - nsIFrame* aForFrame, + nsMathMLContainerFrame* aForFrame, nsMathMLChar* aOpenChar, nsMathMLChar* aCloseChar, nsMathMLChar* aSeparatorsChar,