MathML preferred widths should not depend on layout information
[WebKit-https.git] / Source / WebCore / rendering / mathml / RenderMathMLBlock.cpp
1 /*
2  * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved.
3  * Copyright (C) 2012 David Barton (dbarton@mathscribe.com). All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28
29 #if ENABLE(MATHML)
30
31 #include "RenderMathMLBlock.h"
32
33 #include "GraphicsContext.h"
34 #include "MathMLNames.h"
35 #include "RenderView.h"
36
37 #if ENABLE(DEBUG_MATH_LAYOUT)
38 #include "PaintInfo.h"
39 #endif
40
41 namespace WebCore {
42     
43 using namespace MathMLNames;
44     
45 RenderMathMLBlock::RenderMathMLBlock(Element* container)
46     : RenderFlexibleBox(container)
47     , m_ignoreInAccessibilityTree(false)
48 {
49 }
50
51 bool RenderMathMLBlock::isChildAllowed(RenderObject* child, RenderStyle*) const
52 {
53     return child->node() && child->node()->nodeType() == Node::ELEMENT_NODE;
54 }
55
56 RenderMathMLBlock* RenderMathMLBlock::createAnonymousMathMLBlock(EDisplay display)
57 {
58     RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), display);
59     RenderMathMLBlock* newBlock = new (renderArena()) RenderMathMLBlock(0);
60     newBlock->setDocumentForAnonymous(document());
61     newBlock->setStyle(newStyle.release());
62     return newBlock;
63 }
64
65 int RenderMathMLBlock::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
66 {
67     // mathml.css sets math { -webkit-line-box-contain: glyphs replaced; line-height: 0; }, so when linePositionMode == PositionOfInteriorLineBoxes we want to
68     // return 0 here to match our line-height. This matters when RootInlineBox::ascentAndDescentForBox is called on a RootInlineBox for an inline-block.
69     if (linePositionMode == PositionOfInteriorLineBoxes)
70         return 0;
71     
72     LayoutUnit baseline = firstLineBoxBaseline(); // FIXME: This may be unnecessary after flex baselines are implemented (https://bugs.webkit.org/show_bug.cgi?id=96188).
73     if (baseline != -1)
74         return baseline;
75     
76     return RenderFlexibleBox::baselinePosition(baselineType, firstLine, direction, linePositionMode);
77 }
78
79 const char* RenderMathMLBlock::renderName() const
80 {
81     EDisplay display = style()->display();
82     if (display == FLEX)
83         return isAnonymous() ? "RenderMathMLBlock (anonymous, flex)" : "RenderMathMLBlock (flex)";
84     if (display == INLINE_FLEX)
85         return isAnonymous() ? "RenderMathMLBlock (anonymous, inline-flex)" : "RenderMathMLBlock (inline-flex)";
86     // |display| should be one of the above.
87     ASSERT_NOT_REACHED();
88     return isAnonymous() ? "RenderMathMLBlock (anonymous)" : "RenderMathMLBlock";
89 }
90
91 #if ENABLE(DEBUG_MATH_LAYOUT)
92 void RenderMathMLBlock::paint(PaintInfo& info, const LayoutPoint& paintOffset)
93 {
94     RenderFlexibleBox::paint(info, paintOffset);
95     
96     if (info.context->paintingDisabled() || info.phase != PaintPhaseForeground)
97         return;
98
99     IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset + location());
100
101     GraphicsContextStateSaver stateSaver(*info.context);
102     
103     info.context->setStrokeThickness(1.0f);
104     info.context->setStrokeStyle(SolidStroke);
105     info.context->setStrokeColor(Color(0, 0, 255), ColorSpaceSRGB);
106     
107     info.context->drawLine(adjustedPaintOffset, IntPoint(adjustedPaintOffset.x() + pixelSnappedOffsetWidth(), adjustedPaintOffset.y()));
108     info.context->drawLine(IntPoint(adjustedPaintOffset.x() + pixelSnappedOffsetWidth(), adjustedPaintOffset.y()), IntPoint(adjustedPaintOffset.x() + pixelSnappedOffsetWidth(), adjustedPaintOffset.y() + pixelSnappedOffsetHeight()));
109     info.context->drawLine(IntPoint(adjustedPaintOffset.x(), adjustedPaintOffset.y() + pixelSnappedOffsetHeight()), IntPoint(adjustedPaintOffset.x() + pixelSnappedOffsetWidth(), adjustedPaintOffset.y() + pixelSnappedOffsetHeight()));
110     info.context->drawLine(adjustedPaintOffset, IntPoint(adjustedPaintOffset.x(), adjustedPaintOffset.y() + pixelSnappedOffsetHeight()));
111     
112     int topStart = paddingTop();
113     
114     info.context->setStrokeColor(Color(0, 255, 0), ColorSpaceSRGB);
115     
116     info.context->drawLine(IntPoint(adjustedPaintOffset.x(), adjustedPaintOffset.y() + topStart), IntPoint(adjustedPaintOffset.x() + pixelSnappedOffsetWidth(), adjustedPaintOffset.y() + topStart));
117     
118     int baseline = roundToInt(baselinePosition(AlphabeticBaseline, true, HorizontalLine));
119     
120     info.context->setStrokeColor(Color(255, 0, 0), ColorSpaceSRGB);
121     
122     info.context->drawLine(IntPoint(adjustedPaintOffset.x(), adjustedPaintOffset.y() + baseline), IntPoint(adjustedPaintOffset.x() + pixelSnappedOffsetWidth(), adjustedPaintOffset.y() + baseline));
123 }
124 #endif // ENABLE(DEBUG_MATH_LAYOUT)
125
126 int RenderMathMLTable::firstLineBoxBaseline() const
127 {
128     // In legal MathML, we'll have a MathML parent. That RenderFlexibleBox parent will use our firstLineBoxBaseline() for baseline alignment, per
129     // http://dev.w3.org/csswg/css3-flexbox/#flex-baselines. We want to vertically center an <mtable>, such as a matrix. Essentially the whole <mtable> element fits on a
130     // single line, whose baseline gives this centering. This is different than RenderTable::firstLineBoxBaseline, which returns the baseline of the first row of a <table>.
131     return (logicalHeight() + style()->fontMetrics().xHeight()) / 2;
132 }
133
134 }    
135
136 #endif