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

#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkColor.h"
#include "SkColorFilter.h"
#include "SkGradientShader.h"
#include "SkPaint.h"
#include "SkPictureFlat.h"
#include "SkShader.h"
#include "SkXfermode.h"
#include "Test.h"

static void flattenFlattenableProc(SkOrderedWriteBuffer& buffer,
                                   const void* obj) {
    buffer.writeFlattenable((SkFlattenable*)obj);
}

class Controller : public SkChunkFlatController {
public:
    Controller() : INHERITED(1024) {
        this->INHERITED::setNamedFactorySet(SkNEW(SkNamedFactorySet))->unref();
    }
private:
    typedef SkChunkFlatController INHERITED;
};

/**
 * Verify that two SkFlatData objects that created from the same object are
 * identical when using an SkNamedFactorySet.
 * @param reporter Object to report failures.
 * @param obj Flattenable object to be flattened.
 * @param flattenProc Function that flattens objects with the same type as obj.
 */
static void testCreate(skiatest::Reporter* reporter, const void* obj,
                       void (*flattenProc)(SkOrderedWriteBuffer&, const void*)) {
    Controller controller;
    // No need to delete data because that will be taken care of by the
    // controller.
    SkFlatData* data1 = SkFlatData::Create(&controller, obj, 0, flattenProc);
    data1->setSentinelInCache();
    SkFlatData* data2 = SkFlatData::Create(&controller, obj, 1, flattenProc);
    data2->setSentinelAsCandidate();
    REPORTER_ASSERT(reporter, SkFlatData::Compare(data1, data2) == 0);
}

static void Tests(skiatest::Reporter* reporter) {
    // Test flattening SkShader
    SkPoint points[2];
    points[0].set(0, 0);
    points[1].set(SkIntToScalar(20), SkIntToScalar(20));
    SkColor colors[2];
    colors[0] = SK_ColorRED;
    colors[1] = SK_ColorBLUE;
    SkShader* shader = SkGradientShader::CreateLinear(points, colors, NULL,
                                            2, SkShader::kRepeat_TileMode);
    SkAutoUnref aur(shader);
    testCreate(reporter, shader, flattenFlattenableProc);

    // Test SkBitmap
    {
        SkBitmap bm;
        bm.setConfig(SkBitmap::kARGB_8888_Config, 50, 50);
        bm.allocPixels();
        SkCanvas canvas(bm);
        SkPaint paint;
        paint.setShader(shader);
        canvas.drawPaint(paint);
        testCreate(reporter, &bm, &SkFlattenObjectProc<SkBitmap>);
    }

    // Test SkColorFilter
    SkColorFilter* cf = SkColorFilter::CreateLightingFilter(SK_ColorBLUE,
                                                            SK_ColorRED);
    SkAutoUnref aurcf(cf);
    testCreate(reporter, cf, &flattenFlattenableProc);

    // Test SkXfermode
    SkXfermode* xfer = SkXfermode::Create(SkXfermode::kDstOver_Mode);
    SkAutoUnref aurxf(xfer);
    testCreate(reporter, xfer, &flattenFlattenableProc);
}

#include "TestClassDef.h"
DEFINE_TESTCLASS("FlatData", FlatDataClass, Tests)
