• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "src/core/SkClipStackDevice.h"
9 #include "src/core/SkDraw.h"
10 #include "src/core/SkRasterClip.h"
11 
onDevClipBounds() const12 SkIRect SkClipStackDevice::onDevClipBounds() 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 
onSave()22 void SkClipStackDevice::onSave() {
23     fClipStack.save();
24 }
25 
onRestore()26 void SkClipStackDevice::onRestore() {
27     fClipStack.restore();
28 }
29 
onClipRect(const SkRect & rect,SkClipOp op,bool aa)30 void SkClipStackDevice::onClipRect(const SkRect& rect, SkClipOp op, bool aa) {
31     fClipStack.clipRect(rect, this->localToDevice(), op, aa);
32 }
33 
onClipRRect(const SkRRect & rrect,SkClipOp op,bool aa)34 void SkClipStackDevice::onClipRRect(const SkRRect& rrect, SkClipOp op, bool aa) {
35     fClipStack.clipRRect(rrect, this->localToDevice(), op, aa);
36 }
37 
onClipPath(const SkPath & path,SkClipOp op,bool aa)38 void SkClipStackDevice::onClipPath(const SkPath& path, SkClipOp op, bool aa) {
39     fClipStack.clipPath(path, this->localToDevice(), op, aa);
40 }
41 
onClipShader(sk_sp<SkShader> shader)42 void SkClipStackDevice::onClipShader(sk_sp<SkShader> shader) {
43     fClipStack.clipShader(std::move(shader));
44 }
45 
onClipRegion(const SkRegion & rgn,SkClipOp op)46 void SkClipStackDevice::onClipRegion(const SkRegion& rgn, SkClipOp op) {
47     SkIPoint origin = this->getOrigin();
48     SkRegion tmp;
49     SkPath path;
50     rgn.getBoundaryPath(&path);
51     path.transform(SkMatrix::Translate(-origin));
52     fClipStack.clipPath(path, SkMatrix::I(), op, false);
53 }
54 
onReplaceClip(const SkIRect & rect)55 void SkClipStackDevice::onReplaceClip(const SkIRect& rect) {
56     // FIXME When the deprecated clip ops are completely removed, SkClipStack will need to be
57     // updated to have a better way of tracking replacement.
58     fClipStack.clipRect(SkRect::Make(rect), this->globalToDevice(), kReplace_SkClipOp, false);
59 }
60 
onSetDeviceClipRestriction(SkIRect * clipRestriction)61 void SkClipStackDevice::onSetDeviceClipRestriction(SkIRect* clipRestriction) {
62     if (clipRestriction->isEmpty()) {
63         fClipStack.setDeviceClipRestriction(*clipRestriction);
64     } else {
65         SkIPoint origin = this->getOrigin();
66         SkIRect rect = clipRestriction->makeOffset(-origin);
67         fClipStack.setDeviceClipRestriction(rect);
68         fClipStack.clipDevRect(rect, SkClipOp::kIntersect);
69     }
70 }
71 
onClipIsAA() const72 bool SkClipStackDevice::onClipIsAA() const {
73     SkClipStack::B2TIter        iter(fClipStack);
74     const SkClipStack::Element* element;
75 
76     while ((element = iter.next()) != nullptr) {
77         if (element->isAA()) {
78             return true;
79         }
80     }
81     return false;
82 }
83 
onClipIsWideOpen() const84 bool SkClipStackDevice::onClipIsWideOpen() const {
85     return fClipStack.quickContains(SkRect::MakeIWH(this->width(), this->height()));
86 }
87 
onAsRgnClip(SkRegion * rgn) const88 void SkClipStackDevice::onAsRgnClip(SkRegion* rgn) const {
89     SkClipStack::BoundsType boundType;
90     bool isIntersectionOfRects;
91     SkRect bounds;
92     fClipStack.getBounds(&bounds, &boundType, &isIntersectionOfRects);
93     if (isIntersectionOfRects && SkClipStack::kNormal_BoundsType == boundType) {
94         rgn->setRect(bounds.round());
95     } else {
96         SkRegion boundsRgn({0, 0, this->width(), this->height()});
97         SkPath tmpPath;
98 
99         *rgn = boundsRgn;
100         SkClipStack::B2TIter iter(fClipStack);
101         while (auto elem = iter.next()) {
102             tmpPath.rewind();
103             elem->asDeviceSpacePath(&tmpPath);
104             SkRegion tmpRgn;
105             tmpRgn.setPath(tmpPath, boundsRgn);
106             rgn->op(tmpRgn, SkRegion::Op(elem->getOp()));
107         }
108     }
109 }
110 
onGetClipType() const111 SkBaseDevice::ClipType SkClipStackDevice::onGetClipType() const {
112     if (fClipStack.isWideOpen()) {
113         return ClipType::kRect;
114     }
115     if (fClipStack.isEmpty(SkIRect::MakeWH(this->width(), this->height()))) {
116         return ClipType::kEmpty;
117     } else {
118         SkClipStack::BoundsType boundType;
119         bool isIntersectionOfRects;
120         SkRect bounds;
121         fClipStack.getBounds(&bounds, &boundType, &isIntersectionOfRects);
122         if (isIntersectionOfRects && SkClipStack::kNormal_BoundsType == boundType) {
123             return ClipType::kRect;
124         } else {
125             return ClipType::kComplex;
126         }
127     }
128 }
129