OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "cc/base/simple_enclosed_region.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "cc/base/region.h" | |
9 | |
10 namespace cc { | |
11 | |
12 static bool RectIsLargerArea(const gfx::Rect& a, const gfx::Rect b) { | |
13 int64 a_area = static_cast<int64>(a.width()) * a.height(); | |
14 int64 b_area = static_cast<int64>(b.width()) * b.height(); | |
15 return a_area > b_area; | |
16 } | |
17 | |
18 SimpleEnclosedRegion::SimpleEnclosedRegion(const Region& region) { | |
19 for (Region::Iterator it(region); it.has_rect(); it.next()) | |
20 Union(it.rect()); | |
21 } | |
22 | |
23 SimpleEnclosedRegion::~SimpleEnclosedRegion() { | |
24 } | |
25 | |
26 void SimpleEnclosedRegion::Subtract(const gfx::Rect& sub_rect) { | |
27 // We want to keep as much of the current rect as we can, so find the one | |
28 // largest rectangle inside |rect_| that does not intersect with |sub_rect|. | |
29 if (!rect_.Intersects(sub_rect)) | |
30 return; | |
31 if (sub_rect.Contains(rect_)) { | |
32 rect_ = gfx::Rect(); | |
33 return; | |
34 } | |
35 | |
36 int left = rect_.x(); | |
37 int right = rect_.right(); | |
38 int top = rect_.y(); | |
39 int bottom = rect_.bottom(); | |
40 | |
41 int delta_left = sub_rect.x() - left; | |
42 int delta_right = right - sub_rect.right(); | |
43 int delta_top = sub_rect.y() - top; | |
44 int delta_bottom = bottom - sub_rect.bottom(); | |
45 | |
46 // The horizontal rect is the larger of the two rectangles above or below | |
47 // |sub_rect| and inside rect_. | |
48 int horizontal_top = top; | |
49 int horizontal_bottom = bottom; | |
50 if (delta_top > delta_bottom) | |
51 horizontal_bottom = sub_rect.y(); | |
52 else | |
53 horizontal_top = sub_rect.bottom(); | |
54 // The vertical rect is the larger of the two rectangles to the left or the | |
55 // right of |sub_rect| and inside rect_. | |
56 int vertical_left = left; | |
57 int vertical_right = right; | |
58 if (delta_left > delta_right) | |
59 vertical_right = sub_rect.x(); | |
60 else | |
61 vertical_left = sub_rect.right(); | |
62 | |
63 rect_.SetRect( | |
64 left, horizontal_top, right - left, horizontal_bottom - horizontal_top); | |
65 | |
66 gfx::Rect vertical_rect( | |
67 vertical_left, top, vertical_right - vertical_left, bottom - top); | |
68 if (RectIsLargerArea(vertical_rect, rect_)) | |
69 rect_ = vertical_rect; | |
70 } | |
71 | |
72 void SimpleEnclosedRegion::Union(const gfx::Rect& new_rect) { | |
73 // We want to keep track of a region but bound its complexity at a constant | |
74 // size. We keep track of the largest rectangle seen by area. If we can add | |
75 // the |new_rect| to this rectangle then we do that, as that is the cheapest | |
76 // way to increase the area returned without increasing the complexity. | |
77 if (new_rect.IsEmpty()) | |
78 return; | |
79 if (rect_.Contains(new_rect)) | |
80 return; | |
81 if (new_rect.Contains(rect_)) { | |
82 rect_ = new_rect; | |
83 return; | |
84 } | |
85 | |
86 int left = rect_.x(); | |
87 int top = rect_.y(); | |
88 int right = rect_.right(); | |
89 int bottom = rect_.bottom(); | |
90 | |
91 int new_left = new_rect.x(); | |
92 int new_top = new_rect.y(); | |
93 int new_right = new_rect.right(); | |
94 int new_bottom = new_rect.bottom(); | |
95 | |
96 if (new_top <= top && new_bottom >= bottom) { | |
enne (OOO)
2014/08/21 20:48:05
So many conditionals. O_O
Could you leave a brie
danakj
2014/08/21 21:15:31
I think that would regress the case of two rectang
enne (OOO)
2014/08/21 21:19:40
Aha, ok. That case makes sense.
| |
97 if (new_left < left && new_right >= left) | |
98 left = new_left; | |
99 if (new_right > right && new_left <= right) | |
100 right = new_right; | |
101 } else if (new_left <= left && new_right >= right) { | |
102 if (new_top < top && new_bottom >= top) | |
103 top = new_top; | |
104 if (new_bottom > bottom && new_top <= bottom) | |
105 bottom = new_bottom; | |
106 } else if (top <= new_top && bottom >= new_bottom) { | |
107 if (left < new_left && right >= new_left) | |
108 new_left = left; | |
109 if (right > new_right && left <= new_right) | |
110 new_right = right; | |
111 } else if (left <= new_left && right >= new_right) { | |
112 if (top < new_top && bottom >= new_top) | |
113 new_top = top; | |
114 if (bottom > new_bottom && top <= new_bottom) | |
115 new_bottom = bottom; | |
116 } | |
117 | |
118 rect_.SetRect(left, top, right - left, bottom - top); | |
119 | |
120 gfx::Rect adjusted_new_rect( | |
121 new_left, new_top, new_right - new_left, new_bottom - new_top); | |
122 if (RectIsLargerArea(adjusted_new_rect, rect_)) | |
123 rect_ = adjusted_new_rect; | |
124 } | |
125 | |
126 gfx::Rect SimpleEnclosedRegion::GetRect(size_t i) const { | |
127 DCHECK_LT(i, GetRegionComplexity()); | |
128 return rect_; | |
129 } | |
130 | |
131 } // namespace cc | |
OLD | NEW |