/*
 * 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::FromOldStyle(SkTypeface::kBold));
    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("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:
            SkFAIL("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->peekPixels(&pm);
    for (int y = 0; y < bm->height(); y++) {
        for (int x = 0; x < bm->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);
    }
}
