blob: e8f42a231765e3969d5db48f12049cb47822b8b0 [file] [log] [blame]
joshualitt44701df2015-02-23 14:44:57 -08001/*
2 * Copyright 2010 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef GrClip_DEFINED
9#define GrClip_DEFINED
10
11#include "SkClipStack.h"
12#include "GrSurface.h"
13
14struct SkIRect;
15
16/**
17 * GrClip encapsulates the information required to construct the clip
joshualitt586d5d62015-02-25 11:21:21 -080018 * masks. 'A GrClip is either wide open, just an IRect, just a Rect, or a full clipstack.
joshualitt44701df2015-02-23 14:44:57 -080019 * If the clip is a clipstack than the origin is used to translate the stack with
20 * respect to device coordinates. This allows us to use a clip stack that is
21 * specified for a root device with a layer device that is restricted to a subset
22 * of the original canvas. For other clip types the origin will always be (0,0).
23 *
24 * NOTE: GrClip *must* point to a const clipstack
25 */
26class GrClip : SkNoncopyable {
27public:
joshualitt0413d432015-02-23 17:52:51 -080028 GrClip() : fClipType(kWideOpen_ClipType) {
29 fOrigin.setZero();
30 }
joshualitt586d5d62015-02-25 11:21:21 -080031
joshualitt44701df2015-02-23 14:44:57 -080032 GrClip(const SkIRect& rect) : fClipType(kIRect_ClipType) {
joshualitt0413d432015-02-23 17:52:51 -080033 fOrigin.setZero();
joshualitt44701df2015-02-23 14:44:57 -080034 fClip.fIRect = rect;
35 }
joshualitt586d5d62015-02-25 11:21:21 -080036
37 GrClip(const SkRect& rect) : fClipType(kRect_ClipType) {
38 fOrigin.setZero();
39 fClip.fRect = rect;
40 }
41
joshualitt44701df2015-02-23 14:44:57 -080042 ~GrClip() { this->reset(); }
43
44 const GrClip& operator=(const GrClip& other) {
45 this->reset();
46 fClipType = other.fClipType;
47 switch (other.fClipType) {
joshualitt44701df2015-02-23 14:44:57 -080048 case kWideOpen_ClipType:
joshualitt0413d432015-02-23 17:52:51 -080049 fOrigin.setZero();
joshualitt44701df2015-02-23 14:44:57 -080050 break;
51 case kClipStack_ClipType:
joshualitt0413d432015-02-23 17:52:51 -080052 fClip.fStack = SkRef(other.clipStack());
53 fOrigin = other.origin();
joshualitt44701df2015-02-23 14:44:57 -080054 break;
55 case kIRect_ClipType:
56 fClip.fIRect = other.irect();
joshualitt0413d432015-02-23 17:52:51 -080057 fOrigin.setZero();
joshualitt44701df2015-02-23 14:44:57 -080058 break;
joshualitt586d5d62015-02-25 11:21:21 -080059 case kRect_ClipType:
60 fClip.fRect = other.rect();
61 fOrigin.setZero();
62 break;
joshualitt44701df2015-02-23 14:44:57 -080063 }
64 return *this;
65 }
66
67 bool operator==(const GrClip& other) const {
68 if (this->clipType() != other.clipType()) {
69 return false;
70 }
71
72 switch (fClipType) {
joshualitt44701df2015-02-23 14:44:57 -080073 case kWideOpen_ClipType:
74 return true;
75 case kClipStack_ClipType:
76 if (this->origin() != other.origin()) {
77 return false;
78 }
79
80 if (this->clipStack() && other.clipStack()) {
81 return *this->clipStack() == *other.clipStack();
82 } else {
83 return this->clipStack() == other.clipStack();
84 }
85 break;
86 case kIRect_ClipType:
87 return this->irect() == other.irect();
88 break;
joshualitt586d5d62015-02-25 11:21:21 -080089 case kRect_ClipType:
90 return this->rect() == other.rect();
91 break;
joshualitt44701df2015-02-23 14:44:57 -080092 }
93 }
94
95 bool operator!=(const GrClip& other) const {
96 return !(*this == other);
97 }
98
99 const SkClipStack* clipStack() const {
100 SkASSERT(kClipStack_ClipType == fClipType);
joshualitt0413d432015-02-23 17:52:51 -0800101 return fClip.fStack;
joshualitt44701df2015-02-23 14:44:57 -0800102 }
103
104 void setClipStack(const SkClipStack* clipStack, const SkIPoint* origin = NULL) {
joshualittab2f44c2015-02-24 06:47:14 -0800105 this->reset();
joshualitt44701df2015-02-23 14:44:57 -0800106 if (clipStack->isWideOpen()) {
107 fClipType = kWideOpen_ClipType;
joshualitt0413d432015-02-23 17:52:51 -0800108 fOrigin.setZero();
joshualitt44701df2015-02-23 14:44:57 -0800109 } else {
110 fClipType = kClipStack_ClipType;
joshualitt0413d432015-02-23 17:52:51 -0800111 fClip.fStack = SkRef(clipStack);
joshualitt44701df2015-02-23 14:44:57 -0800112 if (origin) {
joshualitt0413d432015-02-23 17:52:51 -0800113 fOrigin = *origin;
joshualitt44701df2015-02-23 14:44:57 -0800114 } else {
joshualitt0413d432015-02-23 17:52:51 -0800115 fOrigin.setZero();
joshualitt44701df2015-02-23 14:44:57 -0800116 }
117 }
118 }
119
120 const SkIRect& irect() const {
121 SkASSERT(kIRect_ClipType == fClipType);
122 return fClip.fIRect;
123 }
124
joshualitt586d5d62015-02-25 11:21:21 -0800125 const SkRect& rect() const {
126 SkASSERT(kRect_ClipType == fClipType);
127 return fClip.fRect;
128 }
129
joshualitt44701df2015-02-23 14:44:57 -0800130 void reset() {
131 if (kClipStack_ClipType == fClipType) {
joshualitt0413d432015-02-23 17:52:51 -0800132 fClip.fStack->unref();
133 fClip.fStack = NULL;
joshualitt44701df2015-02-23 14:44:57 -0800134 }
135 fClipType = kWideOpen_ClipType;
joshualitt0413d432015-02-23 17:52:51 -0800136 fOrigin.setZero();
joshualitt44701df2015-02-23 14:44:57 -0800137 }
138
joshualitt0413d432015-02-23 17:52:51 -0800139 // We support this for all cliptypes to simplify the logic a bit in clip mask manager.
140 // non clipstack clip types MUST have a (0,0) origin
joshualitt44701df2015-02-23 14:44:57 -0800141 const SkIPoint& origin() const {
joshualitt0413d432015-02-23 17:52:51 -0800142 SkASSERT(fClipType == kClipStack_ClipType || (fOrigin.fX == 0 && fOrigin.fY == 0));
143 return fOrigin;
joshualitt44701df2015-02-23 14:44:57 -0800144 }
145
146 bool isWideOpen(const SkRect& rect) const {
147 return (kWideOpen_ClipType == fClipType) ||
148 (kClipStack_ClipType == fClipType && this->clipStack()->isWideOpen()) ||
joshualitt586d5d62015-02-25 11:21:21 -0800149 (kIRect_ClipType == fClipType && this->irect().contains(rect)) ||
150 (kRect_ClipType == fClipType && this->rect().contains(rect));
joshualitt44701df2015-02-23 14:44:57 -0800151 }
152
153 bool isWideOpen(const SkIRect& rect) const {
154 return (kWideOpen_ClipType == fClipType) ||
155 (kClipStack_ClipType == fClipType && this->clipStack()->isWideOpen()) ||
joshualitt586d5d62015-02-25 11:21:21 -0800156 (kIRect_ClipType == fClipType && this->irect().contains(rect)) ||
157 (kRect_ClipType == fClipType && this->rect().contains(rect));
joshualitt44701df2015-02-23 14:44:57 -0800158 }
159
160 bool isWideOpen() const {
161 return (kWideOpen_ClipType == fClipType) ||
162 (kClipStack_ClipType == fClipType && this->clipStack()->isWideOpen());
163 }
164
joshualitt586d5d62015-02-25 11:21:21 -0800165 bool quickContains(const SkRect& rect) const {
166 return (kWideOpen_ClipType == fClipType) ||
167 (kClipStack_ClipType == fClipType && this->clipStack()->quickContains(rect)) ||
168 (kIRect_ClipType == fClipType && this->irect().contains(rect)) ||
169 (kRect_ClipType == fClipType && this->rect().contains(rect));
170 }
171
joshualitt44701df2015-02-23 14:44:57 -0800172 void getConservativeBounds(const GrSurface* surface,
173 SkIRect* devResult,
174 bool* isIntersectionOfRects = NULL) const {
175 this->getConservativeBounds(surface->width(), surface->height(),
176 devResult, isIntersectionOfRects);
177 }
178
179 void getConservativeBounds(int width, int height,
180 SkIRect* devResult,
181 bool* isIntersectionOfRects = NULL) const;
182
joshualitt9ece6a92015-02-23 17:03:33 -0800183 static const GrClip& WideOpen();
joshualitt44701df2015-02-23 14:44:57 -0800184
185 enum ClipType {
186 kClipStack_ClipType,
187 kWideOpen_ClipType,
188 kIRect_ClipType,
joshualitt586d5d62015-02-25 11:21:21 -0800189 kRect_ClipType,
joshualitt44701df2015-02-23 14:44:57 -0800190 };
191
192 ClipType clipType() const { return fClipType; }
193
194private:
195 union Clip {
joshualitt0413d432015-02-23 17:52:51 -0800196 const SkClipStack* fStack;
joshualitt586d5d62015-02-25 11:21:21 -0800197 SkRect fRect;
joshualitt44701df2015-02-23 14:44:57 -0800198 SkIRect fIRect;
199 } fClip;
200
joshualitt0413d432015-02-23 17:52:51 -0800201 SkIPoint fOrigin;
joshualitt44701df2015-02-23 14:44:57 -0800202 ClipType fClipType;
203};
204
205#endif