diff options
author | Steve Block <steveblock@google.com> | 2011-05-06 11:45:16 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2011-05-12 13:44:10 +0100 |
commit | cad810f21b803229eb11403f9209855525a25d57 (patch) | |
tree | 29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/mathml | |
parent | 121b0cf4517156d0ac5111caf9830c51b69bae8f (diff) | |
download | external_webkit-cad810f21b803229eb11403f9209855525a25d57.zip external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2 |
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'Source/WebCore/mathml')
30 files changed, 3089 insertions, 0 deletions
diff --git a/Source/WebCore/mathml/MathMLElement.cpp b/Source/WebCore/mathml/MathMLElement.cpp new file mode 100644 index 0000000..6088810 --- /dev/null +++ b/Source/WebCore/mathml/MathMLElement.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved. + * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 François Sausset (sausset@gmail.com). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(MATHML) + +#include "MathMLElement.h" + +#include "MathMLNames.h" +#include "RenderObject.h" + +namespace WebCore { + +using namespace MathMLNames; + +MathMLElement::MathMLElement(const QualifiedName& tagName, Document* document) + : StyledElement(tagName, document, CreateStyledElement) +{ +} + +PassRefPtr<MathMLElement> MathMLElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new MathMLElement(tagName, document)); +} + +bool MathMLElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const +{ + if (attrName == mathcolorAttr || attrName == mathbackgroundAttr + || attrName == colorAttr || attrName == backgroundAttr + || attrName == fontsizeAttr || attrName == fontstyleAttr + || attrName == fontweightAttr || attrName == fontfamilyAttr) { + result = eMathML; + return false; + } + return StyledElement::mapToEntry(attrName, result); +} + +void MathMLElement::parseMappedAttribute(Attribute* attr) +{ + if (attr->name() == mathbackgroundAttr) + addCSSProperty(attr, CSSPropertyBackgroundColor, attr->value()); + else if (attr->name() == mathsizeAttr) { + // The following three values of mathsize are handled in WebCore/css/mathml.css + if (attr->value() != "normal" && attr->value() != "small" && attr->value() != "big") + addCSSProperty(attr, CSSPropertyFontSize, attr->value()); + } else if (attr->name() == mathcolorAttr) + addCSSProperty(attr, CSSPropertyColor, attr->value()); + // FIXME: deprecated attributes that should loose in a conflict with a non deprecated attribute + else if (attr->name() == fontsizeAttr) + addCSSProperty(attr, CSSPropertyFontSize, attr->value()); + else if (attr->name() == backgroundAttr) + addCSSProperty(attr, CSSPropertyBackgroundColor, attr->value()); + else if (attr->name() == colorAttr) + addCSSProperty(attr, CSSPropertyColor, attr->value()); + else if (attr->name() == fontstyleAttr) + addCSSProperty(attr, CSSPropertyFontStyle, attr->value()); + else if (attr->name() == fontweightAttr) + addCSSProperty(attr, CSSPropertyFontWeight, attr->value()); + else if (attr->name() == fontfamilyAttr) + addCSSProperty(attr, CSSPropertyFontFamily, attr->value()); + else + StyledElement::parseMappedAttribute(attr); +} + +} + +#endif // ENABLE(MATHML) diff --git a/Source/WebCore/mathml/MathMLElement.h b/Source/WebCore/mathml/MathMLElement.h new file mode 100644 index 0000000..7678f26 --- /dev/null +++ b/Source/WebCore/mathml/MathMLElement.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved. + * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 François Sausset (sausset@gmail.com). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MathMLElement_h +#define MathMLElement_h + +#if ENABLE(MATHML) +#include "StyledElement.h" + +namespace WebCore { + +class MathMLElement : public StyledElement { +public: + static PassRefPtr<MathMLElement> create(const QualifiedName& tagName, Document*); + +protected: + MathMLElement(const QualifiedName& tagName, Document*); + +private: + virtual bool isMathMLElement() const { return true; } + virtual bool mapToEntry(const QualifiedName&, MappedAttributeEntry&) const; + virtual void parseMappedAttribute(Attribute*); +}; + +} + +#endif // ENABLE(MATHML) +#endif // MathMLElement_h diff --git a/Source/WebCore/mathml/MathMLInlineContainerElement.cpp b/Source/WebCore/mathml/MathMLInlineContainerElement.cpp new file mode 100644 index 0000000..eb579d2 --- /dev/null +++ b/Source/WebCore/mathml/MathMLInlineContainerElement.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved. + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(MATHML) + +#include "MathMLInlineContainerElement.h" + +#include "MathMLNames.h" +#include "RenderMathMLBlock.h" +#include "RenderMathMLFenced.h" +#include "RenderMathMLFraction.h" +#include "RenderMathMLRoot.h" +#include "RenderMathMLRow.h" +#include "RenderMathMLSquareRoot.h" +#include "RenderMathMLSubSup.h" +#include "RenderMathMLUnderOver.h" + +namespace WebCore { + +using namespace MathMLNames; + +MathMLInlineContainerElement::MathMLInlineContainerElement(const QualifiedName& tagName, Document* document) + : MathMLElement(tagName, document) +{ +} + +PassRefPtr<MathMLInlineContainerElement> MathMLInlineContainerElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new MathMLInlineContainerElement(tagName, document)); +} + +RenderObject* MathMLInlineContainerElement::createRenderer(RenderArena* arena, RenderStyle*) +{ + if (hasLocalName(mrowTag)) + return new (arena) RenderMathMLRow(this); + if (hasLocalName(msubTag)) + return new (arena) RenderMathMLSubSup(this); + if (hasLocalName(msupTag)) + return new (arena) RenderMathMLSubSup(this); + if (hasLocalName(msubsupTag)) + return new (arena) RenderMathMLSubSup(this); + if (hasLocalName(moverTag)) + return new (arena) RenderMathMLUnderOver(this); + if (hasLocalName(munderTag)) + return new (arena) RenderMathMLUnderOver(this); + if (hasLocalName(munderoverTag)) + return new (arena) RenderMathMLUnderOver(this); + if (hasLocalName(mfracTag)) + return new (arena) RenderMathMLFraction(this); + if (hasLocalName(msqrtTag)) + return new (arena) RenderMathMLSquareRoot(this); + if (hasLocalName(mrootTag)) + return new (arena) RenderMathMLRoot(this); + if (hasLocalName(mfencedTag)) + return new (arena) RenderMathMLFenced(this); + + return new (arena) RenderMathMLBlock(this); +} + +} + +#endif // ENABLE(MATHML) diff --git a/Source/WebCore/mathml/MathMLInlineContainerElement.h b/Source/WebCore/mathml/MathMLInlineContainerElement.h new file mode 100644 index 0000000..4e80e36 --- /dev/null +++ b/Source/WebCore/mathml/MathMLInlineContainerElement.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved. + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MathMLInlineContainerElement_h +#define MathMLInlineContainerElement_h + +#if ENABLE(MATHML) +#include "MathMLElement.h" + +namespace WebCore { + +class MathMLInlineContainerElement : public MathMLElement { +public: + static PassRefPtr<MathMLInlineContainerElement> create(const QualifiedName& tagName, Document*); + +protected: + MathMLInlineContainerElement(const QualifiedName& tagName, Document*); + +private: + virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); +}; + +} + +#endif // ENABLE(MATHML) +#endif // MathMLInlineContainerElement_h diff --git a/Source/WebCore/mathml/MathMLMathElement.cpp b/Source/WebCore/mathml/MathMLMathElement.cpp new file mode 100644 index 0000000..6c5c3c6 --- /dev/null +++ b/Source/WebCore/mathml/MathMLMathElement.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved. + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(MATHML) + +#include "MathMLMathElement.h" + +#include "RenderMathMLMath.h" + +namespace WebCore { + +inline MathMLMathElement::MathMLMathElement(const QualifiedName& tagName, Document* document) + : MathMLInlineContainerElement(tagName, document) +{ +} + +PassRefPtr<MathMLMathElement> MathMLMathElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new MathMLMathElement(tagName, document)); +} + +RenderObject* MathMLMathElement::createRenderer(RenderArena* arena, RenderStyle*) +{ + return new (arena) RenderMathMLMath(this); +} + +} + +#endif // ENABLE(MATHML) diff --git a/Source/WebCore/mathml/MathMLMathElement.h b/Source/WebCore/mathml/MathMLMathElement.h new file mode 100644 index 0000000..d31d548 --- /dev/null +++ b/Source/WebCore/mathml/MathMLMathElement.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved. + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MathMLMathElement_h +#define MathMLMathElement_h + +#if ENABLE(MATHML) +#include "MathMLInlineContainerElement.h" + +namespace WebCore { + +class MathMLMathElement : public MathMLInlineContainerElement { +public: + static PassRefPtr<MathMLMathElement> create(const QualifiedName& tagName, Document*); + +private: + MathMLMathElement(const QualifiedName& tagName, Document*); + + virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); +}; + +} + +#endif // ENABLE(MATHML) +#endif // MathMLMathElement_h diff --git a/Source/WebCore/mathml/MathMLTextElement.cpp b/Source/WebCore/mathml/MathMLTextElement.cpp new file mode 100644 index 0000000..8f830cb --- /dev/null +++ b/Source/WebCore/mathml/MathMLTextElement.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved. + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(MATHML) + +#include "MathMLTextElement.h" + +#include "MathMLNames.h" +#include "RenderMathMLOperator.h" + +namespace WebCore { + +using namespace MathMLNames; + +inline MathMLTextElement::MathMLTextElement(const QualifiedName& tagName, Document* document) + : MathMLElement(tagName, document) +{ +} + +PassRefPtr<MathMLTextElement> MathMLTextElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new MathMLTextElement(tagName, document)); +} + +RenderObject* MathMLTextElement::createRenderer(RenderArena* arena, RenderStyle* style) +{ + if (hasLocalName(MathMLNames::moTag)) + return new (arena) RenderMathMLOperator(this); + + return MathMLElement::createRenderer(arena, style); +} + +} + +#endif // ENABLE(MATHML) diff --git a/Source/WebCore/mathml/MathMLTextElement.h b/Source/WebCore/mathml/MathMLTextElement.h new file mode 100644 index 0000000..3af93d5 --- /dev/null +++ b/Source/WebCore/mathml/MathMLTextElement.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved. + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MathMLTextElement_h +#define MathMLTextElement_h + +#if ENABLE(MATHML) +#include "MathMLElement.h" + +namespace WebCore { + +class MathMLTextElement : public MathMLElement { +public: + static PassRefPtr<MathMLTextElement> create(const QualifiedName& tagName, Document*); + +private: + MathMLTextElement(const QualifiedName& tagName, Document*); + + virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); +}; + +} + +#endif // ENABLE(MATHML) +#endif // MathMLTextElement_h diff --git a/Source/WebCore/mathml/RenderMathMLBlock.cpp b/Source/WebCore/mathml/RenderMathMLBlock.cpp new file mode 100644 index 0000000..14e7656 --- /dev/null +++ b/Source/WebCore/mathml/RenderMathMLBlock.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(MATHML) + +#include "RenderMathMLBlock.h" + +#include "FontSelector.h" +#include "GraphicsContext.h" +#include "MathMLNames.h" +#include "RenderInline.h" +#include "RenderText.h" + +namespace WebCore { + +using namespace MathMLNames; + +RenderMathMLBlock::RenderMathMLBlock(Node* container) + : RenderBlock(container) +{ +} + +bool RenderMathMLBlock::isChildAllowed(RenderObject* child, RenderStyle*) const +{ + return child->node() && child->node()->nodeType() == Node::ELEMENT_NODE; +} + +PassRefPtr<RenderStyle> RenderMathMLBlock::makeBlockStyle() +{ + RefPtr<RenderStyle> newStyle = RenderStyle::create(); + newStyle->inheritFrom(style()); + newStyle->setDisplay(BLOCK); + return newStyle; +} + +int RenderMathMLBlock::nonOperatorHeight() const +{ + if (!isRenderMathMLOperator()) + return offsetHeight(); + + return 0; +} + +void RenderMathMLBlock::stretchToHeight(int height) +{ + for (RenderObject* current = firstChild(); current; current = current->nextSibling()) + if (current->isRenderMathMLBlock()) { + RenderMathMLBlock* block = toRenderMathMLBlock(current); + block->stretchToHeight(height); + } +} + +#if ENABLE(DEBUG_MATH_LAYOUT) +void RenderMathMLBlock::paint(PaintInfo& info, int tx, int ty) +{ + RenderBlock::paint(info, tx, ty); + + if (info.context->paintingDisabled() || info.phase != PaintPhaseForeground) + return; + + tx += x(); + ty += y(); + + info.context->save(); + + info.context->setStrokeThickness(1.0f); + info.context->setStrokeStyle(SolidStroke); + info.context->setStrokeColor(Color(0, 0, 255), ColorSpaceSRGB); + + info.context->drawLine(IntPoint(tx, ty), IntPoint(tx + offsetWidth(), ty)); + info.context->drawLine(IntPoint(tx + offsetWidth(), ty), IntPoint(tx + offsetWidth(), ty + offsetHeight())); + info.context->drawLine(IntPoint(tx, ty + offsetHeight()), IntPoint(tx + offsetWidth(), ty + offsetHeight())); + info.context->drawLine(IntPoint(tx, ty), IntPoint(tx, ty + offsetHeight())); + + int topStart = paddingTop(); + + info.context->setStrokeColor(Color(0, 255, 0), ColorSpaceSRGB); + + info.context->drawLine(IntPoint(tx, ty + topStart), IntPoint(tx + offsetWidth(), ty + topStart)); + + int baseline = baselinePosition(AlphabeticBaseline, true, HorizontalLine); + + info.context->setStrokeColor(Color(255, 0, 0), ColorSpaceSRGB); + + info.context->drawLine(IntPoint(tx, ty + baseline), IntPoint(tx + offsetWidth(), ty + baseline)); + + info.context->restore(); + +} +#endif // ENABLE(DEBUG_MATH_LAYOUT) + + +} + +#endif diff --git a/Source/WebCore/mathml/RenderMathMLBlock.h b/Source/WebCore/mathml/RenderMathMLBlock.h new file mode 100644 index 0000000..f05122a --- /dev/null +++ b/Source/WebCore/mathml/RenderMathMLBlock.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2010 Alex Milowski (alex@milowski.com). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RenderMathMLBlock_h +#define RenderMathMLBlock_h + +#if ENABLE(MATHML) + +#include "RenderBlock.h" + +#define ENABLE_DEBUG_MATH_LAYOUT 0 + +namespace WebCore { + +class RenderMathMLBlock : public RenderBlock { +public: + RenderMathMLBlock(Node* container); + virtual bool isChildAllowed(RenderObject*, RenderStyle*) const; + + virtual bool isRenderMathMLBlock() const { return true; } + virtual bool isRenderMathMLOperator() const { return false; } + virtual bool isRenderMathMLRow() const { return false; } + virtual bool isRenderMathMLMath() const { return false; } + virtual bool hasBase() const { return false; } + virtual int nonOperatorHeight() const; + virtual void stretchToHeight(int height); + +#if ENABLE(DEBUG_MATH_LAYOUT) + virtual void paint(PaintInfo&, int tx, int ty); +#endif + +protected: + int getBoxModelObjectHeight(RenderObject* object) + { + if (object && object->isBoxModelObject()) { + RenderBoxModelObject* box = toRenderBoxModelObject(object); + return box->offsetHeight(); + } + + return 0; + } + int getBoxModelObjectHeight(const RenderObject* object) + { + if (object && object->isBoxModelObject()) { + const RenderBoxModelObject* box = toRenderBoxModelObject(object); + return box->offsetHeight(); + } + + return 0; + } + int getBoxModelObjectWidth(RenderObject* object) + { + if (object && object->isBoxModelObject()) { + RenderBoxModelObject* box = toRenderBoxModelObject(object); + return box->offsetWidth(); + } + + return 0; + } + int getBoxModelObjectWidth(const RenderObject* object) + { + if (object && object->isBoxModelObject()) { + const RenderBoxModelObject* box = toRenderBoxModelObject(object); + return box->offsetWidth(); + } + + return 0; + } + virtual PassRefPtr<RenderStyle> makeBlockStyle(); + +}; + +inline RenderMathMLBlock* toRenderMathMLBlock(RenderObject* object) +{ + ASSERT(!object || object->isRenderMathMLBlock()); + return static_cast<RenderMathMLBlock*>(object); +} + +inline const RenderMathMLBlock* toRenderMathMLBlock(const RenderObject* object) +{ + ASSERT(!object || object->isRenderMathMLBlock()); + return static_cast<const RenderMathMLBlock*>(object); +} + +} + + +#endif // ENABLE(MATHML) +#endif // RenderMathMLBlock_h diff --git a/Source/WebCore/mathml/RenderMathMLFenced.cpp b/Source/WebCore/mathml/RenderMathMLFenced.cpp new file mode 100644 index 0000000..f7bbf71 --- /dev/null +++ b/Source/WebCore/mathml/RenderMathMLFenced.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(MATHML) + +#include "RenderMathMLFenced.h" + +#include "FontSelector.h" +#include "MathMLNames.h" +#include "RenderInline.h" +#include "RenderMathMLOperator.h" +#include "RenderText.h" + +namespace WebCore { + +using namespace MathMLNames; + +enum Braces { OpeningBraceChar = 0x28, ClosingBraceChar = 0x29 }; + +static const float gOperatorPadding = 0.1f; + +RenderMathMLFenced::RenderMathMLFenced(Node* fenced) + : RenderMathMLRow(fenced) + , m_open(OpeningBraceChar) + , m_close(ClosingBraceChar) +{ +} + +void RenderMathMLFenced::updateFromElement() +{ + Element* fenced = static_cast<Element*>(node()); + + // FIXME: Handle open/close values with more than one character (they should be treated like text). + AtomicString openValue = fenced->getAttribute(MathMLNames::openAttr); + if (openValue.length() > 0) + m_open = openValue[0]; + AtomicString closeValue = fenced->getAttribute(MathMLNames::closeAttr); + if (closeValue.length() > 0) + m_close = closeValue[0]; + + AtomicString separators = static_cast<Element*>(fenced)->getAttribute(MathMLNames::separatorsAttr); + if (!separators.isNull()) { + Vector<UChar> characters; + for (unsigned int i = 0; i < separators.length(); i++) { + if (!isSpaceOrNewline(separators[i])) + characters.append(separators[i]); + } + m_separators = !characters.size() ? 0 : StringImpl::create(characters.data() , characters.size()); + } else { + // The separator defaults to a single comma. + m_separators = StringImpl::create(","); + } + + if (isEmpty()) + makeFences(); +} + +RefPtr<RenderStyle> RenderMathMLFenced::makeOperatorStyle() +{ + RefPtr<RenderStyle> newStyle = RenderStyle::create(); + newStyle->inheritFrom(style()); + newStyle->setDisplay(INLINE_BLOCK); + newStyle->setPaddingRight(Length(static_cast<int>(gOperatorPadding * style()->fontSize()), Fixed)); + return newStyle; +} + +void RenderMathMLFenced::makeFences() +{ + RenderObject* openFence = new (renderArena()) RenderMathMLOperator(node(), m_open); + openFence->setStyle(makeOperatorStyle().release()); + RenderBlock::addChild(openFence, firstChild()); + RenderObject* closeFence = new (renderArena()) RenderMathMLOperator(node(), m_close); + closeFence->setStyle(makeOperatorStyle().release()); + RenderBlock::addChild(closeFence); +} + +void RenderMathMLFenced::addChild(RenderObject* child, RenderObject*) +{ + // make the fences if the render object is empty + if (isEmpty()) + updateFromElement(); + + if (m_separators.get()) { + unsigned int count = 0; + for (Node* position = child->node(); position; position = position->previousSibling()) { + if (position->nodeType() == Node::ELEMENT_NODE) + count++; + } + + if (count > 1) { + UChar separator; + + // Use the last separator if we've run out of specified separators. + if ((count - 1) >= m_separators.get()->length()) + separator = (*m_separators.get())[m_separators.get()->length() - 1]; + else + separator = (*m_separators.get())[count - 1]; + + RenderObject* separatorObj = new (renderArena()) RenderMathMLOperator(node(), separator); + separatorObj->setStyle(makeOperatorStyle().release()); + RenderBlock::addChild(separatorObj, lastChild()); + } + } + + // If we have a block, we'll wrap it in an inline-block. + if (child->isBlockFlow() && child->style()->display() != INLINE_BLOCK) { + // Block objects wrapper. + + RenderBlock* block = new (renderArena()) RenderBlock(node()); + RefPtr<RenderStyle> newStyle = RenderStyle::create(); + newStyle->inheritFrom(style()); + newStyle->setDisplay(INLINE_BLOCK); + block->setStyle(newStyle.release()); + + RenderBlock::addChild(block, lastChild()); + block->addChild(child); + } else + RenderBlock::addChild(child, lastChild()); +} + +} + +#endif diff --git a/Source/WebCore/mathml/RenderMathMLFenced.h b/Source/WebCore/mathml/RenderMathMLFenced.h new file mode 100644 index 0000000..64e4d90 --- /dev/null +++ b/Source/WebCore/mathml/RenderMathMLFenced.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RenderMathMLFenced_h +#define RenderMathMLFenced_h + +#if ENABLE(MATHML) + +#include "RenderMathMLRow.h" + +namespace WebCore { + +class RenderMathMLFenced : public RenderMathMLRow { +public: + RenderMathMLFenced(Node *fraction); + virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0); + virtual void updateFromElement(); + +private: + void makeFences(); + RefPtr<RenderStyle> makeOperatorStyle(); + UChar m_open; + UChar m_close; + RefPtr<StringImpl> m_separators; +}; + +} + +#endif // ENABLE(MATHML) + +#endif // RenderMathMLFenced_h diff --git a/Source/WebCore/mathml/RenderMathMLFraction.cpp b/Source/WebCore/mathml/RenderMathMLFraction.cpp new file mode 100644 index 0000000..1435be7 --- /dev/null +++ b/Source/WebCore/mathml/RenderMathMLFraction.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved. + * Copyright (C) 2010 François Sausset (sausset@gmail.com). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(MATHML) + +#include "RenderMathMLFraction.h" + +#include "GraphicsContext.h" +#include "MathMLNames.h" +#include "RenderText.h" + +namespace WebCore { + +using namespace MathMLNames; + +static const double gHorizontalPad = 0.2; +static const int gLineThin = 1; +static const int gLineMedium = 3; +static const int gLineThick = 5; +static const double gFractionAlignment = 0.25; +static const double gFractionBarWidth = 0.05; +static const double gDenominatorPad = 0.1; + +RenderMathMLFraction::RenderMathMLFraction(Element* fraction) + : RenderMathMLBlock(fraction) + , m_lineThickness(gLineThin) +{ + setChildrenInline(false); +} + +void RenderMathMLFraction::updateFromElement() +{ + // FIXME: mfrac where bevelled=true will need to reorganize the descendants + if (isEmpty()) + return; + + Element* fraction = static_cast<Element*>(node()); + + RenderObject* numerator = firstChild(); + String nalign = fraction->getAttribute(MathMLNames::numalignAttr); + if (equalIgnoringCase(nalign, "left")) + numerator->style()->setTextAlign(LEFT); + else if (equalIgnoringCase(nalign, "right")) + numerator->style()->setTextAlign(RIGHT); + else + numerator->style()->setTextAlign(CENTER); + + RenderObject* denominator = numerator->nextSibling(); + if (!denominator) + return; + + String dalign = fraction->getAttribute(MathMLNames::denomalignAttr); + if (equalIgnoringCase(dalign, "left")) + denominator->style()->setTextAlign(LEFT); + else if (equalIgnoringCase(dalign, "right")) + denominator->style()->setTextAlign(RIGHT); + else + denominator->style()->setTextAlign(CENTER); + + // FIXME: parse units + String thickness = fraction->getAttribute(MathMLNames::linethicknessAttr); + m_lineThickness = gLineThin; + if (equalIgnoringCase(thickness, "thin")) + m_lineThickness = gLineThin; + else if (equalIgnoringCase(thickness, "medium")) + m_lineThickness = gLineMedium; + else if (equalIgnoringCase(thickness, "thick")) + m_lineThickness = gLineThick; + else if (equalIgnoringCase(thickness, "0")) + m_lineThickness = 0; + + // Update the style for the padding of the denominator for the line thickness + lastChild()->style()->setPaddingTop(Length(static_cast<int>(m_lineThickness + style()->fontSize() * gDenominatorPad), Fixed)); +} + +void RenderMathMLFraction::addChild(RenderObject* child, RenderObject* beforeChild) +{ + RenderBlock* row = new (renderArena()) RenderMathMLBlock(node()); + RefPtr<RenderStyle> rowStyle = makeBlockStyle(); + + rowStyle->setTextAlign(CENTER); + Length pad(static_cast<int>(rowStyle->fontSize() * gHorizontalPad), Fixed); + rowStyle->setPaddingLeft(pad); + rowStyle->setPaddingRight(pad); + + // Only add padding for rows as denominators + bool isNumerator = isEmpty(); + if (!isNumerator) + rowStyle->setPaddingTop(Length(2, Fixed)); + + row->setStyle(rowStyle.release()); + RenderBlock::addChild(row, beforeChild); + row->addChild(child); + updateFromElement(); +} + +void RenderMathMLFraction::layout() +{ + updateFromElement(); + + // Adjust the fraction line thickness for the zoom + if (lastChild() && lastChild()->isRenderBlock()) + m_lineThickness = static_cast<int>(m_lineThickness * ceil(gFractionBarWidth * style()->fontSize())); + + RenderBlock::layout(); + +} + +void RenderMathMLFraction::paint(PaintInfo& info, int tx, int ty) +{ + RenderMathMLBlock::paint(info, tx, ty); + if (info.context->paintingDisabled() || info.phase != PaintPhaseForeground) + return; + + if (!firstChild() ||!m_lineThickness) + return; + + int verticalOffset = 0; + // The children are always RenderMathMLBlock instances + if (firstChild()->isRenderMathMLBlock()) { + int adjustForThickness = m_lineThickness > 1 ? m_lineThickness / 2 : 1; + if (m_lineThickness % 2 == 1) + adjustForThickness++; + RenderMathMLBlock* numerator = toRenderMathMLBlock(firstChild()); + if (numerator->isRenderMathMLRow()) + verticalOffset = numerator->offsetHeight() + adjustForThickness; + else + verticalOffset = numerator->offsetHeight(); + } + + tx += x(); + ty += y() + verticalOffset; + + info.context->save(); + + info.context->setStrokeThickness(static_cast<float>(m_lineThickness)); + info.context->setStrokeStyle(SolidStroke); + info.context->setStrokeColor(style()->visitedDependentColor(CSSPropertyColor), ColorSpaceSRGB); + + info.context->drawLine(IntPoint(tx, ty), IntPoint(tx + offsetWidth(), ty)); + + info.context->restore(); +} + +int RenderMathMLFraction::baselinePosition(FontBaseline, bool firstLine, LineDirectionMode lineDirection, LinePositionMode linePositionMode) const +{ + if (firstChild() && firstChild()->isRenderMathMLBlock()) { + RenderMathMLBlock* numerator = toRenderMathMLBlock(firstChild()); + // FIXME: the baseline should adjust so the fraction line aligns + // relative certain operators (e.g. aligns with the horizontal + // stroke of the plus). 1/3 of the current font size is just + // a good guess. + return numerator->offsetHeight() + style()->fontSize() / 3; + } + return RenderBlock::baselinePosition(AlphabeticBaseline, firstLine, lineDirection, linePositionMode); +} + +} + + +#endif // ENABLE(MATHML) diff --git a/Source/WebCore/mathml/RenderMathMLFraction.h b/Source/WebCore/mathml/RenderMathMLFraction.h new file mode 100644 index 0000000..8a3a9ed --- /dev/null +++ b/Source/WebCore/mathml/RenderMathMLFraction.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved. + * Copyright (C) 2010 François Sausset (sausset@gmail.com). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RenderMathMLFraction_h +#define RenderMathMLFraction_h + +#if ENABLE(MATHML) + +#include "RenderMathMLBlock.h" + +namespace WebCore { + +class RenderMathMLFraction : public RenderMathMLBlock { +public: + RenderMathMLFraction(Element* fraction); + virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0); + virtual void updateFromElement(); + virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; + virtual void paint(PaintInfo&, int tx, int ty); +protected: + virtual void layout(); +private: + int m_lineThickness; +}; + +} + +#endif // ENABLE(MATHML) + +#endif // RenderMathMLFraction_h diff --git a/Source/WebCore/mathml/RenderMathMLMath.cpp b/Source/WebCore/mathml/RenderMathMLMath.cpp new file mode 100644 index 0000000..2b65f69 --- /dev/null +++ b/Source/WebCore/mathml/RenderMathMLMath.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2010 Alex Milowski (alex@milowski.com). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(MATHML) + +#include "RenderMathMLMath.h" + +#include "MathMLNames.h" + +namespace WebCore { + +using namespace MathMLNames; + +RenderMathMLMath::RenderMathMLMath(Node* math) + : RenderMathMLRow(math) +{ +} + +} + +#endif // ENABLE(MATHML) + diff --git a/Source/WebCore/mathml/RenderMathMLMath.h b/Source/WebCore/mathml/RenderMathMLMath.h new file mode 100644 index 0000000..26f2093 --- /dev/null +++ b/Source/WebCore/mathml/RenderMathMLMath.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2010 Alex Milowski (alex@milowski.com). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RenderMathMLMath_h +#define RenderMathMLMath_h + +#if ENABLE(MATHML) + +#include "RenderMathMLRow.h" + +namespace WebCore { + +class RenderMathMLMath : public RenderMathMLRow { +public: + RenderMathMLMath(Node* container); + virtual bool isRenderMathMLMath() const { return true; } +}; + +} + + +#endif // ENABLE(MATHML) +#endif // RenderMathMLMath_h diff --git a/Source/WebCore/mathml/RenderMathMLOperator.cpp b/Source/WebCore/mathml/RenderMathMLOperator.cpp new file mode 100644 index 0000000..7f039b9 --- /dev/null +++ b/Source/WebCore/mathml/RenderMathMLOperator.cpp @@ -0,0 +1,344 @@ +/* + * Copyright (C) 2010 Alex Milowski (alex@milowski.com). All rights reserved. + * Copyright (C) 2010 François Sausset (sausset@gmail.com). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(MATHML) + +#include "RenderMathMLOperator.h" + +#include "FontSelector.h" +#include "MathMLNames.h" +#include "RenderText.h" + +namespace WebCore { + +using namespace MathMLNames; + +RenderMathMLOperator::RenderMathMLOperator(Node* container) + : RenderMathMLBlock(container) + , m_stretchHeight(0) + , m_operator(0) +{ +} + +RenderMathMLOperator::RenderMathMLOperator(Node* container, UChar operatorChar) + : RenderMathMLBlock(container) + , m_stretchHeight(0) + , m_operator(convertHyphenMinusToMinusSign(operatorChar)) +{ +} + +bool RenderMathMLOperator::isChildAllowed(RenderObject*, RenderStyle*) const +{ + return false; +} + +static const float gOperatorSpacer = 0.1f; +static const float gOperatorExpansion = 1.2f; + +void RenderMathMLOperator::stretchToHeight(int height) +{ + if (height == m_stretchHeight) + return; + m_stretchHeight = static_cast<int>(height * gOperatorExpansion); + + updateBoxModelInfoFromStyle(); + setNeedsLayout(true); +} + +void RenderMathMLOperator::layout() +{ + // FIXME: This probably shouldn't be called here but when the operator + // isn't stretched (e.g. outside of a mrow), it needs to be called somehow + updateFromElement(); + RenderBlock::layout(); +} + +// This is a table of stretchy characters. +// FIXME: Should this be read from the unicode characteristics somehow? +// table: stretchy operator, top char, extension char, bottom char, middle char +static struct StretchyCharacter { + UChar character; + UChar topGlyph; + UChar extensionGlyph; + UChar bottomGlyph; + UChar middleGlyph; +} stretchyCharacters[13] = { + { 0x28 , 0x239b, 0x239c, 0x239d, 0x0 }, // left parenthesis + { 0x29 , 0x239e, 0x239f, 0x23a0, 0x0 }, // right parenthesis + { 0x5b , 0x23a1, 0x23a2, 0x23a3, 0x0 }, // left square bracket + { 0x2308, 0x23a1, 0x23a2, 0x23a2, 0x0 }, // left ceiling + { 0x230a, 0x23a2, 0x23a2, 0x23a3, 0x0 }, // left floor + { 0x5d , 0x23a4, 0x23a5, 0x23a6, 0x0 }, // right square bracket + { 0x2309, 0x23a4, 0x23a5, 0x23a5, 0x0 }, // right ceiling + { 0x230b, 0x23a5, 0x23a5, 0x23a6, 0x0 }, // right floor + { 0x7b , 0x23a7, 0x23aa, 0x23a9, 0x23a8 }, // left curly bracket + { 0x7c , 0x23d0, 0x23d0, 0x23d0, 0x0 }, // vertical bar + { 0x2016, 0x2016, 0x2016, 0x2016, 0x0 }, // double vertical line + { 0x7d , 0x23ab, 0x23aa, 0x23ad, 0x23ac }, // right curly bracket + { 0x222b, 0x2320, 0x23ae, 0x2321, 0x0 } // integral sign +}; + +// We stack glyphs using a 14px height with a displayed glyph height +// of 10px. The line height is set to less than the 14px so that there +// are no blank spaces between the stacked glyphs. +// +// Certain glyphs (e.g. middle and bottom) need to be adjusted upwards +// in the stack so that there isn't a gap. +// +// All of these settings are represented in the constants below. + +// FIXME: use fractions of style()->fontSize() for proper zooming/resizing. +static const int gGlyphFontSize = 14; +static const int gGlyphLineHeight = 11; +static const int gMinimumStretchHeight = 24; +static const int gGlyphHeight = 10; +static const int gTopGlyphTopAdjust = 1; +static const int gMiddleGlyphTopAdjust = -1; +static const int gBottomGlyphTopAdjust = -3; +static const float gMinimumRatioForStretch = 0.10f; + +void RenderMathMLOperator::updateFromElement() +{ + // Destroy our current children + children()->destroyLeftoverChildren(); + + // Since we share a node with our children, destroying our children will set our node's + // renderer to 0, so we need to re-set it back to this. + node()->setRenderer(this); + + // If the operator is fixed, it will be contained in m_operator + UChar firstChar = m_operator; + + // This boolean indicates whether stretching is disabled via the markup. + bool stretchDisabled = false; + + // We made need the element later if we can't stretch. + if (node()->nodeType() == Node::ELEMENT_NODE) { + if (Element* mo = static_cast<Element*>(node())) { + AtomicString stretchyAttr = mo->getAttribute(MathMLNames::stretchyAttr); + stretchDisabled = equalIgnoringCase(stretchyAttr, "false"); + + // If stretching isn't disabled, get the character from the text content. + if (!stretchDisabled && !firstChar) { + String opText = mo->textContent(); + for (unsigned int i = 0; !firstChar && i < opText.length(); i++) { + if (!isSpaceOrNewline(opText[i])) + firstChar = opText[i]; + } + } + } + } + + // The 'index' holds the stretchable character's glyph information + int index = -1; + + // isStretchy indicates whether the character is streatchable via a number of factors. + bool isStretchy = false; + + // Check for a stretchable character. + if (!stretchDisabled && firstChar) { + const int maxIndex = WTF_ARRAY_LENGTH(stretchyCharacters); + for (index++; index < maxIndex; index++) { + if (stretchyCharacters[index].character == firstChar) { + isStretchy = true; + break; + } + } + } + + // We only stretch character if the stretch height is larger than a minimum size (e.g. 24px). + bool shouldStretch = isStretchy && m_stretchHeight>gMinimumStretchHeight; + + // Either stretch is disabled or we don't have a stretchable character over the minimum height + if (stretchDisabled || !shouldStretch) { + m_isStacked = false; + RenderBlock* container = new (renderArena()) RenderMathMLBlock(node()); + + RefPtr<RenderStyle> newStyle = RenderStyle::create(); + newStyle->inheritFrom(style()); + newStyle->setDisplay(INLINE_BLOCK); + newStyle->setVerticalAlign(BASELINE); + + // Check for a stretchable character that is under the minimum height and use the + // font size to adjust the glyph size. + int currentFontSize = style()->fontSize(); + if (!stretchDisabled && isStretchy && m_stretchHeight > 0 && m_stretchHeight <= gMinimumStretchHeight && m_stretchHeight > currentFontSize) { + FontDescription desc; + desc.setIsAbsoluteSize(true); + desc.setSpecifiedSize(m_stretchHeight); + desc.setComputedSize(m_stretchHeight); + newStyle->setFontDescription(desc); + newStyle->font().update(newStyle->font().fontSelector()); + } + + container->setStyle(newStyle.release()); + addChild(container); + + // Build the text of the operator. + RenderText* text = 0; + if (m_operator) + text = new (renderArena()) RenderText(node(), StringImpl::create(&m_operator, 1)); + else if (node()->nodeType() == Node::ELEMENT_NODE) + if (Element* mo = static_cast<Element*>(node())) + text = new (renderArena()) RenderText(node(), mo->textContent().replace(hyphenMinus, minusSign).impl()); + // If we can't figure out the text, leave it blank. + if (text) { + RefPtr<RenderStyle> textStyle = RenderStyle::create(); + textStyle->inheritFrom(container->style()); + text->setStyle(textStyle.release()); + container->addChild(text); + } + } else { + // Build stretchable characters as a stack of glyphs. + m_isStacked = true; + + if (stretchyCharacters[index].middleGlyph) { + // We have a middle glyph (e.g. a curly bracket) that requires special processing. + int half = (m_stretchHeight - gGlyphHeight) / 2; + if (half <= gGlyphHeight) { + // We only have enough space for a single middle glyph. + createGlyph(stretchyCharacters[index].topGlyph, half, gTopGlyphTopAdjust); + createGlyph(stretchyCharacters[index].middleGlyph, gGlyphHeight, gMiddleGlyphTopAdjust); + createGlyph(stretchyCharacters[index].bottomGlyph, 0, gBottomGlyphTopAdjust); + } else { + // We have to extend both the top and bottom to the middle. + createGlyph(stretchyCharacters[index].topGlyph, gGlyphHeight, gTopGlyphTopAdjust); + int remaining = half - gGlyphHeight; + while (remaining > 0) { + if (remaining < gGlyphHeight) { + createGlyph(stretchyCharacters[index].extensionGlyph, remaining); + remaining = 0; + } else { + createGlyph(stretchyCharacters[index].extensionGlyph, gGlyphHeight); + remaining -= gGlyphHeight; + } + } + + // The middle glyph in the stack. + createGlyph(stretchyCharacters[index].middleGlyph, gGlyphHeight, gMiddleGlyphTopAdjust); + + // The remaining is the top half minus the middle glyph height. + remaining = half - gGlyphHeight; + // We need to make sure we have the full height in case the height is odd. + if (m_stretchHeight % 2 == 1) + remaining++; + + // Extend to the bottom glyph. + while (remaining > 0) { + if (remaining < gGlyphHeight) { + createGlyph(stretchyCharacters[index].extensionGlyph, remaining); + remaining = 0; + } else { + createGlyph(stretchyCharacters[index].extensionGlyph, gGlyphHeight); + remaining -= gGlyphHeight; + } + } + + // The bottom glyph in the stack. + createGlyph(stretchyCharacters[index].bottomGlyph, 0, gBottomGlyphTopAdjust); + } + } else { + // We do not have a middle glyph and so we just extend from the top to the bottom glyph. + int remaining = m_stretchHeight - 2 * gGlyphHeight; + createGlyph(stretchyCharacters[index].topGlyph, gGlyphHeight, gTopGlyphTopAdjust); + while (remaining > 0) { + if (remaining < gGlyphHeight) { + createGlyph(stretchyCharacters[index].extensionGlyph, remaining); + remaining = 0; + } else { + createGlyph(stretchyCharacters[index].extensionGlyph, gGlyphHeight); + remaining -= gGlyphHeight; + } + } + createGlyph(stretchyCharacters[index].bottomGlyph, 0, gBottomGlyphTopAdjust); + } + } +} + +RefPtr<RenderStyle> RenderMathMLOperator::createStackableStyle(int size, int topRelative) +{ + RefPtr<RenderStyle> newStyle = RenderStyle::create(); + newStyle->inheritFrom(style()); + newStyle->setDisplay(BLOCK); + + FontDescription desc; + desc.setIsAbsoluteSize(true); + desc.setSpecifiedSize(gGlyphFontSize); + desc.setComputedSize(gGlyphFontSize); + newStyle->setFontDescription(desc); + newStyle->font().update(newStyle->font().fontSelector()); + newStyle->setLineHeight(Length(gGlyphLineHeight, Fixed)); + newStyle->setVerticalAlign(TOP); + + if (size > 0) + newStyle->setMaxHeight(Length(size, Fixed)); + + newStyle->setOverflowY(OHIDDEN); + newStyle->setOverflowX(OHIDDEN); + if (topRelative) { + newStyle->setTop(Length(topRelative, Fixed)); + newStyle->setPosition(RelativePosition); + } + + return newStyle; +} + +RenderBlock* RenderMathMLOperator::createGlyph(UChar glyph, int size, int charRelative, int topRelative) +{ + RenderBlock* container = new (renderArena()) RenderMathMLBlock(node()); + container->setStyle(createStackableStyle(size, topRelative).release()); + addChild(container); + RenderBlock* parent = container; + if (charRelative) { + RenderBlock* charBlock = new (renderArena()) RenderBlock(node()); + RefPtr<RenderStyle> charStyle = RenderStyle::create(); + charStyle->inheritFrom(container->style()); + charStyle->setDisplay(INLINE_BLOCK); + charStyle->setTop(Length(charRelative, Fixed)); + charStyle->setPosition(RelativePosition); + charBlock->setStyle(charStyle); + parent->addChild(charBlock); + parent = charBlock; + } + + RenderText* text = new (renderArena()) RenderText(node(), StringImpl::create(&glyph, 1)); + text->setStyle(container->style()); + parent->addChild(text); + return container; +} + +int RenderMathMLOperator::baselinePosition(FontBaseline, bool firstLine, LineDirectionMode lineDirection, LinePositionMode linePositionMode) const +{ + if (m_isStacked) + return m_stretchHeight * 2 / 3 - (m_stretchHeight - static_cast<int>(m_stretchHeight / gOperatorExpansion)) / 2; + return RenderBlock::baselinePosition(AlphabeticBaseline, firstLine, lineDirection, linePositionMode); +} + +} + +#endif diff --git a/Source/WebCore/mathml/RenderMathMLOperator.h b/Source/WebCore/mathml/RenderMathMLOperator.h new file mode 100644 index 0000000..6501494 --- /dev/null +++ b/Source/WebCore/mathml/RenderMathMLOperator.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2010 Alex Milowski (alex@milowski.com). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RenderMathMLOperator_h +#define RenderMathMLOperator_h + +#if ENABLE(MATHML) + +#include "CharacterNames.h" +#include "RenderMathMLBlock.h" + +namespace WebCore { + +class RenderMathMLOperator : public RenderMathMLBlock { +public: + RenderMathMLOperator(Node* container); + RenderMathMLOperator(Node* container, UChar operatorChar); + virtual bool isRenderMathMLOperator() const { return true; } + virtual void stretchToHeight(int pixelHeight); + virtual void updateFromElement(); + virtual bool isChildAllowed(RenderObject*, RenderStyle*) const; + virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; + +protected: + virtual void layout(); + virtual RefPtr<RenderStyle> createStackableStyle(int size, int topRelative); + virtual RenderBlock* createGlyph(UChar glyph, int size = 0, int charRelative = 0, int topRelative = 0); + +private: + int m_stretchHeight; + bool m_isStacked; + UChar m_operator; +}; + +inline RenderMathMLOperator* toRenderMathMLOperator(RenderMathMLBlock* block) +{ + ASSERT(!block || block->isRenderMathMLOperator()); + return static_cast<RenderMathMLOperator*>(block); +} + +inline const RenderMathMLOperator* toRenderMathMLOperator(const RenderMathMLBlock* block) +{ + ASSERT(!block || block->isRenderMathMLOperator()); + return static_cast<const RenderMathMLOperator*>(block); +} + +inline UChar convertHyphenMinusToMinusSign(UChar glyph) +{ + // When rendered as a mathematical operator, minus glyph should be larger. + if (glyph == hyphenMinus) + return minusSign; + + return glyph; +} + +} + +#endif // ENABLE(MATHML) +#endif // RenderMathMLOperator_h diff --git a/Source/WebCore/mathml/RenderMathMLRoot.cpp b/Source/WebCore/mathml/RenderMathMLRoot.cpp new file mode 100644 index 0000000..f0a7abb --- /dev/null +++ b/Source/WebCore/mathml/RenderMathMLRoot.cpp @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved. + * Copyright (C) 2010 François Sausset (sausset@gmail.com). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(MATHML) + +#include "RenderMathMLRoot.h" + +#include "GraphicsContext.h" +#include "MathMLNames.h" + +namespace WebCore { + +using namespace MathMLNames; + +// Left margin of the radical (px) +const int gRadicalLeftMargin = 3; +// Bottom padding of the radical (px) +const int gRadicalBasePad = 3; +// Threshold above which the radical shape is modified to look nice with big bases (%) +const float gThresholdBaseHeight = 1.5f; +// Radical width (%) +const float gRadicalWidth = 0.75f; +// Horizontal position of the bottom point of the radical (%) +const float gRadicalBottomPointXPos= 0.5f; +// Horizontal position of the top left point of the radical (%) +const float gRadicalTopLeftPointXPos = 0.8f; +// Vertical position of the top left point of the radical (%) +const float gRadicalTopLeftPointYPos = 0.625f; +// Vertical shift of the left end point of the radical (%) +const float gRadicalLeftEndYShift = 0.05f; +// Root padding around the base (%) +const float gRootPadding = 0.2f; +// Additional bottom root padding (%) +const float gRootBottomPadding = 0.2f; + +// Radical line thickness (%) +const float gRadicalLineThickness = 0.02f; +// Radical thick line thickness (%) +const float gRadicalThickLineThickness = 0.1f; + +RenderMathMLRoot::RenderMathMLRoot(Node *expression) +: RenderMathMLBlock(expression) +{ +} + +void RenderMathMLRoot::addChild(RenderObject* child, RenderObject* ) +{ + if (isEmpty()) { + // Add a block for the index + RenderBlock* block = new (renderArena()) RenderBlock(node()); + RefPtr<RenderStyle> indexStyle = makeBlockStyle(); + indexStyle->setDisplay(INLINE_BLOCK); + block->setStyle(indexStyle.release()); + RenderBlock::addChild(block); + + // FIXME: the wrapping does not seem to be needed anymore. + // this is the base, so wrap it so we can pad it + block = new (renderArena()) RenderBlock(node()); + RefPtr<RenderStyle> baseStyle = makeBlockStyle(); + baseStyle->setDisplay(INLINE_BLOCK); + baseStyle->setPaddingLeft(Length(5 * gRadicalWidth , Percent)); + block->setStyle(baseStyle.release()); + RenderBlock::addChild(block); + block->addChild(child); + } else { + // always add to the index + firstChild()->addChild(child); + } +} + +void RenderMathMLRoot::paint(PaintInfo& info, int tx, int ty) +{ + RenderMathMLBlock::paint(info , tx , ty); + + if (info.context->paintingDisabled()) + return; + + if (!firstChild() || !lastChild()) + return; + + tx += x(); + ty += y(); + + RenderBoxModelObject* indexBox = toRenderBoxModelObject(lastChild()); + + int maxHeight = indexBox->offsetHeight(); + // default to the font size in pixels if we're empty + if (!maxHeight) + maxHeight = style()->fontSize(); + int width = indexBox->offsetWidth(); + + int indexWidth = 0; + RenderObject* current = firstChild(); + while (current != lastChild()) { + if (current->isBoxModelObject()) { + RenderBoxModelObject* box = toRenderBoxModelObject(current); + indexWidth += box->offsetWidth(); + } + current = current->nextSibling(); + } + + int frontWidth = static_cast<int>(style()->fontSize() * gRadicalWidth); + int topStartShift = 0; + // Base height above which the shape of the root changes + int thresholdHeight = static_cast<int>(gThresholdBaseHeight * style()->fontSize()); + + if (maxHeight > thresholdHeight && thresholdHeight) { + float shift = (maxHeight - thresholdHeight) / static_cast<float>(thresholdHeight); + if (shift > 1.) + shift = 1.0f; + topStartShift = static_cast<int>(gRadicalBottomPointXPos * frontWidth * shift); + } + + width += topStartShift; + + int rootPad = static_cast<int>(gRootPadding * style()->fontSize()); + int start = tx + indexWidth + gRadicalLeftMargin + style()->paddingLeft().value() - rootPad; + ty += style()->paddingTop().value() - rootPad; + + FloatPoint topStart(start - topStartShift, ty); + FloatPoint bottomLeft(start - gRadicalBottomPointXPos * frontWidth , ty + maxHeight + gRadicalBasePad); + FloatPoint topLeft(start - gRadicalTopLeftPointXPos * frontWidth , ty + gRadicalTopLeftPointYPos * maxHeight); + FloatPoint leftEnd(start - frontWidth , topLeft.y() + gRadicalLeftEndYShift * style()->fontSize()); + + info.context->save(); + + info.context->setStrokeThickness(gRadicalLineThickness * style()->fontSize()); + info.context->setStrokeStyle(SolidStroke); + info.context->setStrokeColor(style()->visitedDependentColor(CSSPropertyColor), ColorSpaceDeviceRGB); + info.context->setLineJoin(MiterJoin); + info.context->setMiterLimit(style()->fontSize()); + + Path root; + + root.moveTo(FloatPoint(topStart.x() + width, ty)); + // draw top + root.addLineTo(topStart); + // draw from top left corner to bottom point of radical + root.addLineTo(bottomLeft); + // draw from bottom point to top of left part of radical base "pocket" + root.addLineTo(topLeft); + // draw to end + root.addLineTo(leftEnd); + + info.context->strokePath(root); + + info.context->save(); + + // Build a mask to draw the thick part of the root. + Path mask; + + mask.moveTo(topStart); + mask.addLineTo(bottomLeft); + mask.addLineTo(topLeft); + mask.addLineTo(FloatPoint(2 * topLeft.x() - leftEnd.x(), 2 * topLeft.y() - leftEnd.y())); + + info.context->clip(mask); + + // Draw the thick part of the root. + info.context->setStrokeThickness(gRadicalThickLineThickness * style()->fontSize()); + info.context->setLineCap(SquareCap); + + Path line; + line.moveTo(bottomLeft); + line.addLineTo(topLeft); + + info.context->strokePath(line); + + info.context->restore(); + + info.context->restore(); + +} + +void RenderMathMLRoot::layout() +{ + RenderBlock::layout(); + + if (!firstChild() || !lastChild()) + return; + + int maxHeight = toRenderBoxModelObject(lastChild())->offsetHeight(); + + RenderObject* current = lastChild()->firstChild(); + if (current) + current->style()->setVerticalAlign(BASELINE); + + if (!maxHeight) + maxHeight = style()->fontSize(); + + // Base height above which the shape of the root changes + int thresholdHeight = static_cast<int>(gThresholdBaseHeight * style()->fontSize()); + int topStartShift = 0; + + if (maxHeight > thresholdHeight && thresholdHeight) { + float shift = (maxHeight - thresholdHeight) / static_cast<float>(thresholdHeight); + if (shift > 1.) + shift = 1.0f; + int frontWidth = static_cast<int>(style()->fontSize() * gRadicalWidth); + topStartShift = static_cast<int>(gRadicalBottomPointXPos * frontWidth * shift); + + style()->setPaddingBottom(Length(static_cast<int>(gRootBottomPadding * style()->fontSize()), Fixed)); + } + + // Positioning of the index + RenderBoxModelObject* indexBox = toRenderBoxModelObject(firstChild()->firstChild()); + if (!indexBox) + return; + + int indexShift = indexBox->offsetWidth() + topStartShift; + int radicalHeight = static_cast<int>((1 - gRadicalTopLeftPointYPos) * maxHeight); + int rootMarginTop = radicalHeight + style()->paddingBottom().value() + indexBox->offsetHeight() - (maxHeight + static_cast<int>(gRootPadding * style()->fontSize())); + + style()->setPaddingLeft(Length(indexShift, Fixed)); + if (rootMarginTop > 0) + style()->setPaddingTop(Length(rootMarginTop + static_cast<int>(gRootPadding * style()->fontSize()), Fixed)); + + setNeedsLayout(true); + setPreferredLogicalWidthsDirty(true, false); + RenderBlock::layout(); + + indexBox->style()->setBottom(Length(radicalHeight + style()->paddingBottom().value(), Fixed)); + + // Now that we've potentially changed its position, we need layout the index again. + indexBox->setNeedsLayout(true); + indexBox->layout(); +} + +} + +#endif // ENABLE(MATHML) + + diff --git a/Source/WebCore/mathml/RenderMathMLRoot.h b/Source/WebCore/mathml/RenderMathMLRoot.h new file mode 100644 index 0000000..80f56ac --- /dev/null +++ b/Source/WebCore/mathml/RenderMathMLRoot.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RenderMathMLRoot_h +#define RenderMathMLRoot_h + +#if ENABLE(MATHML) + +#include "RenderMathMLBlock.h" + +namespace WebCore { + +class RenderMathMLRoot : public RenderMathMLBlock { +public: + RenderMathMLRoot(Node* fraction); + virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0); + virtual void paint(PaintInfo&, int tx, int ty); +protected: + virtual void layout(); +}; + +} + +#endif // ENABLE(MATHML) + +#endif // RenderMathMLRoot_h diff --git a/Source/WebCore/mathml/RenderMathMLRow.cpp b/Source/WebCore/mathml/RenderMathMLRow.cpp new file mode 100644 index 0000000..ad54846 --- /dev/null +++ b/Source/WebCore/mathml/RenderMathMLRow.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2010 Alex Milowski (alex@milowski.com). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(MATHML) + +#include "RenderMathMLRow.h" + +#include "MathMLNames.h" +#include "RenderMathMLOperator.h" + +namespace WebCore { + +using namespace MathMLNames; + +RenderMathMLRow::RenderMathMLRow(Node* row) + : RenderMathMLBlock(row) +{ +} + +int RenderMathMLRow::nonOperatorHeight() const +{ + int maxHeight = 0; + for (RenderObject* current = firstChild(); current; current = current->nextSibling()) { + if (current->isRenderMathMLBlock()) { + RenderMathMLBlock* block = toRenderMathMLBlock(current); + int blockHeight = block->nonOperatorHeight(); + // Check to see if this box has a larger height + if (blockHeight > maxHeight) + maxHeight = blockHeight; + } else if (current->isBoxModelObject()) { + RenderBoxModelObject* box = toRenderBoxModelObject(current); + // Check to see if this box has a larger height + if (box->offsetHeight() > maxHeight) + maxHeight = box->offsetHeight(); + } + + } + return maxHeight; +} + +void RenderMathMLRow::layout() +{ + RenderBlock::layout(); + + int maxHeight = 0; + int childCount = 0; + int operatorCount = 0; + + // Calculate the non-operator max height of the row. + int operatorHeight = 0; + for (RenderObject* current = firstChild(); current; current = current->nextSibling()) { + childCount++; + if (current->isRenderMathMLBlock()) { + RenderMathMLBlock* block = toRenderMathMLBlock(current); + // Check to see if the non-operator block has a greater height. + if (!block->hasBase() && !block->isRenderMathMLOperator() && block->offsetHeight() > maxHeight) + maxHeight = block->offsetHeight(); + if (block->hasBase() && block->nonOperatorHeight() > maxHeight) + maxHeight = block->nonOperatorHeight(); + // If the block is an operator, capture the maximum height and increment the count. + if (block->isRenderMathMLOperator()) { + if (block->offsetHeight() > operatorHeight) + operatorHeight = block->offsetHeight(); + operatorCount++; + } + } else if (current->isBoxModelObject()) { + RenderBoxModelObject* box = toRenderBoxModelObject(current); + // Check to see if this box has a larger height. + if (box->offsetHeight() > maxHeight) + maxHeight = box->offsetHeight(); + } + } + + if (childCount > 0 && childCount == operatorCount) { + // We have only operators and so set the max height to the operator height. + maxHeight = operatorHeight; + } + + // Stretch everything to the same height (blocks can ignore the request). + if (maxHeight > 0) { + bool didStretch = false; + for (RenderObject* current = firstChild(); current; current = current->nextSibling()) { + if (current->isRenderMathMLBlock()) { + RenderMathMLBlock* block = toRenderMathMLBlock(current); + block->stretchToHeight(maxHeight); + didStretch = true; + } + } + if (didStretch) { + setNeedsLayout(true); + setPreferredLogicalWidthsDirty(true, false); + RenderBlock::layout(); + } + } + +} + +int RenderMathMLRow::baselinePosition(FontBaseline, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const +{ + if (firstChild() && firstChild()->isRenderMathMLBlock()) { + RenderMathMLBlock* block = toRenderMathMLBlock(firstChild()); + if (block->isRenderMathMLOperator()) + return block->y() + block->baselinePosition(AlphabeticBaseline, firstLine, direction, linePositionMode); + } + + return RenderBlock::baselinePosition(AlphabeticBaseline, firstLine, direction, linePositionMode); +} + +} + +#endif // ENABLE(MATHML) + diff --git a/Source/WebCore/mathml/RenderMathMLRow.h b/Source/WebCore/mathml/RenderMathMLRow.h new file mode 100644 index 0000000..62a0d09 --- /dev/null +++ b/Source/WebCore/mathml/RenderMathMLRow.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2010 Alex Milowski (alex@milowski.com). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RenderMathMLRow_h +#define RenderMathMLRow_h + +#if ENABLE(MATHML) + +#include "RenderMathMLBlock.h" + +namespace WebCore { + +class RenderMathMLRow : public RenderMathMLBlock { +public: + RenderMathMLRow(Node* container); + virtual bool isRenderMathMLRow() const { return true; } + virtual int nonOperatorHeight() const; + virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; + virtual void stretchToHeight(int) {} +protected: + virtual void layout(); +}; + +} + + +#endif // ENABLE(MATHML) +#endif // RenderMathMLRow_h diff --git a/Source/WebCore/mathml/RenderMathMLSquareRoot.cpp b/Source/WebCore/mathml/RenderMathMLSquareRoot.cpp new file mode 100644 index 0000000..1285acd --- /dev/null +++ b/Source/WebCore/mathml/RenderMathMLSquareRoot.cpp @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved. + * Copyright (C) 2010 François Sausset (sausset@gmail.com). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(MATHML) + +#include "RenderMathMLSquareRoot.h" + +#include "GraphicsContext.h" +#include "MathMLNames.h" +#include "Path.h" + +namespace WebCore { + +using namespace MathMLNames; + +// Bottom padding of the radical (px) +const int gRadicalBasePad = 3; +// Threshold above which the radical shape is modified to look nice with big bases (%) +const float gThresholdBaseHeight = 1.5f; +// Radical width (%) +const float gRadicalWidth = 0.75f; +// Horizontal position of the bottom point of the radical (%) +const float gRadicalBottomPointXPos= 0.5f; +// Horizontal position of the top left point of the radical (%) +const float gRadicalTopLeftPointXPos = 0.2f; +// Vertical position of the top left point of the radical (%) +const float gRadicalTopLeftPointYPos = 0.5f; +// Vertical shift of the left end point of the radical (%) +const float gRadicalLeftEndYShift = 0.05f; +// Additional bottom root padding (%) +const float gRootBottomPadding = 0.2f; + +// Radical line thickness (%) +const float gRadicalLineThickness = 0.02f; +// Radical thick line thickness (%) +const float gRadicalThickLineThickness = 0.1f; + +RenderMathMLSquareRoot::RenderMathMLSquareRoot(Node *expression) + : RenderMathMLBlock(expression) +{ +} + +void RenderMathMLSquareRoot::paint(PaintInfo& info, int tx, int ty) +{ + RenderMathMLBlock::paint(info, tx, ty); + + if (info.context->paintingDisabled()) + return; + + tx += x(); + ty += y(); + + int maxHeight = 0; + int width = 0; + RenderObject* current = firstChild(); + while (current) { + if (current->isBoxModelObject()) { + + RenderBoxModelObject* box = toRenderBoxModelObject(current); + + // Check to see if this box has a larger height + if (box->offsetHeight() > maxHeight) + maxHeight = box->offsetHeight(); + width += box->offsetWidth(); + } + current = current->nextSibling(); + } + // default to the font size in pixels if we're empty + if (!maxHeight) + maxHeight = style()->fontSize(); + + int frontWidth = static_cast<int>(style()->fontSize() * gRadicalWidth); + int topStartShift = 0; + // Base height above which the shape of the root changes + int thresholdHeight = static_cast<int>(gThresholdBaseHeight * style()->fontSize()); + + if (maxHeight > thresholdHeight && thresholdHeight) { + float shift = (maxHeight - thresholdHeight) / static_cast<float>(thresholdHeight); + if (shift > 1.) + shift = 1.0f; + topStartShift = static_cast<int>(gRadicalBottomPointXPos * frontWidth * shift); + } + + width += topStartShift; + + FloatPoint topStart(tx + frontWidth - topStartShift, ty); + FloatPoint bottomLeft(tx + frontWidth * gRadicalBottomPointXPos , ty + maxHeight + gRadicalBasePad); + FloatPoint topLeft(tx + frontWidth * gRadicalTopLeftPointXPos , ty + gRadicalTopLeftPointYPos * maxHeight); + FloatPoint leftEnd(tx , topLeft.y() + gRadicalLeftEndYShift * style()->fontSize()); + + info.context->save(); + + info.context->setStrokeThickness(gRadicalLineThickness * style()->fontSize()); + info.context->setStrokeStyle(SolidStroke); + info.context->setStrokeColor(style()->visitedDependentColor(CSSPropertyColor), ColorSpaceDeviceRGB); + info.context->setLineJoin(MiterJoin); + info.context->setMiterLimit(style()->fontSize()); + + Path root; + + root.moveTo(FloatPoint(topStart.x() + width , ty)); + // draw top + root.addLineTo(topStart); + // draw from top left corner to bottom point of radical + root.addLineTo(bottomLeft); + // draw from bottom point to top of left part of radical base "pocket" + root.addLineTo(topLeft); + // draw to end + root.addLineTo(leftEnd); + + info.context->strokePath(root); + + info.context->save(); + + // Build a mask to draw the thick part of the root. + Path mask; + + mask.moveTo(topStart); + mask.addLineTo(bottomLeft); + mask.addLineTo(topLeft); + mask.addLineTo(FloatPoint(2 * topLeft.x() - leftEnd.x(), 2 * topLeft.y() - leftEnd.y())); + + info.context->clip(mask); + + // Draw the thick part of the root. + info.context->setStrokeThickness(gRadicalThickLineThickness * style()->fontSize()); + info.context->setLineCap(SquareCap); + + Path line; + line.moveTo(bottomLeft); + line.addLineTo(topLeft); + + info.context->strokePath(line); + + info.context->restore(); + + info.context->restore(); +} + +void RenderMathMLSquareRoot::layout() +{ + int maxHeight = 0; + + RenderObject* current = firstChild(); + while (current) { + if (current->isBoxModelObject()) { + RenderBoxModelObject* box = toRenderBoxModelObject(current); + + if (box->offsetHeight() > maxHeight) + maxHeight = box->offsetHeight(); + + box->style()->setVerticalAlign(BASELINE); + } + current = current->nextSibling(); + } + + if (!maxHeight) + maxHeight = style()->fontSize(); + + + if (maxHeight > static_cast<int>(gThresholdBaseHeight * style()->fontSize())) + style()->setPaddingBottom(Length(static_cast<int>(gRootBottomPadding * style()->fontSize()), Fixed)); + + + RenderBlock::layout(); +} + +} + +#endif // ENABLE(MATHML) + + diff --git a/Source/WebCore/mathml/RenderMathMLSquareRoot.h b/Source/WebCore/mathml/RenderMathMLSquareRoot.h new file mode 100644 index 0000000..d40b1ba --- /dev/null +++ b/Source/WebCore/mathml/RenderMathMLSquareRoot.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RenderMathMLSquareRoot_h +#define RenderMathMLSquareRoot_h + +#if ENABLE(MATHML) + +#include "RenderMathMLBlock.h" + +namespace WebCore { + +class RenderMathMLSquareRoot : public RenderMathMLBlock { +public: + RenderMathMLSquareRoot(Node* fraction); + virtual void paint(PaintInfo&, int tx, int ty); +protected: + virtual void layout(); +}; + +} + +#endif // ENABLE(MATHML) + +#endif // RenderMathMLSquareRoot_h + + + diff --git a/Source/WebCore/mathml/RenderMathMLSubSup.cpp b/Source/WebCore/mathml/RenderMathMLSubSup.cpp new file mode 100644 index 0000000..0ea6667 --- /dev/null +++ b/Source/WebCore/mathml/RenderMathMLSubSup.cpp @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2010 Alex Milowski (alex@milowski.com). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(MATHML) + +#include "RenderMathMLSubSup.h" + +#include "FontSelector.h" +#include "MathMLNames.h" +#include "RenderInline.h" +#include "RenderTable.h" +#include "RenderTableCell.h" +#include "RenderTableRow.h" +#include "RenderTableSection.h" +#include "RenderText.h" + +namespace WebCore { + +using namespace MathMLNames; + +static const int gTopAdjustDivisor = 3; +static const int gSubsupScriptMargin = 1; +static const float gSubSupStretch = 1.2f; + +RenderMathMLSubSup::RenderMathMLSubSup(Element* element) + : RenderMathMLBlock(element) + , m_scripts(0) +{ + // Determine what kind of under/over expression we have by element name + if (element->hasLocalName(MathMLNames::msubTag)) + m_kind = Sub; + else if (element->hasLocalName(MathMLNames::msupTag)) + m_kind = Sup; + else if (element->hasLocalName(MathMLNames::msubsupTag)) + m_kind = SubSup; + else + m_kind = SubSup; +} + +void RenderMathMLSubSup::addChild(RenderObject* child, RenderObject* beforeChild) +{ + if (firstChild()) { + // We already have a base, so this is the super/subscripts being added. + + if (m_kind == SubSup) { + if (!m_scripts) { + m_scripts = new (renderArena()) RenderMathMLBlock(node()); + RefPtr<RenderStyle> scriptsStyle = RenderStyle::create(); + scriptsStyle->inheritFrom(style()); + scriptsStyle->setDisplay(INLINE_BLOCK); + scriptsStyle->setVerticalAlign(TOP); + scriptsStyle->setMarginLeft(Length(gSubsupScriptMargin, Fixed)); + scriptsStyle->setTextAlign(LEFT); + m_scripts->setStyle(scriptsStyle.release()); + RenderMathMLBlock::addChild(m_scripts, beforeChild); + } + + RenderBlock* script = new (renderArena()) RenderMathMLBlock(node()); + RefPtr<RenderStyle> scriptStyle = RenderStyle::create(); + scriptStyle->inheritFrom(m_scripts->style()); + scriptStyle->setDisplay(BLOCK); + script->setStyle(scriptStyle.release()); + + m_scripts->addChild(script, m_scripts->firstChild()); + script->addChild(child); + } else + RenderMathMLBlock::addChild(child, beforeChild); + + } else { + RenderMathMLBlock* wrapper = new (renderArena()) RenderMathMLBlock(node()); + RefPtr<RenderStyle> wrapperStyle = RenderStyle::create(); + wrapperStyle->inheritFrom(style()); + wrapperStyle->setDisplay(INLINE_BLOCK); + wrapperStyle->setVerticalAlign(BASELINE); + wrapper->setStyle(wrapperStyle.release()); + RenderMathMLBlock::addChild(wrapper, beforeChild); + wrapper->addChild(child); + + } +} + +void RenderMathMLSubSup::stretchToHeight(int height) +{ + RenderObject* base = firstChild(); + if (!base) + return; + + if (base->firstChild()->isRenderMathMLBlock()) { + RenderMathMLBlock* block = toRenderMathMLBlock(base->firstChild()); + block->stretchToHeight(static_cast<int>(gSubSupStretch * height)); + + // Adjust the script placement after we stretch + if (height > 0 && m_kind == SubSup && m_scripts) { + RenderObject* script = m_scripts->firstChild(); + if (script) { + // Calculate the script height without the container margins. + RenderObject* top = script; + int topHeight = getBoxModelObjectHeight(top->firstChild()); + int topAdjust = topHeight / gTopAdjustDivisor; + top->style()->setMarginTop(Length(-topAdjust, Fixed)); + top->style()->setMarginBottom(Length(height - topHeight + topAdjust, Fixed)); + if (top->isBoxModelObject()) { + RenderBoxModelObject* topBox = toRenderBoxModelObject(top); + topBox->updateBoxModelInfoFromStyle(); + } + m_scripts->setNeedsLayout(true); + setNeedsLayout(true); + } + } + + } +} + +int RenderMathMLSubSup::nonOperatorHeight() const +{ + if (m_kind == SubSup) + return static_cast<int>(style()->fontSize()*gSubSupStretch); + return static_cast<int>(style()->fontSize()); +} + +void RenderMathMLSubSup::layout() +{ + if (firstChild()) + firstChild()->setNeedsLayout(true); + if (m_scripts) + m_scripts->setNeedsLayout(true); + + RenderBlock::layout(); + + if (m_kind == SubSup) { + if (RenderObject* base = firstChild()) { + int maxHeight = 0; + RenderObject* current = base->firstChild(); + while (current) { + int height = getBoxModelObjectHeight(current); + if (height > maxHeight) + maxHeight = height; + current = current->nextSibling(); + } + int heightDiff = m_scripts ? (m_scripts->offsetHeight() - maxHeight) / 2 : 0; + if (heightDiff < 0) + heightDiff = 0; + base->style()->setPaddingTop(Length(heightDiff, Fixed)); + base->setNeedsLayout(true); + } + setNeedsLayout(true); + RenderBlock::layout(); + } +} + +int RenderMathMLSubSup::baselinePosition(FontBaseline, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const +{ + RenderObject* base = firstChild(); + if (!base) + return offsetHeight(); + + int baseline = offsetHeight(); + if (!base || !base->isBoxModelObject()) + return baseline; + + switch (m_kind) { + case SubSup: + base = base->firstChild(); + if (m_scripts && base->isBoxModelObject()) { + RenderBoxModelObject* box = toRenderBoxModelObject(base); + + int topAdjust = (m_scripts->offsetHeight() - box->offsetHeight()) / 2; + + // FIXME: The last bit of this calculation should be more exact. Why is the 2-3px scaled for zoom necessary? + // The baseline is top spacing of the base + the baseline of the base + adjusted space for zoom + float zoomFactor = style()->effectiveZoom(); + return topAdjust + box->baselinePosition(AlphabeticBaseline, firstLine, direction, linePositionMode) + static_cast<int>((zoomFactor > 1.25 ? 2 : 3) * zoomFactor); + } + break; + case Sup: + case Sub: + RenderBoxModelObject* box = toRenderBoxModelObject(base); + baseline = box->baselinePosition(AlphabeticBaseline, firstLine, direction, linePositionMode); + break; + } + + return baseline; + +} + +} + +#endif // ENABLE(MATHML) diff --git a/Source/WebCore/mathml/RenderMathMLSubSup.h b/Source/WebCore/mathml/RenderMathMLSubSup.h new file mode 100644 index 0000000..7a9d310 --- /dev/null +++ b/Source/WebCore/mathml/RenderMathMLSubSup.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2010 Alex Milowski (alex@milowski.com). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef RenderMathMLSubSup_h +#define RenderMathMLSubSup_h + +#if ENABLE(MATHML) + +#include "RenderMathMLBlock.h" +#include "RenderTable.h" + +namespace WebCore { + +class RenderMathMLSubSup : public RenderMathMLBlock { +public: + RenderMathMLSubSup(Element* fraction); + virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0); + virtual bool hasBase() const { return true; } + virtual int nonOperatorHeight() const; + virtual void stretchToHeight(int pixelHeight); + virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; + +protected: + virtual void layout(); + +private: + enum SubSupType { Sub, Sup, SubSup }; + SubSupType m_kind; + RenderBlock* m_scripts; +}; + +} + +#endif // ENABLE(MATHML) + +#endif // RenderMathMLSubSup_h + diff --git a/Source/WebCore/mathml/RenderMathMLUnderOver.cpp b/Source/WebCore/mathml/RenderMathMLUnderOver.cpp new file mode 100644 index 0000000..a3de697 --- /dev/null +++ b/Source/WebCore/mathml/RenderMathMLUnderOver.cpp @@ -0,0 +1,299 @@ +/* + * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(MATHML) + +#include "RenderMathMLUnderOver.h" + +#include "FontSelector.h" +#include "MathMLNames.h" + +namespace WebCore { + +using namespace MathMLNames; + +static const double gOverSpacingAdjustment = 0.5; + +RenderMathMLUnderOver::RenderMathMLUnderOver(Node* expression) + : RenderMathMLBlock(expression) +{ + Element* element = static_cast<Element*>(expression); + // Determine what kind of under/over expression we have by element name + + if (element->hasLocalName(MathMLNames::munderTag)) + m_kind = Under; + else if (element->hasLocalName(MathMLNames::moverTag)) + m_kind = Over; + else if (element->hasLocalName(MathMLNames::munderoverTag)) + m_kind = UnderOver; + else + m_kind = Under; + +} + +void RenderMathMLUnderOver::addChild(RenderObject* child, RenderObject* beforeChild) +{ + RenderMathMLBlock* row = new (renderArena()) RenderMathMLBlock(node()); + RefPtr<RenderStyle> rowStyle = makeBlockStyle(); + row->setStyle(rowStyle.release()); + + // look through the children for rendered elements counting the blocks so we know what child + // we are adding + int blocks = 0; + RenderObject* current = this->firstChild(); + while (current) { + blocks++; + current = current->nextSibling(); + } + + switch (blocks) { + case 0: + // this is the base so just append it + RenderBlock::addChild(row, beforeChild); + break; + case 1: + // the under or over + // FIXME: text-align: center does not work + row->style()->setTextAlign(CENTER); + if (m_kind == Over) { + // add the over as first + RenderBlock::addChild(row, firstChild()); + } else { + // add the under as last + RenderBlock::addChild(row, beforeChild); + } + break; + case 2: + // the under or over + // FIXME: text-align: center does not work + row->style()->setTextAlign(CENTER); + if (m_kind == UnderOver) { + // add the over as first + RenderBlock::addChild(row, firstChild()); + } else { + // we really shouldn't get here as only munderover should have three children + RenderBlock::addChild(row, beforeChild); + } + break; + default: + // munderover shouldn't have more than three children. In theory we shouldn't + // get here if the MathML is correctly formed, but that isn't a guarantee. + // We will treat this as another under element and they'll get something funky. + RenderBlock::addChild(row, beforeChild); + } + row->addChild(child); +} + +inline int getOffsetHeight(RenderObject* obj) +{ + if (obj->isBoxModelObject()) { + RenderBoxModelObject* box = toRenderBoxModelObject(obj); + return box->offsetHeight(); + } + + return 0; +} + +void RenderMathMLUnderOver::stretchToHeight(int height) +{ + + RenderObject* base = firstChild(); + if (!base) + return; + + // For over or underover, the base is the sibling of the first child + if (m_kind != Under) + base = base->nextSibling(); + + if (!base) + return; + + // use the child of the row which is the actual base + base = base->firstChild(); + + if (base && base->isRenderMathMLBlock()) { + RenderMathMLBlock* block = toRenderMathMLBlock(base); + block->stretchToHeight(height); + setNeedsLayout(true); + } +} + +void RenderMathMLUnderOver::layout() +{ + RenderBlock::layout(); + RenderObject* over = 0; + RenderObject* base = 0; + switch (m_kind) { + case Over: + // We need to calculate the baseline over the over versus the start of the base and + // adjust the placement of the base. + over = firstChild(); + if (over) { + // FIXME: descending glyphs intrude into base (e.g. lowercase y over base) + // FIXME: bases that ascend higher than the line box intrude into the over + if (!over->firstChild()->isBoxModelObject()) + break; + + int overSpacing = static_cast<int>(gOverSpacingAdjustment * (getOffsetHeight(over) - toRenderBoxModelObject(over->firstChild())->baselinePosition(AlphabeticBaseline, true, HorizontalLine))); + + // base row wrapper + base = over->nextSibling(); + if (base) { + if (overSpacing > 0) + base->style()->setMarginTop(Length(-overSpacing, Fixed)); + else + base->style()->setMarginTop(Length(0, Fixed)); + } + + } + break; + case Under: + // FIXME: Non-ascending glyphs in the under should be moved closer to the base + + // We need to calculate the baseline of the base versus the start of the under block and + // adjust the placement of the under block. + + // base row wrapper + base = firstChild(); + if (base) { + int baseHeight = getOffsetHeight(base); + // actual base + base = base->firstChild(); + if (!base->isBoxModelObject()) + break; + + // FIXME: We need to look at the space between a single maximum height of + // the line boxes and the baseline and squeeze them together + int underSpacing = baseHeight - toRenderBoxModelObject(base)->baselinePosition(AlphabeticBaseline, true, HorizontalLine); + + // adjust the base's intrusion into the under + RenderObject* under = lastChild(); + if (under && underSpacing > 0) + under->style()->setMarginTop(Length(-underSpacing, Fixed)); + } + break; + case UnderOver: + // FIXME: Non-descending glyphs in the over should be moved closer to the base + // FIXME: Non-ascending glyphs in the under should be moved closer to the base + + // We need to calculate the baseline of the over versus the start of the base and + // adjust the placement of the base. + + over = firstChild(); + if (over) { + // FIXME: descending glyphs intrude into base (e.g. lowercase y over base) + // FIXME: bases that ascend higher than the line box intrude into the over + if (!over->firstChild()->isBoxModelObject()) + break; + int overSpacing = static_cast<int>(gOverSpacingAdjustment * (getOffsetHeight(over) - toRenderBoxModelObject(over->firstChild())->baselinePosition(AlphabeticBaseline, true, HorizontalLine))); + + // base row wrapper + base = over->nextSibling(); + + if (base) { + if (overSpacing > 0) + base->style()->setMarginTop(Length(-overSpacing, Fixed)); + + // We need to calculate the baseline of the base versus the start of the under block and + // adjust the placement of the under block. + + int baseHeight = getOffsetHeight(base); + // actual base + base = base->firstChild(); + if (!base->isBoxModelObject()) + break; + + // FIXME: We need to look at the space between a single maximum height of + // the line boxes and the baseline and squeeze them together + int underSpacing = baseHeight - toRenderBoxModelObject(base)->baselinePosition(AlphabeticBaseline, true, HorizontalLine); + + RenderObject* under = lastChild(); + if (under && under->firstChild()->isRenderInline() && underSpacing > 0) + under->style()->setMarginTop(Length(-underSpacing, Fixed)); + + } + } + break; + } + setNeedsLayout(true); + RenderBlock::layout(); +} + +int RenderMathMLUnderOver::baselinePosition(FontBaseline, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const +{ + RenderObject* current = firstChild(); + if (!current) + return RenderBlock::baselinePosition(AlphabeticBaseline, firstLine, direction, linePositionMode); + + int baseline = 0; + switch (m_kind) { + case UnderOver: + case Over: + baseline += getOffsetHeight(current); + current = current->nextSibling(); + if (current) { + // actual base + RenderObject* base = current->firstChild(); + if (!base || !base->isBoxModelObject()) + break; + baseline += toRenderBoxModelObject(base)->baselinePosition(AlphabeticBaseline, firstLine, HorizontalLine, linePositionMode); + // added the negative top margin + baseline += current->style()->marginTop().value(); + } + break; + case Under: + RenderObject* base = current->firstChild(); + if (base && base->isBoxModelObject()) + baseline += toRenderBoxModelObject(base)->baselinePosition(AlphabeticBaseline, true, HorizontalLine); + } + + // FIXME: Where is the extra 2-3px adjusted for zoom coming from? + float zoomFactor = style()->effectiveZoom(); + baseline += static_cast<int>((zoomFactor > 1.25 ? 2 : 3) * zoomFactor); + return baseline; +} + + +int RenderMathMLUnderOver::nonOperatorHeight() const +{ + int nonOperators = 0; + for (RenderObject* current = firstChild(); current; current = current->nextSibling()) { + if (current->firstChild()->isRenderMathMLBlock()) { + RenderMathMLBlock* block = toRenderMathMLBlock(current->firstChild()); + if (!block->isRenderMathMLOperator()) + nonOperators += getOffsetHeight(current); + } else { + nonOperators += getOffsetHeight(current); + } + } + return nonOperators; +} + +} + + +#endif // ENABLE(MATHML) diff --git a/Source/WebCore/mathml/RenderMathMLUnderOver.h b/Source/WebCore/mathml/RenderMathMLUnderOver.h new file mode 100644 index 0000000..fbab72a --- /dev/null +++ b/Source/WebCore/mathml/RenderMathMLUnderOver.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef RenderMathMLUnderOver_h +#define RenderMathMLUnderOver_h + +#if ENABLE(MATHML) + +#include "RenderMathMLBlock.h" + +namespace WebCore { + +class RenderMathMLUnderOver : public RenderMathMLBlock { +public: + RenderMathMLUnderOver(Node* expression); + virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0); + virtual void layout(); + virtual bool hasBase() const { return true; } + virtual int nonOperatorHeight() const; + virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; + virtual void stretchToHeight(int pixelHeight); +private: + enum UnderOverType { Under, Over, UnderOver }; + UnderOverType m_kind; +}; + +} + +#endif // ENABLE(MATHML) + +#endif // RenderMathMLUnderOver_h diff --git a/Source/WebCore/mathml/mathattrs.in b/Source/WebCore/mathml/mathattrs.in new file mode 100644 index 0000000..4fda481 --- /dev/null +++ b/Source/WebCore/mathml/mathattrs.in @@ -0,0 +1,23 @@ +namespace="MathML" +namespaceURI="http://www.w3.org/1998/Math/MathML" +guardFactoryWith="ENABLE(MATHML)" +attrsNullNamespace + +background +close +color +definitionURL +denomalign +fontfamily +fontsize +fontstyle +fontweight +linethickness +mathbackground +mathcolor +mathsize +mathvariant +numalign +open +separators +stretchy diff --git a/Source/WebCore/mathml/mathtags.in b/Source/WebCore/mathml/mathtags.in new file mode 100644 index 0000000..b2dcb93 --- /dev/null +++ b/Source/WebCore/mathml/mathtags.in @@ -0,0 +1,27 @@ +namespace="MathML" +namespaceURI="http://www.w3.org/1998/Math/MathML" +guardFactoryWith="ENABLE(MATHML)" + +math +mfrac interfaceName=MathMLInlineContainerElement +mfenced interfaceName=MathMLInlineContainerElement +msubsup interfaceName=MathMLInlineContainerElement +mrow interfaceName=MathMLInlineContainerElement +mover interfaceName=MathMLInlineContainerElement +munder interfaceName=MathMLInlineContainerElement +munderover interfaceName=MathMLInlineContainerElement +msqrt interfaceName=MathMLInlineContainerElement +mroot interfaceName=MathMLInlineContainerElement +mi interfaceName=MathMLTextElement +mn interfaceName=MathMLTextElement +mo interfaceName=MathMLTextElement +mtext interfaceName=MathMLTextElement +msub interfaceName=MathMLInlineContainerElement +msup interfaceName=MathMLInlineContainerElement + +#if 0 // Curently only for MathMLNames used by HTMLTreeBuilder. +ms +mglyph +malignmark +annotation-xml +#endif |