• 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_) {}
~Region()154     ~Region() {}
155 
GetRegionRects()156     std::vector<Rect> GetRegionRects() const
157     {
158         return rects_;
159     }
160 
GetRegionRects()161     std::vector<Rect>& GetRegionRects()
162     {
163         return rects_;
164     }
165 
GetSize()166     int GetSize() const
167     {
168         return rects_.size();
169     }
170 
GetBound()171     Rect GetBound() const
172     {
173         return bound_;
174     }
175 
GetBoundRef()176     Rect& GetBoundRef()
177     {
178         return bound_;
179     }
180 
IsEmpty()181     bool IsEmpty() const
182     {
183         return rects_.size() == 0;
184     }
185 
GetRegionInfo()186     std::string GetRegionInfo() const
187     {
188         std::string info = "{ Region Size " + std::to_string(rects_.size()) + ": ";
189         for (auto& r : rects_) {
190             info.append(r.GetRectInfo());
191         }
192         info.append(" }");
193         return info;
194     }
195 
CBegin()196     inline std::vector<Rect>::const_iterator CBegin() const
197     {
198         return rects_.cbegin();
199     }
200 
CEnd()201     inline std::vector<Rect>::const_iterator CEnd() const
202     {
203         return rects_.cend();
204     }
205 
Begin()206     inline std::vector<Rect>::iterator Begin()
207     {
208         return rects_.begin();
209     }
210 
End()211     inline std::vector<Rect>::const_iterator End()
212     {
213         return rects_.end();
214     }
215 
Size()216     inline size_t Size() const
217     {
218         return rects_.size();
219     }
220 
221     // bound of all region rects
222     void MakeBound();
223     /* core Region logic operation function, the return region's rects is guaranteed no-intersection
224         (rect in rects_ do not intersect with each other)
225     */
226     void RegionOp(Region& r1, Region& r2, Region& res, Region::OP op);
227     void RegionOpLocal(Region& r1, Region& r2, Region& res, Region::OP op);
228 
229     Region& OperationSelf(Region& r, Region::OP op);
230     // replace region with and result
231     Region& AndSelf(Region& r);
232     // replace region with or result
233     Region& OrSelf(Region& r);
234     // replace region with xor result
235     Region& XOrSelf(Region& r);
236     // replace region with sub result
237     Region& SubSelf(Region& r);
238 
239     // return intersection region
240     Region And(Region& r);
241     // return merge region
242     Region Or(Region& r);
243     // return merge region subtract intersection region
244     Region Xor(Region& r);
245     // return region belongs to Region(lhs) but not Region(rhs)
246     Region Sub(Region& r);
247 
248 private:
249     class Rects {
250     public:
251         std::vector<Rect> preRects;
252         std::vector<Rect> curRects;
253         int preY = 0;
254         int curY = 0;
255     };
256     // get ranges from segmentTree node according to logical operation type
257     void getRange(std::vector<Range>& ranges, Node& node, OP op);
258     // update tmp rects and region according to current ranges
259     void UpdateRects(Rects& r, std::vector<Range>& ranges, std::vector<int>& indexAt, Region& res);
260 
261 private:
262     std::vector<Rect> rects_;
263     Rect bound_;
264     static bool _s_so_loaded_;
265 };
266 std::ostream& operator<<(std::ostream& os, const Region& r);
267 } // namespace OHOS::Rosen::Occlusion
268 #endif // OHOS_ROSEN_WM_OCCLUSION_REGION_H