• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef OHOS_ROSEN_WM_OCCLUSION_REGION_H
17 #define OHOS_ROSEN_WM_OCCLUSION_REGION_H
18 
19 #include <refbase.h>
20 #include <algorithm>
21 #include <iostream>
22 #include <vector>
23 #include <string>
24 
25 namespace OHOS::Rosen::WmOcclusion {
26 class Rect {
27 public:
28     int left_ = 0;
29     int top_ = 0;
30     int right_ = 0;
31     int bottom_ = 0;
32     static Rect _s_empty_rect_;
33     static Rect _s_invalid_rect_;
34 
Rect()35     Rect() : left_(0), top_(0), right_(0), bottom_(0) {}
Rect(int l,int t,int r,int b)36     Rect(int l, int t, int r, int b) : left_(l), top_(t), right_(r), bottom_(b) {}
37 
GetRectInfo()38     std::string GetRectInfo() const
39     {
40         return std::string("[" +
41             std::to_string(left_) + ", " +
42             std::to_string(top_) + ", " +
43             std::to_string(right_ - left_) + ", " +
44             std::to_string(bottom_ - top_) + "]");
45     }
46 
IsEmpty()47     bool IsEmpty() const
48     {
49         return left_ >= right_ || top_ >= bottom_;
50     }
51 };
52 
53 std::ostream& operator<<(std::ostream& os, const Rect& r);
54 
55 /*
56     Event: Used for record a rect edge in/out event
57     y_: rect edge Y value
58     type: OPEN/CLOSE: lhs rect in/out; VOID_OPEN/VOID_CLOSE: rhs rect in/out
59  */
60 class Event {
61 public:
62     // Use different value to differentiate lhs and rhs ranges.
63     enum Type { OPEN = 1, CLOSE = -1, VOID_OPEN = 2, VOID_CLOSE = -2 };
64     int y_ = 0;
65     Type type_ = Type::OPEN;
66     int left_ = 0;
67     int right_ = 0;
68 
Event(int y,Type type,int l,int r)69     Event(int y, Type type, int l, int r) : y_(y), type_(type), left_(l), right_(r) {}
70 };
71 
72 bool EventSortByY(const Event& e1, const Event& e2);
73 
74 class Range {
75 public:
76     int start_ = 0;
77     int end_ = 0;
Range(int start,int end)78     Range(int start, int end) : start_(start), end_(end) {}
79     bool operator==(const Range& r)
80     {
81         return start_ == r.start_ && end_ == r.end_;
82     }
83 };
84 
85 class Node {
86 public:
87     int start_ = 0;
88     int end_ = 0;
89     int mid_ = 0;
90     Node* left_ = nullptr;
91     Node* right_ = nullptr;
92     int positive_count_ = 0; // used for counting current lhs ranges
93     int negative_count_ = 0; // used for counting current rhs ranges
94 
Node(int s,int e)95     Node(int s, int e) : start_(s), end_(e), mid_((s + e) >> 1) {}
~Node()96     ~Node()
97     {
98         if (right_ != nullptr) {
99             delete right_;
100             right_ = nullptr;
101         }
102         if (left_ != nullptr) {
103             delete left_;
104             left_ = nullptr;
105         }
106     }
107 
IsLeaf()108     inline bool IsLeaf()
109     {
110         return left_ == nullptr && right_ == nullptr;
111     }
112 
113     // push current node [start, end] into range result, merge last range if possible
PushRange(std::vector<Range> & res)114     inline void PushRange(std::vector<Range>& res)
115     {
116         if (res.size() > 0 && start_ == res[res.size() - 1].end_) {
117             // merge range with previous range if their end and start share same point
118             res[res.size() - 1].end_ = end_;
119         } else {
120             res.emplace_back(Range { start_, end_ });
121         }
122     }
123 
124     // update segment tree
125     void Update(int updateStart, int updateEnd, Event::Type type);
126     // get ranges where positive_count_ or negtive_count_ is positive
127     void GetOrRange(std::vector<Range>& res, bool isParentNodePos, bool isParentNodeNeg);
128     // get ranges where positive_count_ and negtive_count_ are both positive
129     void GetAndRange(std::vector<Range>& res, bool isParentNodePos, bool isParentNodeNeg);
130     // get ranges where positive_count_ is positive and negtive_count_ not
131     void GetSubRange(std::vector<Range>& res, bool isParentNodePos, bool isParentNodeNeg);
132     // get ranges where either positive_count_ and negtive_count_ are both positive
133     void GetXOrRange(std::vector<Range>& res, bool isParentNodePos, bool isParentNodeNeg);
134 };
135 
136 class Region {
137 public:
138     enum OP {
139         // bit index 0: lhs
140         // bit index 1: lhs & rhs
141         // bit index 2: rhs
142         AND = 2, // 010
143         OR  = 7, // 111
144         XOR = 5, // 101
145         SUB = 1  // 001
146     };
147 
148     Region() = default;
Region(Rect & rect)149     explicit Region(Rect& rect)
150     {
151         rects_.push_back(rect);
152         bound_ = Rect { rect };
153     }
154 
Region(const Region & region)155     Region(const Region& region) : rects_(region.rects_), bound_(region.bound_) {}
156     Region& operator=(const Region& region)
157     {
158         rects_ = region.rects_;
159         bound_ = region.bound_;
160         return *this;
161     }
~Region()162     ~Region() {}
163 
GetRegionRects()164     std::vector<Rect>& GetRegionRects()
165     {
166         return rects_;
167     }
168 
GetRegionRects()169     std::vector<Rect> GetRegionRects() const
170     {
171         return rects_;
172     }
173 
IsEmpty()174     bool IsEmpty() const
175     {
176         return rects_.size() == 0;
177     }
178 
GetSize()179     int GetSize() const
180     {
181         return rects_.size();
182     }
183 
GetBoundRef()184     Rect& GetBoundRef()
185     {
186         return bound_;
187     }
188 
GetBound()189     Rect GetBound() const
190     {
191         return bound_;
192     }
193 
GetRegionInfo()194     std::string GetRegionInfo() const
195     {
196         std::string info = "{ Region Size " + std::to_string(rects_.size()) + ": ";
197         for (auto& rect : rects_) {
198             info.append(rect.GetRectInfo());
199         }
200         info.append(" }");
201         return info;
202     }
203 
Size()204     inline size_t Size() const
205     {
206         return rects_.size();
207     }
208 
CBegin()209     inline std::vector<Rect>::const_iterator CBegin() const
210     {
211         return rects_.cbegin();
212     }
213 
Begin()214     inline std::vector<Rect>::iterator Begin()
215     {
216         return rects_.begin();
217     }
218 
CEnd()219     inline std::vector<Rect>::const_iterator CEnd() const
220     {
221         return rects_.cend();
222     }
223 
End()224     inline std::vector<Rect>::const_iterator End()
225     {
226         return rects_.end();
227     }
228 
229     /* core Region logic operation function, the return region's rects is guaranteed no-intersection
230         (rect in rects_ do not intersect with each other)
231     */
232     void RegionOp(Region& r1, Region& r2, Region& res, Region::OP op);
233     void RegionOpLocal(Region& r1, Region& r2, Region& res, Region::OP op);
234     // bound of all region rects
235     void MakeBound();
236 
237     // return merge region
238     Region Or(Region& r);
239     // return intersection region
240     Region And(Region& r);
241     // return region belongs to Region(lhs) but not Region(rhs)
242     Region Sub(Region& r);
243     // return merge region subtract intersection region
244     Region Xor(Region& r);
245 
246     Region& OperationSelf(Region& r, Region::OP op);
247     // replace region with or result
248     Region& OrSelf(Region& r);
249     // replace region with and result
250     Region& AndSelf(Region& r);
251     // replace region with sub result
252     Region& SubSelf(Region& r);
253     // replace region with xor result
254     Region& XOrSelf(Region& r);
255 
256 private:
257     class Rects {
258     public:
259         int preY = 0;
260         int curY = 0;
261         std::vector<Rect> preRects;
262         std::vector<Rect> curRects;
263     };
264     // update tmp rects and region according to current ranges
265     void UpdateRects(Rects& r, std::vector<Range>& ranges, std::vector<int>& indexAt, Region& res);
266     // get ranges from segmentTree node according to logical operation type
267     void getRange(std::vector<Range>& ranges, Node& node, OP op);
268 
269 private:
270     std::vector<Rect> rects_;
271     Rect bound_;
272     static bool _s_so_loaded_;
273 };
274 std::ostream& operator<<(std::ostream& os, const Region& r);
275 } // namespace OHOS::Rosen::Occlusion
276 #endif // OHOS_ROSEN_WM_OCCLUSION_REGION_H