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

#include "bench/Benchmark.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkFont.h"
#include "include/core/SkTypeface.h"
#include "include/gpu/ganesh/GrDirectContext.h"
#include "include/gpu/ganesh/GrRecordingContext.h"
#include "src/core/SkStrikeCache.h"
#include "src/core/SkUTF.h"
#include "src/core/SkUtils.h"
#include "src/gpu/ganesh/GrRecordingContextPriv.h"
#include "src/gpu/ganesh/SkGr.h"
#include "src/gpu/ganesh/text/GlyphData.h"
#include "src/text/GlyphRun.h"
#include "src/text/gpu/StrikeCache.h"
#include "src/text/gpu/TextBlob.h"
#include "tools/fonts/FontToolUtils.h"
#include "tools/ganesh/TestCanvas.h"
#include "tools/text/gpu/TextBlobTools.h"

// From Project Guttenberg. This is UTF-8 text.
static const char* gText =
        "Call me Ishmael.  Some years ago--never mind how long precisely";

class FillBench {};
template <> class skiatest::TestCanvas<FillBench> {
public:
    static SkDevice* GetDevice(SkCanvas* canvas) {
        return canvas->topDevice();
    }
};

class DirectMaskGlyphVertexFillBenchmark : public Benchmark {
    using Glyph = skgpu::ganesh::Glyph;
    using GlyphData = skgpu::ganesh::GlyphData;

    bool isSuitableFor(Backend backend) override {
        return backend == Backend::kGanesh;
    }

    const char* onGetName() override {
        return "DirectMaskGlyphVertexFillBenchmark";
    }

    void onPerCanvasPreDraw(SkCanvas* canvas) override {
        auto typeface = ToolUtils::CreateTestTypeface("monospace", SkFontStyle());
        SkFont font(typeface);

        SkMatrix view = SkMatrix::I();
        size_t len = strlen(gText);
        sktext::GlyphRunBuilder builder;
        SkPaint paint;
        auto glyphRunList = builder.textToGlyphRunList(font, paint, gText, len, {100, 100});
        SkASSERT_RELEASE(!glyphRunList.empty());
        auto device = skiatest::TestCanvas<FillBench>::GetDevice(canvas);
        SkMatrix drawMatrix = view;
        const SkPoint drawOrigin = glyphRunList.origin();
        drawMatrix.preTranslate(drawOrigin.x(), drawOrigin.y());
        fBlob = sktext::gpu::TextBlob::Make(glyphRunList,
                                            paint,
                                            drawMatrix,
                                            device->strikeDeviceInfo(),
                                            SkStrikeCache::GlobalStrikeCache());

        const sktext::gpu::AtlasSubRun* subRun =
                sktext::gpu::TextBlobTools::FirstSubRun(fBlob.get());
        SkASSERT_RELEASE(subRun);
        if (!subRun->glyphVector().hasBackendData()) {
            subRun->glyphVector().initBackendData<GlyphData>(&fCache, subRun->maskFormat());
        }
        const auto& glyphData = subRun->glyphVector().accessBackendData<GlyphData>();
        fVertices.reset(new char[glyphData.vertexStride(subRun->maskFormat(), drawMatrix) *
                                 subRun->glyphCount() * 4]);
    }

    void onDraw(int loops, SkCanvas* canvas) override {
        const sktext::gpu::AtlasSubRun* subRun =
                sktext::gpu::TextBlobTools::FirstSubRun(fBlob.get());
        SkASSERT_RELEASE(subRun);

        SkIRect clip = SkIRect::MakeEmpty();
        SkPaint paint;
        SkPMColor4f pmColor = SkColorToPMColor4f(paint.getColor(), /*colorInfo=*/{});
        SkMatrix positionMatrix = SkMatrix::Translate(100, 100);

        auto& glyphData = subRun->glyphVector().accessBackendData<GlyphData>();
        SkSpan<const Glyph> glyphs = subRun->glyphVector().accessBackendGlyphs<Glyph>();
        for (int loop = 0; loop < loops; loop++) {
            glyphData.fillVertexData(subRun->vertexFiller(),
                                     glyphs,
                                     0,
                                     subRun->glyphCount(),
                                     pmColor,
                                     positionMatrix,
                                     clip,
                                     fVertices.get());
        }
    }

private:
    sk_sp<sktext::gpu::TextBlob> fBlob;
    sktext::gpu::StrikeCache fCache;
    std::unique_ptr<char[]> fVertices;
};

DEF_BENCH(return new DirectMaskGlyphVertexFillBenchmark{})
