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

#include "gm/gm.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkFont.h"
#include "include/core/SkImageFilter.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRect.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "include/effects/SkImageFilters.h"
#include "tools/ToolUtils.h"
#include "tools/fonts/FontToolUtils.h"

#include <array>

#define WIDTH 700
#define HEIGHT 560

namespace skiagm {

class MorphologyGM : public GM {
public:
    MorphologyGM() {
        this->setBGColor(0xFF000000);
    }

protected:
    SkString getName() const override { return SkString("morphology"); }

    void onOnceBeforeDraw() override {
        auto surf = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(135, 135));

        SkFont  font(ToolUtils::DefaultPortableTypeface(), 64.0f);
        SkPaint paint;
        paint.setColor(0xFFFFFFFF);
        surf->getCanvas()->drawString("ABC", 10, 55,  font, paint);
        surf->getCanvas()->drawString("XYZ", 10, 110, font, paint);

        fImage = surf->makeImageSnapshot();
    }

    SkISize getISize() override { return SkISize::Make(WIDTH, HEIGHT); }

    void drawClippedBitmap(SkCanvas* canvas, const SkPaint& paint, int x, int y) {
        canvas->save();
        canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
        canvas->clipIRect(fImage->bounds());
        canvas->drawImage(fImage, 0, 0, SkSamplingOptions(), &paint);
        canvas->restore();
    }

    void onDraw(SkCanvas* canvas) override {
        struct Samples {
            int fWidth, fHeight;
            int fRadiusX, fRadiusY;
        };
        static constexpr auto samples = std::to_array<Samples>({
                Samples{ 140, 140,  0,  0 },
                Samples{ 140, 140,  0,  2 },
                Samples{ 140, 140,  2,  0 },
                Samples{ 140, 140,  2,  2 },
                Samples{  24,  24, 25, 25 },
        });
        SkPaint paint;
        SkIRect cropRect = SkIRect::MakeXYWH(25, 20, 100, 80);

        for (unsigned j = 0; j < 4; ++j) {
            for (unsigned i = 0; i < std::size(samples); ++i) {
                const SkIRect* cr = j & 0x02 ? &cropRect : nullptr;
                if (j & 0x01) {
                    paint.setImageFilter(SkImageFilters::Erode(
                            samples[i].fRadiusX, samples[i].fRadiusY, nullptr, cr));
                } else {
                    paint.setImageFilter(SkImageFilters::Dilate(
                            samples[i].fRadiusX, samples[i].fRadiusY, nullptr, cr));
                }
                this->drawClippedBitmap(canvas, paint, i * 140, j * 140);
            }
        }
    }

private:
    sk_sp<SkImage> fImage;

    using INHERITED = GM;
};

//////////////////////////////////////////////////////////////////////////////

DEF_GM(return new MorphologyGM;)

}  // namespace skiagm
