RenderMathMLSquareRoot.cpp [plain text]
#include "config.h"
#if ENABLE(MATHML)
#include "RenderMathMLSquareRoot.h"
#include "GraphicsContext.h"
#include "MathMLNames.h"
#include "PaintInfo.h"
#include "RenderMathMLRow.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.5f;
const float gRadicalLeftEndYShiftEms = 0.05f;
const float gBigRootBottomPaddingEms = 0.2f;
const float gRadicalLineThicknessEms = 0.02f;
const float gRadicalThickLineThicknessEms = 0.1f;
RenderMathMLSquareRoot::RenderMathMLSquareRoot(Element* element)
: RenderMathMLBlock(element)
{
}
void RenderMathMLSquareRoot::addChild(RenderObject* newChild, RenderObject* beforeChild)
{
if (!firstChild()) {
RenderMathMLRow* newMRow = RenderMathMLRow::createAnonymousWithParentRenderer(this);
RenderMathMLBlock::addChild(newMRow);
ASSERT(!newMRow->isAnonymousBlock());
}
ASSERT(firstChild() && firstChild()->isAnonymous() && firstChild()->isRenderMathMLBlock() && toRenderMathMLBlock(firstChild())->isRenderMathMLRow());
firstChild()->addChild(newChild, beforeChild);
}
void RenderMathMLSquareRoot::computePreferredLogicalWidths()
{
m_intrinsicPaddingStart = static_cast<int>(roundf(gFrontWidthEms * style()->fontSize()));
RenderMathMLBlock::computePreferredLogicalWidths();
}
void RenderMathMLSquareRoot::computeLogicalHeight()
{
int baseHeight = roundToInt(getBoxModelObjectHeight(firstChild()));
float thresholdHeight = gThresholdBaseHeightEms * style()->fontSize();
m_intrinsicPaddingAfter = baseHeight > thresholdHeight ? static_cast<int>(roundf(gBigRootBottomPaddingEms * style()->fontSize())) : 0;
setLogicalHeight(baseHeight + borderAndPaddingLogicalHeight());
RenderMathMLBlock::computeLogicalHeight();
}
void RenderMathMLSquareRoot::layout()
{
m_intrinsicPaddingBefore = static_cast<int>(roundf(gSpaceAboveEms * style()->fontSize()));
RenderMathMLBlock::layout();
}
void RenderMathMLSquareRoot::paint(PaintInfo& info, const LayoutPoint& paintOffset)
{
RenderMathMLBlock::paint(info, paintOffset);
if (info.context->paintingDisabled())
return;
IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset + location() + computedCSSContentBoxRect().location());
int baseHeight = roundToInt(getBoxModelObjectHeight(firstChild()));
int overbarWidth = roundToInt(getBoxModelObjectWidth(firstChild()));
int frontWidth = m_intrinsicPaddingStart;
int overbarLeftPointShift = 0;
float thresholdHeight = gThresholdBaseHeightEms * style()->fontSize();
if (baseHeight > thresholdHeight && thresholdHeight) {
float shift = min<float>((baseHeight - thresholdHeight) / thresholdHeight, 1.0f);
overbarLeftPointShift = static_cast<int>(shift * gRadicalBottomPointXFront * frontWidth);
}
overbarWidth += overbarLeftPointShift;
int startX = adjustedPaintOffset.x() + frontWidth;
FloatPoint overbarLeftPoint(startX - 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);
}
}
#endif // ENABLE(MATHML)