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