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