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
devClipBounds() const12 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
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->ctm(), 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->ctm(), 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->ctm(), op, aa);
40 }
41
onClipRegion(const SkRegion & rgn,SkClipOp op)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
onSetDeviceClipRestriction(SkIRect * clipRestriction)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
onClipIsAA() const65 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
onAsRgnClip(SkRegion * rgn) const77 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
onGetClipType() const91 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