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