Add WTF::move()
[WebKit-https.git] / Source / WebCore / rendering / mathml / RenderMathMLFraction.cpp
1 /*
2  * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved.
3  * Copyright (C) 2010 Fran├žois Sausset (sausset@gmail.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 "RenderMathMLFraction.h"
32
33 #include "GraphicsContext.h"
34 #include "MathMLNames.h"
35 #include "PaintInfo.h"
36
37 namespace WebCore {
38     
39 using namespace MathMLNames;
40
41 static const float gLineThin = 0.33f;
42 static const float gLineMedium = 1.f;
43 static const float gLineThick = 3.f;
44 static const float gFractionBarWidth = 0.05f;
45
46 RenderMathMLFraction::RenderMathMLFraction(MathMLInlineContainerElement& element, PassRef<RenderStyle> style)
47     : RenderMathMLBlock(element, WTF::move(style))
48     , m_lineThickness(gLineMedium)
49 {
50 }
51
52 void RenderMathMLFraction::fixChildStyle(RenderObject* child)
53 {
54     ASSERT(child->isAnonymous() && child->style().refCount() == 1);
55     child->style().setFlexDirection(FlowColumn);
56 }
57
58 // FIXME: It's cleaner to only call updateFromElement when an attribute has changed. Move parts
59 // of this to fixChildStyle or other methods, and call them when needed.
60 void RenderMathMLFraction::updateFromElement()
61 {
62     // FIXME: mfrac where bevelled=true will need to reorganize the descendants
63     if (isEmpty()) 
64         return;
65
66     RenderObject* numeratorWrapper = firstChild();
67     RenderObject* denominatorWrapper = numeratorWrapper->nextSibling();
68     if (!denominatorWrapper)
69         return;
70
71     String thickness = element().getAttribute(MathMLNames::linethicknessAttr);
72     m_lineThickness = gLineMedium;
73     if (equalIgnoringCase(thickness, "thin"))
74         m_lineThickness = gLineThin;
75     else if (equalIgnoringCase(thickness, "medium"))
76         m_lineThickness = gLineMedium;
77     else if (equalIgnoringCase(thickness, "thick"))
78         m_lineThickness = gLineThick;
79     else {
80         // This function parses the thickness attribute using gLineMedium as
81         // the default value. If the parsing fails, m_lineThickness will not be
82         // modified i.e. the default value will be used.
83         parseMathMLLength(thickness, m_lineThickness, &style(), false);
84     }
85
86     // Update the style for the padding of the denominator for the line thickness
87     lastChild()->style().setPaddingTop(Length(static_cast<int>(m_lineThickness), Fixed));
88 }
89
90 void RenderMathMLFraction::addChild(RenderObject* child, RenderObject* /* beforeChild */)
91 {
92     if (isEmpty()) {
93         RenderPtr<RenderMathMLBlock> numeratorWrapper = createAnonymousMathMLBlock();
94         fixChildStyle(numeratorWrapper.get());
95         RenderMathMLBlock::addChild(numeratorWrapper.leakPtr());
96         
97         RenderPtr<RenderMathMLBlock> denominatorWrapper = createAnonymousMathMLBlock();
98         fixChildStyle(denominatorWrapper.get());
99         RenderMathMLBlock::addChild(denominatorWrapper.leakPtr());
100     }
101     
102     if (firstChild()->isEmpty())
103         toRenderElement(firstChild())->addChild(child);
104     else
105         toRenderElement(lastChild())->addChild(child);
106     
107     updateFromElement();
108 }
109
110 void RenderMathMLFraction::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
111 {
112     RenderMathMLBlock::styleDidChange(diff, oldStyle);
113     
114     for (RenderObject* child = firstChild(); child; child = child->nextSibling())
115         fixChildStyle(child);
116     updateFromElement();
117 }
118
119 RenderMathMLOperator* RenderMathMLFraction::unembellishedOperator()
120 {
121     RenderObject* numeratorWrapper = firstChild();
122     if (!numeratorWrapper)
123         return 0;
124     RenderObject* numerator = numeratorWrapper->firstChildSlow();
125     if (!numerator || !numerator->isRenderMathMLBlock())
126         return 0;
127     return toRenderMathMLBlock(numerator)->unembellishedOperator();
128 }
129
130 void RenderMathMLFraction::layout()
131 {
132     updateFromElement();
133
134     // Adjust the fraction line thickness for the zoom
135     if (lastChild() && lastChild()->isRenderBlock())
136         m_lineThickness *= ceilf(gFractionBarWidth * style().fontSize());
137
138     RenderMathMLBlock::layout();
139 }
140
141 void RenderMathMLFraction::paint(PaintInfo& info, const LayoutPoint& paintOffset)
142 {
143     RenderMathMLBlock::paint(info, paintOffset);
144     if (info.context->paintingDisabled() || info.phase != PaintPhaseForeground || style().visibility() != VISIBLE)
145         return;
146     
147     RenderBox* denominatorWrapper = lastChildBox();
148     if (!denominatorWrapper || !m_lineThickness)
149         return;
150
151     IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset + location() + denominatorWrapper->location() + LayoutPoint(0, m_lineThickness / 2));
152     
153     GraphicsContextStateSaver stateSaver(*info.context);
154     
155     info.context->setStrokeThickness(m_lineThickness);
156     info.context->setStrokeStyle(SolidStroke);
157     info.context->setStrokeColor(style().visitedDependentColor(CSSPropertyColor), ColorSpaceSRGB);
158     
159     info.context->drawLine(adjustedPaintOffset, IntPoint(adjustedPaintOffset.x() + denominatorWrapper->pixelSnappedOffsetWidth(), adjustedPaintOffset.y()));
160 }
161
162 int RenderMathMLFraction::firstLineBaseline() const
163 {
164     if (RenderBox* denominatorWrapper = lastChildBox())
165         return denominatorWrapper->logicalTop() + static_cast<int>(lroundf((m_lineThickness + style().fontMetrics().xHeight()) / 2));
166     return RenderMathMLBlock::firstLineBaseline();
167 }
168
169 }
170
171 #endif // ENABLE(MATHML)