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