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
GrClip()13 GrClip::GrClip() {
14 fConservativeBounds.setEmpty();
15 fConservativeBoundsValid = true;
16 }
17
GrClip(const GrClip & src)18 GrClip::GrClip(const GrClip& src) {
19 *this = src;
20 }
21
GrClip(const GrIRect & rect)22 GrClip::GrClip(const GrIRect& rect) {
23 this->setFromIRect(rect);
24 }
25
GrClip(const GrRect & rect)26 GrClip::GrClip(const GrRect& rect) {
27 this->setFromRect(rect);
28 }
29
GrClip(GrClipIterator * iter,GrScalar tx,GrScalar ty,const GrRect * bounds)30 GrClip::GrClip(GrClipIterator* iter, GrScalar tx, GrScalar ty,
31 const GrRect* bounds) {
32 this->setFromIterator(iter, tx, ty, bounds);
33 }
34
~GrClip()35 GrClip::~GrClip() {}
36
operator =(const GrClip & src)37 GrClip& GrClip::operator=(const GrClip& src) {
38 fList = src.fList;
39 fConservativeBounds = src.fConservativeBounds;
40 fConservativeBoundsValid = src.fConservativeBoundsValid;
41 return *this;
42 }
43
setEmpty()44 void GrClip::setEmpty() {
45 fList.reset();
46 fConservativeBounds.setEmpty();
47 fConservativeBoundsValid = true;
48 }
49
setFromRect(const GrRect & r)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
setFromIRect(const GrIRect & r)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
intersectWith(SkRect * dst,const SkRect & src)80 static void intersectWith(SkRect* dst, const SkRect& src) {
81 if (!dst->intersect(src)) {
82 dst->setEmpty();
83 }
84 }
85
setFromIterator(GrClipIterator * iter,GrScalar tx,GrScalar ty,const GrRect * conservativeBounds)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