1 /*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef ANDROID_UI_REGION_H
18 #define ANDROID_UI_REGION_H
19
20 #include <stdint.h>
21 #include <sys/types.h>
22 #include <ostream>
23
24 #include <math/HashCombine.h>
25 #include <ui/Rect.h>
26 #include <utils/Flattenable.h>
27
28 #include <android-base/macros.h>
29
30 #include "FatVector.h"
31
32 #include <string>
33
34 namespace android {
35 // ---------------------------------------------------------------------------
36
37 class Region : public LightFlattenable<Region>
38 {
39 public:
40 static const Region INVALID_REGION;
41
42 Region();
43 Region(const Region& rhs);
44 explicit Region(const Rect& rhs);
45 ~Region();
46
47 static Region createTJunctionFreeRegion(const Region& r);
48
49 Region& operator = (const Region& rhs);
50
isEmpty()51 inline bool isEmpty() const { return getBounds().isEmpty(); }
isRect()52 inline bool isRect() const { return mStorage.size() == 1; }
53
getBounds()54 inline Rect getBounds() const { return mStorage[mStorage.size() - 1]; }
bounds()55 inline Rect bounds() const { return getBounds(); }
56
57 bool contains(const Point& point) const;
58 bool contains(int x, int y) const;
59
60 // the region becomes its bounds
61 Region& makeBoundsSelf();
62
63 void clear();
64 void set(const Rect& r);
65 void set(int32_t w, int32_t h);
66 void set(uint32_t w, uint32_t h);
67
68 Region& orSelf(const Rect& rhs);
69 Region& xorSelf(const Rect& rhs);
70 Region& andSelf(const Rect& rhs);
71 Region& subtractSelf(const Rect& rhs);
72
73 // boolean operators, applied on this
74 Region& orSelf(const Region& rhs);
75 Region& xorSelf(const Region& rhs);
76 Region& andSelf(const Region& rhs);
77 Region& subtractSelf(const Region& rhs);
78
79 // boolean operators
80 const Region merge(const Rect& rhs) const;
81 const Region mergeExclusive(const Rect& rhs) const;
82 const Region intersect(const Rect& rhs) const;
83 const Region subtract(const Rect& rhs) const;
84
85 // boolean operators
86 const Region merge(const Region& rhs) const;
87 const Region mergeExclusive(const Region& rhs) const;
88 const Region intersect(const Region& rhs) const;
89 const Region subtract(const Region& rhs) const;
90
91 // these translate rhs first
92 Region& translateSelf(int dx, int dy);
93 Region& scaleSelf(float sx, float sy);
94 Region& orSelf(const Region& rhs, int dx, int dy);
95 Region& xorSelf(const Region& rhs, int dx, int dy);
96 Region& andSelf(const Region& rhs, int dx, int dy);
97 Region& subtractSelf(const Region& rhs, int dx, int dy);
98
99
100 // these translate rhs first
101 const Region translate(int dx, int dy) const WARN_UNUSED;
102 const Region merge(const Region& rhs, int dx, int dy) const WARN_UNUSED;
103 const Region mergeExclusive(const Region& rhs, int dx, int dy) const WARN_UNUSED;
104 const Region intersect(const Region& rhs, int dx, int dy) const WARN_UNUSED;
105 const Region subtract(const Region& rhs, int dx, int dy) const WARN_UNUSED;
106
107 // convenience operators overloads
108 inline const Region operator | (const Region& rhs) const;
109 inline const Region operator ^ (const Region& rhs) const;
110 inline const Region operator & (const Region& rhs) const;
111 inline const Region operator - (const Region& rhs) const;
112 inline const Region operator + (const Point& pt) const;
113
114 inline Region& operator |= (const Region& rhs);
115 inline Region& operator ^= (const Region& rhs);
116 inline Region& operator &= (const Region& rhs);
117 inline Region& operator -= (const Region& rhs);
118 inline Region& operator += (const Point& pt);
119
120
121 // returns true if the regions share the same underlying storage
122 bool isTriviallyEqual(const Region& region) const;
123
124 // returns true if the regions consist of the same rectangle sequence
125 bool hasSameRects(const Region& region) const;
126
127 /* various ways to access the rectangle list */
128
129
130 // STL-like iterators
131 typedef Rect const* const_iterator;
132 const_iterator begin() const;
133 const_iterator end() const;
134
135 // returns an array of rect which has the same life-time has this
136 // Region object.
137 Rect const* getArray(size_t* count) const;
138
139 /* no user serviceable parts here... */
140
141 // add a rectangle to the internal list. This rectangle must
142 // be sorted in Y and X and must not make the region invalid.
143 void addRectUnchecked(int l, int t, int r, int b);
144
isFixedSize()145 inline bool isFixedSize() const { return false; }
146 size_t getFlattenedSize() const;
147 status_t flatten(void* buffer, size_t size) const;
148 status_t unflatten(void const* buffer, size_t size);
149
150 void dump(std::string& out, const char* what, uint32_t flags=0) const;
151 void dump(const char* what, uint32_t flags=0) const;
152
153 private:
154 class rasterizer;
155 friend class rasterizer;
156
157 Region& operationSelf(const Rect& r, uint32_t op);
158 Region& operationSelf(const Region& r, uint32_t op);
159 Region& operationSelf(const Region& r, int dx, int dy, uint32_t op);
160 const Region operation(const Rect& rhs, uint32_t op) const;
161 const Region operation(const Region& rhs, uint32_t op) const;
162 const Region operation(const Region& rhs, int dx, int dy, uint32_t op) const;
163
164 static void boolean_operation(uint32_t op, Region& dst,
165 const Region& lhs, const Region& rhs, int dx, int dy);
166 static void boolean_operation(uint32_t op, Region& dst,
167 const Region& lhs, const Rect& rhs, int dx, int dy);
168
169 static void boolean_operation(uint32_t op, Region& dst,
170 const Region& lhs, const Region& rhs);
171 static void boolean_operation(uint32_t op, Region& dst,
172 const Region& lhs, const Rect& rhs);
173
174 static void translate(Region& reg, int dx, int dy);
175 static void translate(Region& dst, const Region& reg, int dx, int dy);
176
177 static bool validate(const Region& reg,
178 const char* name, bool silent = false);
179
180 // mStorage is a (manually) sorted array of Rects describing the region
181 // with an extra Rect as the last element which is set to the
182 // bounds of the region. However, if the region is
183 // a simple Rect then mStorage contains only that rect.
184 FatVector<Rect> mStorage;
185 };
186
187
188 const Region Region::operator | (const Region& rhs) const {
189 return merge(rhs);
190 }
191 const Region Region::operator ^ (const Region& rhs) const {
192 return mergeExclusive(rhs);
193 }
194 const Region Region::operator & (const Region& rhs) const {
195 return intersect(rhs);
196 }
197 const Region Region::operator - (const Region& rhs) const {
198 return subtract(rhs);
199 }
200 const Region Region::operator + (const Point& pt) const {
201 return translate(pt.x, pt.y);
202 }
203
204
205 Region& Region::operator |= (const Region& rhs) {
206 return orSelf(rhs);
207 }
208 Region& Region::operator ^= (const Region& rhs) {
209 return xorSelf(rhs);
210 }
211 Region& Region::operator &= (const Region& rhs) {
212 return andSelf(rhs);
213 }
214 Region& Region::operator -= (const Region& rhs) {
215 return subtractSelf(rhs);
216 }
217 Region& Region::operator += (const Point& pt) {
218 return translateSelf(pt.x, pt.y);
219 }
220
221 // Defining PrintTo helps with Google Tests.
PrintTo(const Region & region,::std::ostream * os)222 static inline void PrintTo(const Region& region, ::std::ostream* os) {
223 Region::const_iterator head = region.begin();
224 Region::const_iterator const tail = region.end();
225 bool first = true;
226 while (head != tail) {
227 *os << (first ? "Region(" : ", ");
228 PrintTo(*head, os);
229 head++;
230 first = false;
231 }
232 *os << ")";
233 }
234
235 // ---------------------------------------------------------------------------
236 }; // namespace android
237
238 namespace std {
239 template <>
240 struct hash<android::Region> {
241 size_t operator()(const android::Region& region) const {
242 size_t hash = 0;
243 for (const android::Rect& rect : region) {
244 android::hashCombineSingle(hash, rect);
245 }
246 return hash;
247 }
248 };
249 } // namespace std
250
251 #endif // ANDROID_UI_REGION_H
252