| Index: ash/common/system/chromeos/palette/tools/laser_pointer_points.cc
|
| diff --git a/ash/common/system/chromeos/palette/tools/laser_pointer_points.cc b/ash/common/system/chromeos/palette/tools/laser_pointer_points.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..606ccb36d5a016068820b1b8c023fcf2edb9792a
|
| --- /dev/null
|
| +++ b/ash/common/system/chromeos/palette/tools/laser_pointer_points.cc
|
| @@ -0,0 +1,184 @@
|
| +// Copyright 2016 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 "ash/common/system/chromeos/palette/tools/laser_pointer_points.h"
|
| +
|
| +#include "ui/gfx/geometry/cubic_bezier.h"
|
| +
|
| +namespace ash {
|
| +
|
| +LaserPointerPoints::LaserPointerPoints(base::TimeDelta life_duration) {
|
| + life_duration_ = life_duration;
|
| +}
|
| +
|
| +LaserPointerPoints::LaserPointerPoints(const LaserPointerPoints& old) {
|
| + bounds_ = old.bounds_;
|
| + points_ = old.points_;
|
| + life_duration_ = old.life_duration_;
|
| +}
|
| +
|
| +LaserPointerPoints::~LaserPointerPoints() {}
|
| +
|
| +void LaserPointerPoints::AddPoint(const gfx::Point& point) {
|
| + // Creates and adds the new point. Updates the collection and bounding box
|
| + // accordingly.
|
| + base::Time pointTime = base::Time::Now();
|
| + LaserPointerPoint newPoint;
|
| + newPoint.location_ = point;
|
| + newPoint.creationTime_ = pointTime;
|
| +
|
| + if (points_.empty())
|
| + bounds_.SetRect(point.x(), point.y(), 0, 0);
|
| + else {
|
| + std::vector<LaserPointerPoint> generatedPoints;
|
| + // GenerateCurvePoints(newPoint, generatedPoints);
|
| + for (size_t j = 0; j < generatedPoints.size(); j++) {
|
| + points_.push_back(generatedPoints[j]);
|
| + }
|
| + CalculateBounds(newPoint.location_);
|
| + }
|
| + points_.push_back(newPoint);
|
| + ClearOldPoints();
|
| +}
|
| +
|
| +void LaserPointerPoints::Clear() {
|
| + points_.clear();
|
| +}
|
| +
|
| +gfx::Rect LaserPointerPoints::GetBoundingBox() const {
|
| + return bounds_;
|
| +}
|
| +
|
| +LaserPointerPoints::LaserPointerPoint LaserPointerPoints::GetOldest() const {
|
| + if (!points_.empty())
|
| + return points_.front();
|
| + return LaserPointerPoint();
|
| +}
|
| +
|
| +LaserPointerPoints::LaserPointerPoint LaserPointerPoints::GetMostRecent()
|
| + const {
|
| + if (!points_.empty())
|
| + return points_.back();
|
| + return LaserPointerPoint();
|
| +}
|
| +
|
| +bool LaserPointerPoints::IsEmpty() const {
|
| + return points_.empty();
|
| +}
|
| +
|
| +int LaserPointerPoints::GetNumberOfPoints() const {
|
| + return points_.size();
|
| +}
|
| +
|
| +std::deque<LaserPointerPoints::LaserPointerPoint>::const_iterator
|
| +LaserPointerPoints::PointsStart() const {
|
| + return points_.cbegin();
|
| +}
|
| +
|
| +std::deque<LaserPointerPoints::LaserPointerPoint>::const_iterator
|
| +LaserPointerPoints::PointsEnd() const {
|
| + return points_.cend();
|
| +}
|
| +
|
| +void LaserPointerPoints::CalculateBounds(const gfx::Point& point) {
|
| + gfx::Rect oldBounds;
|
| + oldBounds.SetRect(bounds_.x(), bounds_.y(), bounds_.width(),
|
| + bounds_.height());
|
| + // This will do nothing if the point is within the current bounds.
|
| + bool xChanged = false;
|
| + bool yChanged = false;
|
| + if (point.x() <= oldBounds.x()) {
|
| + bounds_.set_x(point.x());
|
| + xChanged = true;
|
| + }
|
| + if (point.y() <= oldBounds.y()) {
|
| + bounds_.set_y(point.y());
|
| + yChanged = true;
|
| + }
|
| + if (point.x() >= oldBounds.right()) {
|
| + bounds_.set_width(std::abs(point.x() - bounds_.x()));
|
| + } else if (xChanged)
|
| + bounds_.set_width(std::abs(oldBounds.right() - bounds_.x()));
|
| + if (point.y() >= oldBounds.bottom()) {
|
| + bounds_.set_height(std::abs(point.y() - bounds_.y()));
|
| + } else if (yChanged)
|
| + bounds_.set_height(std::abs(oldBounds.bottom() - bounds_.y()));
|
| +}
|
| +
|
| +void LaserPointerPoints::ClearOldPoints() {
|
| + if (!points_.empty()) {
|
| + bool needRecalculateBounds = false;
|
| + LaserPointerPoint newest = points_.back();
|
| + for (auto it = points_.begin(); it != points_.end(); it++) {
|
| + if (newest.creationTime_ - it->creationTime_ > life_duration_) {
|
| + if (!needRecalculateBounds || it->location_.x() <= bounds_.x() ||
|
| + it->location_.x() >= bounds_.right() ||
|
| + it->location_.y() <= bounds_.y() ||
|
| + it->location_.y() >= bounds_.bottom()) {
|
| + // If the point was on of the outermost points we have to recalculate
|
| + // the bounds.
|
| + needRecalculateBounds = true;
|
| + }
|
| + points_.erase(it);
|
| + } else {
|
| + // Since the points are sorted by time we can end the loop early once
|
| + // the condition fails.
|
| + break;
|
| + }
|
| + }
|
| + if (needRecalculateBounds)
|
| + RecalculateBounds();
|
| + }
|
| +}
|
| +
|
| +float LaserPointerPoints::DistanceMousePoints(const LaserPointerPoint& point1,
|
| + const LaserPointerPoint& point2) {
|
| + return sqrt((point2.location_.y() - point1.location_.y()) *
|
| + (point2.location_.y() - point1.location_.y()) +
|
| + (point2.location_.x() - point1.location_.x()) *
|
| + (point2.location_.x() - point1.location_.x()));
|
| +}
|
| +
|
| +void LaserPointerPoints::GenerateCurvePoints(
|
| + const LaserPointerPoint& newPoint,
|
| + std::vector<LaserPointerPoint>& generatedPoints) {
|
| + if (points_.empty())
|
| + return;
|
| +
|
| + LaserPointerPoint lastPoint = points_.back();
|
| + gfx::CubicBezier bezier = gfx::CubicBezier(0.25, 0.0, 0.75, 1.0);
|
| + float distance = DistanceMousePoints(newPoint, lastPoint);
|
| +
|
| + // Generate some equidistant points using the bezier.
|
| + for (float j = 1; j <= distance - 1; j += 3) {
|
| + float normalized = 1 - ((distance - j) / distance);
|
| + base::Time generatedTime =
|
| + lastPoint.creationTime_ +
|
| + base::TimeDelta::FromMillisecondsD(
|
| + double{normalized *
|
| + float{(newPoint.creationTime_ - lastPoint.creationTime_)
|
| + .InMillisecondsF()}});
|
| + LaserPointerPoint generatedPoint;
|
| + float currentX =
|
| + lastPoint.location_.x() +
|
| + normalized * (newPoint.location_.x() - lastPoint.location_.x());
|
| + float currentY = lastPoint.location_.y() +
|
| + float{bezier.Solve(normalized)} *
|
| + (newPoint.location_.y() - lastPoint.location_.y());
|
| + generatedPoint.creationTime_ = generatedTime;
|
| + generatedPoint.location_ = gfx::Point(currentX, currentY);
|
| + generatedPoints.push_back(generatedPoint);
|
| + }
|
| +}
|
| +
|
| +void LaserPointerPoints::RecalculateBounds() {
|
| + if (points_.empty())
|
| + bounds_.SetRect(0, 0, 0, 0);
|
| + auto it = points_.begin();
|
| + bounds_.SetRect(it->location_.x(), it->location_.y(), 0, 0);
|
| + for (; it != points_.end(); it++) {
|
| + CalculateBounds(it->location_);
|
| + }
|
| +}
|
| +} // namespace ash
|
|
|