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