1dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch/* 2dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved. 3dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * 4dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * Redistribution and use in source and binary forms, with or without 5dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * modification, are permitted provided that the following conditions 6dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * are met: 7dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * 1. Redistributions of source code must retain the above copyright 8dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * notice, this list of conditions and the following disclaimer. 9dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * 2. Redistributions in binary form must reproduce the above copyright 10dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * notice, this list of conditions and the following disclaimer in the 11dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * documentation and/or other materials provided with the distribution. 12dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * 13dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 14dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 15dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 16dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 17dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch */ 25dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 26dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#include "config.h" 27dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 28dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#if ENABLE(MATHML) 29dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 30dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#include "RenderMathMLFenced.h" 31dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 32dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#include "FontSelector.h" 33dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#include "MathMLNames.h" 34dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#include "RenderInline.h" 35dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#include "RenderMathMLOperator.h" 36dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#include "RenderText.h" 37dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 38dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochnamespace WebCore { 39dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 40dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochusing namespace MathMLNames; 41dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 42dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochenum Braces { OpeningBraceChar = 0x28, ClosingBraceChar = 0x29 }; 43a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 44a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochstatic const float gOperatorPadding = 0.1f; 45dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 46dd8bb3de4f353a81954234999f1fea748aee2ea9Ben MurdochRenderMathMLFenced::RenderMathMLFenced(Node* fenced) 47dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch : RenderMathMLRow(fenced) 48dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch , m_open(OpeningBraceChar) 49dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch , m_close(ClosingBraceChar) 50dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch{ 51dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch} 52dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 53dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochvoid RenderMathMLFenced::updateFromElement() 54dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch{ 55dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch Element* fenced = static_cast<Element*>(node()); 56dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 57dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch // FIXME: Handle open/close values with more than one character (they should be treated like text). 58dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch AtomicString openValue = fenced->getAttribute(MathMLNames::openAttr); 59dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (openValue.length() > 0) 60dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_open = openValue[0]; 61dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch AtomicString closeValue = fenced->getAttribute(MathMLNames::closeAttr); 62dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (closeValue.length() > 0) 63dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_close = closeValue[0]; 64dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 65dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch AtomicString separators = static_cast<Element*>(fenced)->getAttribute(MathMLNames::separatorsAttr); 66dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (!separators.isNull()) { 67dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch Vector<UChar> characters; 68dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch for (unsigned int i = 0; i < separators.length(); i++) { 69dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (!isSpaceOrNewline(separators[i])) 70dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch characters.append(separators[i]); 71dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 72a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_separators = !characters.size() ? 0 : StringImpl::create(characters.data() , characters.size()); 73dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } else { 74dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch // The separator defaults to a single comma. 75dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_separators = StringImpl::create(","); 76dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 77dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 78dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (isEmpty()) 79dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch makeFences(); 80dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch} 81dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 82dd8bb3de4f353a81954234999f1fea748aee2ea9Ben MurdochRefPtr<RenderStyle> RenderMathMLFenced::makeOperatorStyle() 83dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch{ 84dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch RefPtr<RenderStyle> newStyle = RenderStyle::create(); 85dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch newStyle->inheritFrom(style()); 86dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch newStyle->setDisplay(INLINE_BLOCK); 87a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch newStyle->setPaddingRight(Length(static_cast<int>(gOperatorPadding * style()->fontSize()), Fixed)); 88dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return newStyle; 89dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch} 90dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 91dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochvoid RenderMathMLFenced::makeFences() 92dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch{ 93dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch RenderObject* openFence = new (renderArena()) RenderMathMLOperator(node(), m_open); 94dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch openFence->setStyle(makeOperatorStyle().release()); 95dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch RenderBlock::addChild(openFence, firstChild()); 96dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch RenderObject* closeFence = new (renderArena()) RenderMathMLOperator(node(), m_close); 97dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch closeFence->setStyle(makeOperatorStyle().release()); 98dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch RenderBlock::addChild(closeFence); 99dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch} 100dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 101dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochvoid RenderMathMLFenced::addChild(RenderObject* child, RenderObject*) 102dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch{ 103dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch // make the fences if the render object is empty 104dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (isEmpty()) 105dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch updateFromElement(); 106dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 107dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (m_separators.get()) { 108dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch unsigned int count = 0; 109dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch for (Node* position = child->node(); position; position = position->previousSibling()) { 110dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (position->nodeType() == Node::ELEMENT_NODE) 111dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch count++; 112dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 113dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 114dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (count > 1) { 115dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch UChar separator; 116dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 117dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch // Use the last separator if we've run out of specified separators. 118dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if ((count - 1) >= m_separators.get()->length()) 119dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch separator = (*m_separators.get())[m_separators.get()->length() - 1]; 120dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch else 121dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch separator = (*m_separators.get())[count - 1]; 122dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 123dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch RenderObject* separatorObj = new (renderArena()) RenderMathMLOperator(node(), separator); 124dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch separatorObj->setStyle(makeOperatorStyle().release()); 125dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch RenderBlock::addChild(separatorObj, lastChild()); 126dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 127dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 128dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 129dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch // If we have a block, we'll wrap it in an inline-block. 130dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (child->isBlockFlow() && child->style()->display() != INLINE_BLOCK) { 131dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch // Block objects wrapper. 132dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 133dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch RenderBlock* block = new (renderArena()) RenderBlock(node()); 134dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch RefPtr<RenderStyle> newStyle = RenderStyle::create(); 135dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch newStyle->inheritFrom(style()); 136dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch newStyle->setDisplay(INLINE_BLOCK); 137dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch block->setStyle(newStyle.release()); 138dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 139dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch RenderBlock::addChild(block, lastChild()); 140dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch block->addChild(child); 141dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } else 142dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch RenderBlock::addChild(child, lastChild()); 143dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch} 144dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 145dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch} 146dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 147dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#endif 148