summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp')
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp448
1 files changed, 216 insertions, 232 deletions
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp b/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp
index 0e975c730..3d757a7a8 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp
+++ b/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved.
* Copyright (C) 2010 François Sausset (sausset@gmail.com). All rights reserved.
+ * Copyright (C) 2016 Igalia S.L.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -25,285 +26,268 @@
*/
#include "config.h"
+#include "RenderMathMLRoot.h"
#if ENABLE(MATHML)
-#include "RenderMathMLRoot.h"
-
+#include "FontCache.h"
#include "GraphicsContext.h"
+#include "MathMLNames.h"
+#include "MathMLRowElement.h"
#include "PaintInfo.h"
#include "RenderIterator.h"
-#include "RenderMathMLRow.h"
+#include "RenderMathMLMenclose.h"
+#include "RenderMathMLOperator.h"
+
+static const UChar gRadicalCharacter = 0x221A;
namespace WebCore {
-
-// FIXME: This whole file should be changed to work with various writing modes. See https://bugs.webkit.org/show_bug.cgi?id=48951.
-
-// Threshold above which the radical shape is modified to look nice with big bases (em)
-const float gThresholdBaseHeightEms = 1.5f;
-// Normal width of the front of the radical sign, before the base & overbar (em)
-const float gFrontWidthEms = 0.75f;
-// Gap between the base and overbar (em)
-const float gSpaceAboveEms = 0.2f;
-// Horizontal position of the bottom point of the radical (* frontWidth)
-const float gRadicalBottomPointXFront = 0.5f;
-// Lower the radical sign's bottom point (px)
-const int gRadicalBottomPointLower = 3;
-// Horizontal position of the top left point of the radical "dip" (* frontWidth)
-const float gRadicalDipLeftPointXFront = 0.8f;
-// Vertical position of the top left point of a sqrt radical "dip" (* baseHeight)
-const float gSqrtRadicalDipLeftPointYPos = 0.5f;
-// Vertical position of the top left point of an nth root radical "dip" (* baseHeight)
-const float gRootRadicalDipLeftPointYPos = 0.625f;
-// Vertical shift of the left end point of the radical (em)
-const float gRadicalLeftEndYShiftEms = 0.05f;
-// Additional bottom root padding if baseHeight > threshold (em)
-const float gBigRootBottomPaddingEms = 0.2f;
-
-// Radical line thickness (em)
-const float gRadicalLineThicknessEms = 0.02f;
-// Radical thick line thickness (em)
-const float gRadicalThickLineThicknessEms = 0.1f;
-
-RenderMathMLRoot::RenderMathMLRoot(Element& element, PassRef<RenderStyle> style)
- : RenderMathMLBlock(element, std::move(style))
- , m_intrinsicPaddingBefore(0)
- , m_intrinsicPaddingAfter(0)
- , m_intrinsicPaddingStart(0)
- , m_intrinsicPaddingEnd(0)
+
+RenderMathMLRoot::RenderMathMLRoot(MathMLRowElement& element, RenderStyle&& style)
+ : RenderMathMLRow(element, WTFMove(style))
{
+ // Determine what kind of expression we have by element name
+ if (element.hasTagName(MathMLNames::msqrtTag))
+ m_kind = SquareRoot;
+ else if (element.hasTagName(MathMLNames::mrootTag))
+ m_kind = RootWithIndex;
+
+ m_radicalOperator.setOperator(RenderMathMLRoot::style(), gRadicalCharacter, MathOperator::Type::VerticalOperator);
}
-RenderMathMLRoot::RenderMathMLRoot(Document& document, PassRef<RenderStyle> style)
- : RenderMathMLBlock(document, std::move(style))
- , m_intrinsicPaddingBefore(0)
- , m_intrinsicPaddingAfter(0)
- , m_intrinsicPaddingStart(0)
- , m_intrinsicPaddingEnd(0)
+bool RenderMathMLRoot::isValid() const
{
+ // Verify whether the list of children is valid:
+ // <msqrt> child1 child2 ... childN </msqrt>
+ // <mroot> base index </mroot>
+ if (m_kind == SquareRoot)
+ return true;
+
+ ASSERT(m_kind == RootWithIndex);
+ auto* child = firstChildBox();
+ if (!child)
+ return false;
+ child = child->nextSiblingBox();
+ return child && !child->nextSiblingBox();
}
-LayoutUnit RenderMathMLRoot::paddingTop() const
+
+RenderBox& RenderMathMLRoot::getBase() const
{
- LayoutUnit result = computedCSSPaddingTop();
- switch (style().writingMode()) {
- case TopToBottomWritingMode:
- return result + m_intrinsicPaddingBefore;
- case BottomToTopWritingMode:
- return result + m_intrinsicPaddingAfter;
- case LeftToRightWritingMode:
- case RightToLeftWritingMode:
- return result + (style().isLeftToRightDirection() ? m_intrinsicPaddingStart : m_intrinsicPaddingEnd);
- }
- ASSERT_NOT_REACHED();
- return result;
+ ASSERT(isValid());
+ ASSERT(m_kind == RootWithIndex);
+ return *firstChildBox();
}
-LayoutUnit RenderMathMLRoot::paddingBottom() const
+RenderBox& RenderMathMLRoot::getIndex() const
{
- LayoutUnit result = computedCSSPaddingBottom();
- switch (style().writingMode()) {
- case TopToBottomWritingMode:
- return result + m_intrinsicPaddingAfter;
- case BottomToTopWritingMode:
- return result + m_intrinsicPaddingBefore;
- case LeftToRightWritingMode:
- case RightToLeftWritingMode:
- return result + (style().isLeftToRightDirection() ? m_intrinsicPaddingEnd : m_intrinsicPaddingStart);
- }
- ASSERT_NOT_REACHED();
- return result;
+ ASSERT(isValid());
+ ASSERT(m_kind == RootWithIndex);
+ return *firstChildBox()->nextSiblingBox();
}
-LayoutUnit RenderMathMLRoot::paddingLeft() const
+void RenderMathMLRoot::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
- LayoutUnit result = computedCSSPaddingLeft();
- switch (style().writingMode()) {
- case LeftToRightWritingMode:
- return result + m_intrinsicPaddingBefore;
- case RightToLeftWritingMode:
- return result + m_intrinsicPaddingAfter;
- case TopToBottomWritingMode:
- case BottomToTopWritingMode:
- return result + (style().isLeftToRightDirection() ? m_intrinsicPaddingStart : m_intrinsicPaddingEnd);
- }
- ASSERT_NOT_REACHED();
- return result;
+ RenderMathMLRow::styleDidChange(diff, oldStyle);
+ m_radicalOperator.reset(style());
}
-LayoutUnit RenderMathMLRoot::paddingRight() const
+RenderMathMLRoot::HorizontalParameters RenderMathMLRoot::horizontalParameters()
{
- LayoutUnit result = computedCSSPaddingRight();
- switch (style().writingMode()) {
- case RightToLeftWritingMode:
- return result + m_intrinsicPaddingBefore;
- case LeftToRightWritingMode:
- return result + m_intrinsicPaddingAfter;
- case TopToBottomWritingMode:
- case BottomToTopWritingMode:
- return result + (style().isLeftToRightDirection() ? m_intrinsicPaddingEnd : m_intrinsicPaddingStart);
+ HorizontalParameters parameters;
+
+ // Square roots do not require horizontal parameters.
+ if (m_kind == SquareRoot)
+ return parameters;
+
+ // We try and read constants to draw the radical from the OpenType MATH and use fallback values otherwise.
+ const auto& primaryFont = style().fontCascade().primaryFont();
+ if (auto* mathData = style().fontCascade().primaryFont().mathData()) {
+ parameters.kernBeforeDegree = mathData->getMathConstant(primaryFont, OpenTypeMathData::RadicalKernBeforeDegree);
+ parameters.kernAfterDegree = mathData->getMathConstant(primaryFont, OpenTypeMathData::RadicalKernAfterDegree);
+ } else {
+ // RadicalKernBeforeDegree: No suggested value provided. OT Math Illuminated mentions 5/18 em, Gecko uses 0.
+ // RadicalKernAfterDegree: Suggested value is -10/18 of em.
+ parameters.kernBeforeDegree = 5 * style().fontCascade().size() / 18;
+ parameters.kernAfterDegree = -10 * style().fontCascade().size() / 18;
}
- ASSERT_NOT_REACHED();
- return result;
+ return parameters;
}
-LayoutUnit RenderMathMLRoot::paddingBefore() const
+RenderMathMLRoot::VerticalParameters RenderMathMLRoot::verticalParameters()
{
- return computedCSSPaddingBefore() + m_intrinsicPaddingBefore;
-}
+ VerticalParameters parameters;
+ // We try and read constants to draw the radical from the OpenType MATH and use fallback values otherwise.
+ const auto& primaryFont = style().fontCascade().primaryFont();
+ if (auto* mathData = style().fontCascade().primaryFont().mathData()) {
+ parameters.ruleThickness = mathData->getMathConstant(primaryFont, OpenTypeMathData::RadicalRuleThickness);
+ parameters.verticalGap = mathData->getMathConstant(primaryFont, mathMLStyle().displayStyle() ? OpenTypeMathData::RadicalDisplayStyleVerticalGap : OpenTypeMathData::RadicalVerticalGap);
+ parameters.extraAscender = mathData->getMathConstant(primaryFont, OpenTypeMathData::RadicalExtraAscender);
+ if (m_kind == RootWithIndex)
+ parameters.degreeBottomRaisePercent = mathData->getMathConstant(primaryFont, OpenTypeMathData::RadicalDegreeBottomRaisePercent);
+ } else {
+ // RadicalVerticalGap: Suggested value is 5/4 default rule thickness.
+ // RadicalDisplayStyleVerticalGap: Suggested value is default rule thickness + 1/4 x-height.
+ // RadicalRuleThickness: Suggested value is default rule thickness.
+ // RadicalExtraAscender: Suggested value is RadicalRuleThickness.
+ // RadicalDegreeBottomRaisePercent: Suggested value is 60%.
+ parameters.ruleThickness = ruleThicknessFallback();
+ if (mathMLStyle().displayStyle())
+ parameters.verticalGap = parameters.ruleThickness + style().fontMetrics().xHeight() / 4;
+ else
+ parameters.verticalGap = 5 * parameters.ruleThickness / 4;
-LayoutUnit RenderMathMLRoot::paddingAfter() const
-{
- return computedCSSPaddingAfter() + m_intrinsicPaddingAfter;
+ if (m_kind == RootWithIndex) {
+ parameters.extraAscender = parameters.ruleThickness;
+ parameters.degreeBottomRaisePercent = 0.6f;
+ }
+ }
+ return parameters;
}
-LayoutUnit RenderMathMLRoot::paddingStart() const
+void RenderMathMLRoot::computePreferredLogicalWidths()
{
- return computedCSSPaddingStart() + m_intrinsicPaddingStart;
-}
+ ASSERT(preferredLogicalWidthsDirty());
-LayoutUnit RenderMathMLRoot::paddingEnd() const
-{
- return computedCSSPaddingEnd() + m_intrinsicPaddingEnd;
-}
+ if (!isValid()) {
+ m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = 0;
+ setPreferredLogicalWidthsDirty(false);
+ return;
+ }
-void RenderMathMLRoot::addChild(RenderObject* newChild, RenderObject* beforeChild)
-{
- // Insert an implicit <mrow> for <mroot> as well as <msqrt>, to ensure firstChild() will have a box
- // to measure and store a glyph-based height for preferredLogicalHeightAfterSizing.
- if (!firstChild())
- RenderMathMLBlock::addChild(RenderMathMLRow::createAnonymousWithParentRenderer(*this).leakPtr());
-
- // An <mroot>'s index has { position: absolute }.
- if (newChild->style().position() == AbsolutePosition)
- RenderMathMLBlock::addChild(newChild);
- else
- toRenderElement(firstChild())->addChild(newChild, beforeChild && beforeChild->parent() == firstChild() ? beforeChild : 0);
-}
+ LayoutUnit preferredWidth = 0;
+ if (m_kind == SquareRoot) {
+ preferredWidth += m_radicalOperator.maxPreferredWidth();
+ setPreferredLogicalWidthsDirty(true);
+ RenderMathMLRow::computePreferredLogicalWidths();
+ preferredWidth += m_maxPreferredLogicalWidth;
+ } else {
+ ASSERT(m_kind == RootWithIndex);
+ auto horizontal = horizontalParameters();
+ preferredWidth += horizontal.kernBeforeDegree;
+ preferredWidth += getIndex().maxPreferredLogicalWidth();
+ preferredWidth += horizontal.kernAfterDegree;
+ preferredWidth += m_radicalOperator.maxPreferredWidth();
+ preferredWidth += getBase().maxPreferredLogicalWidth();
+ }
-RenderBox* RenderMathMLRoot::index() const
-{
- if (!firstChild())
- return 0;
- RenderObject* index = firstChild()->nextSibling();
- if (!index || !index->isBox())
- return 0;
- return toRenderBox(index);
+ m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = preferredWidth;
+ setPreferredLogicalWidthsDirty(false);
}
-void RenderMathMLRoot::layout()
+void RenderMathMLRoot::layoutBlock(bool relayoutChildren, LayoutUnit)
{
- for (auto& box : childrenOfType<RenderBox>(*this))
- box.layoutIfNeeded();
-
- int baseHeight = firstChild() && firstChild()->isBox() ? roundToInt(toRenderBox(firstChild())->logicalHeight()) : style().fontSize();
- int frontWidth = lroundf(gFrontWidthEms * style().fontSize());
-
- // Base height above which the shape of the root changes
- float thresholdHeight = gThresholdBaseHeightEms * style().fontSize();
- if (baseHeight > thresholdHeight && thresholdHeight) {
- float shift = std::min<float>((baseHeight - thresholdHeight) / thresholdHeight, 1.0f);
- m_overbarLeftPointShift = static_cast<int>(shift * gRadicalBottomPointXFront * frontWidth);
- m_intrinsicPaddingAfter = lroundf(gBigRootBottomPaddingEms * style().fontSize());
+ ASSERT(needsLayout());
+
+ if (!relayoutChildren && simplifiedLayout())
+ return;
+
+ m_radicalOperatorTop = 0;
+ m_baseWidth = 0;
+
+ if (!isValid()) {
+ layoutInvalidMarkup();
+ return;
+ }
+
+ // We layout the children, determine the vertical metrics of the base and set the logical width.
+ // Note: Per the MathML specification, the children of <msqrt> are wrapped in an inferred <mrow>, which is the desired base.
+ LayoutUnit baseAscent, baseDescent;
+ recomputeLogicalWidth();
+ if (m_kind == SquareRoot) {
+ baseAscent = baseDescent;
+ RenderMathMLRow::computeLineVerticalStretch(baseAscent, baseDescent);
+ RenderMathMLRow::layoutRowItems(baseAscent, baseDescent);
+ m_baseWidth = logicalWidth();
} else {
- m_overbarLeftPointShift = 0;
- m_intrinsicPaddingAfter = 0;
+ getBase().layoutIfNeeded();
+ m_baseWidth = getBase().logicalWidth();
+ baseAscent = ascentForChild(getBase());
+ baseDescent = getBase().logicalHeight() - baseAscent;
+ getIndex().layoutIfNeeded();
}
-
- int rootPad = lroundf(gSpaceAboveEms * style().fontSize());
- m_intrinsicPaddingBefore = rootPad;
- m_indexTop = 0;
- if (RenderBox* index = this->index()) {
- m_intrinsicPaddingStart = roundToInt(index->maxPreferredLogicalWidth()) + m_overbarLeftPointShift;
-
- int indexHeight = roundToInt(index->logicalHeight());
- int partDipHeight = lroundf((1 - gRootRadicalDipLeftPointYPos) * baseHeight);
- int rootExtraTop = partDipHeight + indexHeight - (baseHeight + rootPad);
- if (rootExtraTop > 0)
- m_intrinsicPaddingBefore += rootExtraTop;
- else
- m_indexTop = - rootExtraTop;
- } else
- m_intrinsicPaddingStart = frontWidth;
- // FIXME: We should rewrite RenderMathMLRoot to rewrite -webkit-flex-order to get rid of the need
- // for intrinsic padding. See https://bugs.webkit.org/show_bug.cgi?id=107151#c2.
- // FIXME: We should make it so that the preferred width of RenderMathMLRoots doesn't change during layout.
- // Technically, we currently only need to set the dirty bit here if one of the member variables above changes.
- setPreferredLogicalWidthsDirty(true);
+ auto horizontal = horizontalParameters();
+ auto vertical = verticalParameters();
- RenderMathMLBlock::layout();
+ // Stretch the radical operator to cover the base height.
+ // We can then determine the metrics of the radical operator + the base.
+ m_radicalOperator.stretchTo(style(), baseAscent + baseDescent);
+ LayoutUnit radicalOperatorHeight = m_radicalOperator.ascent() + m_radicalOperator.descent();
+ LayoutUnit indexBottomRaise = vertical.degreeBottomRaisePercent * radicalOperatorHeight;
+ LayoutUnit radicalAscent = baseAscent + vertical.verticalGap + vertical.ruleThickness + vertical.extraAscender;
+ LayoutUnit radicalDescent = std::max<LayoutUnit>(baseDescent, radicalOperatorHeight + vertical.extraAscender - radicalAscent);
+ LayoutUnit descent = radicalDescent;
+ LayoutUnit ascent = radicalAscent;
- if (RenderBox* index = this->index())
- index->setLogicalTop(m_indexTop);
+ // We set the logical width.
+ if (m_kind == SquareRoot)
+ setLogicalWidth(m_radicalOperator.width() + m_baseWidth);
+ else {
+ ASSERT(m_kind == RootWithIndex);
+ setLogicalWidth(horizontal.kernBeforeDegree + getIndex().logicalWidth() + horizontal.kernAfterDegree + m_radicalOperator.width() + m_baseWidth);
+ }
+
+ // For <mroot>, we update the metrics to take into account the index.
+ LayoutUnit indexAscent, indexDescent;
+ if (m_kind == RootWithIndex) {
+ indexAscent = ascentForChild(getIndex());
+ indexDescent = getIndex().logicalHeight() - indexAscent;
+ ascent = std::max<LayoutUnit>(radicalAscent, indexBottomRaise + indexDescent + indexAscent - descent);
+ }
+
+ // We set the final position of children.
+ m_radicalOperatorTop = ascent - radicalAscent + vertical.extraAscender;
+ LayoutUnit horizontalOffset = m_radicalOperator.width();
+ if (m_kind == RootWithIndex)
+ horizontalOffset += horizontal.kernBeforeDegree + getIndex().logicalWidth() + horizontal.kernAfterDegree;
+ LayoutPoint baseLocation(mirrorIfNeeded(horizontalOffset, m_baseWidth), ascent - baseAscent);
+ if (m_kind == SquareRoot) {
+ for (auto* child = firstChildBox(); child; child = child->nextSiblingBox())
+ child->setLocation(child->location() + baseLocation);
+ } else {
+ ASSERT(m_kind == RootWithIndex);
+ getBase().setLocation(baseLocation);
+ LayoutPoint indexLocation(mirrorIfNeeded(horizontal.kernBeforeDegree, getIndex()), ascent + descent - indexBottomRaise - indexDescent - indexAscent);
+ getIndex().setLocation(indexLocation);
+ }
+
+ setLogicalHeight(ascent + descent);
+ clearNeedsLayout();
}
void RenderMathMLRoot::paint(PaintInfo& info, const LayoutPoint& paintOffset)
{
- RenderMathMLBlock::paint(info, paintOffset);
-
- if (info.context->paintingDisabled() || style().visibility() != VISIBLE)
+ RenderMathMLRow::paint(info, paintOffset);
+
+ if (!firstChild() || info.context().paintingDisabled() || style().visibility() != VISIBLE || !isValid())
+ return;
+
+ // We draw the radical operator.
+ LayoutPoint radicalOperatorTopLeft = paintOffset + location();
+ LayoutUnit horizontalOffset = 0;
+ if (m_kind == RootWithIndex) {
+ auto horizontal = horizontalParameters();
+ horizontalOffset = horizontal.kernBeforeDegree + getIndex().logicalWidth() + horizontal.kernAfterDegree;
+ }
+ radicalOperatorTopLeft.move(mirrorIfNeeded(horizontalOffset, m_radicalOperator.width()), m_radicalOperatorTop);
+ m_radicalOperator.paint(style(), info, radicalOperatorTopLeft);
+
+ // We draw the radical line.
+ LayoutUnit ruleThickness = verticalParameters().ruleThickness;
+ if (!ruleThickness)
return;
-
- IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset + location() + contentBoxRect().location());
-
- int startX = adjustedPaintOffset.x();
- int frontWidth = lroundf(gFrontWidthEms * style().fontSize());
- int overbarWidth = roundToInt(contentLogicalWidth()) + m_overbarLeftPointShift;
-
- int baseHeight = roundToInt(contentLogicalHeight());
- int rootPad = lroundf(gSpaceAboveEms * style().fontSize());
- adjustedPaintOffset.setY(adjustedPaintOffset.y() - rootPad);
-
- float radicalDipLeftPointYPos = (index() ? gRootRadicalDipLeftPointYPos : gSqrtRadicalDipLeftPointYPos) * baseHeight;
-
- FloatPoint overbarLeftPoint(startX - m_overbarLeftPointShift, adjustedPaintOffset.y());
- FloatPoint bottomPoint(startX - gRadicalBottomPointXFront * frontWidth, adjustedPaintOffset.y() + baseHeight + gRadicalBottomPointLower);
- FloatPoint dipLeftPoint(startX - gRadicalDipLeftPointXFront * frontWidth, adjustedPaintOffset.y() + radicalDipLeftPointYPos);
- 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()));
- // draw top
- root.addLineTo(overbarLeftPoint);
- // draw from top left corner to bottom point of radical
- root.addLineTo(bottomPoint);
- // draw from bottom point to top of left part of radical base "dip"
- root.addLineTo(dipLeftPoint);
- // draw to end
- root.addLineTo(leftEnd);
-
- info.context->strokePath(root);
-
- GraphicsContextStateSaver maskStateSaver(*info.context);
-
- // Build a mask to draw the thick part of the root.
- 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);
-
- // Draw the thick part of the root.
- info.context->setStrokeThickness(gRadicalThickLineThicknessEms * style().fontSize());
- info.context->setLineCap(SquareCap);
-
- Path line;
- line.moveTo(bottomPoint);
- line.addLineTo(dipLeftPoint);
-
- info.context->strokePath(line);
+ GraphicsContextStateSaver stateSaver(info.context());
+
+ info.context().setStrokeThickness(ruleThickness);
+ info.context().setStrokeStyle(SolidStroke);
+ info.context().setStrokeColor(style().visitedDependentColor(CSSPropertyColor));
+ LayoutPoint ruleOffsetFrom = paintOffset + location() + LayoutPoint(0, m_radicalOperatorTop + ruleThickness / 2);
+ LayoutPoint ruleOffsetTo = ruleOffsetFrom;
+ horizontalOffset += m_radicalOperator.width();
+ ruleOffsetFrom.move(mirrorIfNeeded(horizontalOffset), 0);
+ horizontalOffset += m_baseWidth;
+ ruleOffsetTo.move(mirrorIfNeeded(horizontalOffset), 0);
+ info.context().drawLine(ruleOffsetFrom, ruleOffsetTo);
}
}