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
|
// 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 {
// 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 = cc::TilePriority::kMaxTimeToVisibleInSeconds;
if (velocity > 0) {
if (value < threshold)
minimum_time = std::min(cc::TilePriority::kMaxTimeToVisibleInSeconds,
(threshold - value) / velocity);
} else if (velocity <= 0) {
if (value < threshold)
minimum_time = cc::TilePriority::kMaxTimeToVisibleInSeconds;
else if (velocity != 0)
maximum_time = std::min(maximum_time, (threshold - value) / velocity);
}
return Range(minimum_time, maximum_time);
}
} // namespace
namespace cc {
const double TilePriority::kMaxTimeToVisibleInSeconds = 1000;
int TilePriority::manhattanDistance(const gfx::RectF& a, const gfx::RectF& b) {
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
|