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

#include "Benchmark.h"

#include "Resources.h"
#include "SkAutoPixmapStorage.h"
#include "SkData.h"
#include "SkExecutor.h"
#include "SkFloatToDecimal.h"
#include "SkGradientShader.h"
#include "SkImage.h"
#include "SkPDFUnion.h"
#include "SkPixmap.h"
#include "SkRandom.h"
#include "SkStream.h"
#include "SkTo.h"

namespace {
struct WStreamWriteTextBenchmark : public Benchmark {
    std::unique_ptr<SkWStream> fWStream;
    WStreamWriteTextBenchmark() : fWStream(new SkNullWStream) {}
    const char* onGetName() override { return "WStreamWriteText"; }
    bool isSuitableFor(Backend backend) override {
        return backend == kNonRendering_Backend;
    }
    void onDraw(int loops, SkCanvas*) override {
        while (loops-- > 0) {
            for (int i = 1000; i-- > 0;) {
                fWStream->writeText("HELLO SKIA!\n");
            }
        }
    }
};
}  // namespace

DEF_BENCH(return new WStreamWriteTextBenchmark;)

// Test speed of SkFloatToDecimal for typical floats that
// might be found in a PDF document.
struct PDFScalarBench : public Benchmark {
    PDFScalarBench(const char* n, float (*f)(SkRandom*)) : fName(n), fNextFloat(f) {}
    const char* fName;
    float (*fNextFloat)(SkRandom*);
    bool isSuitableFor(Backend b) override {
        return b == kNonRendering_Backend;
    }
    const char* onGetName() override { return fName; }
    void onDraw(int loops, SkCanvas*) override {
        SkRandom random;
        char dst[kMaximumSkFloatToDecimalLength];
        while (loops-- > 0) {
            auto f = fNextFloat(&random);
            (void)SkFloatToDecimal(f, dst);
        }
    }
};

float next_common(SkRandom* random) {
    return random->nextRangeF(-500.0f, 1500.0f);
}
float next_any(SkRandom* random) {
    union { uint32_t u; float f; };
    u = random->nextU();
    static_assert(sizeof(float) == sizeof(uint32_t), "");
    return f;
}

DEF_BENCH(return new PDFScalarBench("PDFScalar_common", next_common);)
DEF_BENCH(return new PDFScalarBench("PDFScalar_random", next_any);)

#ifdef SK_SUPPORT_PDF

#include "SkPDFBitmap.h"
#include "SkPDFDocumentPriv.h"
#include "SkPDFShader.h"
#include "SkPDFUtils.h"

namespace {
class PDFImageBench : public Benchmark {
public:
    PDFImageBench() {}
    ~PDFImageBench() override {}

protected:
    const char* onGetName() override { return "PDFImage"; }
    bool isSuitableFor(Backend backend) override {
        return backend == kNonRendering_Backend;
    }
    void onDelayedSetup() override {
        sk_sp<SkImage> img(GetResourceAsImage("images/color_wheel.png"));
        if (img) {
            // force decoding, throw away reference to encoded data.
            SkAutoPixmapStorage pixmap;
            pixmap.alloc(SkImageInfo::MakeN32Premul(img->dimensions()));
            if (img->readPixels(pixmap, 0, 0)) {
                fImage = SkImage::MakeRasterCopy(pixmap);
            }
        }
    }
    void onDraw(int loops, SkCanvas*) override {
        if (!fImage) {
            return;
        }
        while (loops-- > 0) {
            SkNullWStream nullStream;
            SkPDFDocument doc(&nullStream, SkPDF::Metadata());
            doc.beginPage(256, 256);
            (void)SkPDFSerializeImage(fImage.get(), &doc);
        }
    }

private:
    sk_sp<SkImage> fImage;
};

class PDFJpegImageBench : public Benchmark {
public:
    PDFJpegImageBench() {}
    ~PDFJpegImageBench() override {}

protected:
    const char* onGetName() override { return "PDFJpegImage"; }
    bool isSuitableFor(Backend backend) override {
        return backend == kNonRendering_Backend;
    }
    void onDelayedSetup() override {
        sk_sp<SkImage> img(GetResourceAsImage("images/mandrill_512_q075.jpg"));
        if (!img) { return; }
        sk_sp<SkData> encoded = img->refEncodedData();
        SkASSERT(encoded);
        if (!encoded) { return; }
        fImage = img;
    }
    void onDraw(int loops, SkCanvas*) override {
        if (!fImage) {
            SkDEBUGFAIL("");
            return;
        }
        while (loops-- > 0) {
            SkNullWStream nullStream;
            SkPDFDocument doc(&nullStream, SkPDF::Metadata());
            doc.beginPage(256, 256);
            (void)SkPDFSerializeImage(fImage.get(), &doc);
        }
    }

private:
    sk_sp<SkImage> fImage;
};

/** Test calling DEFLATE on a 78k PDF command stream. Used for measuring
    alternate zlib settings, usage, and library versions. */
class PDFCompressionBench : public Benchmark {
public:
    PDFCompressionBench() {}
    ~PDFCompressionBench() override {}

protected:
    const char* onGetName() override { return "PDFCompression"; }
    bool isSuitableFor(Backend backend) override {
        return backend == kNonRendering_Backend;
    }
    void onDelayedSetup() override {
        fAsset = GetResourceAsStream("pdf_command_stream.txt");
    }
    void onDraw(int loops, SkCanvas*) override {
        SkASSERT(fAsset);
        if (!fAsset) { return; }
        while (loops-- > 0) {
            SkNullWStream wStream;
            SkPDFDocument doc(&wStream, SkPDF::Metadata());
            doc.beginPage(256, 256);
            (void)SkPDFStreamOut(nullptr, fAsset->duplicate(), &doc, true);
       }
    }

private:
    std::unique_ptr<SkStreamAsset> fAsset;
};

struct PDFColorComponentBench : public Benchmark {
    bool isSuitableFor(Backend b) override {
        return b == kNonRendering_Backend;
    }
    const char* onGetName() override { return "PDFColorComponent"; }
    void onDraw(int loops, SkCanvas*) override {
        char dst[5];
        while (loops-- > 0) {
            for (int i = 0; i < 256; ++i) {
                (void)SkPDFUtils::ColorToDecimal(SkToU8(i), dst);
            }
        }
    }
};

struct PDFShaderBench : public Benchmark {
    sk_sp<SkShader> fShader;
    const char* onGetName() final { return "PDFShader"; }
    bool isSuitableFor(Backend b) final { return b == kNonRendering_Backend; }
    void onDelayedSetup() final {
        const SkPoint pts[2] = {{0.0f, 0.0f}, {100.0f, 100.0f}};
        const SkColor colors[] = {
            SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
            SK_ColorWHITE, SK_ColorBLACK,
        };
        fShader = SkGradientShader::MakeLinear(
                pts, colors, nullptr, SK_ARRAY_COUNT(colors),
                SkTileMode::kClamp);
    }
    void onDraw(int loops, SkCanvas*) final {
        SkASSERT(fShader);
        while (loops-- > 0) {
            SkNullWStream nullStream;
            SkPDFDocument doc(&nullStream, SkPDF::Metadata());
            doc.beginPage(256, 256);
            (void) SkPDFMakeShader(&doc, fShader.get(), SkMatrix::I(),
                                   {0, 0, 400, 400}, SK_ColorBLACK);
        }
    }
};

struct WritePDFTextBenchmark : public Benchmark {
    std::unique_ptr<SkWStream> fWStream;
    WritePDFTextBenchmark() : fWStream(new SkNullWStream) {}
    const char* onGetName() override { return "WritePDFText"; }
    bool isSuitableFor(Backend backend) override {
        return backend == kNonRendering_Backend;
    }
    void onDraw(int loops, SkCanvas*) override {
        static const char kHello[] = "HELLO SKIA!\n";
        static const char kBinary[] = "\001\002\003\004\005\006";
        while (loops-- > 0) {
            for (int i = 1000; i-- > 0;) {
                SkPDFWriteString(fWStream.get(), kHello, strlen(kHello));
                SkPDFWriteString(fWStream.get(), kBinary, strlen(kBinary));
            }
        }
    }
};

// Test for regression chromium:947381
// with    5c83ae81aa :   2364.99 microsec
// without 5c83ae81aa : 302821.78 microsec
struct PDFClipPathBenchmark : public Benchmark {
    SkPath fPath;
    void onDelayedSetup() override {
        SkBitmap bitmap;
        bitmap.allocN32Pixels(256, 256);
        bitmap.eraseColor(SK_ColorWHITE);
        {
            SkCanvas tmp(bitmap);
            SkPaint paint;
            paint.setAntiAlias(false);
            paint.setStyle(SkPaint::kStroke_Style);
            paint.setStrokeWidth(10);
            for (int r : {20, 40, 60, 80, 100, 120}) {
                tmp.drawCircle(128, 128, (float)r, paint);
            }
        }
        fPath.reset();
        for (int y = 0; y < 256; ++y) {
            SkColor current = bitmap.getColor(0, y);
            int start = 0;
            for (int x = 0; x < 256; ++x) {
                SkColor color = bitmap.getColor(x, y);
                if (color == current) {
                    continue;
                }
                if (color == SK_ColorBLACK) {
                    start = x;
                } else {
                    fPath.addRect(SkRect::Make(SkIRect{start, y, x, y + 1}));
                }
                current = color;
            }
            if (current == SK_ColorBLACK) {
                fPath.addRect(SkRect::Make(SkIRect{start, y, 256, y + 1}));
            }
        }
    }
    const char* onGetName() override { return "PDFClipPath"; }
    bool isSuitableFor(Backend backend) override {
        return backend == kNonRendering_Backend;
    }
    void onDraw(int loops, SkCanvas*) override {
        while (loops-- > 0) {
            SkNullWStream wStream;
            SkPDFDocument doc(&wStream, SkPDF::Metadata());
            SkCanvas* canvas = doc.beginPage(256, 256);
            canvas->clipPath(fPath);
            canvas->translate(4.0f/3, 4.0f/3);
            canvas->clipPath(fPath);
            canvas->clear(SK_ColorRED);
            doc.endPage();
        }
    }
};

}  // namespace
DEF_BENCH(return new PDFImageBench;)
DEF_BENCH(return new PDFJpegImageBench;)
DEF_BENCH(return new PDFCompressionBench;)
DEF_BENCH(return new PDFColorComponentBench;)
DEF_BENCH(return new PDFShaderBench;)
DEF_BENCH(return new WritePDFTextBenchmark;)
DEF_BENCH(return new PDFClipPathBenchmark;)

#ifdef SK_PDF_ENABLE_SLOW_TESTS
#include "SkExecutor.h"
namespace {
void big_pdf_test(SkDocument* doc, const SkBitmap& background) {
    static const char* kText[] = {
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do",
        "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad",
        "minim veniam, quis nostrud exercitation ullamco laboris nisi ut",
        "aliquip ex ea commodo consequat. Duis aute irure dolor in",
        "reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla",
        "pariatur. Excepteur sint occaecat cupidatat non proident, sunt in",
        "culpa qui officia deserunt mollit anim id est laborum.",
        "",
        "Sed ut perspiciatis, unde omnis iste natus error sit voluptatem",
        "accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae",
        "ab illo inventore veritatis et quasi architecto beatae vitae dicta",
        "sunt, explicabo. Nemo enim ipsam voluptatem, quia voluptas sit,",
        "aspernatur aut odit aut fugit, sed quia consequuntur magni dolores",
        "eos, qui ratione voluptatem sequi nesciunt, neque porro quisquam est,",
        "qui dolorem ipsum, quia dolor sit amet consectetur adipiscing velit,",
        "sed quia non numquam do eius modi tempora incididunt, ut labore et",
        "dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam,",
        "quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi",
        "ut aliquid ex ea commodi consequatur? Quis autem vel eum iure",
        "reprehenderit, qui in ea voluptate velit esse, quam nihil molestiae",
        "consequatur, vel illum, qui dolorem eum fugiat, quo voluptas nulla",
        "pariatur?",
        "",
        "At vero eos et accusamus et iusto odio dignissimos ducimus, qui",
        "blanditiis praesentium voluptatum deleniti atque corrupti, quos",
        "dolores et quas molestias excepturi sint, obcaecati cupiditate non",
        "provident, similique sunt in culpa, qui officia deserunt mollitia",
        "animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis",
        "est et expedita distinctio. Nam libero tempore, cum soluta nobis est",
        "eligendi optio, cumque nihil impedit, quo minus id, quod maxime",
        "placeat, facere possimus, omnis voluptas assumenda est, omnis dolor",
        "repellendus. Temporibus autem quibusdam et aut officiis debitis aut",
        "rerum necessitatibus saepe eveniet, ut et voluptates repudiandae sint",
        "et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente",
        "delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut",
        "perferendis doloribus asperiores repellat",
        "",
        "Sed ut perspiciatis, unde omnis iste natus error sit voluptatem",
        "accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae",
        "ab illo inventore veritatis et quasi architecto beatae vitae dicta",
        "sunt, explicabo. Nemo enim ipsam voluptatem, quia voluptas sit,",
        "aspernatur aut odit aut fugit, sed quia consequuntur magni dolores",
        "eos, qui ratione voluptatem sequi nesciunt, neque porro quisquam est,",
        "qui dolorem ipsum, quia dolor sit amet consectetur adipiscing velit,",
        "sed quia non numquam do eius modi tempora incididunt, ut labore et",
        "dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam,",
        "quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi",
        "ut aliquid ex ea commodi consequatur? Quis autem vel eum iure",
        "reprehenderit, qui in ea voluptate velit esse, quam nihil molestiae",
        "consequatur, vel illum, qui dolorem eum fugiat, quo voluptas nulla",
        "pariatur?",
        "",
    };
    SkCanvas* canvas = nullptr;
    float x = 36;
    float y = 36;
    constexpr size_t kLineCount = SK_ARRAY_COUNT(kText);
    constexpr int kLoopCount = 200;
    SkFont font;
    SkPaint paint;
    for (int loop = 0; loop < kLoopCount; ++loop) {
        for (size_t line = 0; line < kLineCount; ++line) {
            y += font.getSpacing();
            if (!canvas || y > 792 - 36) {
                y = 36 + font.getSpacing();
                canvas = doc->beginPage(612, 792);
                background.notifyPixelsChanged();
                canvas->drawBitmap(background, 0, 0);
            }
            canvas->drawString(kText[line], x, y, font, paint);
        }
    }
}

SkBitmap make_background() {
    SkBitmap background;
    SkBitmap bitmap;
    bitmap.allocN32Pixels(32, 32);
    bitmap.eraseColor(SK_ColorWHITE);
    SkCanvas tmp(bitmap);
    SkPaint gray;
    gray.setColor(SkColorSetARGB(0xFF, 0xEE, 0xEE, 0xEE));
    tmp.drawRect({0,0,16,16}, gray);
    tmp.drawRect({16,16,32,32}, gray);
    SkPaint shader;
    shader.setShader(
            SkShader::MakeBitmapShader(
                bitmap, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
    background.allocN32Pixels(612, 792);
    SkCanvas tmp2(background);
    tmp2.drawPaint(shader);
    return background;
}

struct PDFBigDocBench : public Benchmark {
    bool fFast;
    SkBitmap fBackground;
    std::unique_ptr<SkExecutor> fExecutor;
    PDFBigDocBench(bool fast) : fFast(fast) {}
    void onDelayedSetup() override {
        fBackground = make_background();
        fExecutor = fFast ? SkExecutor::MakeFIFOThreadPool() : nullptr;
    }
    const char* onGetName() override {
        static const char kNameFast[] = "PDFBigDocBench_fast";
        static const char kNameSlow[] = "PDFBigDocBench_slow";
        return fFast ? kNameFast : kNameSlow;
    }
    bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }
    void onDraw(int loops, SkCanvas*) override {
        while (loops-- > 0) {
            #ifdef SK_PDF_TEST_BIGDOCBENCH_OUTPUT
            SkFILEWStream wStream("/tmp/big_pdf.pdf");
            #else
            SkNullWStream wStream;
            #endif
            SkPDF::Metadata metadata;
            metadata.fExecutor = fExecutor.get();
            auto doc = SkPDF::MakeDocument(&wStream, metadata);
            big_pdf_test(doc.get(), fBackground);
        }
    }
};
}  // namespace
DEF_BENCH(return new PDFBigDocBench(false);)
DEF_BENCH(return new PDFBigDocBench(true);)
#endif

#endif // SK_SUPPORT_PDF
