/* * Copyright 2017 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "SkClipStackDevice.h" #include "SkDraw.h" #include "SkRasterClip.h" SkIRect SkClipStackDevice::devClipBounds() const { SkIRect r = fClipStack.bounds(this->imageInfo().bounds()).roundOut(); if (!r.isEmpty()) { SkASSERT(this->imageInfo().bounds().contains(r)); } return r; } /////////////////////////////////////////////////////////////////////////////////////////////////// void SkClipStackDevice::onSave() { fClipStack.save(); } void SkClipStackDevice::onRestore() { fClipStack.restore(); } void SkClipStackDevice::onClipRect(const SkRect& rect, SkClipOp op, bool aa) { fClipStack.clipRect(rect, this->ctm(), op, aa); } void SkClipStackDevice::onClipRRect(const SkRRect& rrect, SkClipOp op, bool aa) { fClipStack.clipRRect(rrect, this->ctm(), op, aa); } void SkClipStackDevice::onClipPath(const SkPath& path, SkClipOp op, bool aa) { fClipStack.clipPath(path, this->ctm(), op, aa); } void SkClipStackDevice::onClipRegion(const SkRegion& rgn, SkClipOp op) { SkIPoint origin = this->getOrigin(); SkRegion tmp; const SkRegion* ptr = &rgn; if (origin.fX | origin.fY) { // translate from "global/canvas" coordinates to relative to this device rgn.translate(-origin.fX, -origin.fY, &tmp); ptr = &tmp; } fClipStack.clipDevRect(ptr->getBounds(), op); } void SkClipStackDevice::onSetDeviceClipRestriction(SkIRect* clipRestriction) { if (clipRestriction->isEmpty()) { fClipStack.setDeviceClipRestriction(*clipRestriction); } else { SkIPoint origin = this->getOrigin(); SkIRect rect = clipRestriction->makeOffset(-origin.x(), -origin.y()); fClipStack.setDeviceClipRestriction(rect); fClipStack.clipDevRect(rect, SkClipOp::kIntersect); } } bool SkClipStackDevice::onClipIsAA() const { SkClipStack::B2TIter iter(fClipStack); const SkClipStack::Element* element; while ((element = iter.next()) != nullptr) { if (element->isAA()) { return true; } } return false; } void SkClipStackDevice::onAsRgnClip(SkRegion* rgn) const { SkClipStack::BoundsType boundType; bool isIntersectionOfRects; SkRect bounds; fClipStack.getBounds(&bounds, &boundType, &isIntersectionOfRects); if (isIntersectionOfRects && SkClipStack::kNormal_BoundsType == boundType) { rgn->setRect(bounds.round()); } else { SkPath path; fClipStack.asPath(&path); rgn->setPath(path, SkRegion(SkIRect::MakeWH(this->width(), this->height()))); } } SkBaseDevice::ClipType SkClipStackDevice::onGetClipType() const { if (fClipStack.isWideOpen()) { return kRect_ClipType; } if (fClipStack.isEmpty(SkIRect::MakeWH(this->width(), this->height()))) { return kEmpty_ClipType; } else { SkClipStack::BoundsType boundType; bool isIntersectionOfRects; SkRect bounds; fClipStack.getBounds(&bounds, &boundType, &isIntersectionOfRects); if (isIntersectionOfRects && SkClipStack::kNormal_BoundsType == boundType) { return kRect_ClipType; } else { return kComplex_ClipType; } } }