• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <algorithm>
17 #include "ui_model.h"
18 
19 namespace OHOS::uitest {
20     using namespace std;
21 
ComputeIntersection(const Rect & ra,const Rect & rb,Rect & result)22     bool RectAlgorithm::ComputeIntersection(const Rect &ra, const Rect &rb, Rect &result)
23     {
24         if (ra.left_ >= rb.right_ || ra.right_ <= rb.left_) {
25             return false;
26         }
27         if (ra.top_ >= rb.bottom_ || ra.bottom_ <= rb.top_) {
28             return false;
29         }
30         array<int32_t, INDEX_FOUR> px = {ra.left_, ra.right_, rb.left_, rb.right_};
31         array<int32_t, INDEX_FOUR> py = {ra.top_, ra.bottom_, rb.top_, rb.bottom_};
32         sort(px.begin(), px.end());
33         sort(py.begin(), py.end());
34         result = {px[INDEX_ONE], px[INDEX_TWO], py[INDEX_ONE], py[INDEX_TWO]};
35         return true;
36     }
37 
38     /** Use static data buffers instead of dynamic-containers to ensure performance.*/
39     static constexpr size_t MAX_OVERLAYS = 64;
40     static constexpr size_t MAX_COORDS = (MAX_OVERLAYS + 1) << 1;
41     static constexpr size_t MAX_POINTS = MAX_COORDS * MAX_COORDS;
42     static int32_t g_XCoords[MAX_COORDS];
43     static int32_t g_YCoords[MAX_COORDS];
44     static Point g_Points[MAX_POINTS];
45     static size_t g_XCount = 0;
46     static size_t g_YCount = 0;
47     static size_t g_PCount = 0;
48 
CollectGridLineCoords(const Rect & rect,const Rect & overlay)49     static void CollectGridLineCoords(const Rect& rect, const Rect& overlay)
50     {
51         bool contained = false;
52         if (overlay.left_ >= rect.left_ && overlay.left_ <= rect.right_) {
53             for (size_t idx = 0; idx < g_XCount; idx++) {
54                 if (overlay.left_ == g_XCoords[idx]) {
55                     contained = true;
56                     break;
57                 }
58             }
59             if (!contained) {
60                 g_XCoords[g_XCount++] = overlay.left_;
61             }
62         }
63 
64         contained = false;
65         if (overlay.right_ >= rect.left_ && overlay.right_ <= rect.right_) {
66             for (size_t idx = 0; idx < g_XCount; idx++) {
67                 if (overlay.right_ == g_XCoords[idx]) {
68                     contained = true;
69                     break;
70                 }
71             }
72             if (!contained) {
73                 g_XCoords[g_XCount++] = overlay.right_;
74             }
75         }
76 
77         contained = false;
78         if (overlay.top_ >= rect.top_ && overlay.top_ <= rect.bottom_) {
79             for (size_t idx = 0; idx < g_YCount; idx++) {
80                 if (overlay.top_ == g_YCoords[idx]) {
81                     contained = true;
82                     break;
83                 }
84             }
85             if (!contained) {
86                 g_YCoords[g_YCount++] = overlay.top_;
87             }
88         }
89 
90         contained = false;
91         if (overlay.bottom_ >= rect.top_ && overlay.bottom_ <= rect.bottom_) {
92             for (size_t idx = 0; idx < g_YCount; idx++) {
93                 if (overlay.bottom_ == g_YCoords[idx]) {
94                     contained = true;
95                     break;
96                 }
97             }
98             if (!contained) {
99                 g_YCoords[g_YCount++] = overlay.bottom_;
100             }
101         }
102     }
103 
CollectGridPoint(int32_t px,int32_t py,const Rect & rect,const vector<Rect> & overlays)104     static void CollectGridPoint(int32_t px, int32_t py, const Rect& rect, const vector<Rect>& overlays)
105     {
106         const auto point = Point(px, py);
107         const bool onRectEdge = RectAlgorithm::IsPointOnEdge(rect, point);
108         if (!onRectEdge && !RectAlgorithm::IsInnerPoint(rect, point)) {
109             return; // point must be on or in the rect
110         }
111         bool onOverlyEdge = false;
112         for (const auto& overlay : overlays) {
113             if (RectAlgorithm::IsInnerPoint(overlay, point)) {
114                 return; // point is in at least one of the overlays, discard
115             }
116             if (!onRectEdge && !onOverlyEdge) {
117                 onOverlyEdge = RectAlgorithm::IsPointOnEdge(overlay, point);
118             }
119         }
120         if (onRectEdge || onOverlyEdge) {
121             g_Points[g_PCount++] = point;
122         }
123     }
124 
FindMaxVisibleRegion(const vector<Rect> & overlays,Rect & out)125     static void FindMaxVisibleRegion(const vector<Rect>& overlays, Rect& out)
126     {
127         // sort grid points and use double-pointer traversing, to resuce time-complexity
128         sort(g_Points, g_Points + g_PCount, [](const Point& pa, const Point& pb) {
129             return pa.px_ == pb.px_ ? pa.py_ < pb.py_ : pa.px_ < pb.px_;
130         });
131         out = Rect(0, 0, 0, 0);
132         for (size_t idx0 = 0; idx0 < g_PCount; idx0++) {
133             for (size_t idx1 = g_PCount - 1; idx1 > idx0; idx1--) {
134                 const auto width = g_Points[idx1].px_ - g_Points[idx0].px_;
135                 const auto height = g_Points[idx1].py_ - g_Points[idx0].py_;
136                 if (width <= 0) {
137                     break; // x is strictly ascending ordered
138                 }
139                 if (width * height <= out.GetWidth() * out.GetHeight()) {
140                     continue; // discard smaller region
141                 }
142                 auto intersect = false;
143                 const auto area = Rect(g_Points[idx0].px_, g_Points[idx1].px_, g_Points[idx0].py_, g_Points[idx1].py_);
144                 for (auto& overlay : overlays) {
145                     if (RectAlgorithm::CheckIntersectant(overlay, area)) {
146                         intersect = true; // region is intersected with some overlays, discard
147                         break;
148                     }
149                 }
150                 if (!intersect) {
151                     out = area;
152                 }
153             }
154         }
155     }
156 
ComputeMaxVisibleRegion(const Rect & rect,const vector<Rect> & overlays,Rect & out)157     bool RectAlgorithm::ComputeMaxVisibleRegion(const Rect& rect, const vector<Rect>& overlays, Rect& out)
158     {
159         vector<Rect> filteredOverlays;
160         for (auto& overlay : overlays) {
161             if (!RectAlgorithm::CheckIntersectant(rect, overlay)) {
162                 continue; // no intersection, invalid overlay
163             }
164             auto intersection = Rect(0, 0, 0, 0);
165             const auto intersected = RectAlgorithm::ComputeIntersection(rect, overlay, intersection);
166             if (intersected && RectAlgorithm::CheckEqual(rect, intersection)) {
167                 out = Rect(0, 0, 0, 0);
168                 return false; // fully covered, no visible region
169             }
170             filteredOverlays.emplace_back(overlay);
171         }
172         if (filteredOverlays.empty()) {
173             out = rect;
174             return true; // not covered
175         }
176         g_XCount = 0;
177         g_YCount = 0;
178         g_PCount = 0;
179         CollectGridLineCoords(rect, rect);
180         for (auto& overlay : filteredOverlays) {
181             CollectGridLineCoords(rect, overlay);
182         }
183         for (size_t xIdx = 0; xIdx < g_XCount; xIdx++) {
184             for (size_t yIdx = 0; yIdx < g_YCount; yIdx++) {
185                 CollectGridPoint(g_XCoords[xIdx], g_YCoords[yIdx], rect, filteredOverlays);
186             }
187         }
188         FindMaxVisibleRegion(filteredOverlays, out);
189         return out.GetHeight() > 0 && out.GetWidth() > 0;
190     }
191 } // namespace OHOS::uitest
192