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