Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / canvas / HitRegion.cpp
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "config.h"
6 #include "core/html/canvas/HitRegion.h"
7
8 #include "core/accessibility/AXObjectCache.h"
9 #include "core/rendering/RenderBoxModelObject.h"
10
11 namespace blink {
12
13 HitRegion::HitRegion(const HitRegionOptions& options)
14     : m_id(options.id)
15     , m_control(options.control)
16     , m_path(options.path)
17     , m_fillRule(options.fillRule)
18 {
19 }
20
21 void HitRegion::updateAccessibility(Element* canvas)
22 {
23     if (!m_control || !canvas || !canvas->renderer() || !m_control->isDescendantOf(canvas))
24         return;
25
26     AXObjectCache* axObjectCache = m_control->document().existingAXObjectCache();
27     if (!axObjectCache)
28         return;
29
30     FloatRect boundingRect = m_path.boundingRect();
31
32     // Offset by the canvas rect, taking border and padding into account.
33     RenderBoxModelObject* rbmo = canvas->renderBoxModelObject();
34     IntRect canvasRect = canvas->renderer()->absoluteBoundingBoxRect();
35     canvasRect.move(rbmo->borderLeft() + rbmo->paddingLeft(),
36         rbmo->borderTop() + rbmo->paddingTop());
37     LayoutRect elementRect = enclosingLayoutRect(boundingRect);
38     elementRect.moveBy(canvasRect.location());
39
40     axObjectCache->setCanvasObjectBounds(m_control.get(), elementRect);
41 }
42
43 bool HitRegion::contains(const LayoutPoint& point) const
44 {
45     return m_path.contains(point, m_fillRule);
46 }
47
48 void HitRegion::removePixels(const Path& clearArea)
49 {
50     m_path.subtractPath(clearArea);
51 }
52
53 void HitRegion::trace(Visitor* visitor)
54 {
55     visitor->trace(m_control);
56 }
57
58 void HitRegionManager::addHitRegion(PassRefPtrWillBeRawPtr<HitRegion> passHitRegion)
59 {
60     RefPtrWillBeRawPtr<HitRegion> hitRegion = passHitRegion;
61
62     m_hitRegionList.add(hitRegion);
63
64     if (!hitRegion->id().isEmpty())
65         m_hitRegionIdMap.set(hitRegion->id(), hitRegion);
66
67     if (hitRegion->control())
68         m_hitRegionControlMap.set(hitRegion->control(), hitRegion);
69 }
70
71 void HitRegionManager::removeHitRegion(HitRegion* hitRegion)
72 {
73     if (!hitRegion)
74         return;
75
76     if (!hitRegion->id().isEmpty())
77         m_hitRegionIdMap.remove(hitRegion->id());
78
79     if (hitRegion->control())
80         m_hitRegionControlMap.remove(hitRegion->control());
81
82     m_hitRegionList.remove(hitRegion);
83 }
84
85 void HitRegionManager::removeHitRegionById(const String& id)
86 {
87     if (!id.isEmpty())
88         removeHitRegion(getHitRegionById(id));
89 }
90
91 void HitRegionManager::removeHitRegionByControl(Element* control)
92 {
93     removeHitRegion(getHitRegionByControl(control));
94 }
95
96 void HitRegionManager::removeHitRegionsInRect(const FloatRect& rect, const AffineTransform& ctm)
97 {
98     Path clearArea;
99     clearArea.addRect(rect);
100     clearArea.transform(ctm);
101
102     HitRegionIterator itEnd = m_hitRegionList.rend();
103     HitRegionList toBeRemoved;
104
105     for (HitRegionIterator it = m_hitRegionList.rbegin(); it != itEnd; ++it) {
106         RefPtrWillBeRawPtr<HitRegion> hitRegion = *it;
107         hitRegion->removePixels(clearArea);
108         if (hitRegion->path().isEmpty())
109             toBeRemoved.add(hitRegion);
110     }
111
112     itEnd = toBeRemoved.rend();
113     for (HitRegionIterator it = toBeRemoved.rbegin(); it != itEnd; ++it)
114         removeHitRegion(it->get());
115 }
116
117 void HitRegionManager::removeAllHitRegions()
118 {
119     m_hitRegionList.clear();
120     m_hitRegionIdMap.clear();
121     m_hitRegionControlMap.clear();
122 }
123
124 HitRegion* HitRegionManager::getHitRegionById(const String& id) const
125 {
126     return m_hitRegionIdMap.get(id);
127 }
128
129 HitRegion* HitRegionManager::getHitRegionByControl(Element* control) const
130 {
131     if (control)
132         return m_hitRegionControlMap.get(control);
133
134     return 0;
135 }
136
137 HitRegion* HitRegionManager::getHitRegionAtPoint(const LayoutPoint& point) const
138 {
139     HitRegionIterator itEnd = m_hitRegionList.rend();
140
141     for (HitRegionIterator it = m_hitRegionList.rbegin(); it != itEnd; ++it) {
142         RefPtrWillBeRawPtr<HitRegion> hitRegion = *it;
143         if (hitRegion->contains(point))
144             return hitRegion.get();
145     }
146
147     return 0;
148 }
149
150 unsigned HitRegionManager::getHitRegionsCount() const
151 {
152     return m_hitRegionList.size();
153 }
154
155 void HitRegionManager::trace(Visitor* visitor)
156 {
157 #if ENABLE(OILPAN)
158     visitor->trace(m_hitRegionList);
159     visitor->trace(m_hitRegionIdMap);
160     visitor->trace(m_hitRegionControlMap);
161 #endif
162 }
163
164 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(HitRegionManager)
165
166 } // namespace blink