RenderMathMLSubSup.cpp [plain text]
#include "config.h"
#if ENABLE(MATHML)
#include "RenderMathMLSubSup.h"
#include "MathMLNames.h"
namespace WebCore {
using namespace MathMLNames;
static const int gSubsupScriptMargin = 1;
RenderMathMLSubSup::RenderMathMLSubSup(Element* element)
: RenderMathMLBlock(element)
, m_scripts(0)
{
if (element->hasLocalName(MathMLNames::msubTag))
m_kind = Sub;
else if (element->hasLocalName(MathMLNames::msupTag))
m_kind = Sup;
else {
ASSERT(element->hasLocalName(MathMLNames::msubsupTag));
m_kind = SubSup;
}
}
RenderBoxModelObject* RenderMathMLSubSup::base() const
{
RenderObject* baseWrapper = firstChild();
if (!baseWrapper)
return 0;
RenderObject* base = baseWrapper->firstChild();
if (!base || !base->isBoxModelObject())
return 0;
return toRenderBoxModelObject(base);
}
void RenderMathMLSubSup::addChild(RenderObject* child, RenderObject* beforeChild)
{
Element* childElement = toElement(child->node());
if (childElement && !childElement->previousElementSibling()) {
RenderBlock* baseWrapper = createAlmostAnonymousBlock(INLINE_BLOCK);
RenderMathMLBlock::addChild(baseWrapper, firstChild());
baseWrapper->addChild(child);
if (m_kind == SubSup && !m_scripts) {
RefPtr<RenderStyle> scriptsStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), INLINE_BLOCK);
scriptsStyle->setVerticalAlign(TOP);
scriptsStyle->setMarginLeft(Length(gSubsupScriptMargin, Fixed));
scriptsStyle->setTextAlign(LEFT);
scriptsStyle->setBlendedFontSize(static_cast<int>(0.75 * style()->fontSize()));
m_scripts = new (renderArena()) RenderMathMLBlock(node());
m_scripts->setStyle(scriptsStyle);
RenderMathMLBlock::addChild(m_scripts, beforeChild);
}
} else {
if (m_kind == SubSup) {
ASSERT(childElement);
if (!childElement)
return;
RenderBlock* script = m_scripts->createAlmostAnonymousBlock();
Element* previousSibling = childElement->previousElementSibling();
if (previousSibling && !previousSibling->previousElementSibling())
m_scripts->addChild(script);
else
m_scripts->addChild(script, m_scripts->firstChild());
script->addChild(child);
} else
RenderMathMLBlock::addChild(child, beforeChild);
}
}
RenderMathMLOperator* RenderMathMLSubSup::unembellishedOperator()
{
RenderBoxModelObject* base = this->base();
if (!base || !base->isRenderMathMLBlock())
return 0;
return toRenderMathMLBlock(base)->unembellishedOperator();
}
void RenderMathMLSubSup::layout()
{
RenderBlock::layout();
if (m_kind != SubSup || !m_scripts)
return;
RenderBoxModelObject* base = this->base();
RenderObject* superscriptWrapper = m_scripts->firstChild();
RenderObject* subscriptWrapper = m_scripts->lastChild();
if (!base || !superscriptWrapper || !subscriptWrapper || superscriptWrapper == subscriptWrapper)
return;
ASSERT(superscriptWrapper->isRenderMathMLBlock());
ASSERT(subscriptWrapper->isRenderMathMLBlock());
RenderObject* superscript = superscriptWrapper->firstChild();
RenderObject* subscript = subscriptWrapper->firstChild();
if (!superscript || !subscript)
return;
LineDirectionMode lineDirection = style()->isHorizontalWritingMode() ? HorizontalLine : VerticalLine;
LayoutUnit baseBaseline = base->baselinePosition(AlphabeticBaseline, true, lineDirection);
LayoutUnit baseExtendUnderBaseline = getBoxModelObjectHeight(base) - baseBaseline;
LayoutUnit axis = style()->fontMetrics().xHeight() / 2;
LayoutUnit superscriptHeight = getBoxModelObjectHeight(superscript);
LayoutUnit subscriptHeight = getBoxModelObjectHeight(subscript);
LayoutUnit basePaddingTop = superscriptHeight + axis - baseBaseline;
LayoutUnit superPaddingBottom = max<LayoutUnit>(baseExtendUnderBaseline + axis - subscriptHeight, 0);
if (basePaddingTop < 0) {
superPaddingBottom += -basePaddingTop;
basePaddingTop = 0;
}
setChildNeedsLayout(true, MarkOnlyThis);
RenderObject* baseWrapper = firstChild();
baseWrapper->style()->setPaddingTop(Length(basePaddingTop, Fixed));
baseWrapper->setNeedsLayout(true, MarkOnlyThis);
superscriptWrapper->style()->setPaddingBottom(Length(superPaddingBottom, Fixed));
superscriptWrapper->setNeedsLayout(true, MarkOnlyThis);
m_scripts->setNeedsLayout(true, MarkOnlyThis);
RenderBlock::layout();
}
}
#endif // ENABLE(MATHML)