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 #ifndef OHOS_ROSEN_WM_OCCLUSION_REGION_H 17 #define OHOS_ROSEN_WM_OCCLUSION_REGION_H 18 19 #include <refbase.h> 20 #include <algorithm> 21 #include <iostream> 22 #include <vector> 23 #include <string> 24 25 namespace OHOS::Rosen::WmOcclusion { 26 class Rect { 27 public: 28 int left_ = 0; 29 int top_ = 0; 30 int right_ = 0; 31 int bottom_ = 0; 32 static Rect _s_empty_rect_; 33 static Rect _s_invalid_rect_; 34 Rect()35 Rect() : left_(0), top_(0), right_(0), bottom_(0) {} Rect(int l,int t,int r,int b)36 Rect(int l, int t, int r, int b) : left_(l), top_(t), right_(r), bottom_(b) {} 37 GetRectInfo()38 std::string GetRectInfo() const 39 { 40 return std::string("[" + 41 std::to_string(left_) + ", " + 42 std::to_string(top_) + ", " + 43 std::to_string(right_ - left_) + ", " + 44 std::to_string(bottom_ - top_) + "]"); 45 } 46 IsEmpty()47 bool IsEmpty() const 48 { 49 return left_ >= right_ || top_ >= bottom_; 50 } 51 }; 52 53 std::ostream& operator<<(std::ostream& os, const Rect& r); 54 55 /* 56 Event: Used for record a rect edge in/out event 57 y_: rect edge Y value 58 type: OPEN/CLOSE: lhs rect in/out; VOID_OPEN/VOID_CLOSE: rhs rect in/out 59 */ 60 class Event { 61 public: 62 // Use different value to differentiate lhs and rhs ranges. 63 enum Type { OPEN = 1, CLOSE = -1, VOID_OPEN = 2, VOID_CLOSE = -2 }; 64 int y_ = 0; 65 Type type_ = Type::OPEN; 66 int left_ = 0; 67 int right_ = 0; 68 Event(int y,Type type,int l,int r)69 Event(int y, Type type, int l, int r) : y_(y), type_(type), left_(l), right_(r) {} 70 }; 71 72 bool EventSortByY(const Event& e1, const Event& e2); 73 74 class Range { 75 public: 76 int start_ = 0; 77 int end_ = 0; Range(int start,int end)78 Range(int start, int end) : start_(start), end_(end) {} 79 bool operator==(const Range& r) 80 { 81 return start_ == r.start_ && end_ == r.end_; 82 } 83 }; 84 85 class Node { 86 public: 87 int start_ = 0; 88 int end_ = 0; 89 int mid_ = 0; 90 Node* left_ = nullptr; 91 Node* right_ = nullptr; 92 int positive_count_ = 0; // used for counting current lhs ranges 93 int negative_count_ = 0; // used for counting current rhs ranges 94 Node(int s,int e)95 Node(int s, int e) : start_(s), end_(e), mid_((s + e) >> 1) {} ~Node()96 ~Node() 97 { 98 if (right_ != nullptr) { 99 delete right_; 100 right_ = nullptr; 101 } 102 if (left_ != nullptr) { 103 delete left_; 104 left_ = nullptr; 105 } 106 } 107 IsLeaf()108 inline bool IsLeaf() 109 { 110 return left_ == nullptr && right_ == nullptr; 111 } 112 113 // push current node [start, end] into range result, merge last range if possible PushRange(std::vector<Range> & res)114 inline void PushRange(std::vector<Range>& res) 115 { 116 if (res.size() > 0 && start_ == res[res.size() - 1].end_) { 117 // merge range with previous range if their end and start share same point 118 res[res.size() - 1].end_ = end_; 119 } else { 120 res.emplace_back(Range { start_, end_ }); 121 } 122 } 123 124 // update segment tree 125 void Update(int updateStart, int updateEnd, Event::Type type); 126 // get ranges where positive_count_ or negtive_count_ is positive 127 void GetOrRange(std::vector<Range>& res, bool isParentNodePos, bool isParentNodeNeg); 128 // get ranges where positive_count_ and negtive_count_ are both positive 129 void GetAndRange(std::vector<Range>& res, bool isParentNodePos, bool isParentNodeNeg); 130 // get ranges where positive_count_ is positive and negtive_count_ not 131 void GetSubRange(std::vector<Range>& res, bool isParentNodePos, bool isParentNodeNeg); 132 // get ranges where either positive_count_ and negtive_count_ are both positive 133 void GetXOrRange(std::vector<Range>& res, bool isParentNodePos, bool isParentNodeNeg); 134 }; 135 136 class Region { 137 public: 138 enum OP { 139 // bit index 0: lhs 140 // bit index 1: lhs & rhs 141 // bit index 2: rhs 142 AND = 2, // 010 143 OR = 7, // 111 144 XOR = 5, // 101 145 SUB = 1 // 001 146 }; 147 148 Region() = default; Region(Rect & rect)149 explicit Region(Rect& rect) 150 { 151 rects_.push_back(rect); 152 bound_ = Rect { rect }; 153 } 154 Region(const Region & region)155 Region(const Region& region) : rects_(region.rects_), bound_(region.bound_) {} 156 Region& operator=(const Region& region) 157 { 158 rects_ = region.rects_; 159 bound_ = region.bound_; 160 return *this; 161 } ~Region()162 ~Region() {} 163 GetRegionRects()164 std::vector<Rect>& GetRegionRects() 165 { 166 return rects_; 167 } 168 GetRegionRects()169 std::vector<Rect> GetRegionRects() const 170 { 171 return rects_; 172 } 173 IsEmpty()174 bool IsEmpty() const 175 { 176 return rects_.size() == 0; 177 } 178 GetSize()179 int GetSize() const 180 { 181 return rects_.size(); 182 } 183 GetBoundRef()184 Rect& GetBoundRef() 185 { 186 return bound_; 187 } 188 GetBound()189 Rect GetBound() const 190 { 191 return bound_; 192 } 193 GetRegionInfo()194 std::string GetRegionInfo() const 195 { 196 std::string info = "{ Region Size " + std::to_string(rects_.size()) + ": "; 197 for (auto& rect : rects_) { 198 info.append(rect.GetRectInfo()); 199 } 200 info.append(" }"); 201 return info; 202 } 203 Size()204 inline size_t Size() const 205 { 206 return rects_.size(); 207 } 208 CBegin()209 inline std::vector<Rect>::const_iterator CBegin() const 210 { 211 return rects_.cbegin(); 212 } 213 Begin()214 inline std::vector<Rect>::iterator Begin() 215 { 216 return rects_.begin(); 217 } 218 CEnd()219 inline std::vector<Rect>::const_iterator CEnd() const 220 { 221 return rects_.cend(); 222 } 223 End()224 inline std::vector<Rect>::const_iterator End() 225 { 226 return rects_.end(); 227 } 228 229 /* core Region logic operation function, the return region's rects is guaranteed no-intersection 230 (rect in rects_ do not intersect with each other) 231 */ 232 void RegionOp(Region& r1, Region& r2, Region& res, Region::OP op); 233 void RegionOpLocal(Region& r1, Region& r2, Region& res, Region::OP op); 234 // bound of all region rects 235 void MakeBound(); 236 237 // return merge region 238 Region Or(Region& r); 239 // return intersection region 240 Region And(Region& r); 241 // return region belongs to Region(lhs) but not Region(rhs) 242 Region Sub(Region& r); 243 // return merge region subtract intersection region 244 Region Xor(Region& r); 245 246 Region& OperationSelf(Region& r, Region::OP op); 247 // replace region with or result 248 Region& OrSelf(Region& r); 249 // replace region with and result 250 Region& AndSelf(Region& r); 251 // replace region with sub result 252 Region& SubSelf(Region& r); 253 // replace region with xor result 254 Region& XOrSelf(Region& r); 255 256 private: 257 class Rects { 258 public: 259 int preY = 0; 260 int curY = 0; 261 std::vector<Rect> preRects; 262 std::vector<Rect> curRects; 263 }; 264 // update tmp rects and region according to current ranges 265 void UpdateRects(Rects& r, std::vector<Range>& ranges, std::vector<int>& indexAt, Region& res); 266 // get ranges from segmentTree node according to logical operation type 267 void getRange(std::vector<Range>& ranges, Node& node, OP op); 268 269 private: 270 std::vector<Rect> rects_; 271 Rect bound_; 272 static bool _s_so_loaded_; 273 }; 274 std::ostream& operator<<(std::ostream& os, const Region& r); 275 } // namespace OHOS::Rosen::Occlusion 276 #endif // OHOS_ROSEN_WM_OCCLUSION_REGION_H