blob: 74d40a7a212e89f4c13123153d1e5b7ca63c2c82 [file] [log] [blame]
// 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"
namespace blink {
HitRegion::HitRegion(const Path& path, const HitRegionOptions& options)
: id_(options.id().IsEmpty() ? String() : options.id()),
control_(options.control()),
path_(path) {
if (options.fillRule() != "evenodd")
fill_rule_ = RULE_NONZERO;
else
fill_rule_ = RULE_EVENODD;
}
bool HitRegion::Contains(const FloatPoint& point) const {
return path_.Contains(point, fill_rule_);
}
void HitRegion::RemovePixels(const Path& clear_area) {
path_.SubtractPath(clear_area);
}
DEFINE_TRACE(HitRegion) {
visitor->Trace(control_);
}
void HitRegionManager::AddHitRegion(HitRegion* hit_region) {
hit_region_list_.insert(hit_region);
if (!hit_region->Id().IsEmpty())
hit_region_id_map_.Set(hit_region->Id(), hit_region);
if (hit_region->Control())
hit_region_control_map_.Set(hit_region->Control(), hit_region);
}
void HitRegionManager::RemoveHitRegion(HitRegion* hit_region) {
if (!hit_region)
return;
if (!hit_region->Id().IsEmpty())
hit_region_id_map_.erase(hit_region->Id());
if (hit_region->Control())
hit_region_control_map_.erase(hit_region->Control());
hit_region_list_.erase(hit_region);
}
void HitRegionManager::RemoveHitRegionById(const String& id) {
if (!id.IsEmpty())
RemoveHitRegion(GetHitRegionById(id));
}
void HitRegionManager::RemoveHitRegionByControl(const Element* control) {
RemoveHitRegion(GetHitRegionByControl(control));
}
void HitRegionManager::RemoveHitRegionsInRect(const FloatRect& rect,
const AffineTransform& ctm) {
Path clear_area;
clear_area.AddRect(rect);
clear_area.Transform(ctm);
HitRegionIterator it_end = hit_region_list_.rend();
HitRegionList to_be_removed;
for (HitRegionIterator it = hit_region_list_.rbegin(); it != it_end; ++it) {
HitRegion* hit_region = *it;
hit_region->RemovePixels(clear_area);
if (hit_region->GetPath().IsEmpty())
to_be_removed.insert(hit_region);
}
it_end = to_be_removed.rend();
for (HitRegionIterator it = to_be_removed.rbegin(); it != it_end; ++it)
RemoveHitRegion(it->Get());
}
void HitRegionManager::RemoveAllHitRegions() {
hit_region_list_.clear();
hit_region_id_map_.clear();
hit_region_control_map_.clear();
}
HitRegion* HitRegionManager::GetHitRegionById(const String& id) const {
return hit_region_id_map_.at(id);
}
HitRegion* HitRegionManager::GetHitRegionByControl(
const Element* control) const {
if (control)
return hit_region_control_map_.at(control);
return nullptr;
}
HitRegion* HitRegionManager::GetHitRegionAtPoint(
const FloatPoint& point) const {
HitRegionIterator it_end = hit_region_list_.rend();
for (HitRegionIterator it = hit_region_list_.rbegin(); it != it_end; ++it) {
HitRegion* hit_region = *it;
if (hit_region->Contains(point))
return hit_region;
}
return nullptr;
}
unsigned HitRegionManager::GetHitRegionsCount() const {
return hit_region_list_.size();
}
DEFINE_TRACE(HitRegionManager) {
visitor->Trace(hit_region_list_);
visitor->Trace(hit_region_id_map_);
visitor->Trace(hit_region_control_map_);
}
} // namespace blink