Region.cpp revision 276293246ea9cbc0a578a7697cc48930376ec0e9
1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "Region"
18
19#include <stdio.h>
20#include <utils/Atomic.h>
21#include <utils/Debug.h>
22#include <utils/String8.h>
23#include <ui/Region.h>
24
25namespace android {
26
27// ----------------------------------------------------------------------------
28
29Region::Region()
30{
31}
32
33Region::Region(const Region& rhs)
34    : mRegion(rhs.mRegion)
35{
36}
37
38Region::Region(const SkRegion& rhs)
39    : mRegion(rhs)
40{
41}
42
43Region::~Region()
44{
45}
46
47Region::Region(const Rect& rhs)
48{
49    set(rhs);
50}
51
52Region::Region(const Parcel& parcel)
53{
54    read(parcel);
55}
56
57Region::Region(const void* buffer)
58{
59    read(buffer);
60}
61
62Region& Region::operator = (const Region& rhs)
63{
64    mRegion = rhs.mRegion;
65    return *this;
66}
67
68const SkRegion& Region::toSkRegion() const
69{
70    return mRegion;
71}
72
73Rect Region::bounds() const
74{
75    const SkIRect& b(mRegion.getBounds());
76    return Rect(b.fLeft, b.fTop, b.fRight, b.fBottom);
77}
78
79void Region::clear()
80{
81    mRegion.setEmpty();
82}
83
84void Region::set(const Rect& r)
85{
86    SkIRect ir;
87    ir.set(r.left, r.top, r.right, r.bottom);
88    mRegion.setRect(ir);
89}
90
91// ----------------------------------------------------------------------------
92
93Region& Region::orSelf(const Rect& r)
94{
95    SkIRect ir;
96    ir.set(r.left, r.top, r.right, r.bottom);
97    mRegion.op(ir, SkRegion::kUnion_Op);
98    return *this;
99}
100
101Region& Region::andSelf(const Rect& r)
102{
103    SkIRect ir;
104    ir.set(r.left, r.top, r.right, r.bottom);
105    mRegion.op(ir, SkRegion::kIntersect_Op);
106    return *this;
107}
108
109// ----------------------------------------------------------------------------
110
111Region& Region::orSelf(const Region& rhs) {
112    mRegion.op(rhs.mRegion, SkRegion::kUnion_Op);
113    return *this;
114}
115
116Region& Region::andSelf(const Region& rhs) {
117    mRegion.op(rhs.mRegion, SkRegion::kIntersect_Op);
118    return *this;
119}
120
121Region& Region::subtractSelf(const Region& rhs) {
122    mRegion.op(rhs.mRegion, SkRegion::kDifference_Op);
123    return *this;
124}
125
126Region& Region::translateSelf(int x, int y) {
127    if (x|y) mRegion.translate(x, y);
128    return *this;
129}
130
131Region Region::merge(const Region& rhs) const {
132    Region result;
133    result.mRegion.op(mRegion, rhs.mRegion, SkRegion::kUnion_Op);
134    return result;
135}
136
137Region Region::intersect(const Region& rhs) const {
138    Region result;
139    result.mRegion.op(mRegion, rhs.mRegion, SkRegion::kIntersect_Op);
140    return result;
141}
142
143Region Region::subtract(const Region& rhs) const {
144    Region result;
145    result.mRegion.op(mRegion, rhs.mRegion, SkRegion::kDifference_Op);
146    return result;
147}
148
149Region Region::translate(int x, int y) const {
150    Region result;
151    mRegion.translate(x, y, &result.mRegion);
152    return result;
153}
154
155// ----------------------------------------------------------------------------
156
157Region& Region::orSelf(const Region& rhs, int dx, int dy) {
158    SkRegion r(rhs.mRegion);
159    r.translate(dx, dy);
160    mRegion.op(r, SkRegion::kUnion_Op);
161    return *this;
162}
163
164Region& Region::andSelf(const Region& rhs, int dx, int dy) {
165    SkRegion r(rhs.mRegion);
166    r.translate(dx, dy);
167    mRegion.op(r, SkRegion::kIntersect_Op);
168    return *this;
169}
170
171Region& Region::subtractSelf(const Region& rhs, int dx, int dy) {
172    SkRegion r(rhs.mRegion);
173    r.translate(dx, dy);
174    mRegion.op(r, SkRegion::kDifference_Op);
175    return *this;
176}
177
178Region Region::merge(const Region& rhs, int dx, int dy) const {
179    Region result;
180    SkRegion r(rhs.mRegion);
181    r.translate(dx, dy);
182    result.mRegion.op(mRegion, r, SkRegion::kUnion_Op);
183    return result;
184}
185
186Region Region::intersect(const Region& rhs, int dx, int dy) const {
187    Region result;
188    SkRegion r(rhs.mRegion);
189    r.translate(dx, dy);
190    result.mRegion.op(mRegion, r, SkRegion::kIntersect_Op);
191    return result;
192}
193
194Region Region::subtract(const Region& rhs, int dx, int dy) const {
195    Region result;
196    SkRegion r(rhs.mRegion);
197    r.translate(dx, dy);
198    result.mRegion.op(mRegion, r, SkRegion::kDifference_Op);
199    return result;
200}
201
202// ----------------------------------------------------------------------------
203
204Region::iterator::iterator(const Region& r)
205    : mIt(r.mRegion)
206{
207}
208
209int Region::iterator::iterate(Rect* rect)
210{
211    if (mIt.done())
212        return 0;
213    const SkIRect& r(mIt.rect());
214    rect->left  = r.fLeft;
215    rect->top   = r.fTop;
216    rect->right = r.fRight;
217    rect->bottom= r.fBottom;
218    mIt.next();
219    return 1;
220}
221
222// ----------------------------------------------------------------------------
223
224// we write a 4byte size ahead of the actual region, so we know how much we'll need for reading
225
226status_t Region::write(Parcel& parcel) const
227{
228    int32_t size = mRegion.flatten(NULL);
229    parcel.writeInt32(size);
230    mRegion.flatten(parcel.writeInplace(size));
231    return NO_ERROR;
232}
233
234status_t Region::read(const Parcel& parcel)
235{
236    size_t size = parcel.readInt32();
237    mRegion.unflatten(parcel.readInplace(size));
238    return NO_ERROR;
239}
240
241ssize_t Region::write(void* buffer, size_t size) const
242{
243    size_t sizeNeeded = mRegion.flatten(NULL);
244    if (sizeNeeded > size) return NO_MEMORY;
245    return mRegion.flatten(buffer);
246}
247
248ssize_t Region::read(const void* buffer)
249{
250    return mRegion.unflatten(buffer);
251}
252
253ssize_t Region::writeEmpty(void* buffer, size_t size)
254{
255    if (size < 4) return NO_MEMORY;
256    // this needs to stay in sync with SkRegion
257    *static_cast<int32_t*>(buffer) = -1;
258    return 4;
259}
260
261bool Region::isEmpty(void* buffer)
262{
263    // this needs to stay in sync with SkRegion
264    return *static_cast<int32_t*>(buffer) == -1;
265}
266
267size_t Region::rects(Vector<Rect>& rectList) const
268{
269    rectList.clear();
270    if (!isEmpty()) {
271        SkRegion::Iterator iterator(mRegion);
272        while( !iterator.done() ) {
273            const SkIRect& ir(iterator.rect());
274            rectList.push(Rect(ir.fLeft, ir.fTop, ir.fRight, ir.fBottom));
275            iterator.next();
276        }
277    }
278    return rectList.size();
279}
280
281void Region::dump(String8& out, const char* what, uint32_t flags) const
282{
283    (void)flags;
284    Vector<Rect> r;
285    rects(r);
286
287    size_t SIZE = 256;
288    char buffer[SIZE];
289
290    snprintf(buffer, SIZE, "  Region %s (this=%p, count=%d)\n", what, this, r.size());
291    out.append(buffer);
292    for (size_t i=0 ; i<r.size() ; i++) {
293        snprintf(buffer, SIZE, "    [%3d, %3d, %3d, %3d]\n",
294            r[i].left, r[i].top,r[i].right,r[i].bottom);
295        out.append(buffer);
296    }
297}
298
299void Region::dump(const char* what, uint32_t flags) const
300{
301    (void)flags;
302    Vector<Rect> r;
303    rects(r);
304    LOGD("  Region %s (this=%p, count=%d)\n", what, this, r.size());
305    for (size_t i=0 ; i<r.size() ; i++) {
306        LOGD("    [%3d, %3d, %3d, %3d]\n",
307            r[i].left, r[i].top,r[i].right,r[i].bottom);
308    }
309}
310
311// ----------------------------------------------------------------------------
312
313}; // namespace android
314