/*
 * Copyright 2018 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/SkBlendMode.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkFont.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRect.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTypeface.h"
#include "include/utils/SkTextUtils.h"
#include "tools/ToolUtils.h"
#include "tools/fonts/FontToolUtils.h"

#include <initializer_list>

namespace skiagm {

// This GM recreates the blend mode images from the Android documentation
class AndroidBlendModesGM : public GM {
public:
    AndroidBlendModesGM() {
        this->setBGColor(SK_ColorBLACK);
    }

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

    SkISize getISize() override {
        return SkISize::Make(kNumCols * kBitmapSize, kNumRows * kBitmapSize);
    }

    void onOnceBeforeDraw() override {
        SkImageInfo ii = SkImageInfo::MakeN32Premul(kBitmapSize, kBitmapSize);
        {
            fCompositeSrc.allocPixels(ii);
            SkCanvas tmp(fCompositeSrc);
            tmp.clear(SK_ColorTRANSPARENT);
            SkPaint p;
            p.setAntiAlias(true);
            p.setColor(ToolUtils::color_to_565(kBlue));
            tmp.drawRect(SkRect::MakeLTRB(16, 96, 160, 240), p);
        }

        {
            fCompositeDst.allocPixels(ii);
            SkCanvas tmp(fCompositeDst);
            tmp.clear(SK_ColorTRANSPARENT);
            SkPaint p;
            p.setAntiAlias(true);
            p.setColor(ToolUtils::color_to_565(kRed));
            tmp.drawCircle(160, 95, 80, p);
        }
    }

    void drawTile(SkCanvas* canvas, int xOffset, int yOffset, SkBlendMode mode) {
        canvas->translate(xOffset, yOffset);

        canvas->clipRect(SkRect::MakeXYWH(0, 0, 256, 256));

        canvas->saveLayer(nullptr, nullptr);

        SkPaint p;
        canvas->drawImage(fCompositeDst.asImage(), 0, 0, SkSamplingOptions(), &p);
        p.setBlendMode(mode);
        canvas->drawImage(fCompositeSrc.asImage(), 0, 0, SkSamplingOptions(), &p);
    }

    void onDraw(SkCanvas* canvas) override {
        SkFont font = ToolUtils::DefaultPortableFont();

        ToolUtils::draw_checkerboard(canvas, kWhite, kGrey, 32);

        int xOffset = 0, yOffset = 0;

        // Android doesn't expose all the blend modes
        // Note that the Android documentation calls:
        //    Skia's kPlus,     add
        //    Skia's kModulate, multiply
        for (SkBlendMode mode : { SkBlendMode::kPlus /* add */, SkBlendMode::kClear,
                                  SkBlendMode::kDarken, SkBlendMode::kDst,
                                  SkBlendMode::kDstATop, SkBlendMode::kDstIn,
                                  SkBlendMode::kDstOut, SkBlendMode::kDstOver,
                                  SkBlendMode::kLighten, SkBlendMode::kModulate /* multiply */,
                                  SkBlendMode::kOverlay, SkBlendMode::kScreen,
                                  SkBlendMode::kSrc, SkBlendMode::kSrcATop,
                                  SkBlendMode::kSrcIn, SkBlendMode::kSrcOut,
                                  SkBlendMode::kSrcOver, SkBlendMode::kXor } ) {

            int saveCount = canvas->save();
            this->drawTile(canvas, xOffset, yOffset, mode);
            canvas->restoreToCount(saveCount);

            SkTextUtils::DrawString(canvas, SkBlendMode_Name(mode),
                               xOffset + kBitmapSize/2.0f,
                               yOffset + kBitmapSize,
                               font, SkPaint(), SkTextUtils::kCenter_Align);

            xOffset += 256;
            if (xOffset >= 1024) {
                xOffset = 0;
                yOffset += 256;
            }
        }
    }

private:
    static const int kBitmapSize = 256;
    static const int kNumRows = 5;
    static const int kNumCols = 4;

    static const SkColor  kBlue  = SkColorSetARGB(255, 22, 150, 243);
    static const SkColor  kRed   = SkColorSetARGB(255, 233, 30, 99);
    static const SkColor  kWhite = SkColorSetARGB(255, 243, 243, 243);
    static const SkColor  kGrey  = SkColorSetARGB(255, 222, 222, 222);

    SkBitmap fCompositeSrc;
    SkBitmap fCompositeDst;

    using INHERITED = GM;
};

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

DEF_GM(return new AndroidBlendModesGM;)
}  // namespace skiagm
