1dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block/*
2dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * Copyright (C) 2010 Alex Milowski (alex@milowski.com). All rights reserved.
3dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block *
4dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * Redistribution and use in source and binary forms, with or without
5dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * modification, are permitted provided that the following conditions
6dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * are met:
7dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * 1. Redistributions of source code must retain the above copyright
8dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block *    notice, this list of conditions and the following disclaimer.
9dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * 2. Redistributions in binary form must reproduce the above copyright
10dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block *    notice, this list of conditions and the following disclaimer in the
11dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block *    documentation and/or other materials provided with the distribution.
12dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block *
13dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
16dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
17dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block */
25dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
26dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "config.h"
27dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
28dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#if ENABLE(MATHML)
29dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
30dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "RenderMathMLRow.h"
31dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
32dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "MathMLNames.h"
33dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "RenderMathMLOperator.h"
34dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
35dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocknamespace WebCore {
36dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
37dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockusing namespace MathMLNames;
38dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
39dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockRenderMathMLRow::RenderMathMLRow(Node* row)
40dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    : RenderMathMLBlock(row)
41dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
42dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
43dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
44dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockint RenderMathMLRow::nonOperatorHeight() const
45dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
46dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    int maxHeight = 0;
47dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    for (RenderObject* current = firstChild(); current; current = current->nextSibling()) {
48dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (current->isRenderMathMLBlock()) {
49dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            RenderMathMLBlock* block = toRenderMathMLBlock(current);
50dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            int blockHeight = block->nonOperatorHeight();
51dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            // Check to see if this box has a larger height
52dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (blockHeight > maxHeight)
53dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                maxHeight = blockHeight;
54dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } else if (current->isBoxModelObject()) {
55dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            RenderBoxModelObject* box = toRenderBoxModelObject(current);
56dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            // Check to see if this box has a larger height
57dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (box->offsetHeight() > maxHeight)
58dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                maxHeight = box->offsetHeight();
59dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
60dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
61dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
62dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return maxHeight;
63dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
64dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
65dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid RenderMathMLRow::layout()
66dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
67dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    RenderBlock::layout();
68dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
69e14391e94c850b8bd03680c23b38978db68687a8John Reck    int maxHeight = 0;
70dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    int childCount = 0;
71dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    int operatorCount = 0;
72dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
73e14391e94c850b8bd03680c23b38978db68687a8John Reck    // Calculate the non-operator max height of the row.
74dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    int operatorHeight = 0;
75dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    for (RenderObject* current = firstChild(); current; current = current->nextSibling()) {
76e14391e94c850b8bd03680c23b38978db68687a8John Reck        childCount++;
77dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (current->isRenderMathMLBlock()) {
78dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            RenderMathMLBlock* block = toRenderMathMLBlock(current);
79e14391e94c850b8bd03680c23b38978db68687a8John Reck            // Check to see if the non-operator block has a greater height.
80e14391e94c850b8bd03680c23b38978db68687a8John Reck            if (!block->hasBase() && !block->isRenderMathMLOperator() && block->offsetHeight() > maxHeight)
81e14391e94c850b8bd03680c23b38978db68687a8John Reck                maxHeight = block->offsetHeight();
82e14391e94c850b8bd03680c23b38978db68687a8John Reck            if (block->hasBase() && block->nonOperatorHeight() > maxHeight)
83e14391e94c850b8bd03680c23b38978db68687a8John Reck                maxHeight = block->nonOperatorHeight();
84e14391e94c850b8bd03680c23b38978db68687a8John Reck            // If the block is an operator, capture the maximum height and increment the count.
85e14391e94c850b8bd03680c23b38978db68687a8John Reck            if (block->isRenderMathMLOperator()) {
86dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                if (block->offsetHeight() > operatorHeight)
87dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    operatorHeight = block->offsetHeight();
88e14391e94c850b8bd03680c23b38978db68687a8John Reck                operatorCount++;
89e14391e94c850b8bd03680c23b38978db68687a8John Reck            }
90dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } else if (current->isBoxModelObject()) {
91dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            RenderBoxModelObject* box = toRenderBoxModelObject(current);
92dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            // Check to see if this box has a larger height.
93dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (box->offsetHeight() > maxHeight)
94dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                maxHeight = box->offsetHeight();
95dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
96dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
97dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
98dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (childCount > 0 && childCount == operatorCount) {
99dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // We have only operators and so set the max height to the operator height.
100dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        maxHeight = operatorHeight;
101dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
102dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
103e14391e94c850b8bd03680c23b38978db68687a8John Reck    // Stretch everything to the same height (blocks can ignore the request).
104e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (maxHeight > 0) {
105e14391e94c850b8bd03680c23b38978db68687a8John Reck        bool didStretch = false;
106e14391e94c850b8bd03680c23b38978db68687a8John Reck        for (RenderObject* current = firstChild(); current; current = current->nextSibling()) {
107e14391e94c850b8bd03680c23b38978db68687a8John Reck            if (current->isRenderMathMLBlock()) {
108e14391e94c850b8bd03680c23b38978db68687a8John Reck                RenderMathMLBlock* block = toRenderMathMLBlock(current);
109e14391e94c850b8bd03680c23b38978db68687a8John Reck                block->stretchToHeight(maxHeight);
110e14391e94c850b8bd03680c23b38978db68687a8John Reck                didStretch = true;
111dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
112e14391e94c850b8bd03680c23b38978db68687a8John Reck        }
113e14391e94c850b8bd03680c23b38978db68687a8John Reck        if (didStretch) {
114e14391e94c850b8bd03680c23b38978db68687a8John Reck            setNeedsLayout(true);
115e14391e94c850b8bd03680c23b38978db68687a8John Reck            setPreferredLogicalWidthsDirty(true, false);
116e14391e94c850b8bd03680c23b38978db68687a8John Reck            RenderBlock::layout();
117dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
118dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
119dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
12006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen}
121dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1226b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerint RenderMathMLRow::baselinePosition(FontBaseline, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
12306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen{
12406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    if (firstChild() && firstChild()->isRenderMathMLBlock()) {
12506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        RenderMathMLBlock* block = toRenderMathMLBlock(firstChild());
12606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        if (block->isRenderMathMLOperator())
1276b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            return block->y() + block->baselinePosition(AlphabeticBaseline, firstLine, direction, linePositionMode);
12806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    }
12906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
1306b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    return RenderBlock::baselinePosition(AlphabeticBaseline, firstLine, direction, linePositionMode);
13106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen}
13206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
133dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
134dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
135dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#endif // ENABLE(MATHML)
136dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
137