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

#include "SkSurface.h"
#include "Resources.h"
#include "gm.h"
#include "sk_tool_utils.h"

#include "SkMath.h"
#include "SkColorPriv.h"

static SkBitmap copy_bitmap(const SkBitmap& src, SkColorType colorType) {
    const SkBitmap* srcPtr = &src;
    SkBitmap tmp(src);
    if (kRGB_565_SkColorType == colorType) {
        tmp.setAlphaType(kOpaque_SkAlphaType);
        srcPtr = &tmp;
    }

    SkBitmap copy;
    sk_tool_utils::copy_to(&copy, colorType, *srcPtr);
    copy.setImmutable();
    return copy;
}

#define SCALE 128

// Make either A8 or gray8 bitmap.
static SkBitmap make_bitmap(SkColorType ct) {
    SkBitmap bm;
    switch (ct) {
        case kAlpha_8_SkColorType:
            bm.allocPixels(SkImageInfo::MakeA8(SCALE, SCALE));
            break;
        case kGray_8_SkColorType:
            bm.allocPixels(
                    SkImageInfo::Make(SCALE, SCALE, ct, kOpaque_SkAlphaType));
            break;
        default:
            SkASSERT(false);
            return bm;
    }
    uint8_t spectrum[256];
    for (int y = 0; y < 256; ++y) {
        spectrum[y] = y;
    }
    for (int y = 0; y < 128; ++y) {
        // Shift over one byte each scanline.
        memcpy(bm.getAddr8(0, y), &spectrum[y], 128);
    }
    bm.setImmutable();
    return bm;
}

static void draw_center_letter(char c,
                               SkPaint* p,
                               SkColor color,
                               SkScalar x,
                               SkScalar y,
                               SkCanvas* canvas) {
    SkRect bounds;
    p->setColor(color);
    p->measureText(&c, 1, &bounds);
    canvas->drawText(&c, 1, x - bounds.centerX(), y - bounds.centerY(), *p);
}

static void color_wheel_native(SkCanvas* canvas) {
    SkAutoCanvasRestore autoCanvasRestore(canvas, true);
    canvas->translate(0.5f * SCALE, 0.5f * SCALE);
    SkPaint p;
    p.setAntiAlias(false);
    p.setColor(SK_ColorWHITE);
    canvas->drawCircle(0.0f, 0.0f, SCALE * 0.5f, p);

    const double sqrt_3_over_2 = 0.8660254037844387;
    const SkScalar Z = 0.0f;
    const SkScalar D = 0.3f * SkIntToScalar(SCALE);
    const SkScalar X = SkDoubleToScalar(D * sqrt_3_over_2);
    const SkScalar Y = D * SK_ScalarHalf;
    sk_tool_utils::set_portable_typeface(&p, nullptr, SkFontStyle::Bold());
    p.setTextSize(0.28125f * SCALE);
    draw_center_letter('K', &p, SK_ColorBLACK, Z, Z, canvas);
    draw_center_letter('R', &p, SK_ColorRED, Z, D, canvas);
    draw_center_letter('G', &p, SK_ColorGREEN, -X, -Y, canvas);
    draw_center_letter('B', &p, SK_ColorBLUE, X, -Y, canvas);
    draw_center_letter('C', &p, SK_ColorCYAN, Z, -D, canvas);
    draw_center_letter('M', &p, SK_ColorMAGENTA, X, Y, canvas);
    draw_center_letter('Y', &p, SK_ColorYELLOW, -X, Y, canvas);
}

template <typename T>
int find(T* array, int N, T item) {
    for (int i = 0; i < N; ++i) {
        if (array[i] == item) {
            return i;
        }
    }
    return -1;
}

static void draw(SkCanvas* canvas,
                 const SkPaint& p,
                 const SkBitmap& src,
                 SkColorType colorType,
                 const char text[]) {
    SkASSERT(src.colorType() == colorType);
    canvas->drawBitmap(src, 0.0f, 0.0f);
    canvas->drawString(text, 0.0f, 12.0f, p);
}

DEF_SIMPLE_GM(all_bitmap_configs, canvas, SCALE, 5 * SCALE) {
    SkAutoCanvasRestore autoCanvasRestore(canvas, true);
    SkPaint p;
    p.setColor(SK_ColorBLACK);
    p.setAntiAlias(true);
    sk_tool_utils::set_portable_typeface(&p, nullptr);

    sk_tool_utils::draw_checkerboard(canvas, SK_ColorLTGRAY, SK_ColorWHITE, 8);

    SkBitmap bitmap;
    if (GetResourceAsBitmap("images/color_wheel.png", &bitmap)) {
        bitmap.setImmutable();
        draw(canvas, p, bitmap, kN32_SkColorType, "Native 32");

        canvas->translate(0.0f, SkIntToScalar(SCALE));
        SkBitmap copy565 = copy_bitmap(bitmap, kRGB_565_SkColorType);
        p.setColor(SK_ColorRED);
        draw(canvas, p, copy565, kRGB_565_SkColorType, "RGB 565");
        p.setColor(SK_ColorBLACK);

        canvas->translate(0.0f, SkIntToScalar(SCALE));
        SkBitmap copy4444 = copy_bitmap(bitmap, kARGB_4444_SkColorType);
        draw(canvas, p, copy4444, kARGB_4444_SkColorType, "ARGB 4444");
    } else {
        canvas->translate(0.0f, SkIntToScalar(2 * SCALE));
    }

    canvas->translate(0.0f, SkIntToScalar(SCALE));
    SkBitmap bitmapA8 = make_bitmap(kAlpha_8_SkColorType);
    draw(canvas, p, bitmapA8, kAlpha_8_SkColorType, "Alpha 8");

    p.setColor(SK_ColorRED);
    canvas->translate(0.0f, SkIntToScalar(SCALE));
    SkBitmap bitmapG8 = make_bitmap(kGray_8_SkColorType);
    draw(canvas, p, bitmapG8, kGray_8_SkColorType, "Gray 8");
}

sk_sp<SkImage> make_not_native32_color_wheel() {
    SkBitmap n32bitmap, notN32bitmap;
    n32bitmap.allocN32Pixels(SCALE, SCALE);
    n32bitmap.eraseColor(SK_ColorTRANSPARENT);
    SkCanvas n32canvas(n32bitmap);
    color_wheel_native(&n32canvas);
    n32canvas.flush();
    #if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
        const SkColorType ct = kRGBA_8888_SkColorType;
    #elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
        const SkColorType ct = kBGRA_8888_SkColorType;
    #endif
    static_assert(ct != kN32_SkColorType, "BRGA!=RGBA");
    SkAssertResult(sk_tool_utils::copy_to(&notN32bitmap, ct, n32bitmap));
    SkASSERT(notN32bitmap.colorType() == ct);
    return SkImage::MakeFromBitmap(notN32bitmap);
}

DEF_SIMPLE_GM(not_native32_bitmap_config, canvas, SCALE, SCALE) {
    sk_sp<SkImage> notN32image(make_not_native32_color_wheel());
    SkASSERT(notN32image);
    sk_tool_utils::draw_checkerboard(canvas, SK_ColorLTGRAY, SK_ColorWHITE, 8);
    canvas->drawImage(notN32image.get(), 0.0f, 0.0f);
}

static uint32_t make_pixel(int x, int y, SkAlphaType alphaType) {
    SkASSERT(x >= 0 && x < SCALE);
    SkASSERT(y >= 0 && y < SCALE);

    SkScalar R = SCALE / 2.0f;

    uint32_t alpha = 0x00;

    if ((x - R) * (x - R) + (y - R) * (y - R) < R * R) {
        alpha = 0xFF;
    }

    uint32_t component;
    switch (alphaType) {
        case kPremul_SkAlphaType:
            component = alpha;
            break;
        case kUnpremul_SkAlphaType:
            component = 0xFF;
            break;
        default:
            SK_ABORT("Should not get here - invalid alpha type");
            return 0xFF000000;
    }
    return alpha << 24 | component;
}

static void make_color_test_bitmap_variant(
    SkColorType colorType,
    SkAlphaType alphaType,
    sk_sp<SkColorSpace> colorSpace,
    SkBitmap* bm)
{
    SkASSERT(colorType == kRGBA_8888_SkColorType || colorType == kBGRA_8888_SkColorType);
    SkASSERT(alphaType == kPremul_SkAlphaType || alphaType == kUnpremul_SkAlphaType);
    bm->allocPixels(
        SkImageInfo::Make(SCALE, SCALE, colorType, alphaType, colorSpace));
    SkPixmap pm = bm->pixmap();
    for (int y = 0; y < pm.height(); y++) {
        for (int x = 0; x < pm.width(); x++) {
            *pm.writable_addr32(x, y) = make_pixel(x, y, alphaType);
        }
    }
}

DEF_SIMPLE_GM(all_variants_8888, canvas, 4 * SCALE + 30, 2 * SCALE + 10) {
    sk_tool_utils::draw_checkerboard(canvas, SK_ColorLTGRAY, SK_ColorWHITE, 8);

    sk_sp<SkColorSpace> colorSpaces[] {
        SkColorSpace::MakeSRGB(),
        nullptr,
    };
    for (auto colorSpace : colorSpaces) {
        canvas->save();
        for (auto alphaType : {kPremul_SkAlphaType, kUnpremul_SkAlphaType}) {
            canvas->save();
            for (auto colorType : {kRGBA_8888_SkColorType, kBGRA_8888_SkColorType}) {
                SkBitmap bm;
                make_color_test_bitmap_variant(colorType, alphaType, colorSpace, &bm);
                canvas->drawBitmap(bm, 0.0f, 0.0f);
                canvas->translate(SCALE + 10, 0.0f);
            }
            canvas->restore();
            canvas->translate(0.0f, SCALE + 10);
        }
        canvas->restore();
        canvas->translate(2 * (SCALE + 10), 0.0f);
    }
}
