// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "modules/canvas2d/HitRegion.h" #include "core/dom/AXObjectCache.h" #include "core/layout/LayoutBoxModelObject.h" namespace blink { HitRegion::HitRegion(const Path& path, const HitRegionOptions& options) : m_id(options.id().isEmpty() ? String() : options.id()) , m_control(options.control()) , m_path(path) { if (options.fillRule() != "evenodd") m_fillRule = RULE_NONZERO; else m_fillRule = RULE_EVENODD; } bool HitRegion::contains(const FloatPoint& point) const { return m_path.contains(point, m_fillRule); } void HitRegion::removePixels(const Path& clearArea) { m_path.subtractPath(clearArea); } DEFINE_TRACE(HitRegion) { visitor->trace(m_control); } void HitRegionManager::addHitRegion(PassRefPtrWillBeRawPtr passHitRegion) { RefPtrWillBeRawPtr hitRegion = passHitRegion; m_hitRegionList.add(hitRegion); if (!hitRegion->id().isEmpty()) m_hitRegionIdMap.set(hitRegion->id(), hitRegion); if (hitRegion->control()) m_hitRegionControlMap.set(hitRegion->control(), hitRegion); } void HitRegionManager::removeHitRegion(HitRegion* hitRegion) { if (!hitRegion) return; if (!hitRegion->id().isEmpty()) m_hitRegionIdMap.remove(hitRegion->id()); if (hitRegion->control()) m_hitRegionControlMap.remove(hitRegion->control()); m_hitRegionList.remove(hitRegion); } void HitRegionManager::removeHitRegionById(const String& id) { if (!id.isEmpty()) removeHitRegion(getHitRegionById(id)); } void HitRegionManager::removeHitRegionByControl(Element* control) { removeHitRegion(getHitRegionByControl(control)); } void HitRegionManager::removeHitRegionsInRect(const FloatRect& rect, const AffineTransform& ctm) { Path clearArea; clearArea.addRect(rect); clearArea.transform(ctm); HitRegionIterator itEnd = m_hitRegionList.rend(); HitRegionList toBeRemoved; for (HitRegionIterator it = m_hitRegionList.rbegin(); it != itEnd; ++it) { RefPtrWillBeRawPtr hitRegion = *it; hitRegion->removePixels(clearArea); if (hitRegion->path().isEmpty()) toBeRemoved.add(hitRegion); } itEnd = toBeRemoved.rend(); for (HitRegionIterator it = toBeRemoved.rbegin(); it != itEnd; ++it) removeHitRegion(it->get()); } void HitRegionManager::removeAllHitRegions() { m_hitRegionList.clear(); m_hitRegionIdMap.clear(); m_hitRegionControlMap.clear(); } HitRegion* HitRegionManager::getHitRegionById(const String& id) const { return m_hitRegionIdMap.get(id); } HitRegion* HitRegionManager::getHitRegionByControl(Element* control) const { if (control) return m_hitRegionControlMap.get(control); return nullptr; } HitRegion* HitRegionManager::getHitRegionAtPoint(const FloatPoint& point) const { HitRegionIterator itEnd = m_hitRegionList.rend(); for (HitRegionIterator it = m_hitRegionList.rbegin(); it != itEnd; ++it) { RefPtrWillBeRawPtr hitRegion = *it; if (hitRegion->contains(point)) return hitRegion.get(); } return nullptr; } unsigned HitRegionManager::getHitRegionsCount() const { return m_hitRegionList.size(); } DEFINE_TRACE(HitRegionManager) { #if ENABLE(OILPAN) visitor->trace(m_hitRegionList); visitor->trace(m_hitRegionIdMap); visitor->trace(m_hitRegionControlMap); #endif } } // namespace blink