Backed out 8 changesets (bug 1917763) for causing bustages at nsMathMLmspaceFrame.h. CLOSED TREE

Backed out changeset 7c7c002d7db2 (bug 1917763)
Backed out changeset 10eb2ccfa645 (bug 1917763)
Backed out changeset 9ba90d161930 (bug 1917763)
Backed out changeset ab7ce0058852 (bug 1917763)
Backed out changeset 19766c906c98 (bug 1917763)
Backed out changeset d1b87bb6e8d4 (bug 1917763)
Backed out changeset 043cf853e2cf (bug 1917763)
Backed out changeset a869862a66ec (bug 1917763)
This commit is contained in:
Butkovits Atila 2024-09-12 18:35:55 +03:00
Родитель e3172f689e
Коммит 3b13c53176
17 изменённых файлов: 540 добавлений и 393 удалений

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

@ -687,10 +687,9 @@ void nsMathMLContainerFrame::RemoveFrame(DestroyContext& aContext,
nsresult nsMathMLContainerFrame::AttributeChanged(int32_t aNameSpaceID,
nsAtom* aAttribute,
int32_t aModType) {
// Since they are numerous MathML attributes that affect layout, and
// XXX Since they are numerous MathML attributes that affect layout, and
// we can't check all of them here, play safe by requesting a reflow.
// TODO(bug 1918308): This should only do work for attributes that cause
// changes!
// XXXldb This should only do work for attributes that cause changes!
PresShell()->FrameNeedsReflow(
this, IntrinsicDirty::FrameAncestorsAndDescendants, NS_FRAME_IS_DIRTY);
@ -939,15 +938,23 @@ void nsMathMLContainerFrame::GetIntrinsicISizeMetrics(
}
// Measure
PlaceFlags flags(PlaceFlag::IntrinsicSize, PlaceFlag::MeasureOnly);
nsresult rv = Place(aRenderingContext->GetDrawTarget(), flags, aDesiredSize);
nsresult rv =
MeasureForWidth(aRenderingContext->GetDrawTarget(), aDesiredSize);
if (NS_FAILED(rv)) {
PlaceFlags flags(PlaceFlag::IntrinsicSize, PlaceFlag::MeasureOnly);
PlaceAsMrow(aRenderingContext->GetDrawTarget(), flags, aDesiredSize);
}
ClearSavedChildMetrics();
}
/* virtual */
nsresult nsMathMLContainerFrame::MeasureForWidth(DrawTarget* aDrawTarget,
ReflowOutput& aDesiredSize) {
PlaceFlags flags(PlaceFlag::IntrinsicSize, PlaceFlag::MeasureOnly);
return Place(aDrawTarget, flags, aDesiredSize);
}
// see spacing table in Chapter 18, TeXBook (p.170)
// Our table isn't quite identical to TeX because operators have
// built-in values for lspace & rspace in the Operator Dictionary.

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

@ -184,6 +184,17 @@ class nsMathMLContainerFrame : public nsContainerFrame, public nsMathMLFrame {
virtual nsresult Place(DrawTarget* aDrawTarget, const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize);
// MeasureForWidth:
//
// A method used by nsMathMLContainerFrame::GetIntrinsicISize to get the
// width that a particular Place method desires. For most frames, this will
// just call the object's Place method. However <msqrt> and <menclose> use
// nsMathMLContainerFrame::GetIntrinsicISize to measure the child frames as
// if in an <mrow>, and so their frames implement MeasureForWidth to use
// nsMathMLContainerFrame::Place.
virtual nsresult MeasureForWidth(DrawTarget* aDrawTarget,
ReflowOutput& aDesiredSize);
// helper to re-sync the automatic data in our children and notify our parent
// to reflow us when changes (e.g., append/insert/remove) happen in our child
// list

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

@ -244,7 +244,7 @@ void nsMathMLFrame::ParseNumericValue(const nsString& aString,
nsCSSUnit unit = cssValue.GetUnit();
if (unit == eCSSUnit_Percent) {
if (unit == eCSSUnit_Percent || unit == eCSSUnit_Number) {
// Relative units. A multiple of the default length value is used.
*aLengthValue = NSToCoordRound(
*aLengthValue * (unit == eCSSUnit_Percent ? cssValue.GetPercentValue()

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

@ -295,10 +295,24 @@ void nsMathMLmencloseFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
}
}
/* virtual */
nsresult nsMathMLmencloseFrame::MeasureForWidth(DrawTarget* aDrawTarget,
ReflowOutput& aDesiredSize) {
PlaceFlags flags(PlaceFlag::IntrinsicSize, PlaceFlag::MeasureOnly);
return PlaceInternal(aDrawTarget, flags, aDesiredSize);
}
/* virtual */
nsresult nsMathMLmencloseFrame::Place(DrawTarget* aDrawTarget,
const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) {
return PlaceInternal(aDrawTarget, aFlags, aDesiredSize);
}
/* virtual */
nsresult nsMathMLmencloseFrame::PlaceInternal(DrawTarget* aDrawTarget,
const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) {
///////////////
// Measure the size of our content using the base class to format like an
// inferred mrow, without border/padding.
@ -669,13 +683,8 @@ nscoord nsMathMLmencloseFrame::FixInterFrameSpacing(
nsresult nsMathMLmencloseFrame::AttributeChanged(int32_t aNameSpaceID,
nsAtom* aAttribute,
int32_t aModType) {
if (aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::notation_) {
if (aAttribute == nsGkAtoms::notation_) {
InitNotations();
// TODO(bug 1918308): This was copied from nsMathMLContainerFrame and seems
// necessary for some invalidation tests, but we can probably do less.
PresShell()->FrameNeedsReflow(
this, IntrinsicDirty::FrameAncestorsAndDescendants, NS_FRAME_IS_DIRTY);
return NS_OK;
}
return nsMathMLContainerFrame::AttributeChanged(aNameSpaceID, aAttribute,

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

@ -57,6 +57,9 @@ class nsMathMLmencloseFrame : public nsMathMLContainerFrame {
nsresult Place(DrawTarget* aDrawTarget, const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) override;
virtual nsresult MeasureForWidth(DrawTarget* aDrawTarget,
ReflowOutput& aDesiredSize) override;
virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
int32_t aModType) override;
@ -83,6 +86,9 @@ class nsMathMLmencloseFrame : public nsMathMLContainerFrame {
ClassID aID = kClassID);
virtual ~nsMathMLmencloseFrame();
nsresult PlaceInternal(DrawTarget* aDrawTarget, const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize);
// functions to parse the "notation" attribute.
nsresult AddNotation(const nsAString& aNotation);
void InitNotations();

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

@ -120,19 +120,20 @@ void nsMathMLmfracFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
nsresult nsMathMLmfracFrame::AttributeChanged(int32_t aNameSpaceID,
nsAtom* aAttribute,
int32_t aModType) {
if (aNameSpaceID == kNameSpaceID_None &&
nsGkAtoms::linethickness_ == aAttribute) {
if (nsGkAtoms::linethickness_ == aAttribute) {
InvalidateFrame();
// TODO(bug 1918308): This was copied from nsMathMLContainerFrame and seems
// necessary for some invalidation tests, but we can probably do less.
PresShell()->FrameNeedsReflow(
this, IntrinsicDirty::FrameAncestorsAndDescendants, NS_FRAME_IS_DIRTY);
return NS_OK;
}
return nsMathMLContainerFrame::AttributeChanged(aNameSpaceID, aAttribute,
aModType);
}
/* virtual */
nsresult nsMathMLmfracFrame::MeasureForWidth(DrawTarget* aDrawTarget,
ReflowOutput& aDesiredSize) {
PlaceFlags flags(PlaceFlag::IntrinsicSize, PlaceFlag::MeasureOnly);
return PlaceInternal(aDrawTarget, flags, aDesiredSize);
}
nscoord nsMathMLmfracFrame::FixInterFrameSpacing(ReflowOutput& aDesiredSize) {
nscoord gap = nsMathMLContainerFrame::FixInterFrameSpacing(aDesiredSize);
if (!gap) return 0;
@ -145,6 +146,12 @@ nscoord nsMathMLmfracFrame::FixInterFrameSpacing(ReflowOutput& aDesiredSize) {
nsresult nsMathMLmfracFrame::Place(DrawTarget* aDrawTarget,
const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) {
return PlaceInternal(aDrawTarget, aFlags, aDesiredSize);
}
nsresult nsMathMLmfracFrame::PlaceInternal(DrawTarget* aDrawTarget,
const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) {
////////////////////////////////////
// Get the children's desired sizes
nsBoundingMetrics bmNum, bmDen;

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

@ -63,6 +63,9 @@ class nsMathMLmfracFrame final : public nsMathMLContainerFrame {
virtual eMathMLFrameType GetMathMLFrameType() override;
virtual nsresult MeasureForWidth(DrawTarget* aDrawTarget,
ReflowOutput& aDesiredSize) override;
nsresult Place(DrawTarget* aDrawTarget, const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) override;
@ -95,6 +98,9 @@ class nsMathMLmfracFrame final : public nsMathMLContainerFrame {
mLineThickness(0) {}
virtual ~nsMathMLmfracFrame();
nsresult PlaceInternal(DrawTarget* aDrawTarget, const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize);
// Display a slash
void DisplaySlash(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
nscoord aThickness, const nsDisplayListSet& aLists);

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

@ -19,6 +19,18 @@ using namespace mozilla;
// <mpadded> -- adjust space around content - implementation
//
#define NS_MATHML_SIGN_INVALID -1 // if the attribute is not there
#define NS_MATHML_SIGN_UNSPECIFIED 0
#define NS_MATHML_SIGN_MINUS 1
#define NS_MATHML_SIGN_PLUS 2
#define NS_MATHML_PSEUDO_UNIT_UNSPECIFIED 0
#define NS_MATHML_PSEUDO_UNIT_ITSELF 1 // special
#define NS_MATHML_PSEUDO_UNIT_WIDTH 2
#define NS_MATHML_PSEUDO_UNIT_HEIGHT 3
#define NS_MATHML_PSEUDO_UNIT_DEPTH 4
#define NS_MATHML_PSEUDO_UNIT_NAMEDSPACE 5
nsIFrame* NS_NewMathMLmpaddedFrame(PresShell* aPresShell,
ComputedStyle* aStyle) {
return new (aPresShell)
@ -39,63 +51,77 @@ nsMathMLmpaddedFrame::InheritAutomaticData(nsIFrame* aParent) {
return NS_OK;
}
nsresult nsMathMLmpaddedFrame::AttributeChanged(int32_t aNameSpaceID,
nsAtom* aAttribute,
int32_t aModType) {
if (aNameSpaceID == kNameSpaceID_None) {
bool hasDirtyAttributes = false;
if (aAttribute == nsGkAtoms::width) {
mWidth.mState = Attribute::ParsingState::Dirty;
hasDirtyAttributes = true;
} else if (aAttribute == nsGkAtoms::height) {
mHeight.mState = Attribute::ParsingState::Dirty;
hasDirtyAttributes = true;
} else if (aAttribute == nsGkAtoms::depth_) {
mDepth.mState = Attribute::ParsingState::Dirty;
hasDirtyAttributes = true;
} else if (aAttribute == nsGkAtoms::lspace_) {
mLeadingSpace.mState = Attribute::ParsingState::Dirty;
hasDirtyAttributes = true;
} else if (aAttribute == nsGkAtoms::voffset_) {
mVerticalOffset.mState = Attribute::ParsingState::Dirty;
hasDirtyAttributes = true;
}
if (hasDirtyAttributes) {
InvalidateFrame();
// TODO(bug 1918308): This was copied from nsMathMLContainerFrame and
// seems necessary for some invalidation tests, but we can probably do
// less.
PresShell()->FrameNeedsReflow(
this, IntrinsicDirty::FrameAncestorsAndDescendants,
NS_FRAME_IS_DIRTY);
}
return NS_OK;
}
return nsMathMLContainerFrame::AttributeChanged(aNameSpaceID, aAttribute,
aModType);
}
void nsMathMLmpaddedFrame::ProcessAttributes() {
// clang-format off
/*
parse the attributes
width = [+|-] unsigned-number (% [pseudo-unit] | pseudo-unit | h-unit | namedspace)
height = [+|-] unsigned-number (% [pseudo-unit] | pseudo-unit | v-unit | namedspace)
depth = [+|-] unsigned-number (% [pseudo-unit] | pseudo-unit | v-unit | namedspace)
lspace = [+|-] unsigned-number (% [pseudo-unit] | pseudo-unit | h-unit | namedspace)
voffset= [+|-] unsigned-number (% [pseudo-unit] | pseudo-unit | v-unit | namedspace)
*/
// clang-format on
void nsMathMLmpaddedFrame::ParseAttribute(nsAtom* aAtom,
Attribute& aAttribute) {
if (aAttribute.mState != Attribute::ParsingState::Dirty) {
return;
}
nsAutoString value;
aAttribute.mState = Attribute::ParsingState::Invalid;
mContent->AsElement()->GetAttr(aAtom, value);
// width
mWidthSign = NS_MATHML_SIGN_INVALID;
mContent->AsElement()->GetAttr(nsGkAtoms::width, value);
if (!value.IsEmpty()) {
if (!ParseAttribute(value, aAttribute)) {
ReportParseError(aAtom->GetUTF16String(), value.get());
if (!ParseAttribute(value, mWidthSign, mWidth, mWidthPseudoUnit)) {
ReportParseError(nsGkAtoms::width->GetUTF16String(), value.get());
}
}
// height
mHeightSign = NS_MATHML_SIGN_INVALID;
mContent->AsElement()->GetAttr(nsGkAtoms::height, value);
if (!value.IsEmpty()) {
if (!ParseAttribute(value, mHeightSign, mHeight, mHeightPseudoUnit)) {
ReportParseError(nsGkAtoms::height->GetUTF16String(), value.get());
}
}
// depth
mDepthSign = NS_MATHML_SIGN_INVALID;
mContent->AsElement()->GetAttr(nsGkAtoms::depth_, value);
if (!value.IsEmpty()) {
if (!ParseAttribute(value, mDepthSign, mDepth, mDepthPseudoUnit)) {
ReportParseError(nsGkAtoms::depth_->GetUTF16String(), value.get());
}
}
// lspace
mLeadingSpaceSign = NS_MATHML_SIGN_INVALID;
mContent->AsElement()->GetAttr(nsGkAtoms::lspace_, value);
if (!value.IsEmpty()) {
if (!ParseAttribute(value, mLeadingSpaceSign, mLeadingSpace,
mLeadingSpacePseudoUnit)) {
ReportParseError(nsGkAtoms::lspace_->GetUTF16String(), value.get());
}
}
// voffset
mVerticalOffsetSign = NS_MATHML_SIGN_INVALID;
mContent->AsElement()->GetAttr(nsGkAtoms::voffset_, value);
if (!value.IsEmpty()) {
if (!ParseAttribute(value, mVerticalOffsetSign, mVerticalOffset,
mVerticalOffsetPseudoUnit)) {
ReportParseError(nsGkAtoms::voffset_->GetUTF16String(), value.get());
}
}
}
bool nsMathMLmpaddedFrame::ParseAttribute(nsString& aString,
Attribute& aAttribute) {
// See https://www.w3.org/TR/MathML3/chapter3.html#presm.mpaddedatt
aAttribute.Reset();
aAttribute.mState = Attribute::ParsingState::Invalid;
// parse an input string in the following format (see bug 148326 for testcases):
// [+|-] unsigned-number (% [pseudo-unit] | pseudo-unit | css-unit | namedspace)
bool nsMathMLmpaddedFrame::ParseAttribute(nsString& aString, int32_t& aSign,
nsCSSValue& aCSSValue,
int32_t& aPseudoUnit) {
aCSSValue.Reset();
aSign = NS_MATHML_SIGN_INVALID;
aPseudoUnit = NS_MATHML_PSEUDO_UNIT_UNSPECIFIED;
aString.CompressWhitespace(); // aString is not a const in this code
int32_t stringLength = aString.Length();
@ -109,13 +135,13 @@ bool nsMathMLmpaddedFrame::ParseAttribute(nsString& aString,
int32_t i = 0;
if (aString[0] == '+') {
aAttribute.mSign = Attribute::Sign::Plus;
aSign = NS_MATHML_SIGN_PLUS;
i++;
} else if (aString[0] == '-') {
aAttribute.mSign = Attribute::Sign::Minus;
aSign = NS_MATHML_SIGN_MINUS;
i++;
} else
aAttribute.mSign = Attribute::Sign::Unspecified;
aSign = NS_MATHML_SIGN_UNSPECIFIED;
// get the number
bool gotDot = false, gotPercent = false;
@ -123,6 +149,7 @@ bool nsMathMLmpaddedFrame::ParseAttribute(nsString& aString,
char16_t c = aString[i];
if (gotDot && c == '.') {
// error - two dots encountered
aSign = NS_MATHML_SIGN_INVALID;
return false;
}
@ -138,12 +165,14 @@ bool nsMathMLmpaddedFrame::ParseAttribute(nsString& aString,
// floatValue = 1, to cater for cases such as width="height", but that
// wouldn't be in line with the spec which requires an explicit number
if (number.IsEmpty()) {
aSign = NS_MATHML_SIGN_INVALID;
return false;
}
nsresult errorCode;
float floatValue = number.ToFloat(&errorCode);
if (NS_FAILED(errorCode)) {
aSign = NS_MATHML_SIGN_INVALID;
return false;
}
@ -159,37 +188,34 @@ bool nsMathMLmpaddedFrame::ParseAttribute(nsString& aString,
if (unit.IsEmpty()) {
if (gotPercent) {
// case ["+"|"-"] unsigned-number "%"
aAttribute.mValue.SetPercentValue(floatValue / 100.0f);
aAttribute.mPseudoUnit = Attribute::PseudoUnit::ItSelf;
aAttribute.mState = Attribute::ParsingState::Valid;
aCSSValue.SetPercentValue(floatValue / 100.0f);
aPseudoUnit = NS_MATHML_PSEUDO_UNIT_ITSELF;
return true;
} else {
// case ["+"|"-"] unsigned-number
// XXXfredw: should we allow non-zero unitless values? See bug 757703.
if (!floatValue) {
aAttribute.mValue.SetFloatValue(floatValue, eCSSUnit_Number);
aAttribute.mPseudoUnit = Attribute::PseudoUnit::ItSelf;
aAttribute.mState = Attribute::ParsingState::Valid;
aCSSValue.SetFloatValue(floatValue, eCSSUnit_Number);
aPseudoUnit = NS_MATHML_PSEUDO_UNIT_ITSELF;
return true;
}
}
} else if (unit.EqualsLiteral("width")) {
aAttribute.mPseudoUnit = Attribute::PseudoUnit::Width;
} else if (unit.EqualsLiteral("height")) {
aAttribute.mPseudoUnit = Attribute::PseudoUnit::Height;
} else if (unit.EqualsLiteral("depth")) {
aAttribute.mPseudoUnit = Attribute::PseudoUnit::Depth;
} else if (!gotPercent) { // percentage can only apply to a pseudo-unit
} else if (unit.EqualsLiteral("width"))
aPseudoUnit = NS_MATHML_PSEUDO_UNIT_WIDTH;
else if (unit.EqualsLiteral("height"))
aPseudoUnit = NS_MATHML_PSEUDO_UNIT_HEIGHT;
else if (unit.EqualsLiteral("depth"))
aPseudoUnit = NS_MATHML_PSEUDO_UNIT_DEPTH;
else if (!gotPercent) { // percentage can only apply to a pseudo-unit
// see if the unit is a named-space
if (dom::MathMLElement::ParseNamedSpaceValue(
unit, aAttribute.mValue, dom::MathMLElement::PARSE_ALLOW_NEGATIVE,
unit, aCSSValue, dom::MathMLElement::PARSE_ALLOW_NEGATIVE,
*mContent->OwnerDoc())) {
// re-scale properly, and we know that the unit of the named-space is 'em'
floatValue *= aAttribute.mValue.GetFloatValue();
aAttribute.mValue.SetFloatValue(floatValue, eCSSUnit_EM);
aAttribute.mPseudoUnit = Attribute::PseudoUnit::NamedSpace;
aAttribute.mState = Attribute::ParsingState::Valid;
floatValue *= aCSSValue.GetFloatValue();
aCSSValue.SetFloatValue(floatValue, eCSSUnit_EM);
aPseudoUnit = NS_MATHML_PSEUDO_UNIT_NAMEDSPACE;
return true;
}
@ -198,22 +224,19 @@ bool nsMathMLmpaddedFrame::ParseAttribute(nsString& aString,
// value here.
number.Append(unit); // leave the sign out if it was there
if (dom::MathMLElement::ParseNumericValue(
number, aAttribute.mValue,
dom::MathMLElement::PARSE_SUPPRESS_WARNINGS, nullptr)) {
aAttribute.mState = Attribute::ParsingState::Valid;
number, aCSSValue, dom::MathMLElement::PARSE_SUPPRESS_WARNINGS,
nullptr))
return true;
}
}
// if we enter here, we have a number that will act as a multiplier on a
// pseudo-unit
if (aAttribute.mPseudoUnit != Attribute::PseudoUnit::Unspecified) {
if (aPseudoUnit != NS_MATHML_PSEUDO_UNIT_UNSPECIFIED) {
if (gotPercent)
aAttribute.mValue.SetPercentValue(floatValue / 100.0f);
aCSSValue.SetPercentValue(floatValue / 100.0f);
else
aAttribute.mValue.SetFloatValue(floatValue, eCSSUnit_Number);
aCSSValue.SetFloatValue(floatValue, eCSSUnit_Number);
aAttribute.mState = Attribute::ParsingState::Valid;
return true;
}
@ -222,33 +245,30 @@ bool nsMathMLmpaddedFrame::ParseAttribute(nsString& aString,
NS_LossyConvertUTF16toASCII(aString).get());
#endif
// if we reach here, it means we encounter an unexpected input
aSign = NS_MATHML_SIGN_INVALID;
return false;
}
void nsMathMLmpaddedFrame::UpdateValue(const Attribute& aAttribute,
Attribute::PseudoUnit aSelfUnit,
void nsMathMLmpaddedFrame::UpdateValue(int32_t aSign, int32_t aPseudoUnit,
const nsCSSValue& aCSSValue,
const ReflowOutput& aDesiredSize,
nscoord& aValueToUpdate,
float aFontSizeInflation) const {
nsCSSUnit unit = aAttribute.mValue.GetUnit();
if (aAttribute.IsValid() && eCSSUnit_Null != unit) {
nsCSSUnit unit = aCSSValue.GetUnit();
if (NS_MATHML_SIGN_INVALID != aSign && eCSSUnit_Null != unit) {
nscoord scaler = 0, amount = 0;
if (eCSSUnit_Percent == unit || eCSSUnit_Number == unit) {
auto pseudoUnit = aAttribute.mPseudoUnit;
if (pseudoUnit == Attribute::PseudoUnit::ItSelf) {
pseudoUnit = aSelfUnit;
}
switch (pseudoUnit) {
case Attribute::PseudoUnit::Width:
switch (aPseudoUnit) {
case NS_MATHML_PSEUDO_UNIT_WIDTH:
scaler = aDesiredSize.Width();
break;
case Attribute::PseudoUnit::Height:
case NS_MATHML_PSEUDO_UNIT_HEIGHT:
scaler = aDesiredSize.BlockStartAscent();
break;
case Attribute::PseudoUnit::Depth:
case NS_MATHML_PSEUDO_UNIT_DEPTH:
scaler = aDesiredSize.Height() - aDesiredSize.BlockStartAscent();
break;
@ -261,29 +281,37 @@ void nsMathMLmpaddedFrame::UpdateValue(const Attribute& aAttribute,
}
if (eCSSUnit_Number == unit)
amount =
NSToCoordRound(float(scaler) * aAttribute.mValue.GetFloatValue());
amount = NSToCoordRound(float(scaler) * aCSSValue.GetFloatValue());
else if (eCSSUnit_Percent == unit)
amount =
NSToCoordRound(float(scaler) * aAttribute.mValue.GetPercentValue());
amount = NSToCoordRound(float(scaler) * aCSSValue.GetPercentValue());
else
amount = CalcLength(PresContext(), mComputedStyle, aAttribute.mValue,
amount = CalcLength(PresContext(), mComputedStyle, aCSSValue,
aFontSizeInflation);
switch (aAttribute.mSign) {
case Attribute::Sign::Plus:
aValueToUpdate += amount;
break;
case Attribute::Sign::Minus:
aValueToUpdate -= amount;
break;
case Attribute::Sign::Unspecified:
aValueToUpdate = amount;
break;
}
if (NS_MATHML_SIGN_PLUS == aSign)
aValueToUpdate += amount;
else if (NS_MATHML_SIGN_MINUS == aSign)
aValueToUpdate -= amount;
else
aValueToUpdate = amount;
}
}
void nsMathMLmpaddedFrame::Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) {
MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
ProcessAttributes();
///////////////
// Let the base class format our content like an inferred mrow
nsMathMLContainerFrame::Reflow(aPresContext, aDesiredSize, aReflowInput,
aStatus);
// NS_ASSERTION(aStatus.IsComplete(), "bad status");
}
/* virtual */
nsresult nsMathMLmpaddedFrame::Place(DrawTarget* aDrawTarget,
const PlaceFlags& aFlags,
@ -327,41 +355,47 @@ nsresult nsMathMLmpaddedFrame::Place(DrawTarget* aDrawTarget,
nscoord width = aDesiredSize.Width();
nscoord voffset = 0;
int32_t pseudoUnit;
nscoord initialWidth = width;
float fontSizeInflation = nsLayoutUtils::FontSizeInflationFor(this);
// update width
ParseAttribute(nsGkAtoms::width, mWidth);
UpdateValue(mWidth, Attribute::PseudoUnit::Width, aDesiredSize, width,
pseudoUnit = (mWidthPseudoUnit == NS_MATHML_PSEUDO_UNIT_ITSELF)
? NS_MATHML_PSEUDO_UNIT_WIDTH
: mWidthPseudoUnit;
UpdateValue(mWidthSign, pseudoUnit, mWidth, aDesiredSize, width,
fontSizeInflation);
width = std::max(0, width);
// update "height" (this is the ascent in the terminology of the REC)
ParseAttribute(nsGkAtoms::height, mHeight);
UpdateValue(mHeight, Attribute::PseudoUnit::Height, aDesiredSize, height,
pseudoUnit = (mHeightPseudoUnit == NS_MATHML_PSEUDO_UNIT_ITSELF)
? NS_MATHML_PSEUDO_UNIT_HEIGHT
: mHeightPseudoUnit;
UpdateValue(mHeightSign, pseudoUnit, mHeight, aDesiredSize, height,
fontSizeInflation);
height = std::max(0, height);
// update "depth" (this is the descent in the terminology of the REC)
ParseAttribute(nsGkAtoms::depth_, mDepth);
UpdateValue(mDepth, Attribute::PseudoUnit::Depth, aDesiredSize, depth,
pseudoUnit = (mDepthPseudoUnit == NS_MATHML_PSEUDO_UNIT_ITSELF)
? NS_MATHML_PSEUDO_UNIT_DEPTH
: mDepthPseudoUnit;
UpdateValue(mDepthSign, pseudoUnit, mDepth, aDesiredSize, depth,
fontSizeInflation);
depth = std::max(0, depth);
// update lspace
ParseAttribute(nsGkAtoms::lspace_, mLeadingSpace);
if (mLeadingSpace.mPseudoUnit != Attribute::PseudoUnit::ItSelf) {
UpdateValue(mLeadingSpace, Attribute::PseudoUnit::Unspecified, aDesiredSize,
if (mLeadingSpacePseudoUnit != NS_MATHML_PSEUDO_UNIT_ITSELF) {
pseudoUnit = mLeadingSpacePseudoUnit;
UpdateValue(mLeadingSpaceSign, pseudoUnit, mLeadingSpace, aDesiredSize,
lspace, fontSizeInflation);
}
// update voffset
ParseAttribute(nsGkAtoms::voffset_, mVerticalOffset);
if (mVerticalOffset.mPseudoUnit != Attribute::PseudoUnit::ItSelf) {
UpdateValue(mVerticalOffset, Attribute::PseudoUnit::Unspecified,
aDesiredSize, voffset, fontSizeInflation);
if (mVerticalOffsetPseudoUnit != NS_MATHML_PSEUDO_UNIT_ITSELF) {
pseudoUnit = mVerticalOffsetPseudoUnit;
UpdateValue(mVerticalOffsetSign, pseudoUnit, mVerticalOffset, aDesiredSize,
voffset, fontSizeInflation);
}
// do the padding now that we have everything
// The idea here is to maintain the invariant that <mpadded>...</mpadded>
// (i.e., with no attributes) looks the same as <mrow>...</mrow>. But when
@ -369,13 +403,13 @@ nsresult nsMathMLmpaddedFrame::Place(DrawTarget* aDrawTarget,
// desired visual effects.
const bool isRTL = StyleVisibility()->mDirection == StyleDirection::Rtl;
if (isRTL ? mWidth.IsValid() : mLeadingSpace.IsValid()) {
if ((isRTL ? mWidthSign : mLeadingSpaceSign) != NS_MATHML_SIGN_INVALID) {
// there was padding on the left. dismiss the left italic correction now
// (so that our parent won't correct us)
mBoundingMetrics.leftBearing = 0;
}
if (isRTL ? mLeadingSpace.IsValid() : mWidth.IsValid()) {
if ((isRTL ? mLeadingSpaceSign : mWidthSign) != NS_MATHML_SIGN_INVALID) {
// there was padding on the right. dismiss the right italic correction now
// (so that our parent won't correct us)
mBoundingMetrics.width = width;
@ -407,3 +441,11 @@ nsresult nsMathMLmpaddedFrame::Place(DrawTarget* aDrawTarget,
return NS_OK;
}
/* virtual */
nsresult nsMathMLmpaddedFrame::MeasureForWidth(DrawTarget* aDrawTarget,
ReflowOutput& aDesiredSize) {
ProcessAttributes();
PlaceFlags flags(PlaceFlag::IntrinsicSize, PlaceFlag::MeasureOnly);
return Place(aDrawTarget, flags, aDesiredSize);
}

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

@ -34,6 +34,10 @@ class nsMathMLmpaddedFrame final : public nsMathMLContainerFrame {
return TransmitAutomaticDataForMrowLikeElement();
}
virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
nsresult Place(DrawTarget* aDrawTarget, const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) override;
@ -44,55 +48,50 @@ class nsMathMLmpaddedFrame final : public nsMathMLContainerFrame {
protected:
explicit nsMathMLmpaddedFrame(ComputedStyle* aStyle,
nsPresContext* aPresContext)
: nsMathMLContainerFrame(aStyle, aPresContext, kClassID) {}
: nsMathMLContainerFrame(aStyle, aPresContext, kClassID),
mWidthSign(0),
mHeightSign(0),
mDepthSign(0),
mLeadingSpaceSign(0),
mVerticalOffsetSign(0),
mWidthPseudoUnit(0),
mHeightPseudoUnit(0),
mDepthPseudoUnit(0),
mLeadingSpacePseudoUnit(0),
mVerticalOffsetPseudoUnit(0) {}
virtual ~nsMathMLmpaddedFrame();
virtual nsresult MeasureForWidth(DrawTarget* aDrawTarget,
ReflowOutput& aDesiredSize) override;
private:
struct Attribute {
enum class Sign : uint8_t {
Unspecified,
Minus,
Plus,
};
enum class PseudoUnit : uint8_t {
Unspecified,
ItSelf,
Width,
Height,
Depth,
NamedSpace,
};
nsCSSValue mValue;
Sign mSign = Sign::Unspecified;
PseudoUnit mPseudoUnit = PseudoUnit::Unspecified;
enum class ParsingState : uint8_t {
Valid,
Invalid,
Dirty,
};
ParsingState mState = ParsingState::Dirty;
void Reset() {
mValue.Reset();
mSign = Sign::Unspecified;
mPseudoUnit = PseudoUnit::Unspecified;
mState = ParsingState::Dirty;
}
bool IsValid() const { return mState == ParsingState::Valid; }
};
nsCSSValue mWidth;
nsCSSValue mHeight;
nsCSSValue mDepth;
nsCSSValue mLeadingSpace;
nsCSSValue mVerticalOffset;
Attribute mWidth;
Attribute mHeight;
Attribute mDepth;
Attribute mLeadingSpace;
Attribute mVerticalOffset;
int32_t mWidthSign;
int32_t mHeightSign;
int32_t mDepthSign;
int32_t mLeadingSpaceSign;
int32_t mVerticalOffsetSign;
nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
int32_t aModType) final;
void ParseAttribute(nsAtom* aAtom, Attribute& aAttribute);
bool ParseAttribute(nsString& aString, Attribute& aAttribute);
int32_t mWidthPseudoUnit;
int32_t mHeightPseudoUnit;
int32_t mDepthPseudoUnit;
int32_t mLeadingSpacePseudoUnit;
int32_t mVerticalOffsetPseudoUnit;
void UpdateValue(const Attribute& aAttribute, Attribute::PseudoUnit aSelfUnit,
// helpers to process the attributes
void ProcessAttributes();
bool ParseAttribute(nsString& aString, int32_t& aSign, nsCSSValue& aCSSValue,
int32_t& aPseudoUnit);
void UpdateValue(int32_t aSign, int32_t aPseudoUnit,
const nsCSSValue& aCSSValue,
const ReflowOutput& aDesiredSize, nscoord& aValueToUpdate,
float aFontSizeInflation) const;
};

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

@ -129,26 +129,64 @@ void nsMathMLmrootFrame::GetRadicalXOffsets(nscoord aIndexWidth,
if (aSqrOffset) *aSqrOffset = dxSqr;
}
nsresult nsMathMLmrootFrame::Place(DrawTarget* aDrawTarget,
const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) {
void nsMathMLmrootFrame::Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) {
if (ShouldUseRowFallback()) {
// report an error, encourage people to get their markups in order
if (!aFlags.contains(PlaceFlag::MeasureOnly)) {
ReportChildCountError();
}
return PlaceAsMrow(aDrawTarget, aFlags, aDesiredSize);
ReportChildCountError();
nsMathMLContainerFrame::Reflow(aPresContext, aDesiredSize, aReflowInput,
aStatus);
return;
}
MarkInReflow();
MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
nsReflowStatus childStatus;
aDesiredSize.ClearSize();
aDesiredSize.SetBlockStartAscent(0);
nsBoundingMetrics bmSqr, bmBase, bmIndex;
nsIFrame* baseFrame = mFrames.FirstChild();
nsIFrame* indexFrame = baseFrame->GetNextSibling();
nsMargin baseMargin = GetMarginForPlace(aFlags, baseFrame),
indexMargin = GetMarginForPlace(aFlags, indexFrame);
ReflowOutput baseSize(aDesiredSize.GetWritingMode());
ReflowOutput indexSize(aDesiredSize.GetWritingMode());
GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase);
GetReflowAndBoundingMetricsFor(indexFrame, indexSize, bmIndex);
nsMargin baseMargin, indexMargin;
DrawTarget* drawTarget = aReflowInput.mRenderingContext->GetDrawTarget();
//////////////////
// Reflow Children
int32_t count = 0;
nsIFrame* baseFrame = nullptr;
nsIFrame* indexFrame = nullptr;
ReflowOutput baseSize(aReflowInput);
ReflowOutput indexSize(aReflowInput);
nsIFrame* childFrame = mFrames.FirstChild();
while (childFrame) {
// ask our children to compute their bounding metrics
ReflowOutput childDesiredSize(aReflowInput);
WritingMode wm = childFrame->GetWritingMode();
LogicalSize availSize = aReflowInput.ComputedSize(wm);
availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
ReflowInput childReflowInput(aPresContext, aReflowInput, childFrame,
availSize);
ReflowChild(childFrame, aPresContext, childDesiredSize, childReflowInput,
childStatus);
// NS_ASSERTION(childStatus.IsComplete(), "bad status");
if (0 == count) {
// base
baseFrame = childFrame;
baseSize = childDesiredSize;
bmBase = childDesiredSize.mBoundingMetrics;
baseMargin = baseFrame->GetUsedMargin();
} else if (1 == count) {
// index
indexFrame = childFrame;
indexSize = childDesiredSize;
bmIndex = childDesiredSize.mBoundingMetrics;
indexMargin = indexFrame->GetUsedMargin();
}
count++;
childFrame = childFrame->GetNextSibling();
}
////////////
// Prepare the radical symbol and the overline bar
@ -165,7 +203,7 @@ nsresult nsMathMLmrootFrame::Place(DrawTarget* aDrawTarget,
// p.131)
char16_t one = '1';
nsBoundingMetrics bmOne =
nsLayoutUtils::AppUnitBoundsOfString(&one, 1, *fm, aDrawTarget);
nsLayoutUtils::AppUnitBoundsOfString(&one, 1, *fm, drawTarget);
if (bmOne.ascent > bmBase.ascent + baseMargin.top) {
psi += bmOne.ascent - bmBase.ascent - baseMargin.top;
}
@ -190,22 +228,13 @@ nsresult nsMathMLmrootFrame::Place(DrawTarget* aDrawTarget,
// height(radical) should be >= height(base) + psi + ruleThickness
nsBoundingMetrics radicalSize;
if (aFlags.contains(PlaceFlag::IntrinsicSize)) {
nscoord radical_width =
mSqrChar.GetMaxWidth(this, aDrawTarget, fontSizeInflation);
bmSqr.leftBearing = 0;
bmSqr.rightBearing = radical_width;
bmSqr.width = radical_width;
bmSqr.ascent = bmSqr.descent = 0;
} else {
mSqrChar.Stretch(this, aDrawTarget, fontSizeInflation,
NS_STRETCH_DIRECTION_VERTICAL, contSize, radicalSize,
NS_STRETCH_LARGER,
StyleVisibility()->mDirection == StyleDirection::Rtl);
// radicalSize have changed at this point, and should match with
// the bounding metrics of the char
mSqrChar.GetBoundingMetrics(bmSqr);
}
mSqrChar.Stretch(this, drawTarget, fontSizeInflation,
NS_STRETCH_DIRECTION_VERTICAL, contSize, radicalSize,
NS_STRETCH_LARGER,
StyleVisibility()->mDirection == StyleDirection::Rtl);
// radicalSize have changed at this point, and should match with
// the bounding metrics of the char
mSqrChar.GetBoundingMetrics(bmSqr);
// Update the desired size for the container (like msqrt, index is not yet
// included) the baseline will be that of the base.
@ -276,46 +305,92 @@ nsresult nsMathMLmrootFrame::Place(DrawTarget* aDrawTarget,
aDesiredSize.mBoundingMetrics = mBoundingMetrics;
// Add padding+border around the final layout.
auto borderPadding = GetBorderPaddingForPlace(aFlags);
auto borderPadding = GetUsedBorderAndPadding();
InflateReflowAndBoundingMetrics(borderPadding, aDesiredSize,
mBoundingMetrics);
if (!aFlags.contains(PlaceFlag::MeasureOnly)) {
nsPresContext* presContext = PresContext();
// place the index
const bool isRTL = StyleVisibility()->mDirection == StyleDirection::Rtl;
nscoord borderPaddingInlineStart =
isRTL ? borderPadding.right : borderPadding.left;
nscoord dx = borderPaddingInlineStart + dxIndex +
indexMargin.Side(isRTL ? eSideRight : eSideLeft);
nscoord dy =
aDesiredSize.BlockStartAscent() -
(indexRaisedAscent + indexSize.BlockStartAscent() - bmIndex.ascent);
FinishReflowChild(indexFrame, presContext, indexSize, nullptr,
MirrorIfRTL(aDesiredSize.Width(), indexSize.Width(), dx),
dy + indexMargin.top, ReflowChildFlags::Default);
GatherAndStoreOverflow(&aDesiredSize);
// place the radical symbol and the radical bar
dx = borderPaddingInlineStart + dxSqr;
dy = borderPadding.top + indexClearance +
leading; // leave a leading at the top
mSqrChar.SetRect(nsRect(MirrorIfRTL(aDesiredSize.Width(), bmSqr.width, dx),
dy, bmSqr.width, bmSqr.ascent + bmSqr.descent));
dx += bmSqr.width;
mBarRect.SetRect(MirrorIfRTL(aDesiredSize.Width(),
bmBase.width + baseMargin.LeftRight(), dx),
dy, bmBase.width + baseMargin.LeftRight(), ruleThickness);
// place the index
const bool isRTL = StyleVisibility()->mDirection == StyleDirection::Rtl;
nscoord borderPaddingInlineStart =
isRTL ? borderPadding.right : borderPadding.left;
nscoord dx = borderPaddingInlineStart + dxIndex +
indexMargin.Side(isRTL ? eSideRight : eSideLeft);
nscoord dy =
aDesiredSize.BlockStartAscent() -
(indexRaisedAscent + indexSize.BlockStartAscent() - bmIndex.ascent);
FinishReflowChild(indexFrame, aPresContext, indexSize, nullptr,
MirrorIfRTL(aDesiredSize.Width(), indexSize.Width(), dx),
dy + indexMargin.top, ReflowChildFlags::Default);
// place the base
dx += isRTL ? baseMargin.right : baseMargin.left;
dy = aDesiredSize.BlockStartAscent() - baseSize.BlockStartAscent();
FinishReflowChild(baseFrame, presContext, baseSize, nullptr,
MirrorIfRTL(aDesiredSize.Width(), baseSize.Width(), dx),
dy, ReflowChildFlags::Default);
}
// place the radical symbol and the radical bar
dx = borderPaddingInlineStart + dxSqr;
dy = borderPadding.top + indexClearance +
leading; // leave a leading at the top
mSqrChar.SetRect(nsRect(MirrorIfRTL(aDesiredSize.Width(), bmSqr.width, dx),
dy, bmSqr.width, bmSqr.ascent + bmSqr.descent));
dx += bmSqr.width;
mBarRect.SetRect(MirrorIfRTL(aDesiredSize.Width(),
bmBase.width + baseMargin.LeftRight(), dx),
dy, bmBase.width + baseMargin.LeftRight(), ruleThickness);
// place the base
dx += isRTL ? baseMargin.right : baseMargin.left;
dy = aDesiredSize.BlockStartAscent() - baseSize.BlockStartAscent();
FinishReflowChild(baseFrame, aPresContext, baseSize, nullptr,
MirrorIfRTL(aDesiredSize.Width(), baseSize.Width(), dx), dy,
ReflowChildFlags::Default);
mReference.x = 0;
mReference.y = aDesiredSize.BlockStartAscent();
}
/* virtual */
nsresult nsMathMLmrootFrame::MeasureForWidth(DrawTarget* aDrawTarget,
ReflowOutput& aDesiredSize) {
const PlaceFlags flags(PlaceFlag::IntrinsicSize, PlaceFlag::MeasureOnly);
if (ShouldUseRowFallback()) {
return PlaceAsMrow(aDrawTarget, flags, aDesiredSize);
}
// ShouldUseRowFallback() returned false so there are exactly two children.
nsIFrame* baseFrame = mFrames.FirstChild();
MOZ_ASSERT(baseFrame);
nsIFrame* indexFrame = baseFrame->GetNextSibling();
MOZ_ASSERT(indexFrame);
MOZ_ASSERT(!indexFrame->GetNextSibling());
nsBoundingMetrics bmBase, bmIndex;
ReflowOutput baseSize(aDesiredSize.GetWritingMode());
ReflowOutput indexSize(aDesiredSize.GetWritingMode());
float fontSizeInflation = nsLayoutUtils::FontSizeInflationFor(this);
GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase);
GetReflowAndBoundingMetricsFor(indexFrame, indexSize, bmIndex);
nscoord baseMargin = baseFrame->IntrinsicISizeOffsets().margin,
indexMargin = indexFrame->IntrinsicISizeOffsets().margin;
nscoord sqrWidth = mSqrChar.GetMaxWidth(this, aDrawTarget, fontSizeInflation);
nscoord dxIndex, dxSqr;
RefPtr<nsFontMetrics> fm =
nsLayoutUtils::GetFontMetricsForFrame(this, fontSizeInflation);
GetRadicalXOffsets(bmIndex.width + indexMargin, sqrWidth, fm, &dxIndex,
&dxSqr);
mBoundingMetrics.width = dxSqr + sqrWidth + bmBase.width + baseMargin;
mBoundingMetrics.leftBearing =
std::min(dxIndex + bmIndex.leftBearing + indexMargin, dxSqr);
mBoundingMetrics.rightBearing =
dxSqr + sqrWidth +
std::max(bmBase.width + baseMargin, bmBase.rightBearing + baseMargin);
aDesiredSize.Width() = mBoundingMetrics.width;
aDesiredSize.mBoundingMetrics = mBoundingMetrics;
// Add border+padding.
nsMargin borderPadding = GetBorderPaddingForPlace(flags);
InflateReflowAndBoundingMetrics(borderPadding, aDesiredSize,
mBoundingMetrics);
return NS_OK;
}

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

@ -34,10 +34,17 @@ class nsMathMLmrootFrame final : public nsMathMLContainerFrame {
NS_IMETHOD
TransmitAutomaticData() override;
virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
void GetRadicalXOffsets(nscoord aIndexWidth, nscoord aSqrWidth,
nsFontMetrics* aFontMetrics, nscoord* aIndexOffset,
nscoord* aSqrOffset);
nsresult MeasureForWidth(DrawTarget* aDrawTarget,
ReflowOutput& aDesiredSize) final;
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists) override;
@ -55,8 +62,6 @@ class nsMathMLmrootFrame final : public nsMathMLContainerFrame {
private:
bool ShouldUseRowFallback();
nsresult Place(DrawTarget* aDrawTarget, const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) final;
};
#endif /* nsMathMLmrootFrame_h___ */

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

@ -28,86 +28,78 @@ NS_IMPL_FRAMEARENA_HELPERS(nsMathMLmspaceFrame)
nsMathMLmspaceFrame::~nsMathMLmspaceFrame() = default;
nsresult nsMathMLmspaceFrame::AttributeChanged(int32_t aNameSpaceID,
nsAtom* aAttribute,
int32_t aModType) {
if (aNameSpaceID == kNameSpaceID_None) {
bool hasDirtyAttributes = false;
if (aAttribute == nsGkAtoms::width) {
mWidth.mState = Attribute::ParsingState::Dirty;
hasDirtyAttributes = true;
} else if (aAttribute == nsGkAtoms::height) {
mHeight.mState = Attribute::ParsingState::Dirty;
hasDirtyAttributes = true;
} else if (aAttribute == nsGkAtoms::depth_) {
mDepth.mState = Attribute::ParsingState::Dirty;
hasDirtyAttributes = true;
}
if (hasDirtyAttributes) {
InvalidateFrame();
// TODO(bug 1918308): This was copied from nsMathMLContainerFrame and
// seems necessary for some invalidation tests, but we can probably do
// less.
PresShell()->FrameNeedsReflow(
this, IntrinsicDirty::FrameAncestorsAndDescendants,
NS_FRAME_IS_DIRTY);
}
return NS_OK;
}
return nsMathMLContainerFrame::AttributeChanged(aNameSpaceID, aAttribute,
aModType);
}
nscoord nsMathMLmspaceFrame::CalculateAttributeValue(nsAtom* aAtom,
Attribute& aAttribute,
uint32_t aFlags,
float aFontSizeInflation) {
if (aAttribute.mState == Attribute::ParsingState::Dirty) {
nsAutoString value;
aAttribute.mState = Attribute::ParsingState::Invalid;
mContent->AsElement()->GetAttr(aAtom, value);
if (!value.IsEmpty()) {
if (dom::MathMLElement::ParseNumericValue(
value, aAttribute.mValue, aFlags, PresContext()->Document())) {
aAttribute.mState = Attribute::ParsingState::Valid;
} else {
ReportParseError(aAtom->GetUTF16String(), value.get());
}
}
}
// Invalid is interpreted as the default which is 0.
// Percentages are interpreted as a multiple of the default value.
if (aAttribute.mState == Attribute::ParsingState::Invalid ||
aAttribute.mValue.GetUnit() == eCSSUnit_Percent) {
return 0;
}
return CalcLength(PresContext(), mComputedStyle, aAttribute.mValue,
aFontSizeInflation);
}
nsresult nsMathMLmspaceFrame::Place(DrawTarget* aDrawTarget,
const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) {
void nsMathMLmspaceFrame::ProcessAttributes(nsPresContext* aPresContext) {
nsAutoString value;
float fontSizeInflation = nsLayoutUtils::FontSizeInflationFor(this);
// width
//
// "Specifies the desired width of the space."
//
// values: length
// default: 0em
//
// The default value is "0em", so unitless values can be ignored.
// <mspace/> is listed among MathML elements allowing negative spacing and
// the MathML test suite contains "Presentation/TokenElements/mspace/mspace2"
// as an example. Hence we allow negative values.
nscoord width = CalculateAttributeValue(
nsGkAtoms::width, mWidth, dom::MathMLElement::PARSE_ALLOW_NEGATIVE,
fontSizeInflation);
//
mWidth = 0;
mContent->AsElement()->GetAttr(nsGkAtoms::width, value);
if (!value.IsEmpty()) {
ParseNumericValue(value, &mWidth, dom::MathMLElement::PARSE_ALLOW_NEGATIVE,
aPresContext, mComputedStyle, fontSizeInflation);
}
// We do not allow negative values for height and depth attributes. See bug
// 716349.
nscoord height =
CalculateAttributeValue(nsGkAtoms::height, mHeight, 0, fontSizeInflation);
nscoord depth =
CalculateAttributeValue(nsGkAtoms::depth_, mDepth, 0, fontSizeInflation);
// height
//
// "Specifies the desired height (above the baseline) of the space."
//
// values: length
// default: 0ex
//
// The default value is "0ex", so unitless values can be ignored.
// We do not allow negative values. See bug 716349.
//
mHeight = 0;
mContent->AsElement()->GetAttr(nsGkAtoms::height, value);
if (!value.IsEmpty()) {
ParseNumericValue(value, &mHeight, 0, aPresContext, mComputedStyle,
fontSizeInflation);
}
// depth
//
// "Specifies the desired depth (below the baseline) of the space."
//
// values: length
// default: 0ex
//
// The default value is "0ex", so unitless values can be ignored.
// We do not allow negative values. See bug 716349.
//
mDepth = 0;
mContent->AsElement()->GetAttr(nsGkAtoms::depth_, value);
if (!value.IsEmpty()) {
ParseNumericValue(value, &mDepth, 0, aPresContext, mComputedStyle,
fontSizeInflation);
}
}
void nsMathMLmspaceFrame::Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) {
MarkInReflow();
MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
ProcessAttributes(aPresContext);
const auto& borderPadding = GetUsedBorderAndPadding();
mBoundingMetrics = nsBoundingMetrics();
mBoundingMetrics.width = width;
mBoundingMetrics.ascent = height;
mBoundingMetrics.descent = depth;
mBoundingMetrics.width = mWidth + borderPadding.LeftRight();
mBoundingMetrics.ascent = mHeight + borderPadding.top;
mBoundingMetrics.descent = mDepth + borderPadding.bottom;
mBoundingMetrics.leftBearing = 0;
mBoundingMetrics.rightBearing = mBoundingMetrics.width;
@ -116,10 +108,16 @@ nsresult nsMathMLmspaceFrame::Place(DrawTarget* aDrawTarget,
aDesiredSize.Height() = mBoundingMetrics.ascent + mBoundingMetrics.descent;
// Also return our bounding metrics
aDesiredSize.mBoundingMetrics = mBoundingMetrics;
}
// Add padding+border.
auto borderPadding = GetBorderPaddingForPlace(aFlags);
InflateReflowAndBoundingMetrics(borderPadding, aDesiredSize,
mBoundingMetrics);
/* virtual */
nsresult nsMathMLmspaceFrame::MeasureForWidth(DrawTarget* aDrawTarget,
ReflowOutput& aDesiredSize) {
ProcessAttributes(PresContext());
mBoundingMetrics = nsBoundingMetrics();
auto offsets = IntrinsicISizeOffsets();
mBoundingMetrics.width = mWidth + offsets.BorderPadding();
aDesiredSize.Width() = std::max(0, mBoundingMetrics.width);
aDesiredSize.mBoundingMetrics = mBoundingMetrics;
return NS_OK;
}

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

@ -33,32 +33,29 @@ class nsMathMLmspaceFrame final : public nsMathMLContainerFrame {
return NS_OK;
}
virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
protected:
explicit nsMathMLmspaceFrame(ComputedStyle* aStyle,
nsPresContext* aPresContext)
: nsMathMLContainerFrame(aStyle, aPresContext, kClassID) {}
: nsMathMLContainerFrame(aStyle, aPresContext, kClassID),
mWidth(0),
mHeight(0),
mDepth(0) {}
virtual ~nsMathMLmspaceFrame();
private:
struct Attribute {
nsCSSValue mValue;
enum class ParsingState : uint8_t {
Valid,
Invalid,
Dirty,
};
ParsingState mState = ParsingState::Dirty;
};
Attribute mWidth;
Attribute mHeight;
Attribute mDepth;
virtual nsresult MeasureForWidth(DrawTarget* aDrawTarget,
ReflowOutput& aDesiredSize) override;
nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
int32_t aModType) final;
nscoord CalculateAttributeValue(nsAtom* aAtom, Attribute& aAttribute,
uint32_t aFlags, float aFontSizeInflation);
nsresult Place(DrawTarget* aDrawTarget, const PlaceFlags& aFlags,
ReflowOutput& aDesiredSize) final;
private:
nscoord mWidth;
nscoord mHeight;
nscoord mDepth;
// helper method to initialize our member data
void ProcessAttributes(nsPresContext* aPresContext);
};
#endif /* nsMathMLmspaceFrame_h___ */

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

@ -47,9 +47,6 @@ nsMathMLmsqrtFrame::InheritAutomaticData(nsIFrame* aParent) {
nsresult nsMathMLmsqrtFrame::AttributeChanged(int32_t aNameSpaceID,
nsAtom* aAttribute,
int32_t aModType) {
// Skip nsMathMLmencloseFrame::AttributeChanged, since msqrt does not accept
// the notation attribute.
// TODO(bug 1918310): msqrt should share its logic with mroot instead.
return nsMathMLContainerFrame::AttributeChanged(aNameSpaceID, aAttribute,
aModType);
}

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

@ -37,7 +37,9 @@ These attributes are inherited by every element from its rendering environment,
but can be set explicitly only on <mstyle>. (See Section 3.3.4.)
*/
// TODO(bug 1918310): msqrt should share its logic with mroot instead.
// XXXfredw: This class should share its layout logic with nsMathMLmrootFrame
// when the menclose "radical" notation is removed.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1548522
class nsMathMLmsqrtFrame final : public nsMathMLmencloseFrame {
public:
NS_DECL_FRAMEARENA_HELPERS(nsMathMLmsqrtFrame)

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

@ -665,7 +665,7 @@ nsresult nsMathMLmtableWrapperFrame::AttributeChanged(int32_t aNameSpaceID,
if (!rgFrame || !rgFrame->IsTableRowGroupFrame()) return NS_OK;
// align - just need to issue a dirty (resize) reflow command
if (aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::align) {
if (aAttribute == nsGkAtoms::align) {
PresShell()->FrameNeedsReflow(this, IntrinsicDirty::None,
NS_FRAME_IS_DIRTY);
return NS_OK;
@ -674,8 +674,7 @@ nsresult nsMathMLmtableWrapperFrame::AttributeChanged(int32_t aNameSpaceID,
// displaystyle - may seem innocuous, but it is actually very harsh --
// like changing an unit. Blow away and recompute all our automatic
// presentational data, and issue a style-changed reflow request
if (aNameSpaceID == kNameSpaceID_None &&
aAttribute == nsGkAtoms::displaystyle_) {
if (aAttribute == nsGkAtoms::displaystyle_) {
nsMathMLContainerFrame::RebuildAutomaticDataForChildren(GetParent());
// Need to reflow the parent, not us, because this can actually
// affect siblings.
@ -687,37 +686,32 @@ nsresult nsMathMLmtableWrapperFrame::AttributeChanged(int32_t aNameSpaceID,
// ...and the other attributes affect rows or columns in one way or another
if (aNameSpaceID == kNameSpaceID_None &&
(aAttribute == nsGkAtoms::rowspacing_ ||
aAttribute == nsGkAtoms::columnspacing_ ||
aAttribute == nsGkAtoms::framespacing_)) {
if (aAttribute == nsGkAtoms::rowspacing_ ||
aAttribute == nsGkAtoms::columnspacing_ ||
aAttribute == nsGkAtoms::framespacing_) {
nsMathMLmtableFrame* mathMLmtableFrame = do_QueryFrame(tableFrame);
if (mathMLmtableFrame) {
ParseSpacingAttribute(mathMLmtableFrame, aAttribute);
mathMLmtableFrame->SetUseCSSSpacing();
}
PresShell()->FrameNeedsReflow(
this, IntrinsicDirty::FrameAncestorsAndDescendants, NS_FRAME_IS_DIRTY);
return NS_OK;
}
if (aNameSpaceID == kNameSpaceID_None &&
(aAttribute == nsGkAtoms::rowalign_ ||
aAttribute == nsGkAtoms::rowlines_ ||
aAttribute == nsGkAtoms::columnalign_ ||
aAttribute == nsGkAtoms::columnlines_)) {
} else if (aAttribute == nsGkAtoms::rowalign_ ||
aAttribute == nsGkAtoms::rowlines_ ||
aAttribute == nsGkAtoms::columnalign_ ||
aAttribute == nsGkAtoms::columnlines_) {
// clear any cached property list for this table
tableFrame->RemoveProperty(AttributeToProperty(aAttribute));
// Reparse the new attribute on the table.
ParseFrameAttribute(tableFrame, aAttribute, true);
PresShell()->FrameNeedsReflow(
this, IntrinsicDirty::FrameAncestorsAndDescendants, NS_FRAME_IS_DIRTY);
} else {
// Ignore attributes that do not affect layout.
return NS_OK;
}
// Skip nsTableWrapperFrame::AttributeChanged, mtable does not share more
// attributes with table.
return nsContainerFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
// Explicitly request a reflow in our subtree to pick up any changes
PresShell()->FrameNeedsReflow(
this, IntrinsicDirty::FrameAncestorsAndDescendants, NS_FRAME_IS_DIRTY);
return NS_OK;
}
nsIFrame* nsMathMLmtableWrapperFrame::GetRowFrameAt(int32_t aRowIndex) {
@ -1030,13 +1024,9 @@ nsresult nsMathMLmtrFrame::AttributeChanged(int32_t aNameSpaceID,
// rowalign : Here
// columnalign : Here
if (aNameSpaceID != kNameSpaceID_None ||
(aAttribute != nsGkAtoms::rowalign_ &&
aAttribute != nsGkAtoms::columnalign_)) {
// Skip nsTableCellFrame::AttributeChanged, mtr does not share any attribute
// with tr.
return nsContainerFrame::AttributeChanged(aNameSpaceID, aAttribute,
aModType);
if (aAttribute != nsGkAtoms::rowalign_ &&
aAttribute != nsGkAtoms::columnalign_) {
return NS_OK;
}
RemoveProperty(AttributeToProperty(aAttribute));
@ -1085,9 +1075,8 @@ nsresult nsMathMLmtdFrame::AttributeChanged(int32_t aNameSpaceID,
// rowspan : here
// columnspan : here
if (aNameSpaceID == kNameSpaceID_None &&
(aAttribute == nsGkAtoms::rowalign_ ||
aAttribute == nsGkAtoms::columnalign_)) {
if (aAttribute == nsGkAtoms::rowalign_ ||
aAttribute == nsGkAtoms::columnalign_) {
RemoveProperty(AttributeToProperty(aAttribute));
// Reparse the attribute.
@ -1095,17 +1084,15 @@ nsresult nsMathMLmtdFrame::AttributeChanged(int32_t aNameSpaceID,
return NS_OK;
}
if (aNameSpaceID == kNameSpaceID_None &&
(aAttribute == nsGkAtoms::rowspan ||
aAttribute == nsGkAtoms::columnspan_)) {
// nsTableCellFrame takes care of renaming columnspan to colspan.
if (aAttribute == nsGkAtoms::rowspan ||
aAttribute == nsGkAtoms::columnspan_) {
// use the naming expected by the base class
if (aAttribute == nsGkAtoms::columnspan_) aAttribute = nsGkAtoms::colspan;
return nsTableCellFrame::AttributeChanged(aNameSpaceID, aAttribute,
aModType);
}
// Skip nsTableCellFrame::AttributeChanged, mtd does not share more attributes
// with td.
return nsContainerFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
return NS_OK;
}
StyleVerticalAlignKeyword nsMathMLmtdFrame::GetVerticalAlign() const {

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

@ -39,9 +39,8 @@ nsMathMLmunderoverFrame::~nsMathMLmunderoverFrame() = default;
nsresult nsMathMLmunderoverFrame::AttributeChanged(int32_t aNameSpaceID,
nsAtom* aAttribute,
int32_t aModType) {
if (aNameSpaceID == kNameSpaceID_None &&
(nsGkAtoms::accent_ == aAttribute ||
nsGkAtoms::accentunder_ == aAttribute)) {
if (nsGkAtoms::accent_ == aAttribute ||
nsGkAtoms::accentunder_ == aAttribute) {
// When we have automatic data to update within ourselves, we ask our
// parent to re-layout its children
return ReLayoutChildren(GetParent());