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