144701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt/*
244701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt * Copyright 2010 Google Inc.
344701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt *
444701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt * Use of this source code is governed by a BSD-style license that can be
544701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt * found in the LICENSE file.
644701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt */
744701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
844701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt#ifndef GrClip_DEFINED
944701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt#define GrClip_DEFINED
1044701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
1144701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt#include "SkClipStack.h"
1244701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt#include "GrSurface.h"
1344701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
1444701df5ce572ac3cccec785cf52103d3d5d14a5joshualittstruct SkIRect;
1544701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
1644701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt/**
1744701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt * GrClip encapsulates the information required to construct the clip
18570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt * masks. 'A GrClip is either wide open, just an IRect, just a Rect, or a full clipstack.
1944701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt * If the clip is a clipstack than the origin is used to translate the stack with
2044701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt * respect to device coordinates. This allows us to use a clip stack that is
2144701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt * specified for a root device with a layer device that is restricted to a subset
2244701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt * of the original canvas. For other clip types the origin will always be (0,0).
2344701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt *
2444701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt * NOTE: GrClip *must* point to a const clipstack
2544701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt */
2644701df5ce572ac3cccec785cf52103d3d5d14a5joshualittclass GrClip : SkNoncopyable {
2744701df5ce572ac3cccec785cf52103d3d5d14a5joshualittpublic:
280413d43e1b44b93c89603f218aadbfebf7195ac5joshualitt    GrClip() : fClipType(kWideOpen_ClipType) {
290413d43e1b44b93c89603f218aadbfebf7195ac5joshualitt        fOrigin.setZero();
300413d43e1b44b93c89603f218aadbfebf7195ac5joshualitt    }
31570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt
3244701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    GrClip(const SkIRect& rect) : fClipType(kIRect_ClipType) {
330413d43e1b44b93c89603f218aadbfebf7195ac5joshualitt        fOrigin.setZero();
3444701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        fClip.fIRect = rect;
3544701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    }
36570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt
37bb3be25a861e70e0752956cdd03f88f4bf9d167ebsalomon    GrClip(const SkRect& rect) : fClipType(kIRect_ClipType) {
38570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt        fOrigin.setZero();
39bb3be25a861e70e0752956cdd03f88f4bf9d167ebsalomon        fClip.fIRect.fLeft   = SkScalarRoundToInt(rect.fLeft);
40bb3be25a861e70e0752956cdd03f88f4bf9d167ebsalomon        fClip.fIRect.fTop    = SkScalarRoundToInt(rect.fTop);
41bb3be25a861e70e0752956cdd03f88f4bf9d167ebsalomon        fClip.fIRect.fRight  = SkScalarRoundToInt(rect.fRight);
42bb3be25a861e70e0752956cdd03f88f4bf9d167ebsalomon        fClip.fIRect.fBottom = SkScalarRoundToInt(rect.fBottom);
43570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt    }
44570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt
4544701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    ~GrClip() { this->reset(); }
4644701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
4744701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    const GrClip& operator=(const GrClip& other) {
4844701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        this->reset();
4944701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        fClipType = other.fClipType;
5044701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        switch (other.fClipType) {
5144701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt            case kWideOpen_ClipType:
520413d43e1b44b93c89603f218aadbfebf7195ac5joshualitt                fOrigin.setZero();
5344701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt                break;
5444701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt            case kClipStack_ClipType:
550413d43e1b44b93c89603f218aadbfebf7195ac5joshualitt                fClip.fStack = SkRef(other.clipStack());
560413d43e1b44b93c89603f218aadbfebf7195ac5joshualitt                fOrigin = other.origin();
5744701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt                break;
5844701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt            case kIRect_ClipType:
5944701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt                fClip.fIRect = other.irect();
600413d43e1b44b93c89603f218aadbfebf7195ac5joshualitt                fOrigin.setZero();
6144701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt                break;
6244701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        }
6344701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        return *this;
6444701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    }
6544701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
6644701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    bool operator==(const GrClip& other) const {
6744701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        if (this->clipType() != other.clipType()) {
6844701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt            return false;
6944701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        }
7044701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
7144701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        switch (fClipType) {
7244701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt            case kWideOpen_ClipType:
7344701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt                return true;
7444701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt            case kClipStack_ClipType:
7544701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt                if (this->origin() != other.origin()) {
7644701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt                    return false;
7744701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt                }
7844701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
7944701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt                if (this->clipStack() && other.clipStack()) {
8044701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt                    return *this->clipStack() == *other.clipStack();
8144701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt                } else {
8244701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt                    return this->clipStack() == other.clipStack();
8344701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt                }
8444701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt                break;
8544701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt            case kIRect_ClipType:
8644701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt                return this->irect() == other.irect();
8744701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt                break;
8844701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        }
8944701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    }
9044701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
9144701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    bool operator!=(const GrClip& other) const {
9244701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        return !(*this == other);
9344701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    }
9444701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
9544701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    const SkClipStack* clipStack() const {
9644701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        SkASSERT(kClipStack_ClipType == fClipType);
970413d43e1b44b93c89603f218aadbfebf7195ac5joshualitt        return fClip.fStack;
9844701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    }
9944701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
10044701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    void setClipStack(const SkClipStack* clipStack, const SkIPoint* origin = NULL) {
101ab2f44cbfab6d2e0e09c93c41932f464a061742djoshualitt        this->reset();
10244701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        if (clipStack->isWideOpen()) {
10344701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt            fClipType = kWideOpen_ClipType;
1040413d43e1b44b93c89603f218aadbfebf7195ac5joshualitt            fOrigin.setZero();
10544701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        } else {
10644701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt            fClipType = kClipStack_ClipType;
1070413d43e1b44b93c89603f218aadbfebf7195ac5joshualitt            fClip.fStack = SkRef(clipStack);
10844701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt            if (origin) {
1090413d43e1b44b93c89603f218aadbfebf7195ac5joshualitt                fOrigin = *origin;
11044701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt            } else {
1110413d43e1b44b93c89603f218aadbfebf7195ac5joshualitt                fOrigin.setZero();
11244701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt            }
11344701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        }
11444701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    }
11544701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
11644701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    const SkIRect& irect() const {
11744701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        SkASSERT(kIRect_ClipType == fClipType);
11844701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        return fClip.fIRect;
11944701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    }
12044701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
12144701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    void reset() {
12244701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        if (kClipStack_ClipType == fClipType) {
1230413d43e1b44b93c89603f218aadbfebf7195ac5joshualitt            fClip.fStack->unref();
1240413d43e1b44b93c89603f218aadbfebf7195ac5joshualitt            fClip.fStack = NULL;
12544701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        }
12644701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        fClipType = kWideOpen_ClipType;
1270413d43e1b44b93c89603f218aadbfebf7195ac5joshualitt        fOrigin.setZero();
12844701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    }
12944701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
1300413d43e1b44b93c89603f218aadbfebf7195ac5joshualitt    // We support this for all cliptypes to simplify the logic a bit in clip mask manager.
1310413d43e1b44b93c89603f218aadbfebf7195ac5joshualitt    // non clipstack clip types MUST have a (0,0) origin
13244701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    const SkIPoint& origin() const {
1330413d43e1b44b93c89603f218aadbfebf7195ac5joshualitt        SkASSERT(fClipType == kClipStack_ClipType || (fOrigin.fX == 0 && fOrigin.fY == 0));
1340413d43e1b44b93c89603f218aadbfebf7195ac5joshualitt        return fOrigin;
13544701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    }
13644701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
13744701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    bool isWideOpen(const SkRect& rect) const {
13844701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        return (kWideOpen_ClipType == fClipType) ||
13944701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt               (kClipStack_ClipType == fClipType && this->clipStack()->isWideOpen()) ||
140bb3be25a861e70e0752956cdd03f88f4bf9d167ebsalomon               (kIRect_ClipType == fClipType && this->irect().contains(rect));
14144701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    }
14244701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
14344701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    bool isWideOpen(const SkIRect& rect) const {
14444701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        return (kWideOpen_ClipType == fClipType) ||
14544701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt               (kClipStack_ClipType == fClipType && this->clipStack()->isWideOpen()) ||
146bb3be25a861e70e0752956cdd03f88f4bf9d167ebsalomon               (kIRect_ClipType == fClipType && this->irect().contains(rect));
14744701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    }
14844701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
14944701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    bool isWideOpen() const {
15044701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        return (kWideOpen_ClipType == fClipType) ||
15144701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt               (kClipStack_ClipType == fClipType && this->clipStack()->isWideOpen());
15244701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    }
15344701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
154570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt    bool quickContains(const SkRect& rect) const {
155570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt        return (kWideOpen_ClipType == fClipType) ||
156570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt               (kClipStack_ClipType == fClipType && this->clipStack()->quickContains(rect)) ||
157bb3be25a861e70e0752956cdd03f88f4bf9d167ebsalomon               (kIRect_ClipType == fClipType && this->irect().contains(rect));
158570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt    }
159570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt
16044701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    void getConservativeBounds(const GrSurface* surface,
16144701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt                               SkIRect* devResult,
16244701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt                               bool* isIntersectionOfRects = NULL) const {
16344701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        this->getConservativeBounds(surface->width(), surface->height(),
16444701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt                                    devResult, isIntersectionOfRects);
16544701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    }
16644701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
16744701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    void getConservativeBounds(int width, int height,
16844701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt                               SkIRect* devResult,
16944701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt                               bool* isIntersectionOfRects = NULL) const;
17044701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
1719ece6a95481c3226b4519c8e9f685eb3fc1873b3joshualitt    static const GrClip& WideOpen();
17244701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
17344701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    enum ClipType {
17444701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        kClipStack_ClipType,
17544701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        kWideOpen_ClipType,
17644701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        kIRect_ClipType,
17744701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    };
17844701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
17944701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    ClipType clipType() const { return fClipType; }
18044701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
18144701df5ce572ac3cccec785cf52103d3d5d14a5joshualittprivate:
18244701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    union Clip {
1830413d43e1b44b93c89603f218aadbfebf7195ac5joshualitt        const SkClipStack* fStack;
18444701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt        SkIRect fIRect;
18544701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    } fClip;
18644701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
1870413d43e1b44b93c89603f218aadbfebf7195ac5joshualitt    SkIPoint fOrigin;
18844701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    ClipType fClipType;
18944701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt};
19044701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt
19144701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt#endif
192