RenderMathMLUnderOver.cpp [plain text]
#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);
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());
int blocks = 0;
RenderObject* current = this->firstChild();
while (current) {
blocks++;
current = current->nextSibling();
}
switch (blocks) {
case 0:
RenderBlock::addChild(row, beforeChild);
break;
case 1:
row->style()->setTextAlign(CENTER);
if (m_kind == Over) {
RenderBlock::addChild(row, firstChild());
} else {
RenderBlock::addChild(row, beforeChild);
}
break;
case 2:
row->style()->setTextAlign(CENTER);
if (m_kind == UnderOver) {
RenderBlock::addChild(row, firstChild());
} else {
RenderBlock::addChild(row, beforeChild);
}
break;
default:
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;
if (m_kind != Under)
base = base->nextSibling();
if (!base)
return;
base = base->firstChild();
if (base && base->isRenderMathMLBlock()) {
RenderMathMLBlock* block = toRenderMathMLBlock(base);
block->stretchToHeight(height);
updateBoxModelInfoFromStyle();
setNeedsLayoutAndPrefWidthsRecalc();
markContainingBlocksForLayout();
}
}
void RenderMathMLUnderOver::layout()
{
RenderBlock::layout();
RenderObject* over = 0;
RenderObject* base = 0;
switch (m_kind) {
case Over:
over = firstChild();
if (over) {
int overSpacing = static_cast<int>(gOverSpacingAdjustment * (getOffsetHeight(over) - over->firstChild()->baselinePosition(true)));
base = over->nextSibling();
if (base) {
if (overSpacing > 0)
base->style()->setMarginTop(Length(-overSpacing, Fixed));
else
base->style()->setMarginTop(Length(0, Fixed));
}
}
break;
case Under:
base = firstChild();
if (base) {
int baseHeight = getOffsetHeight(base);
base = base->firstChild();
int underSpacing = baseHeight - base->baselinePosition(true);
RenderObject* under = lastChild();
if (under && underSpacing > 0)
under->style()->setMarginTop(Length(-underSpacing, Fixed));
}
break;
case UnderOver:
over = firstChild();
if (over) {
int overSpacing = static_cast<int>(gOverSpacingAdjustment * (getOffsetHeight(over) - over->firstChild()->baselinePosition(true)));
base = over->nextSibling();
if (base) {
if (overSpacing > 0)
base->style()->setMarginTop(Length(-overSpacing, Fixed));
int baseHeight = getOffsetHeight(base);
base = base->firstChild();
int underSpacing = baseHeight - base->baselinePosition(true);
RenderObject* under = lastChild();
if (under && under->firstChild()->isRenderInline() && underSpacing > 0)
under->style()->setMarginTop(Length(-underSpacing, Fixed));
}
}
break;
}
setNeedsLayoutAndPrefWidthsRecalc();
RenderBlock::layout();
}
int RenderMathMLUnderOver::baselinePosition(bool, bool) const
{
int baseline = 0;
RenderObject* current = 0;
switch (m_kind) {
case UnderOver:
case Over:
current = firstChild();
baseline += getOffsetHeight(current);
current = current->nextSibling();
if (current) {
RenderObject* base = current->firstChild();
baseline += base->baselinePosition(true);
baseline += current->style()->marginTop().value();
}
break;
case Under:
current = firstChild();
if (current) {
RenderObject* base = current->firstChild();
baseline += base->baselinePosition(true);
}
}
return baseline;
}
int RenderMathMLUnderOver::nonOperatorHeight() const
{
return 0;
}
}
#endif // ENABLE(MATHML)