1dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block/* 2dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * Copyright (C) 2009 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 "RenderMathMLUnderOver.h" 31dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 32dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "FontSelector.h" 33dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "MathMLNames.h" 34dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 35dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocknamespace WebCore { 36dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 37dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockusing namespace MathMLNames; 38dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 39dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockstatic const double gOverSpacingAdjustment = 0.5; 40dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 41dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockRenderMathMLUnderOver::RenderMathMLUnderOver(Node* expression) 42dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block : RenderMathMLBlock(expression) 43dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 44dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block Element* element = static_cast<Element*>(expression); 45dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // Determine what kind of under/over expression we have by element name 46dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 47dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (element->hasLocalName(MathMLNames::munderTag)) 48dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_kind = Under; 49dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block else if (element->hasLocalName(MathMLNames::moverTag)) 50dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_kind = Over; 51dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block else if (element->hasLocalName(MathMLNames::munderoverTag)) 52dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_kind = UnderOver; 53dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block else 54dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_kind = Under; 55dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 56dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 57dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 58dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid RenderMathMLUnderOver::addChild(RenderObject* child, RenderObject* beforeChild) 59dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 60dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderMathMLBlock* row = new (renderArena()) RenderMathMLBlock(node()); 61dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RefPtr<RenderStyle> rowStyle = makeBlockStyle(); 62dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block row->setStyle(rowStyle.release()); 63dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 64dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // look through the children for rendered elements counting the blocks so we know what child 65dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // we are adding 66dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block int blocks = 0; 67dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderObject* current = this->firstChild(); 68dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block while (current) { 69dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block blocks++; 70dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block current = current->nextSibling(); 71dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 72dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 73dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block switch (blocks) { 74dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block case 0: 75dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // this is the base so just append it 76dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderBlock::addChild(row, beforeChild); 77dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block break; 78dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block case 1: 79dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // the under or over 80dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // FIXME: text-align: center does not work 81dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block row->style()->setTextAlign(CENTER); 82dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (m_kind == Over) { 83dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // add the over as first 84dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderBlock::addChild(row, firstChild()); 85dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } else { 86dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // add the under as last 87dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderBlock::addChild(row, beforeChild); 88dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 89dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block break; 90dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block case 2: 91dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // the under or over 92dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // FIXME: text-align: center does not work 93dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block row->style()->setTextAlign(CENTER); 94dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (m_kind == UnderOver) { 95dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // add the over as first 96dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderBlock::addChild(row, firstChild()); 97dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } else { 98dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // we really shouldn't get here as only munderover should have three children 99dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderBlock::addChild(row, beforeChild); 100dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 101dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block break; 102dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block default: 103dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // munderover shouldn't have more than three children. In theory we shouldn't 104dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // get here if the MathML is correctly formed, but that isn't a guarantee. 105dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // We will treat this as another under element and they'll get something funky. 106dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderBlock::addChild(row, beforeChild); 107dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 108dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block row->addChild(child); 109dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 110dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 111dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockinline int getOffsetHeight(RenderObject* obj) 112dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 113dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (obj->isBoxModelObject()) { 114dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderBoxModelObject* box = toRenderBoxModelObject(obj); 115dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return box->offsetHeight(); 116dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 117dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 118dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return 0; 119dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 120dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 121e14391e94c850b8bd03680c23b38978db68687a8John Reckvoid RenderMathMLUnderOver::stretchToHeight(int height) 122dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 123dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 124dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderObject* base = firstChild(); 125dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!base) 126dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return; 127dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 128dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // For over or underover, the base is the sibling of the first child 129dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (m_kind != Under) 130dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block base = base->nextSibling(); 131dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 132dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!base) 133dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return; 134dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 135dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // use the child of the row which is the actual base 136dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block base = base->firstChild(); 137dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 138dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (base && base->isRenderMathMLBlock()) { 139dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderMathMLBlock* block = toRenderMathMLBlock(base); 140dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block block->stretchToHeight(height); 141e14391e94c850b8bd03680c23b38978db68687a8John Reck setNeedsLayout(true); 142dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 143dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 144dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 145dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid RenderMathMLUnderOver::layout() 146dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 147dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderBlock::layout(); 148dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderObject* over = 0; 149dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderObject* base = 0; 150dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block switch (m_kind) { 151dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block case Over: 152dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // We need to calculate the baseline over the over versus the start of the base and 153dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // adjust the placement of the base. 154dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block over = firstChild(); 155dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (over) { 156dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // FIXME: descending glyphs intrude into base (e.g. lowercase y over base) 157dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // FIXME: bases that ascend higher than the line box intrude into the over 158a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!over->firstChild()->isBoxModelObject()) 159a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch break; 160a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 1616b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner int overSpacing = static_cast<int>(gOverSpacingAdjustment * (getOffsetHeight(over) - toRenderBoxModelObject(over->firstChild())->baselinePosition(AlphabeticBaseline, true, HorizontalLine))); 162dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 163dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // base row wrapper 164dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block base = over->nextSibling(); 165dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (base) { 166dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (overSpacing > 0) 167dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block base->style()->setMarginTop(Length(-overSpacing, Fixed)); 168dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block else 169dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block base->style()->setMarginTop(Length(0, Fixed)); 170dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 171dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 172dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 173dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block break; 174dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block case Under: 175dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // FIXME: Non-ascending glyphs in the under should be moved closer to the base 176dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 177dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // We need to calculate the baseline of the base versus the start of the under block and 178dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // adjust the placement of the under block. 179dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 180dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // base row wrapper 181dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block base = firstChild(); 182dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (base) { 183dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block int baseHeight = getOffsetHeight(base); 184dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // actual base 185dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block base = base->firstChild(); 186a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!base->isBoxModelObject()) 187a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch break; 188a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 189dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // FIXME: We need to look at the space between a single maximum height of 190dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // the line boxes and the baseline and squeeze them together 1916b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner int underSpacing = baseHeight - toRenderBoxModelObject(base)->baselinePosition(AlphabeticBaseline, true, HorizontalLine); 192dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 193dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // adjust the base's intrusion into the under 194dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderObject* under = lastChild(); 195dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (under && underSpacing > 0) 196dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block under->style()->setMarginTop(Length(-underSpacing, Fixed)); 197dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 198dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block break; 199dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block case UnderOver: 200dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // FIXME: Non-descending glyphs in the over should be moved closer to the base 201dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // FIXME: Non-ascending glyphs in the under should be moved closer to the base 202dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 203dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // We need to calculate the baseline of the over versus the start of the base and 204dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // adjust the placement of the base. 205dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 206dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block over = firstChild(); 207dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (over) { 208dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // FIXME: descending glyphs intrude into base (e.g. lowercase y over base) 209dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // FIXME: bases that ascend higher than the line box intrude into the over 210a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!over->firstChild()->isBoxModelObject()) 211a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch break; 2126b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner int overSpacing = static_cast<int>(gOverSpacingAdjustment * (getOffsetHeight(over) - toRenderBoxModelObject(over->firstChild())->baselinePosition(AlphabeticBaseline, true, HorizontalLine))); 213dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 214dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // base row wrapper 215dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block base = over->nextSibling(); 216dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 217dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (base) { 218dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (overSpacing > 0) 219dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block base->style()->setMarginTop(Length(-overSpacing, Fixed)); 220dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 221dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // We need to calculate the baseline of the base versus the start of the under block and 222dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // adjust the placement of the under block. 223dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 224dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block int baseHeight = getOffsetHeight(base); 225dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // actual base 226dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block base = base->firstChild(); 227a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!base->isBoxModelObject()) 228a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch break; 229a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 230dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // FIXME: We need to look at the space between a single maximum height of 231dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // the line boxes and the baseline and squeeze them together 2326b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner int underSpacing = baseHeight - toRenderBoxModelObject(base)->baselinePosition(AlphabeticBaseline, true, HorizontalLine); 233dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 234dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderObject* under = lastChild(); 235dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (under && under->firstChild()->isRenderInline() && underSpacing > 0) 236dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block under->style()->setMarginTop(Length(-underSpacing, Fixed)); 237dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 238dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 239dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 240dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block break; 241dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 242e14391e94c850b8bd03680c23b38978db68687a8John Reck setNeedsLayout(true); 243dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderBlock::layout(); 244dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 245dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 2466b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerint RenderMathMLUnderOver::baselinePosition(FontBaseline, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const 247dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 248e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block RenderObject* current = firstChild(); 249e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block if (!current) 2506b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return RenderBlock::baselinePosition(AlphabeticBaseline, firstLine, direction, linePositionMode); 251e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block 252dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block int baseline = 0; 253dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block switch (m_kind) { 254dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block case UnderOver: 255dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block case Over: 256dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block baseline += getOffsetHeight(current); 257dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block current = current->nextSibling(); 258dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (current) { 259dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // actual base 260dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderObject* base = current->firstChild(); 261a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!base || !base->isBoxModelObject()) 262e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block break; 2636b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner baseline += toRenderBoxModelObject(base)->baselinePosition(AlphabeticBaseline, firstLine, HorizontalLine, linePositionMode); 264dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // added the negative top margin 265dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block baseline += current->style()->marginTop().value(); 266dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 267dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block break; 268dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block case Under: 269e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block RenderObject* base = current->firstChild(); 270a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (base && base->isBoxModelObject()) 2716b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner baseline += toRenderBoxModelObject(base)->baselinePosition(AlphabeticBaseline, true, HorizontalLine); 272dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 273e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block 274e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block // FIXME: Where is the extra 2-3px adjusted for zoom coming from? 275e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block float zoomFactor = style()->effectiveZoom(); 276e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block baseline += static_cast<int>((zoomFactor > 1.25 ? 2 : 3) * zoomFactor); 277dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return baseline; 278dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 279dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 280dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 281dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockint RenderMathMLUnderOver::nonOperatorHeight() const 282dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 283e14391e94c850b8bd03680c23b38978db68687a8John Reck int nonOperators = 0; 284e14391e94c850b8bd03680c23b38978db68687a8John Reck for (RenderObject* current = firstChild(); current; current = current->nextSibling()) { 285e14391e94c850b8bd03680c23b38978db68687a8John Reck if (current->firstChild()->isRenderMathMLBlock()) { 286e14391e94c850b8bd03680c23b38978db68687a8John Reck RenderMathMLBlock* block = toRenderMathMLBlock(current->firstChild()); 287e14391e94c850b8bd03680c23b38978db68687a8John Reck if (!block->isRenderMathMLOperator()) 288e14391e94c850b8bd03680c23b38978db68687a8John Reck nonOperators += getOffsetHeight(current); 289e14391e94c850b8bd03680c23b38978db68687a8John Reck } else { 290e14391e94c850b8bd03680c23b38978db68687a8John Reck nonOperators += getOffsetHeight(current); 291e14391e94c850b8bd03680c23b38978db68687a8John Reck } 292e14391e94c850b8bd03680c23b38978db68687a8John Reck } 293e14391e94c850b8bd03680c23b38978db68687a8John Reck return nonOperators; 294dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 295dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 296dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 297dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 298dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 299dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#endif // ENABLE(MATHML) 300