/*
 * 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 "SkBenchmark.h"
#include "SkCanvas.h"
#include "SkColor.h"
#include "SkPaint.h"
#include "SkPicture.h"
#include "SkPoint.h"
#include "SkRandom.h"
#include "SkRect.h"
#include "SkString.h"

class PictureRecordBench : public SkBenchmark {
public:
    PictureRecordBench(void* param, const char name[]) : INHERITED(param) {
        fName.printf("picture_record_%s", name);
        fPictureWidth = SkIntToScalar(PICTURE_WIDTH);
        fPictureHeight = SkIntToScalar(PICTURE_HEIGHT);
        fIsRendering = false;
    }

    enum {
        PICTURE_WIDTH = 1000,
        PICTURE_HEIGHT = 4000,
    };
protected:
    virtual const char* onGetName() {
        return fName.c_str();
    }

    virtual void onDraw(SkCanvas*) {
        SkPicture picture;

        SkCanvas* pCanvas = picture.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT);
        recordCanvas(pCanvas);

        // we don't need to draw the picture as the endRecording step will
        // do the work of transferring the recorded content into a playback
        // object.
        picture.endRecording();
    }

    virtual void recordCanvas(SkCanvas* canvas) = 0;

    SkString fName;
    SkScalar fPictureWidth;
    SkScalar fPictureHeight;
    SkScalar fTextSize;
private:
    typedef SkBenchmark INHERITED;
};

/*
 *  An SkPicture has internal dictionaries to store bitmaps, matrices, paints,
 *  and regions.  This bench populates those dictionaries to test the speed of
 *  reading and writing to those particular dictionary data structures.
 */
class DictionaryRecordBench : public PictureRecordBench {
public:
    DictionaryRecordBench(void* param)
        : INHERITED(param, "dictionaries") { }

protected:
    virtual void recordCanvas(SkCanvas* canvas) {

        const SkPoint translateDelta = getTranslateDelta(this->getLoops());

        for (int i = 0; i < this->getLoops(); i++) {

            SkColor color = SK_ColorYELLOW + (i % 255);
            SkIRect rect = SkIRect::MakeWH(i % PICTURE_WIDTH, i % PICTURE_HEIGHT);

            canvas->save();

            // set the clip to the given region
            SkRegion region;
            region.setRect(rect);
            canvas->clipRegion(region);

            // fill the clip with a color
            SkPaint paint;
            paint.setColor(color);
            canvas->drawPaint(paint);

            // set a matrix on the canvas
            SkMatrix matrix;
            matrix.setRotate(SkIntToScalar(i % 360));
            canvas->setMatrix(matrix);

            // create a simple bitmap
            SkBitmap bitmap;
            bitmap.setConfig(SkBitmap::kRGB_565_Config, 10, 10);
            bitmap.allocPixels();

            // draw a single color into the bitmap
            SkCanvas bitmapCanvas(bitmap);
            bitmapCanvas.drawColor(SkColorSetA(color, i % 255));

            // draw the bitmap onto the canvas
            canvas->drawBitmapMatrix(bitmap, matrix);

            canvas->restore();
            canvas->translate(translateDelta.fX, translateDelta.fY);
        }
    }

    SkPoint getTranslateDelta(int M) {
        SkIPoint canvasSize = onGetSize();
        return SkPoint::Make(SkIntToScalar((PICTURE_WIDTH - canvasSize.fX)/M),
                             SkIntToScalar((PICTURE_HEIGHT- canvasSize.fY)/M));
    }
private:
    typedef PictureRecordBench INHERITED;
};

/*
 *  Populates the SkPaint dictionary with a large number of unique paint
 *  objects that differ only by color
 */
class UniquePaintDictionaryRecordBench : public PictureRecordBench {
public:
    UniquePaintDictionaryRecordBench(void* param)
        : INHERITED(param, "unique_paint_dictionary") { }

protected:
    virtual void recordCanvas(SkCanvas* canvas) {
        SkRandom rand;
        for (int i = 0; i < this->getLoops(); i++) {
            SkPaint paint;
            paint.setColor(rand.nextU());
            canvas->drawPaint(paint);
        }
    }

private:
    typedef PictureRecordBench INHERITED;
};

/*
 *  Populates the SkPaint dictionary with a number of unique paint
 *  objects that get reused repeatedly.
 *
 *  Re-creating the paint objects in the inner loop slows the benchmark down 10%.
 *  Using setColor(i % objCount) instead of a random color creates a very high rate
 *  of hash conflicts, slowing us down 12%.
 */
class RecurringPaintDictionaryRecordBench : public PictureRecordBench {
public:
    RecurringPaintDictionaryRecordBench(void* param)
        : INHERITED(param, "recurring_paint_dictionary") {
        SkRandom rand;
        for (int i = 0; i < ObjCount; i++) {
            fPaint[i].setColor(rand.nextU());
        }
    }

    enum {
        ObjCount = 100,  // number of unique paint objects
    };
protected:
    virtual void recordCanvas(SkCanvas* canvas) {

        for (int i = 0; i < this->getLoops(); i++) {
            canvas->drawPaint(fPaint[i % ObjCount]);
        }
    }

private:
    SkPaint fPaint [ObjCount];
    typedef PictureRecordBench INHERITED;
};

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

static SkBenchmark* Fact0(void* p) { return new DictionaryRecordBench(p); }
static SkBenchmark* Fact1(void* p) { return new UniquePaintDictionaryRecordBench(p); }
static SkBenchmark* Fact2(void* p) { return new RecurringPaintDictionaryRecordBench(p); }

static BenchRegistry gReg0(Fact0);
static BenchRegistry gReg1(Fact1);
static BenchRegistry gReg2(Fact2);
