SkRegion.h revision 87b8e645865f9633f410c02252a0fd3feb18f09b
10910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/*
20910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * Copyright (C) 2005 The Android Open Source Project
30910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *
40910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
50910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * you may not use this file except in compliance with the License.
60910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * You may obtain a copy of the License at
70910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *
80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
90910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *
100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * See the License for the specific language governing permissions and
140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * limitations under the License.
150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */
160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifndef SkRegion_DEFINED
180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkRegion_DEFINED
190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkRect.h"
210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass SkPath;
230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass SkRgnBuilder;
240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectnamespace android {
260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    class Region;
270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkRegion_gEmptyRunHeadPtr   ((SkRegion::RunHead*)-1)
300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkRegion_gRectRunHeadPtr    0
310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** \class SkRegion
330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    The SkRegion class encapsulates the geometric region used to specify
350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    clipping areas for drawing.
360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
37137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenbergerclass SK_API SkRegion {
380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic:
390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    typedef int32_t RunType;
400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    enum {
410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kRunTypeSentinel = 0x7FFFFFFF
420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRegion();
450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRegion(const SkRegion&);
460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    explicit SkRegion(const SkIRect&);
470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    ~SkRegion();
480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRegion& operator=(const SkRegion&);
5087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
5187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
5287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if the two regions are equal. i.e. The enclose exactly
5387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  the same area.
5487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
5587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    friend bool operator==(const SkRegion& a, const SkRegion& b);
5687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
5787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
5887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if the two regions are not equal.
5987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
6087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    friend bool operator!=(const SkRegion& a, const SkRegion& b) {
610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return !(a == b);
620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
6587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Replace this region with the specified region, and return true if the
6687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  resulting region is non-empty.
6787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool set(const SkRegion& src) {
690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(&src);
700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *this = src;
710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return !this->isEmpty();
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
7587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Swap the contents of this and the specified region. This operation
7687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  is gauarenteed to never fail.
7787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
7887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    void swap(SkRegion&);
790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    /** Return true if this region is empty */
8187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool isEmpty() const { return fRunHead == SkRegion_gEmptyRunHeadPtr; }
8287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    /** Return true if this region is a single, non-empty rectangle */
8487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool isRect() const { return fRunHead == SkRegion_gRectRunHeadPtr; }
8587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    /** Return true if this region consists of more than 1 rectangular area */
8787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool isComplex() const { return !this->isEmpty() && !this->isRect(); }
8887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
8987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
9087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return the bounds of this region. If the region is empty, returns an
9187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  empty rectangle.
9287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkIRect& getBounds() const { return fBounds; }
940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
9687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Returns true if the region is non-empty, and if so, sets the specified
9787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  path to the boundary(s) of the region. If the region is empty, then
9887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  this returns false, and path is left unmodified.
9987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool getBoundaryPath(SkPath* path) const;
1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
10387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Set the region to be empty, and return false, since the resulting
10487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  region is empty
10587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
10687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool setEmpty();
1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
10987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  If rect is non-empty, set this region to that rectangle and return true,
11087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  otherwise set this region to empty and return false.
11187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
11287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool setRect(const SkIRect&);
1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
11587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  If left < right and top < bottom, set this region to that rectangle and
11687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  return true, otherwise set this region to empty and return false.
11787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
11887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool setRect(int32_t left, int32_t top, int32_t right, int32_t bottom);
1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
12187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Set this region to the union of an array of rects. This is generally
12287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  faster than calling region.op(rect, kUnion_Op) in a loop. If count is
12387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  0, then this region is set to the empty region.
12487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  @return true if the resulting region is non-empty
12540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger     */
12640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    bool setRects(const SkIRect rects[], int count);
12740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
12887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
12987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Set this region to the specified region, and return true if it is
13087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  non-empty.
13187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
13287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool setRegion(const SkRegion&);
13387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
13487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
13587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Set this region to the area described by the path, clipped.
13687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if the resulting region is non-empty.
13787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  This produces a region that is identical to the pixels that would be
13887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  drawn by the path (with no antialiasing) with the specified clip.
13987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
14087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool setPath(const SkPath&, const SkRegion& clip);
1410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
14287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
14387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Returns true if the specified rectangle has a non-empty intersection
14487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  with this region.
14587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
14687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool intersects(const SkIRect&) const;
1470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
14887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
14987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Returns true if the specified region has a non-empty intersection
15087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  with this region.
15187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
15287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool intersects(const SkRegion&) const;
15387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
15487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
15587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if the specified x,y coordinate is inside the region.
15687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
15787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool contains(int32_t x, int32_t y) const;
15887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
15987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
16087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if the specified rectangle is completely inside the region.
16187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  This works for simple (rectangular) and complex regions, and always
16287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  returns the correct result. Note: if either this region or the rectangle
16387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  is empty, contains() returns false.
16487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
16587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool contains(const SkIRect&) const;
16687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
16787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
16887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if the specified region is completely inside the region.
16987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  This works for simple (rectangular) and complex regions, and always
17087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  returns the correct result. Note: if either region is empty, contains()
17187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  returns false.
17287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
17387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool contains(const SkRegion&) const;
17487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
17587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
17687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if this region is a single rectangle (not complex) and the
17787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  specified rectangle is contained by this region. Returning false is not
17887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  a guarantee that the rectangle is not contained by this region, but
17987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  return true is a guarantee that the rectangle is contained by this region.
18087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
1810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool quickContains(const SkIRect& r) const {
1820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return this->quickContains(r.fLeft, r.fTop, r.fRight, r.fBottom);
1830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
18587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
18687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if this region is a single rectangle (not complex) and the
18787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  specified rectangle is contained by this region. Returning false is not
18887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  a guarantee that the rectangle is not contained by this region, but
18987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  return true is a guarantee that the rectangle is contained by this
19087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  region.
19187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
1920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool quickContains(int32_t left, int32_t top, int32_t right,
1930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                       int32_t bottom) const {
1940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(this->isEmpty() == fBounds.isEmpty()); // valid region
1950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return left < right && top < bottom &&
1970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project               fRunHead == SkRegion_gRectRunHeadPtr &&  // this->isRect()
1980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project               /* fBounds.contains(left, top, right, bottom); */
1990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project               fBounds.fLeft <= left && fBounds.fTop <= top &&
2000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project               fBounds.fRight >= right && fBounds.fBottom >= bottom;
2010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
20387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
20487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if this region is empty, or if the specified rectangle does
20587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  not intersect the region. Returning false is not a guarantee that they
20687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  intersect, but returning true is a guarantee that they do not.
20787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
20887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool quickReject(const SkIRect& rect) const {
2090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return this->isEmpty() || rect.isEmpty() ||
2100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                !SkIRect::Intersects(fBounds, rect);
2110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
21387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
21487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if this region, or rgn, is empty, or if their bounds do not
21587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  intersect. Returning false is not a guarantee that they intersect, but
21687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  returning true is a guarantee that they do not.
21787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
2180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool quickReject(const SkRegion& rgn) const {
2190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return this->isEmpty() || rgn.isEmpty() ||
2200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project               !SkIRect::Intersects(fBounds, rgn.fBounds);
2210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
22387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /** Translate the region by the specified (dx, dy) amount. */
2240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    void translate(int dx, int dy) { this->translate(dx, dy, this); }
2250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
22687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
22787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Translate the region by the specified (dx, dy) amount, writing the
22887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  resulting region into dst. Note: it is legal to pass this region as the
22987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  dst parameter, effectively translating the region in place. If dst is
23087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  null, nothing happens.
23187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
2320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    void translate(int dx, int dy, SkRegion* dst) const;
2330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
23487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
23587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  The logical operations that can be performed when combining two regions.
23687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
2370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    enum Op {
2380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kDifference_Op, //!< subtract the op region from the first region
2390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kIntersect_Op,  //!< intersect the two regions
2400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kUnion_Op,      //!< union (inclusive-or) the two regions
2410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kXOR_Op,        //!< exclusive-or the two regions
2420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        /** subtract the first region from the op region */
2430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kReverseDifference_Op,
2440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kReplace_Op     //!< replace the dst region with the op region
2450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
2460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
24787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
24887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Set this region to the result of applying the Op to this region and the
24987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  specified rectangle: this = (this op rect).
25087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if the resulting region is non-empty.
25187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
2520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool op(const SkIRect& rect, Op op) { return this->op(*this, rect, op); }
2530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
25487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
25587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Set this region to the result of applying the Op to this region and the
25687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  specified rectangle: this = (this op rect).
25787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if the resulting region is non-empty.
25887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
2590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool op(int left, int top, int right, int bottom, Op op) {
2600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkIRect rect;
2610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rect.set(left, top, right, bottom);
2620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return this->op(*this, rect, op);
2630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
26587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
26687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Set this region to the result of applying the Op to this region and the
26787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  specified region: this = (this op rgn).
26887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if the resulting region is non-empty.
26987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
2700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool op(const SkRegion& rgn, Op op) { return this->op(*this, rgn, op); }
27187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
27287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
27387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Set this region to the result of applying the Op to the specified
27487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  rectangle and region: this = (rect op rgn).
27587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if the resulting region is non-empty.
27687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
2770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool op(const SkIRect& rect, const SkRegion& rgn, Op);
27887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
27987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
28087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Set this region to the result of applying the Op to the specified
28187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  region and rectangle: this = (rgn op rect).
28287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if the resulting region is non-empty.
28387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
2840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool op(const SkRegion& rgn, const SkIRect& rect, Op);
28587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
28687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
28787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Set this region to the result of applying the Op to the specified
28887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  regions: this = (rgna op rgnb).
28987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if the resulting region is non-empty.
29087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
2910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool op(const SkRegion& rgna, const SkRegion& rgnb, Op op);
2920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
29305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#ifdef ANDROID
2949221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato    /** Returns a new char* containing the list of rectangles in this region
2959221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato     */
2969221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato    char* toString();
29705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#endif
2989221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato
29987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
30087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Returns the sequence of rectangles, sorted in Y and X, that make up
30187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  this region.
30287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
303137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger    class SK_API Iterator {
3040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    public:
3050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        Iterator() : fRgn(NULL), fDone(true) {}
3060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        Iterator(const SkRegion&);
3070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // if we have a region, reset to it and return true, else return false
3080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        bool rewind();
3090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // reset the iterator, using the new region
3100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        void reset(const SkRegion&);
31105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        bool done() const { return fDone; }
3120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        void next();
3130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const SkIRect& rect() const { return fRect; }
31440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        // may return null
31540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        const SkRegion* rgn() const { return fRgn; }
31687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
3170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    private:
3180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const SkRegion* fRgn;
3190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const RunType*  fRuns;
3200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkIRect         fRect;
3210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        bool            fDone;
3220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
3230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
32487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
32587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Returns the sequence of rectangles, sorted in Y and X, that make up
32687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  this region intersected with the specified clip rectangle.
32787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
328137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger    class SK_API Cliperator {
3290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    public:
3300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        Cliperator(const SkRegion&, const SkIRect& clip);
33187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        bool done() { return fDone; }
33287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        void  next();
3330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const SkIRect& rect() const { return fRect; }
3340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    private:
3360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        Iterator    fIter;
3370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkIRect     fClip;
3380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkIRect     fRect;
3390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        bool        fDone;
3400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
3410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
34287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
34387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Returns the sequence of runs that make up this region for the specified
34487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Y scanline, clipped to the specified left and right X values.
34587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
3460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    class Spanerator {
3470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    public:
3480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        Spanerator(const SkRegion&, int y, int left, int right);
34987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        bool next(int* left, int* right);
3500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    private:
3520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const SkRegion::RunType* fRuns;
3530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int     fLeft, fRight;
3540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        bool    fDone;
3550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
3560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
35787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
35887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Write the region to the buffer, and return the number of bytes written.
35987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  If buffer is NULL, it still returns the number of bytes.
36087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
3610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint32_t flatten(void* buffer) const;
36287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
36387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
36487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Initialized the region from the buffer, returning the number
36587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  of bytes actually read.
36687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
3670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint32_t unflatten(const void* buffer);
36887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
36987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
37087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Returns a reference to a global empty region. Just a convenience for
37187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  callers that need a const empty region.
37287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
37387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    static const SkRegion& GetEmptyRegion();
37487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
3750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(void dump() const;)
3760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(void validate() const;)
3770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(static void UnitTest();)
3780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // expose this to allow for regression test on complex regions
3800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(bool debugSetRuns(const RunType runs[], int count);)
3810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprivate:
3830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    enum {
3840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kOpCount = kReplace_Op + 1
3850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
3860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    enum {
3880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kRectRegionRuns = 6 // need to store a region of a rect [T B L R S S]
3890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
3900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    friend class android::Region;    // needed for marshalling efficiently
3920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    void allocateRuns(int count); // allocate space for count runs
3930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    struct RunHead;
3950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkIRect     fBounds;
3970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    RunHead*    fRunHead;
3980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    void            freeRuns();
4000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const RunType*  getRuns(RunType tmpStorage[], int* count) const;
4010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool            setRuns(RunType runs[], int count);
4020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int count_runtype_values(int* itop, int* ibot) const;
4040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    static void BuildRectRuns(const SkIRect& bounds,
4060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                              RunType runs[kRectRegionRuns]);
4070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // returns true if runs are just a rect
4080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    static bool ComputeRunBounds(const RunType runs[], int count,
4090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                 SkIRect* bounds);
4100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    friend struct RunHead;
4120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    friend class Iterator;
4130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    friend class Spanerator;
4140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    friend class SkRgnBuilder;
4150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    friend class SkFlatRegion;
4160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
4170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
419