summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2015-10-15 09:45:50 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2015-10-15 09:45:50 +0000
commite15dd966d523731101f70ccf768bba12435a0208 (patch)
treeae9cb828a24ded2585a41af3f21411523b47897d /Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp
downloadWebKitGtk-tarball-e15dd966d523731101f70ccf768bba12435a0208.tar.gz
webkitgtk-2.10.2webkitgtk-2.10.2
Diffstat (limited to 'Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp')
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp518
1 files changed, 518 insertions, 0 deletions
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp b/Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp
new file mode 100644
index 000000000..d17f9ad63
--- /dev/null
+++ b/Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp
@@ -0,0 +1,518 @@
+/*
+ * Copyright (C) 2010 Alex Milowski (alex@milowski.com). All rights reserved.
+ * Copyright (C) 2013 The MathJax Consortium.
+ *
+ * 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 "RenderMathMLScripts.h"
+
+#include "MathMLElement.h"
+
+namespace WebCore {
+
+using namespace MathMLNames;
+
+// RenderMathMLScripts implements various MathML elements drawing scripts attached to a base. For valid MathML elements, the structure of the render tree should be:
+//
+// - msub, msup, msubsup: BaseWrapper SubSupPairWrapper
+// - mmultiscripts: BaseWrapper SubSupPairWrapper* (mprescripts SubSupPairWrapper*)*
+//
+// where BaseWrapper and SubSupPairWrapper do not contain any <mprescripts/> children. In addition, BaseWrapper must have one child and SubSupPairWrapper must have either one child (msub, msup) or two children (msubsup, mmultiscripts).
+//
+// In order to accept invalid markup and to handle the script elements consistently and uniformly, we will use a more general structure that encompasses both valid and invalid elements:
+//
+// BaseWrapper SubSupPairWrapper* (mprescripts SubSupPairWrapper*)*
+//
+// where BaseWrapper can now be empty and SubSupPairWrapper can now have one or two elements.
+//
+
+static bool isPrescript(const RenderObject& renderObject)
+{
+ return renderObject.node() && renderObject.node()->hasTagName(MathMLNames::mprescriptsTag);
+}
+
+RenderMathMLScripts::RenderMathMLScripts(Element& element, Ref<RenderStyle>&& style)
+ : RenderMathMLBlock(element, WTF::move(style))
+ , m_baseWrapper(0)
+{
+ // Determine what kind of sub/sup expression we have by element name
+ if (element.hasTagName(MathMLNames::msubTag))
+ m_kind = Sub;
+ else if (element.hasTagName(MathMLNames::msupTag))
+ m_kind = Super;
+ else if (element.hasTagName(MathMLNames::msubsupTag))
+ m_kind = SubSup;
+ else {
+ ASSERT(element.hasTagName(MathMLNames::mmultiscriptsTag));
+ m_kind = Multiscripts;
+ }
+}
+
+RenderBoxModelObject* RenderMathMLScripts::base() const
+{
+ if (!m_baseWrapper)
+ return nullptr;
+ RenderObject* base = m_baseWrapper->firstChild();
+ if (!is<RenderBoxModelObject>(base))
+ return nullptr;
+ return downcast<RenderBoxModelObject>(base);
+}
+
+void RenderMathMLScripts::fixAnonymousStyleForSubSupPair(RenderObject* subSupPair, bool isPostScript)
+{
+ ASSERT(subSupPair && subSupPair->style().refCount() == 1);
+ RenderStyle& scriptsStyle = subSupPair->style();
+
+ // subSup pairs are drawn in column from bottom (subscript) to top (superscript).
+ scriptsStyle.setFlexDirection(FlowColumnReverse);
+
+ // The MathML specification does not specify horizontal alignment of
+ // scripts. We align the bottom (respectively top) edge of the subscript
+ // (respectively superscript) with the bottom (respectively top) edge of
+ // the flex container. Note that for valid <msub> and <msup> elements, the
+ // subSupPair should actually have only one script.
+ if (m_kind == Sub)
+ scriptsStyle.setJustifyContentPosition(ContentPositionFlexStart);
+ else if (m_kind == Super)
+ scriptsStyle.setJustifyContentPosition(ContentPositionFlexEnd);
+ else
+ scriptsStyle.setJustifyContentDistribution(ContentDistributionSpaceBetween);
+
+ // The MathML specification does not specify vertical alignment of scripts.
+ // Let's right align prescripts and left align postscripts.
+ // See http://lists.w3.org/Archives/Public/www-math/2012Aug/0006.html
+ scriptsStyle.setAlignItemsPosition(isPostScript ? ItemPositionFlexStart : ItemPositionFlexEnd);
+
+ // We set the order property so that the prescripts are drawn before the base.
+ scriptsStyle.setOrder(isPostScript ? 0 : -1);
+
+ // We set this wrapper's font-size for its line-height.
+ LayoutUnit scriptSize = static_cast<int>(0.75 * style().fontSize());
+ scriptsStyle.setFontSize(scriptSize);
+}
+
+void RenderMathMLScripts::fixAnonymousStyles()
+{
+ // We set the base wrapper's style so that baseHeight in layout() will be an unstretched height.
+ ASSERT(m_baseWrapper && m_baseWrapper->style().hasOneRef());
+ m_baseWrapper->style().setAlignSelfPosition(ItemPositionFlexStart);
+
+ // This sets the style for postscript pairs.
+ RenderObject* subSupPair = m_baseWrapper;
+ for (subSupPair = subSupPair->nextSibling(); subSupPair && !isPrescript(*subSupPair); subSupPair = subSupPair->nextSibling())
+ fixAnonymousStyleForSubSupPair(subSupPair, true);
+
+ if (subSupPair && m_kind == Multiscripts) {
+ // This sets the style for prescript pairs.
+ for (subSupPair = subSupPair->nextSibling(); subSupPair && !isPrescript(*subSupPair); subSupPair = subSupPair->nextSibling())
+ fixAnonymousStyleForSubSupPair(subSupPair, false);
+ }
+
+ // This resets style for extra subSup pairs.
+ for (; subSupPair; subSupPair = subSupPair->nextSibling()) {
+ if (!isPrescript(*subSupPair)) {
+ ASSERT(subSupPair && subSupPair->style().refCount() == 1);
+ RenderStyle& scriptsStyle = subSupPair->style();
+ scriptsStyle.setFlexDirection(FlowRow);
+ scriptsStyle.setJustifyContentPosition(ContentPositionFlexStart);
+ scriptsStyle.setAlignItemsPosition(ItemPositionCenter);
+ scriptsStyle.setOrder(0);
+ scriptsStyle.setFontSize(style().fontSize());
+ }
+ }
+}
+
+void RenderMathMLScripts::addChildInternal(bool doNotRestructure, RenderObject* child, RenderObject* beforeChild)
+{
+ if (doNotRestructure) {
+ RenderMathMLBlock::addChild(child, beforeChild);
+ return;
+ }
+
+ if (beforeChild) {
+ // beforeChild may be a grandchild, so we call the addChild function of the corresponding wrapper instead.
+ RenderObject* parent = beforeChild->parent();
+ if (parent != this) {
+ RenderMathMLBlock& parentBlock = downcast<RenderMathMLBlock>(*parent);
+ if (is<RenderMathMLScriptsWrapper>(parentBlock)) {
+ RenderMathMLScriptsWrapper& wrapper = downcast<RenderMathMLScriptsWrapper>(parentBlock);
+ wrapper.addChildInternal(false, child, beforeChild);
+ return;
+ }
+ }
+ }
+
+ if (beforeChild == m_baseWrapper) {
+ // This is like inserting the child at the beginning of the base wrapper.
+ m_baseWrapper->addChildInternal(false, child, m_baseWrapper->firstChild());
+ return;
+ }
+
+ if (isPrescript(*child)) {
+ // The new child becomes an <mprescripts/> separator.
+ RenderMathMLBlock::addChild(child, beforeChild);
+ return;
+ }
+
+ if (!beforeChild || isPrescript(*beforeChild)) {
+ // We are at the end of a sequence of subSup pairs.
+ RenderMathMLBlock* previousSibling = downcast<RenderMathMLBlock>(beforeChild ? beforeChild->previousSibling() : lastChild());
+ if (is<RenderMathMLScriptsWrapper>(previousSibling)) {
+ RenderMathMLScriptsWrapper& wrapper = downcast<RenderMathMLScriptsWrapper>(*previousSibling);
+ if ((wrapper.m_kind == RenderMathMLScriptsWrapper::Base && wrapper.isEmpty()) || (wrapper.m_kind == RenderMathMLScriptsWrapper::SubSupPair && !wrapper.firstChild()->nextSibling())) {
+ // The previous sibling is either an empty base or a SubSup pair with a single child so we can insert the new child into that wrapper.
+ wrapper.addChildInternal(true, child);
+ return;
+ }
+ }
+ // Otherwise we create a new subSupPair to store the new child.
+ RenderMathMLScriptsWrapper* subSupPair = RenderMathMLScriptsWrapper::createAnonymousWrapper(this, RenderMathMLScriptsWrapper::SubSupPair);
+ subSupPair->addChildInternal(true, child);
+ RenderMathMLBlock::addChild(subSupPair, beforeChild);
+ return;
+ }
+
+ // beforeChild is a subSup pair. This is like inserting the new child at the beginning of the subSup wrapper.
+ RenderMathMLScriptsWrapper& wrapper = downcast<RenderMathMLScriptsWrapper>(*beforeChild);
+ ASSERT(wrapper.m_kind == RenderMathMLScriptsWrapper::SubSupPair);
+ ASSERT(!(m_baseWrapper->isEmpty() && m_baseWrapper->nextSibling() == beforeChild));
+ wrapper.addChildInternal(false, child, wrapper.firstChild());
+}
+
+void RenderMathMLScripts::removeChildInternal(bool doNotRestructure, RenderObject& child)
+{
+ if (doNotRestructure) {
+ RenderMathMLBlock::removeChild(child);
+ return;
+ }
+
+ ASSERT(isPrescript(child));
+
+ RenderObject* previousSibling = child.previousSibling();
+ RenderObject* nextSibling = child.nextSibling();
+ ASSERT(previousSibling);
+
+ if (nextSibling && !isPrescript(*previousSibling) && !isPrescript(*nextSibling)) {
+ RenderMathMLScriptsWrapper& previousWrapper = downcast<RenderMathMLScriptsWrapper>(*previousSibling);
+ RenderMathMLScriptsWrapper& nextWrapper = downcast<RenderMathMLScriptsWrapper>(*nextSibling);
+ ASSERT(nextWrapper.m_kind == RenderMathMLScriptsWrapper::SubSupPair && !nextWrapper.isEmpty());
+ if ((previousWrapper.m_kind == RenderMathMLScriptsWrapper::Base && previousWrapper.isEmpty()) || (previousWrapper.m_kind == RenderMathMLScriptsWrapper::SubSupPair && !previousWrapper.firstChild()->nextSibling())) {
+ RenderObject* script = nextWrapper.firstChild();
+ nextWrapper.removeChildInternal(false, *script);
+ previousWrapper.addChildInternal(true, script);
+ }
+ }
+
+ RenderMathMLBlock::removeChild(child);
+}
+
+void RenderMathMLScripts::addChild(RenderObject* child, RenderObject* beforeChild)
+{
+ if (isEmpty()) {
+ m_baseWrapper = RenderMathMLScriptsWrapper::createAnonymousWrapper(this, RenderMathMLScriptsWrapper::Base);
+ RenderMathMLBlock::addChild(m_baseWrapper);
+ }
+
+ addChildInternal(false, child, beforeChild);
+
+ fixAnonymousStyles();
+}
+
+void RenderMathMLScripts::removeChild(RenderObject& child)
+{
+ if (beingDestroyed() || documentBeingDestroyed()) {
+ // The renderer is being destroyed so we remove the child normally.
+ RenderMathMLBlock::removeChild(child);
+ return;
+ }
+
+ removeChildInternal(false, child);
+ fixAnonymousStyles();
+}
+
+void RenderMathMLScripts::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+ RenderMathMLBlock::styleDidChange(diff, oldStyle);
+
+ if (!isEmpty())
+ fixAnonymousStyles();
+}
+
+RenderMathMLOperator* RenderMathMLScripts::unembellishedOperator()
+{
+ RenderBoxModelObject* base = this->base();
+ if (!is<RenderMathMLBlock>(base))
+ return nullptr;
+ return downcast<RenderMathMLBlock>(*base).unembellishedOperator();
+}
+
+void RenderMathMLScripts::layout()
+{
+ RenderMathMLBlock::layout();
+
+ if (!m_baseWrapper)
+ return;
+ RenderBox* base = m_baseWrapper->firstChildBox();
+ if (!base)
+ return;
+
+ // Our layout rules include: Don't let the superscript go below the "axis" (half x-height above the
+ // baseline), or the subscript above the axis. Also, don't let the superscript's top edge be
+ // below the base's top edge, or the subscript's bottom edge above the base's bottom edge.
+
+ LayoutUnit baseHeight = base->logicalHeight();
+ LayoutUnit baseBaseline = base->firstLineBaseline().valueOr(baseHeight);
+ LayoutUnit axis = style().fontMetrics().xHeight() / 2;
+ int fontSize = style().fontSize();
+
+ ASSERT(m_baseWrapper->style().hasOneRef());
+ bool needsSecondLayout = false;
+
+ LayoutUnit topPadding = 0;
+ LayoutUnit bottomPadding = 0;
+
+ Element* scriptElement = element();
+ LayoutUnit superscriptShiftValue = 0;
+ LayoutUnit subscriptShiftValue = 0;
+ if (m_kind == Sub || m_kind == SubSup || m_kind == Multiscripts)
+ parseMathMLLength(scriptElement->fastGetAttribute(MathMLNames::subscriptshiftAttr), subscriptShiftValue, &style(), false);
+ if (m_kind == Super || m_kind == SubSup || m_kind == Multiscripts)
+ parseMathMLLength(scriptElement->fastGetAttribute(MathMLNames::superscriptshiftAttr), superscriptShiftValue, &style(), false);
+
+ bool isPostScript = true;
+ RenderMathMLBlock* subSupPair = downcast<RenderMathMLBlock>(m_baseWrapper->nextSibling());
+ for (; subSupPair; subSupPair = downcast<RenderMathMLBlock>(subSupPair->nextSibling())) {
+
+ // We skip the base and <mprescripts/> elements.
+ if (isPrescript(*subSupPair)) {
+ if (!isPostScript)
+ break;
+ isPostScript = false;
+ continue;
+ }
+
+ if (RenderBox* superscript = m_kind == Sub ? 0 : subSupPair->lastChildBox()) {
+ LayoutUnit superscriptHeight = superscript->logicalHeight();
+ LayoutUnit superscriptBaseline = superscript->firstLineBaseline().valueOr(superscriptHeight);
+ LayoutUnit minBaseline = std::max<LayoutUnit>(fontSize / 3 + 1 + superscriptBaseline, superscriptHeight + axis + superscriptShiftValue);
+
+ topPadding = std::max<LayoutUnit>(topPadding, minBaseline - baseBaseline);
+ }
+
+ if (RenderBox* subscript = m_kind == Super ? 0 : subSupPair->firstChildBox()) {
+ LayoutUnit subscriptHeight = subscript->logicalHeight();
+ LayoutUnit subscriptBaseline = subscript->firstLineBaseline().valueOr(subscriptHeight);
+ LayoutUnit baseExtendUnderBaseline = baseHeight - baseBaseline;
+ LayoutUnit subscriptUnderItsBaseline = subscriptHeight - subscriptBaseline;
+ LayoutUnit minExtendUnderBaseline = std::max<LayoutUnit>(fontSize / 5 + 1 + subscriptUnderItsBaseline, subscriptHeight + subscriptShiftValue - axis);
+
+ bottomPadding = std::max<LayoutUnit>(bottomPadding, minExtendUnderBaseline - baseExtendUnderBaseline);
+ }
+ }
+
+ Length newPadding(topPadding, Fixed);
+ if (newPadding != m_baseWrapper->style().paddingTop()) {
+ m_baseWrapper->style().setPaddingTop(newPadding);
+ needsSecondLayout = true;
+ }
+
+ newPadding = Length(bottomPadding, Fixed);
+ if (newPadding != m_baseWrapper->style().paddingBottom()) {
+ m_baseWrapper->style().setPaddingBottom(newPadding);
+ needsSecondLayout = true;
+ }
+
+ if (!needsSecondLayout)
+ return;
+
+ setNeedsLayout(MarkOnlyThis);
+ m_baseWrapper->setChildNeedsLayout(MarkOnlyThis);
+
+ RenderMathMLBlock::layout();
+}
+
+Optional<int> RenderMathMLScripts::firstLineBaseline() const
+{
+ if (m_baseWrapper) {
+ if (Optional<int> baseline = m_baseWrapper->firstLineBaseline())
+ return baseline;
+ }
+ return RenderMathMLBlock::firstLineBaseline();
+}
+
+RenderMathMLScriptsWrapper* RenderMathMLScriptsWrapper::createAnonymousWrapper(RenderMathMLScripts* renderObject, WrapperType type)
+{
+ RenderMathMLScriptsWrapper* newBlock = new RenderMathMLScriptsWrapper(renderObject->document(), RenderStyle::createAnonymousStyleWithDisplay(&renderObject->style(), FLEX), type);
+ newBlock->initializeStyle();
+ return newBlock;
+}
+
+void RenderMathMLScriptsWrapper::addChildInternal(bool doNotRestructure, RenderObject* child, RenderObject* beforeChild)
+{
+ if (doNotRestructure) {
+ RenderMathMLBlock::addChild(child, beforeChild);
+ return;
+ }
+
+ RenderMathMLScripts* parentNode = downcast<RenderMathMLScripts>(parent());
+
+ if (m_kind == Base) {
+ RenderObject* sibling = nextSibling();
+
+ if (!isEmpty() && !beforeChild) {
+ // This is like inserting the child after the base wrapper.
+ parentNode->addChildInternal(false, sibling);
+ return;
+ }
+
+ // The old base (if any) becomes a script ; the new child becomes either the base or an <mprescripts> separator.
+ RenderObject* oldBase = firstChild();
+ if (oldBase)
+ RenderMathMLBlock::removeChild(*oldBase);
+ if (isPrescript(*child))
+ parentNode->addChildInternal(true, child, sibling);
+ else
+ RenderMathMLBlock::addChild(child);
+ if (oldBase)
+ parentNode->addChildInternal(false, oldBase, sibling);
+ return;
+ }
+
+ if (isPrescript(*child)) {
+ // We insert an <mprescripts> element.
+ if (!beforeChild)
+ parentNode->addChildInternal(true, child, nextSibling());
+ else if (beforeChild == firstChild())
+ parentNode->addChildInternal(true, child, this);
+ else {
+ // We insert the <mprescripts> in the middle of a subSup pair so we must split that pair.
+ RenderObject* sibling = nextSibling();
+ parentNode->removeChildInternal(true, *this);
+ parentNode->addChildInternal(true, child, sibling);
+
+ RenderObject* script = firstChild();
+ RenderMathMLBlock::removeChild(*script);
+ parentNode->addChildInternal(false, script, child);
+
+ script = beforeChild;
+ RenderMathMLBlock::removeChild(*script);
+ parentNode->addChildInternal(false, script, sibling);
+ destroy();
+ }
+ return;
+ }
+
+ // We first move to the last subSup pair in the curent sequence of scripts.
+ RenderMathMLScriptsWrapper* subSupPair = this;
+ while (subSupPair->nextSibling() && !isPrescript(*subSupPair->nextSibling()))
+ subSupPair = downcast<RenderMathMLScriptsWrapper>(subSupPair->nextSibling());
+ if (subSupPair->firstChild()->nextSibling()) {
+ // The last pair has two children so we need to create a new pair to leave room for the new child.
+ RenderMathMLScriptsWrapper* newPair = createAnonymousWrapper(parentNode, RenderMathMLScriptsWrapper::SubSupPair);
+ parentNode->addChildInternal(true, newPair, subSupPair->nextSibling());
+ subSupPair = newPair;
+ }
+
+ // We shift the successors in the current sequence of scripts.
+ for (RenderObject* previousSibling = subSupPair->previousSibling(); subSupPair != this; previousSibling = previousSibling->previousSibling()) {
+ RenderMathMLScriptsWrapper& previousSubSupPair = downcast<RenderMathMLScriptsWrapper>(*previousSibling);
+ RenderObject* script = previousSubSupPair.lastChild();
+ previousSubSupPair.removeChildInternal(true, *script);
+ subSupPair->addChildInternal(true, script, subSupPair->firstChild());
+ subSupPair = downcast<RenderMathMLScriptsWrapper>(previousSibling);
+ }
+
+ // This subSup pair now contain one element which is either beforeChild or the script that was before. Hence we can insert the new child before of after that element.
+ RenderMathMLBlock::addChild(child, firstChild() == beforeChild ? beforeChild : nullptr);
+}
+
+void RenderMathMLScriptsWrapper::addChild(RenderObject* child, RenderObject* beforeChild)
+{
+ RenderMathMLScripts* parentNode = downcast<RenderMathMLScripts>(parent());
+
+ addChildInternal(false, child, beforeChild);
+
+ parentNode->fixAnonymousStyles();
+}
+
+void RenderMathMLScriptsWrapper::removeChildInternal(bool doNotRestructure, RenderObject& child)
+{
+ if (doNotRestructure) {
+ RenderMathMLBlock::removeChild(child);
+ return;
+ }
+
+ RenderMathMLScripts* parentNode = downcast<RenderMathMLScripts>(parent());
+
+ if (m_kind == Base) {
+ // We remove the child from the base wrapper.
+ RenderObject* sibling = nextSibling();
+ RenderMathMLBlock::removeChild(child);
+ if (sibling && !isPrescript(*sibling)) {
+ // If there are postscripts, the first one becomes the base.
+ RenderMathMLScriptsWrapper& wrapper = downcast<RenderMathMLScriptsWrapper>(*sibling);
+ RenderObject* script = wrapper.firstChild();
+ wrapper.removeChildInternal(false, *script);
+ RenderMathMLBlock::addChild(script);
+ }
+ return;
+ }
+
+ // We remove the child and shift the successors in the current sequence of scripts.
+ RenderMathMLBlock::removeChild(child);
+ RenderMathMLScriptsWrapper* subSupPair = this;
+ for (RenderObject* nextSibling = subSupPair->nextSibling(); nextSibling && !isPrescript(*nextSibling); nextSibling = nextSibling->nextSibling()) {
+ RenderMathMLScriptsWrapper& nextSubSupPair = downcast<RenderMathMLScriptsWrapper>(*nextSibling);
+ RenderObject* script = nextSubSupPair.firstChild();
+ nextSubSupPair.removeChildInternal(true, *script);
+ subSupPair->addChildInternal(true, script);
+ subSupPair = downcast<RenderMathMLScriptsWrapper>(nextSibling);
+ }
+
+ // We remove the last subSup pair if it became empty.
+ if (subSupPair->isEmpty()) {
+ parentNode->removeChildInternal(true, *subSupPair);
+ subSupPair->destroy();
+ }
+}
+
+void RenderMathMLScriptsWrapper::removeChild(RenderObject& child)
+{
+ if (beingDestroyed() || documentBeingDestroyed()) {
+ // The renderer is being destroyed so we remove the child normally.
+ RenderMathMLBlock::removeChild(child);
+ return;
+ }
+
+ RenderMathMLScripts* parentNode = downcast<RenderMathMLScripts>(parent());
+ removeChildInternal(false, child);
+ parentNode->fixAnonymousStyles();
+}
+
+}
+
+#endif // ENABLE(MATHML)