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