summaryrefslogtreecommitdiff
path: root/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util.h
blob: d50a32db9d17161a603bf12d8251a6c14ca2d6f8 (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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright 2019 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.

#ifndef UI_EVENTS_OZONE_EVDEV_TOUCH_FILTER_NEURAL_STYLUS_PALM_DETECTION_FILTER_UTIL_H_
#define UI_EVENTS_OZONE_EVDEV_TOUCH_FILTER_NEURAL_STYLUS_PALM_DETECTION_FILTER_UTIL_H_

#include <cstdint>
#include <deque>
#include <vector>

#if defined(__ANDROID__) || defined(__ANDROID_HOST__)
#undef LOG_INFO
#undef LOG_WARNING
#include <chrome_to_android_compatibility.h>
#endif
#include "base/time/time.h"
#if !defined(__ANDROID__) && !defined(__ANDROID_HOST__)
#include "ui/events/ozone/evdev/event_device_info.h"
#endif
#include "ui/events/ozone/evdev/touch_evdev_types.h"
#include "ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_model.h"
#include "ui/gfx/geometry/point_f.h"

namespace ui {

struct COMPONENT_EXPORT(EVDEV) PalmFilterDeviceInfo {
  float max_x = 0.f;
  float max_y = 0.f;
  float x_res = 1.f;
  float y_res = 1.f;
  float major_radius_res = 1.f;
  float minor_radius_res = 1.f;
  bool minor_radius_supported = false;
#if defined(__ANDROID__) || defined(__ANDROID_HOST__)
  auto operator<=>(const PalmFilterDeviceInfo&) const = default;
#endif
};

std::ostream& operator<<(std::ostream& out, const PalmFilterDeviceInfo& info);

#if !defined(__ANDROID__) && !defined(__ANDROID_HOST__)
COMPONENT_EXPORT(EVDEV)
PalmFilterDeviceInfo CreatePalmFilterDeviceInfo(const EventDeviceInfo& devinfo);
#endif

// Data for a single touch event.
struct COMPONENT_EXPORT(EVDEV) PalmFilterSample {
  float major_radius = 0;
  float minor_radius = 0;
  float pressure = 0;
  float edge = 0;
  int tracking_id = 0;
  gfx::PointF point;
  base::TimeTicks time;

  bool operator==(const PalmFilterSample& other) const {
    return major_radius == other.major_radius &&
           minor_radius == other.minor_radius && pressure == other.pressure &&
           edge == other.edge && tracking_id == other.tracking_id &&
           point == other.point && time == other.time;
  }
};

std::ostream& operator<<(std::ostream& out, const PalmFilterSample& sample);

COMPONENT_EXPORT(EVDEV)
PalmFilterSample CreatePalmFilterSample(
    const InProgressTouchEvdev& touch,
    const base::TimeTicks& time,
    const NeuralStylusPalmDetectionFilterModelConfig& model_config,
    const PalmFilterDeviceInfo& dev_info);

class COMPONENT_EXPORT(EVDEV) PalmFilterStroke {
 public:
  explicit PalmFilterStroke(
      const NeuralStylusPalmDetectionFilterModelConfig& model_config,
      int tracking_id);
  PalmFilterStroke(const PalmFilterStroke& other);
  PalmFilterStroke(PalmFilterStroke&& other);
  ~PalmFilterStroke();

  void ProcessSample(const PalmFilterSample& sample);
  gfx::PointF GetCentroid() const;
  float BiggestSize() const;
  // If no elements in stroke, returns 0.0;
  float MaxMajorRadius() const;
  /**
   * Return the time duration of this stroke.
   */
  base::TimeDelta Duration() const;
  /**
   * Provide a (potentially resampled) sample at the requested time.
   * Only interpolation is allowed.
   * The requested time must be within the window at which the gesture occurred.
   */
  PalmFilterSample GetSampleAt(base::TimeTicks time) const;

  /**
   * Return true if the provided duration is between the duration of the
   * previous sample and the current sample. In other words, if the addition of
   * the last sample caused the total stroke duration to exceed the provided
   * duration. Return false otherwise.
   */
  bool LastSampleCrossed(base::TimeDelta duration) const;

  const std::deque<PalmFilterSample>& samples() const;
  uint64_t samples_seen() const;
  int tracking_id() const;

 private:
  void AddToUnscaledCentroid(const gfx::Vector2dF point);
  void AddSample(const PalmFilterSample& sample);

  base::TimeDelta PreviousDuration() const;

  std::deque<PalmFilterSample> samples_;
  const int tracking_id_;
  /**
   * How many total samples have been reported for this stroke. This is
   * different from samples_.size() because samples_ will get pruned to only
   * keep a certain number of last samples.
   * When resampling is enabled, this value will be equal to the number of
   * resampled values that this stroke has received. It may not be equal to the
   * number of times 'AddSample' has been called.
   */
  uint64_t samples_seen_ = 0;

  const uint64_t max_sample_count_;
  base::TimeTicks first_sample_time_;
  const base::Optional<base::TimeDelta> resample_period_;

  gfx::PointF unscaled_centroid_ = gfx::PointF(0., 0.);
  // Used in part of the kahan summation.
  gfx::Vector2dF unscaled_centroid_sum_error_ =
      gfx::PointF(0., 0.).OffsetFromOrigin();
  friend std::ostream& operator<<(std::ostream& out,
                                  const PalmFilterStroke& stroke);
};

template <typename T>
std::ostream& operator<<(std::ostream& out, const std::deque<T>& queue) {
  for (const auto& entry : queue) {
    out << entry << "\n";
  }
  return out;
}

std::ostream& operator<<(std::ostream& out, const PalmFilterStroke& filter);

}  // namespace ui

#endif  // UI_EVENTS_OZONE_EVDEV_TOUCH_FILTER_NEURAL_STYLUS_PALM_DETECTION_FILTER_UTIL_H_