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