SkRasterClip.cpp revision 56074222ee31f617ff176865f4b7aa38ede3bb0a
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#include "SkRasterClip.h" 9 10 11SkRasterClip::SkRasterClip() { 12 fIsBW = true; 13} 14 15SkRasterClip::SkRasterClip(const SkIRect& bounds) : fBW(bounds) { 16 fIsBW = true; 17} 18 19SkRasterClip::~SkRasterClip() {} 20 21bool SkRasterClip::isEmpty() const { 22 return fIsBW ? fBW.isEmpty() : fAA.isEmpty(); 23} 24 25bool SkRasterClip::isRect() const { 26 return fIsBW ? fBW.isRect() : false; 27} 28 29bool SkRasterClip::isComplex() const { 30 return fIsBW ? fBW.isComplex() : !fAA.isEmpty(); 31} 32 33const SkIRect& SkRasterClip::getBounds() const { 34 return fIsBW ? fBW.getBounds() : fAA.getBounds(); 35} 36 37bool SkRasterClip::setEmpty() { 38 fIsBW = true; 39 fBW.setEmpty(); 40 fAA.setEmpty(); 41 return false; 42} 43 44bool SkRasterClip::setRect(const SkIRect& rect) { 45 fIsBW = true; 46 fAA.setEmpty(); 47 return fBW.setRect(rect); 48} 49 50bool SkRasterClip::setPath(const SkPath& path, const SkRegion& clip, bool doAA) { 51 if (this->isBW() && !doAA) { 52 return fBW.setPath(path, clip); 53 } else { 54 if (this->isBW()) { 55 this->convertToAA(); 56 } 57 return fAA.setPath(path, &clip, doAA); 58 } 59} 60 61bool SkRasterClip::setPath(const SkPath& path, const SkIRect& clip, bool doAA) { 62 SkRegion tmp; 63 tmp.setRect(clip); 64 return this->setPath(path, tmp, doAA); 65} 66 67bool SkRasterClip::setPath(const SkPath& path, const SkRasterClip& clip, 68 bool doAA) { 69 if (clip.isBW()) { 70 return this->setPath(path, clip.bwRgn(), doAA); 71 } else { 72 SkRegion tmp; 73 tmp.setRect(clip.getBounds()); 74 if (!this->setPath(path, clip, doAA)) { 75 return false; 76 } 77 return this->op(clip, SkRegion::kIntersect_Op); 78 } 79} 80 81bool SkRasterClip::op(const SkIRect& rect, SkRegion::Op op) { 82 return fIsBW ? fBW.op(rect, op) : fAA.op(rect, op); 83} 84 85bool SkRasterClip::op(const SkRegion& rgn, SkRegion::Op op) { 86 if (fIsBW) { 87 return fBW.op(rgn, op); 88 } else { 89 SkAAClip tmp; 90 tmp.setRegion(rgn); 91 return fAA.op(tmp, op); 92 } 93} 94 95bool SkRasterClip::op(const SkRasterClip& clip, SkRegion::Op op) { 96 if (this->isBW() && clip.isBW()) { 97 return fBW.op(clip.fBW, op); 98 } else { 99 SkAAClip tmp; 100 const SkAAClip* other; 101 102 if (this->isBW()) { 103 this->convertToAA(); 104 } 105 if (clip.isBW()) { 106 tmp.setRegion(clip.bwRgn()); 107 other = &tmp; 108 } else { 109 other = &clip.aaRgn(); 110 } 111 return fAA.op(*other, op); 112 } 113} 114 115// return true if x is nearly integral (within 1/256) since that is the highest 116// precision our aa code can have. 117static bool is_integral(SkScalar x) { 118 int ix = SkScalarRoundToInt(x); 119 SkScalar sx = SkIntToScalar(ix); 120 return SkScalarAbs(sx - x) < (SK_Scalar1 / 256); 121} 122 123bool SkRasterClip::op(const SkRect& r, SkRegion::Op op, bool doAA) { 124 if (doAA) { 125 // check that the rect really needs aa 126 if (is_integral(r.fLeft) && is_integral(r.fTop) && 127 is_integral(r.fRight) && is_integral(r.fBottom)) { 128 doAA = false; 129 } 130 } 131 132 if (fIsBW && !doAA) { 133 SkIRect ir; 134 r.round(&ir); 135 return fBW.op(ir, op); 136 } else { 137 if (fIsBW) { 138 this->convertToAA(); 139 } 140 return fAA.op(r, op, doAA); 141 } 142} 143 144const SkRegion& SkRasterClip::forceGetBW() { 145 if (!fIsBW) { 146 fBW.setRect(fAA.getBounds()); 147 } 148 return fBW; 149} 150 151void SkRasterClip::convertToAA() { 152 SkASSERT(fIsBW); 153 fAA.setRegion(fBW); 154 fIsBW = false; 155} 156 157