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