aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/gpu/GrClip.h
blob: 8c8b9b358f84a41433aa1a7d717cba28b76bfa0b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*
 * Copyright 2010 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef GrClip_DEFINED
#define GrClip_DEFINED

#include "SkClipStack.h"
#include "GrSurface.h"

struct SkIRect;

/**
 * GrClip encapsulates the information required to construct the clip
 * masks. 'A GrClip is either wide open, just an IRect, just a Rect(TODO), or a full clipstack.
 * If the clip is a clipstack than the origin is used to translate the stack with
 * respect to device coordinates. This allows us to use a clip stack that is
 * specified for a root device with a layer device that is restricted to a subset
 * of the original canvas. For other clip types the origin will always be (0,0).
 *
 * NOTE: GrClip *must* point to a const clipstack
 */
class GrClip : SkNoncopyable {
public:
    GrClip() : fClipType(kWideOpen_ClipType) {}
    GrClip(const SkIRect& rect) : fClipType(kIRect_ClipType) {
        fClip.fIRect = rect;
    }
    ~GrClip() { this->reset(); }

    const GrClip& operator=(const GrClip& other) {
        this->reset();
        fClipType = other.fClipType;
        switch (other.fClipType) {
            default:
                SkFAIL("Incomplete Switch\n");
            case kWideOpen_ClipType:
                break;
            case kClipStack_ClipType:
                fClip.fClipStack.fStack = SkRef(other.clipStack());
                fClip.fClipStack.fOrigin = other.origin();
                break;
            case kIRect_ClipType:
                fClip.fIRect = other.irect();
                break;
        }
        return *this;
    }

    bool operator==(const GrClip& other) const {
        if (this->clipType() != other.clipType()) {
            return false;
        }

        switch (fClipType) {
            default:
                SkFAIL("Incomplete Switch\n");
                return false;
            case kWideOpen_ClipType:
                return true;
            case kClipStack_ClipType:
                if (this->origin() != other.origin()) {
                    return false;
                }

                if (this->clipStack() && other.clipStack()) {
                    return *this->clipStack() == *other.clipStack();
                } else {
                    return this->clipStack() == other.clipStack();
                }
                break;
            case kIRect_ClipType:
                return this->irect() == other.irect();
                break;
        }
    }

    bool operator!=(const GrClip& other) const {
        return !(*this == other);
    }

    const SkClipStack* clipStack() const {
        SkASSERT(kClipStack_ClipType == fClipType);
        return fClip.fClipStack.fStack;
    }

    void setClipStack(const SkClipStack* clipStack, const SkIPoint* origin = NULL) {
        if (clipStack->isWideOpen()) {
            fClipType = kWideOpen_ClipType;
        } else {
            fClipType = kClipStack_ClipType;
            fClip.fClipStack.fStack = SkRef(clipStack);
            if (origin) {
                fClip.fClipStack.fOrigin = *origin;
            } else {
                fClip.fClipStack.fOrigin.setZero();
            }
        }
    }

    const SkIRect& irect() const {
        SkASSERT(kIRect_ClipType == fClipType);
        return fClip.fIRect;
    }

    void reset() {
        if (kClipStack_ClipType == fClipType) {
            fClip.fClipStack.fStack->unref();
            fClip.fClipStack.fStack = NULL;
        }
        fClipType = kWideOpen_ClipType;
    }

    const SkIPoint& origin() const {
        SkASSERT(kClipStack_ClipType == fClipType);
        return fClip.fClipStack.fOrigin;
    }

    bool isWideOpen(const SkRect& rect) const {
        return (kWideOpen_ClipType == fClipType) ||
               (kClipStack_ClipType == fClipType && this->clipStack()->isWideOpen()) ||
               (kIRect_ClipType == fClipType && this->irect().contains(rect));
    }

    bool isWideOpen(const SkIRect& rect) const {
        return (kWideOpen_ClipType == fClipType) ||
               (kClipStack_ClipType == fClipType && this->clipStack()->isWideOpen()) ||
               (kIRect_ClipType == fClipType && this->irect().contains(rect));
    }

    bool isWideOpen() const {
        return (kWideOpen_ClipType == fClipType) ||
               (kClipStack_ClipType == fClipType && this->clipStack()->isWideOpen());
    }

    void getConservativeBounds(const GrSurface* surface,
                               SkIRect* devResult,
                               bool* isIntersectionOfRects = NULL) const {
        this->getConservativeBounds(surface->width(), surface->height(),
                                    devResult, isIntersectionOfRects);
    }

    void getConservativeBounds(int width, int height,
                               SkIRect* devResult,
                               bool* isIntersectionOfRects = NULL) const;

    static const GrClip& WideOpen();

    enum ClipType {
        kClipStack_ClipType,
        kWideOpen_ClipType,
        kIRect_ClipType,
    };

    ClipType clipType() const { return fClipType; }

private:
    union Clip {
        struct ClipStack {
            const SkClipStack* fStack;
            SkIPoint fOrigin;
        } fClipStack;
        SkIRect fIRect;
    } fClip;

    ClipType fClipType;
};

#endif