1 /*
2 * Copyright (c) 2023-2023 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 <common/rs_occlusion_region_helper.h>
16
17 namespace OHOS {
18 namespace Rosen {
19 namespace Occlusion {
20
Insert(const Rect & r)21 void Assembler::Insert(const Rect&r)
22 {
23 if (rectsRow_.size() > 0) {
24 if (cur_->top_ != r.top_) { // current rect r is not in same row of current span
25 FlushVerticalSpan(); // current span will be cleared
26 } else if (cur_->right_ == r.left_) { // merge rect in horizon (X) direction
27 cur_->right_ = r.right_;
28 return;
29 }
30 }
31 rectsRow_.push_back(r);
32 cur_ = rectsRow_.begin() + static_cast<long>(rectsRow_.size() - 1);
33 }
34
FlushVerticalSpan()35 void Assembler::FlushVerticalSpan()
36 {
37 if (rectsRow_.size() == 0) {
38 return;
39 }
40 if (CurrentSpanCanMerge()) {
41 MergeSpanVertically();
42 } else {
43 bound_.left_ = std::min(rectsRow_[0].left_, bound_.left_);
44 bound_.right_ = std::max(rectsRow_[rectsRow_.size() - 1].right_, bound_.right_);
45 storage_.insert(storage_.end(), rectsRow_.begin(), rectsRow_.end());
46 end_ = (storage_.begin() + static_cast<long>(storage_.size()));
47 lastRectRowBegin_ = end_ - static_cast<long>(rectsRow_.size());
48 }
49 rectsRow_.clear();
50 }
51
CurrentSpanCanMerge() const52 bool Assembler::CurrentSpanCanMerge() const
53 {
54 bool merge = false;
55 if (end_ - lastRectRowBegin_ == static_cast<long>(rectsRow_.size())) {
56 std::vector<Rect>::const_iterator curRowPtr = rectsRow_.cbegin();
57 std::vector<Rect>::const_iterator lastRowPtr = lastRectRowBegin_;
58 if (curRowPtr->top_ != lastRowPtr->bottom_) {
59 return false;
60 }
61 merge = true;
62 while (lastRowPtr != end_) {
63 if ((curRowPtr->left_ != lastRowPtr->left_) ||
64 (curRowPtr->right_ != lastRowPtr->right_)) {
65 merge = false;
66 break;
67 }
68 ++curRowPtr;
69 ++lastRowPtr;
70 }
71 }
72 return merge;
73 }
74
MergeSpanVertically()75 void Assembler::MergeSpanVertically()
76 {
77 if (rectsRow_.size() == 0) {
78 return;
79 }
80 const int bottom = rectsRow_[0].bottom_;
81 std::vector<Rect>::iterator r = lastRectRowBegin_;
82 while (r != end_) {
83 r->bottom_ = bottom;
84 ++r;
85 }
86 }
87
~Assembler()88 Assembler::~Assembler()
89 {
90 if (storage_.size()) {
91 bound_.top_ = storage_[0].top_;
92 bound_.bottom_ = storage_[storage_.size() - 1].bottom_;
93 }
94 }
95
GetEdgeRelation(int & head,int & tail,bool & moreLhs,bool & moreRhs)96 inline RectType Looper::GetEdgeRelation(int &head, int &tail,
97 bool &moreLhs, bool &moreRhs)
98 {
99 RectType relationship;
100 moreLhs = false;
101 moreRhs = false;
102 if (lhsStart_ < rhsStart_) {
103 relationship = RectType::LHS_ONLY;
104 head = lhsStart_;
105 if (lhsEnd_ <= rhsStart_) {
106 tail = lhsEnd_;
107 moreLhs = true;
108 } else {
109 lhsStart_ = rhsStart_;
110 tail = rhsStart_;
111 }
112 } else if (rhsStart_ < lhsStart_) {
113 relationship = RectType::RHS_ONLY;
114 head = rhsStart_;
115 if (rhsEnd_ <= lhsStart_) {
116 tail = rhsEnd_;
117 moreRhs = true;
118 } else {
119 rhsStart_ = lhsStart_;
120 tail = lhsStart_;
121 }
122 } else {
123 relationship = RectType::LHS_RHS_BOTH;
124 head = lhsStart_;
125 if (lhsEnd_ <= rhsEnd_) {
126 tail = rhsStart_ = lhsEnd_;
127 moreLhs = true;
128 }
129 if (rhsEnd_ <= lhsEnd_) {
130 tail = lhsStart_ = rhsEnd_;
131 moreRhs = true;
132 }
133 }
134 return relationship;
135 }
136
NextScanline(int & curTop,int & curBottom)137 RectType OuterLooper::NextScanline(int &curTop, int &curBottom)
138 {
139 bool moreLhs;
140 bool moreRhs;
141 RectType relationships = Looper::GetEdgeRelation(curTop, curBottom, moreLhs, moreRhs);
142 MoveScanline(moreLhs, moreRhs);
143 return relationships;
144 }
145
MoveScanline(bool moreLhs,bool moreRhs)146 inline void OuterLooper::MoveScanline(bool moreLhs, bool moreRhs)
147 {
148 if (moreLhs) {
149 MoveScanline(lhs_, lhsStart_, lhsEnd_);
150 }
151 if (moreRhs) {
152 MoveScanline(rhs_, rhsStart_, rhsEnd_);
153 }
154 return;
155 }
156
MoveScanline(RectsPtr & r,int & top,int & bottom)157 void OuterLooper::MoveScanline(RectsPtr &r, int &top, int &bottom)
158 {
159 auto rect = r.rects_;
160 auto count = r.count_;
161 auto rectEnd = rect + static_cast<long>(count);
162 int curTop = rect->top_;
163 while (rect != rectEnd && rect->top_ == curTop) {
164 ++rect;
165 --count;
166 }
167 if (rect != rectEnd) {
168 top = rect->top_;
169 bottom = rect->bottom_;
170 } else {
171 top = INT_MAX;
172 bottom = INT_MAX;
173 }
174 r.rects_ = rect;
175 r.count_ = count;
176 return;
177 }
178
Init(RectType relationship)179 void InnerLooper::Init(RectType relationship)
180 {
181 if (relationship == RectType::LHS_ONLY) {
182 if (lhs_.count_) {
183 lhsStart_ = lhs_.rects_->left_;
184 lhsEnd_ = lhs_.rects_->right_;
185 }
186 rhsStart_ = INT_MAX;
187 rhsEnd_ = INT_MAX;
188 } else if (relationship == RectType::RHS_ONLY) {
189 if (rhs_.count_) {
190 rhsStart_ = rhs_.rects_->left_;
191 rhsEnd_ = rhs_.rects_->right_;
192 }
193 lhsStart_ = INT_MAX;
194 lhsEnd_ = INT_MAX;
195 } else {
196 if (lhs_.count_) {
197 lhsStart_ = lhs_.rects_->left_;
198 lhsEnd_ = lhs_.rects_->right_;
199 }
200 if (rhs_.count_) {
201 rhsStart_ = rhs_.rects_->left_;
202 rhsEnd_ = rhs_.rects_->right_;
203 }
204 }
205 }
206
NextRect(int & curLeft,int & curRight)207 RectType InnerLooper::NextRect(int &curLeft, int &curRight)
208 {
209 bool moreLhs;
210 bool moreRhs;
211 RectType rectType = GetEdgeRelation(curLeft, curRight, moreLhs, moreRhs);
212 MoveRect(moreLhs, moreRhs);
213 return rectType;
214 }
215
MoveRect(bool moreLhs,bool moreRhs)216 inline void InnerLooper::MoveRect(bool moreLhs, bool moreRhs)
217 {
218 if (moreLhs) {
219 MoveRect(lhs_, lhsStart_, lhsEnd_);
220 }
221 if (moreRhs) {
222 MoveRect(rhs_, rhsStart_, rhsEnd_);
223 }
224 return;
225 }
226
MoveRect(RectsPtr & r,int & left,int & right)227 void InnerLooper::MoveRect(RectsPtr &r, int &left, int &right)
228 {
229 if (r.count_) {
230 int curTop = r.rects_->top_;
231 ++r.rects_;
232 r.count_--;
233 if (r.count_ > 0 && r.rects_->top_ == curTop) {
234 left = r.rects_->left_;
235 right = r.rects_->right_;
236 } else {
237 left = INT_MAX;
238 right = INT_MAX;
239 }
240 }
241 }
242
243 } // namespace Occlusion
244 } // namespace Rosen
245 } // namespace OHOS