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 "RenderMathMLOperator.h" 34 35namespace WebCore { 36 37using namespace MathMLNames; 38 39RenderMathMLRow::RenderMathMLRow(Node* row) 40 : RenderMathMLBlock(row) 41{ 42} 43 44int RenderMathMLRow::nonOperatorHeight() const 45{ 46 int maxHeight = 0; 47 for (RenderObject* current = firstChild(); current; current = current->nextSibling()) { 48 if (current->isRenderMathMLBlock()) { 49 RenderMathMLBlock* block = toRenderMathMLBlock(current); 50 int blockHeight = block->nonOperatorHeight(); 51 // Check to see if this box has a larger height 52 if (blockHeight > maxHeight) 53 maxHeight = blockHeight; 54 } else if (current->isBoxModelObject()) { 55 RenderBoxModelObject* box = toRenderBoxModelObject(current); 56 // Check to see if this box has a larger height 57 if (box->offsetHeight() > maxHeight) 58 maxHeight = box->offsetHeight(); 59 } 60 61 } 62 return maxHeight; 63} 64 65void RenderMathMLRow::layout() 66{ 67 RenderBlock::layout(); 68 69 int maxHeight = 0; 70 int childCount = 0; 71 int operatorCount = 0; 72 73 // Calculate the non-operator max height of the row. 74 int operatorHeight = 0; 75 for (RenderObject* current = firstChild(); current; current = current->nextSibling()) { 76 childCount++; 77 if (current->isRenderMathMLBlock()) { 78 RenderMathMLBlock* block = toRenderMathMLBlock(current); 79 // Check to see if the non-operator block has a greater height. 80 if (!block->hasBase() && !block->isRenderMathMLOperator() && block->offsetHeight() > maxHeight) 81 maxHeight = block->offsetHeight(); 82 if (block->hasBase() && block->nonOperatorHeight() > maxHeight) 83 maxHeight = block->nonOperatorHeight(); 84 // If the block is an operator, capture the maximum height and increment the count. 85 if (block->isRenderMathMLOperator()) { 86 if (block->offsetHeight() > operatorHeight) 87 operatorHeight = block->offsetHeight(); 88 operatorCount++; 89 } 90 } else if (current->isBoxModelObject()) { 91 RenderBoxModelObject* box = toRenderBoxModelObject(current); 92 // Check to see if this box has a larger height. 93 if (box->offsetHeight() > maxHeight) 94 maxHeight = box->offsetHeight(); 95 } 96 } 97 98 if (childCount > 0 && childCount == operatorCount) { 99 // We have only operators and so set the max height to the operator height. 100 maxHeight = operatorHeight; 101 } 102 103 // Stretch everything to the same height (blocks can ignore the request). 104 if (maxHeight > 0) { 105 bool didStretch = false; 106 for (RenderObject* current = firstChild(); current; current = current->nextSibling()) { 107 if (current->isRenderMathMLBlock()) { 108 RenderMathMLBlock* block = toRenderMathMLBlock(current); 109 block->stretchToHeight(maxHeight); 110 didStretch = true; 111 } 112 } 113 if (didStretch) { 114 setNeedsLayout(true); 115 setPreferredLogicalWidthsDirty(true, false); 116 RenderBlock::layout(); 117 } 118 } 119 120} 121 122int RenderMathMLRow::baselinePosition(FontBaseline, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const 123{ 124 if (firstChild() && firstChild()->isRenderMathMLBlock()) { 125 RenderMathMLBlock* block = toRenderMathMLBlock(firstChild()); 126 if (block->isRenderMathMLOperator()) 127 return block->y() + block->baselinePosition(AlphabeticBaseline, firstLine, direction, linePositionMode); 128 } 129 130 return RenderBlock::baselinePosition(AlphabeticBaseline, firstLine, direction, linePositionMode); 131} 132 133} 134 135#endif // ENABLE(MATHML) 136 137