RenderMathMLRoot.cpp [plain text]
#include "config.h"
#if ENABLE(MATHML)
#include "RenderMathMLRoot.h"
#include "GraphicsContext.h"
#include "MathMLNames.h"
#include "PaintInfo.h"
using namespace std;
namespace WebCore {
using namespace MathMLNames;
const float gThresholdBaseHeightEms = 1.5f;
const float gFrontWidthEms = 0.75f;
const float gSpaceAboveEms = 0.2f;
const float gRadicalBottomPointXFront = 0.5f;
const int gRadicalBottomPointLower = 3;
const float gRadicalDipLeftPointXFront = 0.8f;
const float gRadicalDipLeftPointYPos = 0.625f;
const float gRadicalLeftEndYShiftEms = 0.05f;
const float gBigRootBottomPaddingEms = 0.2f;
const float gRadicalLineThicknessEms = 0.02f;
const float gRadicalThickLineThicknessEms = 0.1f;
RenderMathMLRoot::RenderMathMLRoot(Element* element)
: RenderMathMLBlock(element)
{
}
RenderBoxModelObject* RenderMathMLRoot::index() const
{
if (!firstChild())
return 0;
RenderObject* index = firstChild()->nextSibling();
if (!index || !index->isBoxModelObject())
return 0;
return toRenderBoxModelObject(index);
}
void RenderMathMLRoot::paint(PaintInfo& info, const LayoutPoint& paintOffset)
{
RenderMathMLBlock::paint(info, paintOffset);
if (info.context->paintingDisabled())
return;
if (!index())
return;
IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset + location() + computedCSSContentBoxRect().location());
int baseHeight = roundToInt(getBoxModelObjectHeight(firstChild()));
int overbarWidth = roundToInt(getBoxModelObjectWidth(firstChild())) + m_overbarLeftPointShift;
int indexWidth = index()->pixelSnappedOffsetWidth();
int frontWidth = static_cast<int>(roundf(gFrontWidthEms * style()->fontSize()));
int startX = adjustedPaintOffset.x() + indexWidth + m_overbarLeftPointShift;
int rootPad = static_cast<int>(roundf(gSpaceAboveEms * style()->fontSize()));
adjustedPaintOffset.setY(adjustedPaintOffset.y() + m_intrinsicPaddingBefore - rootPad);
FloatPoint overbarLeftPoint(startX - m_overbarLeftPointShift, adjustedPaintOffset.y());
FloatPoint bottomPoint(startX - gRadicalBottomPointXFront * frontWidth, adjustedPaintOffset.y() + baseHeight + gRadicalBottomPointLower);
FloatPoint dipLeftPoint(startX - gRadicalDipLeftPointXFront * frontWidth, adjustedPaintOffset.y() + gRadicalDipLeftPointYPos * baseHeight);
FloatPoint leftEnd(startX - frontWidth, dipLeftPoint.y() + gRadicalLeftEndYShiftEms * style()->fontSize());
GraphicsContextStateSaver stateSaver(*info.context);
info.context->setStrokeThickness(gRadicalLineThicknessEms * 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(overbarLeftPoint.x() + overbarWidth, adjustedPaintOffset.y()));
root.addLineTo(overbarLeftPoint);
root.addLineTo(bottomPoint);
root.addLineTo(dipLeftPoint);
root.addLineTo(leftEnd);
info.context->strokePath(root);
GraphicsContextStateSaver maskStateSaver(*info.context);
Path mask;
mask.moveTo(overbarLeftPoint);
mask.addLineTo(bottomPoint);
mask.addLineTo(dipLeftPoint);
mask.addLineTo(FloatPoint(2 * dipLeftPoint.x() - leftEnd.x(), 2 * dipLeftPoint.y() - leftEnd.y()));
info.context->clip(mask);
info.context->setStrokeThickness(gRadicalThickLineThicknessEms * style()->fontSize());
info.context->setLineCap(SquareCap);
Path line;
line.moveTo(bottomPoint);
line.addLineTo(dipLeftPoint);
info.context->strokePath(line);
}
void RenderMathMLRoot::layout()
{
RenderBlock::layout();
if (!index())
return;
int baseHeight = roundToInt(getBoxModelObjectHeight(firstChild()));
float thresholdHeight = gThresholdBaseHeightEms * style()->fontSize();
if (baseHeight > thresholdHeight && thresholdHeight) {
float shift = min<float>((baseHeight - thresholdHeight) / thresholdHeight, 1.0f);
int frontWidth = static_cast<int>(roundf(gFrontWidthEms * style()->fontSize()));
m_overbarLeftPointShift = static_cast<int>(shift * gRadicalBottomPointXFront * frontWidth);
m_intrinsicPaddingAfter = static_cast<int>(roundf(gBigRootBottomPaddingEms * style()->fontSize()));
} else {
m_overbarLeftPointShift = 0;
m_intrinsicPaddingAfter = 0;
}
RenderBoxModelObject* index = this->index();
m_intrinsicPaddingStart = index->pixelSnappedOffsetWidth() + m_overbarLeftPointShift;
int rootPad = static_cast<int>(roundf(gSpaceAboveEms * style()->fontSize()));
int partDipHeight = static_cast<int>(roundf((1 - gRadicalDipLeftPointYPos) * baseHeight));
int rootExtraTop = partDipHeight + index->pixelSnappedOffsetHeight() - (baseHeight + rootPad);
m_intrinsicPaddingBefore = rootPad + max(rootExtraTop, 0);
setNeedsLayout(true, MarkOnlyThis);
setPreferredLogicalWidthsDirty(true, MarkOnlyThis); RenderBlock::layout();
if (rootExtraTop < 0 && index->isBox())
toRenderBox(index)->setLogicalTop(-rootExtraTop);
}
}
#endif // ENABLE(MATHML)