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