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