/*
 * 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 "SkDeviceLooper.h"
#include "SkRasterClip.h"
#include "Test.h"

static void make_bm(SkBitmap* bm, int w, int h) {
    bm->allocPixels(SkImageInfo::Make(w, h, kAlpha_8_SkColorType,
                                      kPremul_SkAlphaType));
}

static bool equal(const SkRasterClip& a, const SkRasterClip& b) {
    if (a.isBW()) {
        return b.isBW() && a.bwRgn() == b.bwRgn();
    } else {
        return a.isAA() && a.aaRgn() == b.aaRgn();
    }
}

static const struct {
    SkISize fDevSize;
    SkIRect fRCBounds;
    SkIRect fRect;
} gRec[] = {
    { { 4000, 10 }, { 0, 0, 4000, 10 }, { 0, 0, 4000, 4000 } },
    { { 10, 4000 }, { 0, 0, 10, 4000 }, { 0, 0, 4000, 4000 } },
    // very large devce, small rect
    { { 32000, 10 }, { 0, 0, 32000, 10 }, { 0, 0, 4000, 4000 } },
    { { 10, 32000 }, { 0, 0, 10, 32000 }, { 0, 0, 4000, 4000 } },
    // very large device, small clip
    { { 32000, 10 }, { 0, 0, 4000, 10 }, { 0, 0, 32000, 32000 } },
    { { 10, 32000 }, { 0, 0, 10, 4000 }, { 0, 0, 32000, 32000 } },
};

static void test_simple(skiatest::Reporter* reporter) {

    for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) {
        SkBitmap bitmap;
        make_bm(&bitmap, gRec[i].fDevSize.width(), gRec[i].fDevSize.height());

        SkRasterClip rc(gRec[i].fRCBounds);

        for (int aa = 0; aa <= 1; ++aa) {
            SkDeviceLooper looper(bitmap, rc, gRec[i].fRect, SkToBool(aa));

            bool valid = looper.next();
            REPORTER_ASSERT(reporter, valid);
            if (valid) {
                REPORTER_ASSERT(reporter, looper.getBitmap().width() == bitmap.width());
                REPORTER_ASSERT(reporter, looper.getBitmap().height() == bitmap.height());
                REPORTER_ASSERT(reporter, equal(looper.getRC(), rc));

                REPORTER_ASSERT(reporter, !looper.next());
            }
        }
        // test that a rect that doesn't intersect returns no loops
        {
            SkIRect r = rc.getBounds();
            r.offset(r.width(), 0);
            SkDeviceLooper looper(bitmap, rc, r, false);
            REPORTER_ASSERT(reporter, !looper.next());
        }
    }
}

// mask-bits are interpreted as the areas where the clip is visible
//  [ 0x01  0x02 ]
//  [ 0x04  0x08 ]
//
static void make_rgn(SkRegion* rgn, int w, int h, unsigned mask) {
    SkASSERT(SkAlign2(w));
    SkASSERT(SkAlign2(h));
    w >>= 1;
    h >>= 1;
    const SkIRect baseR = SkIRect::MakeWH(w, h);

    int bit = 1;
    for (int y = 0; y <= 1; ++y) {
        for (int x = 0; x <= 1; ++x) {
            if (mask & bit) {
                SkIRect r = baseR;
                r.offset(x * w, y * h);
                rgn->op(r, SkRegion::kUnion_Op);
            }
            bit <<= 1;
        }
    }
}

static void test_complex(skiatest::Reporter* reporter) {
    // choose size values that will result in 4 quadrants, given fAA setting
    const int BW_SIZE = 17 * 1000;
    const int AA_SIZE = 7 * 1000;

    struct {
        SkISize fSize;
        bool    fAA;
    } const gRec[] = {
        { { BW_SIZE, BW_SIZE }, false },
        { {  AA_SIZE, AA_SIZE }, true },
    };

    for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) {
        const int w = gRec[i].fSize.width();
        const int h = gRec[i].fSize.height();

        SkBitmap bitmap;
        make_bm(&bitmap, w, h);

        const SkIRect rect = SkIRect::MakeWH(w, h);

        // mask-bits are interpreted as the areas where the clip is visible
        //  [ 0x01  0x02 ]
        //  [ 0x04  0x08 ]
        //
        for (int mask = 0; mask <= 15; ++mask) {
            SkRegion rgn;
            make_rgn(&rgn, w, h, mask);

            SkRasterClip rc;
            rc.op(rgn, SkRegion::kReplace_Op);

            SkDeviceLooper looper(bitmap, rc, rect, gRec[i].fAA);
            while (looper.next()) {
                REPORTER_ASSERT(reporter, !looper.getRC().isEmpty());
            }
        }
    }
}

DEF_TEST(DeviceLooper, reporter) {
    test_simple(reporter);
    test_complex(reporter);
}
