nsMathMLmspaceFrame.cpp (4988B)
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/. */ 6 7 #include "nsMathMLmspaceFrame.h" 8 9 #include <algorithm> 10 11 #include "mozilla/PresShell.h" 12 #include "mozilla/dom/MathMLElement.h" 13 #include "mozilla/gfx/2D.h" 14 #include "nsLayoutUtils.h" 15 16 using namespace mozilla; 17 18 // 19 // <mspace> -- space - implementation 20 // 21 22 nsIFrame* NS_NewMathMLmspaceFrame(PresShell* aPresShell, 23 ComputedStyle* aStyle) { 24 return new (aPresShell) 25 nsMathMLmspaceFrame(aStyle, aPresShell->GetPresContext()); 26 } 27 28 NS_IMPL_FRAMEARENA_HELPERS(nsMathMLmspaceFrame) 29 30 nsMathMLmspaceFrame::~nsMathMLmspaceFrame() = default; 31 32 nsresult nsMathMLmspaceFrame::AttributeChanged(int32_t aNameSpaceID, 33 nsAtom* aAttribute, 34 AttrModType aModType) { 35 if (aNameSpaceID == kNameSpaceID_None) { 36 bool hasDirtyAttributes = false; 37 IntrinsicDirty intrinsicDirty = IntrinsicDirty::None; 38 if (aAttribute == nsGkAtoms::width) { 39 mWidth.mState = Attribute::ParsingState::Dirty; 40 hasDirtyAttributes = true; 41 intrinsicDirty = IntrinsicDirty::FrameAndAncestors; 42 } else if (aAttribute == nsGkAtoms::height) { 43 mHeight.mState = Attribute::ParsingState::Dirty; 44 hasDirtyAttributes = true; 45 } else if (aAttribute == nsGkAtoms::depth) { 46 mDepth.mState = Attribute::ParsingState::Dirty; 47 hasDirtyAttributes = true; 48 } 49 if (hasDirtyAttributes) { 50 PresShell()->FrameNeedsReflow(this, intrinsicDirty, NS_FRAME_IS_DIRTY); 51 } 52 return NS_OK; 53 } 54 return nsMathMLContainerFrame::AttributeChanged(aNameSpaceID, aAttribute, 55 aModType); 56 } 57 58 nscoord nsMathMLmspaceFrame::CalculateAttributeValue(nsAtom* aAtom, 59 Attribute& aAttribute, 60 uint32_t aFlags, 61 float aFontSizeInflation) { 62 if (aAttribute.mState == Attribute::ParsingState::Dirty) { 63 nsAutoString value; 64 aAttribute.mState = Attribute::ParsingState::Invalid; 65 mContent->AsElement()->GetAttr(aAtom, value); 66 if (!value.IsEmpty()) { 67 if (dom::MathMLElement::ParseNumericValue( 68 value, aAttribute.mValue, aFlags, PresContext()->Document())) { 69 aAttribute.mState = Attribute::ParsingState::Valid; 70 } else { 71 ReportParseError(aAtom->GetUTF16String(), value.get()); 72 } 73 } 74 } 75 // Invalid is interpreted as the default which is 0. 76 // Percentages are interpreted as a multiple of the default value. 77 if (aAttribute.mState == Attribute::ParsingState::Invalid || 78 aAttribute.mValue.GetUnit() == eCSSUnit_Percent) { 79 return 0; 80 } 81 return CalcLength(aAttribute.mValue, aFontSizeInflation, this); 82 } 83 84 void nsMathMLmspaceFrame::Place(DrawTarget* aDrawTarget, 85 const PlaceFlags& aFlags, 86 ReflowOutput& aDesiredSize) { 87 float fontSizeInflation = nsLayoutUtils::FontSizeInflationFor(this); 88 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, 94 fontSizeInflation); 95 96 // We do not allow negative values for height and depth attributes. See bug 97 // 716349. 98 nscoord height = 99 CalculateAttributeValue(nsGkAtoms::height, mHeight, 0, fontSizeInflation); 100 nscoord depth = 101 CalculateAttributeValue(nsGkAtoms::depth, mDepth, 0, fontSizeInflation); 102 103 mBoundingMetrics = nsBoundingMetrics(); 104 mBoundingMetrics.width = width; 105 mBoundingMetrics.ascent = height; 106 mBoundingMetrics.descent = depth; 107 mBoundingMetrics.leftBearing = 0; 108 mBoundingMetrics.rightBearing = mBoundingMetrics.width; 109 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; 115 116 // Apply width/height to math content box. 117 const PlaceFlags flags; 118 auto sizes = GetWidthAndHeightForPlaceAdjustment(flags); 119 ApplyAdjustmentForWidthAndHeight(flags, sizes, aDesiredSize, 120 mBoundingMetrics); 121 122 // Add padding+border. 123 auto borderPadding = GetBorderPaddingForPlace(aFlags); 124 InflateReflowAndBoundingMetrics(borderPadding, aDesiredSize, 125 mBoundingMetrics); 126 }