Bug 1908069 - Introduce PlaceFlags parameter to MathML layout methods. r=emilio

MathML classes has a few Place*() methods  used for layout and intrinsic
size calculation. These methods have a parameter "aPlaceOrigin"
indicating whether the children and other painted objects should have
their final positions set, or if the method is only called for measuring.
This parameter is typically set to false when doing intrinsic size
calculation or when performing some non-final measurement for operator
stretching.

For intrinsic size calculation, it is generally enough to perform
placement with aPlaceOrigin=false and ignoring the vertical metrics.
Some Place*() methods also have a parameter "aWidthOnly" for special
handling. For example, msqrt stretches a radical symbol vertically to
match the height of the content but when doing intrinsic size
calculation this is approximated to nsMathMLChar::GetMaxWidth() instead.
When we implement border/padding/margin we should also be able to
choose between using IntrinsicISizeOffsets() or GetUsed*() methods.

Finally, some Place*() methods initially call a place routing of a
parent class before further tweaking the layout. For example, msqrt
uses mrow layout on children and adds some radical symbol on top of
them. When we implement border/padding, we should make sure we don't
add the border/padding before the final result.

In order to handle all these placement behaviors, a new EnumSet is
introduced. This commit does not change behavior. Handling of padding,
border and margin will be handled in follow-up patches.

Differential Revision: https://phabricator.services.mozilla.com/D216669
This commit is contained in:
Frédéric Wang 2024-08-07 06:00:43 +00:00
parent 7a1a9c40a3
commit bcc3be9085
17 changed files with 146 additions and 113 deletions

View File

@ -103,9 +103,10 @@ void nsMathMLContainerFrame::GetPreferredStretchSize(
// when our actual size is ok, just use it
aPreferredStretchSize = mBoundingMetrics;
} else if (aOptions & STRETCH_CONSIDER_EMBELLISHMENTS) {
// compute our up-to-date size using Place()
// compute our up-to-date size using Place(), without border/padding.
ReflowOutput reflowOutput(GetWritingMode());
Place(aDrawTarget, false, reflowOutput);
PlaceFlags flags(PlaceFlag::MeasureOnly, PlaceFlag::IgnoreBorderPadding);
Place(aDrawTarget, flags, reflowOutput);
aPreferredStretchSize = reflowOutput.mBoundingMetrics;
} else {
// compute a size that includes embellishments iff the container stretches
@ -296,7 +297,8 @@ nsMathMLContainerFrame::Stretch(DrawTarget* aDrawTarget,
}
// re-position all our children
nsresult rv = Place(aDrawTarget, true, aDesiredStretchSize);
PlaceFlags flags;
nsresult rv = Place(aDrawTarget, flags, aDesiredStretchSize);
if (NS_FAILED(rv)) {
// Make sure the child frames get their DidReflow() calls.
DidReflowChildren(mFrames.FirstChild());
@ -378,14 +380,18 @@ nsresult nsMathMLContainerFrame::FinalizeReflow(DrawTarget* aDrawTarget,
!NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags) ||
(mEmbellishData.coreFrame != this && !mPresentationData.baseFrame &&
mEmbellishData.direction == NS_STRETCH_DIRECTION_UNSUPPORTED);
nsresult rv = Place(aDrawTarget, placeOrigin, aDesiredSize);
PlaceFlags flags;
if (!placeOrigin) {
flags += PlaceFlag::MeasureOnly;
}
nsresult rv = Place(aDrawTarget, flags, aDesiredSize);
// 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 placeOrigin is false we should reach Place() with
// PlaceFlag::MeasureOnly unset through Stretch() eventually.
if (NS_FAILED(rv)) {
GatherAndStoreOverflow(&aDesiredSize);
DidReflowChildren(PrincipalChildList().FirstChild());
@ -865,9 +871,6 @@ void nsMathMLContainerFrame::GetIntrinsicISizeMetrics(
containerFrame->GetIntrinsicISizeMetrics(aRenderingContext,
childDesiredSize);
} else {
// XXX This includes margin while Reflow currently doesn't consider
// margin, so we may end up with too much space, but, with stretchy
// characters, this is an approximation anyway.
nscoord width = nsLayoutUtils::IntrinsicForContainer(
aRenderingContext, childFrame, IntrinsicISizeType::PrefISize);
@ -894,7 +897,8 @@ void nsMathMLContainerFrame::GetIntrinsicISizeMetrics(
nsresult rv =
MeasureForWidth(aRenderingContext->GetDrawTarget(), aDesiredSize);
if (NS_FAILED(rv)) {
PlaceAsMrow(aRenderingContext->GetDrawTarget(), false, aDesiredSize);
PlaceFlags flags(PlaceFlag::IntrinsicSize, PlaceFlag::MeasureOnly);
PlaceAsMrow(aRenderingContext->GetDrawTarget(), flags, aDesiredSize);
}
ClearSavedChildMetrics();
@ -903,7 +907,8 @@ void nsMathMLContainerFrame::GetIntrinsicISizeMetrics(
/* virtual */
nsresult nsMathMLContainerFrame::MeasureForWidth(DrawTarget* aDrawTarget,
ReflowOutput& aDesiredSize) {
return Place(aDrawTarget, false, aDesiredSize);
PlaceFlags flags(PlaceFlag::IntrinsicSize, PlaceFlag::MeasureOnly);
return Place(aDrawTarget, flags, aDesiredSize);
}
// see spacing table in Chapter 18, TeXBook (p.170)
@ -1107,7 +1112,7 @@ class nsMathMLContainerFrame::RowChildFrameIterator {
/* virtual */
nsresult nsMathMLContainerFrame::Place(DrawTarget* aDrawTarget,
bool aPlaceOrigin,
const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) {
// This is needed in case this frame is empty (i.e., no child frames)
mBoundingMetrics = nsBoundingMetrics();
@ -1139,7 +1144,7 @@ nsresult nsMathMLContainerFrame::Place(DrawTarget* aDrawTarget,
//////////////////
// Place Children
if (aPlaceOrigin) {
if (!aFlags.contains(PlaceFlag::MeasureOnly)) {
PositionRowChildFrames(0, aDesiredSize.BlockStartAscent());
}
@ -1147,9 +1152,9 @@ nsresult nsMathMLContainerFrame::Place(DrawTarget* aDrawTarget,
}
nsresult nsMathMLContainerFrame::PlaceAsMrow(DrawTarget* aDrawTarget,
bool aPlaceOrigin,
const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) {
return nsMathMLContainerFrame::Place(aDrawTarget, aPlaceOrigin, aDesiredSize);
return nsMathMLContainerFrame::Place(aDrawTarget, aFlags, aDesiredSize);
}
void nsMathMLContainerFrame::PositionRowChildFrames(nscoord aOffsetX,

View File

@ -133,11 +133,37 @@ class nsMathMLContainerFrame : public nsContainerFrame, public nsMathMLFrame {
// Additional methods
protected:
enum class PlaceFlag : uint8_t {
// If MeasureOnly is set, compute your desired size using the information
// from GetReflowAndBoundingMetricsFor. However, child frames or other
// elements should not be repositioned.
// If MeasureOnly is not set, reflow is finished. You should position all
// your children, and return your desired size. You should now use
// FinishReflowChild() on your children to complete post-reflow operations.
MeasureOnly,
// If IntrinsicSize is set, the function is actually used to determine
// intrinsic size (and consequently MeasureOnly is expected to be set too).
// - It will use nsMathMLChar::GetMaxWidth instead of nsMathMLChar::Stretch.
// - It will use IntrinsicISizeOffsets() for padding/border/margin instead
// of GetUsedBorder/Padding/Margin().
// - etc
IntrinsicSize,
// If IgnoreBorderPadding is set, the function will complete without
// adding the border/padding around the math layout. This can be used for
// elements like <msqrt> that first layout their children as an <mrow>,
// place some radical symbol on top of them and finally add its
// padding/border around that radical symbol.
IgnoreBorderPadding,
};
using PlaceFlags = mozilla::EnumSet<PlaceFlag>;
/* Place :
* This method is used to measure or position child frames and other
* elements. It may be called any number of times with aPlaceOrigin
* false to measure, and the final call of the Reflow process before
* returning from Reflow() or Stretch() will have aPlaceOrigin true
* elements. It may be called any number of times with MeasureOnly
* true, and the final call of the Reflow process before
* returning from Reflow() or Stretch() will have MeasureOnly false
* to position the elements.
*
* IMPORTANT: This method uses GetReflowAndBoundingMetricsFor() which must
@ -146,15 +172,8 @@ class nsMathMLContainerFrame : public nsContainerFrame, public nsMathMLFrame {
* The Place() method will use this information to compute the desired size
* of the frame.
*
* @param aPlaceOrigin [in]
* If aPlaceOrigin is false, compute your desired size using the
* information from GetReflowAndBoundingMetricsFor. However, child
* frames or other elements should not be repositioned.
*
* If aPlaceOrigin is true, reflow is finished. You should position
* all your children, and return your desired size. You should now
* use FinishReflowChild() on your children to complete post-reflow
* operations.
* @param aFlags [in] Flags to indicate the way the Place method should
* behave. See document for PlaceFlag above.
*
* @param aDesiredSize [out] parameter where you should return your desired
* size and your ascent/descent info. Compute your desired size using
@ -162,7 +181,7 @@ class nsMathMLContainerFrame : public nsContainerFrame, public nsMathMLFrame {
* any space you want for border/padding in the desired size you
* return.
*/
virtual nsresult Place(DrawTarget* aDrawTarget, bool aPlaceOrigin,
virtual nsresult Place(DrawTarget* aDrawTarget, const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize);
// MeasureForWidth:
@ -197,7 +216,7 @@ class nsMathMLContainerFrame : public nsContainerFrame, public nsMathMLFrame {
* (typically invalid markup) was encountered during reflow. Parameters are
* the same as Place().
*/
nsresult PlaceAsMrow(DrawTarget* aDrawTarget, bool aPlaceOrigin,
nsresult PlaceAsMrow(DrawTarget* aDrawTarget, const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize);
/*

View File

@ -149,7 +149,8 @@ void nsMathMLTokenFrame::Reflow(nsPresContext* aPresContext,
// pass, it is not computed here because our children may be text frames
// that do not implement the GetBoundingMetrics() interface.
/* virtual */
nsresult nsMathMLTokenFrame::Place(DrawTarget* aDrawTarget, bool aPlaceOrigin,
nsresult nsMathMLTokenFrame::Place(DrawTarget* aDrawTarget,
const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) {
mBoundingMetrics = nsBoundingMetrics();
for (nsIFrame* childFrame : PrincipalChildList()) {
@ -171,7 +172,7 @@ nsresult nsMathMLTokenFrame::Place(DrawTarget* aDrawTarget, bool aPlaceOrigin,
aDesiredSize.Height() = aDesiredSize.BlockStartAscent() +
std::max(mBoundingMetrics.descent, descent);
if (aPlaceOrigin) {
if (!aFlags.contains(PlaceFlag::MeasureOnly)) {
nscoord dy, dx = 0;
for (nsIFrame* childFrame : PrincipalChildList()) {
ReflowOutput childSize(aDesiredSize.GetWritingMode());

View File

@ -53,8 +53,8 @@ class nsMathMLTokenFrame : public nsMathMLContainerFrame {
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
virtual nsresult Place(DrawTarget* aDrawTarget, bool aPlaceOrigin,
ReflowOutput& aDesiredSize) override;
nsresult Place(DrawTarget* aDrawTarget, const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) override;
protected:
explicit nsMathMLTokenFrame(ComputedStyle* aStyle,

View File

@ -299,26 +299,28 @@ void nsMathMLmencloseFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
/* virtual */
nsresult nsMathMLmencloseFrame::MeasureForWidth(DrawTarget* aDrawTarget,
ReflowOutput& aDesiredSize) {
return PlaceInternal(aDrawTarget, false, aDesiredSize, true);
PlaceFlags flags(PlaceFlag::IntrinsicSize, PlaceFlag::MeasureOnly);
return PlaceInternal(aDrawTarget, flags, aDesiredSize);
}
/* virtual */
nsresult nsMathMLmencloseFrame::Place(DrawTarget* aDrawTarget,
bool aPlaceOrigin,
const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) {
return PlaceInternal(aDrawTarget, aPlaceOrigin, aDesiredSize, false);
return PlaceInternal(aDrawTarget, aFlags, aDesiredSize);
}
/* virtual */
nsresult nsMathMLmencloseFrame::PlaceInternal(DrawTarget* aDrawTarget,
bool aPlaceOrigin,
ReflowOutput& aDesiredSize,
bool aWidthOnly) {
const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) {
///////////////
// Measure the size of our content using the base class to format like an
// inferred mrow.
// inferred mrow, without border/padding.
ReflowOutput baseSize(aDesiredSize.GetWritingMode());
nsresult rv = nsMathMLContainerFrame::Place(aDrawTarget, false, baseSize);
PlaceFlags flags =
aFlags + PlaceFlag::MeasureOnly + PlaceFlag::IgnoreBorderPadding;
nsresult rv = nsMathMLContainerFrame::Place(aDrawTarget, flags, baseSize);
if (NS_FAILED(rv)) {
DidReflowChildren(PrincipalChildList().FirstChild());
@ -461,7 +463,7 @@ nsresult nsMathMLmencloseFrame::PlaceInternal(DrawTarget* aDrawTarget,
///////////////
// longdiv notation:
if (IsToDraw(NOTATION_LONGDIV)) {
if (aWidthOnly) {
if (aFlags.contains(PlaceFlag::IntrinsicSize)) {
nscoord longdiv_width = mMathMLChar[mLongDivCharIndex].GetMaxWidth(
this, aDrawTarget, fontSizeInflation);
@ -503,7 +505,7 @@ nsresult nsMathMLmencloseFrame::PlaceInternal(DrawTarget* aDrawTarget,
? &dx_right
: &dx_left;
if (aWidthOnly) {
if (aFlags.contains(PlaceFlag::IntrinsicSize)) {
nscoord radical_width = mMathMLChar[mRadicalCharIndex].GetMaxWidth(
this, aDrawTarget, fontSizeInflation);
@ -627,7 +629,7 @@ nsresult nsMathMLmencloseFrame::PlaceInternal(DrawTarget* aDrawTarget,
mReference.x = 0;
mReference.y = aDesiredSize.BlockStartAscent();
if (aPlaceOrigin) {
if (!aFlags.contains(PlaceFlag::MeasureOnly)) {
//////////////////
// Set position and size of MathMLChars
if (IsToDraw(NOTATION_LONGDIV))

View File

@ -54,8 +54,8 @@ class nsMathMLmencloseFrame : public nsMathMLContainerFrame {
friend nsIFrame* NS_NewMathMLmencloseFrame(mozilla::PresShell* aPresShell,
ComputedStyle* aStyle);
virtual nsresult Place(DrawTarget* aDrawTarget, bool aPlaceOrigin,
ReflowOutput& aDesiredSize) override;
nsresult Place(DrawTarget* aDrawTarget, const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) override;
virtual nsresult MeasureForWidth(DrawTarget* aDrawTarget,
ReflowOutput& aDesiredSize) override;
@ -86,8 +86,8 @@ class nsMathMLmencloseFrame : public nsMathMLContainerFrame {
ClassID aID = kClassID);
virtual ~nsMathMLmencloseFrame();
nsresult PlaceInternal(DrawTarget* aDrawTarget, bool aPlaceOrigin,
ReflowOutput& aDesiredSize, bool aWidthOnly);
nsresult PlaceInternal(DrawTarget* aDrawTarget, const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize);
// functions to parse the "notation" attribute.
nsresult AddNotation(const nsAString& aNotation);

View File

@ -130,7 +130,8 @@ nsresult nsMathMLmfracFrame::AttributeChanged(int32_t aNameSpaceID,
/* virtual */
nsresult nsMathMLmfracFrame::MeasureForWidth(DrawTarget* aDrawTarget,
ReflowOutput& aDesiredSize) {
return PlaceInternal(aDrawTarget, false, aDesiredSize, true);
PlaceFlags flags(PlaceFlag::IntrinsicSize, PlaceFlag::MeasureOnly);
return PlaceInternal(aDrawTarget, flags, aDesiredSize);
}
nscoord nsMathMLmfracFrame::FixInterFrameSpacing(ReflowOutput& aDesiredSize) {
@ -142,15 +143,15 @@ nscoord nsMathMLmfracFrame::FixInterFrameSpacing(ReflowOutput& aDesiredSize) {
}
/* virtual */
nsresult nsMathMLmfracFrame::Place(DrawTarget* aDrawTarget, bool aPlaceOrigin,
nsresult nsMathMLmfracFrame::Place(DrawTarget* aDrawTarget,
const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) {
return PlaceInternal(aDrawTarget, aPlaceOrigin, aDesiredSize, false);
return PlaceInternal(aDrawTarget, aFlags, aDesiredSize);
}
nsresult nsMathMLmfracFrame::PlaceInternal(DrawTarget* aDrawTarget,
bool aPlaceOrigin,
ReflowOutput& aDesiredSize,
bool aWidthOnly) {
const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) {
////////////////////////////////////
// Get the children's desired sizes
nsBoundingMetrics bmNum, bmDen;
@ -161,10 +162,10 @@ nsresult nsMathMLmfracFrame::PlaceInternal(DrawTarget* aDrawTarget,
if (frameNum) frameDen = frameNum->GetNextSibling();
if (!frameNum || !frameDen || frameDen->GetNextSibling()) {
// report an error, encourage people to get their markups in order
if (aPlaceOrigin) {
if (!aFlags.contains(PlaceFlag::MeasureOnly)) {
ReportChildCountError();
}
return PlaceAsMrow(aDrawTarget, aPlaceOrigin, aDesiredSize);
return PlaceAsMrow(aDrawTarget, aFlags, aDesiredSize);
}
GetReflowAndBoundingMetricsFor(frameNum, sizeNum, bmNum);
GetReflowAndBoundingMetricsFor(frameDen, sizeDen, bmDen);
@ -356,7 +357,7 @@ nsresult nsMathMLmfracFrame::PlaceInternal(DrawTarget* aDrawTarget,
mReference.x = 0;
mReference.y = aDesiredSize.BlockStartAscent();
if (aPlaceOrigin) {
if (!aFlags.contains(PlaceFlag::MeasureOnly)) {
nscoord dy;
// place numerator
dy = 0;

View File

@ -66,8 +66,8 @@ class nsMathMLmfracFrame final : public nsMathMLContainerFrame {
virtual nsresult MeasureForWidth(DrawTarget* aDrawTarget,
ReflowOutput& aDesiredSize) override;
virtual nsresult Place(DrawTarget* aDrawTarget, bool aPlaceOrigin,
ReflowOutput& aDesiredSize) override;
nsresult Place(DrawTarget* aDrawTarget, const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) override;
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists) override;
@ -98,8 +98,8 @@ class nsMathMLmfracFrame final : public nsMathMLContainerFrame {
mLineThickness(0) {}
virtual ~nsMathMLmfracFrame();
nsresult PlaceInternal(DrawTarget* aDrawTarget, bool aPlaceOrigin,
ReflowOutput& aDesiredSize, bool aWidthOnly);
nsresult PlaceInternal(DrawTarget* aDrawTarget, const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize);
// Display a slash
void DisplaySlash(nsDisplayListBuilder* aBuilder, const nsRect& aRect,

View File

@ -93,24 +93,24 @@ nsMathMLmmultiscriptsFrame::TransmitAutomaticData() {
/* virtual */
nsresult nsMathMLmmultiscriptsFrame::Place(DrawTarget* aDrawTarget,
bool aPlaceOrigin,
const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) {
nscoord subScriptShift = 0;
nscoord supScriptShift = 0;
float fontSizeInflation = nsLayoutUtils::FontSizeInflationFor(this);
return PlaceMultiScript(PresContext(), aDrawTarget, aPlaceOrigin,
aDesiredSize, this, subScriptShift, supScriptShift,
return PlaceMultiScript(PresContext(), aDrawTarget, aFlags, aDesiredSize,
this, subScriptShift, supScriptShift,
fontSizeInflation);
}
// exported routine that both munderover and mmultiscripts share.
// munderover uses this when movablelimits is set.
nsresult nsMathMLmmultiscriptsFrame::PlaceMultiScript(
nsPresContext* aPresContext, DrawTarget* aDrawTarget, bool aPlaceOrigin,
ReflowOutput& aDesiredSize, nsMathMLContainerFrame* aFrame,
nscoord aUserSubScriptShift, nscoord aUserSupScriptShift,
float aFontSizeInflation) {
nsPresContext* aPresContext, DrawTarget* aDrawTarget,
const PlaceFlags& aFlags, ReflowOutput& aDesiredSize,
nsMathMLContainerFrame* aFrame, nscoord aUserSubScriptShift,
nscoord aUserSupScriptShift, float aFontSizeInflation) {
nsAtom* tag = aFrame->GetContent()->NodeInfo()->NameAtom();
// This function deals with both munderover etc. as well as msubsup etc.
@ -139,7 +139,7 @@ nsresult nsMathMLmmultiscriptsFrame::PlaceMultiScript(
aFrame->ReportErrorToConsole("NoBase");
else
aFrame->ReportChildCountError();
return aFrame->PlaceAsMrow(aDrawTarget, aPlaceOrigin, aDesiredSize);
return aFrame->PlaceAsMrow(aDrawTarget, aFlags, aDesiredSize);
}
// get x-height (an ex)
@ -290,24 +290,24 @@ nsresult nsMathMLmmultiscriptsFrame::PlaceMultiScript(
while (childFrame) {
if (childFrame->GetContent()->IsMathMLElement(nsGkAtoms::mprescripts_)) {
if (tag != nsGkAtoms::mmultiscripts_) {
if (aPlaceOrigin) {
if (!aFlags.contains(PlaceFlag::MeasureOnly)) {
aFrame->ReportInvalidChildError(nsGkAtoms::mprescripts_);
}
return aFrame->PlaceAsMrow(aDrawTarget, aPlaceOrigin, aDesiredSize);
return aFrame->PlaceAsMrow(aDrawTarget, aFlags, aDesiredSize);
}
if (prescriptsFrame) {
// duplicate <mprescripts/> found
// report an error, encourage people to get their markups in order
if (aPlaceOrigin) {
if (!aFlags.contains(PlaceFlag::MeasureOnly)) {
aFrame->ReportErrorToConsole("DuplicateMprescripts");
}
return aFrame->PlaceAsMrow(aDrawTarget, aPlaceOrigin, aDesiredSize);
return aFrame->PlaceAsMrow(aDrawTarget, aFlags, aDesiredSize);
}
if (!isSubScript) {
if (aPlaceOrigin) {
if (!aFlags.contains(PlaceFlag::MeasureOnly)) {
aFrame->ReportErrorToConsole("SubSupMismatch");
}
return aFrame->PlaceAsMrow(aDrawTarget, aPlaceOrigin, aDesiredSize);
return aFrame->PlaceAsMrow(aDrawTarget, aFlags, aDesiredSize);
}
prescriptsFrame = childFrame;
@ -481,7 +481,7 @@ nsresult nsMathMLmmultiscriptsFrame::PlaceMultiScript(
(count != 3 && tag == nsGkAtoms::msubsup_) || !baseFrame ||
(!isSubScript && tag == nsGkAtoms::mmultiscripts_)) {
// report an error, encourage people to get their markups in order
if (aPlaceOrigin) {
if (!aFlags.contains(PlaceFlag::MeasureOnly)) {
if ((count != 2 &&
(tag == nsGkAtoms::msup_ || tag == nsGkAtoms::msub_)) ||
(count != 3 && tag == nsGkAtoms::msubsup_)) {
@ -492,7 +492,7 @@ nsresult nsMathMLmmultiscriptsFrame::PlaceMultiScript(
aFrame->ReportErrorToConsole("SubSupMismatch");
}
}
return aFrame->PlaceAsMrow(aDrawTarget, aPlaceOrigin, aDesiredSize);
return aFrame->PlaceAsMrow(aDrawTarget, aFlags, aDesiredSize);
}
// we left out the width of prescripts, so ...
@ -543,7 +543,7 @@ nsresult nsMathMLmmultiscriptsFrame::PlaceMultiScript(
// The list of frames is in the order: {base} {postscripts} {prescripts}
// We go over the list in a circular manner, starting at <prescripts/>
if (aPlaceOrigin) {
if (!aFlags.contains(PlaceFlag::MeasureOnly)) {
nscoord dx = 0, dy = 0;
// With msub and msup there is only one element and

View File

@ -31,16 +31,14 @@ class nsMathMLmmultiscriptsFrame final : public nsMathMLContainerFrame {
NS_IMETHOD
TransmitAutomaticData() override;
virtual nsresult Place(DrawTarget* aDrawTarget, bool aPlaceOrigin,
ReflowOutput& aDesiredSize) override;
nsresult Place(DrawTarget* aDrawTarget, const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) override;
static nsresult PlaceMultiScript(nsPresContext* aPresContext,
DrawTarget* aDrawTarget, bool aPlaceOrigin,
ReflowOutput& aDesiredSize,
nsMathMLContainerFrame* aForFrame,
nscoord aUserSubScriptShift,
nscoord aUserSupScriptShift,
float aFontSizeInflation);
static nsresult PlaceMultiScript(
nsPresContext* aPresContext, DrawTarget* aDrawTarget,
const PlaceFlags& aFlags, ReflowOutput& aDesiredSize,
nsMathMLContainerFrame* aFrame, nscoord aUserSubScriptShift,
nscoord aUserSupScriptShift, float aFontSizeInflation);
uint8_t ScriptIncrement(nsIFrame* aFrame) override;

View File

@ -738,9 +738,10 @@ nsMathMLmoFrame::Stretch(DrawTarget* aDrawTarget,
}
}
// Place our children using the default method
// Place our children using the default method and no border/padding.
// This will allow our child text frame to get its DidReflow()
nsresult rv = Place(aDrawTarget, true, aDesiredStretchSize);
PlaceFlags flags = PlaceFlag::IgnoreBorderPadding;
nsresult rv = Place(aDrawTarget, flags, aDesiredStretchSize);
if (NS_FAILED(rv)) {
// Make sure the child frames get their DidReflow() calls.
DidReflowChildren(mFrames.FirstChild());
@ -930,10 +931,10 @@ void nsMathMLmoFrame::Reflow(nsPresContext* aPresContext,
nsMathMLTokenFrame::Reflow(aPresContext, aDesiredSize, aReflowInput, aStatus);
}
nsresult nsMathMLmoFrame::Place(DrawTarget* aDrawTarget, bool aPlaceOrigin,
nsresult nsMathMLmoFrame::Place(DrawTarget* aDrawTarget,
const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) {
nsresult rv =
nsMathMLTokenFrame::Place(aDrawTarget, aPlaceOrigin, aDesiredSize);
nsresult rv = nsMathMLTokenFrame::Place(aDrawTarget, aFlags, aDesiredSize);
if (NS_FAILED(rv)) {
return rv;
@ -950,7 +951,8 @@ nsresult nsMathMLmoFrame::Place(DrawTarget* aDrawTarget, bool aPlaceOrigin,
Stretch() method.
*/
if (!aPlaceOrigin && StyleFont()->mMathStyle == StyleMathStyle::Normal &&
if (aFlags.contains(PlaceFlag::MeasureOnly) &&
StyleFont()->mMathStyle == StyleMathStyle::Normal &&
NS_MATHML_OPERATOR_IS_LARGEOP(mFlags) && UseMathMLChar()) {
nsBoundingMetrics newMetrics;
rv = mMathMLChar.Stretch(

View File

@ -46,8 +46,8 @@ class nsMathMLmoFrame final : public nsMathMLTokenFrame {
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
virtual nsresult Place(DrawTarget* aDrawTarget, bool aPlaceOrigin,
ReflowOutput& aDesiredSize) override;
nsresult Place(DrawTarget* aDrawTarget, const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) override;
virtual void MarkIntrinsicISizesDirty() override;

View File

@ -313,9 +313,13 @@ void nsMathMLmpaddedFrame::Reflow(nsPresContext* aPresContext,
}
/* virtual */
nsresult nsMathMLmpaddedFrame::Place(DrawTarget* aDrawTarget, bool aPlaceOrigin,
nsresult nsMathMLmpaddedFrame::Place(DrawTarget* aDrawTarget,
const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) {
nsresult rv = nsMathMLContainerFrame::Place(aDrawTarget, false, aDesiredSize);
// First perform normal row layout without border/padding.
PlaceFlags flags =
aFlags + PlaceFlag::MeasureOnly + PlaceFlag::IgnoreBorderPadding;
nsresult rv = nsMathMLContainerFrame::Place(aDrawTarget, flags, aDesiredSize);
if (NS_FAILED(rv)) {
DidReflowChildren(PrincipalChildList().FirstChild());
return rv;
@ -424,7 +428,7 @@ nsresult nsMathMLmpaddedFrame::Place(DrawTarget* aDrawTarget, bool aPlaceOrigin,
mReference.x = 0;
mReference.y = aDesiredSize.BlockStartAscent();
if (aPlaceOrigin) {
if (!aFlags.contains(PlaceFlag::MeasureOnly)) {
// Finish reflowing child frames, positioning their origins.
PositionRowChildFrames(dx, aDesiredSize.BlockStartAscent() - voffset);
}
@ -436,5 +440,6 @@ nsresult nsMathMLmpaddedFrame::Place(DrawTarget* aDrawTarget, bool aPlaceOrigin,
nsresult nsMathMLmpaddedFrame::MeasureForWidth(DrawTarget* aDrawTarget,
ReflowOutput& aDesiredSize) {
ProcessAttributes();
return Place(aDrawTarget, false, aDesiredSize);
PlaceFlags flags(PlaceFlag::IntrinsicSize, PlaceFlag::MeasureOnly);
return Place(aDrawTarget, flags, aDesiredSize);
}

View File

@ -38,8 +38,8 @@ class nsMathMLmpaddedFrame final : public nsMathMLContainerFrame {
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
virtual nsresult Place(DrawTarget* aDrawTarget, bool aPlaceOrigin,
ReflowOutput& aDesiredSize) override;
nsresult Place(DrawTarget* aDrawTarget, const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) override;
bool IsMrowLike() override {
return mFrames.FirstChild() != mFrames.LastChild() || !mFrames.FirstChild();

View File

@ -95,11 +95,11 @@ void nsMathMLmspaceFrame::Reflow(nsPresContext* aPresContext,
ProcessAttributes(aPresContext);
auto borderPadding = aReflowInput.ComputedPhysicalBorderPadding();
const auto& borderPadding = GetUsedBorderAndPadding();
mBoundingMetrics = nsBoundingMetrics();
mBoundingMetrics.width = mWidth + borderPadding.LeftRight();
mBoundingMetrics.ascent = mHeight + borderPadding.Side(eSideTop);
mBoundingMetrics.descent = mDepth + borderPadding.Side(eSideBottom);
mBoundingMetrics.ascent = mHeight + borderPadding.top;
mBoundingMetrics.descent = mDepth + borderPadding.bottom;
mBoundingMetrics.leftBearing = 0;
mBoundingMetrics.rightBearing = mBoundingMetrics.width;
@ -116,7 +116,7 @@ nsresult nsMathMLmspaceFrame::MeasureForWidth(DrawTarget* aDrawTarget,
ProcessAttributes(PresContext());
mBoundingMetrics = nsBoundingMetrics();
auto offsets = IntrinsicISizeOffsets();
mBoundingMetrics.width = mWidth + offsets.padding + offsets.border;
mBoundingMetrics.width = mWidth + offsets.BorderPadding();
aDesiredSize.Width() = std::max(0, mBoundingMetrics.width);
aDesiredSize.mBoundingMetrics = mBoundingMetrics;
return NS_OK;

View File

@ -358,7 +358,7 @@ i.e.,:
/* virtual */
nsresult nsMathMLmunderoverFrame::Place(DrawTarget* aDrawTarget,
bool aPlaceOrigin,
const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) {
float fontSizeInflation = nsLayoutUtils::FontSizeInflationFor(this);
if (NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) &&
@ -366,17 +366,17 @@ nsresult nsMathMLmunderoverFrame::Place(DrawTarget* aDrawTarget,
// place like sub sup or subsup
if (mContent->IsMathMLElement(nsGkAtoms::munderover_)) {
return nsMathMLmmultiscriptsFrame::PlaceMultiScript(
PresContext(), aDrawTarget, aPlaceOrigin, aDesiredSize, this, 0, 0,
PresContext(), aDrawTarget, aFlags, aDesiredSize, this, 0, 0,
fontSizeInflation);
} else if (mContent->IsMathMLElement(nsGkAtoms::munder_)) {
return nsMathMLmmultiscriptsFrame::PlaceMultiScript(
PresContext(), aDrawTarget, aPlaceOrigin, aDesiredSize, this, 0, 0,
PresContext(), aDrawTarget, aFlags, aDesiredSize, this, 0, 0,
fontSizeInflation);
} else {
NS_ASSERTION(mContent->IsMathMLElement(nsGkAtoms::mover_),
"mContent->NodeInfo()->NameAtom() not recognized");
return nsMathMLmmultiscriptsFrame::PlaceMultiScript(
PresContext(), aDrawTarget, aPlaceOrigin, aDesiredSize, this, 0, 0,
PresContext(), aDrawTarget, aFlags, aDesiredSize, this, 0, 0,
fontSizeInflation);
}
}
@ -426,10 +426,10 @@ nsresult nsMathMLmunderoverFrame::Place(DrawTarget* aDrawTarget,
}
}
if (haveError) {
if (aPlaceOrigin) {
if (!aFlags.contains(PlaceFlag::MeasureOnly)) {
ReportChildCountError();
}
return PlaceAsMrow(aDrawTarget, aPlaceOrigin, aDesiredSize);
return PlaceAsMrow(aDrawTarget, aFlags, aDesiredSize);
}
GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase);
if (underFrame) {
@ -672,7 +672,7 @@ nsresult nsMathMLmunderoverFrame::Place(DrawTarget* aDrawTarget,
mReference.x = 0;
mReference.y = aDesiredSize.BlockStartAscent();
if (aPlaceOrigin) {
if (!aFlags.contains(PlaceFlag::MeasureOnly)) {
nscoord dy;
// place overscript
if (overFrame) {

View File

@ -27,7 +27,7 @@ class nsMathMLmunderoverFrame final : public nsMathMLContainerFrame,
friend nsIFrame* NS_NewMathMLmunderoverFrame(mozilla::PresShell* aPresShell,
ComputedStyle* aStyle);
nsresult Place(DrawTarget* aDrawTarget, bool aPlaceOrigin,
nsresult Place(DrawTarget* aDrawTarget, const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) override;
NS_IMETHOD InheritAutomaticData(nsIFrame* aParent) override;