/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrGpu.h"
#include "GrPathRendering.h"
#include "SkDescriptor.h"
#include "SkScalerContext.h"
#include "SkGlyph.h"
#include "SkMatrix.h"
#include "SkTypeface.h"
#include "GrPathRange.h"

const GrUserStencilSettings& GrPathRendering::GetStencilPassSettings(FillType fill) {
    switch (fill) {
        default:
            SK_ABORT("Unexpected path fill.");
        case GrPathRendering::kWinding_FillType: {
            constexpr static GrUserStencilSettings kWindingStencilPass(
                GrUserStencilSettings::StaticInit<
                    0xffff,
                    GrUserStencilTest::kAlwaysIfInClip,
                    0xffff,
                    GrUserStencilOp::kIncWrap,
                    GrUserStencilOp::kIncWrap,
                    0xffff>()
            );
            return kWindingStencilPass;
        }
        case GrPathRendering::kEvenOdd_FillType: {
            constexpr static GrUserStencilSettings kEvenOddStencilPass(
                GrUserStencilSettings::StaticInit<
                    0xffff,
                    GrUserStencilTest::kAlwaysIfInClip,
                    0xffff,
                    GrUserStencilOp::kInvert,
                    GrUserStencilOp::kInvert,
                    0xffff>()
            );
            return kEvenOddStencilPass;
        }
    }
}

class GlyphGenerator : public GrPathRange::PathGenerator {
public:
    GlyphGenerator(const SkTypeface& typeface, const SkScalerContextEffects& effects,
                   const SkDescriptor& desc)
        : fScalerContext(typeface.createScalerContext(effects, &desc))
#ifdef SK_DEBUG
        , fDesc(desc.copy())
#endif
    {}

    int getNumPaths() override {
        return fScalerContext->getGlyphCount();
    }

    void generatePath(int glyphID, SkPath* out) override {
        fScalerContext->getPath(glyphID, out);
    }
#ifdef SK_DEBUG
    bool isEqualTo(const SkDescriptor& desc) const override { return *fDesc == desc; }
#endif
private:
    const std::unique_ptr<SkScalerContext> fScalerContext;
#ifdef SK_DEBUG
    const std::unique_ptr<SkDescriptor> fDesc;
#endif
};

sk_sp<GrPathRange> GrPathRendering::createGlyphs(const SkTypeface* typeface,
                                                 const SkScalerContextEffects& effects,
                                                 const SkDescriptor* desc,
                                                 const GrStyle& style) {
    if (nullptr == typeface) {
        typeface = SkTypeface::GetDefaultTypeface();
        SkASSERT(nullptr != typeface);
    }

    if (desc) {
        sk_sp<GlyphGenerator> generator(new GlyphGenerator(*typeface, effects, *desc));
        return this->createPathRange(generator.get(), style);
    }

    SkScalerContextRec rec;
    memset(&rec, 0, sizeof(rec));
    rec.fFontID = typeface->uniqueID();
    rec.fTextSize = SkPaint::kCanonicalTextSizeForPaths;
    rec.fPreScaleX = rec.fPost2x2[0][0] = rec.fPost2x2[1][1] = SK_Scalar1;
    // Don't bake stroke information into the glyphs, we'll let the GPU do the stroking.

    SkAutoDescriptor ad(sizeof(rec) + SkDescriptor::ComputeOverhead(1));
    SkDescriptor*    genericDesc = ad.getDesc();

    genericDesc->init();
    genericDesc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
    genericDesc->computeChecksum();

    // No effects, so we make a dummy struct
    SkScalerContextEffects noEffects;

    sk_sp<GlyphGenerator> generator(new GlyphGenerator(*typeface, noEffects, *genericDesc));
    return this->createPathRange(generator.get(), style);
}

void GrPathRendering::stencilPath(const StencilPathArgs& args, const GrPath* path) {
    fGpu->handleDirtyContext();
    this->onStencilPath(args, path);
}

void GrPathRendering::drawPath(const GrPipeline& pipeline,
                               const GrPrimitiveProcessor& primProc,
                               // Cover pass settings in pipeline.
                               const GrStencilSettings& stencilPassSettings,
                               const GrPath* path) {
    fGpu->handleDirtyContext();
    if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*fGpu->caps())) {
        fGpu->xferBarrier(pipeline.renderTarget(), barrierType);
    }
    this->onDrawPath(pipeline, primProc, stencilPassSettings, path);
}

void GrPathRendering::drawPaths(const GrPipeline& pipeline,
                                const GrPrimitiveProcessor& primProc,
                                // Cover pass settings in pipeline.
                                const GrStencilSettings& stencilPassSettings,
                                const GrPathRange* pathRange,
                                const void* indices,
                                PathIndexType indexType,
                                const float transformValues[],
                                PathTransformType transformType,
                                int count) {
    fGpu->handleDirtyContext();
    if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*fGpu->caps())) {
        fGpu->xferBarrier(pipeline.renderTarget(), barrierType);
    }
#ifdef SK_DEBUG
    pathRange->assertPathsLoaded(indices, indexType, count);
#endif
    this->onDrawPaths(pipeline, primProc, stencilPassSettings, pathRange, indices, indexType,
                      transformValues, transformType, count);
}
