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