summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/mathml/RenderMathMLRow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/rendering/mathml/RenderMathMLRow.cpp')
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLRow.cpp162
1 files changed, 134 insertions, 28 deletions
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLRow.cpp b/Source/WebCore/rendering/mathml/RenderMathMLRow.cpp
index 02ef296cd..c4bebc2a2 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLRow.cpp
+++ b/Source/WebCore/rendering/mathml/RenderMathMLRow.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2010 Alex Milowski (alex@milowski.com). All rights reserved.
+ * Copyright (C) 2016 Igalia S.L.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -24,12 +25,12 @@
*/
#include "config.h"
+#include "RenderMathMLRow.h"
#if ENABLE(MATHML)
-#include "RenderMathMLRow.h"
-
#include "MathMLNames.h"
+#include "MathMLRowElement.h"
#include "RenderIterator.h"
#include "RenderMathMLOperator.h"
#include "RenderMathMLRoot.h"
@@ -38,47 +39,152 @@ namespace WebCore {
using namespace MathMLNames;
-RenderMathMLRow::RenderMathMLRow(Element& element, PassRef<RenderStyle> style)
- : RenderMathMLBlock(element, std::move(style))
+RenderMathMLRow::RenderMathMLRow(MathMLRowElement& element, RenderStyle&& style)
+ : RenderMathMLBlock(element, WTFMove(style))
{
}
-RenderMathMLRow::RenderMathMLRow(Document& document, PassRef<RenderStyle> style)
- : RenderMathMLBlock(document, std::move(style))
+MathMLRowElement& RenderMathMLRow::element() const
{
+ return static_cast<MathMLRowElement&>(nodeForNonAnonymous());
}
-RenderPtr<RenderMathMLRow> RenderMathMLRow::createAnonymousWithParentRenderer(RenderMathMLRoot& parent)
+std::optional<int> RenderMathMLRow::firstLineBaseline() const
{
- RenderPtr<RenderMathMLRow> newMRow = createRenderer<RenderMathMLRow>(parent.document(), RenderStyle::createAnonymousStyleWithDisplay(&parent.style(), FLEX));
- newMRow->initializeStyle();
- return newMRow;
+ auto* baselineChild = firstChildBox();
+ if (!baselineChild)
+ return std::optional<int>();
+
+ return std::optional<int>(static_cast<int>(lroundf(ascentForChild(*baselineChild) + baselineChild->logicalTop())));
}
-void RenderMathMLRow::layout()
+void RenderMathMLRow::computeLineVerticalStretch(LayoutUnit& ascent, LayoutUnit& descent)
{
- int stretchLogicalHeight = 0;
- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- if (child->needsLayout())
- toRenderElement(child)->layout();
- // FIXME: Only skip renderMo if it is stretchy.
- if (child->isRenderMathMLBlock() && toRenderMathMLBlock(child)->unembellishedOperator())
+ for (auto* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+ if (is<RenderMathMLBlock>(child)) {
+ auto* renderOperator = downcast<RenderMathMLBlock>(child)->unembellishedOperator();
+ if (renderOperator && renderOperator->isStretchy())
+ continue;
+ }
+
+ child->layoutIfNeeded();
+
+ LayoutUnit childHeightAboveBaseline = ascentForChild(*child);
+ LayoutUnit childDepthBelowBaseline = child->logicalHeight() - childHeightAboveBaseline;
+
+ ascent = std::max(ascent, childHeightAboveBaseline);
+ descent = std::max(descent, childDepthBelowBaseline);
+ }
+
+ // We ensure a minimal stretch size.
+ if (ascent + descent <= 0) {
+ ascent = style().fontSize();
+ descent = 0;
+ }
+}
+
+void RenderMathMLRow::computePreferredLogicalWidths()
+{
+ ASSERT(preferredLogicalWidthsDirty());
+
+ m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = 0;
+
+ LayoutUnit preferredWidth = 0;
+ for (auto* child = firstChildBox(); child; child = child->nextSiblingBox())
+ preferredWidth += child->maxPreferredLogicalWidth() + child->marginLogicalWidth();
+
+ m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = preferredWidth + borderAndPaddingLogicalWidth();
+
+ setPreferredLogicalWidthsDirty(false);
+}
+
+void RenderMathMLRow::layoutRowItems(LayoutUnit& ascent, LayoutUnit& descent)
+{
+ // We first stretch the vertical operators.
+ // For inline formulas, we can then calculate the logical width.
+ LayoutUnit width = borderAndPaddingStart();
+ for (auto* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+ if (child->isOutOfFlowPositioned())
continue;
- if (child->isBox())
- stretchLogicalHeight = std::max<int>(stretchLogicalHeight, roundToInt(toRenderBox(child)->logicalHeight()));
+
+ if (is<RenderMathMLBlock>(child)) {
+ auto renderOperator = downcast<RenderMathMLBlock>(child)->unembellishedOperator();
+ if (renderOperator && renderOperator->isStretchy() && renderOperator->isVertical())
+ renderOperator->stretchTo(ascent, descent);
+ }
+
+ child->layoutIfNeeded();
+
+ width += child->marginStart() + child->logicalWidth() + child->marginEnd();
}
- if (!stretchLogicalHeight)
- stretchLogicalHeight = style().fontSize();
-
- // Set the sizes of (possibly embellished) stretchy operator children.
- for (auto& child : childrenOfType<RenderMathMLBlock>(*this)) {
- if (auto renderMo = child.unembellishedOperator()) {
- if (renderMo->stretchHeight() != stretchLogicalHeight)
- renderMo->stretchToHeight(stretchLogicalHeight);
+
+ width += borderEnd() + paddingEnd();
+ if ((!isRenderMathMLMath() || style().display() == INLINE))
+ setLogicalWidth(width);
+
+ LayoutUnit verticalOffset = borderTop() + paddingTop();
+ LayoutUnit maxAscent = 0, maxDescent = 0; // Used baseline alignment.
+ LayoutUnit horizontalOffset = borderAndPaddingStart();
+ bool shouldFlipHorizontal = !style().isLeftToRightDirection();
+ for (auto* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+ if (child->isOutOfFlowPositioned()) {
+ child->containingBlock()->insertPositionedObject(*child);
+ continue;
}
+ LayoutUnit childHorizontalExtent = child->logicalWidth();
+ LayoutUnit ascent = ascentForChild(*child);
+ LayoutUnit descent = child->verticalMarginExtent() + child->logicalHeight() - ascent;
+ maxAscent = std::max(maxAscent, ascent);
+ maxDescent = std::max(maxDescent, descent);
+ LayoutUnit childVerticalMarginBoxExtent = maxAscent + maxDescent;
+
+ horizontalOffset += child->marginStart();
+
+ setLogicalHeight(std::max(logicalHeight(), verticalOffset + borderBottom() + paddingBottom() + childVerticalMarginBoxExtent + horizontalScrollbarHeight()));
+
+ LayoutPoint childLocation(shouldFlipHorizontal ? logicalWidth() - horizontalOffset - childHorizontalExtent : horizontalOffset, verticalOffset + child->marginTop());
+ child->setLocation(childLocation);
+
+ horizontalOffset += childHorizontalExtent + child->marginEnd();
}
- RenderMathMLBlock::layout();
+ LayoutUnit centerBlockOffset = 0;
+ if (style().display() == BLOCK)
+ centerBlockOffset = std::max<LayoutUnit>(0, (logicalWidth() - (horizontalOffset + borderEnd() + paddingEnd())) / 2);
+
+ if (shouldFlipHorizontal && centerBlockOffset > 0)
+ centerBlockOffset = -centerBlockOffset;
+
+ for (auto* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+ LayoutUnit ascent = ascentForChild(*child);
+ LayoutUnit startOffset = maxAscent - ascent;
+ child->setLocation(child->location() + LayoutPoint(centerBlockOffset, startOffset));
+ }
+
+ ascent = maxAscent;
+ descent = maxDescent;
+}
+
+void RenderMathMLRow::layoutBlock(bool relayoutChildren, LayoutUnit)
+{
+ ASSERT(needsLayout());
+
+ if (!relayoutChildren && simplifiedLayout())
+ return;
+
+ LayoutUnit ascent = 0;
+ LayoutUnit descent = 0;
+ computeLineVerticalStretch(ascent, descent);
+
+ recomputeLogicalWidth();
+
+ setLogicalHeight(borderAndPaddingLogicalHeight() + scrollbarLogicalHeight());
+
+ layoutRowItems(ascent, descent);
+
+ updateLogicalHeight();
+
+ clearNeedsLayout();
}
}