2 * Copyright (C) 2006, 2008, 2011 Apple Inc. All rights reserved.
3 * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
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.
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.
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.
23 #include "core/layout/HitTestLocation.h"
25 #include "platform/geometry/FloatRoundedRect.h"
29 HitTestLocation::HitTestLocation()
30 : m_isRectBased(false)
31 , m_isRectilinear(true)
35 HitTestLocation::HitTestLocation(const LayoutPoint
& point
)
37 , m_boundingBox(rectForPoint(point
, 0, 0, 0, 0))
38 , m_transformedPoint(point
)
39 , m_transformedRect(m_boundingBox
)
40 , m_isRectBased(false)
41 , m_isRectilinear(true)
45 HitTestLocation::HitTestLocation(const FloatPoint
& point
)
46 : m_point(flooredLayoutPoint(point
))
47 , m_boundingBox(rectForPoint(m_point
, 0, 0, 0, 0))
48 , m_transformedPoint(point
)
49 , m_transformedRect(m_boundingBox
)
50 , m_isRectBased(false)
51 , m_isRectilinear(true)
55 HitTestLocation::HitTestLocation(const FloatPoint
& point
, const FloatQuad
& quad
)
56 : m_transformedPoint(point
)
57 , m_transformedRect(quad
)
60 m_point
= flooredLayoutPoint(point
);
61 m_boundingBox
= enclosingIntRect(quad
.boundingBox());
62 m_isRectilinear
= quad
.isRectilinear();
65 HitTestLocation::HitTestLocation(const LayoutPoint
& centerPoint
, unsigned topPadding
, unsigned rightPadding
, unsigned bottomPadding
, unsigned leftPadding
)
66 : m_point(centerPoint
)
67 , m_boundingBox(rectForPoint(centerPoint
, topPadding
, rightPadding
, bottomPadding
, leftPadding
))
68 , m_transformedPoint(centerPoint
)
69 , m_isRectBased(topPadding
|| rightPadding
|| bottomPadding
|| leftPadding
)
70 , m_isRectilinear(true)
72 m_transformedRect
= FloatQuad(m_boundingBox
);
75 HitTestLocation::HitTestLocation(const HitTestLocation
& other
, const LayoutSize
& offset
)
76 : m_point(other
.m_point
)
77 , m_boundingBox(other
.m_boundingBox
)
78 , m_transformedPoint(other
.m_transformedPoint
)
79 , m_transformedRect(other
.m_transformedRect
)
80 , m_isRectBased(other
.m_isRectBased
)
81 , m_isRectilinear(other
.m_isRectilinear
)
86 HitTestLocation::HitTestLocation(const HitTestLocation
& other
)
87 : m_point(other
.m_point
)
88 , m_boundingBox(other
.m_boundingBox
)
89 , m_transformedPoint(other
.m_transformedPoint
)
90 , m_transformedRect(other
.m_transformedRect
)
91 , m_isRectBased(other
.m_isRectBased
)
92 , m_isRectilinear(other
.m_isRectilinear
)
96 HitTestLocation::~HitTestLocation()
100 HitTestLocation
& HitTestLocation::operator=(const HitTestLocation
& other
)
102 m_point
= other
.m_point
;
103 m_boundingBox
= other
.m_boundingBox
;
104 m_transformedPoint
= other
.m_transformedPoint
;
105 m_transformedRect
= other
.m_transformedRect
;
106 m_isRectBased
= other
.m_isRectBased
;
107 m_isRectilinear
= other
.m_isRectilinear
;
112 void HitTestLocation::move(const LayoutSize
& offset
)
114 m_point
.move(offset
);
115 m_transformedPoint
.move(offset
);
116 m_transformedRect
.move(offset
);
117 m_boundingBox
= enclosingIntRect(m_transformedRect
.boundingBox());
120 template<typename RectType
>
121 bool HitTestLocation::intersectsRect(const RectType
& rect
, const RectType
& boundingBox
) const
123 // FIXME: When the hit test is not rect based we should use rect.contains(m_point).
124 // That does change some corner case tests though.
126 // First check if rect even intersects our bounding box.
127 if (!rect
.intersects(boundingBox
))
130 // If the transformed rect is rectilinear the bounding box intersection was accurate.
134 // If rect fully contains our bounding box, we are also sure of an intersection.
135 if (rect
.contains(boundingBox
))
138 // Otherwise we need to do a slower quad based intersection test.
139 return m_transformedRect
.intersectsRect(FloatRect(rect
));
142 bool HitTestLocation::intersects(const LayoutRect
& rect
) const
144 return intersectsRect(rect
, LayoutRect(m_boundingBox
));
147 bool HitTestLocation::intersects(const FloatRect
& rect
) const
149 return intersectsRect(rect
, FloatRect(m_boundingBox
));
152 bool HitTestLocation::intersects(const FloatRoundedRect
& rect
) const
154 return rect
.intersectsQuad(m_transformedRect
);
157 bool HitTestLocation::containsPoint(const FloatPoint
& point
) const
159 return m_transformedRect
.containsPoint(point
);
162 IntRect
HitTestLocation::rectForPoint(const LayoutPoint
& point
, unsigned topPadding
, unsigned rightPadding
, unsigned bottomPadding
, unsigned leftPadding
)
164 IntPoint
actualPoint(flooredIntPoint(point
));
165 actualPoint
-= IntSize(leftPadding
, topPadding
);
167 IntSize
actualPadding(leftPadding
+ rightPadding
, topPadding
+ bottomPadding
);
168 // As IntRect is left inclusive and right exclusive (seeing IntRect::contains(x, y)), adding "1".
169 // FIXME: Remove this once non-rect based hit-detection stops using IntRect:intersects.
170 actualPadding
+= IntSize(1, 1);
172 return IntRect(actualPoint
, actualPadding
);