1926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/*
2926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * Copyright (C) 2006, 2008, 2011 Apple Inc. All rights reserved.
3926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
4926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) *
5926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * This library is free software; you can redistribute it and/or
6926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * modify it under the terms of the GNU Library General Public
7926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * License as published by the Free Software Foundation; either
8926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * version 2 of the License, or (at your option) any later version.
9926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) *
10926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * This library is distributed in the hope that it will be useful,
11926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of
12926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * Library General Public License for more details.
14926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) *
15926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * You should have received a copy of the GNU Library General Public License
16926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * along with this library; see the file COPYING.LIB.  If not, write to
17926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * Boston, MA 02110-1301, USA.
19926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) *
20926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)*/
21926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
22926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#include "config.h"
2353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/HitTestLocation.h"
24926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
25926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)namespace WebCore {
26926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
27926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)HitTestLocation::HitTestLocation()
2809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    : m_isRectBased(false)
29926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_isRectilinear(true)
30926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
31926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
32926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
33926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)HitTestLocation::HitTestLocation(const LayoutPoint& point)
34926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    : m_point(point)
35926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_boundingBox(rectForPoint(point, 0, 0, 0, 0))
36926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_transformedPoint(point)
37926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_transformedRect(m_boundingBox)
38926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_isRectBased(false)
39926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_isRectilinear(true)
40926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
41926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
42926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
43926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)HitTestLocation::HitTestLocation(const FloatPoint& point)
44926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    : m_point(flooredLayoutPoint(point))
45926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_boundingBox(rectForPoint(m_point, 0, 0, 0, 0))
46926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_transformedPoint(point)
47926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_transformedRect(m_boundingBox)
48926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_isRectBased(false)
49926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_isRectilinear(true)
50926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
51926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
52926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
53926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)HitTestLocation::HitTestLocation(const FloatPoint& point, const FloatQuad& quad)
54926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    : m_transformedPoint(point)
55926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_transformedRect(quad)
56926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_isRectBased(true)
57926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
58926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_point = flooredLayoutPoint(point);
59926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_boundingBox = enclosingIntRect(quad.boundingBox());
60926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_isRectilinear = quad.isRectilinear();
61926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
62926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
63926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)HitTestLocation::HitTestLocation(const LayoutPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
64926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    : m_point(centerPoint)
65926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_boundingBox(rectForPoint(centerPoint, topPadding, rightPadding, bottomPadding, leftPadding))
66926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_transformedPoint(centerPoint)
67926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_isRectBased(topPadding || rightPadding || bottomPadding || leftPadding)
68926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_isRectilinear(true)
69926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
70926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_transformedRect = FloatQuad(m_boundingBox);
71926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
72926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
7309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)HitTestLocation::HitTestLocation(const HitTestLocation& other, const LayoutSize& offset)
74926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    : m_point(other.m_point)
75926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_boundingBox(other.m_boundingBox)
76926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_transformedPoint(other.m_transformedPoint)
77926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_transformedRect(other.m_transformedRect)
78926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_isRectBased(other.m_isRectBased)
79926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_isRectilinear(other.m_isRectilinear)
80926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
81926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    move(offset);
82926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
83926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
84926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)HitTestLocation::HitTestLocation(const HitTestLocation& other)
85926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    : m_point(other.m_point)
86926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_boundingBox(other.m_boundingBox)
87926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_transformedPoint(other.m_transformedPoint)
88926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_transformedRect(other.m_transformedRect)
89926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_isRectBased(other.m_isRectBased)
90926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_isRectilinear(other.m_isRectilinear)
91926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
92926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
93926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
94926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)HitTestLocation::~HitTestLocation()
95926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
96926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
97926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
98926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)HitTestLocation& HitTestLocation::operator=(const HitTestLocation& other)
99926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
100926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_point = other.m_point;
101926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_boundingBox = other.m_boundingBox;
102926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_transformedPoint = other.m_transformedPoint;
103926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_transformedRect = other.m_transformedRect;
104926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_isRectBased = other.m_isRectBased;
105926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_isRectilinear = other.m_isRectilinear;
106926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
107926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return *this;
108926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
109926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
110926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void HitTestLocation::move(const LayoutSize& offset)
111926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
112926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_point.move(offset);
113926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_transformedPoint.move(offset);
114926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_transformedRect.move(offset);
115926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_boundingBox = enclosingIntRect(m_transformedRect.boundingBox());
116926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
117926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
118926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)template<typename RectType>
119926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool HitTestLocation::intersectsRect(const RectType& rect) const
120926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
121926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // FIXME: When the hit test is not rect based we should use rect.contains(m_point).
122926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // That does change some corner case tests though.
123926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
124926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // First check if rect even intersects our bounding box.
125926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!rect.intersects(m_boundingBox))
126926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return false;
127926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
128926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // If the transformed rect is rectilinear the bounding box intersection was accurate.
129926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (m_isRectilinear)
130926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return true;
131926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
132926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // If rect fully contains our bounding box, we are also sure of an intersection.
133926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (rect.contains(m_boundingBox))
134926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return true;
135926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
136926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Otherwise we need to do a slower quad based intersection test.
137926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return m_transformedRect.intersectsRect(rect);
138926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
139926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
140926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool HitTestLocation::intersects(const LayoutRect& rect) const
141926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
142926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return intersectsRect(rect);
143926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
144926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
145926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool HitTestLocation::intersects(const FloatRect& rect) const
146926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
147926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return intersectsRect(rect);
148926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
149926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
150926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool HitTestLocation::intersects(const RoundedRect& rect) const
151926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
152926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return rect.intersectsQuad(m_transformedRect);
153926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
154926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
155926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)IntRect HitTestLocation::rectForPoint(const LayoutPoint& point, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
156926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
157926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    IntPoint actualPoint(flooredIntPoint(point));
158926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    actualPoint -= IntSize(leftPadding, topPadding);
159926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
160926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    IntSize actualPadding(leftPadding + rightPadding, topPadding + bottomPadding);
161926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // As IntRect is left inclusive and right exclusive (seeing IntRect::contains(x, y)), adding "1".
162926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // FIXME: Remove this once non-rect based hit-detection stops using IntRect:intersects.
163926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    actualPadding += IntSize(1, 1);
164926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
165926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return IntRect(actualPoint, actualPadding);
166926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
167926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
168926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)} // namespace WebCore
169