/*
 * 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() override {
        // 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());
}
