1/*
2 * Copyright (C) 2010 Alex Milowski (alex@milowski.com). All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
16 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
17 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27
28#if ENABLE(MATHML)
29
30#include "RenderMathMLRow.h"
31
32#include "MathMLNames.h"
33#include "RenderIterator.h"
34#include "RenderMathMLOperator.h"
35#include "RenderMathMLRoot.h"
36
37namespace WebCore {
38
39using namespace MathMLNames;
40
41RenderMathMLRow::RenderMathMLRow(Element& element, PassRef<RenderStyle> style)
42    : RenderMathMLBlock(element, WTF::move(style))
43{
44}
45
46RenderMathMLRow::RenderMathMLRow(Document& document, PassRef<RenderStyle> style)
47    : RenderMathMLBlock(document, WTF::move(style))
48{
49}
50
51RenderPtr<RenderMathMLRow> RenderMathMLRow::createAnonymousWithParentRenderer(RenderMathMLRoot& parent)
52{
53    RenderPtr<RenderMathMLRow> newMRow = createRenderer<RenderMathMLRow>(parent.document(), RenderStyle::createAnonymousStyleWithDisplay(&parent.style(), FLEX));
54    newMRow->initializeStyle();
55    return newMRow;
56}
57
58void RenderMathMLRow::updateOperatorProperties()
59{
60    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
61        if (child->isRenderMathMLBlock()) {
62            if (auto renderOperator = toRenderMathMLBlock(child)->unembellishedOperator())
63                renderOperator->updateOperatorProperties();
64        }
65    }
66    setNeedsLayoutAndPrefWidthsRecalc();
67}
68
69void RenderMathMLRow::layout()
70{
71    int stretchHeightAboveBaseline = 0, stretchDepthBelowBaseline = 0;
72    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
73        if (child->needsLayout())
74            toRenderElement(child)->layout();
75        if (child->isRenderMathMLBlock()) {
76            // We skip the stretchy operators as they must not be included in the computation of the stretch size.
77            auto renderOperator = toRenderMathMLBlock(child)->unembellishedOperator();
78            if (renderOperator && renderOperator->hasOperatorFlag(MathMLOperatorDictionary::Stretchy))
79                continue;
80        }
81        LayoutUnit childHeightAboveBaseline = 0, childDepthBelowBaseline = 0;
82        if (child->isRenderMathMLBlock()) {
83            RenderMathMLBlock* mathmlChild = toRenderMathMLBlock(child);
84            childHeightAboveBaseline = mathmlChild->firstLineBaseline();
85            if (childHeightAboveBaseline == -1)
86                childHeightAboveBaseline = mathmlChild->logicalHeight();
87            childDepthBelowBaseline = mathmlChild->logicalHeight() - childHeightAboveBaseline;
88        } else if (child->isRenderMathMLTable()) {
89            RenderMathMLTable* tableChild = toRenderMathMLTable(child);
90            childHeightAboveBaseline = tableChild->firstLineBaseline();
91            childDepthBelowBaseline = tableChild->logicalHeight() - childHeightAboveBaseline;
92        } else if (child->isBox()) {
93            childHeightAboveBaseline = toRenderBox(child)->logicalHeight();
94            childDepthBelowBaseline = 0;
95        }
96        stretchHeightAboveBaseline = std::max<LayoutUnit>(stretchHeightAboveBaseline, childHeightAboveBaseline);
97        stretchDepthBelowBaseline = std::max<LayoutUnit>(stretchDepthBelowBaseline, childDepthBelowBaseline);
98    }
99    if (stretchHeightAboveBaseline + stretchDepthBelowBaseline <= 0)
100        stretchHeightAboveBaseline = style().fontSize();
101
102    // Set the sizes of (possibly embellished) stretchy operator children.
103    for (auto& child : childrenOfType<RenderMathMLBlock>(*this)) {
104        if (auto renderOperator = child.unembellishedOperator())
105            renderOperator->stretchTo(stretchHeightAboveBaseline, stretchDepthBelowBaseline);
106    }
107
108    RenderMathMLBlock::layout();
109}
110
111}
112
113#endif // ENABLE(MATHML)
114