1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2010 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkPath.h" 9cb93a386Sopenharmony_ci#include "src/core/SkRasterClip.h" 10cb93a386Sopenharmony_ci#include "src/core/SkRegionPriv.h" 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_ciSkRasterClip::SkRasterClip(const SkRasterClip& that) 13cb93a386Sopenharmony_ci : fIsBW(that.fIsBW) 14cb93a386Sopenharmony_ci , fIsEmpty(that.fIsEmpty) 15cb93a386Sopenharmony_ci , fIsRect(that.fIsRect) 16cb93a386Sopenharmony_ci , fShader(that.fShader) 17cb93a386Sopenharmony_ci{ 18cb93a386Sopenharmony_ci AUTO_RASTERCLIP_VALIDATE(that); 19cb93a386Sopenharmony_ci 20cb93a386Sopenharmony_ci if (fIsBW) { 21cb93a386Sopenharmony_ci fBW = that.fBW; 22cb93a386Sopenharmony_ci } else { 23cb93a386Sopenharmony_ci fAA = that.fAA; 24cb93a386Sopenharmony_ci } 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 27cb93a386Sopenharmony_ci} 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_ciSkRasterClip& SkRasterClip::operator=(const SkRasterClip& that) { 30cb93a386Sopenharmony_ci AUTO_RASTERCLIP_VALIDATE(that); 31cb93a386Sopenharmony_ci 32cb93a386Sopenharmony_ci fIsBW = that.fIsBW; 33cb93a386Sopenharmony_ci if (fIsBW) { 34cb93a386Sopenharmony_ci fBW = that.fBW; 35cb93a386Sopenharmony_ci } else { 36cb93a386Sopenharmony_ci fAA = that.fAA; 37cb93a386Sopenharmony_ci } 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_ci fIsEmpty = that.isEmpty(); 40cb93a386Sopenharmony_ci fIsRect = that.isRect(); 41cb93a386Sopenharmony_ci fShader = that.fShader; 42cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 43cb93a386Sopenharmony_ci return *this; 44cb93a386Sopenharmony_ci} 45cb93a386Sopenharmony_ci 46cb93a386Sopenharmony_ciSkRasterClip::SkRasterClip(const SkRegion& rgn) : fBW(rgn) { 47cb93a386Sopenharmony_ci fIsBW = true; 48cb93a386Sopenharmony_ci fIsEmpty = this->computeIsEmpty(); // bounds might be empty, so compute 49cb93a386Sopenharmony_ci fIsRect = !fIsEmpty; 50cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 51cb93a386Sopenharmony_ci} 52cb93a386Sopenharmony_ci 53cb93a386Sopenharmony_ciSkRasterClip::SkRasterClip(const SkIRect& bounds) : fBW(bounds) { 54cb93a386Sopenharmony_ci fIsBW = true; 55cb93a386Sopenharmony_ci fIsEmpty = this->computeIsEmpty(); // bounds might be empty, so compute 56cb93a386Sopenharmony_ci fIsRect = !fIsEmpty; 57cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 58cb93a386Sopenharmony_ci} 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_ciSkRasterClip::SkRasterClip() { 61cb93a386Sopenharmony_ci fIsBW = true; 62cb93a386Sopenharmony_ci fIsEmpty = true; 63cb93a386Sopenharmony_ci fIsRect = false; 64cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 65cb93a386Sopenharmony_ci} 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_ciSkRasterClip::SkRasterClip(const SkPath& path, const SkIRect& bounds, bool doAA) { 68cb93a386Sopenharmony_ci if (doAA) { 69cb93a386Sopenharmony_ci fIsBW = false; 70cb93a386Sopenharmony_ci fAA.setPath(path, bounds, true); 71cb93a386Sopenharmony_ci } else { 72cb93a386Sopenharmony_ci fIsBW = true; 73cb93a386Sopenharmony_ci fBW.setPath(path, SkRegion(bounds)); 74cb93a386Sopenharmony_ci } 75cb93a386Sopenharmony_ci fIsEmpty = this->computeIsEmpty(); // bounds might be empty, so compute 76cb93a386Sopenharmony_ci fIsRect = this->computeIsRect(); 77cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 78cb93a386Sopenharmony_ci} 79cb93a386Sopenharmony_ci 80cb93a386Sopenharmony_ciSkRasterClip::~SkRasterClip() { 81cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 82cb93a386Sopenharmony_ci} 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_cibool SkRasterClip::setEmpty() { 85cb93a386Sopenharmony_ci AUTO_RASTERCLIP_VALIDATE(*this); 86cb93a386Sopenharmony_ci 87cb93a386Sopenharmony_ci fIsBW = true; 88cb93a386Sopenharmony_ci fBW.setEmpty(); 89cb93a386Sopenharmony_ci fAA.setEmpty(); 90cb93a386Sopenharmony_ci fIsEmpty = true; 91cb93a386Sopenharmony_ci fIsRect = false; 92cb93a386Sopenharmony_ci return false; 93cb93a386Sopenharmony_ci} 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_cibool SkRasterClip::setRect(const SkIRect& rect) { 96cb93a386Sopenharmony_ci AUTO_RASTERCLIP_VALIDATE(*this); 97cb93a386Sopenharmony_ci 98cb93a386Sopenharmony_ci fIsBW = true; 99cb93a386Sopenharmony_ci fAA.setEmpty(); 100cb93a386Sopenharmony_ci fIsRect = fBW.setRect(rect); 101cb93a386Sopenharmony_ci fIsEmpty = !fIsRect; 102cb93a386Sopenharmony_ci return fIsRect; 103cb93a386Sopenharmony_ci} 104cb93a386Sopenharmony_ci 105cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////////// 106cb93a386Sopenharmony_ci 107cb93a386Sopenharmony_cibool SkRasterClip::op(const SkIRect& rect, SkClipOp op) { 108cb93a386Sopenharmony_ci AUTO_RASTERCLIP_VALIDATE(*this); 109cb93a386Sopenharmony_ci 110cb93a386Sopenharmony_ci if (fIsBW) { 111cb93a386Sopenharmony_ci fBW.op(rect, (SkRegion::Op) op); 112cb93a386Sopenharmony_ci } else { 113cb93a386Sopenharmony_ci fAA.op(rect, op); 114cb93a386Sopenharmony_ci } 115cb93a386Sopenharmony_ci return this->updateCacheAndReturnNonEmpty(); 116cb93a386Sopenharmony_ci} 117cb93a386Sopenharmony_ci 118cb93a386Sopenharmony_cibool SkRasterClip::op(const SkRegion& rgn, SkClipOp op) { 119cb93a386Sopenharmony_ci AUTO_RASTERCLIP_VALIDATE(*this); 120cb93a386Sopenharmony_ci 121cb93a386Sopenharmony_ci if (fIsBW) { 122cb93a386Sopenharmony_ci (void)fBW.op(rgn, (SkRegion::Op) op); 123cb93a386Sopenharmony_ci } else { 124cb93a386Sopenharmony_ci SkAAClip tmp; 125cb93a386Sopenharmony_ci tmp.setRegion(rgn); 126cb93a386Sopenharmony_ci (void)fAA.op(tmp, op); 127cb93a386Sopenharmony_ci } 128cb93a386Sopenharmony_ci return this->updateCacheAndReturnNonEmpty(); 129cb93a386Sopenharmony_ci} 130cb93a386Sopenharmony_ci 131cb93a386Sopenharmony_ci/** 132cb93a386Sopenharmony_ci * Our antialiasing currently has a granularity of 1/4 of a pixel along each 133cb93a386Sopenharmony_ci * axis. Thus we can treat an axis coordinate as an integer if it differs 134cb93a386Sopenharmony_ci * from its nearest int by < half of that value (1/8 in this case). 135cb93a386Sopenharmony_ci */ 136cb93a386Sopenharmony_cistatic bool nearly_integral(SkScalar x) { 137cb93a386Sopenharmony_ci static const SkScalar domain = SK_Scalar1 / 4; 138cb93a386Sopenharmony_ci static const SkScalar halfDomain = domain / 2; 139cb93a386Sopenharmony_ci 140cb93a386Sopenharmony_ci x += halfDomain; 141cb93a386Sopenharmony_ci return x - SkScalarFloorToScalar(x) < domain; 142cb93a386Sopenharmony_ci} 143cb93a386Sopenharmony_ci 144cb93a386Sopenharmony_cibool SkRasterClip::op(const SkRect& localRect, const SkMatrix& matrix, SkClipOp op, bool doAA) { 145cb93a386Sopenharmony_ci AUTO_RASTERCLIP_VALIDATE(*this); 146cb93a386Sopenharmony_ci 147cb93a386Sopenharmony_ci const bool isScaleTrans = matrix.isScaleTranslate(); 148cb93a386Sopenharmony_ci if (!isScaleTrans) { 149cb93a386Sopenharmony_ci return this->op(SkPath::Rect(localRect), matrix, op, doAA); 150cb93a386Sopenharmony_ci } 151cb93a386Sopenharmony_ci 152cb93a386Sopenharmony_ci SkRect devRect = matrix.mapRect(localRect); 153cb93a386Sopenharmony_ci if (fIsBW && doAA) { 154cb93a386Sopenharmony_ci // check that the rect really needs aa, or is it close enought to 155cb93a386Sopenharmony_ci // integer boundaries that we can just treat it as a BW rect? 156cb93a386Sopenharmony_ci if (nearly_integral(devRect.fLeft) && nearly_integral(devRect.fTop) && 157cb93a386Sopenharmony_ci nearly_integral(devRect.fRight) && nearly_integral(devRect.fBottom)) { 158cb93a386Sopenharmony_ci doAA = false; 159cb93a386Sopenharmony_ci } 160cb93a386Sopenharmony_ci } 161cb93a386Sopenharmony_ci 162cb93a386Sopenharmony_ci if (fIsBW && !doAA) { 163cb93a386Sopenharmony_ci (void)fBW.op(devRect.round(), (SkRegion::Op) op); 164cb93a386Sopenharmony_ci } else { 165cb93a386Sopenharmony_ci if (fIsBW) { 166cb93a386Sopenharmony_ci this->convertToAA(); 167cb93a386Sopenharmony_ci } 168cb93a386Sopenharmony_ci (void)fAA.op(devRect, op, doAA); 169cb93a386Sopenharmony_ci } 170cb93a386Sopenharmony_ci return this->updateCacheAndReturnNonEmpty(); 171cb93a386Sopenharmony_ci} 172cb93a386Sopenharmony_ci 173cb93a386Sopenharmony_cibool SkRasterClip::op(const SkRRect& rrect, const SkMatrix& matrix, SkClipOp op, bool doAA) { 174cb93a386Sopenharmony_ci return this->op(SkPath::RRect(rrect), matrix, op, doAA); 175cb93a386Sopenharmony_ci} 176cb93a386Sopenharmony_ci 177cb93a386Sopenharmony_cibool SkRasterClip::op(const SkPath& path, const SkMatrix& matrix, SkClipOp op, bool doAA) { 178cb93a386Sopenharmony_ci AUTO_RASTERCLIP_VALIDATE(*this); 179cb93a386Sopenharmony_ci 180cb93a386Sopenharmony_ci SkPath devPath; 181cb93a386Sopenharmony_ci path.transform(matrix, &devPath); 182cb93a386Sopenharmony_ci 183cb93a386Sopenharmony_ci // Since op is either intersect or difference, the clip is always shrinking; that means we can 184cb93a386Sopenharmony_ci // always use our current bounds as the limiting factor for region/aaclip operations. 185cb93a386Sopenharmony_ci if (this->isRect() && op == SkClipOp::kIntersect) { 186cb93a386Sopenharmony_ci // However, in the relatively common case of intersecting a new path with a rectangular 187cb93a386Sopenharmony_ci // clip, it's faster to convert the path into a region/aa-mask in place than evaluate the 188cb93a386Sopenharmony_ci // actual intersection. See skbug.com/12398 189cb93a386Sopenharmony_ci if (doAA && fIsBW) { 190cb93a386Sopenharmony_ci this->convertToAA(); 191cb93a386Sopenharmony_ci } 192cb93a386Sopenharmony_ci if (fIsBW) { 193cb93a386Sopenharmony_ci fBW.setPath(devPath, SkRegion(this->getBounds())); 194cb93a386Sopenharmony_ci } else { 195cb93a386Sopenharmony_ci fAA.setPath(devPath, this->getBounds(), doAA); 196cb93a386Sopenharmony_ci } 197cb93a386Sopenharmony_ci return this->updateCacheAndReturnNonEmpty(); 198cb93a386Sopenharmony_ci } else { 199cb93a386Sopenharmony_ci return this->op(SkRasterClip(devPath, this->getBounds(), doAA), op); 200cb93a386Sopenharmony_ci } 201cb93a386Sopenharmony_ci} 202cb93a386Sopenharmony_ci 203cb93a386Sopenharmony_cibool SkRasterClip::op(sk_sp<SkShader> sh) { 204cb93a386Sopenharmony_ci AUTO_RASTERCLIP_VALIDATE(*this); 205cb93a386Sopenharmony_ci 206cb93a386Sopenharmony_ci if (!fShader) { 207cb93a386Sopenharmony_ci fShader = sh; 208cb93a386Sopenharmony_ci } else { 209cb93a386Sopenharmony_ci fShader = SkShaders::Blend(SkBlendMode::kSrcIn, sh, fShader); 210cb93a386Sopenharmony_ci } 211cb93a386Sopenharmony_ci return !this->isEmpty(); 212cb93a386Sopenharmony_ci} 213cb93a386Sopenharmony_ci 214cb93a386Sopenharmony_cibool SkRasterClip::op(const SkRasterClip& clip, SkClipOp op) { 215cb93a386Sopenharmony_ci AUTO_RASTERCLIP_VALIDATE(*this); 216cb93a386Sopenharmony_ci clip.validate(); 217cb93a386Sopenharmony_ci 218cb93a386Sopenharmony_ci if (this->isBW() && clip.isBW()) { 219cb93a386Sopenharmony_ci (void)fBW.op(clip.fBW, (SkRegion::Op) op); 220cb93a386Sopenharmony_ci } else { 221cb93a386Sopenharmony_ci SkAAClip tmp; 222cb93a386Sopenharmony_ci const SkAAClip* other; 223cb93a386Sopenharmony_ci 224cb93a386Sopenharmony_ci if (this->isBW()) { 225cb93a386Sopenharmony_ci this->convertToAA(); 226cb93a386Sopenharmony_ci } 227cb93a386Sopenharmony_ci if (clip.isBW()) { 228cb93a386Sopenharmony_ci tmp.setRegion(clip.bwRgn()); 229cb93a386Sopenharmony_ci other = &tmp; 230cb93a386Sopenharmony_ci } else { 231cb93a386Sopenharmony_ci other = &clip.aaRgn(); 232cb93a386Sopenharmony_ci } 233cb93a386Sopenharmony_ci (void)fAA.op(*other, op); 234cb93a386Sopenharmony_ci } 235cb93a386Sopenharmony_ci return this->updateCacheAndReturnNonEmpty(); 236cb93a386Sopenharmony_ci} 237cb93a386Sopenharmony_ci 238cb93a386Sopenharmony_civoid SkRasterClip::translate(int dx, int dy, SkRasterClip* dst) const { 239cb93a386Sopenharmony_ci if (nullptr == dst) { 240cb93a386Sopenharmony_ci return; 241cb93a386Sopenharmony_ci } 242cb93a386Sopenharmony_ci 243cb93a386Sopenharmony_ci AUTO_RASTERCLIP_VALIDATE(*this); 244cb93a386Sopenharmony_ci 245cb93a386Sopenharmony_ci if (this->isEmpty()) { 246cb93a386Sopenharmony_ci dst->setEmpty(); 247cb93a386Sopenharmony_ci return; 248cb93a386Sopenharmony_ci } 249cb93a386Sopenharmony_ci if (0 == (dx | dy)) { 250cb93a386Sopenharmony_ci *dst = *this; 251cb93a386Sopenharmony_ci return; 252cb93a386Sopenharmony_ci } 253cb93a386Sopenharmony_ci 254cb93a386Sopenharmony_ci dst->fIsBW = fIsBW; 255cb93a386Sopenharmony_ci if (fIsBW) { 256cb93a386Sopenharmony_ci fBW.translate(dx, dy, &dst->fBW); 257cb93a386Sopenharmony_ci dst->fAA.setEmpty(); 258cb93a386Sopenharmony_ci } else { 259cb93a386Sopenharmony_ci fAA.translate(dx, dy, &dst->fAA); 260cb93a386Sopenharmony_ci dst->fBW.setEmpty(); 261cb93a386Sopenharmony_ci } 262cb93a386Sopenharmony_ci dst->updateCacheAndReturnNonEmpty(); 263cb93a386Sopenharmony_ci} 264cb93a386Sopenharmony_ci 265cb93a386Sopenharmony_civoid SkRasterClip::convertToAA() { 266cb93a386Sopenharmony_ci AUTO_RASTERCLIP_VALIDATE(*this); 267cb93a386Sopenharmony_ci 268cb93a386Sopenharmony_ci SkASSERT(fIsBW); 269cb93a386Sopenharmony_ci fAA.setRegion(fBW); 270cb93a386Sopenharmony_ci fIsBW = false; 271cb93a386Sopenharmony_ci 272cb93a386Sopenharmony_ci // since we are being explicitly asked to convert-to-aa, we pass false so we don't "optimize" 273cb93a386Sopenharmony_ci // ourselves back to BW. 274cb93a386Sopenharmony_ci (void)this->updateCacheAndReturnNonEmpty(false); 275cb93a386Sopenharmony_ci} 276cb93a386Sopenharmony_ci 277cb93a386Sopenharmony_ci#ifdef SK_DEBUG 278cb93a386Sopenharmony_civoid SkRasterClip::validate() const { 279cb93a386Sopenharmony_ci // can't ever assert that fBW is empty, since we may have called forceGetBW 280cb93a386Sopenharmony_ci if (fIsBW) { 281cb93a386Sopenharmony_ci SkASSERT(fAA.isEmpty()); 282cb93a386Sopenharmony_ci } 283cb93a386Sopenharmony_ci 284cb93a386Sopenharmony_ci SkRegionPriv::Validate(fBW); 285cb93a386Sopenharmony_ci fAA.validate(); 286cb93a386Sopenharmony_ci 287cb93a386Sopenharmony_ci SkASSERT(this->computeIsEmpty() == fIsEmpty); 288cb93a386Sopenharmony_ci SkASSERT(this->computeIsRect() == fIsRect); 289cb93a386Sopenharmony_ci} 290cb93a386Sopenharmony_ci#endif 291cb93a386Sopenharmony_ci 292cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 293cb93a386Sopenharmony_ci 294cb93a386Sopenharmony_ciSkAAClipBlitterWrapper::SkAAClipBlitterWrapper() { 295cb93a386Sopenharmony_ci SkDEBUGCODE(fClipRgn = nullptr;) 296cb93a386Sopenharmony_ci SkDEBUGCODE(fBlitter = nullptr;) 297cb93a386Sopenharmony_ci} 298cb93a386Sopenharmony_ci 299cb93a386Sopenharmony_ciSkAAClipBlitterWrapper::SkAAClipBlitterWrapper(const SkRasterClip& clip, 300cb93a386Sopenharmony_ci SkBlitter* blitter) { 301cb93a386Sopenharmony_ci this->init(clip, blitter); 302cb93a386Sopenharmony_ci} 303cb93a386Sopenharmony_ci 304cb93a386Sopenharmony_ciSkAAClipBlitterWrapper::SkAAClipBlitterWrapper(const SkAAClip* aaclip, 305cb93a386Sopenharmony_ci SkBlitter* blitter) { 306cb93a386Sopenharmony_ci SkASSERT(blitter); 307cb93a386Sopenharmony_ci SkASSERT(aaclip); 308cb93a386Sopenharmony_ci fBWRgn.setRect(aaclip->getBounds()); 309cb93a386Sopenharmony_ci fAABlitter.init(blitter, aaclip); 310cb93a386Sopenharmony_ci // now our return values 311cb93a386Sopenharmony_ci fClipRgn = &fBWRgn; 312cb93a386Sopenharmony_ci fBlitter = &fAABlitter; 313cb93a386Sopenharmony_ci} 314cb93a386Sopenharmony_ci 315cb93a386Sopenharmony_civoid SkAAClipBlitterWrapper::init(const SkRasterClip& clip, SkBlitter* blitter) { 316cb93a386Sopenharmony_ci SkASSERT(blitter); 317cb93a386Sopenharmony_ci if (clip.isBW()) { 318cb93a386Sopenharmony_ci fClipRgn = &clip.bwRgn(); 319cb93a386Sopenharmony_ci fBlitter = blitter; 320cb93a386Sopenharmony_ci } else { 321cb93a386Sopenharmony_ci const SkAAClip& aaclip = clip.aaRgn(); 322cb93a386Sopenharmony_ci fBWRgn.setRect(aaclip.getBounds()); 323cb93a386Sopenharmony_ci fAABlitter.init(blitter, &aaclip); 324cb93a386Sopenharmony_ci // now our return values 325cb93a386Sopenharmony_ci fClipRgn = &fBWRgn; 326cb93a386Sopenharmony_ci fBlitter = &fAABlitter; 327cb93a386Sopenharmony_ci } 328cb93a386Sopenharmony_ci} 329