summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/modules/canvas/canvas2d/hit_region.cc
blob: fc1ba5beebd313ad773ecf1641c9e6de9867d38f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// 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(blink::Visitor* visitor) {
  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(blink::Visitor* visitor) {
  visitor->Trace(hit_region_list_);
  visitor->Trace(hit_region_id_map_);
  visitor->Trace(hit_region_control_map_);
}

}  // namespace blink