Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / rendering / HitTestLocation.cpp
1 /*
2  * Copyright (C) 2006, 2008, 2011 Apple Inc. All rights reserved.
3  * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  *
20 */
21
22 #include "config.h"
23 #include "core/rendering/HitTestLocation.h"
24
25 #include "HTMLNames.h"
26 #include "SVGNames.h"
27 #include "XLinkNames.h"
28
29 namespace WebCore {
30
31 using namespace HTMLNames;
32
33 HitTestLocation::HitTestLocation()
34     : m_isRectBased(false)
35     , m_isRectilinear(true)
36 {
37 }
38
39 HitTestLocation::HitTestLocation(const LayoutPoint& point)
40     : m_point(point)
41     , m_boundingBox(rectForPoint(point, 0, 0, 0, 0))
42     , m_transformedPoint(point)
43     , m_transformedRect(m_boundingBox)
44     , m_isRectBased(false)
45     , m_isRectilinear(true)
46 {
47 }
48
49 HitTestLocation::HitTestLocation(const FloatPoint& point)
50     : m_point(flooredLayoutPoint(point))
51     , m_boundingBox(rectForPoint(m_point, 0, 0, 0, 0))
52     , m_transformedPoint(point)
53     , m_transformedRect(m_boundingBox)
54     , m_isRectBased(false)
55     , m_isRectilinear(true)
56 {
57 }
58
59 HitTestLocation::HitTestLocation(const FloatPoint& point, const FloatQuad& quad)
60     : m_transformedPoint(point)
61     , m_transformedRect(quad)
62     , m_isRectBased(true)
63 {
64     m_point = flooredLayoutPoint(point);
65     m_boundingBox = enclosingIntRect(quad.boundingBox());
66     m_isRectilinear = quad.isRectilinear();
67 }
68
69 HitTestLocation::HitTestLocation(const LayoutPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
70     : m_point(centerPoint)
71     , m_boundingBox(rectForPoint(centerPoint, topPadding, rightPadding, bottomPadding, leftPadding))
72     , m_transformedPoint(centerPoint)
73     , m_isRectBased(topPadding || rightPadding || bottomPadding || leftPadding)
74     , m_isRectilinear(true)
75 {
76     m_transformedRect = FloatQuad(m_boundingBox);
77 }
78
79 HitTestLocation::HitTestLocation(const HitTestLocation& other, const LayoutSize& offset)
80     : m_point(other.m_point)
81     , m_boundingBox(other.m_boundingBox)
82     , m_transformedPoint(other.m_transformedPoint)
83     , m_transformedRect(other.m_transformedRect)
84     , m_isRectBased(other.m_isRectBased)
85     , m_isRectilinear(other.m_isRectilinear)
86 {
87     move(offset);
88 }
89
90 HitTestLocation::HitTestLocation(const HitTestLocation& other)
91     : m_point(other.m_point)
92     , m_boundingBox(other.m_boundingBox)
93     , m_transformedPoint(other.m_transformedPoint)
94     , m_transformedRect(other.m_transformedRect)
95     , m_isRectBased(other.m_isRectBased)
96     , m_isRectilinear(other.m_isRectilinear)
97 {
98 }
99
100 HitTestLocation::~HitTestLocation()
101 {
102 }
103
104 HitTestLocation& HitTestLocation::operator=(const HitTestLocation& other)
105 {
106     m_point = other.m_point;
107     m_boundingBox = other.m_boundingBox;
108     m_transformedPoint = other.m_transformedPoint;
109     m_transformedRect = other.m_transformedRect;
110     m_isRectBased = other.m_isRectBased;
111     m_isRectilinear = other.m_isRectilinear;
112
113     return *this;
114 }
115
116 void HitTestLocation::move(const LayoutSize& offset)
117 {
118     m_point.move(offset);
119     m_transformedPoint.move(offset);
120     m_transformedRect.move(offset);
121     m_boundingBox = enclosingIntRect(m_transformedRect.boundingBox());
122 }
123
124 template<typename RectType>
125 bool HitTestLocation::intersectsRect(const RectType& rect) const
126 {
127     // FIXME: When the hit test is not rect based we should use rect.contains(m_point).
128     // That does change some corner case tests though.
129
130     // First check if rect even intersects our bounding box.
131     if (!rect.intersects(m_boundingBox))
132         return false;
133
134     // If the transformed rect is rectilinear the bounding box intersection was accurate.
135     if (m_isRectilinear)
136         return true;
137
138     // If rect fully contains our bounding box, we are also sure of an intersection.
139     if (rect.contains(m_boundingBox))
140         return true;
141
142     // Otherwise we need to do a slower quad based intersection test.
143     return m_transformedRect.intersectsRect(rect);
144 }
145
146 bool HitTestLocation::intersects(const LayoutRect& rect) const
147 {
148     return intersectsRect(rect);
149 }
150
151 bool HitTestLocation::intersects(const FloatRect& rect) const
152 {
153     return intersectsRect(rect);
154 }
155
156 bool HitTestLocation::intersects(const RoundedRect& rect) const
157 {
158     return rect.intersectsQuad(m_transformedRect);
159 }
160
161 IntRect HitTestLocation::rectForPoint(const LayoutPoint& point, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
162 {
163     IntPoint actualPoint(flooredIntPoint(point));
164     actualPoint -= IntSize(leftPadding, topPadding);
165
166     IntSize actualPadding(leftPadding + rightPadding, topPadding + bottomPadding);
167     // As IntRect is left inclusive and right exclusive (seeing IntRect::contains(x, y)), adding "1".
168     // FIXME: Remove this once non-rect based hit-detection stops using IntRect:intersects.
169     actualPadding += IntSize(1, 1);
170
171     return IntRect(actualPoint, actualPadding);
172 }
173
174 } // namespace WebCore