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 "RenderMathMLSubSup.h" 31dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 32dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "FontSelector.h" 33dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "MathMLNames.h" 34dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "RenderInline.h" 35dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "RenderTable.h" 36dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "RenderTableCell.h" 37dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "RenderTableRow.h" 38dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "RenderTableSection.h" 39dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "RenderText.h" 40dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 41dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocknamespace WebCore { 42dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 43dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockusing namespace MathMLNames; 44dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 45dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockstatic const int gTopAdjustDivisor = 3; 46dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockstatic const int gSubsupScriptMargin = 1; 47dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochstatic const float gSubSupStretch = 1.2f; 48dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 49dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockRenderMathMLSubSup::RenderMathMLSubSup(Element* element) 50dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block : RenderMathMLBlock(element) 51dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block , m_scripts(0) 52dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 53dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // Determine what kind of under/over expression we have by element name 54dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (element->hasLocalName(MathMLNames::msubTag)) 55dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_kind = Sub; 56dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block else if (element->hasLocalName(MathMLNames::msupTag)) 57dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_kind = Sup; 58dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block else if (element->hasLocalName(MathMLNames::msubsupTag)) 59dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_kind = SubSup; 60dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block else 61dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_kind = SubSup; 62dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 63dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 64dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid RenderMathMLSubSup::addChild(RenderObject* child, RenderObject* beforeChild) 65dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 66dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (firstChild()) { 67dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // We already have a base, so this is the super/subscripts being added. 68dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 69dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (m_kind == SubSup) { 70dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!m_scripts) { 71dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_scripts = new (renderArena()) RenderMathMLBlock(node()); 72dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RefPtr<RenderStyle> scriptsStyle = RenderStyle::create(); 73dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block scriptsStyle->inheritFrom(style()); 74dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block scriptsStyle->setDisplay(INLINE_BLOCK); 7506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen scriptsStyle->setVerticalAlign(TOP); 76dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block scriptsStyle->setMarginLeft(Length(gSubsupScriptMargin, Fixed)); 77dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block scriptsStyle->setTextAlign(LEFT); 78dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_scripts->setStyle(scriptsStyle.release()); 79dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderMathMLBlock::addChild(m_scripts, beforeChild); 80dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 81dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 82dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderBlock* script = new (renderArena()) RenderMathMLBlock(node()); 83dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RefPtr<RenderStyle> scriptStyle = RenderStyle::create(); 84dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block scriptStyle->inheritFrom(m_scripts->style()); 85dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block scriptStyle->setDisplay(BLOCK); 86dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block script->setStyle(scriptStyle.release()); 87dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 88dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_scripts->addChild(script, m_scripts->firstChild()); 89dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block script->addChild(child); 90dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } else 91dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderMathMLBlock::addChild(child, beforeChild); 92dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 93dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } else { 94dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderMathMLBlock* wrapper = new (renderArena()) RenderMathMLBlock(node()); 95dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RefPtr<RenderStyle> wrapperStyle = RenderStyle::create(); 96dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block wrapperStyle->inheritFrom(style()); 97dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block wrapperStyle->setDisplay(INLINE_BLOCK); 98e14391e94c850b8bd03680c23b38978db68687a8John Reck wrapperStyle->setVerticalAlign(BASELINE); 99dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block wrapper->setStyle(wrapperStyle.release()); 100dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderMathMLBlock::addChild(wrapper, beforeChild); 101dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block wrapper->addChild(child); 102e14391e94c850b8bd03680c23b38978db68687a8John Reck 103dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 104dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 105dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 106ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Blockvoid RenderMathMLSubSup::stretchToHeight(int height) 107dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 108dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderObject* base = firstChild(); 109dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!base) 110dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return; 111dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 112ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block if (base->firstChild()->isRenderMathMLBlock()) { 113ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block RenderMathMLBlock* block = toRenderMathMLBlock(base->firstChild()); 114dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block block->stretchToHeight(static_cast<int>(gSubSupStretch * height)); 115e14391e94c850b8bd03680c23b38978db68687a8John Reck 116e14391e94c850b8bd03680c23b38978db68687a8John Reck // Adjust the script placement after we stretch 117ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block if (height > 0 && m_kind == SubSup && m_scripts) { 118ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block RenderObject* script = m_scripts->firstChild(); 119ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block if (script) { 120ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block // Calculate the script height without the container margins. 121ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block RenderObject* top = script; 122ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block int topHeight = getBoxModelObjectHeight(top->firstChild()); 123ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block int topAdjust = topHeight / gTopAdjustDivisor; 124ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block top->style()->setMarginTop(Length(-topAdjust, Fixed)); 125ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block top->style()->setMarginBottom(Length(height - topHeight + topAdjust, Fixed)); 126ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block if (top->isBoxModelObject()) { 127ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block RenderBoxModelObject* topBox = toRenderBoxModelObject(top); 128ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block topBox->updateBoxModelInfoFromStyle(); 129ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block } 130e14391e94c850b8bd03680c23b38978db68687a8John Reck m_scripts->setNeedsLayout(true); 131e14391e94c850b8bd03680c23b38978db68687a8John Reck setNeedsLayout(true); 132dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 133dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 134e14391e94c850b8bd03680c23b38978db68687a8John Reck 135dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 136dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 137dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 138dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockint RenderMathMLSubSup::nonOperatorHeight() const 139dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 140e14391e94c850b8bd03680c23b38978db68687a8John Reck if (m_kind == SubSup) 141e14391e94c850b8bd03680c23b38978db68687a8John Reck return static_cast<int>(style()->fontSize()*gSubSupStretch); 142e14391e94c850b8bd03680c23b38978db68687a8John Reck return static_cast<int>(style()->fontSize()); 143dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 144dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 145dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid RenderMathMLSubSup::layout() 146dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 147e14391e94c850b8bd03680c23b38978db68687a8John Reck if (firstChild()) 148e14391e94c850b8bd03680c23b38978db68687a8John Reck firstChild()->setNeedsLayout(true); 149e14391e94c850b8bd03680c23b38978db68687a8John Reck if (m_scripts) 150e14391e94c850b8bd03680c23b38978db68687a8John Reck m_scripts->setNeedsLayout(true); 151e14391e94c850b8bd03680c23b38978db68687a8John Reck 152dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderBlock::layout(); 153dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 154dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (m_kind == SubSup) { 155f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (RenderObject* base = firstChild()) { 15606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen int maxHeight = 0; 15706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen RenderObject* current = base->firstChild(); 15806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen while (current) { 15906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen int height = getBoxModelObjectHeight(current); 16006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen if (height > maxHeight) 16106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen maxHeight = height; 16206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen current = current->nextSibling(); 16306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen } 1645ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen int heightDiff = m_scripts ? (m_scripts->offsetHeight() - maxHeight) / 2 : 0; 16506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen if (heightDiff < 0) 16606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen heightDiff = 0; 167e14391e94c850b8bd03680c23b38978db68687a8John Reck base->style()->setPaddingTop(Length(heightDiff, Fixed)); 168f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch base->setNeedsLayout(true); 169dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 170e14391e94c850b8bd03680c23b38978db68687a8John Reck setNeedsLayout(true); 171dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderBlock::layout(); 172dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 173dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 174dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 1756b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerint RenderMathMLSubSup::baselinePosition(FontBaseline, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const 176dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 177dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderObject* base = firstChild(); 178dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!base) 179dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return offsetHeight(); 180dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 181dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block int baseline = offsetHeight(); 182a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!base || !base->isBoxModelObject()) 183a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return baseline; 184a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 185dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block switch (m_kind) { 186dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block case SubSup: 187e14391e94c850b8bd03680c23b38978db68687a8John Reck base = base->firstChild(); 188e14391e94c850b8bd03680c23b38978db68687a8John Reck if (m_scripts && base->isBoxModelObject()) { 189e14391e94c850b8bd03680c23b38978db68687a8John Reck RenderBoxModelObject* box = toRenderBoxModelObject(base); 190e14391e94c850b8bd03680c23b38978db68687a8John Reck 191a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch int topAdjust = (m_scripts->offsetHeight() - box->offsetHeight()) / 2; 192a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 19306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen // FIXME: The last bit of this calculation should be more exact. Why is the 2-3px scaled for zoom necessary? 19406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen // The baseline is top spacing of the base + the baseline of the base + adjusted space for zoom 19506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen float zoomFactor = style()->effectiveZoom(); 1966b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return topAdjust + box->baselinePosition(AlphabeticBaseline, firstLine, direction, linePositionMode) + static_cast<int>((zoomFactor > 1.25 ? 2 : 3) * zoomFactor); 197dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 198dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block break; 199e14391e94c850b8bd03680c23b38978db68687a8John Reck case Sup: 200dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block case Sub: 201e14391e94c850b8bd03680c23b38978db68687a8John Reck RenderBoxModelObject* box = toRenderBoxModelObject(base); 2026b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner baseline = box->baselinePosition(AlphabeticBaseline, firstLine, direction, linePositionMode); 203a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch break; 204dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 205dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 206dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return baseline; 207dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 208dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 209dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 210dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 211dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 212dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#endif // ENABLE(MATHML) 213