/*
 * 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 "SampleCode.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "SkGradientShader.h"
#include "SkPath.h"
#include "SkRegion.h"
#include "SkShader.h"
#include "SkUtils.h"

#include <math.h>

static void test_strokerect(SkCanvas* canvas) {
    int width = 100;
    int height = 100;

    SkBitmap bitmap;
    bitmap.allocPixels(SkImageInfo::MakeA8(width*2, height*2));
    bitmap.eraseColor(SK_ColorTRANSPARENT);

    SkScalar dx = 20;
    SkScalar dy = 20;

    SkPath path;
    path.addRect(0.0f, 0.0f,
                 SkIntToScalar(width), SkIntToScalar(height),
                 SkPath::kCW_Direction);
    SkRect r = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));

    SkCanvas c(bitmap);
    c.translate(dx, dy);

    SkPaint paint;
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(1);

    // use the rect
    c.clear(SK_ColorTRANSPARENT);
    c.drawRect(r, paint);
    canvas->drawBitmap(bitmap, 0, 0, nullptr);

    // use the path
    c.clear(SK_ColorTRANSPARENT);
    c.drawPath(path, paint);
    canvas->drawBitmap(bitmap, SkIntToScalar(2*width), 0, nullptr);
}

static void drawFadingText(SkCanvas* canvas,
                           const char* text, size_t len, SkScalar x, SkScalar y,
                           const SkPaint& paint) {
    // Need a bounds for the text
    SkRect bounds;
    SkPaint::FontMetrics fm;

    paint.getFontMetrics(&fm);
    bounds.set(x, y + fm.fTop, x + paint.measureText(text, len), y + fm.fBottom);

    // may need to outset bounds a little, to account for hinting and/or
    // antialiasing
    bounds.inset(-SkIntToScalar(2), -SkIntToScalar(2));

    canvas->saveLayer(&bounds, nullptr);
    canvas->drawText(text, len, x, y, paint);

    const SkPoint pts[] = {
        { bounds.fLeft, y },
        { bounds.fRight, y }
    };
    const SkColor colors[] = { SK_ColorBLACK, SK_ColorBLACK, 0 };

    // pos[1] value is where we start to fade, relative to the width
    // of our pts[] array.
    const SkScalar pos[] = { 0, 0.9f, SK_Scalar1 };

    SkPaint p;
    p.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 3, SkShader::kClamp_TileMode));
    p.setXfermodeMode(SkXfermode::kDstIn_Mode);
    canvas->drawRect(bounds, p);

    canvas->restore();
}

static void test_text(SkCanvas* canvas) {
    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setTextSize(20);

    const char* str = "Hamburgefons";
    size_t len = strlen(str);
    SkScalar x = 20;
    SkScalar y = 20;

    canvas->drawText(str, len, x, y, paint);

    y += 20;

    const SkPoint pts[] = { { x, y }, { x + paint.measureText(str, len), y } };
    const SkColor colors[] = { SK_ColorBLACK, SK_ColorBLACK, 0 };
    const SkScalar pos[] = { 0, 0.9f, 1 };
    paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos,
                                                 SK_ARRAY_COUNT(colors),
                                                 SkShader::kClamp_TileMode));
    canvas->drawText(str, len, x, y, paint);

    y += 20;
    paint.setShader(nullptr);
    drawFadingText(canvas, str, len, x, y, paint);
}

#ifdef SK_DEBUG
static void make_rgn(SkRegion* rgn, int left, int top, int right, int bottom,
                     int count, int32_t runs[]) {
    SkIRect r;
    r.set(left, top, right, bottom);

    rgn->debugSetRuns(runs, count);
    SkASSERT(rgn->getBounds() == r);
}

static void test_union_bug_1505668(SkRegion* ra, SkRegion* rb, SkRegion* rc) {
    static int32_t dataA[] = {
        0x00000001,
        0x000001dd, 2, 0x00000001, 0x0000000c, 0x0000000d, 0x00000025, 0x7fffffff,
        0x000001de, 1, 0x00000001, 0x00000025, 0x7fffffff,
        0x000004b3, 1, 0x00000001, 0x00000026, 0x7fffffff,
        0x000004b4, 1, 0x0000000c, 0x00000026, 0x7fffffff,
        0x00000579, 1, 0x00000000, 0x0000013a, 0x7fffffff,
        0x000005d8, 1, 0x00000000, 0x0000013b, 0x7fffffff,
        0x7fffffff
    };
    make_rgn(ra, 0, 1, 315, 1496, SK_ARRAY_COUNT(dataA), dataA);

    static int32_t dataB[] = {
        0x000000b6,
        0x000000c4, 1, 0x000000a1, 0x000000f0, 0x7fffffff,
        0x000000d6, 0, 0x7fffffff,
        0x000000e4, 2, 0x00000070, 0x00000079, 0x000000a1, 0x000000b0, 0x7fffffff,
        0x000000e6, 0, 0x7fffffff,
        0x000000f4, 2, 0x00000070, 0x00000079, 0x000000a1, 0x000000b0, 0x7fffffff,
        0x000000f6, 0, 0x7fffffff,
        0x00000104, 1, 0x000000a1, 0x000000b0, 0x7fffffff,
        0x7fffffff
    };
    make_rgn(rb, 112, 182, 240, 260, SK_ARRAY_COUNT(dataB), dataB);

    rc->op(*ra, *rb, SkRegion::kUnion_Op);
}
#endif

static void scale_rect(SkIRect* dst, const SkIRect& src, float scale) {
    dst->fLeft = (int)::roundf(src.fLeft * scale);
    dst->fTop = (int)::roundf(src.fTop * scale);
    dst->fRight = (int)::roundf(src.fRight * scale);
    dst->fBottom = (int)::roundf(src.fBottom * scale);
}

static void scale_rgn(SkRegion* dst, const SkRegion& src, float scale) {
    SkRegion tmp;
    SkRegion::Iterator iter(src);

    for (; !iter.done(); iter.next()) {
        SkIRect r;
        scale_rect(&r, iter.rect(), scale);
        tmp.op(r, SkRegion::kUnion_Op);
    }
    dst->swap(tmp);
}

static void paint_rgn(SkCanvas* canvas, const SkRegion& rgn,
                      const SkPaint& paint) {
    SkRegion scaled;
    scale_rgn(&scaled, rgn, 0.5f);

    SkRegion::Iterator  iter(rgn);

    for (; !iter.done(); iter.next())
    {
        SkRect    r;
        r.set(iter.rect());
        canvas->drawRect(r, paint);
    }
}

class RegionView : public SampleView {
public:
    RegionView() {
        fBase.set(100, 100, 150, 150);
        fRect = fBase;
        fRect.inset(5, 5);
        fRect.offset(25, 25);
        this->setBGColor(0xFFDDDDDD);
    }

    void build_base_rgn(SkRegion* rgn) {
        rgn->setRect(fBase);
        SkIRect r = fBase;
        r.offset(75, 20);
        rgn->op(r, SkRegion::kUnion_Op);
    }

    void build_rgn(SkRegion* rgn, SkRegion::Op op) {
        build_base_rgn(rgn);
        rgn->op(fRect, op);
    }


protected:
    // overrides from SkEventSink
    bool onQuery(SkEvent* evt) override {
        if (SampleCode::TitleQ(*evt)) {
            SampleCode::TitleR(evt, "Regions");
            return true;
        }
        return this->INHERITED::onQuery(evt);
    }

    static void drawstr(SkCanvas* canvas, const char text[], const SkPoint& loc,
                        bool hilite) {
        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setTextSize(SkIntToScalar(20));
        paint.setColor(hilite ? SK_ColorRED : 0x40FF0000);
        canvas->drawText(text, strlen(text), loc.fX, loc.fY, paint);
    }

    void drawPredicates(SkCanvas* canvas, const SkPoint pts[]) {
        SkRegion rgn;
        build_base_rgn(&rgn);

        drawstr(canvas, "Intersects", pts[0], rgn.intersects(fRect));
        drawstr(canvas, "Contains", pts[1], rgn.contains(fRect));
    }

    void drawOrig(SkCanvas* canvas, bool bg) {
        SkRect      r;
        SkPaint     paint;

        paint.setStyle(SkPaint::kStroke_Style);
        if (bg)
            paint.setColor(0xFFBBBBBB);

        SkRegion rgn;
        build_base_rgn(&rgn);
        paint_rgn(canvas, rgn, paint);

        r.set(fRect);
        canvas->drawRect(r, paint);
    }

    void drawRgnOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) {
        SkRegion    rgn;

        this->build_rgn(&rgn, op);

        {
            SkRegion tmp, tmp2(rgn);

            tmp = tmp2;
            tmp.translate(5, -3);

            {
                char    buffer[1000];
                SkDEBUGCODE(size_t  size = ) tmp.writeToMemory(nullptr);
                SkASSERT(size <= sizeof(buffer));
                SkDEBUGCODE(size_t  size2 = ) tmp.writeToMemory(buffer);
                SkASSERT(size == size2);

                SkRegion    tmp3;
                SkDEBUGCODE(size2 = ) tmp3.readFromMemory(buffer, 1000);
                SkASSERT(size == size2);

                SkASSERT(tmp3 == tmp);
            }

            rgn.translate(20, 30, &tmp);
            SkASSERT(rgn.isEmpty() || tmp != rgn);
            tmp.translate(-20, -30);
            SkASSERT(tmp == rgn);
        }

        this->drawOrig(canvas, true);

        SkPaint paint;
        paint.setColor((color & ~(0xFF << 24)) | (0x44 << 24));
        paint_rgn(canvas, rgn, paint);

        paint.setStyle(SkPaint::kStroke_Style);
        paint.setColor(color);
        paint_rgn(canvas, rgn, paint);
    }

    void drawPathOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) {
        SkRegion    rgn;
        SkPath      path;

        this->build_rgn(&rgn, op);
        rgn.getBoundaryPath(&path);

        this->drawOrig(canvas, true);

        SkPaint paint;

        paint.setStyle(SkPaint::kFill_Style);
        paint.setColor((color & ~(0xFF << 24)) | (0x44 << 24));
        canvas->drawPath(path, paint);
        paint.setColor(color);
        paint.setStyle(SkPaint::kStroke_Style);
        canvas->drawPath(path, paint);
    }

    void onDrawContent(SkCanvas* canvas) override {
        if (false) { // avoid bit rot, suppress warning
            test_strokerect(canvas);
            return;
        }
        if (false) { // avoid bit rot, suppress warning
            test_text(canvas);
            return;
        }
#ifdef SK_DEBUG
        if (true) {
            SkRegion a, b, c;
            test_union_bug_1505668(&a, &b, &c);

            if (false) {    // draw the result of the test
                SkPaint paint;

                canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
                paint.setColor(SK_ColorRED);
                paint_rgn(canvas, a, paint);
                paint.setColor(0x800000FF);
                paint_rgn(canvas, b, paint);
                paint.setColor(SK_ColorBLACK);
                paint.setStyle(SkPaint::kStroke_Style);
             //   paint_rgn(canvas, c, paint);
                return;
            }
        }
#endif
        const SkPoint origins[] = {
            { 30*SK_Scalar1, 50*SK_Scalar1 },
            { 150*SK_Scalar1, 50*SK_Scalar1 },
        };
        this->drawPredicates(canvas, origins);

        static const struct {
            SkColor         fColor;
            const char*     fName;
            SkRegion::Op    fOp;
        } gOps[] = {
            { SK_ColorBLACK,    "Difference",   SkRegion::kDifference_Op    },
            { SK_ColorRED,      "Intersect",    SkRegion::kIntersect_Op     },
            { 0xFF008800,       "Union",        SkRegion::kUnion_Op         },
            { SK_ColorBLUE,     "XOR",          SkRegion::kXOR_Op           }
        };

        SkPaint textPaint;
        textPaint.setAntiAlias(true);
        textPaint.setTextSize(SK_Scalar1*24);

        this->drawOrig(canvas, false);
        canvas->save();
            canvas->translate(SkIntToScalar(200), 0);
            this->drawRgnOped(canvas, SkRegion::kUnion_Op, SK_ColorBLACK);
        canvas->restore();

        canvas->translate(0, SkIntToScalar(200));

        for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); op++) {
            canvas->drawText(gOps[op].fName, strlen(gOps[op].fName), SkIntToScalar(75), SkIntToScalar(50), textPaint);

            this->drawRgnOped(canvas, gOps[op].fOp, gOps[op].fColor);

            canvas->save();
            canvas->translate(0, SkIntToScalar(200));
            this->drawPathOped(canvas, gOps[op].fOp, gOps[op].fColor);
            canvas->restore();

            canvas->translate(SkIntToScalar(200), 0);
        }
    }

    virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y,
                                              unsigned modi) override {
        return fRect.contains(SkScalarRoundToInt(x),
                              SkScalarRoundToInt(y)) ? new Click(this) : nullptr;
    }

    bool onClick(Click* click) override {
        fRect.offset(click->fICurr.fX - click->fIPrev.fX,
                     click->fICurr.fY - click->fIPrev.fY);
        this->inval(nullptr);
        return true;
    }

private:
    SkIRect    fBase, fRect;

    typedef SampleView INHERITED;
};

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

static SkView* MyFactory() { return new RegionView; }
static SkViewRegister reg(MyFactory);
