1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2017 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 "src/core/SkClipStackDevice.h"
9cb93a386Sopenharmony_ci#include "src/core/SkDraw.h"
10cb93a386Sopenharmony_ci#include "src/core/SkRasterClip.h"
11cb93a386Sopenharmony_ci
12cb93a386Sopenharmony_ciSkIRect SkClipStackDevice::onDevClipBounds() const {
13cb93a386Sopenharmony_ci    SkIRect r = fClipStack.bounds(this->imageInfo().bounds()).roundOut();
14cb93a386Sopenharmony_ci    if (!r.isEmpty()) {
15cb93a386Sopenharmony_ci        SkASSERT(this->imageInfo().bounds().contains(r));
16cb93a386Sopenharmony_ci    }
17cb93a386Sopenharmony_ci    return r;
18cb93a386Sopenharmony_ci}
19cb93a386Sopenharmony_ci
20cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////////////////////////
21cb93a386Sopenharmony_ci
22cb93a386Sopenharmony_civoid SkClipStackDevice::onSave() {
23cb93a386Sopenharmony_ci    fClipStack.save();
24cb93a386Sopenharmony_ci}
25cb93a386Sopenharmony_ci
26cb93a386Sopenharmony_civoid SkClipStackDevice::onRestore() {
27cb93a386Sopenharmony_ci    fClipStack.restore();
28cb93a386Sopenharmony_ci}
29cb93a386Sopenharmony_ci
30cb93a386Sopenharmony_civoid SkClipStackDevice::onClipRect(const SkRect& rect, SkClipOp op, bool aa) {
31cb93a386Sopenharmony_ci    fClipStack.clipRect(rect, this->localToDevice(), op, aa);
32cb93a386Sopenharmony_ci}
33cb93a386Sopenharmony_ci
34cb93a386Sopenharmony_civoid SkClipStackDevice::onClipRRect(const SkRRect& rrect, SkClipOp op, bool aa) {
35cb93a386Sopenharmony_ci    fClipStack.clipRRect(rrect, this->localToDevice(), op, aa);
36cb93a386Sopenharmony_ci}
37cb93a386Sopenharmony_ci
38cb93a386Sopenharmony_civoid SkClipStackDevice::onClipPath(const SkPath& path, SkClipOp op, bool aa) {
39cb93a386Sopenharmony_ci    fClipStack.clipPath(path, this->localToDevice(), op, aa);
40cb93a386Sopenharmony_ci}
41cb93a386Sopenharmony_ci
42cb93a386Sopenharmony_civoid SkClipStackDevice::onClipShader(sk_sp<SkShader> shader) {
43cb93a386Sopenharmony_ci    fClipStack.clipShader(std::move(shader));
44cb93a386Sopenharmony_ci}
45cb93a386Sopenharmony_ci
46cb93a386Sopenharmony_civoid SkClipStackDevice::onClipRegion(const SkRegion& rgn, SkClipOp op) {
47cb93a386Sopenharmony_ci    SkIPoint origin = this->getOrigin();
48cb93a386Sopenharmony_ci    SkRegion tmp;
49cb93a386Sopenharmony_ci    SkPath path;
50cb93a386Sopenharmony_ci    rgn.getBoundaryPath(&path);
51cb93a386Sopenharmony_ci    path.transform(SkMatrix::Translate(-origin));
52cb93a386Sopenharmony_ci    fClipStack.clipPath(path, SkMatrix::I(), op, false);
53cb93a386Sopenharmony_ci}
54cb93a386Sopenharmony_ci
55cb93a386Sopenharmony_civoid SkClipStackDevice::onReplaceClip(const SkIRect& rect) {
56cb93a386Sopenharmony_ci    SkRect deviceRect = SkMatrixPriv::MapRect(this->globalToDevice(), SkRect::Make(rect));
57cb93a386Sopenharmony_ci    fClipStack.replaceClip(deviceRect, /*doAA=*/false);
58cb93a386Sopenharmony_ci}
59cb93a386Sopenharmony_ci
60cb93a386Sopenharmony_cibool SkClipStackDevice::onClipIsAA() const {
61cb93a386Sopenharmony_ci    SkClipStack::B2TIter        iter(fClipStack);
62cb93a386Sopenharmony_ci    const SkClipStack::Element* element;
63cb93a386Sopenharmony_ci
64cb93a386Sopenharmony_ci    while ((element = iter.next()) != nullptr) {
65cb93a386Sopenharmony_ci        if (element->isAA()) {
66cb93a386Sopenharmony_ci            return true;
67cb93a386Sopenharmony_ci        }
68cb93a386Sopenharmony_ci    }
69cb93a386Sopenharmony_ci    return false;
70cb93a386Sopenharmony_ci}
71cb93a386Sopenharmony_ci
72cb93a386Sopenharmony_cibool SkClipStackDevice::onClipIsWideOpen() const {
73cb93a386Sopenharmony_ci    return fClipStack.quickContains(SkRect::MakeIWH(this->width(), this->height()));
74cb93a386Sopenharmony_ci}
75cb93a386Sopenharmony_ci
76cb93a386Sopenharmony_civoid SkClipStackDevice::onAsRgnClip(SkRegion* rgn) const {
77cb93a386Sopenharmony_ci    SkClipStack::BoundsType boundType;
78cb93a386Sopenharmony_ci    bool isIntersectionOfRects;
79cb93a386Sopenharmony_ci    SkRect bounds;
80cb93a386Sopenharmony_ci    fClipStack.getBounds(&bounds, &boundType, &isIntersectionOfRects);
81cb93a386Sopenharmony_ci    if (isIntersectionOfRects && SkClipStack::kNormal_BoundsType == boundType) {
82cb93a386Sopenharmony_ci        rgn->setRect(bounds.round());
83cb93a386Sopenharmony_ci    } else {
84cb93a386Sopenharmony_ci        SkRegion boundsRgn({0, 0, this->width(), this->height()});
85cb93a386Sopenharmony_ci        SkPath tmpPath;
86cb93a386Sopenharmony_ci
87cb93a386Sopenharmony_ci        *rgn = boundsRgn;
88cb93a386Sopenharmony_ci        SkClipStack::B2TIter iter(fClipStack);
89cb93a386Sopenharmony_ci        while (auto elem = iter.next()) {
90cb93a386Sopenharmony_ci            tmpPath.rewind();
91cb93a386Sopenharmony_ci            elem->asDeviceSpacePath(&tmpPath);
92cb93a386Sopenharmony_ci            SkRegion tmpRgn;
93cb93a386Sopenharmony_ci            tmpRgn.setPath(tmpPath, boundsRgn);
94cb93a386Sopenharmony_ci            if (elem->isReplaceOp()) {
95cb93a386Sopenharmony_ci                // All replace elements are rectangles
96cb93a386Sopenharmony_ci                // TODO: SkClipStack can be simplified to be I,D,R ops now, which means element
97cb93a386Sopenharmony_ci                // iteration can be from top of the stack to the most recent replace element.
98cb93a386Sopenharmony_ci                // When that's done, this loop will be simplifiable.
99cb93a386Sopenharmony_ci                rgn->setRect(elem->getDeviceSpaceRect().round());
100cb93a386Sopenharmony_ci            } else {
101cb93a386Sopenharmony_ci                rgn->op(tmpRgn, static_cast<SkRegion::Op>(elem->getOp()));
102cb93a386Sopenharmony_ci            }
103cb93a386Sopenharmony_ci        }
104cb93a386Sopenharmony_ci    }
105cb93a386Sopenharmony_ci}
106cb93a386Sopenharmony_ci
107cb93a386Sopenharmony_ciSkBaseDevice::ClipType SkClipStackDevice::onGetClipType() const {
108cb93a386Sopenharmony_ci    if (fClipStack.isWideOpen()) {
109cb93a386Sopenharmony_ci        return ClipType::kRect;
110cb93a386Sopenharmony_ci    }
111cb93a386Sopenharmony_ci    if (fClipStack.isEmpty(SkIRect::MakeWH(this->width(), this->height()))) {
112cb93a386Sopenharmony_ci        return ClipType::kEmpty;
113cb93a386Sopenharmony_ci    } else {
114cb93a386Sopenharmony_ci        SkClipStack::BoundsType boundType;
115cb93a386Sopenharmony_ci        bool isIntersectionOfRects;
116cb93a386Sopenharmony_ci        SkRect bounds;
117cb93a386Sopenharmony_ci        fClipStack.getBounds(&bounds, &boundType, &isIntersectionOfRects);
118cb93a386Sopenharmony_ci        if (isIntersectionOfRects && SkClipStack::kNormal_BoundsType == boundType) {
119cb93a386Sopenharmony_ci            return ClipType::kRect;
120cb93a386Sopenharmony_ci        } else {
121cb93a386Sopenharmony_ci            return ClipType::kComplex;
122cb93a386Sopenharmony_ci        }
123cb93a386Sopenharmony_ci    }
124cb93a386Sopenharmony_ci}
125