11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
20910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2005 The Android Open Source Project
40910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
70910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */
80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
91cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifndef SkRegion_DEFINED
110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkRegion_DEFINED
120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkRect.h"
140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass SkPath;
160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass SkRgnBuilder;
170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectnamespace android {
190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    class Region;
200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkRegion_gEmptyRunHeadPtr   ((SkRegion::RunHead*)-1)
230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkRegion_gRectRunHeadPtr    0
240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** \class SkRegion
260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    The SkRegion class encapsulates the geometric region used to specify
280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    clipping areas for drawing.
290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
30137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenbergerclass SK_API SkRegion {
310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic:
320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    typedef int32_t RunType;
330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    enum {
340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kRunTypeSentinel = 0x7FFFFFFF
350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRegion();
380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRegion(const SkRegion&);
390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    explicit SkRegion(const SkIRect&);
400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    ~SkRegion();
410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRegion& operator=(const SkRegion&);
4387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
4487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
4587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if the two regions are equal. i.e. The enclose exactly
4687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  the same area.
4787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
484f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    bool operator==(const SkRegion& other) const;
4987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
5087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
5187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if the two regions are not equal.
5287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
534f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    bool operator!=(const SkRegion& other) const {
544f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        return !(*this == other);
550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
5887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Replace this region with the specified region, and return true if the
5987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  resulting region is non-empty.
6087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool set(const SkRegion& src) {
620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(&src);
630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *this = src;
640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return !this->isEmpty();
650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
6887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Swap the contents of this and the specified region. This operation
6987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  is gauarenteed to never fail.
7087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
7187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    void swap(SkRegion&);
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    /** Return true if this region is empty */
7487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool isEmpty() const { return fRunHead == SkRegion_gEmptyRunHeadPtr; }
7587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    /** Return true if this region is a single, non-empty rectangle */
7787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool isRect() const { return fRunHead == SkRegion_gRectRunHeadPtr; }
7887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    /** Return true if this region consists of more than 1 rectangular area */
8087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool isComplex() const { return !this->isEmpty() && !this->isRect(); }
8187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
8287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
8387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return the bounds of this region. If the region is empty, returns an
8487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  empty rectangle.
8587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkIRect& getBounds() const { return fBounds; }
870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger     *  Returns true if the region is non-empty, and if so, appends the
901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger     *  boundary(s) of the region to the specified path.
911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger     *  If the region is empty, returns false, and path is left unmodified.
9287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool getBoundaryPath(SkPath* path) const;
940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
9687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Set the region to be empty, and return false, since the resulting
9787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  region is empty
9887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
9987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool setEmpty();
1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
10287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  If rect is non-empty, set this region to that rectangle and return true,
10387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  otherwise set this region to empty and return false.
10487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
10587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool setRect(const SkIRect&);
1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
10887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  If left < right and top < bottom, set this region to that rectangle and
10987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  return true, otherwise set this region to empty and return false.
11087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
11187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool setRect(int32_t left, int32_t top, int32_t right, int32_t bottom);
1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
11487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Set this region to the union of an array of rects. This is generally
11587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  faster than calling region.op(rect, kUnion_Op) in a loop. If count is
11687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  0, then this region is set to the empty region.
11787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  @return true if the resulting region is non-empty
11840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger     */
11940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    bool setRects(const SkIRect rects[], int count);
12040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
12187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
12287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Set this region to the specified region, and return true if it is
12387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  non-empty.
12487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
12587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool setRegion(const SkRegion&);
12687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
12787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
12887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Set this region to the area described by the path, clipped.
12987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if the resulting region is non-empty.
13087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  This produces a region that is identical to the pixels that would be
13187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  drawn by the path (with no antialiasing) with the specified clip.
13287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
13387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool setPath(const SkPath&, const SkRegion& clip);
1340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
13587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
13687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Returns true if the specified rectangle has a non-empty intersection
13787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  with this region.
13887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
13987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool intersects(const SkIRect&) const;
1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
14187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
14287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Returns true if the specified region has a non-empty intersection
14387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  with this region.
14487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
14587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool intersects(const SkRegion&) const;
14687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
14787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
14887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if the specified x,y coordinate is inside the region.
14987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
15087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool contains(int32_t x, int32_t y) const;
15187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
15287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
15387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if the specified rectangle is completely inside the region.
15487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  This works for simple (rectangular) and complex regions, and always
15587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  returns the correct result. Note: if either this region or the rectangle
15687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  is empty, contains() returns false.
15787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
15887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool contains(const SkIRect&) const;
15987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
16087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
16187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if the specified region is completely inside the region.
16287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  This works for simple (rectangular) and complex regions, and always
16387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  returns the correct result. Note: if either region is empty, contains()
16487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  returns false.
16587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
16687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool contains(const SkRegion&) const;
16787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
16887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
16987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if this region is a single rectangle (not complex) and the
17087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  specified rectangle is contained by this region. Returning false is not
17187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  a guarantee that the rectangle is not contained by this region, but
17287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  return true is a guarantee that the rectangle is contained by this region.
17387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
1740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool quickContains(const SkIRect& r) const {
1750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return this->quickContains(r.fLeft, r.fTop, r.fRight, r.fBottom);
1760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
17887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
17987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if this region is a single rectangle (not complex) and the
18087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  specified rectangle is contained by this region. Returning false is not
18187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  a guarantee that the rectangle is not contained by this region, but
18287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  return true is a guarantee that the rectangle is contained by this
18387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  region.
18487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
1850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool quickContains(int32_t left, int32_t top, int32_t right,
1860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                       int32_t bottom) const {
1870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(this->isEmpty() == fBounds.isEmpty()); // valid region
1880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return left < right && top < bottom &&
1900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project               fRunHead == SkRegion_gRectRunHeadPtr &&  // this->isRect()
1910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project               /* fBounds.contains(left, top, right, bottom); */
1920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project               fBounds.fLeft <= left && fBounds.fTop <= top &&
1930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project               fBounds.fRight >= right && fBounds.fBottom >= bottom;
1940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
19687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
19787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if this region is empty, or if the specified rectangle does
19887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  not intersect the region. Returning false is not a guarantee that they
19987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  intersect, but returning true is a guarantee that they do not.
20087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
20187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    bool quickReject(const SkIRect& rect) const {
2020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return this->isEmpty() || rect.isEmpty() ||
2030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                !SkIRect::Intersects(fBounds, rect);
2040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
20687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
20787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if this region, or rgn, is empty, or if their bounds do not
20887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  intersect. Returning false is not a guarantee that they intersect, but
20987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  returning true is a guarantee that they do not.
21087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
2110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool quickReject(const SkRegion& rgn) const {
2120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return this->isEmpty() || rgn.isEmpty() ||
2130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project               !SkIRect::Intersects(fBounds, rgn.fBounds);
2140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
21687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /** Translate the region by the specified (dx, dy) amount. */
2170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    void translate(int dx, int dy) { this->translate(dx, dy, this); }
2180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
21987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
22087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Translate the region by the specified (dx, dy) amount, writing the
22187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  resulting region into dst. Note: it is legal to pass this region as the
22287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  dst parameter, effectively translating the region in place. If dst is
22387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  null, nothing happens.
22487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
2250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    void translate(int dx, int dy, SkRegion* dst) const;
2260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
22787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
22887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  The logical operations that can be performed when combining two regions.
22987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
2300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    enum Op {
2310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kDifference_Op, //!< subtract the op region from the first region
2320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kIntersect_Op,  //!< intersect the two regions
2330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kUnion_Op,      //!< union (inclusive-or) the two regions
2340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kXOR_Op,        //!< exclusive-or the two regions
2350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        /** subtract the first region from the op region */
2360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kReverseDifference_Op,
2370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kReplace_Op     //!< replace the dst region with the op region
2380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
2390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
24087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
24187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Set this region to the result of applying the Op to this region and the
24287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  specified rectangle: this = (this op rect).
24387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if the resulting region is non-empty.
24487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
2450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool op(const SkIRect& rect, Op op) { return this->op(*this, rect, op); }
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(int left, int top, int right, int bottom, Op op) {
2530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkIRect rect;
2540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rect.set(left, top, right, bottom);
2550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return this->op(*this, rect, op);
2560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
25887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
25987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Set this region to the result of applying the Op to this region and the
26087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  specified region: this = (this op rgn).
26187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if the resulting region is non-empty.
26287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
2630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool op(const SkRegion& rgn, Op op) { return this->op(*this, rgn, op); }
26487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
26587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
26687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Set this region to the result of applying the Op to the specified
26787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  rectangle and region: this = (rect op rgn).
26887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if the resulting region is non-empty.
26987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
2700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool op(const SkIRect& rect, const SkRegion& rgn, Op);
27187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
27287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
27387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Set this region to the result of applying the Op to the specified
27487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  region and rectangle: this = (rgn op rect).
27587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if the resulting region is non-empty.
27687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
2770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool op(const SkRegion& rgn, const SkIRect& rect, Op);
27887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
27987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
28087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Set this region to the result of applying the Op to the specified
28187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  regions: this = (rgna op rgnb).
28287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Return true if the resulting region is non-empty.
28387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
2840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool op(const SkRegion& rgna, const SkRegion& rgnb, Op op);
2850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
2879221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato    /** Returns a new char* containing the list of rectangles in this region
2889221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato     */
2899221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato    char* toString();
29005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#endif
2919221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato
29287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
29387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Returns the sequence of rectangles, sorted in Y and X, that make up
29487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  this region.
29587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
296137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger    class SK_API Iterator {
2970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    public:
2980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        Iterator() : fRgn(NULL), fDone(true) {}
2990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        Iterator(const SkRegion&);
3000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // if we have a region, reset to it and return true, else return false
3010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        bool rewind();
3020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // reset the iterator, using the new region
3030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        void reset(const SkRegion&);
30405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        bool done() const { return fDone; }
3050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        void next();
3060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const SkIRect& rect() const { return fRect; }
30740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        // may return null
30840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        const SkRegion* rgn() const { return fRgn; }
30987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
3100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    private:
3110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const SkRegion* fRgn;
3120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const RunType*  fRuns;
3130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkIRect         fRect;
3140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        bool            fDone;
3150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
3160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
31787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
31887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Returns the sequence of rectangles, sorted in Y and X, that make up
31987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  this region intersected with the specified clip rectangle.
32087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
321137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger    class SK_API Cliperator {
3220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    public:
3230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        Cliperator(const SkRegion&, const SkIRect& clip);
32487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        bool done() { return fDone; }
32587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        void  next();
3260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const SkIRect& rect() const { return fRect; }
3270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    private:
3290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        Iterator    fIter;
3300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkIRect     fClip;
3310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkIRect     fRect;
3320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        bool        fDone;
3330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
3340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
33587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
33687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Returns the sequence of runs that make up this region for the specified
33787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Y scanline, clipped to the specified left and right X values.
33887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
3390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    class Spanerator {
3400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    public:
3410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        Spanerator(const SkRegion&, int y, int left, int right);
34287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        bool next(int* left, int* right);
3430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    private:
3450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const SkRegion::RunType* fRuns;
3460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int     fLeft, fRight;
3470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        bool    fDone;
3480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
3490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
35087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
35187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Write the region to the buffer, and return the number of bytes written.
35287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  If buffer is NULL, it still returns the number of bytes.
35387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
3540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint32_t flatten(void* buffer) const;
35587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
35687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
35787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Initialized the region from the buffer, returning the number
35887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  of bytes actually read.
35987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
3600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint32_t unflatten(const void* buffer);
36187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
36287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    /**
36387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  Returns a reference to a global empty region. Just a convenience for
36487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     *  callers that need a const empty region.
36587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger     */
36687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    static const SkRegion& GetEmptyRegion();
36787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
3680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(void dump() const;)
3690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(void validate() const;)
3700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(static void UnitTest();)
3710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // expose this to allow for regression test on complex regions
3730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(bool debugSetRuns(const RunType runs[], int count);)
3740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprivate:
3760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    enum {
3770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kOpCount = kReplace_Op + 1
3780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
3790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    enum {
3810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kRectRegionRuns = 6 // need to store a region of a rect [T B L R S S]
3820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
3830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    friend class android::Region;    // needed for marshalling efficiently
3850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    void allocateRuns(int count); // allocate space for count runs
3860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    struct RunHead;
3880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkIRect     fBounds;
3900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    RunHead*    fRunHead;
3910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    void            freeRuns();
3930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const RunType*  getRuns(RunType tmpStorage[], int* count) const;
3940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool            setRuns(RunType runs[], int count);
3950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int count_runtype_values(int* itop, int* ibot) const;
3970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    static void BuildRectRuns(const SkIRect& bounds,
3990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                              RunType runs[kRectRegionRuns]);
4000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // returns true if runs are just a rect
4010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    static bool ComputeRunBounds(const RunType runs[], int count,
4020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                 SkIRect* bounds);
4030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    friend struct RunHead;
4050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    friend class Iterator;
4060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    friend class Spanerator;
4070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    friend class SkRgnBuilder;
4080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    friend class SkFlatRegion;
4090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
4100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
412