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

#include "SkDeque.h"
#include "SkLayerRasterizer.h"
#include "SkPaint.h"
#include "SkRasterizer.h"
#include "Test.h"

class SkReadBuffer;

// Dummy class to place on a paint just to ensure the paint's destructor
// is called.
// ONLY to be used by LayerRasterizer_destructor, since other tests may
// be run in a separate thread, and this class is not threadsafe.
class DummyRasterizer : public SkRasterizer {
public:
    DummyRasterizer()
        : INHERITED()
    {
        // Not threadsafe. Only used in one thread.
        gCount++;
    }

    ~DummyRasterizer() {
        // Not threadsafe. Only used in one thread.
        gCount--;
    }

    static int GetCount() { return gCount; }

    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(DummyRasterizer);

private:
    static int gCount;

    typedef SkRasterizer INHERITED;
};

int DummyRasterizer::gCount;

sk_sp<SkFlattenable> DummyRasterizer::CreateProc(SkReadBuffer&) {
    return sk_make_sp<DummyRasterizer>();
}

// Check to make sure that the SkPaint in the layer has its destructor called.
DEF_TEST(LayerRasterizer_destructor, reporter) {
    {
        SkPaint paint;
        paint.setRasterizer(sk_make_sp<DummyRasterizer>());
        REPORTER_ASSERT(reporter, DummyRasterizer::GetCount() == 1);

        SkLayerRasterizer::Builder builder;
        builder.addLayer(paint);
    }
    REPORTER_ASSERT(reporter, DummyRasterizer::GetCount() == 0);
}

class LayerRasterizerTester {
public:
    static int CountLayers(const SkLayerRasterizer& layerRasterizer) {
        return layerRasterizer.fLayers->count();
    }

    static const SkDeque& GetLayers(const SkLayerRasterizer& layerRasterizer) {
        return *layerRasterizer.fLayers;
    }
};

// MUST stay in sync with definition of SkLayerRasterizer_Rec in SkLayerRasterizer.cpp.
struct SkLayerRasterizer_Rec {
    SkPaint     fPaint;
    SkVector    fOffset;
};

static bool equals(const SkLayerRasterizer_Rec& rec1, const SkLayerRasterizer_Rec& rec2) {
    return rec1.fPaint == rec2.fPaint && rec1.fOffset == rec2.fOffset;
}

DEF_TEST(LayerRasterizer_copy, reporter) {
    SkLayerRasterizer::Builder builder;
    REPORTER_ASSERT(reporter, nullptr == builder.snapshot());
    SkPaint paint;
    // Create a bunch of paints with different flags.
    for (uint32_t flags = 0x01; flags < SkPaint::kAllFlags; flags <<= 1) {
        paint.setFlags(flags);
        builder.addLayer(paint, static_cast<SkScalar>(flags), static_cast<SkScalar>(flags));
    }

    // Create a layer rasterizer with all the existing layers.
    sk_sp<SkLayerRasterizer> firstCopy(builder.snapshot());

    // Add one more layer.
    paint.setFlags(SkPaint::kAllFlags);
    builder.addLayer(paint);

    sk_sp<SkLayerRasterizer> oneLarger(builder.snapshot());
    sk_sp<SkLayerRasterizer> detached(builder.detach());

    // Check the counts for consistency.
    const int largerCount = LayerRasterizerTester::CountLayers(*oneLarger.get());
    const int smallerCount = LayerRasterizerTester::CountLayers(*firstCopy.get());
    REPORTER_ASSERT(reporter, largerCount == LayerRasterizerTester::CountLayers(*detached.get()));
    REPORTER_ASSERT(reporter, smallerCount == largerCount - 1);

    const SkLayerRasterizer_Rec* recFirstCopy = nullptr;
    const SkLayerRasterizer_Rec* recOneLarger = nullptr;
    const SkLayerRasterizer_Rec* recDetached = nullptr;

    const SkDeque& layersFirstCopy = LayerRasterizerTester::GetLayers(*firstCopy.get());
    const SkDeque& layersOneLarger = LayerRasterizerTester::GetLayers(*oneLarger.get());
    const SkDeque& layersDetached = LayerRasterizerTester::GetLayers(*detached.get());

    // Ensure that our version of SkLayerRasterizer_Rec is the same as the one in
    // SkLayerRasterizer.cpp - or at least the same size. If the order were switched, we
    // would fail the test elsewhere.
    REPORTER_ASSERT(reporter, layersFirstCopy.elemSize() == sizeof(SkLayerRasterizer_Rec));
    REPORTER_ASSERT(reporter, layersOneLarger.elemSize() == sizeof(SkLayerRasterizer_Rec));
    REPORTER_ASSERT(reporter, layersDetached.elemSize() == sizeof(SkLayerRasterizer_Rec));

    SkDeque::F2BIter iterFirstCopy(layersFirstCopy);
    SkDeque::F2BIter iterOneLarger(layersOneLarger);
    SkDeque::F2BIter iterDetached(layersDetached);

    for (int i = 0; i < largerCount; ++i) {
        recFirstCopy = static_cast<const SkLayerRasterizer_Rec*>(iterFirstCopy.next());
        recOneLarger = static_cast<const SkLayerRasterizer_Rec*>(iterOneLarger.next());
        recDetached  = static_cast<const SkLayerRasterizer_Rec*>(iterDetached.next());

        REPORTER_ASSERT(reporter, equals(*recOneLarger, *recDetached));
        if (smallerCount == i) {
            REPORTER_ASSERT(reporter, recFirstCopy == nullptr);
        } else {
            REPORTER_ASSERT(reporter, equals(*recFirstCopy, *recOneLarger));
        }
    }
}

DEF_TEST(LayerRasterizer_detachEmpty, reporter) {
    SkLayerRasterizer::Builder builder;
    REPORTER_ASSERT(reporter, nullptr == builder.detach());
}
