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 11namespace blink { 12 13HitRegion::HitRegion(const HitRegionOptionsInternal& options) 14 : m_id(options.id) 15 , m_control(options.control) 16 , m_path(options.path) 17 , m_fillRule(options.fillRule) 18{ 19} 20 21void 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 43bool HitRegion::contains(const LayoutPoint& point) const 44{ 45 return m_path.contains(point, m_fillRule); 46} 47 48void HitRegion::removePixels(const Path& clearArea) 49{ 50 m_path.subtractPath(clearArea); 51} 52 53void HitRegion::trace(Visitor* visitor) 54{ 55 visitor->trace(m_control); 56} 57 58void 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 71void 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 85void HitRegionManager::removeHitRegionById(const String& id) 86{ 87 if (!id.isEmpty()) 88 removeHitRegion(getHitRegionById(id)); 89} 90 91void HitRegionManager::removeHitRegionByControl(Element* control) 92{ 93 removeHitRegion(getHitRegionByControl(control)); 94} 95 96void 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 117void HitRegionManager::removeAllHitRegions() 118{ 119 m_hitRegionList.clear(); 120 m_hitRegionIdMap.clear(); 121 m_hitRegionControlMap.clear(); 122} 123 124HitRegion* HitRegionManager::getHitRegionById(const String& id) const 125{ 126 return m_hitRegionIdMap.get(id); 127} 128 129HitRegion* HitRegionManager::getHitRegionByControl(Element* control) const 130{ 131 if (control) 132 return m_hitRegionControlMap.get(control); 133 134 return 0; 135} 136 137HitRegion* 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 150unsigned HitRegionManager::getHitRegionsCount() const 151{ 152 return m_hitRegionList.size(); 153} 154 155void 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 164DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(HitRegionManager) 165 166} // namespace blink 167