/* * Copyright 2011 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "GrPathRenderer.h" #include "GrCaps.h" #include "GrContextPriv.h" #include "GrPaint.h" #include "GrRenderTargetContext.h" #include "GrShape.h" #include "GrUserStencilSettings.h" #include "SkDrawProcs.h" #ifdef SK_DEBUG void GrPathRenderer::StencilPathArgs::validate() const { SkASSERT(fContext); SkASSERT(fRenderTargetContext); SkASSERT(fClipConservativeBounds); SkASSERT(fViewMatrix); SkASSERT(fShape); SkASSERT(fShape->style().isSimpleFill()); SkASSERT(GrAAType::kCoverage != fAAType); SkPath path; fShape->asPath(&path); SkASSERT(!path.isInverseFillType()); } #endif ////////////////////////////////////////////////////////////////////////////// GrPathRenderer::GrPathRenderer() {} GrPathRenderer::StencilSupport GrPathRenderer::getStencilSupport(const GrShape& shape) const { SkDEBUGCODE(SkPath path;) SkDEBUGCODE(shape.asPath(&path);) SkASSERT(shape.style().isSimpleFill()); SkASSERT(!path.isInverseFillType()); return this->onGetStencilSupport(shape); } bool GrPathRenderer::drawPath(const DrawPathArgs& args) { #ifdef SK_DEBUG args.validate(); CanDrawPathArgs canArgs; canArgs.fCaps = args.fContext->contextPriv().caps(); canArgs.fClipConservativeBounds = args.fClipConservativeBounds; canArgs.fViewMatrix = args.fViewMatrix; canArgs.fShape = args.fShape; canArgs.fAAType = args.fAAType; canArgs.fTargetIsWrappedVkSecondaryCB = args.fRenderTargetContext->wrapsVkSecondaryCB(); canArgs.validate(); canArgs.fHasUserStencilSettings = !args.fUserStencilSettings->isUnused(); SkASSERT(!(canArgs.fAAType == GrAAType::kMSAA && GrFSAAType::kUnifiedMSAA != args.fRenderTargetContext->fsaaType())); SkASSERT(!(canArgs.fAAType == GrAAType::kMixedSamples && GrFSAAType::kMixedSamples != args.fRenderTargetContext->fsaaType())); SkASSERT(CanDrawPath::kNo != this->canDrawPath(canArgs)); if (!args.fUserStencilSettings->isUnused()) { SkPath path; args.fShape->asPath(&path); SkASSERT(args.fShape->style().isSimpleFill()); SkASSERT(kNoRestriction_StencilSupport == this->getStencilSupport(*args.fShape)); } #endif return this->onDrawPath(args); } bool GrPathRenderer::IsStrokeHairlineOrEquivalent(const GrStyle& style, const SkMatrix& matrix, SkScalar* outCoverage) { if (style.pathEffect()) { return false; } const SkStrokeRec& stroke = style.strokeRec(); if (stroke.isHairlineStyle()) { if (outCoverage) { *outCoverage = SK_Scalar1; } return true; } return stroke.getStyle() == SkStrokeRec::kStroke_Style && SkDrawTreatAAStrokeAsHairline(stroke.getWidth(), matrix, outCoverage); } void GrPathRenderer::GetPathDevBounds(const SkPath& path, int devW, int devH, const SkMatrix& matrix, SkRect* bounds) { if (path.isInverseFillType()) { *bounds = SkRect::MakeWH(SkIntToScalar(devW), SkIntToScalar(devH)); return; } *bounds = path.getBounds(); matrix.mapRect(bounds); } void GrPathRenderer::onStencilPath(const StencilPathArgs& args) { static constexpr GrUserStencilSettings kIncrementStencil( GrUserStencilSettings::StaticInit< 0xffff, GrUserStencilTest::kAlways, 0xffff, GrUserStencilOp::kReplace, GrUserStencilOp::kReplace, 0xffff>() ); GrPaint paint; DrawPathArgs drawArgs{args.fContext, std::move(paint), &kIncrementStencil, args.fRenderTargetContext, nullptr, // clip args.fClipConservativeBounds, args.fViewMatrix, args.fShape, args.fAAType, false}; this->drawPath(drawArgs); }