de0b86fdda134f24b5ac4eb15f62454b4692fb84
[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 #if ENABLE(DETAILS) || ENABLE(CALENDAR_PICKER)
25
26 #include "Element.h"
27 #include "GraphicsContext.h"
28 #include "HTMLNames.h"
29 #include "PaintInfo.h"
30
31 namespace WebCore {
32
33 using namespace HTMLNames;
34
35 RenderDetailsMarker::RenderDetailsMarker(Node* node)
36     : RenderBlock(node)
37 {
38 }
39
40 static Path createPath(const FloatPoint* path)
41 {
42     Path result;
43     result.moveTo(FloatPoint(path[0].x(), path[0].y()));
44     for (int i = 1; i < 4; ++i)
45         result.addLineTo(FloatPoint(path[i].x(), path[i].y()));
46     return result;
47 }
48
49 static Path createDownArrowPath()
50 {
51     FloatPoint points[4] = { FloatPoint(0.0f, 0.07f), FloatPoint(0.5f, 0.93f), FloatPoint(1.0f, 0.07f), FloatPoint(0.0f, 0.07f) };
52     return createPath(points);
53 }
54
55 static Path createUpArrowPath()
56 {
57     FloatPoint points[4] = { FloatPoint(0.0f, 0.93f), FloatPoint(0.5f, 0.07f), FloatPoint(1.0f, 0.93f), FloatPoint(0.0f, 0.93f) };
58     return createPath(points);
59 }
60
61 static Path createLeftArrowPath()
62 {
63     FloatPoint points[4] = { FloatPoint(1.0f, 0.0f), FloatPoint(0.14f, 0.5f), FloatPoint(1.0f, 1.0f), FloatPoint(1.0f, 0.0f) };
64     return createPath(points);
65 }
66
67 static Path createRightArrowPath()
68 {
69     FloatPoint points[4] = { FloatPoint(0.0f, 0.0f), FloatPoint(0.86f, 0.5f), FloatPoint(0.0f, 1.0f), FloatPoint(0.0f, 0.0f) };
70     return createPath(points);
71 }
72
73 RenderDetailsMarker::Orientation RenderDetailsMarker::orientation() const
74 {
75     switch (style()->writingMode()) {
76     case TopToBottomWritingMode:
77         if (style()->isLeftToRightDirection())
78             return isOpen() ? Down : Right;
79         return isOpen() ? Down : Left;
80     case RightToLeftWritingMode:
81         if (style()->isLeftToRightDirection())
82             return isOpen() ? Left : Down;
83         return isOpen() ? Left : Up;
84     case LeftToRightWritingMode:
85         if (style()->isLeftToRightDirection())
86             return isOpen() ? Right : Down;
87         return isOpen() ? Right : Up;
88     case BottomToTopWritingMode:
89         if (style()->isLeftToRightDirection())
90             return isOpen() ? Up : Right;
91         return isOpen() ? Up : Left;
92     }
93     return Right;
94 }
95
96 Path RenderDetailsMarker::getCanonicalPath() const
97 {
98     switch (orientation()) {
99     case Left: return createLeftArrowPath();
100     case Right: return createRightArrowPath();
101     case Up: return createUpArrowPath();
102     case Down: return createDownArrowPath();
103     }
104
105     return Path();
106 }
107
108 Path RenderDetailsMarker::getPath(const LayoutPoint& origin) const
109 {
110     Path result = getCanonicalPath();
111     result.transform(AffineTransform().scale(logicalHeight()));
112     result.translate(FloatSize(origin.x(), origin.y()));
113     return result;
114 }
115
116 void RenderDetailsMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
117 {
118     if (paintInfo.phase != PaintPhaseForeground || style()->visibility() != VISIBLE) {
119         RenderBlock::paint(paintInfo, paintOffset);
120         return;
121     }
122
123     LayoutPoint boxOrigin(paintOffset + location());
124     LayoutRect overflowRect(visualOverflowRect());
125     overflowRect.moveBy(boxOrigin);
126     overflowRect.inflate(maximalOutlineSize(paintInfo.phase));
127
128     if (!paintInfo.rect.intersects(pixelSnappedIntRect(overflowRect)))
129         return;
130
131     const Color color(style()->visitedDependentColor(CSSPropertyColor));
132     paintInfo.context->setStrokeColor(color, style()->colorSpace());
133     paintInfo.context->setStrokeStyle(SolidStroke);
134     paintInfo.context->setStrokeThickness(1.0f);
135     paintInfo.context->setFillColor(color, style()->colorSpace());
136
137     paintInfo.context->fillPath(getPath(boxOrigin));
138 }
139
140 bool RenderDetailsMarker::isOpen() const
141 {
142     for (RenderObject* renderer = parent(); renderer; renderer = renderer->parent()) {
143         if (!renderer->node())
144             continue;
145         if (renderer->node()->hasTagName(detailsTag))
146             return !toElement(renderer->node())->getAttribute(openAttr).isNull();
147         if (renderer->node()->hasTagName(inputTag))
148             return true;
149     }
150
151     return false;
152 }
153
154 }
155
156 #endif