Add WTF::move()
[WebKit-https.git] / Source / WebCore / rendering / mathml / RenderMathMLMenclose.cpp
1 /*
2  * Copyright (C) 2014 Gurpreet Kaur (k.gurpreet@samsung.com). All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
16  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
17  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #define _USE_MATH_DEFINES 1
27 #include "config.h"
28
29 #if ENABLE(MATHML)
30 #include "RenderMathMLMenclose.h"
31
32 #include "GraphicsContext.h"
33 #include "MathMLMencloseElement.h"
34 #include "PaintInfo.h"
35 #include "RenderMathMLSquareRoot.h"
36 #include <wtf/MathExtras.h>
37
38 namespace WebCore {
39
40 using namespace MathMLNames;
41
42 RenderMathMLMenclose::RenderMathMLMenclose(Element& element, PassRef<RenderStyle> style)
43     : RenderMathMLRow(element, WTF::move(style))
44 {
45 }
46
47 void RenderMathMLMenclose::addChild(RenderObject* newChild, RenderObject* beforeChild)
48 {
49     MathMLMencloseElement* menclose = toMathMLMencloseElement(element());
50     // Allow an anonymous RenderMathMLSquareRoot to handle drawing the radical
51     // notation, rather than duplicating the code needed to paint a root.
52     if (!firstChild() && menclose->isRadical())        
53         RenderMathMLBlock::addChild(RenderMathMLSquareRoot::createAnonymousWithParentRenderer(*this).leakPtr());
54     
55     if (newChild) {
56         if (firstChild() && menclose->isRadical())
57             toRenderElement(firstChild())->addChild(newChild, beforeChild && beforeChild->parent() == firstChild() ? beforeChild : nullptr);
58         else
59             RenderMathMLBlock::addChild(newChild, beforeChild);
60     }
61 }
62
63 void RenderMathMLMenclose::computePreferredLogicalWidths()
64 {
65     ASSERT(preferredLogicalWidthsDirty());
66
67     RenderMathMLBlock::computePreferredLogicalWidths();
68     const int paddingTop = 6;
69
70     MathMLMencloseElement* menclose = toMathMLMencloseElement(element());
71     const Vector<String>& notationValues = menclose->notationValues();
72     size_t notationalValueSize = notationValues.size();
73     for (size_t i = 0; i < notationalValueSize; i++) {
74         if (notationValues[i] == "circle") {
75             m_minPreferredLogicalWidth = minPreferredLogicalWidth() * float(M_SQRT2);
76             m_maxPreferredLogicalWidth = maxPreferredLogicalWidth() * float(M_SQRT2);
77         }
78     }
79
80     if (menclose->isDefaultLongDiv()) {
81         style().setPaddingTop(Length(paddingTop, Fixed));
82         style().setPaddingLeft(Length(menclose->longDivLeftPadding().toInt(), Fixed));
83     }
84     setPreferredLogicalWidthsDirty(false);
85 }
86
87 void RenderMathMLMenclose::updateLogicalHeight()
88 {
89     MathMLMencloseElement* menclose = toMathMLMencloseElement(element());
90     const Vector<String>& notationValues = menclose->notationValues();
91     size_t notationalValueSize = notationValues.size();
92     for (size_t i = 0; i < notationalValueSize; i++)
93         if (notationValues[i] == "circle")
94             setLogicalHeight(logicalHeight() * float(M_SQRT2));
95 }
96
97 void RenderMathMLMenclose::paint(PaintInfo& info, const LayoutPoint& paintOffset)
98 {
99     RenderMathMLBlock::paint(info, paintOffset);
100
101     if (info.context->paintingDisabled() || info.phase != PaintPhaseForeground || style().visibility() != VISIBLE)
102         return;
103     
104     MathMLMencloseElement* menclose = toMathMLMencloseElement(element());
105     const Vector<String>& notationValues = menclose->notationValues();
106     size_t notationalValueSize = notationValues.size();
107     bool isDefaultLongDiv = menclose->isDefaultLongDiv();
108     if ((notationalValueSize && checkNotationalValuesValidity(notationValues)) || isDefaultLongDiv) {
109         IntRect rect = absoluteBoundingBoxRect();
110         int left = rect.x();
111         int top = rect.y();
112         int boxWidth = rect.width();
113         int boxHeight = rect.height();
114         int halfboxWidth = rect.width() / 2;
115         int halfboxHeight = rect.height() / 2;
116
117         GraphicsContextStateSaver stateSaver(*info.context);
118         info.context->setStrokeThickness(1);
119         info.context->setStrokeStyle(SolidStroke);
120         info.context->setStrokeColor(style().visitedDependentColor(CSSPropertyColor), ColorSpaceDeviceRGB);
121         // TODO add support for notation value updiagonalarrow https://bugs.webkit.org/show_bug.cgi?id=127466
122         for (size_t i = 0; i < notationalValueSize; i++) {
123             if (notationValues[i] == "updiagonalstrike")
124                 info.context->drawLine(IntPoint(left, top + boxHeight), IntPoint(left + boxWidth, top));
125             else if (notationValues[i] == "downdiagonalstrike")
126                 info.context->drawLine(IntPoint(left, top), IntPoint(left + boxWidth, top + boxHeight));
127             else if (notationValues[i] == "verticalstrike")
128                 info.context->drawLine(IntPoint(left + halfboxWidth, top), IntPoint(left + halfboxWidth, top + boxHeight));
129             else if (notationValues[i] == "horizontalstrike")
130                 info.context->drawLine(IntPoint(left, top + halfboxHeight), IntPoint(left + boxWidth, top + halfboxHeight));
131             else if (notationValues[i] == "circle") {
132                 info.context->setFillColor(Color::transparent, ColorSpaceDeviceRGB);
133                 info.context->drawEllipse(rect);
134             } else if (notationValues[i] == "longdiv")
135                 isDefaultLongDiv = true;
136         }
137         if (isDefaultLongDiv) {
138             Path root;
139             int midxPoint = 0;
140             root.moveTo(FloatPoint(left, top));
141             int childLeft = firstChild() ? firstChild()->absoluteBoundingBoxRect().x() : 0;
142             if (childLeft)
143                 midxPoint= childLeft - left;
144             else
145                 midxPoint = style().paddingLeft().value();
146             root.addBezierCurveTo(FloatPoint(left, top), FloatPoint(left + midxPoint, top + halfboxHeight), FloatPoint(left, top + boxHeight));
147             info.context->strokePath(root);
148             if (isDefaultLongDiv)
149                 info.context->drawLine(IntPoint(left, top), IntPoint(left + boxWidth + midxPoint, top));
150         }
151     }
152 }
153
154 bool RenderMathMLMenclose::checkNotationalValuesValidity(const Vector<String>& attr) const
155 {
156     size_t attrSize = attr.size();
157     for (size_t i = 0; i < attrSize; i++) {
158         if (attr[i] == "updiagonalstrike" || attr[i] == "downdiagonalstrike" || attr[i] == "horizontalstrike" || attr[i] == "verticalstrike"
159             || attr[i] == "circle" || attr[i] == "longdiv")
160             return true;
161     }
162     return false;
163 }
164
165 }
166 #endif // ENABLE(MATHML)