don't use frame origin offsets to store ascents. b=363240, r+sr=roc

This commit is contained in:
karlt+%karlt.net 2008-02-26 04:19:36 +00:00
Родитель b5aa7e530c
Коммит 166233b82f
8 изменённых файлов: 156 добавлений и 124 удалений

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

@ -1491,6 +1491,9 @@ GK_ATOM(changeListProperty, "ChangeListProperty") // void*
GK_ATOM(collapseOffsetProperty, "CollapseOffsetProperty") // nsPoint* GK_ATOM(collapseOffsetProperty, "CollapseOffsetProperty") // nsPoint*
GK_ATOM(computedOffsetProperty, "ComputedOffsetProperty") // nsPoint* GK_ATOM(computedOffsetProperty, "ComputedOffsetProperty") // nsPoint*
GK_ATOM(generatedContent, "GeneratedContentProperty") // nsCOMArray<nsIContent>* GK_ATOM(generatedContent, "GeneratedContentProperty") // nsCOMArray<nsIContent>*
#ifdef MOZ_MATHML
GK_ATOM(HTMLReflowMetricsProperty, "HTMLReflowMetricsProperty") // nsHTMLReflowMetrics*
#endif
GK_ATOM(IBSplitSpecialPrevSibling, "IBSplitSpecialPrevSibling")// nsIFrame* GK_ATOM(IBSplitSpecialPrevSibling, "IBSplitSpecialPrevSibling")// nsIFrame*
GK_ATOM(IBSplitSpecialSibling, "IBSplitSpecialSibling") // nsIFrame* GK_ATOM(IBSplitSpecialSibling, "IBSplitSpecialSibling") // nsIFrame*
GK_ATOM(lineCursorProperty, "LineCursorProperty") // nsLineBox* GK_ATOM(lineCursorProperty, "LineCursorProperty") // nsLineBox*

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

@ -125,12 +125,13 @@ public:
/* Place : /* Place :
* This method is used before returning from Reflow(), or when a MathML frame * 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 * The Place() method will use this information to compute the desired size
* of the frame. * 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 // The bit merely tells the context of the frame. In the context of
// displaystyle="false", it is intended to slightly alter how the // displaystyle="false", it is intended to slightly alter how the
// rendering is done in inline mode. // rendering is done in inline mode.
#define NS_MATHML_DISPLAYSTYLE 0x00000001 #define NS_MATHML_DISPLAYSTYLE 0x00000001U
// This bit is used to emulate TeX rendering. // This bit is used to emulate TeX rendering.
// Internal use only, cannot be set by the user with an attribute. // 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 // This bit is set if the frame will fire a vertical stretch
// command on all its (non-empty) children. // command on all its (non-empty) children.
// Tags like <mrow> (or an inferred mrow), mpadded, etc, will fire a // Tags like <mrow> (or an inferred mrow), mpadded, etc, will fire a
// vertical stretch command on all their non-empty children // 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 // This bit is set if the frame will fire a horizontal stretch
// command on all its (non-empty) children. // command on all its (non-empty) children.
// Tags like munder, mover, munderover, will fire a // Tags like munder, mover, munderover, will fire a
// horizontal stretch command on all their non-empty children // 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 // This bit is set if the frame has the explicit attribute
// displaystyle="true" or "false". It is only relevant to <mstyle> and <mtable> // displaystyle="true" or "false". It is only relevant to <mstyle> and <mtable>
// because they are the only tags where the attribute is allowed by the spec. // 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 // This bit is set when the frame cannot be formatted due to an
// error (e.g., invalid markup such as a <msup> without an overscript). // error (e.g., invalid markup such as a <msup> without an overscript).
// When set, a visual feedback will be provided to the user. // 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 // 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 // This bit is used for visual debug. When set, the bounding box
// of your frame is painted. This visual debug enable to ensure that // of your frame is painted. This visual debug enable to ensure that
// you have properly filled your mReference and mBoundingMetrics in // you have properly filled your mReference and mBoundingMetrics in
// Place(). // Place().
#define NS_MATHML_SHOW_BOUNDING_METRICS 0x10000000 #define NS_MATHML_SHOW_BOUNDING_METRICS 0x10000000U
// Macros that retrieve those bits // Macros that retrieve those bits

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

@ -58,7 +58,6 @@
#include "nsGkAtoms.h" #include "nsGkAtoms.h"
#include "nsMathMLParts.h" #include "nsMathMLParts.h"
#include "nsMathMLChar.h"
#include "nsMathMLContainerFrame.h" #include "nsMathMLContainerFrame.h"
#include "nsAutoPtr.h" #include "nsAutoPtr.h"
#include "nsStyleSet.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<nsHTMLReflowMetrics*>(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 // helper method to facilitate getting the reflow and bounding metrics
void /* static */ void
nsMathMLContainerFrame::GetReflowAndBoundingMetricsFor(nsIFrame* aFrame, nsMathMLContainerFrame::GetReflowAndBoundingMetricsFor(nsIFrame* aFrame,
nsHTMLReflowMetrics& aReflowMetrics, nsHTMLReflowMetrics& aReflowMetrics,
nsBoundingMetrics& aBoundingMetrics, nsBoundingMetrics& aBoundingMetrics,
@ -175,37 +201,42 @@ nsMathMLContainerFrame::GetReflowAndBoundingMetricsFor(nsIFrame* aFra
{ {
NS_PRECONDITION(aFrame, "null arg"); NS_PRECONDITION(aFrame, "null arg");
nsHTMLReflowMetrics *metrics = static_cast<nsHTMLReflowMetrics*>
(aFrame->GetProperty(nsGkAtoms::HTMLReflowMetricsProperty));
// IMPORTANT: This function is only meant to be called in Place() methods // 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 // where it is assumed that SaveReflowAndBoundingMetricsFor has recorded the
// for the frame's ascent and descent information // information.
NS_ASSERTION(metrics, "Didn't SaveReflowAndBoundingMetricsFor frame!");
if (metrics) {
aReflowMetrics = *metrics;
aBoundingMetrics = metrics->mBoundingMetrics;
}
nsRect rect = aFrame->GetRect(); if (aMathMLFrameType) {
aReflowMetrics.ascent = rect.y; if (!IsForeignChild(aFrame)) {
aReflowMetrics.width = rect.width;
aReflowMetrics.height = rect.height;
nscoord descent = aReflowMetrics.height - aReflowMetrics.ascent;
if (aFrame->IsFrameOfType(nsIFrame::eMathML)) {
nsIMathMLFrame* mathMLFrame; nsIMathMLFrame* mathMLFrame;
CallQueryInterface(aFrame, &mathMLFrame); CallQueryInterface(aFrame, &mathMLFrame);
if (mathMLFrame) { if (mathMLFrame) {
mathMLFrame->GetBoundingMetrics(aBoundingMetrics);
if (aMathMLFrameType)
*aMathMLFrameType = mathMLFrame->GetMathMLFrameType(); *aMathMLFrameType = mathMLFrame->GetMathMLFrameType();
return; return;
} }
} }
// 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; *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 // helper to get the preferred size that a container frame should use to fire
// the stretch on its stretchy child frames. // the stretch on its stretchy child frames.
void void
@ -236,13 +267,6 @@ nsMathMLContainerFrame::GetPreferredStretchSize(nsIRenderingContext& aRenderingC
nsIFrame* childFrame = GetFirstChild(nsnull); nsIFrame* childFrame = GetFirstChild(nsnull);
while (childFrame) { while (childFrame) {
// initializations in case this child happens not to be a MathML frame // 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; nsIMathMLFrame* mathMLFrame;
childFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); childFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame);
if (mathMLFrame) { if (mathMLFrame) {
@ -254,6 +278,8 @@ nsMathMLContainerFrame::GetPreferredStretchSize(nsIRenderingContext& aRenderingC
embellishData.direction == aStretchDirection && embellishData.direction == aStretchDirection &&
presentationData.baseFrame) { presentationData.baseFrame) {
// embellishements are not included, only consider the inner first child itself // 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; nsIMathMLFrame* mathMLchildFrame;
presentationData.baseFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLchildFrame); presentationData.baseFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLchildFrame);
if (mathMLchildFrame) { if (mathMLchildFrame) {
@ -262,6 +288,10 @@ nsMathMLContainerFrame::GetPreferredStretchSize(nsIRenderingContext& aRenderingC
} }
mathMLFrame->GetBoundingMetrics(bmChild); mathMLFrame->GetBoundingMetrics(bmChild);
} }
else {
nsHTMLReflowMetrics unused;
GetReflowAndBoundingMetricsFor(childFrame, unused, bmChild);
}
if (firstTime) { if (firstTime) {
firstTime = PR_FALSE; firstTime = PR_FALSE;
@ -361,10 +391,9 @@ nsMathMLContainerFrame::Stretch(nsIRenderingContext& aRenderingContext,
// do the stretching... // do the stretching...
mathMLFrame->Stretch(aRenderingContext, mathMLFrame->Stretch(aRenderingContext,
mEmbellishData.direction, containerSize, childSize); mEmbellishData.direction, containerSize, childSize);
// store the updated metrics // store the updated metrics
baseFrame->SetRect(nsRect(0, childSize.ascent, SaveReflowAndBoundingMetricsFor(baseFrame, childSize,
childSize.width, childSize.height)); childSize.mBoundingMetrics);
// Remember the siblings which were _deferred_. // Remember the siblings which were _deferred_.
// Now that this embellished child may have changed, we need to // Now that this embellished child may have changed, we need to
@ -391,8 +420,8 @@ nsMathMLContainerFrame::Stretch(nsIRenderingContext& aRenderingContext,
mathMLFrame->Stretch(aRenderingContext, stretchDir, mathMLFrame->Stretch(aRenderingContext, stretchDir,
containerSize, childSize); containerSize, childSize);
// store the updated metrics // store the updated metrics
childFrame->SetRect(nsRect(0, childSize.ascent, SaveReflowAndBoundingMetricsFor(childFrame, childSize,
childSize.width, childSize.height)); childSize.mBoundingMetrics);
} }
} }
childFrame = childFrame->GetNextSibling(); childFrame = childFrame->GetNextSibling();
@ -441,6 +470,8 @@ nsMathMLContainerFrame::Stretch(nsIRenderingContext& aRenderingContext,
} }
} }
// Finished with these:
ClearSavedChildMetrics();
// Set our overflow area // Set our overflow area
GatherAndStoreOverflow(&aDesiredStretchSize); GatherAndStoreOverflow(&aDesiredStretchSize);
} }
@ -490,11 +521,11 @@ nsMathMLContainerFrame::FinalizeReflow(nsIRenderingContext& aRenderingContext,
return rv; return rv;
} }
PRBool parentWillFireStretch = PR_FALSE;
if (!placeOrigin) { if (!placeOrigin) {
// This means the rect.x and rect.y of our children were not set!! // 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 // 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... // targeted at us. The Stretch() will cause the rect.x and rect.y to clear...
PRBool parentWillFireStretch = PR_FALSE;
nsIMathMLFrame* mathMLFrame; nsIMathMLFrame* mathMLFrame;
mParent->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); mParent->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame);
if (mathMLFrame) { if (mathMLFrame) {
@ -550,8 +581,11 @@ nsMathMLContainerFrame::FinalizeReflow(nsIRenderingContext& aRenderingContext,
// Also return our bounding metrics // Also return our bounding metrics
aDesiredSize.mBoundingMetrics = mBoundingMetrics; aDesiredSize.mBoundingMetrics = mBoundingMetrics;
if (placeOrigin) { if (!parentWillFireStretch) {
// Not expecting a stretch. Set our overflow area. // Not expecting a stretch.
// Finished with these:
ClearSavedChildMetrics();
// Set our overflow area.
GatherAndStoreOverflow(&aDesiredSize); GatherAndStoreOverflow(&aDesiredSize);
} }
@ -844,15 +878,6 @@ nsMathMLContainerFrame::GatherAndStoreOverflow(nsHTMLReflowMetrics* aMetrics)
FinishAndStoreOverflow(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 nsresult
nsMathMLContainerFrame::ReflowChild(nsIFrame* aChildFrame, nsMathMLContainerFrame::ReflowChild(nsIFrame* aChildFrame,
nsPresContext* aPresContext, nsPresContext* aPresContext,
@ -876,13 +901,13 @@ nsMathMLContainerFrame::ReflowChild(nsIFrame* aChildFrame,
NS_ASSERTION(!inlineFrame, "Inline frames should be wrapped in blocks"); NS_ASSERTION(!inlineFrame, "Inline frames should be wrapped in blocks");
#endif #endif
// XXX should we do something here to compute good bounding metrics for
// the child?
nsresult rv = nsHTMLContainerFrame:: nsresult rv = nsHTMLContainerFrame::
ReflowChild(aChildFrame, aPresContext, aDesiredSize, aReflowState, ReflowChild(aChildFrame, aPresContext, aDesiredSize, aReflowState,
0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
if (NS_FAILED(rv))
return rv;
if (aDesiredSize.ascent == nsHTMLReflowMetrics::ASK_FOR_BASELINE) { if (aDesiredSize.ascent == nsHTMLReflowMetrics::ASK_FOR_BASELINE) {
// This will be suitable for inline frames, which are wrapped in a block. // This will be suitable for inline frames, which are wrapped in a block.
if(!nsLayoutUtils::GetLastLineBaseline(aChildFrame, if(!nsLayoutUtils::GetLastLineBaseline(aChildFrame,
@ -893,8 +918,7 @@ nsMathMLContainerFrame::ReflowChild(nsIFrame* aChildFrame,
aDesiredSize.ascent = aDesiredSize.height; aDesiredSize.ascent = aDesiredSize.height;
} }
} }
if (IsForeignChild(aChildFrame) && if (IsForeignChild(aChildFrame)) {
(aDesiredSize.mFlags | NS_REFLOW_CALC_BOUNDING_METRICS)) {
// use ComputeTightBounds API as aDesiredSize.mBoundingMetrics is not set. // use ComputeTightBounds API as aDesiredSize.mBoundingMetrics is not set.
nsRect r = aChildFrame->ComputeTightBounds(aReflowState.rendContext->ThebesContext()); nsRect r = aChildFrame->ComputeTightBounds(aReflowState.rendContext->ThebesContext());
aDesiredSize.mBoundingMetrics.leftBearing = r.x; aDesiredSize.mBoundingMetrics.leftBearing = r.x;
@ -936,11 +960,8 @@ nsMathMLContainerFrame::Reflow(nsPresContext* aPresContext,
return rv; return rv;
} }
// At this stage, the origin points of the children have no use, so we will use the SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
// origins as placeholders to store the child's ascent and descent. Later on, childDesiredSize.mBoundingMetrics);
// 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));
childFrame = childFrame->GetNextSibling(); childFrame = childFrame->GetNextSibling();
} }
@ -983,8 +1004,8 @@ nsMathMLContainerFrame::Reflow(nsPresContext* aPresContext,
mathMLFrame->Stretch(*aReflowState.rendContext, stretchDir, mathMLFrame->Stretch(*aReflowState.rendContext, stretchDir,
containerSize, childDesiredSize); containerSize, childDesiredSize);
// store the updated metrics // store the updated metrics
childFrame->SetRect(nsRect(0, childDesiredSize.ascent, SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
childDesiredSize.width, childDesiredSize.height)); childDesiredSize.mBoundingMetrics);
} }
childFrame = childFrame->GetNextSibling(); childFrame = childFrame->GetNextSibling();
} }

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

@ -119,6 +119,8 @@ public:
nsHTMLContainerFrame::IsFrameOfType(aFlags & ~(nsIFrame::eMathML)); nsHTMLContainerFrame::IsFrameOfType(aFlags & ~(nsIFrame::eMathML));
} }
virtual PRIntn GetSkipSides() const { return 0; }
NS_IMETHOD NS_IMETHOD
AppendFrames(nsIAtom* aListName, AppendFrames(nsIAtom* aListName,
nsIFrame* aFrameList); nsIFrame* aFrameList);
@ -229,18 +231,29 @@ public:
FinalizeReflow(nsIRenderingContext& aRenderingContext, FinalizeReflow(nsIRenderingContext& aRenderingContext,
nsHTMLReflowMetrics& aDesiredSize); nsHTMLReflowMetrics& aDesiredSize);
// helper method to facilitate getting the reflow and bounding metrics. // Record metrics of a child frame for recovery through the following method
// The argument aMathMLFrameType, when non null, will return the 'type' of static void
// the frame, which is used to determine the inter-frame spacing. SaveReflowAndBoundingMetricsFor(nsIFrame* aFrame,
// IMPORTANT: This function is only meant to be called in Place() methods const nsHTMLReflowMetrics& aReflowMetrics,
// where it is assumed that the frame's rect is still acting as place holder const nsBoundingMetrics& aBoundingMetrics);
// for the frame's ascent and descent information
// 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 static void
GetReflowAndBoundingMetricsFor(nsIFrame* aFrame, GetReflowAndBoundingMetricsFor(nsIFrame* aFrame,
nsHTMLReflowMetrics& aReflowMetrics, nsHTMLReflowMetrics& aReflowMetrics,
nsBoundingMetrics& aBoundingMetrics, nsBoundingMetrics& aBoundingMetrics,
eMathMLFrameType* aMathMLFrameType = nsnull); 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 // helper to let the update of presentation data pass through
// a subtree that may contain non-MathML container frames // a subtree that may contain non-MathML container frames
static void static void
@ -284,8 +297,6 @@ public:
ReLayoutChildren(nsIFrame* aParentFrame, nsFrameState aBits); ReLayoutChildren(nsIFrame* aParentFrame, nsFrameState aBits);
protected: protected:
virtual PRIntn GetSkipSides() const { return 0; }
// Helper method which positions child frames as an <mrow> on given baseline // Helper method which positions child frames as an <mrow> on given baseline
// y = aBaseline starting from x = aOffsetX, calling FinishReflowChild() // y = aBaseline starting from x = aOffsetX, calling FinishReflowChild()
// on the frames. // on the frames.

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

@ -145,9 +145,8 @@ nsMathMLTokenFrame::Reflow(nsPresContext* aPresContext,
return rv; return rv;
} }
// origins are used as placeholders to store the child's ascent. SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
childFrame->SetRect(nsRect(0, childDesiredSize.ascent, childDesiredSize.mBoundingMetrics);
childDesiredSize.width, childDesiredSize.height));
// compute and cache the bounding metrics // compute and cache the bounding metrics
aDesiredSize.mBoundingMetrics += childDesiredSize.mBoundingMetrics; aDesiredSize.mBoundingMetrics += childDesiredSize.mBoundingMetrics;
@ -189,15 +188,14 @@ nsMathMLTokenFrame::Place(nsIRenderingContext& aRenderingContext,
nscoord dy, dx = 0; nscoord dy, dx = 0;
nsIFrame* childFrame = GetFirstChild(nsnull); nsIFrame* childFrame = GetFirstChild(nsnull);
while (childFrame) { while (childFrame) {
nsRect rect = childFrame->GetRect();
nsHTMLReflowMetrics childSize; nsHTMLReflowMetrics childSize;
childSize.width = rect.width; GetReflowAndBoundingMetricsFor(childFrame, childSize,
childSize.height = rect.height; childSize.mBoundingMetrics);
// place and size the child; (dx,0) makes the caret happy - bug 188146 // 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); FinishReflowChild(childFrame, PresContext(), nsnull, childSize, dx, dy, 0);
dx += rect.width; dx += childSize.width;
childFrame = childFrame->GetNextSibling(); childFrame = childFrame->GetNextSibling();
} }
} }

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

@ -288,8 +288,8 @@ nsMathMLmactionFrame::Reflow(nsPresContext* aPresContext,
childFrame, availSize); childFrame, availSize);
rv = ReflowChild(childFrame, aPresContext, aDesiredSize, rv = ReflowChild(childFrame, aPresContext, aDesiredSize,
childReflowState, aStatus); childReflowState, aStatus);
childFrame->SetRect(nsRect(0,aDesiredSize.ascent, SaveReflowAndBoundingMetricsFor(childFrame, aDesiredSize,
aDesiredSize.width,aDesiredSize.height)); aDesiredSize.mBoundingMetrics);
mBoundingMetrics = aDesiredSize.mBoundingMetrics; mBoundingMetrics = aDesiredSize.mBoundingMetrics;
} }
FinalizeReflow(*aReflowState.rendContext, aDesiredSize); FinalizeReflow(*aReflowState.rendContext, aDesiredSize);

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

@ -250,7 +250,7 @@ nsMathMLmfencedFrame::doReflow(nsPresContext* aPresContext,
const nsHTMLReflowState& aReflowState, const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aDesiredSize, nsHTMLReflowMetrics& aDesiredSize,
nsReflowStatus& aStatus, nsReflowStatus& aStatus,
nsIFrame* aForFrame, nsMathMLContainerFrame* aForFrame,
nsMathMLChar* aOpenChar, nsMathMLChar* aOpenChar,
nsMathMLChar* aCloseChar, nsMathMLChar* aCloseChar,
nsMathMLChar* aSeparatorsChar, nsMathMLChar* aSeparatorsChar,
@ -262,9 +262,6 @@ nsMathMLmfencedFrame::doReflow(nsPresContext* aPresContext,
aDesiredSize.ascent = 0; aDesiredSize.ascent = 0;
aDesiredSize.mBoundingMetrics.Clear(); aDesiredSize.mBoundingMetrics.Clear();
nsMathMLContainerFrame* mathMLFrame =
static_cast<nsMathMLContainerFrame*>(aForFrame);
PRInt32 i; PRInt32 i;
nsCOMPtr<nsIFontMetrics> fm; nsCOMPtr<nsIFontMetrics> fm;
const nsStyleFont* font = aForFrame->GetStyleFont(); const nsStyleFont* font = aForFrame->GetStyleFont();
@ -304,20 +301,17 @@ nsMathMLmfencedFrame::doReflow(nsPresContext* aPresContext,
| NS_REFLOW_CALC_BOUNDING_METRICS); | NS_REFLOW_CALC_BOUNDING_METRICS);
nsHTMLReflowState childReflowState(aPresContext, aReflowState, nsHTMLReflowState childReflowState(aPresContext, aReflowState,
childFrame, availSize); childFrame, availSize);
rv = mathMLFrame->ReflowChild(childFrame, aPresContext, childDesiredSize, rv = aForFrame->ReflowChild(childFrame, aPresContext, childDesiredSize,
childReflowState, childStatus); childReflowState, childStatus);
//NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status"); //NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status");
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
// Call DidReflow() for the child frames we successfully did reflow. // Call DidReflow() for the child frames we successfully did reflow.
mathMLFrame->DidReflowChildren(firstChild, childFrame); aForFrame->DidReflowChildren(firstChild, childFrame);
return rv; return rv;
} }
// At this stage, the origin points of the children have no use, so we will use the SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
// origins as placeholders to store the child's ascent and descent. Later on, childDesiredSize.mBoundingMetrics);
// 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));
// compute the bounding metrics right now for mfrac // compute the bounding metrics right now for mfrac
nscoord childDescent = childDesiredSize.height - childDesiredSize.ascent; nscoord childDescent = childDesiredSize.height - childDesiredSize.ascent;
@ -337,14 +331,14 @@ nsMathMLmfencedFrame::doReflow(nsPresContext* aPresContext,
nsStretchDirection stretchDir = NS_STRETCH_DIRECTION_VERTICAL; nsStretchDirection stretchDir = NS_STRETCH_DIRECTION_VERTICAL;
nsPresentationData presentationData; nsPresentationData presentationData;
mathMLFrame->GetPresentationData(presentationData); aForFrame->GetPresentationData(presentationData);
if (!NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(presentationData.flags)) { 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 // case when the call is made for mfrac, we only need to stretch the '/' separator
containerSize = aDesiredSize.mBoundingMetrics; // computed earlier containerSize = aDesiredSize.mBoundingMetrics; // computed earlier
} }
else { else {
// case when the call is made for mfenced // case when the call is made for mfenced
mathMLFrame->GetPreferredStretchSize(*aReflowState.rendContext, aForFrame->GetPreferredStretchSize(*aReflowState.rendContext,
0, /* i.e., without embellishments */ 0, /* i.e., without embellishments */
stretchDir, containerSize); stretchDir, containerSize);
childFrame = firstChild; childFrame = firstChild;
@ -354,13 +348,14 @@ nsMathMLmfencedFrame::doReflow(nsPresContext* aPresContext,
if (mathmlChild) { if (mathmlChild) {
nsHTMLReflowMetrics childDesiredSize; nsHTMLReflowMetrics childDesiredSize;
// retrieve the metrics that was stored at the previous pass // retrieve the metrics that was stored at the previous pass
GetReflowAndBoundingMetricsFor(childFrame, childDesiredSize, childDesiredSize.mBoundingMetrics); GetReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
childDesiredSize.mBoundingMetrics);
mathmlChild->Stretch(*aReflowState.rendContext, mathmlChild->Stretch(*aReflowState.rendContext,
stretchDir, containerSize, childDesiredSize); stretchDir, containerSize, childDesiredSize);
// store the updated metrics // store the updated metrics
childFrame->SetRect(nsRect(0, childDesiredSize.ascent, SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
childDesiredSize.width, childDesiredSize.height)); childDesiredSize.mBoundingMetrics);
nscoord childDescent = childDesiredSize.height - childDesiredSize.ascent; nscoord childDescent = childDesiredSize.height - childDesiredSize.ascent;
if (descent < childDescent) if (descent < childDescent)
@ -371,7 +366,7 @@ nsMathMLmfencedFrame::doReflow(nsPresContext* aPresContext,
childFrame = childFrame->GetNextSibling(); childFrame = childFrame->GetNextSibling();
} }
// bug 121748: for surrounding fences & separators, use a size that covers everything // bug 121748: for surrounding fences & separators, use a size that covers everything
mathMLFrame->GetPreferredStretchSize(*aReflowState.rendContext, aForFrame->GetPreferredStretchSize(*aReflowState.rendContext,
STRETCH_CONSIDER_EMBELLISHMENTS, STRETCH_CONSIDER_EMBELLISHMENTS,
stretchDir, containerSize); stretchDir, containerSize);
} }
@ -431,7 +426,7 @@ nsMathMLmfencedFrame::doReflow(nsPresContext* aPresContext,
else else
aDesiredSize.mBoundingMetrics += bm; aDesiredSize.mBoundingMetrics += bm;
mathMLFrame->FinishReflowChild(childFrame, aPresContext, nsnull, childSize, aForFrame->FinishReflowChild(childFrame, aPresContext, nsnull, childSize,
dx, ascent - childSize.ascent, 0); dx, ascent - childSize.ascent, 0);
dx += childSize.width; dx += childSize.width;
@ -456,14 +451,17 @@ nsMathMLmfencedFrame::doReflow(nsPresContext* aPresContext,
aDesiredSize.height = ascent + descent; aDesiredSize.height = ascent + descent;
aDesiredSize.ascent = ascent; aDesiredSize.ascent = ascent;
mathMLFrame->SetBoundingMetrics(aDesiredSize.mBoundingMetrics); aForFrame->SetBoundingMetrics(aDesiredSize.mBoundingMetrics);
mathMLFrame->SetReference(nsPoint(0, aDesiredSize.ascent)); aForFrame->SetReference(nsPoint(0, aDesiredSize.ascent));
// see if we should fix the spacing // see if we should fix the spacing
mathMLFrame->FixInterFrameSpacing(aDesiredSize); aForFrame->FixInterFrameSpacing(aDesiredSize);
// Finished with these:
aForFrame->ClearSavedChildMetrics();
// Set our overflow area // Set our overflow area
mathMLFrame->GatherAndStoreOverflow(&aDesiredSize); aForFrame->GatherAndStoreOverflow(&aDesiredSize);
aStatus = NS_FRAME_COMPLETE; aStatus = NS_FRAME_COMPLETE;
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);

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

@ -94,7 +94,7 @@ public:
const nsHTMLReflowState& aReflowState, const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aDesiredSize, nsHTMLReflowMetrics& aDesiredSize,
nsReflowStatus& aStatus, nsReflowStatus& aStatus,
nsIFrame* aForFrame, nsMathMLContainerFrame* aForFrame,
nsMathMLChar* aOpenChar, nsMathMLChar* aOpenChar,
nsMathMLChar* aCloseChar, nsMathMLChar* aCloseChar,
nsMathMLChar* aSeparatorsChar, nsMathMLChar* aSeparatorsChar,