/*
 * Copyright 2013 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/SkColor.h"
#include "include/core/SkFilterQuality.h"
#include "include/core/SkFont.h"
#include "include/core/SkFontStyle.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPixmap.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 "tools/Resources.h"
#include "tools/ToolUtils.h"

static const char* kFilterQualityNames[] = { "none", "low", "medium", "high" };

struct DownsampleBitmapGM : public skiagm::GM {
    SkBitmap      (*fMakeBitmap)(SkImageInfo);
    SkString        fName;
    SkFilterQuality fFilterQuality;

    DownsampleBitmapGM(SkBitmap (*fn)(SkImageInfo), const char* kind, SkFilterQuality fq)
        : fMakeBitmap(fn)
        , fName(SkStringPrintf("downsamplebitmap_%s_%s", kind, kFilterQualityNames[fq]))
        , fFilterQuality(fq)
    {
        this->setBGColor(0xFFDDDDDD);
    }

    SkString onShortName() override { return fName; }

    SkISize onISize() override {
        SkBitmap bm = fMakeBitmap(SkImageInfo::MakeN32Premul(1,1)/*whatever*/);
        return SkISize::Make(bm.width(), 4 * bm.height());
    }

    void onDraw(SkCanvas* canvas) override {
        SkImageInfo info = canvas->imageInfo();
        if (!info.colorType()) { info = info.makeColorType(   kN32_SkColorType); }
        if (!info.alphaType()) { info = info.makeAlphaType(kPremul_SkAlphaType); }

        SkBitmap bm = fMakeBitmap(info);

        int curY = 0;
        int curHeight;
        float curScale = 1;
        do {

            SkMatrix matrix;
            matrix.setScale( curScale, curScale );

            SkPaint paint;
            paint.setFilterQuality(fFilterQuality);

            canvas->save();
                canvas->translate(0, (SkScalar)curY);
                canvas->concat(matrix);
                canvas->drawBitmap(bm, 0, 0, &paint);
            canvas->restore();

            curHeight = (int) (bm.height() * curScale + 2);
            curY += curHeight;
            curScale *= 0.75f;
        } while (curHeight >= 2 && curY < 4*bm.height());
    }
};

static SkBitmap convert_bitmap_format(SkBitmap src, SkImageInfo info) {
    SkBitmap dst;
    dst.allocPixels(info.makeDimensions(src.dimensions()));

    SkPixmap pm;
    SkAssertResult(dst.peekPixels(&pm));
    SkAssertResult(src.readPixels(pm));

    return dst;
}


static SkBitmap make_text(SkImageInfo info) {
    const SkScalar textSize = 72;

    SkBitmap bm;
    bm.allocPixels(info.makeWH(int(textSize * 8), int(textSize * 6)));
    SkCanvas canvas(bm);
    canvas.drawColor(SK_ColorWHITE);

    SkPaint paint;
    SkFont font;
    font.setSubpixel(true);
    font.setSize(textSize);

    font.setTypeface(ToolUtils::create_portable_typeface("serif", SkFontStyle()));
    canvas.drawString("Hamburgefons", textSize/2, 1.2f*textSize, font, paint);
    font.setTypeface(ToolUtils::create_portable_typeface("serif", SkFontStyle::Bold()));
    canvas.drawString("Hamburgefons", textSize/2, 2.4f*textSize, font, paint);
    font.setTypeface(ToolUtils::create_portable_typeface("serif", SkFontStyle::Italic()));
    canvas.drawString("Hamburgefons", textSize/2, 3.6f*textSize, font, paint);
    font.setTypeface(ToolUtils::create_portable_typeface("serif", SkFontStyle::BoldItalic()));
    canvas.drawString("Hamburgefons", textSize/2, 4.8f*textSize, font, paint);

    return bm;
}
DEF_GM( return new DownsampleBitmapGM(make_text, "text",   kHigh_SkFilterQuality); )
DEF_GM( return new DownsampleBitmapGM(make_text, "text", kMedium_SkFilterQuality); )
DEF_GM( return new DownsampleBitmapGM(make_text, "text",    kLow_SkFilterQuality); )
DEF_GM( return new DownsampleBitmapGM(make_text, "text",   kNone_SkFilterQuality); )


static SkBitmap make_checkerboard(SkImageInfo info) {
    const auto size      = 512;
    const auto numChecks = 256;

    SkBitmap bm;
    bm.allocN32Pixels(size,size);
    for (int y = 0; y < size; ++y) {
        for (int x = 0; x < size; ++x) {
            SkPMColor* s = bm.getAddr32(x, y);
            int cx = (x * numChecks) / size;
            int cy = (y * numChecks) / size;
            if ((cx+cy)%2) {
                *s = 0xFFFFFFFF;
            } else {
                *s = 0xFF000000;
            }
        }
    }
    return convert_bitmap_format(bm, info);
}
DEF_GM( return new DownsampleBitmapGM(make_checkerboard, "checkerboard",   kHigh_SkFilterQuality); )
DEF_GM( return new DownsampleBitmapGM(make_checkerboard, "checkerboard", kMedium_SkFilterQuality); )
DEF_GM( return new DownsampleBitmapGM(make_checkerboard, "checkerboard",    kLow_SkFilterQuality); )
DEF_GM( return new DownsampleBitmapGM(make_checkerboard, "checkerboard",   kNone_SkFilterQuality); )


static SkBitmap make_image(SkImageInfo info) {
    SkBitmap bm;
    if (!GetResourceAsBitmap("images/mandrill_512.png", &bm)) {
        bm.allocN32Pixels(1, 1);
        bm.eraseARGB(255, 255, 0 , 0); // red == bad
    }
    return convert_bitmap_format(bm, info);
}
DEF_GM( return new DownsampleBitmapGM(make_image, "image",   kHigh_SkFilterQuality); )
DEF_GM( return new DownsampleBitmapGM(make_image, "image", kMedium_SkFilterQuality); )
DEF_GM( return new DownsampleBitmapGM(make_image, "image",    kLow_SkFilterQuality); )
DEF_GM( return new DownsampleBitmapGM(make_image, "image",   kNone_SkFilterQuality); )
