/*
* 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);
}