1 /* 2 * Copyright 2017 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 "SkClipStackDevice.h" 9 #include "SkDraw.h" 10 #include "SkRasterClip.h" 11 12 SkIRect SkClipStackDevice::devClipBounds() const { 13 SkIRect r = fClipStack.bounds(this->imageInfo().bounds()).roundOut(); 14 if (!r.isEmpty()) { 15 SkASSERT(this->imageInfo().bounds().contains(r)); 16 } 17 return r; 18 } 19 20 /////////////////////////////////////////////////////////////////////////////////////////////////// 21 22 void SkClipStackDevice::onSave() { 23 fClipStack.save(); 24 } 25 26 void SkClipStackDevice::onRestore() { 27 fClipStack.restore(); 28 } 29 30 void SkClipStackDevice::onClipRect(const SkRect& rect, SkClipOp op, bool aa) { 31 fClipStack.clipRect(rect, this->ctm(), op, aa); 32 } 33 34 void SkClipStackDevice::onClipRRect(const SkRRect& rrect, SkClipOp op, bool aa) { 35 fClipStack.clipRRect(rrect, this->ctm(), op, aa); 36 } 37 38 void SkClipStackDevice::onClipPath(const SkPath& path, SkClipOp op, bool aa) { 39 fClipStack.clipPath(path, this->ctm(), op, aa); 40 } 41 42 void SkClipStackDevice::onClipRegion(const SkRegion& rgn, SkClipOp op) { 43 SkIPoint origin = this->getOrigin(); 44 SkRegion tmp; 45 const SkRegion* ptr = &rgn; 46 if (origin.fX | origin.fY) { 47 // translate from "global/canvas" coordinates to relative to this device 48 rgn.translate(-origin.fX, -origin.fY, &tmp); 49 ptr = &tmp; 50 } 51 fClipStack.clipDevRect(ptr->getBounds(), op); 52 } 53 54 void SkClipStackDevice::onSetDeviceClipRestriction(SkIRect* clipRestriction) { 55 if (clipRestriction->isEmpty()) { 56 fClipStack.setDeviceClipRestriction(*clipRestriction); 57 } else { 58 SkIPoint origin = this->getOrigin(); 59 SkIRect rect = clipRestriction->makeOffset(-origin.x(), -origin.y()); 60 fClipStack.setDeviceClipRestriction(rect); 61 fClipStack.clipDevRect(rect, SkClipOp::kIntersect); 62 } 63 } 64 65 bool SkClipStackDevice::onClipIsAA() const { 66 SkClipStack::B2TIter iter(fClipStack); 67 const SkClipStack::Element* element; 68 69 while ((element = iter.next()) != nullptr) { 70 if (element->isAA()) { 71 return true; 72 } 73 } 74 return false; 75 } 76 77 void SkClipStackDevice::onAsRgnClip(SkRegion* rgn) const { 78 SkClipStack::BoundsType boundType; 79 bool isIntersectionOfRects; 80 SkRect bounds; 81 fClipStack.getBounds(&bounds, &boundType, &isIntersectionOfRects); 82 if (isIntersectionOfRects && SkClipStack::kNormal_BoundsType == boundType) { 83 rgn->setRect(bounds.round()); 84 } else { 85 SkPath path; 86 fClipStack.asPath(&path); 87 rgn->setPath(path, SkRegion(SkIRect::MakeWH(this->width(), this->height()))); 88 } 89 } 90 91 SkBaseDevice::ClipType SkClipStackDevice::onGetClipType() const { 92 if (fClipStack.isWideOpen()) { 93 return kRect_ClipType; 94 } 95 if (fClipStack.isEmpty(SkIRect::MakeWH(this->width(), this->height()))) { 96 return kEmpty_ClipType; 97 } else { 98 SkClipStack::BoundsType boundType; 99 bool isIntersectionOfRects; 100 SkRect bounds; 101 fClipStack.getBounds(&bounds, &boundType, &isIntersectionOfRects); 102 if (isIntersectionOfRects && SkClipStack::kNormal_BoundsType == boundType) { 103 return kRect_ClipType; 104 } else { 105 return kComplex_ClipType; 106 } 107 } 108 } 109