1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker * Copyright (C) 2007 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker *
4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker *
8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker *
10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker */
16*38e8c45fSAndroid Build Coastguard Worker
17*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "Region"
18*38e8c45fSAndroid Build Coastguard Worker
19*38e8c45fSAndroid Build Coastguard Worker #include <inttypes.h>
20*38e8c45fSAndroid Build Coastguard Worker #include <limits.h>
21*38e8c45fSAndroid Build Coastguard Worker
22*38e8c45fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
23*38e8c45fSAndroid Build Coastguard Worker
24*38e8c45fSAndroid Build Coastguard Worker #include <utils/Log.h>
25*38e8c45fSAndroid Build Coastguard Worker
26*38e8c45fSAndroid Build Coastguard Worker #include <ui/Point.h>
27*38e8c45fSAndroid Build Coastguard Worker #include <ui/Rect.h>
28*38e8c45fSAndroid Build Coastguard Worker #include <ui/Region.h>
29*38e8c45fSAndroid Build Coastguard Worker #include <ui/RegionHelper.h>
30*38e8c45fSAndroid Build Coastguard Worker
31*38e8c45fSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
32*38e8c45fSAndroid Build Coastguard Worker
33*38e8c45fSAndroid Build Coastguard Worker // ### VALIDATE_REGIONS ###
34*38e8c45fSAndroid Build Coastguard Worker // To enable VALIDATE_REGIONS traces, use the "libui-validate-regions-defaults"
35*38e8c45fSAndroid Build Coastguard Worker // in Android.bp. Do not #define VALIDATE_REGIONS here as it requires extra libs.
36*38e8c45fSAndroid Build Coastguard Worker
37*38e8c45fSAndroid Build Coastguard Worker #define VALIDATE_WITH_CORECG (false)
38*38e8c45fSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
39*38e8c45fSAndroid Build Coastguard Worker
40*38e8c45fSAndroid Build Coastguard Worker #if defined(VALIDATE_REGIONS)
41*38e8c45fSAndroid Build Coastguard Worker #include <utils/CallStack.h>
42*38e8c45fSAndroid Build Coastguard Worker #endif
43*38e8c45fSAndroid Build Coastguard Worker
44*38e8c45fSAndroid Build Coastguard Worker #if VALIDATE_WITH_CORECG
45*38e8c45fSAndroid Build Coastguard Worker #include <core/SkRegion.h>
46*38e8c45fSAndroid Build Coastguard Worker #endif
47*38e8c45fSAndroid Build Coastguard Worker
48*38e8c45fSAndroid Build Coastguard Worker namespace android {
49*38e8c45fSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
50*38e8c45fSAndroid Build Coastguard Worker
51*38e8c45fSAndroid Build Coastguard Worker using base::StringAppendF;
52*38e8c45fSAndroid Build Coastguard Worker
53*38e8c45fSAndroid Build Coastguard Worker enum {
54*38e8c45fSAndroid Build Coastguard Worker op_nand = region_operator<Rect>::op_nand,
55*38e8c45fSAndroid Build Coastguard Worker op_and = region_operator<Rect>::op_and,
56*38e8c45fSAndroid Build Coastguard Worker op_or = region_operator<Rect>::op_or,
57*38e8c45fSAndroid Build Coastguard Worker op_xor = region_operator<Rect>::op_xor
58*38e8c45fSAndroid Build Coastguard Worker };
59*38e8c45fSAndroid Build Coastguard Worker
60*38e8c45fSAndroid Build Coastguard Worker enum {
61*38e8c45fSAndroid Build Coastguard Worker direction_LTR,
62*38e8c45fSAndroid Build Coastguard Worker direction_RTL
63*38e8c45fSAndroid Build Coastguard Worker };
64*38e8c45fSAndroid Build Coastguard Worker
65*38e8c45fSAndroid Build Coastguard Worker const Region Region::INVALID_REGION(Rect::INVALID_RECT);
66*38e8c45fSAndroid Build Coastguard Worker
67*38e8c45fSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
68*38e8c45fSAndroid Build Coastguard Worker
Region()69*38e8c45fSAndroid Build Coastguard Worker Region::Region() {
70*38e8c45fSAndroid Build Coastguard Worker mStorage.push_back(Rect(0, 0));
71*38e8c45fSAndroid Build Coastguard Worker }
72*38e8c45fSAndroid Build Coastguard Worker
Region(const Region & rhs)73*38e8c45fSAndroid Build Coastguard Worker Region::Region(const Region& rhs)
74*38e8c45fSAndroid Build Coastguard Worker {
75*38e8c45fSAndroid Build Coastguard Worker mStorage.clear();
76*38e8c45fSAndroid Build Coastguard Worker mStorage.insert(mStorage.begin(), rhs.mStorage.begin(), rhs.mStorage.end());
77*38e8c45fSAndroid Build Coastguard Worker #if defined(VALIDATE_REGIONS)
78*38e8c45fSAndroid Build Coastguard Worker validate(rhs, "rhs copy-ctor");
79*38e8c45fSAndroid Build Coastguard Worker #endif
80*38e8c45fSAndroid Build Coastguard Worker }
81*38e8c45fSAndroid Build Coastguard Worker
Region(const Rect & rhs)82*38e8c45fSAndroid Build Coastguard Worker Region::Region(const Rect& rhs) {
83*38e8c45fSAndroid Build Coastguard Worker mStorage.push_back(rhs);
84*38e8c45fSAndroid Build Coastguard Worker }
85*38e8c45fSAndroid Build Coastguard Worker
~Region()86*38e8c45fSAndroid Build Coastguard Worker Region::~Region()
87*38e8c45fSAndroid Build Coastguard Worker {
88*38e8c45fSAndroid Build Coastguard Worker }
89*38e8c45fSAndroid Build Coastguard Worker
90*38e8c45fSAndroid Build Coastguard Worker /**
91*38e8c45fSAndroid Build Coastguard Worker * Copy rects from the src vector into the dst vector, resolving vertical T-Junctions along the way
92*38e8c45fSAndroid Build Coastguard Worker *
93*38e8c45fSAndroid Build Coastguard Worker * First pass through, divideSpanRTL will be set because the 'previous span' (indexing into the dst
94*38e8c45fSAndroid Build Coastguard Worker * vector) will be reversed. Each rectangle in the original list, starting from the bottom, will be
95*38e8c45fSAndroid Build Coastguard Worker * compared with the span directly below, and subdivided as needed to resolve T-junctions.
96*38e8c45fSAndroid Build Coastguard Worker *
97*38e8c45fSAndroid Build Coastguard Worker * The resulting temporary vector will be a completely reversed copy of the original, without any
98*38e8c45fSAndroid Build Coastguard Worker * bottom-up T-junctions.
99*38e8c45fSAndroid Build Coastguard Worker *
100*38e8c45fSAndroid Build Coastguard Worker * Second pass through, divideSpanRTL will be false since the previous span will index into the
101*38e8c45fSAndroid Build Coastguard Worker * final, correctly ordered region buffer. Each rectangle will be compared with the span directly
102*38e8c45fSAndroid Build Coastguard Worker * above it, and subdivided to resolve any remaining T-junctions.
103*38e8c45fSAndroid Build Coastguard Worker */
reverseRectsResolvingJunctions(const Rect * begin,const Rect * end,FatVector<Rect> & dst,int spanDirection)104*38e8c45fSAndroid Build Coastguard Worker static void reverseRectsResolvingJunctions(const Rect* begin, const Rect* end, FatVector<Rect>& dst,
105*38e8c45fSAndroid Build Coastguard Worker int spanDirection) {
106*38e8c45fSAndroid Build Coastguard Worker dst.clear();
107*38e8c45fSAndroid Build Coastguard Worker
108*38e8c45fSAndroid Build Coastguard Worker const Rect* current = end - 1;
109*38e8c45fSAndroid Build Coastguard Worker int lastTop = current->top;
110*38e8c45fSAndroid Build Coastguard Worker
111*38e8c45fSAndroid Build Coastguard Worker // add first span immediately
112*38e8c45fSAndroid Build Coastguard Worker do {
113*38e8c45fSAndroid Build Coastguard Worker dst.push_back(*current);
114*38e8c45fSAndroid Build Coastguard Worker current--;
115*38e8c45fSAndroid Build Coastguard Worker } while (current->top == lastTop && current >= begin);
116*38e8c45fSAndroid Build Coastguard Worker
117*38e8c45fSAndroid Build Coastguard Worker int beginLastSpan = -1;
118*38e8c45fSAndroid Build Coastguard Worker int endLastSpan = -1;
119*38e8c45fSAndroid Build Coastguard Worker int top = -1;
120*38e8c45fSAndroid Build Coastguard Worker int bottom = -1;
121*38e8c45fSAndroid Build Coastguard Worker
122*38e8c45fSAndroid Build Coastguard Worker // for all other spans, split if a t-junction exists in the span directly above
123*38e8c45fSAndroid Build Coastguard Worker while (current >= begin) {
124*38e8c45fSAndroid Build Coastguard Worker if (current->top != (current + 1)->top) {
125*38e8c45fSAndroid Build Coastguard Worker // new span
126*38e8c45fSAndroid Build Coastguard Worker if ((spanDirection == direction_RTL && current->bottom != (current + 1)->top) ||
127*38e8c45fSAndroid Build Coastguard Worker (spanDirection == direction_LTR && current->top != (current + 1)->bottom)) {
128*38e8c45fSAndroid Build Coastguard Worker // previous span not directly adjacent, don't check for T junctions
129*38e8c45fSAndroid Build Coastguard Worker beginLastSpan = INT_MAX;
130*38e8c45fSAndroid Build Coastguard Worker } else {
131*38e8c45fSAndroid Build Coastguard Worker beginLastSpan = endLastSpan + 1;
132*38e8c45fSAndroid Build Coastguard Worker }
133*38e8c45fSAndroid Build Coastguard Worker endLastSpan = static_cast<int>(dst.size()) - 1;
134*38e8c45fSAndroid Build Coastguard Worker
135*38e8c45fSAndroid Build Coastguard Worker top = current->top;
136*38e8c45fSAndroid Build Coastguard Worker bottom = current->bottom;
137*38e8c45fSAndroid Build Coastguard Worker }
138*38e8c45fSAndroid Build Coastguard Worker int left = current->left;
139*38e8c45fSAndroid Build Coastguard Worker int right = current->right;
140*38e8c45fSAndroid Build Coastguard Worker
141*38e8c45fSAndroid Build Coastguard Worker for (int prevIndex = beginLastSpan; prevIndex <= endLastSpan; prevIndex++) {
142*38e8c45fSAndroid Build Coastguard Worker // prevIndex can't be -1 here because if endLastSpan is set to a
143*38e8c45fSAndroid Build Coastguard Worker // value greater than -1 (allowing the loop to execute),
144*38e8c45fSAndroid Build Coastguard Worker // beginLastSpan (and therefore prevIndex) will also be increased
145*38e8c45fSAndroid Build Coastguard Worker const Rect prev = dst[static_cast<size_t>(prevIndex)];
146*38e8c45fSAndroid Build Coastguard Worker if (spanDirection == direction_RTL) {
147*38e8c45fSAndroid Build Coastguard Worker // iterating over previous span RTL, quit if it's too far left
148*38e8c45fSAndroid Build Coastguard Worker if (prev.right <= left) break;
149*38e8c45fSAndroid Build Coastguard Worker
150*38e8c45fSAndroid Build Coastguard Worker if (prev.right > left && prev.right < right) {
151*38e8c45fSAndroid Build Coastguard Worker dst.push_back(Rect(prev.right, top, right, bottom));
152*38e8c45fSAndroid Build Coastguard Worker right = prev.right;
153*38e8c45fSAndroid Build Coastguard Worker }
154*38e8c45fSAndroid Build Coastguard Worker
155*38e8c45fSAndroid Build Coastguard Worker if (prev.left > left && prev.left < right) {
156*38e8c45fSAndroid Build Coastguard Worker dst.push_back(Rect(prev.left, top, right, bottom));
157*38e8c45fSAndroid Build Coastguard Worker right = prev.left;
158*38e8c45fSAndroid Build Coastguard Worker }
159*38e8c45fSAndroid Build Coastguard Worker
160*38e8c45fSAndroid Build Coastguard Worker // if an entry in the previous span is too far right, nothing further left in the
161*38e8c45fSAndroid Build Coastguard Worker // current span will need it
162*38e8c45fSAndroid Build Coastguard Worker if (prev.left >= right) {
163*38e8c45fSAndroid Build Coastguard Worker beginLastSpan = prevIndex;
164*38e8c45fSAndroid Build Coastguard Worker }
165*38e8c45fSAndroid Build Coastguard Worker } else {
166*38e8c45fSAndroid Build Coastguard Worker // iterating over previous span LTR, quit if it's too far right
167*38e8c45fSAndroid Build Coastguard Worker if (prev.left >= right) break;
168*38e8c45fSAndroid Build Coastguard Worker
169*38e8c45fSAndroid Build Coastguard Worker if (prev.left > left && prev.left < right) {
170*38e8c45fSAndroid Build Coastguard Worker dst.push_back(Rect(left, top, prev.left, bottom));
171*38e8c45fSAndroid Build Coastguard Worker left = prev.left;
172*38e8c45fSAndroid Build Coastguard Worker }
173*38e8c45fSAndroid Build Coastguard Worker
174*38e8c45fSAndroid Build Coastguard Worker if (prev.right > left && prev.right < right) {
175*38e8c45fSAndroid Build Coastguard Worker dst.push_back(Rect(left, top, prev.right, bottom));
176*38e8c45fSAndroid Build Coastguard Worker left = prev.right;
177*38e8c45fSAndroid Build Coastguard Worker }
178*38e8c45fSAndroid Build Coastguard Worker // if an entry in the previous span is too far left, nothing further right in the
179*38e8c45fSAndroid Build Coastguard Worker // current span will need it
180*38e8c45fSAndroid Build Coastguard Worker if (prev.right <= left) {
181*38e8c45fSAndroid Build Coastguard Worker beginLastSpan = prevIndex;
182*38e8c45fSAndroid Build Coastguard Worker }
183*38e8c45fSAndroid Build Coastguard Worker }
184*38e8c45fSAndroid Build Coastguard Worker }
185*38e8c45fSAndroid Build Coastguard Worker
186*38e8c45fSAndroid Build Coastguard Worker if (left < right) {
187*38e8c45fSAndroid Build Coastguard Worker dst.push_back(Rect(left, top, right, bottom));
188*38e8c45fSAndroid Build Coastguard Worker }
189*38e8c45fSAndroid Build Coastguard Worker
190*38e8c45fSAndroid Build Coastguard Worker current--;
191*38e8c45fSAndroid Build Coastguard Worker }
192*38e8c45fSAndroid Build Coastguard Worker }
193*38e8c45fSAndroid Build Coastguard Worker
194*38e8c45fSAndroid Build Coastguard Worker /**
195*38e8c45fSAndroid Build Coastguard Worker * Creates a new region with the same data as the argument, but divides rectangles as necessary to
196*38e8c45fSAndroid Build Coastguard Worker * remove T-Junctions
197*38e8c45fSAndroid Build Coastguard Worker *
198*38e8c45fSAndroid Build Coastguard Worker * Note: the output will not necessarily be a very efficient representation of the region, since it
199*38e8c45fSAndroid Build Coastguard Worker * may be that a triangle-based approach would generate significantly simpler geometry
200*38e8c45fSAndroid Build Coastguard Worker */
createTJunctionFreeRegion(const Region & r)201*38e8c45fSAndroid Build Coastguard Worker Region Region::createTJunctionFreeRegion(const Region& r) {
202*38e8c45fSAndroid Build Coastguard Worker if (r.isEmpty()) return r;
203*38e8c45fSAndroid Build Coastguard Worker if (r.isRect()) return r;
204*38e8c45fSAndroid Build Coastguard Worker
205*38e8c45fSAndroid Build Coastguard Worker FatVector<Rect> reversed;
206*38e8c45fSAndroid Build Coastguard Worker reverseRectsResolvingJunctions(r.begin(), r.end(), reversed, direction_RTL);
207*38e8c45fSAndroid Build Coastguard Worker
208*38e8c45fSAndroid Build Coastguard Worker Region outputRegion;
209*38e8c45fSAndroid Build Coastguard Worker reverseRectsResolvingJunctions(reversed.data(), reversed.data() + reversed.size(),
210*38e8c45fSAndroid Build Coastguard Worker outputRegion.mStorage, direction_LTR);
211*38e8c45fSAndroid Build Coastguard Worker outputRegion.mStorage.push_back(
212*38e8c45fSAndroid Build Coastguard Worker r.getBounds()); // to make region valid, mStorage must end with bounds
213*38e8c45fSAndroid Build Coastguard Worker
214*38e8c45fSAndroid Build Coastguard Worker #if defined(VALIDATE_REGIONS)
215*38e8c45fSAndroid Build Coastguard Worker validate(outputRegion, "T-Junction free region");
216*38e8c45fSAndroid Build Coastguard Worker #endif
217*38e8c45fSAndroid Build Coastguard Worker
218*38e8c45fSAndroid Build Coastguard Worker return outputRegion;
219*38e8c45fSAndroid Build Coastguard Worker }
220*38e8c45fSAndroid Build Coastguard Worker
operator =(const Region & rhs)221*38e8c45fSAndroid Build Coastguard Worker Region& Region::operator = (const Region& rhs)
222*38e8c45fSAndroid Build Coastguard Worker {
223*38e8c45fSAndroid Build Coastguard Worker #if defined(VALIDATE_REGIONS)
224*38e8c45fSAndroid Build Coastguard Worker validate(*this, "this->operator=");
225*38e8c45fSAndroid Build Coastguard Worker validate(rhs, "rhs.operator=");
226*38e8c45fSAndroid Build Coastguard Worker #endif
227*38e8c45fSAndroid Build Coastguard Worker if (this == &rhs) {
228*38e8c45fSAndroid Build Coastguard Worker // Already equal to itself
229*38e8c45fSAndroid Build Coastguard Worker return *this;
230*38e8c45fSAndroid Build Coastguard Worker }
231*38e8c45fSAndroid Build Coastguard Worker
232*38e8c45fSAndroid Build Coastguard Worker mStorage.clear();
233*38e8c45fSAndroid Build Coastguard Worker mStorage.insert(mStorage.begin(), rhs.mStorage.begin(), rhs.mStorage.end());
234*38e8c45fSAndroid Build Coastguard Worker return *this;
235*38e8c45fSAndroid Build Coastguard Worker }
236*38e8c45fSAndroid Build Coastguard Worker
makeBoundsSelf()237*38e8c45fSAndroid Build Coastguard Worker Region& Region::makeBoundsSelf()
238*38e8c45fSAndroid Build Coastguard Worker {
239*38e8c45fSAndroid Build Coastguard Worker if (mStorage.size() >= 2) {
240*38e8c45fSAndroid Build Coastguard Worker const Rect bounds(getBounds());
241*38e8c45fSAndroid Build Coastguard Worker mStorage.clear();
242*38e8c45fSAndroid Build Coastguard Worker mStorage.push_back(bounds);
243*38e8c45fSAndroid Build Coastguard Worker }
244*38e8c45fSAndroid Build Coastguard Worker return *this;
245*38e8c45fSAndroid Build Coastguard Worker }
246*38e8c45fSAndroid Build Coastguard Worker
contains(const Point & point) const247*38e8c45fSAndroid Build Coastguard Worker bool Region::contains(const Point& point) const {
248*38e8c45fSAndroid Build Coastguard Worker return contains(point.x, point.y);
249*38e8c45fSAndroid Build Coastguard Worker }
250*38e8c45fSAndroid Build Coastguard Worker
contains(int x,int y) const251*38e8c45fSAndroid Build Coastguard Worker bool Region::contains(int x, int y) const {
252*38e8c45fSAndroid Build Coastguard Worker const_iterator cur = begin();
253*38e8c45fSAndroid Build Coastguard Worker const_iterator const tail = end();
254*38e8c45fSAndroid Build Coastguard Worker while (cur != tail) {
255*38e8c45fSAndroid Build Coastguard Worker if (y >= cur->top && y < cur->bottom && x >= cur->left && x < cur->right) {
256*38e8c45fSAndroid Build Coastguard Worker return true;
257*38e8c45fSAndroid Build Coastguard Worker }
258*38e8c45fSAndroid Build Coastguard Worker cur++;
259*38e8c45fSAndroid Build Coastguard Worker }
260*38e8c45fSAndroid Build Coastguard Worker return false;
261*38e8c45fSAndroid Build Coastguard Worker }
262*38e8c45fSAndroid Build Coastguard Worker
clear()263*38e8c45fSAndroid Build Coastguard Worker void Region::clear()
264*38e8c45fSAndroid Build Coastguard Worker {
265*38e8c45fSAndroid Build Coastguard Worker mStorage.clear();
266*38e8c45fSAndroid Build Coastguard Worker mStorage.push_back(Rect(0, 0));
267*38e8c45fSAndroid Build Coastguard Worker }
268*38e8c45fSAndroid Build Coastguard Worker
set(const Rect & r)269*38e8c45fSAndroid Build Coastguard Worker void Region::set(const Rect& r)
270*38e8c45fSAndroid Build Coastguard Worker {
271*38e8c45fSAndroid Build Coastguard Worker mStorage.clear();
272*38e8c45fSAndroid Build Coastguard Worker mStorage.push_back(r);
273*38e8c45fSAndroid Build Coastguard Worker }
274*38e8c45fSAndroid Build Coastguard Worker
set(int32_t w,int32_t h)275*38e8c45fSAndroid Build Coastguard Worker void Region::set(int32_t w, int32_t h)
276*38e8c45fSAndroid Build Coastguard Worker {
277*38e8c45fSAndroid Build Coastguard Worker mStorage.clear();
278*38e8c45fSAndroid Build Coastguard Worker mStorage.push_back(Rect(w, h));
279*38e8c45fSAndroid Build Coastguard Worker }
280*38e8c45fSAndroid Build Coastguard Worker
set(uint32_t w,uint32_t h)281*38e8c45fSAndroid Build Coastguard Worker void Region::set(uint32_t w, uint32_t h)
282*38e8c45fSAndroid Build Coastguard Worker {
283*38e8c45fSAndroid Build Coastguard Worker mStorage.clear();
284*38e8c45fSAndroid Build Coastguard Worker mStorage.push_back(Rect(w, h));
285*38e8c45fSAndroid Build Coastguard Worker }
286*38e8c45fSAndroid Build Coastguard Worker
isTriviallyEqual(const Region & region) const287*38e8c45fSAndroid Build Coastguard Worker bool Region::isTriviallyEqual(const Region& region) const {
288*38e8c45fSAndroid Build Coastguard Worker return begin() == region.begin();
289*38e8c45fSAndroid Build Coastguard Worker }
290*38e8c45fSAndroid Build Coastguard Worker
hasSameRects(const Region & other) const291*38e8c45fSAndroid Build Coastguard Worker bool Region::hasSameRects(const Region& other) const {
292*38e8c45fSAndroid Build Coastguard Worker size_t thisRectCount = 0;
293*38e8c45fSAndroid Build Coastguard Worker android::Rect const* thisRects = getArray(&thisRectCount);
294*38e8c45fSAndroid Build Coastguard Worker size_t otherRectCount = 0;
295*38e8c45fSAndroid Build Coastguard Worker android::Rect const* otherRects = other.getArray(&otherRectCount);
296*38e8c45fSAndroid Build Coastguard Worker
297*38e8c45fSAndroid Build Coastguard Worker if (thisRectCount != otherRectCount) return false;
298*38e8c45fSAndroid Build Coastguard Worker
299*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < thisRectCount; i++) {
300*38e8c45fSAndroid Build Coastguard Worker if (thisRects[i] != otherRects[i]) return false;
301*38e8c45fSAndroid Build Coastguard Worker }
302*38e8c45fSAndroid Build Coastguard Worker return true;
303*38e8c45fSAndroid Build Coastguard Worker }
304*38e8c45fSAndroid Build Coastguard Worker
305*38e8c45fSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
306*38e8c45fSAndroid Build Coastguard Worker
addRectUnchecked(int l,int t,int r,int b)307*38e8c45fSAndroid Build Coastguard Worker void Region::addRectUnchecked(int l, int t, int r, int b)
308*38e8c45fSAndroid Build Coastguard Worker {
309*38e8c45fSAndroid Build Coastguard Worker Rect rect(l,t,r,b);
310*38e8c45fSAndroid Build Coastguard Worker mStorage.insert(mStorage.end() - 1, rect);
311*38e8c45fSAndroid Build Coastguard Worker }
312*38e8c45fSAndroid Build Coastguard Worker
313*38e8c45fSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
314*38e8c45fSAndroid Build Coastguard Worker
orSelf(const Rect & r)315*38e8c45fSAndroid Build Coastguard Worker Region& Region::orSelf(const Rect& r) {
316*38e8c45fSAndroid Build Coastguard Worker if (isEmpty()) {
317*38e8c45fSAndroid Build Coastguard Worker set(r);
318*38e8c45fSAndroid Build Coastguard Worker return *this;
319*38e8c45fSAndroid Build Coastguard Worker }
320*38e8c45fSAndroid Build Coastguard Worker return operationSelf(r, op_or);
321*38e8c45fSAndroid Build Coastguard Worker }
xorSelf(const Rect & r)322*38e8c45fSAndroid Build Coastguard Worker Region& Region::xorSelf(const Rect& r) {
323*38e8c45fSAndroid Build Coastguard Worker return operationSelf(r, op_xor);
324*38e8c45fSAndroid Build Coastguard Worker }
andSelf(const Rect & r)325*38e8c45fSAndroid Build Coastguard Worker Region& Region::andSelf(const Rect& r) {
326*38e8c45fSAndroid Build Coastguard Worker return operationSelf(r, op_and);
327*38e8c45fSAndroid Build Coastguard Worker }
subtractSelf(const Rect & r)328*38e8c45fSAndroid Build Coastguard Worker Region& Region::subtractSelf(const Rect& r) {
329*38e8c45fSAndroid Build Coastguard Worker return operationSelf(r, op_nand);
330*38e8c45fSAndroid Build Coastguard Worker }
operationSelf(const Rect & r,uint32_t op)331*38e8c45fSAndroid Build Coastguard Worker Region& Region::operationSelf(const Rect& r, uint32_t op) {
332*38e8c45fSAndroid Build Coastguard Worker Region lhs(*this);
333*38e8c45fSAndroid Build Coastguard Worker boolean_operation(op, *this, lhs, r);
334*38e8c45fSAndroid Build Coastguard Worker return *this;
335*38e8c45fSAndroid Build Coastguard Worker }
336*38e8c45fSAndroid Build Coastguard Worker
337*38e8c45fSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
338*38e8c45fSAndroid Build Coastguard Worker
orSelf(const Region & rhs)339*38e8c45fSAndroid Build Coastguard Worker Region& Region::orSelf(const Region& rhs) {
340*38e8c45fSAndroid Build Coastguard Worker if (isEmpty()) {
341*38e8c45fSAndroid Build Coastguard Worker *this = rhs;
342*38e8c45fSAndroid Build Coastguard Worker return *this;
343*38e8c45fSAndroid Build Coastguard Worker }
344*38e8c45fSAndroid Build Coastguard Worker return operationSelf(rhs, op_or);
345*38e8c45fSAndroid Build Coastguard Worker }
xorSelf(const Region & rhs)346*38e8c45fSAndroid Build Coastguard Worker Region& Region::xorSelf(const Region& rhs) {
347*38e8c45fSAndroid Build Coastguard Worker return operationSelf(rhs, op_xor);
348*38e8c45fSAndroid Build Coastguard Worker }
andSelf(const Region & rhs)349*38e8c45fSAndroid Build Coastguard Worker Region& Region::andSelf(const Region& rhs) {
350*38e8c45fSAndroid Build Coastguard Worker return operationSelf(rhs, op_and);
351*38e8c45fSAndroid Build Coastguard Worker }
subtractSelf(const Region & rhs)352*38e8c45fSAndroid Build Coastguard Worker Region& Region::subtractSelf(const Region& rhs) {
353*38e8c45fSAndroid Build Coastguard Worker return operationSelf(rhs, op_nand);
354*38e8c45fSAndroid Build Coastguard Worker }
operationSelf(const Region & rhs,uint32_t op)355*38e8c45fSAndroid Build Coastguard Worker Region& Region::operationSelf(const Region& rhs, uint32_t op) {
356*38e8c45fSAndroid Build Coastguard Worker Region lhs(*this);
357*38e8c45fSAndroid Build Coastguard Worker boolean_operation(op, *this, lhs, rhs);
358*38e8c45fSAndroid Build Coastguard Worker return *this;
359*38e8c45fSAndroid Build Coastguard Worker }
360*38e8c45fSAndroid Build Coastguard Worker
translateSelf(int x,int y)361*38e8c45fSAndroid Build Coastguard Worker Region& Region::translateSelf(int x, int y) {
362*38e8c45fSAndroid Build Coastguard Worker if (x|y) translate(*this, x, y);
363*38e8c45fSAndroid Build Coastguard Worker return *this;
364*38e8c45fSAndroid Build Coastguard Worker }
365*38e8c45fSAndroid Build Coastguard Worker
scaleSelf(float sx,float sy)366*38e8c45fSAndroid Build Coastguard Worker Region& Region::scaleSelf(float sx, float sy) {
367*38e8c45fSAndroid Build Coastguard Worker size_t count = mStorage.size();
368*38e8c45fSAndroid Build Coastguard Worker Rect* rects = mStorage.data();
369*38e8c45fSAndroid Build Coastguard Worker while (count) {
370*38e8c45fSAndroid Build Coastguard Worker rects->left = static_cast<int32_t>(static_cast<float>(rects->left) * sx + 0.5f);
371*38e8c45fSAndroid Build Coastguard Worker rects->right = static_cast<int32_t>(static_cast<float>(rects->right) * sx + 0.5f);
372*38e8c45fSAndroid Build Coastguard Worker rects->top = static_cast<int32_t>(static_cast<float>(rects->top) * sy + 0.5f);
373*38e8c45fSAndroid Build Coastguard Worker rects->bottom = static_cast<int32_t>(static_cast<float>(rects->bottom) * sy + 0.5f);
374*38e8c45fSAndroid Build Coastguard Worker rects++;
375*38e8c45fSAndroid Build Coastguard Worker count--;
376*38e8c45fSAndroid Build Coastguard Worker }
377*38e8c45fSAndroid Build Coastguard Worker return *this;
378*38e8c45fSAndroid Build Coastguard Worker }
379*38e8c45fSAndroid Build Coastguard Worker
380*38e8c45fSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
381*38e8c45fSAndroid Build Coastguard Worker
merge(const Rect & rhs) const382*38e8c45fSAndroid Build Coastguard Worker const Region Region::merge(const Rect& rhs) const {
383*38e8c45fSAndroid Build Coastguard Worker return operation(rhs, op_or);
384*38e8c45fSAndroid Build Coastguard Worker }
mergeExclusive(const Rect & rhs) const385*38e8c45fSAndroid Build Coastguard Worker const Region Region::mergeExclusive(const Rect& rhs) const {
386*38e8c45fSAndroid Build Coastguard Worker return operation(rhs, op_xor);
387*38e8c45fSAndroid Build Coastguard Worker }
intersect(const Rect & rhs) const388*38e8c45fSAndroid Build Coastguard Worker const Region Region::intersect(const Rect& rhs) const {
389*38e8c45fSAndroid Build Coastguard Worker return operation(rhs, op_and);
390*38e8c45fSAndroid Build Coastguard Worker }
subtract(const Rect & rhs) const391*38e8c45fSAndroid Build Coastguard Worker const Region Region::subtract(const Rect& rhs) const {
392*38e8c45fSAndroid Build Coastguard Worker return operation(rhs, op_nand);
393*38e8c45fSAndroid Build Coastguard Worker }
operation(const Rect & rhs,uint32_t op) const394*38e8c45fSAndroid Build Coastguard Worker const Region Region::operation(const Rect& rhs, uint32_t op) const {
395*38e8c45fSAndroid Build Coastguard Worker Region result;
396*38e8c45fSAndroid Build Coastguard Worker boolean_operation(op, result, *this, rhs);
397*38e8c45fSAndroid Build Coastguard Worker return result;
398*38e8c45fSAndroid Build Coastguard Worker }
399*38e8c45fSAndroid Build Coastguard Worker
400*38e8c45fSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
401*38e8c45fSAndroid Build Coastguard Worker
merge(const Region & rhs) const402*38e8c45fSAndroid Build Coastguard Worker const Region Region::merge(const Region& rhs) const {
403*38e8c45fSAndroid Build Coastguard Worker return operation(rhs, op_or);
404*38e8c45fSAndroid Build Coastguard Worker }
mergeExclusive(const Region & rhs) const405*38e8c45fSAndroid Build Coastguard Worker const Region Region::mergeExclusive(const Region& rhs) const {
406*38e8c45fSAndroid Build Coastguard Worker return operation(rhs, op_xor);
407*38e8c45fSAndroid Build Coastguard Worker }
intersect(const Region & rhs) const408*38e8c45fSAndroid Build Coastguard Worker const Region Region::intersect(const Region& rhs) const {
409*38e8c45fSAndroid Build Coastguard Worker return operation(rhs, op_and);
410*38e8c45fSAndroid Build Coastguard Worker }
subtract(const Region & rhs) const411*38e8c45fSAndroid Build Coastguard Worker const Region Region::subtract(const Region& rhs) const {
412*38e8c45fSAndroid Build Coastguard Worker return operation(rhs, op_nand);
413*38e8c45fSAndroid Build Coastguard Worker }
operation(const Region & rhs,uint32_t op) const414*38e8c45fSAndroid Build Coastguard Worker const Region Region::operation(const Region& rhs, uint32_t op) const {
415*38e8c45fSAndroid Build Coastguard Worker Region result;
416*38e8c45fSAndroid Build Coastguard Worker boolean_operation(op, result, *this, rhs);
417*38e8c45fSAndroid Build Coastguard Worker return result;
418*38e8c45fSAndroid Build Coastguard Worker }
419*38e8c45fSAndroid Build Coastguard Worker
translate(int x,int y) const420*38e8c45fSAndroid Build Coastguard Worker const Region Region::translate(int x, int y) const {
421*38e8c45fSAndroid Build Coastguard Worker Region result;
422*38e8c45fSAndroid Build Coastguard Worker translate(result, *this, x, y);
423*38e8c45fSAndroid Build Coastguard Worker return result;
424*38e8c45fSAndroid Build Coastguard Worker }
425*38e8c45fSAndroid Build Coastguard Worker
426*38e8c45fSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
427*38e8c45fSAndroid Build Coastguard Worker
orSelf(const Region & rhs,int dx,int dy)428*38e8c45fSAndroid Build Coastguard Worker Region& Region::orSelf(const Region& rhs, int dx, int dy) {
429*38e8c45fSAndroid Build Coastguard Worker return operationSelf(rhs, dx, dy, op_or);
430*38e8c45fSAndroid Build Coastguard Worker }
xorSelf(const Region & rhs,int dx,int dy)431*38e8c45fSAndroid Build Coastguard Worker Region& Region::xorSelf(const Region& rhs, int dx, int dy) {
432*38e8c45fSAndroid Build Coastguard Worker return operationSelf(rhs, dx, dy, op_xor);
433*38e8c45fSAndroid Build Coastguard Worker }
andSelf(const Region & rhs,int dx,int dy)434*38e8c45fSAndroid Build Coastguard Worker Region& Region::andSelf(const Region& rhs, int dx, int dy) {
435*38e8c45fSAndroid Build Coastguard Worker return operationSelf(rhs, dx, dy, op_and);
436*38e8c45fSAndroid Build Coastguard Worker }
subtractSelf(const Region & rhs,int dx,int dy)437*38e8c45fSAndroid Build Coastguard Worker Region& Region::subtractSelf(const Region& rhs, int dx, int dy) {
438*38e8c45fSAndroid Build Coastguard Worker return operationSelf(rhs, dx, dy, op_nand);
439*38e8c45fSAndroid Build Coastguard Worker }
operationSelf(const Region & rhs,int dx,int dy,uint32_t op)440*38e8c45fSAndroid Build Coastguard Worker Region& Region::operationSelf(const Region& rhs, int dx, int dy, uint32_t op) {
441*38e8c45fSAndroid Build Coastguard Worker Region lhs(*this);
442*38e8c45fSAndroid Build Coastguard Worker boolean_operation(op, *this, lhs, rhs, dx, dy);
443*38e8c45fSAndroid Build Coastguard Worker return *this;
444*38e8c45fSAndroid Build Coastguard Worker }
445*38e8c45fSAndroid Build Coastguard Worker
446*38e8c45fSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
447*38e8c45fSAndroid Build Coastguard Worker
merge(const Region & rhs,int dx,int dy) const448*38e8c45fSAndroid Build Coastguard Worker const Region Region::merge(const Region& rhs, int dx, int dy) const {
449*38e8c45fSAndroid Build Coastguard Worker return operation(rhs, dx, dy, op_or);
450*38e8c45fSAndroid Build Coastguard Worker }
mergeExclusive(const Region & rhs,int dx,int dy) const451*38e8c45fSAndroid Build Coastguard Worker const Region Region::mergeExclusive(const Region& rhs, int dx, int dy) const {
452*38e8c45fSAndroid Build Coastguard Worker return operation(rhs, dx, dy, op_xor);
453*38e8c45fSAndroid Build Coastguard Worker }
intersect(const Region & rhs,int dx,int dy) const454*38e8c45fSAndroid Build Coastguard Worker const Region Region::intersect(const Region& rhs, int dx, int dy) const {
455*38e8c45fSAndroid Build Coastguard Worker return operation(rhs, dx, dy, op_and);
456*38e8c45fSAndroid Build Coastguard Worker }
subtract(const Region & rhs,int dx,int dy) const457*38e8c45fSAndroid Build Coastguard Worker const Region Region::subtract(const Region& rhs, int dx, int dy) const {
458*38e8c45fSAndroid Build Coastguard Worker return operation(rhs, dx, dy, op_nand);
459*38e8c45fSAndroid Build Coastguard Worker }
operation(const Region & rhs,int dx,int dy,uint32_t op) const460*38e8c45fSAndroid Build Coastguard Worker const Region Region::operation(const Region& rhs, int dx, int dy, uint32_t op) const {
461*38e8c45fSAndroid Build Coastguard Worker Region result;
462*38e8c45fSAndroid Build Coastguard Worker boolean_operation(op, result, *this, rhs, dx, dy);
463*38e8c45fSAndroid Build Coastguard Worker return result;
464*38e8c45fSAndroid Build Coastguard Worker }
465*38e8c45fSAndroid Build Coastguard Worker
466*38e8c45fSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
467*38e8c45fSAndroid Build Coastguard Worker
468*38e8c45fSAndroid Build Coastguard Worker // This is our region rasterizer, which merges rects and spans together
469*38e8c45fSAndroid Build Coastguard Worker // to obtain an optimal region.
470*38e8c45fSAndroid Build Coastguard Worker class Region::rasterizer : public region_operator<Rect>::region_rasterizer
471*38e8c45fSAndroid Build Coastguard Worker {
472*38e8c45fSAndroid Build Coastguard Worker Rect bounds;
473*38e8c45fSAndroid Build Coastguard Worker FatVector<Rect>& storage;
474*38e8c45fSAndroid Build Coastguard Worker Rect* head;
475*38e8c45fSAndroid Build Coastguard Worker Rect* tail;
476*38e8c45fSAndroid Build Coastguard Worker FatVector<Rect> span;
477*38e8c45fSAndroid Build Coastguard Worker Rect* cur;
478*38e8c45fSAndroid Build Coastguard Worker public:
rasterizer(Region & reg)479*38e8c45fSAndroid Build Coastguard Worker explicit rasterizer(Region& reg)
480*38e8c45fSAndroid Build Coastguard Worker : bounds(INT_MAX, 0, INT_MIN, 0), storage(reg.mStorage), head(), tail(), cur() {
481*38e8c45fSAndroid Build Coastguard Worker storage.clear();
482*38e8c45fSAndroid Build Coastguard Worker }
483*38e8c45fSAndroid Build Coastguard Worker
484*38e8c45fSAndroid Build Coastguard Worker virtual ~rasterizer();
485*38e8c45fSAndroid Build Coastguard Worker
486*38e8c45fSAndroid Build Coastguard Worker virtual void operator()(const Rect& rect);
487*38e8c45fSAndroid Build Coastguard Worker
488*38e8c45fSAndroid Build Coastguard Worker private:
489*38e8c45fSAndroid Build Coastguard Worker template<typename T>
min(T rhs,T lhs)490*38e8c45fSAndroid Build Coastguard Worker static inline T min(T rhs, T lhs) { return rhs < lhs ? rhs : lhs; }
491*38e8c45fSAndroid Build Coastguard Worker template<typename T>
max(T rhs,T lhs)492*38e8c45fSAndroid Build Coastguard Worker static inline T max(T rhs, T lhs) { return rhs > lhs ? rhs : lhs; }
493*38e8c45fSAndroid Build Coastguard Worker
494*38e8c45fSAndroid Build Coastguard Worker void flushSpan();
495*38e8c45fSAndroid Build Coastguard Worker };
496*38e8c45fSAndroid Build Coastguard Worker
~rasterizer()497*38e8c45fSAndroid Build Coastguard Worker Region::rasterizer::~rasterizer()
498*38e8c45fSAndroid Build Coastguard Worker {
499*38e8c45fSAndroid Build Coastguard Worker if (span.size()) {
500*38e8c45fSAndroid Build Coastguard Worker flushSpan();
501*38e8c45fSAndroid Build Coastguard Worker }
502*38e8c45fSAndroid Build Coastguard Worker if (storage.size()) {
503*38e8c45fSAndroid Build Coastguard Worker bounds.top = storage.front().top;
504*38e8c45fSAndroid Build Coastguard Worker bounds.bottom = storage.back().bottom;
505*38e8c45fSAndroid Build Coastguard Worker if (storage.size() == 1) {
506*38e8c45fSAndroid Build Coastguard Worker storage.clear();
507*38e8c45fSAndroid Build Coastguard Worker }
508*38e8c45fSAndroid Build Coastguard Worker } else {
509*38e8c45fSAndroid Build Coastguard Worker bounds.left = 0;
510*38e8c45fSAndroid Build Coastguard Worker bounds.right = 0;
511*38e8c45fSAndroid Build Coastguard Worker }
512*38e8c45fSAndroid Build Coastguard Worker storage.push_back(bounds);
513*38e8c45fSAndroid Build Coastguard Worker }
514*38e8c45fSAndroid Build Coastguard Worker
operator ()(const Rect & rect)515*38e8c45fSAndroid Build Coastguard Worker void Region::rasterizer::operator()(const Rect& rect)
516*38e8c45fSAndroid Build Coastguard Worker {
517*38e8c45fSAndroid Build Coastguard Worker //ALOGD(">>> %3d, %3d, %3d, %3d",
518*38e8c45fSAndroid Build Coastguard Worker // rect.left, rect.top, rect.right, rect.bottom);
519*38e8c45fSAndroid Build Coastguard Worker if (span.size()) {
520*38e8c45fSAndroid Build Coastguard Worker if (cur->top != rect.top) {
521*38e8c45fSAndroid Build Coastguard Worker flushSpan();
522*38e8c45fSAndroid Build Coastguard Worker } else if (cur->right == rect.left) {
523*38e8c45fSAndroid Build Coastguard Worker cur->right = rect.right;
524*38e8c45fSAndroid Build Coastguard Worker return;
525*38e8c45fSAndroid Build Coastguard Worker }
526*38e8c45fSAndroid Build Coastguard Worker }
527*38e8c45fSAndroid Build Coastguard Worker span.push_back(rect);
528*38e8c45fSAndroid Build Coastguard Worker cur = span.data() + (span.size() - 1);
529*38e8c45fSAndroid Build Coastguard Worker }
530*38e8c45fSAndroid Build Coastguard Worker
flushSpan()531*38e8c45fSAndroid Build Coastguard Worker void Region::rasterizer::flushSpan()
532*38e8c45fSAndroid Build Coastguard Worker {
533*38e8c45fSAndroid Build Coastguard Worker bool merge = false;
534*38e8c45fSAndroid Build Coastguard Worker if (tail-head == ssize_t(span.size())) {
535*38e8c45fSAndroid Build Coastguard Worker Rect const* p = span.data();
536*38e8c45fSAndroid Build Coastguard Worker Rect const* q = head;
537*38e8c45fSAndroid Build Coastguard Worker if (p->top == q->bottom) {
538*38e8c45fSAndroid Build Coastguard Worker merge = true;
539*38e8c45fSAndroid Build Coastguard Worker while (q != tail) {
540*38e8c45fSAndroid Build Coastguard Worker if ((p->left != q->left) || (p->right != q->right)) {
541*38e8c45fSAndroid Build Coastguard Worker merge = false;
542*38e8c45fSAndroid Build Coastguard Worker break;
543*38e8c45fSAndroid Build Coastguard Worker }
544*38e8c45fSAndroid Build Coastguard Worker p++;
545*38e8c45fSAndroid Build Coastguard Worker q++;
546*38e8c45fSAndroid Build Coastguard Worker }
547*38e8c45fSAndroid Build Coastguard Worker }
548*38e8c45fSAndroid Build Coastguard Worker }
549*38e8c45fSAndroid Build Coastguard Worker if (merge) {
550*38e8c45fSAndroid Build Coastguard Worker const int bottom = span.front().bottom;
551*38e8c45fSAndroid Build Coastguard Worker Rect* r = head;
552*38e8c45fSAndroid Build Coastguard Worker while (r != tail) {
553*38e8c45fSAndroid Build Coastguard Worker r->bottom = bottom;
554*38e8c45fSAndroid Build Coastguard Worker r++;
555*38e8c45fSAndroid Build Coastguard Worker }
556*38e8c45fSAndroid Build Coastguard Worker } else {
557*38e8c45fSAndroid Build Coastguard Worker bounds.left = min(span.front().left, bounds.left);
558*38e8c45fSAndroid Build Coastguard Worker bounds.right = max(span.back().right, bounds.right);
559*38e8c45fSAndroid Build Coastguard Worker storage.insert(storage.end(), span.begin(), span.end());
560*38e8c45fSAndroid Build Coastguard Worker tail = storage.data() + storage.size();
561*38e8c45fSAndroid Build Coastguard Worker head = tail - span.size();
562*38e8c45fSAndroid Build Coastguard Worker }
563*38e8c45fSAndroid Build Coastguard Worker span.clear();
564*38e8c45fSAndroid Build Coastguard Worker }
565*38e8c45fSAndroid Build Coastguard Worker
validate(const Region & reg,const char * name,bool silent)566*38e8c45fSAndroid Build Coastguard Worker bool Region::validate(const Region& reg, const char* name, bool silent)
567*38e8c45fSAndroid Build Coastguard Worker {
568*38e8c45fSAndroid Build Coastguard Worker if (reg.mStorage.empty()) {
569*38e8c45fSAndroid Build Coastguard Worker ALOGE_IF(!silent, "%s: mStorage is empty, which is never valid", name);
570*38e8c45fSAndroid Build Coastguard Worker // return immediately as the code below assumes mStorage is non-empty
571*38e8c45fSAndroid Build Coastguard Worker return false;
572*38e8c45fSAndroid Build Coastguard Worker }
573*38e8c45fSAndroid Build Coastguard Worker
574*38e8c45fSAndroid Build Coastguard Worker bool result = true;
575*38e8c45fSAndroid Build Coastguard Worker const_iterator cur = reg.begin();
576*38e8c45fSAndroid Build Coastguard Worker const_iterator const tail = reg.end();
577*38e8c45fSAndroid Build Coastguard Worker const_iterator prev = cur;
578*38e8c45fSAndroid Build Coastguard Worker Rect b(*prev);
579*38e8c45fSAndroid Build Coastguard Worker while (cur != tail) {
580*38e8c45fSAndroid Build Coastguard Worker if (cur->isValid() == false) {
581*38e8c45fSAndroid Build Coastguard Worker // We allow this particular flavor of invalid Rect, since it is used
582*38e8c45fSAndroid Build Coastguard Worker // as a signal value in various parts of the system
583*38e8c45fSAndroid Build Coastguard Worker if (*cur != Rect::INVALID_RECT) {
584*38e8c45fSAndroid Build Coastguard Worker ALOGE_IF(!silent, "%s: region contains an invalid Rect", name);
585*38e8c45fSAndroid Build Coastguard Worker result = false;
586*38e8c45fSAndroid Build Coastguard Worker }
587*38e8c45fSAndroid Build Coastguard Worker }
588*38e8c45fSAndroid Build Coastguard Worker if (cur->right > region_operator<Rect>::max_value) {
589*38e8c45fSAndroid Build Coastguard Worker ALOGE_IF(!silent, "%s: rect->right > max_value", name);
590*38e8c45fSAndroid Build Coastguard Worker result = false;
591*38e8c45fSAndroid Build Coastguard Worker }
592*38e8c45fSAndroid Build Coastguard Worker if (cur->bottom > region_operator<Rect>::max_value) {
593*38e8c45fSAndroid Build Coastguard Worker ALOGE_IF(!silent, "%s: rect->right > max_value", name);
594*38e8c45fSAndroid Build Coastguard Worker result = false;
595*38e8c45fSAndroid Build Coastguard Worker }
596*38e8c45fSAndroid Build Coastguard Worker if (prev != cur) {
597*38e8c45fSAndroid Build Coastguard Worker b.left = b.left < cur->left ? b.left : cur->left;
598*38e8c45fSAndroid Build Coastguard Worker b.top = b.top < cur->top ? b.top : cur->top;
599*38e8c45fSAndroid Build Coastguard Worker b.right = b.right > cur->right ? b.right : cur->right;
600*38e8c45fSAndroid Build Coastguard Worker b.bottom = b.bottom > cur->bottom ? b.bottom : cur->bottom;
601*38e8c45fSAndroid Build Coastguard Worker if ((*prev < *cur) == false) {
602*38e8c45fSAndroid Build Coastguard Worker ALOGE_IF(!silent, "%s: region's Rects not sorted", name);
603*38e8c45fSAndroid Build Coastguard Worker result = false;
604*38e8c45fSAndroid Build Coastguard Worker }
605*38e8c45fSAndroid Build Coastguard Worker if (cur->top == prev->top) {
606*38e8c45fSAndroid Build Coastguard Worker if (cur->bottom != prev->bottom) {
607*38e8c45fSAndroid Build Coastguard Worker ALOGE_IF(!silent, "%s: invalid span %p", name, cur);
608*38e8c45fSAndroid Build Coastguard Worker result = false;
609*38e8c45fSAndroid Build Coastguard Worker } else if (cur->left < prev->right) {
610*38e8c45fSAndroid Build Coastguard Worker ALOGE_IF(!silent,
611*38e8c45fSAndroid Build Coastguard Worker "%s: spans overlap horizontally prev=%p, cur=%p",
612*38e8c45fSAndroid Build Coastguard Worker name, prev, cur);
613*38e8c45fSAndroid Build Coastguard Worker result = false;
614*38e8c45fSAndroid Build Coastguard Worker }
615*38e8c45fSAndroid Build Coastguard Worker } else if (cur->top < prev->bottom) {
616*38e8c45fSAndroid Build Coastguard Worker ALOGE_IF(!silent,
617*38e8c45fSAndroid Build Coastguard Worker "%s: spans overlap vertically prev=%p, cur=%p",
618*38e8c45fSAndroid Build Coastguard Worker name, prev, cur);
619*38e8c45fSAndroid Build Coastguard Worker result = false;
620*38e8c45fSAndroid Build Coastguard Worker }
621*38e8c45fSAndroid Build Coastguard Worker prev = cur;
622*38e8c45fSAndroid Build Coastguard Worker }
623*38e8c45fSAndroid Build Coastguard Worker cur++;
624*38e8c45fSAndroid Build Coastguard Worker }
625*38e8c45fSAndroid Build Coastguard Worker if (b != reg.getBounds()) {
626*38e8c45fSAndroid Build Coastguard Worker result = false;
627*38e8c45fSAndroid Build Coastguard Worker ALOGE_IF(!silent,
628*38e8c45fSAndroid Build Coastguard Worker "%s: invalid bounds [%d,%d,%d,%d] vs. [%d,%d,%d,%d]", name,
629*38e8c45fSAndroid Build Coastguard Worker b.left, b.top, b.right, b.bottom,
630*38e8c45fSAndroid Build Coastguard Worker reg.getBounds().left, reg.getBounds().top,
631*38e8c45fSAndroid Build Coastguard Worker reg.getBounds().right, reg.getBounds().bottom);
632*38e8c45fSAndroid Build Coastguard Worker }
633*38e8c45fSAndroid Build Coastguard Worker if (reg.mStorage.size() == 2) {
634*38e8c45fSAndroid Build Coastguard Worker result = false;
635*38e8c45fSAndroid Build Coastguard Worker ALOGE_IF(!silent, "%s: mStorage size is 2, which is never valid", name);
636*38e8c45fSAndroid Build Coastguard Worker }
637*38e8c45fSAndroid Build Coastguard Worker #if defined(VALIDATE_REGIONS)
638*38e8c45fSAndroid Build Coastguard Worker if (result == false && !silent) {
639*38e8c45fSAndroid Build Coastguard Worker reg.dump(name);
640*38e8c45fSAndroid Build Coastguard Worker CallStack stack(LOG_TAG);
641*38e8c45fSAndroid Build Coastguard Worker }
642*38e8c45fSAndroid Build Coastguard Worker #endif
643*38e8c45fSAndroid Build Coastguard Worker return result;
644*38e8c45fSAndroid Build Coastguard Worker }
645*38e8c45fSAndroid Build Coastguard Worker
boolean_operation(uint32_t op,Region & dst,const Region & lhs,const Region & rhs,int dx,int dy)646*38e8c45fSAndroid Build Coastguard Worker void Region::boolean_operation(uint32_t op, Region& dst,
647*38e8c45fSAndroid Build Coastguard Worker const Region& lhs,
648*38e8c45fSAndroid Build Coastguard Worker const Region& rhs, int dx, int dy)
649*38e8c45fSAndroid Build Coastguard Worker {
650*38e8c45fSAndroid Build Coastguard Worker #if defined(VALIDATE_REGIONS)
651*38e8c45fSAndroid Build Coastguard Worker validate(lhs, "boolean_operation (before): lhs");
652*38e8c45fSAndroid Build Coastguard Worker validate(rhs, "boolean_operation (before): rhs");
653*38e8c45fSAndroid Build Coastguard Worker validate(dst, "boolean_operation (before): dst");
654*38e8c45fSAndroid Build Coastguard Worker #endif
655*38e8c45fSAndroid Build Coastguard Worker
656*38e8c45fSAndroid Build Coastguard Worker size_t lhs_count;
657*38e8c45fSAndroid Build Coastguard Worker Rect const * const lhs_rects = lhs.getArray(&lhs_count);
658*38e8c45fSAndroid Build Coastguard Worker
659*38e8c45fSAndroid Build Coastguard Worker size_t rhs_count;
660*38e8c45fSAndroid Build Coastguard Worker Rect const * const rhs_rects = rhs.getArray(&rhs_count);
661*38e8c45fSAndroid Build Coastguard Worker
662*38e8c45fSAndroid Build Coastguard Worker region_operator<Rect>::region lhs_region(lhs_rects, lhs_count);
663*38e8c45fSAndroid Build Coastguard Worker region_operator<Rect>::region rhs_region(rhs_rects, rhs_count, dx, dy);
664*38e8c45fSAndroid Build Coastguard Worker region_operator<Rect> operation(op, lhs_region, rhs_region);
665*38e8c45fSAndroid Build Coastguard Worker { // scope for rasterizer (dtor has side effects)
666*38e8c45fSAndroid Build Coastguard Worker rasterizer r(dst);
667*38e8c45fSAndroid Build Coastguard Worker operation(r);
668*38e8c45fSAndroid Build Coastguard Worker }
669*38e8c45fSAndroid Build Coastguard Worker
670*38e8c45fSAndroid Build Coastguard Worker #if defined(VALIDATE_REGIONS)
671*38e8c45fSAndroid Build Coastguard Worker validate(lhs, "boolean_operation: lhs");
672*38e8c45fSAndroid Build Coastguard Worker validate(rhs, "boolean_operation: rhs");
673*38e8c45fSAndroid Build Coastguard Worker validate(dst, "boolean_operation: dst");
674*38e8c45fSAndroid Build Coastguard Worker #endif
675*38e8c45fSAndroid Build Coastguard Worker
676*38e8c45fSAndroid Build Coastguard Worker #if VALIDATE_WITH_CORECG
677*38e8c45fSAndroid Build Coastguard Worker SkRegion sk_lhs;
678*38e8c45fSAndroid Build Coastguard Worker SkRegion sk_rhs;
679*38e8c45fSAndroid Build Coastguard Worker SkRegion sk_dst;
680*38e8c45fSAndroid Build Coastguard Worker
681*38e8c45fSAndroid Build Coastguard Worker for (size_t i=0 ; i<lhs_count ; i++)
682*38e8c45fSAndroid Build Coastguard Worker sk_lhs.op(
683*38e8c45fSAndroid Build Coastguard Worker lhs_rects[i].left + dx,
684*38e8c45fSAndroid Build Coastguard Worker lhs_rects[i].top + dy,
685*38e8c45fSAndroid Build Coastguard Worker lhs_rects[i].right + dx,
686*38e8c45fSAndroid Build Coastguard Worker lhs_rects[i].bottom + dy,
687*38e8c45fSAndroid Build Coastguard Worker SkRegion::kUnion_Op);
688*38e8c45fSAndroid Build Coastguard Worker
689*38e8c45fSAndroid Build Coastguard Worker for (size_t i=0 ; i<rhs_count ; i++)
690*38e8c45fSAndroid Build Coastguard Worker sk_rhs.op(
691*38e8c45fSAndroid Build Coastguard Worker rhs_rects[i].left + dx,
692*38e8c45fSAndroid Build Coastguard Worker rhs_rects[i].top + dy,
693*38e8c45fSAndroid Build Coastguard Worker rhs_rects[i].right + dx,
694*38e8c45fSAndroid Build Coastguard Worker rhs_rects[i].bottom + dy,
695*38e8c45fSAndroid Build Coastguard Worker SkRegion::kUnion_Op);
696*38e8c45fSAndroid Build Coastguard Worker
697*38e8c45fSAndroid Build Coastguard Worker const char* name = "---";
698*38e8c45fSAndroid Build Coastguard Worker SkRegion::Op sk_op;
699*38e8c45fSAndroid Build Coastguard Worker switch (op) {
700*38e8c45fSAndroid Build Coastguard Worker case op_or: sk_op = SkRegion::kUnion_Op; name="OR"; break;
701*38e8c45fSAndroid Build Coastguard Worker case op_xor: sk_op = SkRegion::kUnion_XOR; name="XOR"; break;
702*38e8c45fSAndroid Build Coastguard Worker case op_and: sk_op = SkRegion::kIntersect_Op; name="AND"; break;
703*38e8c45fSAndroid Build Coastguard Worker case op_nand: sk_op = SkRegion::kDifference_Op; name="NAND"; break;
704*38e8c45fSAndroid Build Coastguard Worker }
705*38e8c45fSAndroid Build Coastguard Worker sk_dst.op(sk_lhs, sk_rhs, sk_op);
706*38e8c45fSAndroid Build Coastguard Worker
707*38e8c45fSAndroid Build Coastguard Worker if (sk_dst.empty() && dst.empty()) return;
708*38e8c45fSAndroid Build Coastguard Worker
709*38e8c45fSAndroid Build Coastguard Worker bool same = true;
710*38e8c45fSAndroid Build Coastguard Worker Region::const_iterator head = dst.begin();
711*38e8c45fSAndroid Build Coastguard Worker Region::const_iterator const tail = dst.end();
712*38e8c45fSAndroid Build Coastguard Worker SkRegion::Iterator it(sk_dst);
713*38e8c45fSAndroid Build Coastguard Worker while (!it.done()) {
714*38e8c45fSAndroid Build Coastguard Worker if (head != tail) {
715*38e8c45fSAndroid Build Coastguard Worker if (
716*38e8c45fSAndroid Build Coastguard Worker head->left != it.rect().fLeft ||
717*38e8c45fSAndroid Build Coastguard Worker head->top != it.rect().fTop ||
718*38e8c45fSAndroid Build Coastguard Worker head->right != it.rect().fRight ||
719*38e8c45fSAndroid Build Coastguard Worker head->bottom != it.rect().fBottom
720*38e8c45fSAndroid Build Coastguard Worker ) {
721*38e8c45fSAndroid Build Coastguard Worker same = false;
722*38e8c45fSAndroid Build Coastguard Worker break;
723*38e8c45fSAndroid Build Coastguard Worker }
724*38e8c45fSAndroid Build Coastguard Worker } else {
725*38e8c45fSAndroid Build Coastguard Worker same = false;
726*38e8c45fSAndroid Build Coastguard Worker break;
727*38e8c45fSAndroid Build Coastguard Worker }
728*38e8c45fSAndroid Build Coastguard Worker head++;
729*38e8c45fSAndroid Build Coastguard Worker it.next();
730*38e8c45fSAndroid Build Coastguard Worker }
731*38e8c45fSAndroid Build Coastguard Worker
732*38e8c45fSAndroid Build Coastguard Worker if (head != tail) {
733*38e8c45fSAndroid Build Coastguard Worker same = false;
734*38e8c45fSAndroid Build Coastguard Worker }
735*38e8c45fSAndroid Build Coastguard Worker
736*38e8c45fSAndroid Build Coastguard Worker if(!same) {
737*38e8c45fSAndroid Build Coastguard Worker ALOGD("---\nregion boolean %s failed", name);
738*38e8c45fSAndroid Build Coastguard Worker lhs.dump("lhs");
739*38e8c45fSAndroid Build Coastguard Worker rhs.dump("rhs");
740*38e8c45fSAndroid Build Coastguard Worker dst.dump("dst");
741*38e8c45fSAndroid Build Coastguard Worker ALOGD("should be");
742*38e8c45fSAndroid Build Coastguard Worker SkRegion::Iterator it(sk_dst);
743*38e8c45fSAndroid Build Coastguard Worker while (!it.done()) {
744*38e8c45fSAndroid Build Coastguard Worker ALOGD(" [%3d, %3d, %3d, %3d]",
745*38e8c45fSAndroid Build Coastguard Worker it.rect().fLeft,
746*38e8c45fSAndroid Build Coastguard Worker it.rect().fTop,
747*38e8c45fSAndroid Build Coastguard Worker it.rect().fRight,
748*38e8c45fSAndroid Build Coastguard Worker it.rect().fBottom);
749*38e8c45fSAndroid Build Coastguard Worker it.next();
750*38e8c45fSAndroid Build Coastguard Worker }
751*38e8c45fSAndroid Build Coastguard Worker }
752*38e8c45fSAndroid Build Coastguard Worker #endif
753*38e8c45fSAndroid Build Coastguard Worker }
754*38e8c45fSAndroid Build Coastguard Worker
boolean_operation(uint32_t op,Region & dst,const Region & lhs,const Rect & rhs,int dx,int dy)755*38e8c45fSAndroid Build Coastguard Worker void Region::boolean_operation(uint32_t op, Region& dst,
756*38e8c45fSAndroid Build Coastguard Worker const Region& lhs,
757*38e8c45fSAndroid Build Coastguard Worker const Rect& rhs, int dx, int dy)
758*38e8c45fSAndroid Build Coastguard Worker {
759*38e8c45fSAndroid Build Coastguard Worker // We allow this particular flavor of invalid Rect, since it is used as a
760*38e8c45fSAndroid Build Coastguard Worker // signal value in various parts of the system
761*38e8c45fSAndroid Build Coastguard Worker if (!rhs.isValid() && rhs != Rect::INVALID_RECT) {
762*38e8c45fSAndroid Build Coastguard Worker ALOGE("Region::boolean_operation(op=%d) invalid Rect={%d,%d,%d,%d}",
763*38e8c45fSAndroid Build Coastguard Worker op, rhs.left, rhs.top, rhs.right, rhs.bottom);
764*38e8c45fSAndroid Build Coastguard Worker return;
765*38e8c45fSAndroid Build Coastguard Worker }
766*38e8c45fSAndroid Build Coastguard Worker
767*38e8c45fSAndroid Build Coastguard Worker #if VALIDATE_WITH_CORECG || defined(VALIDATE_REGIONS)
768*38e8c45fSAndroid Build Coastguard Worker boolean_operation(op, dst, lhs, Region(rhs), dx, dy);
769*38e8c45fSAndroid Build Coastguard Worker #else
770*38e8c45fSAndroid Build Coastguard Worker size_t lhs_count;
771*38e8c45fSAndroid Build Coastguard Worker Rect const * const lhs_rects = lhs.getArray(&lhs_count);
772*38e8c45fSAndroid Build Coastguard Worker
773*38e8c45fSAndroid Build Coastguard Worker region_operator<Rect>::region lhs_region(lhs_rects, lhs_count);
774*38e8c45fSAndroid Build Coastguard Worker region_operator<Rect>::region rhs_region(&rhs, 1, dx, dy);
775*38e8c45fSAndroid Build Coastguard Worker region_operator<Rect> operation(op, lhs_region, rhs_region);
776*38e8c45fSAndroid Build Coastguard Worker { // scope for rasterizer (dtor has side effects)
777*38e8c45fSAndroid Build Coastguard Worker rasterizer r(dst);
778*38e8c45fSAndroid Build Coastguard Worker operation(r);
779*38e8c45fSAndroid Build Coastguard Worker }
780*38e8c45fSAndroid Build Coastguard Worker
781*38e8c45fSAndroid Build Coastguard Worker #endif
782*38e8c45fSAndroid Build Coastguard Worker }
783*38e8c45fSAndroid Build Coastguard Worker
boolean_operation(uint32_t op,Region & dst,const Region & lhs,const Region & rhs)784*38e8c45fSAndroid Build Coastguard Worker void Region::boolean_operation(uint32_t op, Region& dst,
785*38e8c45fSAndroid Build Coastguard Worker const Region& lhs, const Region& rhs)
786*38e8c45fSAndroid Build Coastguard Worker {
787*38e8c45fSAndroid Build Coastguard Worker boolean_operation(op, dst, lhs, rhs, 0, 0);
788*38e8c45fSAndroid Build Coastguard Worker }
789*38e8c45fSAndroid Build Coastguard Worker
boolean_operation(uint32_t op,Region & dst,const Region & lhs,const Rect & rhs)790*38e8c45fSAndroid Build Coastguard Worker void Region::boolean_operation(uint32_t op, Region& dst,
791*38e8c45fSAndroid Build Coastguard Worker const Region& lhs, const Rect& rhs)
792*38e8c45fSAndroid Build Coastguard Worker {
793*38e8c45fSAndroid Build Coastguard Worker boolean_operation(op, dst, lhs, rhs, 0, 0);
794*38e8c45fSAndroid Build Coastguard Worker }
795*38e8c45fSAndroid Build Coastguard Worker
translate(Region & reg,int dx,int dy)796*38e8c45fSAndroid Build Coastguard Worker void Region::translate(Region& reg, int dx, int dy)
797*38e8c45fSAndroid Build Coastguard Worker {
798*38e8c45fSAndroid Build Coastguard Worker if ((dx || dy) && !reg.isEmpty()) {
799*38e8c45fSAndroid Build Coastguard Worker #if defined(VALIDATE_REGIONS)
800*38e8c45fSAndroid Build Coastguard Worker validate(reg, "translate (before)");
801*38e8c45fSAndroid Build Coastguard Worker #endif
802*38e8c45fSAndroid Build Coastguard Worker size_t count = reg.mStorage.size();
803*38e8c45fSAndroid Build Coastguard Worker Rect* rects = reg.mStorage.data();
804*38e8c45fSAndroid Build Coastguard Worker while (count) {
805*38e8c45fSAndroid Build Coastguard Worker rects->offsetBy(dx, dy);
806*38e8c45fSAndroid Build Coastguard Worker rects++;
807*38e8c45fSAndroid Build Coastguard Worker count--;
808*38e8c45fSAndroid Build Coastguard Worker }
809*38e8c45fSAndroid Build Coastguard Worker #if defined(VALIDATE_REGIONS)
810*38e8c45fSAndroid Build Coastguard Worker validate(reg, "translate (after)");
811*38e8c45fSAndroid Build Coastguard Worker #endif
812*38e8c45fSAndroid Build Coastguard Worker }
813*38e8c45fSAndroid Build Coastguard Worker }
814*38e8c45fSAndroid Build Coastguard Worker
translate(Region & dst,const Region & reg,int dx,int dy)815*38e8c45fSAndroid Build Coastguard Worker void Region::translate(Region& dst, const Region& reg, int dx, int dy)
816*38e8c45fSAndroid Build Coastguard Worker {
817*38e8c45fSAndroid Build Coastguard Worker dst = reg;
818*38e8c45fSAndroid Build Coastguard Worker translate(dst, dx, dy);
819*38e8c45fSAndroid Build Coastguard Worker }
820*38e8c45fSAndroid Build Coastguard Worker
821*38e8c45fSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
822*38e8c45fSAndroid Build Coastguard Worker
getFlattenedSize() const823*38e8c45fSAndroid Build Coastguard Worker size_t Region::getFlattenedSize() const {
824*38e8c45fSAndroid Build Coastguard Worker return sizeof(uint32_t) + mStorage.size() * sizeof(Rect);
825*38e8c45fSAndroid Build Coastguard Worker }
826*38e8c45fSAndroid Build Coastguard Worker
flatten(void * buffer,size_t size) const827*38e8c45fSAndroid Build Coastguard Worker status_t Region::flatten(void* buffer, size_t size) const {
828*38e8c45fSAndroid Build Coastguard Worker #if defined(VALIDATE_REGIONS)
829*38e8c45fSAndroid Build Coastguard Worker validate(*this, "Region::flatten");
830*38e8c45fSAndroid Build Coastguard Worker #endif
831*38e8c45fSAndroid Build Coastguard Worker if (size < getFlattenedSize()) {
832*38e8c45fSAndroid Build Coastguard Worker return NO_MEMORY;
833*38e8c45fSAndroid Build Coastguard Worker }
834*38e8c45fSAndroid Build Coastguard Worker // Cast to uint32_t since the size of a size_t can vary between 32- and
835*38e8c45fSAndroid Build Coastguard Worker // 64-bit processes
836*38e8c45fSAndroid Build Coastguard Worker FlattenableUtils::write(buffer, size, static_cast<uint32_t>(mStorage.size()));
837*38e8c45fSAndroid Build Coastguard Worker for (auto rect : mStorage) {
838*38e8c45fSAndroid Build Coastguard Worker status_t result = rect.flatten(buffer, size);
839*38e8c45fSAndroid Build Coastguard Worker if (result != NO_ERROR) {
840*38e8c45fSAndroid Build Coastguard Worker return result;
841*38e8c45fSAndroid Build Coastguard Worker }
842*38e8c45fSAndroid Build Coastguard Worker FlattenableUtils::advance(buffer, size, sizeof(rect));
843*38e8c45fSAndroid Build Coastguard Worker }
844*38e8c45fSAndroid Build Coastguard Worker return NO_ERROR;
845*38e8c45fSAndroid Build Coastguard Worker }
846*38e8c45fSAndroid Build Coastguard Worker
unflatten(void const * buffer,size_t size)847*38e8c45fSAndroid Build Coastguard Worker status_t Region::unflatten(void const* buffer, size_t size) {
848*38e8c45fSAndroid Build Coastguard Worker if (size < sizeof(uint32_t)) {
849*38e8c45fSAndroid Build Coastguard Worker return NO_MEMORY;
850*38e8c45fSAndroid Build Coastguard Worker }
851*38e8c45fSAndroid Build Coastguard Worker
852*38e8c45fSAndroid Build Coastguard Worker uint32_t numRects = 0;
853*38e8c45fSAndroid Build Coastguard Worker FlattenableUtils::read(buffer, size, numRects);
854*38e8c45fSAndroid Build Coastguard Worker if (size < numRects * sizeof(Rect)) {
855*38e8c45fSAndroid Build Coastguard Worker return NO_MEMORY;
856*38e8c45fSAndroid Build Coastguard Worker }
857*38e8c45fSAndroid Build Coastguard Worker
858*38e8c45fSAndroid Build Coastguard Worker if (numRects > (UINT32_MAX / sizeof(Rect))) {
859*38e8c45fSAndroid Build Coastguard Worker android_errorWriteWithInfoLog(0x534e4554, "29983260", -1, nullptr, 0);
860*38e8c45fSAndroid Build Coastguard Worker return NO_MEMORY;
861*38e8c45fSAndroid Build Coastguard Worker }
862*38e8c45fSAndroid Build Coastguard Worker
863*38e8c45fSAndroid Build Coastguard Worker Region result;
864*38e8c45fSAndroid Build Coastguard Worker result.mStorage.clear();
865*38e8c45fSAndroid Build Coastguard Worker for (size_t r = 0; r < numRects; ++r) {
866*38e8c45fSAndroid Build Coastguard Worker Rect rect(Rect::EMPTY_RECT);
867*38e8c45fSAndroid Build Coastguard Worker status_t status = rect.unflatten(buffer, size);
868*38e8c45fSAndroid Build Coastguard Worker if (status != NO_ERROR) {
869*38e8c45fSAndroid Build Coastguard Worker return status;
870*38e8c45fSAndroid Build Coastguard Worker }
871*38e8c45fSAndroid Build Coastguard Worker FlattenableUtils::advance(buffer, size, sizeof(rect));
872*38e8c45fSAndroid Build Coastguard Worker result.mStorage.push_back(rect);
873*38e8c45fSAndroid Build Coastguard Worker }
874*38e8c45fSAndroid Build Coastguard Worker
875*38e8c45fSAndroid Build Coastguard Worker #if defined(VALIDATE_REGIONS)
876*38e8c45fSAndroid Build Coastguard Worker validate(result, "Region::unflatten");
877*38e8c45fSAndroid Build Coastguard Worker #endif
878*38e8c45fSAndroid Build Coastguard Worker
879*38e8c45fSAndroid Build Coastguard Worker if (!result.validate(result, "Region::unflatten", true)) {
880*38e8c45fSAndroid Build Coastguard Worker ALOGE("Region::unflatten() failed, invalid region");
881*38e8c45fSAndroid Build Coastguard Worker return BAD_VALUE;
882*38e8c45fSAndroid Build Coastguard Worker }
883*38e8c45fSAndroid Build Coastguard Worker mStorage.clear();
884*38e8c45fSAndroid Build Coastguard Worker mStorage.insert(mStorage.begin(), result.mStorage.begin(), result.mStorage.end());
885*38e8c45fSAndroid Build Coastguard Worker return NO_ERROR;
886*38e8c45fSAndroid Build Coastguard Worker }
887*38e8c45fSAndroid Build Coastguard Worker
888*38e8c45fSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
889*38e8c45fSAndroid Build Coastguard Worker
begin() const890*38e8c45fSAndroid Build Coastguard Worker Region::const_iterator Region::begin() const {
891*38e8c45fSAndroid Build Coastguard Worker return mStorage.data();
892*38e8c45fSAndroid Build Coastguard Worker }
893*38e8c45fSAndroid Build Coastguard Worker
end() const894*38e8c45fSAndroid Build Coastguard Worker Region::const_iterator Region::end() const {
895*38e8c45fSAndroid Build Coastguard Worker // Workaround for b/77643177
896*38e8c45fSAndroid Build Coastguard Worker // mStorage should never be empty, but somehow it is and it's causing
897*38e8c45fSAndroid Build Coastguard Worker // an abort in ubsan
898*38e8c45fSAndroid Build Coastguard Worker if (mStorage.empty()) return mStorage.data();
899*38e8c45fSAndroid Build Coastguard Worker
900*38e8c45fSAndroid Build Coastguard Worker size_t numRects = isRect() ? 1 : mStorage.size() - 1;
901*38e8c45fSAndroid Build Coastguard Worker return mStorage.data() + numRects;
902*38e8c45fSAndroid Build Coastguard Worker }
903*38e8c45fSAndroid Build Coastguard Worker
getArray(size_t * count) const904*38e8c45fSAndroid Build Coastguard Worker Rect const* Region::getArray(size_t* count) const {
905*38e8c45fSAndroid Build Coastguard Worker if (count) *count = static_cast<size_t>(end() - begin());
906*38e8c45fSAndroid Build Coastguard Worker return begin();
907*38e8c45fSAndroid Build Coastguard Worker }
908*38e8c45fSAndroid Build Coastguard Worker
909*38e8c45fSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
910*38e8c45fSAndroid Build Coastguard Worker
dump(std::string & out,const char * what,uint32_t) const911*38e8c45fSAndroid Build Coastguard Worker void Region::dump(std::string& out, const char* what, uint32_t /* flags */) const {
912*38e8c45fSAndroid Build Coastguard Worker const_iterator head = begin();
913*38e8c45fSAndroid Build Coastguard Worker const_iterator const tail = end();
914*38e8c45fSAndroid Build Coastguard Worker
915*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&out, " Region %s (this=%p, count=%" PRIdPTR ")\n", what, this, tail - head);
916*38e8c45fSAndroid Build Coastguard Worker while (head != tail) {
917*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&out, " [%3d, %3d, %3d, %3d]\n", head->left, head->top, head->right,
918*38e8c45fSAndroid Build Coastguard Worker head->bottom);
919*38e8c45fSAndroid Build Coastguard Worker ++head;
920*38e8c45fSAndroid Build Coastguard Worker }
921*38e8c45fSAndroid Build Coastguard Worker }
922*38e8c45fSAndroid Build Coastguard Worker
dump(const char * what,uint32_t) const923*38e8c45fSAndroid Build Coastguard Worker void Region::dump(const char* what, uint32_t /* flags */) const
924*38e8c45fSAndroid Build Coastguard Worker {
925*38e8c45fSAndroid Build Coastguard Worker const_iterator head = begin();
926*38e8c45fSAndroid Build Coastguard Worker const_iterator const tail = end();
927*38e8c45fSAndroid Build Coastguard Worker ALOGD(" Region %s (this=%p, count=%" PRIdPTR ")\n", what, this, tail-head);
928*38e8c45fSAndroid Build Coastguard Worker while (head != tail) {
929*38e8c45fSAndroid Build Coastguard Worker ALOGD(" [%3d, %3d, %3d, %3d]\n",
930*38e8c45fSAndroid Build Coastguard Worker head->left, head->top, head->right, head->bottom);
931*38e8c45fSAndroid Build Coastguard Worker head++;
932*38e8c45fSAndroid Build Coastguard Worker }
933*38e8c45fSAndroid Build Coastguard Worker }
934*38e8c45fSAndroid Build Coastguard Worker
935*38e8c45fSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
936*38e8c45fSAndroid Build Coastguard Worker
937*38e8c45fSAndroid Build Coastguard Worker }; // namespace android
938