Native text selection UI is incorrectly suppressed in Microsoft Visio
[WebKit-https.git] / Source / WebCore / 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 "HitTestLocation.h"
24
25 namespace WebCore {
26
27 HitTestLocation::HitTestLocation()
28     : m_isRectBased(false)
29     , m_isRectilinear(true)
30 {
31 }
32
33 HitTestLocation::HitTestLocation(const LayoutPoint& point)
34     : m_point(point)
35     , m_boundingBox(rectForPoint(point, 0, 0, 0, 0))
36     , m_transformedPoint(point)
37     , m_transformedRect(m_boundingBox)
38     , m_isRectBased(false)
39     , m_isRectilinear(true)
40 {
41 }
42
43 HitTestLocation::HitTestLocation(const FloatPoint& point)
44     : m_point(flooredLayoutPoint(point))
45     , m_boundingBox(rectForPoint(m_point, 0, 0, 0, 0))
46     , m_transformedPoint(point)
47     , m_transformedRect(m_boundingBox)
48     , m_isRectBased(false)
49     , m_isRectilinear(true)
50 {
51 }
52
53 HitTestLocation::HitTestLocation(const FloatPoint& point, const FloatQuad& quad)
54     : m_transformedPoint(point)
55     , m_transformedRect(quad)
56     , m_isRectBased(true)
57 {
58     m_point = flooredLayoutPoint(point);
59     m_boundingBox = enclosingIntRect(quad.boundingBox());
60     m_isRectilinear = quad.isRectilinear();
61 }
62
63 HitTestLocation::HitTestLocation(const LayoutPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
64     : m_point(centerPoint)
65     , m_boundingBox(rectForPoint(centerPoint, topPadding, rightPadding, bottomPadding, leftPadding))
66     , m_transformedPoint(centerPoint)
67     , m_isRectBased(topPadding || rightPadding || bottomPadding || leftPadding)
68     , m_isRectilinear(true)
69 {
70     m_transformedRect = FloatQuad(m_boundingBox);
71 }
72
73 HitTestLocation::HitTestLocation(const HitTestLocation& other, const LayoutSize& offset)
74     : m_point(other.m_point)
75     , m_boundingBox(other.m_boundingBox)
76     , m_transformedPoint(other.m_transformedPoint)
77     , m_transformedRect(other.m_transformedRect)
78     , m_isRectBased(other.m_isRectBased)
79     , m_isRectilinear(other.m_isRectilinear)
80 {
81     move(offset);
82 }
83
84 HitTestLocation::HitTestLocation(const HitTestLocation& other)
85     : m_point(other.m_point)
86     , m_boundingBox(other.m_boundingBox)
87     , m_transformedPoint(other.m_transformedPoint)
88     , m_transformedRect(other.m_transformedRect)
89     , m_isRectBased(other.m_isRectBased)
90     , m_isRectilinear(other.m_isRectilinear)
91 {
92 }
93
94 HitTestLocation::~HitTestLocation() = default;
95
96 HitTestLocation& HitTestLocation::operator=(const HitTestLocation& other)
97 {
98     m_point = other.m_point;
99     m_boundingBox = other.m_boundingBox;
100     m_transformedPoint = other.m_transformedPoint;
101     m_transformedRect = other.m_transformedRect;
102     m_isRectBased = other.m_isRectBased;
103     m_isRectilinear = other.m_isRectilinear;
104
105     return *this;
106 }
107
108 void HitTestLocation::move(const LayoutSize& offset)
109 {
110     m_point.move(offset);
111     m_transformedPoint.move(offset);
112     m_transformedRect.move(offset);
113     m_boundingBox = enclosingIntRect(m_transformedRect.boundingBox());
114 }
115
116 template<typename RectType>
117 bool HitTestLocation::intersectsRect(const RectType& rect) const
118 {
119     // FIXME: When the hit test is not rect based we should use rect.contains(m_point).
120     // That does change some corner case tests though.
121
122     // First check if rect even intersects our bounding box.
123     if (!rect.intersects(m_boundingBox))
124         return false;
125
126     // If the transformed rect is rectilinear the bounding box intersection was accurate.
127     if (m_isRectilinear)
128         return true;
129
130     // If rect fully contains our bounding box, we are also sure of an intersection.
131     if (rect.contains(m_boundingBox))
132         return true;
133
134     // Otherwise we need to do a slower quad based intersection test.
135     return m_transformedRect.intersectsRect(rect);
136 }
137
138 bool HitTestLocation::intersects(const LayoutRect& rect) const
139 {
140     return intersectsRect(rect);
141 }
142
143 bool HitTestLocation::intersects(const FloatRect& rect) const
144 {
145     return intersectsRect(rect);
146 }
147
148 bool HitTestLocation::intersects(const RoundedRect& rect) const
149 {
150     return rect.intersectsQuad(m_transformedRect);
151 }
152
153 IntRect HitTestLocation::rectForPoint(const LayoutPoint& point, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
154 {
155     IntPoint actualPoint(flooredIntPoint(point));
156     actualPoint -= IntSize(leftPadding, topPadding);
157
158     IntSize actualPadding(leftPadding + rightPadding, topPadding + bottomPadding);
159     // As IntRect is left inclusive and right exclusive (seeing IntRect::contains(x, y)), adding "1".
160     // FIXME: Remove this once non-rect based hit-detection stops using IntRect:intersects.
161     actualPadding += IntSize(1, 1);
162
163     return IntRect(actualPoint, actualPadding);
164 }
165
166 } // namespace WebCore