1 /* 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 14 struct SkIRect; 15 16 /** 17 * GrClip encapsulates the information required to construct the clip 18 * masks. 'A GrClip is either wide open, just an IRect, just a Rect, or a full clipstack. 19 * 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 */ 26 class GrClip : SkNoncopyable { 27 public: GrClip()28 GrClip() : fClipType(kWideOpen_ClipType) { 29 fOrigin.setZero(); 30 } 31 GrClip(const SkIRect & rect)32 GrClip(const SkIRect& rect) : fClipType(kIRect_ClipType) { 33 fOrigin.setZero(); 34 fClip.fIRect = rect; 35 } 36 GrClip(const SkRect & rect)37 GrClip(const SkRect& rect) : fClipType(kIRect_ClipType) { 38 fOrigin.setZero(); 39 fClip.fIRect.fLeft = SkScalarRoundToInt(rect.fLeft); 40 fClip.fIRect.fTop = SkScalarRoundToInt(rect.fTop); 41 fClip.fIRect.fRight = SkScalarRoundToInt(rect.fRight); 42 fClip.fIRect.fBottom = SkScalarRoundToInt(rect.fBottom); 43 } 44 ~GrClip()45 ~GrClip() { this->reset(); } 46 47 const GrClip& operator=(const GrClip& other) { 48 this->reset(); 49 fClipType = other.fClipType; 50 switch (other.fClipType) { 51 case kWideOpen_ClipType: 52 fOrigin.setZero(); 53 break; 54 case kClipStack_ClipType: 55 fClip.fStack = SkRef(other.clipStack()); 56 fOrigin = other.origin(); 57 break; 58 case kIRect_ClipType: 59 fClip.fIRect = other.irect(); 60 fOrigin.setZero(); 61 break; 62 } 63 return *this; 64 } 65 66 bool operator==(const GrClip& other) const { 67 if (this->clipType() != other.clipType()) { 68 return false; 69 } 70 71 switch (fClipType) { 72 case kWideOpen_ClipType: 73 return true; 74 case kClipStack_ClipType: 75 if (this->origin() != other.origin()) { 76 return false; 77 } 78 79 if (this->clipStack() && other.clipStack()) { 80 return *this->clipStack() == *other.clipStack(); 81 } else { 82 return this->clipStack() == other.clipStack(); 83 } 84 break; 85 case kIRect_ClipType: 86 return this->irect() == other.irect(); 87 break; 88 } 89 } 90 91 bool operator!=(const GrClip& other) const { 92 return !(*this == other); 93 } 94 clipStack()95 const SkClipStack* clipStack() const { 96 SkASSERT(kClipStack_ClipType == fClipType); 97 return fClip.fStack; 98 } 99 100 void setClipStack(const SkClipStack* clipStack, const SkIPoint* origin = NULL) { 101 this->reset(); 102 if (clipStack->isWideOpen()) { 103 fClipType = kWideOpen_ClipType; 104 fOrigin.setZero(); 105 } else { 106 fClipType = kClipStack_ClipType; 107 fClip.fStack = SkRef(clipStack); 108 if (origin) { 109 fOrigin = *origin; 110 } else { 111 fOrigin.setZero(); 112 } 113 } 114 } 115 irect()116 const SkIRect& irect() const { 117 SkASSERT(kIRect_ClipType == fClipType); 118 return fClip.fIRect; 119 } 120 reset()121 void reset() { 122 if (kClipStack_ClipType == fClipType) { 123 fClip.fStack->unref(); 124 fClip.fStack = NULL; 125 } 126 fClipType = kWideOpen_ClipType; 127 fOrigin.setZero(); 128 } 129 130 // We support this for all cliptypes to simplify the logic a bit in clip mask manager. 131 // non clipstack clip types MUST have a (0,0) origin origin()132 const SkIPoint& origin() const { 133 SkASSERT(fClipType == kClipStack_ClipType || (fOrigin.fX == 0 && fOrigin.fY == 0)); 134 return fOrigin; 135 } 136 isWideOpen(const SkRect & rect)137 bool isWideOpen(const SkRect& rect) const { 138 return (kWideOpen_ClipType == fClipType) || 139 (kClipStack_ClipType == fClipType && this->clipStack()->isWideOpen()) || 140 (kIRect_ClipType == fClipType && this->irect().contains(rect)); 141 } 142 isWideOpen(const SkIRect & rect)143 bool isWideOpen(const SkIRect& rect) const { 144 return (kWideOpen_ClipType == fClipType) || 145 (kClipStack_ClipType == fClipType && this->clipStack()->isWideOpen()) || 146 (kIRect_ClipType == fClipType && this->irect().contains(rect)); 147 } 148 isWideOpen()149 bool isWideOpen() const { 150 return (kWideOpen_ClipType == fClipType) || 151 (kClipStack_ClipType == fClipType && this->clipStack()->isWideOpen()); 152 } 153 quickContains(const SkRect & rect)154 bool quickContains(const SkRect& rect) const { 155 return (kWideOpen_ClipType == fClipType) || 156 (kClipStack_ClipType == fClipType && this->clipStack()->quickContains(rect)) || 157 (kIRect_ClipType == fClipType && this->irect().contains(rect)); 158 } 159 160 void getConservativeBounds(const GrSurface* surface, 161 SkIRect* devResult, 162 bool* isIntersectionOfRects = NULL) const { 163 this->getConservativeBounds(surface->width(), surface->height(), 164 devResult, isIntersectionOfRects); 165 } 166 167 void getConservativeBounds(int width, int height, 168 SkIRect* devResult, 169 bool* isIntersectionOfRects = NULL) const; 170 171 static const GrClip& WideOpen(); 172 173 enum ClipType { 174 kClipStack_ClipType, 175 kWideOpen_ClipType, 176 kIRect_ClipType, 177 }; 178 clipType()179 ClipType clipType() const { return fClipType; } 180 181 private: 182 union Clip { 183 const SkClipStack* fStack; 184 SkIRect fIRect; 185 } fClip; 186 187 SkIPoint fOrigin; 188 ClipType fClipType; 189 }; 190 191 #endif 192