fune/layout/mathml/nsMathMLmspaceFrame.cpp
Delan Azabani 9e07fbde4d Bug 1658121 - Implement padding/border layout for <mspace>. r=emilio
This patch doesn’t try to handle width/height or similar properties ([[ https://github.com/mathml-refresh/mathml/issues/45 | mathml-refresh/mathml#45 ]]) or non-horizontal writing modes ([[ https://bugzilla.mozilla.org/show_bug.cgi?id=1077525 | bug 1077525 ]]).

* [[ https://phabricator.services.mozilla.com/D86471?id=324103 | Diff 1 ]] implements padding well enough to pass WPT’s [[ http://wpt.live/mathml/relations/css-styling/padding-border-margin/padding-002.html | “Padding properties on mspace” ]]
* [[ https://phabricator.services.mozilla.com/D86471?id=324105 | Diff 2 ]] implements border well enough to pass WPT’s [[ http://wpt.live/mathml/relations/css-styling/padding-border-margin/border-002.html | “Border properties on mspace” ]]
* [[ https://phabricator.services.mozilla.com/D86471?id=324110 | Diff 3 ]] adjusts mBlockStartAscent + mBoundingMetrics in the same way as the rest of the ReflowOutput
* [[ https://phabricator.services.mozilla.com/D86471?id=327654 | Diff 4 ]] adjusts MeasureForWidth by IntrinsicISizeOffsets().{padding,border}
* Diff 5 through Diff 8 relate to margin layout, and now live in D87594
* [[ https://phabricator.services.mozilla.com/D86471?id=328587 | Diff 9 ]] + [[ https://phabricator.services.mozilla.com/D86471?id=336839 | Diff 10 ]] mark the relevant WPT cases as passing
* [[ https://phabricator.services.mozilla.com/D86471?id=338658 | Diff 11 ]] adds a workaround for [[ https://bugzilla.mozilla.org/show_bug.cgi?id=1658135 | bug 1658135 ]] to the WPT support script

Differential Revision: https://phabricator.services.mozilla.com/D86471
2020-09-13 11:17:03 +00:00

124 lines
4.3 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsMathMLmspaceFrame.h"
#include "mozilla/dom/MathMLElement.h"
#include "mozilla/PresShell.h"
#include "mozilla/gfx/2D.h"
#include <algorithm>
using namespace mozilla;
//
// <mspace> -- space - implementation
//
nsIFrame* NS_NewMathMLmspaceFrame(PresShell* aPresShell,
ComputedStyle* aStyle) {
return new (aPresShell)
nsMathMLmspaceFrame(aStyle, aPresShell->GetPresContext());
}
NS_IMPL_FRAMEARENA_HELPERS(nsMathMLmspaceFrame)
nsMathMLmspaceFrame::~nsMathMLmspaceFrame() = default;
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.
//
mWidth = 0;
mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::width, value);
if (!value.IsEmpty()) {
ParseNumericValue(value, &mWidth, dom::MathMLElement::PARSE_ALLOW_NEGATIVE,
aPresContext, mComputedStyle, 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(kNameSpaceID_None, 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(kNameSpaceID_None, 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!");
mPresentationData.flags &= ~NS_MATHML_ERROR;
ProcessAttributes(aPresContext);
auto borderPadding = aReflowInput.ComputedPhysicalBorderPadding();
mBoundingMetrics = nsBoundingMetrics();
mBoundingMetrics.width = mWidth + borderPadding.LeftRight();
mBoundingMetrics.ascent = mHeight + borderPadding.Side(eSideTop);
mBoundingMetrics.descent = mDepth + borderPadding.Side(eSideBottom);
mBoundingMetrics.leftBearing = 0;
mBoundingMetrics.rightBearing = mBoundingMetrics.width;
aDesiredSize.SetBlockStartAscent(mBoundingMetrics.ascent);
aDesiredSize.Width() = std::max(0, mBoundingMetrics.width);
aDesiredSize.Height() = mBoundingMetrics.ascent + mBoundingMetrics.descent;
// Also return our bounding metrics
aDesiredSize.mBoundingMetrics = mBoundingMetrics;
NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
}
/* virtual */
nsresult nsMathMLmspaceFrame::MeasureForWidth(DrawTarget* aDrawTarget,
ReflowOutput& aDesiredSize) {
ProcessAttributes(PresContext());
mBoundingMetrics = nsBoundingMetrics();
auto offsets = IntrinsicISizeOffsets();
mBoundingMetrics.width = mWidth + offsets.padding + offsets.border;
aDesiredSize.Width() = std::max(0, mBoundingMetrics.width);
aDesiredSize.mBoundingMetrics = mBoundingMetrics;
return NS_OK;
}