Index: cc/tile_priority.cc |
diff --git a/cc/tile_priority.cc b/cc/tile_priority.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..967698fdb78ce06d50f68697d55cd61b9dd9f824 |
--- /dev/null |
+++ b/cc/tile_priority.cc |
@@ -0,0 +1,104 @@ |
+// Copyright 2012 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 "cc/tile_priority.h" |
+ |
+namespace { |
+ |
+const double kMaxTimeToVisibleInSeconds = 1000.0; |
+ |
+// TODO(qinmin): modify ui/range/Range.h to support template so that we |
+// don't need to define this. |
+struct Range { |
+ Range(double start, double end) : start_(start), end_(end) {} |
+ Range Intersects(const Range& other); |
+ bool IsEmpty(); |
+ double start_; |
+ double end_; |
+}; |
+ |
+Range Range::Intersects(const Range& other) { |
+ start_ = std::max(start_, other.start_); |
+ end_ = std::min(end_, other.end_); |
+ return Range(start_, end_); |
+} |
+ |
+bool Range::IsEmpty() { |
+ return start_ >= end_; |
+} |
+ |
+// Calculate a time range that |value| will be larger than |threshold| |
+// given the velocity of its change. |
+Range TimeRangeValueLargerThanThreshold( |
+ int value, int threshold, double velocity) { |
+ double minimum_time = 0; |
+ double maximum_time = kMaxTimeToVisibleInSeconds; |
+ |
+ if (velocity > 0) { |
+ if (value < threshold) |
+ minimum_time = std::min(kMaxTimeToVisibleInSeconds, |
+ (threshold - value) / velocity); |
+ } else if (velocity <= 0) { |
+ if (value < threshold) |
+ minimum_time = kMaxTimeToVisibleInSeconds; |
+ else if (velocity != 0) |
+ maximum_time = std::min(maximum_time, (threshold - value) / velocity); |
+ } |
+ |
+ return Range(minimum_time, maximum_time); |
+} |
+ |
+} // namespace |
+ |
+namespace cc { |
+ |
+int TilePriority::manhattanDistance(const gfx::RectF& a, const gfx::RectF& b) { |
enne (OOO)
2012/12/03 19:57:28
Can you write a quick unit test for this math?
qinmin
2012/12/04 00:37:30
Done.
|
+ gfx::RectF c = gfx::UnionRects(a, b); |
+ // Rects touching the edge of the screen should not be considered visible. |
+ // So we add 1 pixel here to avoid that situation. |
+ int x = static_cast<int>( |
+ std::max(0.0f, c.width() - a.width() - b.width() + 1)); |
+ int y = static_cast<int>( |
+ std::max(0.0f, c.height() - a.height() - b.height() + 1)); |
+ return (x + y); |
+} |
+ |
+double TilePriority::TimeForBoundsToIntersect(gfx::RectF previous_bounds, |
+ gfx::RectF current_bounds, |
+ double time_delta, |
+ gfx::RectF target_bounds) { |
+ if (current_bounds.Intersects(target_bounds)) |
+ return 0; |
+ |
+ if (previous_bounds.Intersects(target_bounds) || time_delta == 0) |
+ return kMaxTimeToVisibleInSeconds; |
+ |
+ // As we are trying to solve the case of both scaling and scrolling, using |
+ // a single coordinate with velocity is not enough. The logic here is to |
+ // calculate the velocity for each edge. Then we calculate the time range that |
+ // each edge will stay on the same side of the target bounds. If there is an |
+ // overlap between these time ranges, the bounds must have intersect with |
+ // each other during that period of time. |
+ double velocity = |
+ (current_bounds.right() - previous_bounds.right()) / time_delta; |
+ Range range = TimeRangeValueLargerThanThreshold( |
+ current_bounds.right(), target_bounds.x(), velocity); |
+ |
+ velocity = (current_bounds.x() - previous_bounds.x()) / time_delta; |
+ range = range.Intersects(TimeRangeValueLargerThanThreshold( |
+ -current_bounds.x(), -target_bounds.right(), -velocity)); |
+ |
+ |
+ velocity = (current_bounds.y() - previous_bounds.y()) / time_delta; |
+ range = range.Intersects(TimeRangeValueLargerThanThreshold( |
+ -current_bounds.y(), -target_bounds.bottom(), -velocity)); |
+ |
+ velocity = (current_bounds.bottom() - previous_bounds.bottom()) / time_delta; |
+ range = range.Intersects(TimeRangeValueLargerThanThreshold( |
+ current_bounds.bottom(), target_bounds.y(), velocity)); |
+ |
+ return range.IsEmpty() ? kMaxTimeToVisibleInSeconds : range.start_; |
+} |
+ |
+} // namespace cc |