blob: a9b0a45c73e70d55dac3aa30a0e7e65cd5056796 [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 "third_party/blink/renderer/modules/canvas/canvas2d/hit_region.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.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);
}
void HitRegion::Trace(Visitor* visitor) const {
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();
}
void HitRegionManager::Trace(Visitor* visitor) const {
visitor->Trace(hit_region_list_);
visitor->Trace(hit_region_id_map_);
visitor->Trace(hit_region_control_map_);
}
} // namespace blink