Set overflow area for nsMathMLContainerFrames. b=161155, r+sr=roc

This commit is contained in:
karlt+@karlt.net 2007-12-28 15:04:19 -08:00
Родитель 45fb01d780
Коммит 7f6a3cf6f5
10 изменённых файлов: 136 добавлений и 93 удалений

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

@ -318,10 +318,10 @@ nsMathMLContainerFrame::Stretch(nsIRenderingContext& aRenderingContext,
// Pass the stretch to the base child ...
nsIFrame* childFrame = mPresentationData.baseFrame;
if (childFrame) {
nsIFrame* baseFrame = mPresentationData.baseFrame;
if (baseFrame) {
nsIMathMLFrame* mathMLFrame;
childFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame);
baseFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame);
NS_ASSERTION(mathMLFrame, "Something is wrong somewhere");
if (mathMLFrame) {
PRBool stretchAll =
@ -331,7 +331,7 @@ nsMathMLContainerFrame::Stretch(nsIRenderingContext& aRenderingContext,
// And the trick is that the child's rect.x is still holding the descent,
// and rect.y is still holding the ascent ...
nsHTMLReflowMetrics childSize(aDesiredStretchSize);
GetReflowAndBoundingMetricsFor(childFrame, childSize, childSize.mBoundingMetrics);
GetReflowAndBoundingMetricsFor(baseFrame, childSize, childSize.mBoundingMetrics);
// See if we should downsize and confine the stretch to us...
// XXX there may be other cases where we can downsize the stretch,
@ -362,8 +362,8 @@ nsMathMLContainerFrame::Stretch(nsIRenderingContext& aRenderingContext,
mEmbellishData.direction, containerSize, childSize);
// store the updated metrics
childFrame->SetRect(nsRect(0, childSize.ascent,
childSize.width, childSize.height));
baseFrame->SetRect(nsRect(0, childSize.ascent,
childSize.width, childSize.height));
// Remember the siblings which were _deferred_.
// Now that this embellished child may have changed, we need to
@ -378,7 +378,7 @@ nsMathMLContainerFrame::Stretch(nsIRenderingContext& aRenderingContext,
GetPreferredStretchSize(aRenderingContext, STRETCH_CONSIDER_EMBELLISHMENTS,
stretchDir, containerSize);
childFrame = mFrames.FirstChild();
nsIFrame* childFrame = mFrames.FirstChild();
while (childFrame) {
if (childFrame != mPresentationData.baseFrame) {
childFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame);
@ -425,20 +425,23 @@ nsMathMLContainerFrame::Stretch(nsIRenderingContext& aRenderingContext,
aDesiredStretchSize.mBoundingMetrics.width = mBoundingMetrics.width;
nscoord dx = coreData.leftSpace;
if (!dx) return NS_OK;
if (dx != 0) {
mBoundingMetrics.leftBearing += dx;
mBoundingMetrics.rightBearing += dx;
aDesiredStretchSize.mBoundingMetrics.leftBearing += dx;
aDesiredStretchSize.mBoundingMetrics.rightBearing += dx;
mBoundingMetrics.leftBearing += dx;
mBoundingMetrics.rightBearing += dx;
aDesiredStretchSize.mBoundingMetrics.leftBearing += dx;
aDesiredStretchSize.mBoundingMetrics.rightBearing += dx;
childFrame = mFrames.FirstChild();
while (childFrame) {
childFrame->SetPosition(childFrame->GetPosition()
+ nsPoint(dx, 0));
childFrame = childFrame->GetNextSibling();
nsIFrame* childFrame = mFrames.FirstChild();
while (childFrame) {
childFrame->SetPosition(childFrame->GetPosition()
+ nsPoint(dx, 0));
childFrame = childFrame->GetNextSibling();
}
}
}
// Set our overflow area
GatherAndStoreOverflow(&aDesiredStretchSize);
}
}
}
@ -539,12 +542,18 @@ nsMathMLContainerFrame::FinalizeReflow(nsIRenderingContext& aRenderingContext,
#endif
}
}
// Also return our bounding metrics
aDesiredSize.mBoundingMetrics = mBoundingMetrics;
// see if we should fix the spacing
FixInterFrameSpacing(aDesiredSize);
// Also return our bounding metrics
aDesiredSize.mBoundingMetrics = mBoundingMetrics;
if (placeOrigin) {
// Not expecting a stretch. Set our overflow area.
GatherAndStoreOverflow(&aDesiredSize);
}
return NS_OK;
}
@ -966,6 +975,35 @@ nsMathMLContainerFrame::AttributeChanged(PRInt32 aNameSpaceID,
NS_FRAME_IS_DIRTY);
}
void
nsMathMLContainerFrame::GatherAndStoreOverflow(nsHTMLReflowMetrics* aMetrics)
{
// nsIFrame::FinishAndStoreOverflow likes the overflow area to include the
// frame rectangle.
nsRect frameRect(0, 0, aMetrics->width, aMetrics->height);
// All non-child-frame content such as nsMathMLChars (and most child-frame
// content) is included in mBoundingMetrics.
nsRect boundingBox(mBoundingMetrics.leftBearing,
aMetrics->ascent - mBoundingMetrics.ascent,
mBoundingMetrics.rightBearing - mBoundingMetrics.leftBearing,
mBoundingMetrics.ascent + mBoundingMetrics.descent);
aMetrics->mOverflowArea.UnionRect(frameRect, boundingBox);
// mBoundingMetrics does not necessarily include content of <mpadded>
// elements whose mBoundingMetrics may not be representative of the true
// bounds, and doesn't include the CSS2 outline rectangles of children, so
// make such to include child overflow areas.
nsIFrame* childFrame = mFrames.FirstChild();
while (childFrame) {
ConsiderChildOverflow(aMetrics->mOverflowArea, childFrame);
childFrame = childFrame->GetNextSibling();
}
FinishAndStoreOverflow(aMetrics);
}
static PRBool
IsForeignChild(nsIFrame* aFrame)
{
@ -1029,12 +1067,11 @@ nsMathMLContainerFrame::ReflowChild(nsIFrame* aChildFrame,
}
NS_IMETHODIMP
nsMathMLContainerFrame::Reflow(nsPresContext* aPresContext,
nsMathMLContainerFrame::Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
nsresult rv;
aDesiredSize.width = aDesiredSize.height = 0;
aDesiredSize.ascent = 0;
aDesiredSize.mBoundingMetrics.Clear();
@ -1050,8 +1087,8 @@ nsMathMLContainerFrame::Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics childDesiredSize(aDesiredSize.mFlags);
nsHTMLReflowState childReflowState(aPresContext, aReflowState,
childFrame, availSize);
rv = ReflowChild(childFrame, aPresContext, childDesiredSize,
childReflowState, childStatus);
nsresult rv = 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.

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

@ -304,6 +304,11 @@ public:
protected:
virtual PRIntn GetSkipSides() const { return 0; }
// A variant on FinishAndStoreOverflow() that uses the union of child
// overflows, the frame bounds, and mBoundingMetrics to set and store the
// overflow.
void GatherAndStoreOverflow(nsHTMLReflowMetrics* aMetrics);
/**
* 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.

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

@ -166,11 +166,6 @@ nsMathMLTokenFrame::Reflow(nsPresContext* aPresContext,
// place and size children
FinalizeReflow(*aReflowState.rendContext, aDesiredSize);
// XXX set a tentative size for the overflow area. The frame might still be
// stretched later.
aDesiredSize.mOverflowArea.SetRect(0, 0, aDesiredSize.width, aDesiredSize.height);
FinishAndStoreOverflow(&aDesiredSize);
aStatus = NS_FRAME_COMPLETE;
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
return NS_OK;
@ -203,7 +198,7 @@ nsMathMLTokenFrame::Place(nsIRenderingContext& aRenderingContext,
nsRect rect = childFrame->GetRect();
nsHTMLReflowMetrics childSize;
childSize.width = rect.width;
childSize.height = aDesiredSize.height; //rect.height;
childSize.height = rect.height;
// place and size the child; (dx,0) makes the caret happy - bug 188146
dy = rect.IsEmpty() ? 0 : aDesiredSize.ascent - rect.y;

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

@ -466,6 +466,9 @@ nsMathMLmfencedFrame::doReflow(nsPresContext* aPresContext,
// see if we should fix the spacing
mathMLFrame->FixInterFrameSpacing(aDesiredSize);
// Set our overflow area
mathMLFrame->GatherAndStoreOverflow(&aDesiredSize);
aStatus = NS_FRAME_COMPLETE;
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
return NS_OK;

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

@ -890,6 +890,9 @@ nsMathMLmoFrame::Stretch(nsIRenderingContext& aRenderingContext,
}
}
// Set our overflow area
GatherAndStoreOverflow(&aDesiredStretchSize);
if (mFrames.GetLength() != 1)
return NS_OK;

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

@ -294,14 +294,12 @@ nsMathMLmpaddedFrame::ParseAttribute(nsString& aString,
}
void
nsMathMLmpaddedFrame::UpdateValue(nsPresContext* aPresContext,
nsStyleContext* aStyleContext,
PRInt32 aSign,
nsMathMLmpaddedFrame::UpdateValue(PRInt32 aSign,
PRInt32 aPseudoUnit,
nsCSSValue& aCSSValue,
nscoord aLeftSpace,
nsBoundingMetrics& aBoundingMetrics,
nscoord& aValueToUpdate)
nscoord& aValueToUpdate) const
{
nsCSSUnit unit = aCSSValue.GetUnit();
if (NS_MATHML_SIGN_INVALID != aSign && eCSSUnit_Null != unit) {
@ -338,7 +336,7 @@ nsMathMLmpaddedFrame::UpdateValue(nsPresContext* aPresContext,
else if (eCSSUnit_Percent == unit)
amount = NSToCoordRound(float(scaler) * aCSSValue.GetPercentValue());
else
amount = CalcLength(aPresContext, aStyleContext, aCSSValue);
amount = CalcLength(PresContext(), mStyleContext, aCSSValue);
nscoord oldValue = aValueToUpdate;
if (NS_MATHML_SIGN_PLUS == aSign)
@ -372,10 +370,21 @@ nsMathMLmpaddedFrame::Reflow(nsPresContext* aPresContext,
nsresult rv = nsMathMLContainerFrame::Reflow(aPresContext, aDesiredSize,
aReflowState, aStatus);
//NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status");
if (NS_FAILED(rv)) return rv;
return rv;
}
// use our overflow area to cache our natural size
aDesiredSize.mOverflowArea = nsRect(0, 0, aDesiredSize.width, aDesiredSize.height);
NS_IMETHODIMP
nsMathMLmpaddedFrame::Place(nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize)
{
nsresult rv =
nsMathMLContainerFrame::Place(aRenderingContext, aPlaceOrigin,
aDesiredSize);
if (NS_MATHML_HAS_ERROR(mPresentationData.flags) || NS_FAILED(rv)) {
DidReflowChildren(GetFirstChild(nsnull));
return rv;
}
nscoord height = mBoundingMetrics.ascent;
nscoord depth = mBoundingMetrics.descent;
@ -387,29 +396,25 @@ nsMathMLmpaddedFrame::Reflow(nsPresContext* aPresContext,
// update width
pseudoUnit = (mWidthPseudoUnit == NS_MATHML_PSEUDO_UNIT_ITSELF)
? NS_MATHML_PSEUDO_UNIT_WIDTH : mWidthPseudoUnit;
UpdateValue(aPresContext, mStyleContext,
mWidthSign, pseudoUnit, mWidth,
UpdateValue(mWidthSign, pseudoUnit, mWidth,
lspace, mBoundingMetrics, width);
// update "height" (this is the ascent in the terminology of the REC)
pseudoUnit = (mHeightPseudoUnit == NS_MATHML_PSEUDO_UNIT_ITSELF)
? NS_MATHML_PSEUDO_UNIT_HEIGHT : mHeightPseudoUnit;
UpdateValue(aPresContext, mStyleContext,
mHeightSign, pseudoUnit, mHeight,
UpdateValue(mHeightSign, pseudoUnit, mHeight,
lspace, mBoundingMetrics, height);
// update "depth" (this is the descent in the terminology of the REC)
pseudoUnit = (mDepthPseudoUnit == NS_MATHML_PSEUDO_UNIT_ITSELF)
? NS_MATHML_PSEUDO_UNIT_DEPTH : mDepthPseudoUnit;
UpdateValue(aPresContext, mStyleContext,
mDepthSign, pseudoUnit, mDepth,
UpdateValue(mDepthSign, pseudoUnit, mDepth,
lspace, mBoundingMetrics, depth);
// update lspace -- should be *last* because lspace is overwritten!!
pseudoUnit = (mLeftSpacePseudoUnit == NS_MATHML_PSEUDO_UNIT_ITSELF)
? NS_MATHML_PSEUDO_UNIT_LSPACE : mLeftSpacePseudoUnit;
UpdateValue(aPresContext, mStyleContext,
mLeftSpaceSign, pseudoUnit, mLeftSpace,
UpdateValue(mLeftSpaceSign, pseudoUnit, mLeftSpace,
lspace, mBoundingMetrics, lspace);
// do the padding now that we have everything
@ -441,12 +446,10 @@ nsMathMLmpaddedFrame::Reflow(nsPresContext* aPresContext,
aDesiredSize.height += dy + depth - mBoundingMetrics.descent;
aDesiredSize.mBoundingMetrics = mBoundingMetrics;
// combine our tweaked size and our natural size to get our real estate
nsRect rect(0, 0, aDesiredSize.width, aDesiredSize.height);
aDesiredSize.mOverflowArea.MoveTo(dx, dy);
aDesiredSize.mOverflowArea.UnionRect(aDesiredSize.mOverflowArea, rect);
mReference.x = 0;
mReference.y = aDesiredSize.ascent;
if (dx || dy) {
if (aPlaceOrigin && (dx || dy)) {
nsIFrame* childFrame = mFrames.FirstChild();
while (childFrame) {
childFrame->SetPosition(childFrame->GetPosition() + nsPoint(dx, dy));
@ -454,11 +457,5 @@ nsMathMLmpaddedFrame::Reflow(nsPresContext* aPresContext,
}
}
mReference.x = 0;
mReference.y = aDesiredSize.ascent;
FinishAndStoreOverflow(&aDesiredSize);
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
return NS_OK;
}

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

@ -60,6 +60,11 @@ public:
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD
Place(nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize);
protected:
nsMathMLmpaddedFrame(nsStyleContext* aContext) : nsMathMLContainerFrame(aContext) {}
virtual ~nsMathMLmpaddedFrame();
@ -92,15 +97,13 @@ private:
nsCSSValue& aCSSValue,
PRInt32& aPseudoUnit);
static void
UpdateValue(nsPresContext* aPresContext,
nsStyleContext* aStyleContext,
PRInt32 aSign,
void
UpdateValue(PRInt32 aSign,
PRInt32 aPseudoUnit,
nsCSSValue& aCSSValue,
nscoord aLeftSpace,
nsBoundingMetrics& aBoundingMetrics,
nscoord& aValueToUpdate);
nscoord& aValueToUpdate) const;
};
#endif /* nsMathMLmpaddedFrame_h___ */

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

@ -369,6 +369,7 @@ nsMathMLmrootFrame::Reflow(nsPresContext* aPresContext,
aDesiredSize.width = mBoundingMetrics.width;
aDesiredSize.mBoundingMetrics = mBoundingMetrics;
GatherAndStoreOverflow(&aDesiredSize);
aStatus = NS_FRAME_COMPLETE;
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);

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

@ -164,18 +164,20 @@ nsMathMLmsqrtFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
}
NS_IMETHODIMP
nsMathMLmsqrtFrame::Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
nsMathMLmsqrtFrame::Place(nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize)
{
///////////////
// Let the base class format our content like an inferred mrow
nsHTMLReflowMetrics baseSize(aDesiredSize);
nsresult rv = nsMathMLContainerFrame::Reflow(aPresContext, baseSize,
aReflowState, aStatus);
//NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status");
if (NS_FAILED(rv)) return rv;
// Measure the size of our content using the base class to format like an
// inferred mrow.
nsHTMLReflowMetrics baseSize;
nsresult rv =
nsMathMLContainerFrame::Place(aRenderingContext, aPlaceOrigin, baseSize);
if (NS_MATHML_HAS_ERROR(mPresentationData.flags) || NS_FAILED(rv)) {
DidReflowChildren(GetFirstChild(nsnull));
return rv;
}
nsBoundingMetrics bmSqr, bmBase;
bmBase = baseSize.mBoundingMetrics;
@ -183,20 +185,19 @@ nsMathMLmsqrtFrame::Reflow(nsPresContext* aPresContext,
////////////
// Prepare the radical symbol and the overline bar
nsIRenderingContext& renderingContext = *aReflowState.rendContext;
renderingContext.SetFont(GetStyleFont()->mFont, nsnull);
aRenderingContext.SetFont(GetStyleFont()->mFont, nsnull);
nsCOMPtr<nsIFontMetrics> fm;
renderingContext.GetFontMetrics(*getter_AddRefs(fm));
aRenderingContext.GetFontMetrics(*getter_AddRefs(fm));
// For radical glyphs from TeX fonts and some of the radical glyphs from
// Mathematica fonts, the thickness of the overline can be obtained from the
// ascent of the glyph. Most fonts however have radical glyphs above the
// baseline so no assumption can be made about the meaning of the ascent.
nscoord ruleThickness, leading, em;
GetRuleThickness(renderingContext, fm, ruleThickness);
GetRuleThickness(aRenderingContext, fm, ruleThickness);
nsBoundingMetrics bmOne;
renderingContext.GetBoundingMetrics(NS_LITERAL_STRING("1").get(), 1, bmOne);
aRenderingContext.GetBoundingMetrics(NS_LITERAL_STRING("1").get(), 1, bmOne);
// get the leading to be left at the top of the resulting frame
// this seems more reliable than using fm->GetLeading() on suspicious fonts
@ -235,7 +236,7 @@ nsMathMLmsqrtFrame::Reflow(nsPresContext* aPresContext,
// height(radical) should be >= height(base) + psi + ruleThickness
nsBoundingMetrics radicalSize;
mSqrChar.Stretch(aPresContext, renderingContext,
mSqrChar.Stretch(PresContext(), aRenderingContext,
NS_STRETCH_DIRECTION_VERTICAL,
contSize, radicalSize,
NS_STRETCH_LARGER);
@ -271,20 +272,19 @@ nsMathMLmsqrtFrame::Reflow(nsPresContext* aPresContext,
mReference.x = 0;
mReference.y = aDesiredSize.ascent;
//////////////////
// Adjust the origins to leave room for the sqrt char and the overline bar
if (aPlaceOrigin) {
//////////////////
// Adjust the origins to leave room for the sqrt char and the overline bar
dx = radicalSize.width;
dy = aDesiredSize.ascent - baseSize.ascent;
nsIFrame* childFrame = mFrames.FirstChild();
while (childFrame) {
childFrame->SetPosition(childFrame->GetPosition() + nsPoint(dx, dy));
childFrame = childFrame->GetNextSibling();
dx = radicalSize.width;
dy = aDesiredSize.ascent - baseSize.ascent;
nsIFrame* childFrame = mFrames.FirstChild();
while (childFrame) {
childFrame->SetPosition(childFrame->GetPosition() + nsPoint(dx, dy));
childFrame = childFrame->GetNextSibling();
}
}
aDesiredSize.mBoundingMetrics = mBoundingMetrics;
aStatus = NS_FRAME_COMPLETE;
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
return NS_OK;
}

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

@ -88,10 +88,9 @@ public:
nsIFrame* aPrevInFlow);
NS_IMETHOD
Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
Place(nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,