1 2 /* 3 * Copyright 2010 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 11 #include "GrClip.h" 12 13 GrClip::GrClip() { 14 fConservativeBounds.setEmpty(); 15 fConservativeBoundsValid = true; 16 } 17 18 GrClip::GrClip(const GrClip& src) { 19 *this = src; 20 } 21 22 GrClip::GrClip(const GrIRect& rect) { 23 this->setFromIRect(rect); 24 } 25 26 GrClip::GrClip(const GrRect& rect) { 27 this->setFromRect(rect); 28 } 29 30 GrClip::GrClip(GrClipIterator* iter, GrScalar tx, GrScalar ty, 31 const GrRect* bounds) { 32 this->setFromIterator(iter, tx, ty, bounds); 33 } 34 35 GrClip::~GrClip() {} 36 37 GrClip& GrClip::operator=(const GrClip& src) { 38 fList = src.fList; 39 fConservativeBounds = src.fConservativeBounds; 40 fConservativeBoundsValid = src.fConservativeBoundsValid; 41 return *this; 42 } 43 44 void GrClip::setEmpty() { 45 fList.reset(); 46 fConservativeBounds.setEmpty(); 47 fConservativeBoundsValid = true; 48 } 49 50 void GrClip::setFromRect(const GrRect& r) { 51 fList.reset(); 52 if (r.isEmpty()) { 53 // use a canonical empty rect for == testing. 54 setEmpty(); 55 } else { 56 fList.push_back(); 57 fList.back().fRect = r; 58 fList.back().fType = kRect_ClipType; 59 fList.back().fOp = kReplace_SetOp; 60 fConservativeBounds = r; 61 fConservativeBoundsValid = true; 62 } 63 } 64 65 void GrClip::setFromIRect(const GrIRect& r) { 66 fList.reset(); 67 if (r.isEmpty()) { 68 // use a canonical empty rect for == testing. 69 setEmpty(); 70 } else { 71 fList.push_back(); 72 fList.back().fRect.set(r); 73 fList.back().fType = kRect_ClipType; 74 fList.back().fOp = kReplace_SetOp; 75 fConservativeBounds.set(r); 76 fConservativeBoundsValid = true; 77 } 78 } 79 80 static void intersectWith(SkRect* dst, const SkRect& src) { 81 if (!dst->intersect(src)) { 82 dst->setEmpty(); 83 } 84 } 85 86 void GrClip::setFromIterator(GrClipIterator* iter, GrScalar tx, GrScalar ty, 87 const GrRect* conservativeBounds) { 88 fList.reset(); 89 90 int rectCount = 0; 91 92 // compute bounds for common case of series of intersecting rects. 93 bool isectRectValid = true; 94 95 if (iter) { 96 for (iter->rewind(); !iter->isDone(); iter->next()) { 97 Element& e = fList.push_back(); 98 e.fType = iter->getType(); 99 e.fOp = iter->getOp(); 100 // iterators should not emit replace 101 GrAssert(kReplace_SetOp != e.fOp); 102 switch (e.fType) { 103 case kRect_ClipType: 104 iter->getRect(&e.fRect); 105 if (tx || ty) { 106 e.fRect.offset(tx, ty); 107 } 108 ++rectCount; 109 if (isectRectValid) { 110 if (kIntersect_SetOp == e.fOp) { 111 GrAssert(fList.count() <= 2); 112 if (fList.count() > 1) { 113 GrAssert(2 == rectCount); 114 rectCount = 1; 115 fList.pop_back(); 116 GrAssert(kRect_ClipType == fList.back().fType); 117 intersectWith(&fList.back().fRect, e.fRect); 118 } 119 } else { 120 isectRectValid = false; 121 } 122 } 123 break; 124 case kPath_ClipType: 125 e.fPath = *iter->getPath(); 126 if (tx || ty) { 127 e.fPath.offset(tx, ty); 128 } 129 e.fPathFill = iter->getPathFill(); 130 isectRectValid = false; 131 break; 132 default: 133 GrCrash("Unknown clip element type."); 134 } 135 } 136 } 137 fConservativeBoundsValid = false; 138 if (isectRectValid && rectCount) { 139 fConservativeBounds = fList[0].fRect; 140 fConservativeBoundsValid = true; 141 } else if (NULL != conservativeBounds) { 142 fConservativeBounds = *conservativeBounds; 143 fConservativeBoundsValid = true; 144 } 145 } 146