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 #include "wm_occlusion_region.h"
16 
17 #include <map>
18 #include <set>
19 
20 namespace OHOS::Rosen::WmOcclusion {
21 static Rect _s_empty_rect_ { 0, 0, 0, 0 };
22 static Rect _s_invalid_rect_ { 0, 0, -1, -1 };
23 bool Region::_s_so_loaded_ = false;
24 
operator <<(std::ostream & os,const Rect & r)25 std::ostream& operator<<(std::ostream& os, const Rect& r)
26 {
27     os << "{" << r.left_ << "," << r.top_ << "," << r.right_ << "," << r.bottom_ << "}";
28     return os;
29 }
30 
Update(int updateStart,int updateEnd,Event::Type type)31 void Node::Update(int updateStart, int updateEnd, Event::Type type)
32 {
33     if (updateStart >= updateEnd) {
34         return;
35     }
36     if (updateStart == start_ && updateEnd == end_) {
37         if (type == Event::Type::CLOSE || type == Event::Type::OPEN) {
38             positive_count_ += type;
39         } else {
40             negative_count_ += type;
41         }
42     } else {
43         if (right_ == nullptr) {
44             right_ = new Node { mid_, end_ };
45         }
46         if (left_ == nullptr) {
47             left_ = new Node { start_, mid_ };
48         }
49 
50         if (left_) {
51             left_->Update(updateStart, mid_ < updateEnd ? mid_ : updateEnd, type);
52         }
53         if (right_) {
54             right_->Update(mid_ > updateStart ? mid_ : updateStart, updateEnd, type);
55         }
56     }
57 }
58 
EventSortByY(const Event & e1,const Event & e2)59 bool EventSortByY(const Event& e1, const Event& e2)
60 {
61     if (e1.y_ == e2.y_) {
62         return e1.type_ < e2.type_;
63     }
64     return e1.y_ < e2.y_;
65 }
66 
GetOrRange(std::vector<Range> & res,bool isParentNodePos=false,bool isParentNodeNeg=false)67 void Node::GetOrRange(std::vector<Range>& res, bool isParentNodePos = false, bool isParentNodeNeg = false)
68 {
69     bool isNeg = isParentNodeNeg || (negative_count_ > 0);
70     bool isPos = isParentNodePos || (positive_count_ > 0);
71 
72     if (isNeg || isPos) {
73         PushRange(res);
74     } else {
75         if (left_ != nullptr) {
76             left_->GetOrRange(res, isPos, isNeg);
77         }
78         if (right_ != nullptr) {
79             right_->GetOrRange(res, isPos, isNeg);
80         }
81     }
82 }
83 
GetAndRange(std::vector<Range> & res,bool isParentNodePos=false,bool isParentNodeNeg=false)84 void Node::GetAndRange(std::vector<Range>& res, bool isParentNodePos = false, bool isParentNodeNeg = false)
85 {
86     bool isNeg = isParentNodeNeg || (negative_count_ > 0);
87     bool isPos = isParentNodePos || (positive_count_ > 0);
88 
89     if (isNeg && isPos) {
90         PushRange(res);
91     } else {
92         if (left_ != nullptr) {
93             left_->GetAndRange(res, isPos, isNeg);
94         }
95         if (right_ != nullptr) {
96             right_->GetAndRange(res, isPos, isNeg);
97         }
98     }
99 }
100 
GetSubRange(std::vector<Range> & res,bool isParentNodePos=false,bool isParentNodeNeg=false)101 void Node::GetSubRange(std::vector<Range>& res, bool isParentNodePos = false, bool isParentNodeNeg = false)
102 {
103     bool isNeg = isParentNodeNeg || (negative_count_ > 0);
104     bool isPos = isParentNodePos || (positive_count_ > 0);
105 
106     if (isPos && !isNeg && IsLeaf()) {
107         PushRange(res);
108     } else if (isNeg) {
109         return;
110     } else {
111         if (left_ != nullptr) {
112             left_->GetSubRange(res, isPos, isNeg);
113         }
114         if (right_ != nullptr) {
115             right_->GetSubRange(res, isPos, isNeg);
116         }
117     }
118 }
119 
GetXOrRange(std::vector<Range> & res,bool isParentNodePos=false,bool isParentNodeNeg=false)120 void Node::GetXOrRange(std::vector<Range>& res, bool isParentNodePos = false, bool isParentNodeNeg = false)
121 {
122     bool isNeg = isParentNodeNeg || (negative_count_ > 0);
123     bool isPos = isParentNodePos || (positive_count_ > 0);
124 
125     if (((isPos && !isNeg) || (!isPos && isNeg)) && IsLeaf()) {
126         PushRange(res);
127     } else if (isNeg && isPos) {
128         return;
129     } else {
130         if (left_ != nullptr) {
131             left_->GetXOrRange(res, isPos, isNeg);
132         }
133         if (right_ != nullptr) {
134             right_->GetXOrRange(res, isPos, isNeg);
135         }
136     }
137 }
138 
getRange(std::vector<Range> & ranges,Node & node,Region::OP op)139 void Region::getRange(std::vector<Range>& ranges, Node& node, Region::OP op)
140 {
141     switch (op) {
142         case Region::OP::AND:
143             node.GetAndRange(ranges);
144             break;
145         case Region::OP::SUB:
146             node.GetSubRange(ranges);
147             break;
148         case Region::OP::OR:
149             node.GetOrRange(ranges);
150             break;
151         case Region::OP::XOR:
152             node.GetXOrRange(ranges);
153             break;
154         default:
155             break;
156     }
157     return;
158 }
159 
MakeEnumerate(std::set<int> & ys,std::map<int,int> & indexOf,std::vector<int> & indexAt)160 void MakeEnumerate(std::set<int>& ys, std::map<int, int>& indexOf, std::vector<int>& indexAt)
161 {
162     int index = 0;
163     auto it = ys.begin();
164     while (it != ys.end()) {
165         indexOf[*it] = index++;
166         indexAt.push_back(*it);
167         ++it;
168     }
169     return;
170 }
171 
UpdateRects(Rects & r,std::vector<Range> & ranges,std::vector<int> & indexAt,Region & res)172 void Region::UpdateRects(Rects& r, std::vector<Range>& ranges, std::vector<int>& indexAt, Region& res)
173 {
174     uint32_t i = 0;
175     uint32_t j = 0;
176     while (i < r.preRects.size() && j < ranges.size()) {
177         if (r.preRects[i].left_ == indexAt[ranges[j].start_] && r.preRects[i].right_ == indexAt[ranges[j].end_]) {
178             r.curRects.emplace_back(Rect { r.preRects[i].left_, r.preRects[i].top_, r.preRects[i].right_, r.curY });
179             j++;
180             i++;
181         } else if (r.preRects[i].right_ < indexAt[ranges[j].end_]) {
182             res.GetRegionRects().push_back(r.preRects[i]);
183             i++;
184         } else {
185             r.curRects.emplace_back(Rect { indexAt[ranges[j].start_], r.preY, indexAt[ranges[j].end_], r.curY });
186             j++;
187         }
188     }
189 
190     for (; j < ranges.size(); j++) {
191         r.curRects.emplace_back(Rect { indexAt[ranges[j].start_], r.preY, indexAt[ranges[j].end_], r.curY });
192     }
193     for (; i < r.preRects.size(); i++) {
194         res.GetRegionRects().push_back(r.preRects[i]);
195     }
196     r.preRects.clear();
197     r.preRects.swap(r.curRects);
198     return;
199 }
200 
MakeBound()201 void Region::MakeBound()
202 {
203     if (rects_.size()) {
204         bound_ = rects_[0];
205         for (const auto& r : rects_) {
206             bound_.top_ = std::min(r.top_, bound_.top_);
207             bound_.left_ = std::min(r.left_, bound_.left_);
208             bound_.right_ = std::max(r.right_, bound_.right_);
209             bound_.bottom_ = std::max(r.bottom_, bound_.bottom_);
210         }
211     }
212 }
213 
RegionOpLocal(Region & r1,Region & r2,Region & res,Region::OP op)214 void Region::RegionOpLocal(Region& r1, Region& r2, Region& res, Region::OP op)
215 {
216     r1.MakeBound();
217     r2.MakeBound();
218     res.GetRegionRects().clear();
219     std::set<int> xs;
220     std::vector<Event> events;
221 
222     for (auto& rect : r1.GetRegionRects()) {
223         events.emplace_back(Event { rect.top_, Event::Type::OPEN, rect.left_, rect.right_ });
224         events.emplace_back(Event { rect.bottom_, Event::Type::CLOSE, rect.left_, rect.right_ });
225         xs.insert(rect.left_);
226         xs.insert(rect.right_);
227     }
228     for (auto& rect : r2.GetRegionRects()) {
229         events.emplace_back(Event { rect.top_, Event::Type::VOID_OPEN, rect.left_, rect.right_ });
230         events.emplace_back(Event { rect.bottom_, Event::Type::VOID_CLOSE, rect.left_, rect.right_ });
231         xs.insert(rect.left_);
232         xs.insert(rect.right_);
233     }
234 
235     if (events.empty()) {
236         return;
237     }
238 
239     std::vector<int> indexAt;
240     std::map<int, int> indexOf;
241     MakeEnumerate(xs, indexOf, indexAt);
242     sort(events.begin(), events.end(), EventSortByY);
243     size_t indexOfSize = indexOf.size() > 0 ? (indexOf.size() - 1) : 0;
244     Node rootNode { 0, static_cast<int>(indexOfSize) };
245 
246     std::vector<Range> ranges;
247     Rects r;
248     r.curY = events[0].y_;
249     r.preY = events[0].y_;
250     for (auto& event : events) {
251         r.curY = event.y_;
252         ranges.clear();
253         getRange(ranges, rootNode, op);
254         if (r.curY > r.preY) {
255             UpdateRects(r, ranges, indexAt, res);
256         }
257         rootNode.Update(indexOf[event.left_], indexOf[event.right_], event.type_);
258         r.preY = r.curY;
259     }
260     copy(r.preRects.begin(), r.preRects.end(), back_inserter(res.GetRegionRects()));
261     res.MakeBound();
262 }
263 
RegionOp(Region & r1,Region & r2,Region & res,Region::OP op)264 void Region::RegionOp(Region& r1, Region& r2, Region& res, Region::OP op)
265 {
266     RegionOpLocal(r1, r2, res, op);
267 }
268 
OperationSelf(Region & r,Region::OP op)269 Region& Region::OperationSelf(Region& r, Region::OP op)
270 {
271     Region r1(*this);
272     RegionOp(r1, r, *this, op);
273     return *this;
274 }
275 
Or(Region & r)276 Region Region::Or(Region& r)
277 {
278     Region res;
279     RegionOp(*this, r, res, Region::OP::OR);
280     return res;
281 }
282 
And(Region & r)283 Region Region::And(Region& r)
284 {
285     Region res;
286     RegionOp(*this, r, res, Region::OP::AND);
287     return res;
288 }
289 
Sub(Region & r)290 Region Region::Sub(Region& r)
291 {
292     Region res;
293     RegionOp(*this, r, res, Region::OP::SUB);
294     return res;
295 }
296 
Xor(Region & r)297 Region Region::Xor(Region& r)
298 {
299     Region res;
300     RegionOp(*this, r, res, Region::OP::XOR);
301     return res;
302 }
303 
OrSelf(Region & r)304 Region& Region::OrSelf(Region& r)
305 {
306     return OperationSelf(r, Region::OP::OR);
307 }
308 
AndSelf(Region & r)309 Region& Region::AndSelf(Region& r)
310 {
311     return OperationSelf(r, Region::OP::AND);
312 }
313 
SubSelf(Region & r)314 Region& Region::SubSelf(Region& r)
315 {
316     return OperationSelf(r, Region::OP::SUB);
317 }
318 
XOrSelf(Region & r)319 Region& Region::XOrSelf(Region& r)
320 {
321     return OperationSelf(r, Region::OP::XOR);
322 }
323 
operator <<(std::ostream & os,const Region & r)324 std::ostream& operator<<(std::ostream& os, const Region& r)
325 {
326     os << "{";
327     os << r.GetSize() << ": ";
328     for (const Rect& regionRect : r.GetRegionRects()) {
329         os << regionRect;
330     }
331     os << "}" << std::endl;
332     return os;
333 }
334 } // namespace OHOS