Call DidReflow() on child frames where needed in case of errors. b=366012 r+sr=rbs

This commit is contained in:
mats.palmgren%bredband.net 2007-03-02 10:55:55 +00:00
Родитель 9e11670efb
Коммит fd36f101fc
12 изменённых файлов: 88 добавлений и 39 удалений

Просмотреть файл

@ -399,7 +399,11 @@ nsMathMLContainerFrame::Stretch(nsIRenderingContext& aRenderingContext,
}
// re-position all our children
Place(aRenderingContext, PR_TRUE, aDesiredStretchSize);
nsresult rv = Place(aRenderingContext, PR_TRUE, aDesiredStretchSize);
if (NS_MATHML_HAS_ERROR(mPresentationData.flags) || NS_FAILED(rv)) {
// Make sure the child frames get their DidReflow() calls.
DidReflowChildren(mFrames.FirstChild());
}
// If our parent is not embellished, it means we are the outermost embellished
// container and so we put the spacing, otherwise we don't include the spacing,
@ -469,11 +473,17 @@ nsMathMLContainerFrame::FinalizeReflow(nsIRenderingContext& aRenderingContext,
PRBool placeOrigin = !NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags) ||
(mEmbellishData.coreFrame != this && !mPresentationData.baseFrame &&
mEmbellishData.direction == NS_STRETCH_DIRECTION_UNSUPPORTED);
Place(aRenderingContext, placeOrigin, aDesiredSize);
nsresult rv = Place(aRenderingContext, placeOrigin, aDesiredSize);
// exit now if the frame was flagged as having invalid markup
if (NS_MATHML_HAS_ERROR(mPresentationData.flags)) {
return NS_OK;
// Place() will call FinishReflowChild() when placeOrigin is true but if
// it returns before reaching FinishReflowChild() due to errors we need
// to fulfill the reflow protocol by calling DidReflow for the child frames
// that still needs it here (or we may crash - bug 366012).
// If placeOrigin is false we should reach Place() with aPlaceOrigin == true
// through Stretch() eventually.
if (NS_MATHML_HAS_ERROR(mPresentationData.flags) || NS_FAILED(rv)) {
DidReflowChildren(GetFirstChild(nsnull));
return rv;
}
if (!placeOrigin) {
@ -516,6 +526,17 @@ nsMathMLContainerFrame::FinalizeReflow(nsIRenderingContext& aRenderingContext,
}
Stretch(aRenderingContext, NS_STRETCH_DIRECTION_DEFAULT, defaultSize,
aDesiredSize);
#ifdef NS_DEBUG
{
// The Place() call above didn't request FinishReflowChild(),
// so let's check that we eventually did through Stretch().
nsIFrame* childFrame = GetFirstChild(nsnull);
for ( ; childFrame; childFrame = childFrame->GetNextSibling()) {
NS_ASSERTION(!(childFrame->GetStateBits() & NS_FRAME_IN_REFLOW),
"DidReflow() was never called");
}
}
#endif
}
}
// Also return our bounding metrics
@ -1033,7 +1054,11 @@ nsMathMLContainerFrame::Reflow(nsPresContext* aPresContext,
rv = ReflowChild(childFrame, aPresContext, childDesiredSize,
childReflowState, childStatus);
//NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status");
if (NS_FAILED(rv)) return rv;
if (NS_FAILED(rv)) {
// Call DidReflow() for the child frames we successfully did reflow.
DidReflowChildren(mFrames.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,
@ -1388,7 +1413,22 @@ nsMathMLContainerFrame::FixInterFrameSpacing(nsHTMLReflowMetrics& aDesiredSize)
return gap;
}
void
nsMathMLContainerFrame::DidReflowChildren(nsIFrame* aFirst, nsIFrame* aStop)
{
NS_PRECONDITION(aFirst, "expected a frame");
for (nsIFrame* frame = aFirst;
frame != aStop;
frame = frame->GetNextSibling()) {
NS_ASSERTION(frame, "aStop isn't a sibling");
if (frame->GetStateBits() & NS_FRAME_IN_REFLOW) {
frame->DidReflow(frame->GetPresContext(), nsnull,
NS_FRAME_REFLOW_FINISHED);
}
}
}
//==========================

Просмотреть файл

@ -75,6 +75,7 @@
class nsMathMLContainerFrame : public nsHTMLContainerFrame,
public nsMathMLFrame {
friend class nsMathMLmfencedFrame;
public:
nsMathMLContainerFrame(nsStyleContext* aContext) : nsHTMLContainerFrame(aContext) {}
@ -305,6 +306,13 @@ public:
protected:
virtual PRIntn GetSkipSides() const { return 0; }
/**
* Call DidReflow() if the NS_FRAME_IN_REFLOW frame bit is set on aFirst and
* all its next siblings up to, but not including, aStop.
* aStop == nsnull meaning all next siblings with the bit set.
*/
void DidReflowChildren(nsIFrame* aFirst, nsIFrame* aStop = nsnull);
};

Просмотреть файл

@ -142,7 +142,11 @@ nsMathMLTokenFrame::Reflow(nsPresContext* aPresContext,
rv = ReflowChild(childFrame, aPresContext, childDesiredSize,
childReflowState, aStatus);
//NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status");
if (NS_FAILED(rv)) return rv;
if (NS_FAILED(rv)) {
// Call DidReflow() for the child frames we successfully did reflow.
DidReflowChildren(GetFirstChild(nsnull), childFrame);
return rv;
}
// origins are used as placeholders to store the child's ascent and descent.
childFrame->SetRect(nsRect(0, childDesiredSize.ascent,

Просмотреть файл

@ -303,7 +303,11 @@ nsMathMLmfencedFrame::doReflow(nsPresContext* aPresContext,
rv = mathMLFrame->ReflowChild(childFrame, aPresContext, childDesiredSize,
childReflowState, childStatus);
//NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status");
if (NS_FAILED(rv)) return rv;
if (NS_FAILED(rv)) {
// Call DidReflow() for the child frames we successfully did reflow.
mathMLFrame->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,

Просмотреть файл

@ -788,7 +788,11 @@ nsMathMLmoFrame::Stretch(nsIRenderingContext& aRenderingContext,
// Place our children using the default method
// This will allow our child text frame to get its DidReflow()
Place(aRenderingContext, PR_TRUE, aDesiredStretchSize);
nsresult rv = Place(aRenderingContext, PR_TRUE, aDesiredStretchSize);
if (NS_MATHML_HAS_ERROR(mPresentationData.flags) || NS_FAILED(rv)) {
// Make sure the child frames get their DidReflow() calls.
DidReflowChildren(mFrames.FirstChild());
}
// Fixup for the final height.
// On one hand, our stretchy height can sometimes be shorter than surrounding

Просмотреть файл

@ -186,7 +186,11 @@ nsMathMLmrootFrame::Reflow(nsPresContext* aPresContext,
rv = ReflowChild(childFrame, aPresContext,
childDesiredSize, childReflowState, childStatus);
//NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status");
if (NS_FAILED(rv)) return rv;
if (NS_FAILED(rv)) {
// Call DidReflow() for the child frames we successfully did reflow.
DidReflowChildren(mFrames.FirstChild(), childFrame);
return rv;
}
if (0 == count) {
// base
baseFrame = childFrame;

Просмотреть файл

@ -117,15 +117,10 @@ nsMathMLmsubFrame::PlaceSubScript (nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize,
nsIFrame* aFrame,
nsMathMLContainerFrame* aFrame,
nscoord aUserSubScriptShift,
nscoord aScriptSpace)
{
// the caller better be a mathml frame
nsIMathMLFrame* mathMLFrame;
aFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame);
if (!mathMLFrame) return NS_ERROR_INVALID_ARG;
// force the scriptSpace to be atleast 1 pixel
aScriptSpace = PR_MAX(nsPresContext::CSSPixelsToAppUnits(1), aScriptSpace);
@ -195,7 +190,7 @@ nsMathMLmsubFrame::PlaceSubScript (nsPresContext* aPresContext,
boundingMetrics.leftBearing = bmBase.leftBearing;
boundingMetrics.rightBearing = PR_MAX(bmBase.rightBearing, bmBase.width +
PR_MAX(bmSubScript.width + aScriptSpace, bmSubScript.rightBearing));
mathMLFrame->SetBoundingMetrics (boundingMetrics);
aFrame->SetBoundingMetrics (boundingMetrics);
// reflow metrics
aDesiredSize.ascent =
@ -206,7 +201,7 @@ nsMathMLmsubFrame::PlaceSubScript (nsPresContext* aPresContext,
aDesiredSize.width = boundingMetrics.width;
aDesiredSize.mBoundingMetrics = boundingMetrics;
mathMLFrame->SetReference(nsPoint(0, aDesiredSize.ascent));
aFrame->SetReference(nsPoint(0, aDesiredSize.ascent));
if (aPlaceOrigin) {
nscoord dx, dy;

Просмотреть файл

@ -64,7 +64,7 @@ public:
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize,
nsIFrame* aForFrame,
nsMathMLContainerFrame* aForFrame,
nscoord aUserSubScriptShift,
nscoord aScriptSpace);

Просмотреть файл

@ -133,16 +133,11 @@ nsMathMLmsubsupFrame::PlaceSubSupScript(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize,
nsIFrame* aFrame,
nsMathMLContainerFrame* aFrame,
nscoord aUserSubScriptShift,
nscoord aUserSupScriptShift,
nscoord aScriptSpace)
{
// the caller better be a mathml frame
nsIMathMLFrame* mathMLFrame;
aFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame);
if (!mathMLFrame) return NS_ERROR_INVALID_ARG;
// force the scriptSpace to be atleast 1 pixel
nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
aScriptSpace = PR_MAX(onePixel, aScriptSpace);
@ -258,7 +253,7 @@ nsMathMLmsubsupFrame::PlaceSubSupScript(nsPresContext* aPresContext,
// Rule 18c, App. G, TeXbook
nscoord supScriptShift;
nsPresentationData presentationData;
mathMLFrame->GetPresentationData(presentationData);
aFrame->GetPresentationData(presentationData);
if ( presentationData.scriptLevel == 0 &&
NS_MATHML_IS_DISPLAYSTYLE(presentationData.flags) &&
!NS_MATHML_IS_COMPRESSED(presentationData.flags)) {
@ -325,7 +320,7 @@ nsMathMLmsubsupFrame::PlaceSubSupScript(nsPresContext* aPresContext,
boundingMetrics.leftBearing = bmBase.leftBearing;
boundingMetrics.rightBearing = bmBase.width +
PR_MAX((italicCorrection + bmSupScript.rightBearing), bmSubScript.rightBearing);
mathMLFrame->SetBoundingMetrics(boundingMetrics);
aFrame->SetBoundingMetrics(boundingMetrics);
// reflow metrics
aDesiredSize.ascent =
@ -339,7 +334,7 @@ nsMathMLmsubsupFrame::PlaceSubSupScript(nsPresContext* aPresContext,
aDesiredSize.width = boundingMetrics.width;
aDesiredSize.mBoundingMetrics = boundingMetrics;
mathMLFrame->SetReference(nsPoint(0, aDesiredSize.ascent));
aFrame->SetReference(nsPoint(0, aDesiredSize.ascent));
if (aPlaceOrigin) {
nscoord dx, dy;

Просмотреть файл

@ -64,7 +64,7 @@ public:
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize,
nsIFrame* aForFrame,
nsMathMLContainerFrame* aForFrame,
nscoord aUserSubScriptShift,
nscoord aUserSupScriptShift,
nscoord aScriptSpace);

Просмотреть файл

@ -117,15 +117,10 @@ nsMathMLmsupFrame::PlaceSuperScript(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize,
nsIFrame* aFrame,
nsMathMLContainerFrame* aFrame,
nscoord aUserSupScriptShift,
nscoord aScriptSpace)
{
// the caller better be a mathml frame
nsIMathMLFrame* mathMLFrame;
aFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame);
if (!mathMLFrame) return NS_ERROR_INVALID_ARG;
// force the scriptSpace to be at least 1 pixel
nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
aScriptSpace = PR_MAX(onePixel, aScriptSpace);
@ -195,7 +190,7 @@ nsMathMLmsupFrame::PlaceSuperScript(nsPresContext* aPresContext,
// Rule 18c, App. G, TeXbook
nscoord supScriptShift;
nsPresentationData presentationData;
mathMLFrame->GetPresentationData (presentationData);
aFrame->GetPresentationData (presentationData);
if ( presentationData.scriptLevel == 0 &&
NS_MATHML_IS_DISPLAYSTYLE(presentationData.flags) &&
!NS_MATHML_IS_COMPRESSED(presentationData.flags)) {
@ -233,7 +228,7 @@ nsMathMLmsupFrame::PlaceSuperScript(nsPresContext* aPresContext,
boundingMetrics.leftBearing = bmBase.leftBearing;
boundingMetrics.rightBearing = bmBase.width + italicCorrection +
bmSupScript.rightBearing;
mathMLFrame->SetBoundingMetrics(boundingMetrics);
aFrame->SetBoundingMetrics(boundingMetrics);
// reflow metrics
aDesiredSize.ascent =
@ -244,7 +239,7 @@ nsMathMLmsupFrame::PlaceSuperScript(nsPresContext* aPresContext,
aDesiredSize.width = boundingMetrics.width;
aDesiredSize.mBoundingMetrics = boundingMetrics;
mathMLFrame->SetReference(nsPoint(0, aDesiredSize.ascent));
aFrame->SetReference(nsPoint(0, aDesiredSize.ascent));
if (aPlaceOrigin) {
nscoord dx, dy;

Просмотреть файл

@ -64,7 +64,7 @@ public:
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize,
nsIFrame* aForFrame,
nsMathMLContainerFrame* aForFrame,
nscoord aUserSupScriptShift,
nscoord aScriptSpace);