OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/tile_priority.h" | 5 #include "cc/tile_priority.h" |
6 | 6 |
7 namespace { | 7 namespace { |
8 | 8 |
9 // TODO(qinmin): modify ui/range/Range.h to support template so that we | 9 // TODO(qinmin): modify ui/range/Range.h to support template so that we |
10 // don't need to define this. | 10 // don't need to define this. |
11 struct Range { | 11 struct Range { |
12 Range(double start, double end) : start_(start), end_(end) {} | 12 Range(float start, float end) : start_(start), end_(end) {} |
13 Range Intersects(const Range& other); | |
14 bool IsEmpty(); | 13 bool IsEmpty(); |
15 double start_; | 14 float start_; |
16 double end_; | 15 float end_; |
17 }; | 16 }; |
18 | 17 |
19 Range Range::Intersects(const Range& other) { | 18 inline bool Intersects(const Range& a, const Range& b) { |
20 start_ = std::max(start_, other.start_); | 19 return a.start_ < b.end_ && b.start_ < a.end_; |
21 end_ = std::min(end_, other.end_); | 20 } |
22 return Range(start_, end_); | 21 |
| 22 inline Range Intersect(const Range& a, const Range& b) { |
| 23 return Range(std::max(a.start_, b.start_), std::min(a.end_, b.end_)); |
23 } | 24 } |
24 | 25 |
25 bool Range::IsEmpty() { | 26 bool Range::IsEmpty() { |
26 return start_ >= end_; | 27 return start_ >= end_; |
27 } | 28 } |
28 | 29 |
29 // Calculate a time range that |value| will be larger than |threshold| | 30 inline Range Intersect(const Range& previous, const Range& current, float time_d
elta, const Range& target) |
30 // given the velocity of its change. | 31 { |
31 Range TimeRangeValueLargerThanThreshold( | 32 // Calculate the scale factors. |
32 int value, int threshold, double velocity) { | 33 float time_per_dist_start = time_delta/(current.start_-previous.start_); |
33 double minimum_time = 0; | 34 float time_per_dist_end = time_delta/(current.end_ -previous.end_ ); |
34 double maximum_time = cc::TilePriority::kMaxTimeToVisibleInSeconds; | |
35 | 35 |
36 if (velocity > 0) { | 36 // Calcuate the 4 times of intersection. |
37 if (value < threshold) | 37 float start_hit_start = (target.start_-current.start_)*time_per_dist_start; |
38 minimum_time = std::min(cc::TilePriority::kMaxTimeToVisibleInSeconds, | 38 float start_hit_end = (target.end_ -current.start_)*time_per_dist_start; |
39 (threshold - value) / velocity); | 39 float end_hit_start = (target.start_-current.end_)*time_per_dist_end; |
40 } else if (velocity <= 0) { | 40 float end_hit_end = (target.end_ -current.end_)*time_per_dist_end; |
41 if (value < threshold) | |
42 minimum_time = cc::TilePriority::kMaxTimeToVisibleInSeconds; | |
43 else if (velocity != 0) | |
44 maximum_time = std::min(maximum_time, (threshold - value) / velocity); | |
45 } | |
46 | 41 |
47 return Range(minimum_time, maximum_time); | 42 // Return the union of the for intersection times. |
| 43 return Range( |
| 44 std::min( |
| 45 std::min(start_hit_start, start_hit_end), |
| 46 std::min(end_hit_start, end_hit_end)), |
| 47 std::max( |
| 48 std::max(start_hit_start, start_hit_end), |
| 49 std::max(end_hit_start, end_hit_end))); |
48 } | 50 } |
49 | 51 |
50 } // namespace | 52 } // namespace |
51 | 53 |
52 namespace cc { | 54 namespace cc { |
53 | 55 |
54 const double TilePriority::kMaxTimeToVisibleInSeconds = 1000; | 56 const float TilePriority::kMaxTimeToVisibleInSeconds = std::numeric_limits<float
>::infinity(); |
55 | 57 |
56 int TilePriority::manhattanDistance(const gfx::RectF& a, const gfx::RectF& b) { | 58 float TilePriority::TimeForBoundsToIntersect(const gfx::RectF& previous_bounds, |
57 gfx::RectF c = gfx::UnionRects(a, b); | 59 const gfx::RectF& current_bounds, |
58 // Rects touching the edge of the screen should not be considered visible. | 60 float time_delta, |
59 // So we add 1 pixel here to avoid that situation. | 61 const gfx::RectF& target_bounds) { |
60 int x = static_cast<int>( | 62 // Convert the rects to ranges. |
61 std::max(0.0f, c.width() - a.width() - b.width() + 1)); | 63 Range previous_x_range(previous_bounds.x(), previous_bounds.right()); |
62 int y = static_cast<int>( | 64 Range previous_y_range(previous_bounds.y(), previous_bounds.bottom()); |
63 std::max(0.0f, c.height() - a.height() - b.height() + 1)); | 65 Range current_x_range(current_bounds.x(), current_bounds.right()); |
64 return (x + y); | 66 Range current_y_range(current_bounds.y(), current_bounds.bottom()); |
65 } | 67 Range target_x_range(current_bounds.x(), target_bounds.right()); |
| 68 Range target_y_range(current_bounds.y(), target_bounds.bottom()); |
66 | 69 |
67 double TilePriority::TimeForBoundsToIntersect(gfx::RectF previous_bounds, | 70 // Check to see if the tile is visible. |
68 gfx::RectF current_bounds, | 71 if (Intersects(current_x_range, target_x_range) && |
69 double time_delta, | 72 Intersects(current_y_range, target_y_range)) |
70 gfx::RectF target_bounds) { | 73 return 0.0f; |
71 if (current_bounds.Intersects(target_bounds)) | |
72 return 0; | |
73 | 74 |
74 if (previous_bounds.Intersects(target_bounds) || time_delta == 0) | 75 // Check to see if the tile didn't move. |
| 76 if (time_delta == 0.0f) |
75 return kMaxTimeToVisibleInSeconds; | 77 return kMaxTimeToVisibleInSeconds; |
76 | 78 |
77 // As we are trying to solve the case of both scaling and scrolling, using | 79 // Calculate the intersection time intervals in X and Y. |
78 // a single coordinate with velocity is not enough. The logic here is to | 80 Range x_range = Intersect( |
79 // calculate the velocity for each edge. Then we calculate the time range that | 81 previous_x_range, current_x_range, time_delta, target_x_range); |
80 // each edge will stay on the same side of the target bounds. If there is an | 82 Range y_range = Intersect( |
81 // overlap between these time ranges, the bounds must have intersect with | 83 previous_y_range, current_y_range, time_delta, target_y_range); |
82 // each other during that period of time. | |
83 double velocity = | |
84 (current_bounds.right() - previous_bounds.right()) / time_delta; | |
85 Range range = TimeRangeValueLargerThanThreshold( | |
86 current_bounds.right(), target_bounds.x(), velocity); | |
87 | 84 |
88 velocity = (current_bounds.x() - previous_bounds.x()) / time_delta; | 85 // Intersect the X and Y intervals and clamp to positive range. |
89 range = range.Intersects(TimeRangeValueLargerThanThreshold( | 86 Range range = Intersect(x_range, y_range); |
90 -current_bounds.x(), -target_bounds.right(), -velocity)); | 87 range.start_ = std::max(range.start_, 0.0f); |
91 | 88 |
92 | 89 if (range.IsEmpty()) |
93 velocity = (current_bounds.y() - previous_bounds.y()) / time_delta; | 90 return kMaxTimeToVisibleInSeconds; |
94 range = range.Intersects(TimeRangeValueLargerThanThreshold( | 91 return range.start_; |
95 -current_bounds.y(), -target_bounds.bottom(), -velocity)); | |
96 | |
97 velocity = (current_bounds.bottom() - previous_bounds.bottom()) / time_delta; | |
98 range = range.Intersects(TimeRangeValueLargerThanThreshold( | |
99 current_bounds.bottom(), target_bounds.y(), velocity)); | |
100 | |
101 return range.IsEmpty() ? kMaxTimeToVisibleInSeconds : range.start_; | |
102 } | 92 } |
103 | 93 |
104 } // namespace cc | 94 } // namespace cc |
OLD | NEW |