diff options
Diffstat (limited to 'Source/WebCore/rendering/mathml')
6 files changed, 117 insertions, 217 deletions
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp b/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp index 4297dd7ff..351f99e84 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp @@ -48,6 +48,7 @@ RenderMathMLFenced::RenderMathMLFenced(Element* element) : RenderMathMLRow(element) , m_open(OpeningBraceChar) , m_close(ClosingBraceChar) + , m_closeFenceRenderer(0) { } @@ -94,49 +95,67 @@ void RenderMathMLFenced::makeFences() RenderObject* openFence = new (renderArena()) RenderMathMLOperator(node(), m_open); openFence->setStyle(createOperatorStyle()); RenderBlock::addChild(openFence, firstChild()); - RenderObject* closeFence = new (renderArena()) RenderMathMLOperator(node(), m_close); - closeFence->setStyle(createOperatorStyle()); - RenderBlock::addChild(closeFence); + m_closeFenceRenderer = new (renderArena()) RenderMathMLOperator(node(), m_close); + m_closeFenceRenderer->setStyle(createOperatorStyle()); + RenderBlock::addChild(m_closeFenceRenderer); } -void RenderMathMLFenced::addChild(RenderObject* child, RenderObject*) +void RenderMathMLFenced::addChild(RenderObject* child, RenderObject* beforeChild) { // make the fences if the render object is empty if (isEmpty()) updateFromElement(); + // FIXME: Adding or removing a child should possibly cause all later separators to shift places if they're different, + // as later child positions change by +1 or -1. + + RenderObject* separatorRenderer = 0; if (m_separators.get()) { unsigned int count = 0; for (Node* position = child->node(); position; position = position->previousSibling()) { - if (position->nodeType() == Node::ELEMENT_NODE) + if (position->isElementNode()) count++; } - - if (count > 1) { + if (!beforeChild) { + // We're adding at the end (before the closing fence), so a new separator would go before the new child, not after it. + --count; + } + // |count| is now the number of element children that will be before our new separator, i.e. it's the 1-based index of the separator. + + if (count > 0) { UChar separator; // Use the last separator if we've run out of specified separators. - if ((count - 1) >= m_separators.get()->length()) + if (count > m_separators.get()->length()) separator = (*m_separators.get())[m_separators.get()->length() - 1]; else - separator = (*m_separators.get())[count - 2]; + separator = (*m_separators.get())[count - 1]; - RenderObject* separatorObj = new (renderArena()) RenderMathMLOperator(node(), separator); - separatorObj->setStyle(createOperatorStyle()); - RenderBlock::addChild(separatorObj, lastChild()); + separatorRenderer = new (renderArena()) RenderMathMLOperator(node(), separator); + separatorRenderer->setStyle(createOperatorStyle()); } } // If we have a block, we'll wrap it in an inline-block. if (child->isBlockFlow() && child->style()->display() != INLINE_BLOCK) { // Block objects wrapper. - RenderBlock* block = createAlmostAnonymousBlock(INLINE_BLOCK); - RenderBlock::addChild(block, lastChild()); - block->addChild(child); - } else - RenderBlock::addChild(child, lastChild()); + block->addChild(child); + child = block; + } + + if (beforeChild) { + // Adding |x| before an existing |y| e.g. in element (y) - first insert our new child |x|, then its separator, to get (x, y). + RenderBlock::addChild(child, beforeChild); + if (separatorRenderer) + RenderBlock::addChild(separatorRenderer, beforeChild); + } else { + // Adding |y| at the end of an existing element e.g. (x) - insert the separator first before the closing fence, then |y|, to get (x, y). + if (separatorRenderer) + RenderBlock::addChild(separatorRenderer, m_closeFenceRenderer); + RenderBlock::addChild(child, m_closeFenceRenderer); + } } } diff --git a/Source/WebCore/rendering/mathml/RenderMathMLFenced.h b/Source/WebCore/rendering/mathml/RenderMathMLFenced.h index b2bca9971..75324dcdc 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLFenced.h +++ b/Source/WebCore/rendering/mathml/RenderMathMLFenced.h @@ -47,6 +47,8 @@ private: UChar m_open; UChar m_close; RefPtr<StringImpl> m_separators; + + RenderObject* m_closeFenceRenderer; }; } diff --git a/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp b/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp index e6d5165a9..efeed1a1f 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp @@ -31,15 +31,12 @@ #include "RenderMathMLRoot.h" #include "GraphicsContext.h" -#include "MathMLNames.h" #include "PaintInfo.h" using namespace std; namespace WebCore { -using namespace MathMLNames; - // 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) @@ -54,8 +51,10 @@ const float gRadicalBottomPointXFront = 0.5f; 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 the radical "dip" (* baseHeight) -const float gRadicalDipLeftPointYPos = 0.625f; +// 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) @@ -81,6 +80,65 @@ RenderBoxModelObject* RenderMathMLRoot::index() const return toRenderBoxModelObject(index); } +void RenderMathMLRoot::computePreferredLogicalWidths() +{ + ASSERT(preferredLogicalWidthsDirty() && needsLayout()); + + computeChildrenPreferredLogicalHeights(); + + int baseHeight = firstChild() ? roundToInt(preferredLogicalHeightAfterSizing(firstChild())) : 0; + + 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 = min<float>((baseHeight - thresholdHeight) / thresholdHeight, 1.0f); + m_overbarLeftPointShift = static_cast<int>(shift * gRadicalBottomPointXFront * frontWidth); + m_intrinsicPaddingAfter = lroundf(gBigRootBottomPaddingEms * style()->fontSize()); + } else { + m_overbarLeftPointShift = 0; + m_intrinsicPaddingAfter = 0; + } + + int rootPad = lroundf(gSpaceAboveEms * style()->fontSize()); + m_intrinsicPaddingBefore = rootPad; + m_indexTop = 0; + if (RenderBoxModelObject* index = this->index()) { + m_intrinsicPaddingStart = roundToInt(index->maxPreferredLogicalWidth()) + m_overbarLeftPointShift; + + int indexHeight = roundToInt(preferredLogicalHeightAfterSizing(index)); + 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; + + RenderMathMLBlock::computePreferredLogicalWidths(); + + // Shrink our logical width to its probable value now without triggering unnecessary relayout of our children. + ASSERT(needsLayout() && logicalWidth() >= maxPreferredLogicalWidth()); + setLogicalWidth(maxPreferredLogicalWidth()); +} + +void RenderMathMLRoot::layout() +{ + // Our computePreferredLogicalWidths() may change our logical width and then layout our children, which + // RenderBlock::layout()'s relayoutChildren logic isn't expecting. + if (preferredLogicalWidthsDirty()) + computePreferredLogicalWidths(); + + RenderMathMLBlock::layout(); + + RenderBoxModelObject* index = this->index(); + // If |index|, it should be a RenderBlock here, unless the user has overriden its { position: absolute }. + if (index && index->isBox()) + toRenderBox(index)->setLogicalTop(m_indexTop); +} + void RenderMathMLRoot::paint(PaintInfo& info, const LayoutPoint& paintOffset) { RenderMathMLBlock::paint(info, paintOffset); @@ -88,24 +146,21 @@ void RenderMathMLRoot::paint(PaintInfo& info, const LayoutPoint& paintOffset) if (info.context->paintingDisabled()) return; - if (!index()) - return; + IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset + location() + contentBoxRect().location()); - IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset + location() + computedCSSContentBoxRect().location()); + int startX = adjustedPaintOffset.x(); + int frontWidth = lroundf(gFrontWidthEms * style()->fontSize()); + int overbarWidth = roundToInt(getBoxModelObjectWidth(firstChild())) + m_overbarLeftPointShift; int baseHeight = roundToInt(getBoxModelObjectHeight(firstChild())); + int rootPad = lroundf(gSpaceAboveEms * style()->fontSize()); + adjustedPaintOffset.setY(adjustedPaintOffset.y() - rootPad); - 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); + 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() + gRadicalDipLeftPointYPos * baseHeight); + FloatPoint dipLeftPoint(startX - gRadicalDipLeftPointXFront * frontWidth, adjustedPaintOffset.y() + radicalDipLeftPointYPos); FloatPoint leftEnd(startX - frontWidth, dipLeftPoint.y() + gRadicalLeftEndYShiftEms * style()->fontSize()); GraphicsContextStateSaver stateSaver(*info.context); @@ -153,46 +208,6 @@ void RenderMathMLRoot::paint(PaintInfo& info, const LayoutPoint& paintOffset) info.context->strokePath(line); } -void RenderMathMLRoot::layout() -{ - RenderBlock::layout(); - - if (!index()) - return; - - int baseHeight = roundToInt(getBoxModelObjectHeight(firstChild())); - - // Base height above which the shape of the root changes - 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); // FIXME: Can this really be right? - // FIXME: Preferred logical widths are currently wrong the first time through, relying on layout() to set m_intrinsicPaddingStart. - RenderBlock::layout(); - - // |index| should be a RenderBlock here, unless the user has overriden its { position: absolute }. - if (rootExtraTop < 0 && index->isBox()) - toRenderBox(index)->setLogicalTop(-rootExtraTop); -} - } #endif // ENABLE(MATHML) diff --git a/Source/WebCore/rendering/mathml/RenderMathMLRoot.h b/Source/WebCore/rendering/mathml/RenderMathMLRoot.h index 65ec82dc7..cd5d6e6e2 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLRoot.h +++ b/Source/WebCore/rendering/mathml/RenderMathMLRoot.h @@ -32,7 +32,7 @@ namespace WebCore { -// Render base^(1/index), using radical notation. +// Render base^(1/index), or sqrt(base) via the derived class RenderMathMLSquareRoot, using radical notation. class RenderMathMLRoot : public RenderMathMLBlock { public: RenderMathMLRoot(Element*); @@ -45,10 +45,13 @@ protected: private: virtual const char* renderName() const { return "RenderMathMLRoot"; } + virtual void computePreferredLogicalWidths() OVERRIDE; + // This may return 0 for a non-MathML index (which won't occur in valid MathML). RenderBoxModelObject* index() const; int m_overbarLeftPointShift; + int m_indexTop; }; } diff --git a/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.cpp b/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.cpp index 86975dbfb..b4b07a2cf 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.cpp @@ -30,45 +30,12 @@ #include "RenderMathMLSquareRoot.h" -#include "GraphicsContext.h" -#include "MathMLNames.h" -#include "PaintInfo.h" #include "RenderMathMLRow.h" -using namespace std; - namespace WebCore { -using namespace MathMLNames; - -// 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 the radical "dip" (* baseHeight) -const float gRadicalDipLeftPointYPos = 0.5f; -// 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; - RenderMathMLSquareRoot::RenderMathMLSquareRoot(Element* element) - : RenderMathMLBlock(element) + : RenderMathMLRoot(element) { } @@ -77,7 +44,7 @@ void RenderMathMLSquareRoot::addChild(RenderObject* newChild, RenderObject* befo if (!firstChild()) { RenderMathMLRow* newMRow = RenderMathMLRow::createAnonymousWithParentRenderer(this); - RenderMathMLBlock::addChild(newMRow); + RenderMathMLRoot::addChild(newMRow); // newMRow->isAnonymousBlock() is false because newMRow's display is INLINE_BLOCK, // so we don't need to worry about removeLeftoverAnonymousBlock(). @@ -88,106 +55,6 @@ void RenderMathMLSquareRoot::addChild(RenderObject* newChild, RenderObject* befo 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; - // Base height above which the shape of the root changes - 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())); - // 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); -} - } #endif // ENABLE(MATHML) diff --git a/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h b/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h index ea6d324db..b0270efbb 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h +++ b/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h @@ -28,12 +28,12 @@ #if ENABLE(MATHML) -#include "RenderMathMLBlock.h" +#include "RenderMathMLRoot.h" namespace WebCore { // Render sqrt(base), using radical notation. -class RenderMathMLSquareRoot : public RenderMathMLBlock { +class RenderMathMLSquareRoot : public RenderMathMLRoot { public: RenderMathMLSquareRoot(Element*); @@ -43,12 +43,6 @@ private: virtual const char* renderName() const { return "RenderMathMLSquareRoot"; } virtual bool createsAnonymousWrapper() const OVERRIDE { return true; } - - virtual void computePreferredLogicalWidths() OVERRIDE; - virtual void computeLogicalHeight() OVERRIDE; - virtual void layout() OVERRIDE; - - virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE; }; } |