blob: d50a32db9d17161a603bf12d8251a6c14ca2d6f8 [file] [log] [blame]
// 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_