1 /* 2 Copyright 2010 Google Inc. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 18 #include "GrClip.h" 19 20 GrClip::GrClip() 21 : fList(&fListStorage) { 22 fConservativeBounds.setEmpty(); 23 fConservativeBoundsValid = true; 24 } 25 26 GrClip::GrClip(const GrClip& src) 27 : fList(&fListStorage) { 28 *this = src; 29 } 30 31 GrClip::GrClip(const GrIRect& rect) 32 : fList(&fListStorage) { 33 this->setFromIRect(rect); 34 } 35 36 GrClip::GrClip(const GrRect& rect) 37 : fList(&fListStorage) { 38 this->setFromRect(rect); 39 } 40 41 GrClip::GrClip(GrClipIterator* iter, GrScalar tx, GrScalar ty, 42 const GrRect* bounds) 43 : fList(&fListStorage) { 44 this->setFromIterator(iter, tx, ty, bounds); 45 } 46 47 GrClip::~GrClip() {} 48 49 GrClip& GrClip::operator=(const GrClip& src) { 50 fList = src.fList; 51 fConservativeBounds = src.fConservativeBounds; 52 fConservativeBoundsValid = src.fConservativeBoundsValid; 53 return *this; 54 } 55 56 void GrClip::setEmpty() { 57 fList.reset(); 58 fConservativeBounds.setEmpty(); 59 fConservativeBoundsValid = true; 60 } 61 62 void GrClip::setFromRect(const GrRect& r) { 63 fList.reset(); 64 if (r.isEmpty()) { 65 // use a canonical empty rect for == testing. 66 setEmpty(); 67 } else { 68 fList.push_back(); 69 fList.back().fRect = r; 70 fList.back().fType = kRect_ClipType; 71 fConservativeBounds = r; 72 fConservativeBoundsValid = true; 73 } 74 } 75 76 void GrClip::setFromIRect(const GrIRect& r) { 77 fList.reset(); 78 if (r.isEmpty()) { 79 // use a canonical empty rect for == testing. 80 setEmpty(); 81 } else { 82 fList.push_back(); 83 fList.back().fRect.set(r); 84 fList.back().fType = kRect_ClipType; 85 fConservativeBounds.set(r); 86 fConservativeBoundsValid = true; 87 } 88 } 89 90 static void intersectWith(SkRect* dst, const SkRect& src) { 91 if (!dst->intersect(src)) { 92 dst->setEmpty(); 93 } 94 } 95 96 void GrClip::setFromIterator(GrClipIterator* iter, GrScalar tx, GrScalar ty, 97 const GrRect* conservativeBounds) { 98 fList.reset(); 99 100 int rectCount = 0; 101 102 // compute bounds for common case of series of intersecting rects. 103 bool isectRectValid = true; 104 105 if (iter) { 106 for (iter->rewind(); !iter->isDone(); iter->next()) { 107 Element& e = fList.push_back(); 108 e.fType = iter->getType(); 109 e.fOp = iter->getOp(); 110 // iterators should not emit replace 111 GrAssert(kReplace_SetOp != e.fOp); 112 switch (e.fType) { 113 case kRect_ClipType: 114 iter->getRect(&e.fRect); 115 if (tx || ty) { 116 e.fRect.offset(tx, ty); 117 } 118 ++rectCount; 119 if (isectRectValid) { 120 if (1 == rectCount || kIntersect_SetOp == e.fOp) { 121 GrAssert(fList.count() <= 2); 122 if (fList.count() > 1) { 123 GrAssert(2 == rectCount); 124 rectCount = 1; 125 fList.pop_back(); 126 GrAssert(kRect_ClipType == fList.back().fType); 127 intersectWith(&fList.back().fRect, e.fRect); 128 } 129 } else { 130 isectRectValid = false; 131 } 132 } 133 break; 134 case kPath_ClipType: 135 e.fPath = *iter->getPath(); 136 if (tx || ty) { 137 e.fPath.offset(tx, ty); 138 } 139 e.fPathFill = iter->getPathFill(); 140 isectRectValid = false; 141 break; 142 default: 143 GrCrash("Unknown clip element type."); 144 } 145 } 146 } 147 fConservativeBoundsValid = false; 148 if (isectRectValid) { 149 fConservativeBoundsValid = true; 150 if (rectCount > 0) { 151 fConservativeBounds = fList[0].fRect; 152 } else { 153 fConservativeBounds.setEmpty(); 154 } 155 } else if (NULL != conservativeBounds) { 156 fConservativeBounds = *conservativeBounds; 157 fConservativeBoundsValid = true; 158 } 159 } 160