1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsMathMLmspaceFrame.h"
9 #include "mozilla/dom/MathMLElement.h"
10 #include "mozilla/PresShell.h"
11 #include "mozilla/gfx/2D.h"
12 #include "nsLayoutUtils.h"
15 using namespace mozilla
;
18 // <mspace> -- space - implementation
21 nsIFrame
* NS_NewMathMLmspaceFrame(PresShell
* aPresShell
,
22 ComputedStyle
* aStyle
) {
23 return new (aPresShell
)
24 nsMathMLmspaceFrame(aStyle
, aPresShell
->GetPresContext());
27 NS_IMPL_FRAMEARENA_HELPERS(nsMathMLmspaceFrame
)
29 nsMathMLmspaceFrame::~nsMathMLmspaceFrame() = default;
31 nsresult
nsMathMLmspaceFrame::AttributeChanged(int32_t aNameSpaceID
,
34 if (aNameSpaceID
== kNameSpaceID_None
) {
35 bool hasDirtyAttributes
= false;
36 IntrinsicDirty intrinsicDirty
= IntrinsicDirty::None
;
37 if (aAttribute
== nsGkAtoms::width
) {
38 mWidth
.mState
= Attribute::ParsingState::Dirty
;
39 hasDirtyAttributes
= true;
40 intrinsicDirty
= IntrinsicDirty::FrameAndAncestors
;
41 } else if (aAttribute
== nsGkAtoms::height
) {
42 mHeight
.mState
= Attribute::ParsingState::Dirty
;
43 hasDirtyAttributes
= true;
44 } else if (aAttribute
== nsGkAtoms::depth_
) {
45 mDepth
.mState
= Attribute::ParsingState::Dirty
;
46 hasDirtyAttributes
= true;
48 if (hasDirtyAttributes
) {
49 PresShell()->FrameNeedsReflow(this, intrinsicDirty
, NS_FRAME_IS_DIRTY
);
53 return nsMathMLContainerFrame::AttributeChanged(aNameSpaceID
, aAttribute
,
57 nscoord
nsMathMLmspaceFrame::CalculateAttributeValue(nsAtom
* aAtom
,
58 Attribute
& aAttribute
,
60 float aFontSizeInflation
) {
61 if (aAttribute
.mState
== Attribute::ParsingState::Dirty
) {
63 aAttribute
.mState
= Attribute::ParsingState::Invalid
;
64 mContent
->AsElement()->GetAttr(aAtom
, value
);
65 if (!value
.IsEmpty()) {
66 if (dom::MathMLElement::ParseNumericValue(
67 value
, aAttribute
.mValue
, aFlags
, PresContext()->Document())) {
68 aAttribute
.mState
= Attribute::ParsingState::Valid
;
70 ReportParseError(aAtom
->GetUTF16String(), value
.get());
74 // Invalid is interpreted as the default which is 0.
75 // Percentages are interpreted as a multiple of the default value.
76 if (aAttribute
.mState
== Attribute::ParsingState::Invalid
||
77 aAttribute
.mValue
.GetUnit() == eCSSUnit_Percent
) {
80 return CalcLength(PresContext(), mComputedStyle
, aAttribute
.mValue
,
84 nsresult
nsMathMLmspaceFrame::Place(DrawTarget
* aDrawTarget
,
85 const PlaceFlags
& aFlags
,
86 ReflowOutput
& aDesiredSize
) {
87 float fontSizeInflation
= nsLayoutUtils::FontSizeInflationFor(this);
89 // <mspace/> is listed among MathML elements allowing negative spacing and
90 // the MathML test suite contains "Presentation/TokenElements/mspace/mspace2"
91 // as an example. Hence we allow negative values.
92 nscoord width
= CalculateAttributeValue(
93 nsGkAtoms::width
, mWidth
, dom::MathMLElement::PARSE_ALLOW_NEGATIVE
,
96 // We do not allow negative values for height and depth attributes. See bug
99 CalculateAttributeValue(nsGkAtoms::height
, mHeight
, 0, fontSizeInflation
);
101 CalculateAttributeValue(nsGkAtoms::depth_
, mDepth
, 0, fontSizeInflation
);
103 mBoundingMetrics
= nsBoundingMetrics();
104 mBoundingMetrics
.width
= width
;
105 mBoundingMetrics
.ascent
= height
;
106 mBoundingMetrics
.descent
= depth
;
107 mBoundingMetrics
.leftBearing
= 0;
108 mBoundingMetrics
.rightBearing
= mBoundingMetrics
.width
;
110 aDesiredSize
.SetBlockStartAscent(mBoundingMetrics
.ascent
);
111 aDesiredSize
.Width() = std::max(0, mBoundingMetrics
.width
);
112 aDesiredSize
.Height() = mBoundingMetrics
.ascent
+ mBoundingMetrics
.descent
;
113 // Also return our bounding metrics
114 aDesiredSize
.mBoundingMetrics
= mBoundingMetrics
;
116 // Apply width/height to math content box.
117 const PlaceFlags flags
;
118 auto sizes
= GetWidthAndHeightForPlaceAdjustment(flags
);
119 ApplyAdjustmentForWidthAndHeight(flags
, sizes
, aDesiredSize
,
122 // Add padding+border.
123 auto borderPadding
= GetBorderPaddingForPlace(aFlags
);
124 InflateReflowAndBoundingMetrics(borderPadding
, aDesiredSize
,