/* * Copyright 2016 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef GrScissorState_DEFINED #define GrScissorState_DEFINED #include "include/core/SkRect.h" /** * The scissor state is stored as the scissor rectangle and the backing store bounds of the render * target that the scissor will apply to. If the render target is approximate fit and the padded * content should not be modified, the clip should apply the render target context's logical bounds * as part of the scissor (e.g. when stenciling). This puts the onus on the render target context * to intentionally discard the scissor at its logical bounds when drawing into the padded content * is acceptable (e.g. color-only updates). */ class GrScissorState { public: // The disabled scissor state for a render target of the given size. explicit GrScissorState(const SkISize& rtDims) : fRTSize(rtDims) , fRect(SkIRect::MakeSize(rtDims)) {} void setDisabled() { fRect = SkIRect::MakeSize(fRTSize); } bool set(const SkIRect& rect) { this->setDisabled(); return this->intersect(rect); } bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& rect) { if (!fRect.intersect(rect)) { fRect.setEmpty(); return false; } else { return true; } } // If the scissor was configured for the backing store dimensions and it's acceptable to // draw outside the logical dimensions of the target, this will discard the scissor test if // the test wouldn't modify the logical dimensions. bool relaxTest(const SkISize& logicalDimensions) { SkASSERT(logicalDimensions.fWidth <= fRTSize.fWidth && logicalDimensions.fHeight <= fRTSize.fHeight); if (fRect.fLeft == 0 && fRect.fTop == 0 && fRect.fRight >= logicalDimensions.fWidth && fRect.fBottom >= logicalDimensions.fHeight) { this->setDisabled(); return true; } else { return false; } } bool operator==(const GrScissorState& other) const { return fRTSize == other.fRTSize && fRect == other.fRect; } bool operator!=(const GrScissorState& other) const { return !(*this == other); } bool enabled() const { SkASSERT(fRect.isEmpty() || SkIRect::MakeSize(fRTSize).contains(fRect)); // This is equivalent to a strict contains check on SkIRect::MakeSize(rtSize) w/o creating // the render target bounding rectangle. return fRect.fLeft > 0 || fRect.fTop > 0 || fRect.fRight < fRTSize.fWidth || fRect.fBottom < fRTSize.fHeight; } // Will always be equal to or contained in the rt bounds, or empty if scissor rectangles were // added that did not intersect with the render target or prior scissor. const SkIRect& rect() const { SkASSERT(fRect.isEmpty() || SkIRect::MakeSize(fRTSize).contains(fRect)); return fRect; } private: // The scissor is considered enabled if the rectangle does not cover the render target SkISize fRTSize; SkIRect fRect; }; #endif