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

#include "gm.h"
#include "SkCanvas.h"
#include "SkPath.h"

#include "SkGradientShader.h"
static void test_shallow_gradient(SkCanvas* canvas, SkScalar width, SkScalar height) {
    SkColor colors[] = { 0xFF7F7F7F, 0xFF7F7F7F, 0xFF000000 };
    SkScalar pos[] = { 0, 0.35f, SK_Scalar1 };
    SkPoint pts[] = { { 0, 0 }, { width, height } };
    SkShader* s = SkGradientShader::CreateLinear(pts, colors, pos,
                                                 SK_ARRAY_COUNT(colors),
                                                 SkShader::kClamp_TileMode);
    SkPaint paint;
    paint.setShader(s)->unref();
    canvas->drawPaint(paint);
}

#include "SkDashPathEffect.h"
static void test_giant_dash(SkCanvas* canvas) {
    SkPaint paint;
    const SkScalar intervals[] = { SK_Scalar1, SK_Scalar1 };

    paint.setStrokeWidth(2);
    paint.setPathEffect(new SkDashPathEffect(intervals, 2, 0))->unref();

    SkScalar big = 500 * 1000;

    canvas->drawLine(10, 10, big, 10, paint);
    canvas->drawLine(-big, 20, 500, 20, paint);
    canvas->drawLine(-big, 30, big, 30, paint);

    const SkScalar intervals2[] = { 20, 5, 10, 5 };
    paint.setPathEffect(new SkDashPathEffect(intervals2, 4, 17))->unref();

    canvas->translate(0, 40);
    SkScalar x = -500;
    SkScalar width = 3173;
    for (int i = 0; i < 40; ++i) {
        if (i > 10)
        canvas->drawLine(x, 0, x + width, 0, paint);
        x += 1;
        canvas->translate(0, 4);
    }
}



// Reproduces bug found here: http://jsfiddle.net/R8Cu5/1/
//
#include "SkGradientShader.h"
static void test_grad(SkCanvas* canvas) {
    SkPoint pts[] = {
        { 478.544067f, -84.2041016f },
        { 602.455933f, 625.204102f },
    };
    SkColor colors[] = { SK_ColorBLACK, SK_ColorBLACK, SK_ColorRED, SK_ColorRED };
    SkScalar pos[] = { 0, 0.3f, 0.3f, 1.0f };
    SkShader* s = SkGradientShader::CreateLinear(pts, colors, pos, 4, SkShader::kClamp_TileMode);
    SkPaint p;
    p.setShader(s)->unref();
    canvas->drawPaint(p);
}

static SkCanvas* MakeCanvas(const SkIRect& bounds) {
    SkBitmap bm;
    bm.setConfig(SkBitmap::kARGB_8888_Config, bounds.width(), bounds.height());
    bm.allocPixels();
    bm.eraseColor(SK_ColorTRANSPARENT);

    SkCanvas* canvas = new SkCanvas(bm);
    canvas->translate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop));
    return canvas;
}

#ifdef SK_DEBUG
static void GetBitmap(const SkCanvas* canvas, SkBitmap* bm) {
    *bm = canvas->getDevice()->accessBitmap(false);
}
#endif

static void compare_canvas(const SkCanvas* a, const SkCanvas* b) {
#ifdef SK_DEBUG
    SkBitmap bma, bmb;
    GetBitmap(a, &bma);
    GetBitmap(b, &bmb);

    SkASSERT(bma.width() == bmb.width());
    SkASSERT(bma.height() == bmb.height());

    bma.lockPixels();
    bmb.lockPixels();
    for (int y = 0; y < bma.height(); ++y) {
        const SkPMColor* rowa = bma.getAddr32(0, y);
        const SkPMColor* rowb = bmb.getAddr32(0, y);
        SkASSERT(!memcmp(rowa, rowb, bma.width() << 2));

        for (int x = 1; x < bma.width() - 1; ++x) {
            SkASSERT(0xFF000000 == rowa[x]);
            SkASSERT(0xFF000000 == rowb[x]);
        }
    }
#endif
}

static void drawRectAsPath(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
    SkPath path;
    path.addRect(r);
    canvas->drawPath(path, p);
}

static void test_maskFromPath(const SkPath& path) {
    SkIRect bounds;
    path.getBounds().roundOut(&bounds);

    SkPaint paint;
    paint.setAntiAlias(true);

    SkAutoTUnref<SkCanvas> path_canvas(MakeCanvas(bounds));
    path_canvas->drawPath(path, paint);

    SkAutoTUnref<SkCanvas> rect_canvas(MakeCanvas(bounds));
    drawRectAsPath(rect_canvas, path.getBounds(), paint);

    compare_canvas(path_canvas, rect_canvas);
}

static void test_mask() {
    for (int i = 1; i <= 20; ++i) {
        const SkScalar dx = SK_Scalar1 / i;
        const SkRect constr = SkRect::MakeWH(dx, SkIntToScalar(2));
        for (int n = 2; n < 20; ++n) {
            SkPath path;
            path.setFillType(SkPath::kEvenOdd_FillType);
            SkRect r = constr;
            while (r.fRight < SkIntToScalar(4)) {
                path.addRect(r);
                r.offset(dx, 0);
            }
            test_maskFromPath(path);
        }
    }
}

namespace skiagm {

/** Draw a 2px border around the target, then red behind the target;
    set the clip to match the target, then draw >> the target in blue.
*/

static void draw (SkCanvas* canvas, SkRect& target, int x, int y) {
    SkPaint borderPaint;
    borderPaint.setColor(SkColorSetRGB(0x0, 0xDD, 0x0));
    borderPaint.setAntiAlias(true);
    SkPaint backgroundPaint;
    backgroundPaint.setColor(SkColorSetRGB(0xDD, 0x0, 0x0));
    backgroundPaint.setAntiAlias(true);
    SkPaint foregroundPaint;
    foregroundPaint.setColor(SkColorSetRGB(0x0, 0x0, 0xDD));
    foregroundPaint.setAntiAlias(true);

    canvas->save();
    canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
    target.inset(SkIntToScalar(-2), SkIntToScalar(-2));
    canvas->drawRect(target, borderPaint);
    target.inset(SkIntToScalar(2), SkIntToScalar(2));
    canvas->drawRect(target, backgroundPaint);
    canvas->clipRect(target, SkRegion::kIntersect_Op, true);
    target.inset(SkIntToScalar(-4), SkIntToScalar(-4));
    canvas->drawRect(target, foregroundPaint);
    canvas->restore();
}

static void draw_square (SkCanvas* canvas, int x, int y) {
    SkRect target (SkRect::MakeWH(10 * SK_Scalar1, 10 * SK_Scalar1));
    draw(canvas, target, x, y);
}

static void draw_column (SkCanvas* canvas, int x, int y) {
    SkRect target (SkRect::MakeWH(1 * SK_Scalar1, 10 * SK_Scalar1));
    draw(canvas, target, x, y);
}

static void draw_bar (SkCanvas* canvas, int x, int y) {
    SkRect target (SkRect::MakeWH(10 * SK_Scalar1, 1 * SK_Scalar1));
    draw(canvas, target, x, y);
}

static void draw_rect_tests (SkCanvas* canvas) {
    draw_square(canvas, 10, 10);
    draw_column(canvas, 30, 10);
    draw_bar(canvas, 10, 30);
}

/**
   Test a set of clipping problems discovered while writing blitAntiRect,
   and test all the code paths through the clipping blitters.
   Each region should show as a blue center surrounded by a 2px green
   border, with no red.
*/

class AAClipGM : public GM {
public:
    AAClipGM() {

    }

protected:
    virtual SkString onShortName() {
        return SkString("aaclip");
    }

    virtual SkISize onISize() {
        return make_isize(640, 480);
    }

    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
        if (false) {
            SkRect bounds;
            canvas->getClipBounds(&bounds);
            test_shallow_gradient(canvas, bounds.width(), bounds.height()); return;
        }
        if (false) {
            test_giant_dash(canvas); return;
        }
        if (false) {
            test_grad(canvas); return;
        }
        if (false) { // avoid bit rot, suppress warning
            test_mask();
        }

        // Initial pixel-boundary-aligned draw
        draw_rect_tests(canvas);

        // Repeat 4x with .2, .4, .6, .8 px offsets
        canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5);
        canvas->translate(SkIntToScalar(50), 0);
        draw_rect_tests(canvas);

        canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5);
        canvas->translate(SkIntToScalar(50), 0);
        draw_rect_tests(canvas);

        canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5);
        canvas->translate(SkIntToScalar(50), 0);
        draw_rect_tests(canvas);

        canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5);
        canvas->translate(SkIntToScalar(50), 0);
        draw_rect_tests(canvas);
    }

    virtual uint32_t onGetFlags() const { return kSkipPipe_Flag; }

private:
    typedef GM INHERITED;
};

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

static GM* MyFactory(void*) { return new AAClipGM; }
static GMRegistry reg(MyFactory);

}
