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