Combine event and touch action regions into a single class
[WebKit-https.git] / Source / WebCore / rendering / RenderDetailsMarker.cpp
1 /*
2  * Copyright (C) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies)
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  *
19  */
20
21 #include "config.h"
22 #include "RenderDetailsMarker.h"
23
24 #include "Element.h"
25 #include "GraphicsContext.h"
26 #include "HTMLDetailsElement.h"
27 #include "HTMLInputElement.h"
28 #include "HTMLNames.h"
29 #include "PaintInfo.h"
30 #include <wtf/IsoMallocInlines.h>
31
32 namespace WebCore {
33
34 using namespace HTMLNames;
35
36 WTF_MAKE_ISO_ALLOCATED_IMPL(RenderDetailsMarker);
37
38 RenderDetailsMarker::RenderDetailsMarker(DetailsMarkerControl& element, RenderStyle&& style)
39     : RenderBlockFlow(element, WTFMove(style))
40 {
41 }
42
43 static Path createPath(const FloatPoint* path)
44 {
45     Path result;
46     result.moveTo(FloatPoint(path[0].x(), path[0].y()));
47     for (int i = 1; i < 4; ++i)
48         result.addLineTo(FloatPoint(path[i].x(), path[i].y()));
49     return result;
50 }
51
52 static Path createDownArrowPath()
53 {
54     FloatPoint points[4] = { FloatPoint(0.0f, 0.07f), FloatPoint(0.5f, 0.93f), FloatPoint(1.0f, 0.07f), FloatPoint(0.0f, 0.07f) };
55     return createPath(points);
56 }
57
58 static Path createUpArrowPath()
59 {
60     FloatPoint points[4] = { FloatPoint(0.0f, 0.93f), FloatPoint(0.5f, 0.07f), FloatPoint(1.0f, 0.93f), FloatPoint(0.0f, 0.93f) };
61     return createPath(points);
62 }
63
64 static Path createLeftArrowPath()
65 {
66     FloatPoint points[4] = { FloatPoint(1.0f, 0.0f), FloatPoint(0.14f, 0.5f), FloatPoint(1.0f, 1.0f), FloatPoint(1.0f, 0.0f) };
67     return createPath(points);
68 }
69
70 static Path createRightArrowPath()
71 {
72     FloatPoint points[4] = { FloatPoint(0.0f, 0.0f), FloatPoint(0.86f, 0.5f), FloatPoint(0.0f, 1.0f), FloatPoint(0.0f, 0.0f) };
73     return createPath(points);
74 }
75
76 RenderDetailsMarker::Orientation RenderDetailsMarker::orientation() const
77 {
78     switch (style().writingMode()) {
79     case TopToBottomWritingMode:
80         if (style().isLeftToRightDirection())
81             return isOpen() ? Down : Right;
82         return isOpen() ? Down : Left;
83     case RightToLeftWritingMode:
84         if (style().isLeftToRightDirection())
85             return isOpen() ? Left : Down;
86         return isOpen() ? Left : Up;
87     case LeftToRightWritingMode:
88         if (style().isLeftToRightDirection())
89             return isOpen() ? Right : Down;
90         return isOpen() ? Right : Up;
91     case BottomToTopWritingMode:
92         if (style().isLeftToRightDirection())
93             return isOpen() ? Up : Right;
94         return isOpen() ? Up : Left;
95     }
96     return Right;
97 }
98
99 Path RenderDetailsMarker::getCanonicalPath() const
100 {
101     switch (orientation()) {
102     case Left: return createLeftArrowPath();
103     case Right: return createRightArrowPath();
104     case Up: return createUpArrowPath();
105     case Down: return createDownArrowPath();
106     }
107
108     return Path();
109 }
110
111 Path RenderDetailsMarker::getPath(const LayoutPoint& origin) const
112 {
113     Path result = getCanonicalPath();
114     result.transform(AffineTransform().scale(contentWidth(), contentHeight()));
115     result.translate(FloatSize(origin.x(), origin.y()));
116     return result;
117 }
118
119 void RenderDetailsMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
120 {
121     if (paintInfo.phase != PaintPhase::Foreground || style().visibility() != Visibility::Visible) {
122         RenderBlockFlow::paint(paintInfo, paintOffset);
123         return;
124     }
125
126     LayoutPoint boxOrigin(paintOffset + location());
127     LayoutRect overflowRect(visualOverflowRect());
128     overflowRect.moveBy(boxOrigin);
129
130     if (!paintInfo.rect.intersects(snappedIntRect(overflowRect)))
131         return;
132
133     const Color color(style().visitedDependentColorWithColorFilter(CSSPropertyColor));
134     paintInfo.context().setStrokeColor(color);
135     paintInfo.context().setStrokeStyle(SolidStroke);
136     paintInfo.context().setStrokeThickness(1.0f);
137     paintInfo.context().setFillColor(color);
138
139     boxOrigin.move(borderLeft() + paddingLeft(), borderTop() + paddingTop());
140     paintInfo.context().fillPath(getPath(boxOrigin));
141 }
142
143 bool RenderDetailsMarker::isOpen() const
144 {
145     for (RenderObject* renderer = parent(); renderer; renderer = renderer->parent()) {
146         if (!renderer->node())
147             continue;
148         if (is<HTMLDetailsElement>(*renderer->node()))
149             return !downcast<HTMLDetailsElement>(*renderer->node()).attributeWithoutSynchronization(openAttr).isNull();
150         if (is<HTMLInputElement>(*renderer->node()))
151             return true;
152     }
153
154     return false;
155 }
156
157 }