#include "SkBenchmark.h"
#include "SkCanvas.h"
#include "SkColor.h"
#include "SkPaint.h"
#include "SkPicture.h"
#include "SkPictureRecorder.h"
#include "SkPoint.h"
#include "SkRandom.h"
#include "SkRect.h"
#include "SkString.h"
class PictureRecordBench : public SkBenchmark {
public:
    PictureRecordBench(const char name[])  {
        fName.printf("picture_record_%s", name);
    }
    virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
        return backend == kNonRendering_Backend;
    }
    enum {
        PICTURE_WIDTH = 1000,
        PICTURE_HEIGHT = 4000,
    };
protected:
    virtual const char* onGetName() SK_OVERRIDE {
        return fName.c_str();
    }
private:
    SkString fName;
    typedef SkBenchmark INHERITED;
};
static const int kMaxLoopsPerCanvas = 10000;
class DictionaryRecordBench : public PictureRecordBench {
public:
    DictionaryRecordBench() : INHERITED("dictionaries") {}
protected:
    virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
        SkPictureRecorder recorder;
        SkCanvas* canvas = NULL;
        const SkPoint translateDelta = getTranslateDelta(loops);
        for (int i = 0; i < loops; i++) {
            if (0 == i % kMaxLoopsPerCanvas) {
                SkAutoTUnref<SkPicture> picture(recorder.endRecording());
                canvas = recorder.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT, NULL, 0);
            }
            SkColor color = SK_ColorYELLOW + (i % 255);
            SkIRect rect = SkIRect::MakeWH(i % PICTURE_WIDTH, i % PICTURE_HEIGHT);
            canvas->save();
                        SkRegion region;
            region.setRect(rect);
            canvas->clipRegion(region);
                        SkPaint paint;
            paint.setColor(color);
            canvas->drawPaint(paint);
                        SkMatrix matrix;
            matrix.setRotate(SkIntToScalar(i % 360));
            canvas->setMatrix(matrix);
                        SkBitmap bitmap;
            bitmap.allocPixels(SkImageInfo::Make(10, 10,
                                                 kRGB_565_SkColorType, kOpaque_SkAlphaType));
                        SkCanvas bitmapCanvas(bitmap);
            bitmapCanvas.drawColor(SkColorSetA(color, i % 255));
                        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;
};
class UniquePaintDictionaryRecordBench : public PictureRecordBench {
public:
    UniquePaintDictionaryRecordBench() : INHERITED("unique_paint_dictionary") { }
protected:
    virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
        SkRandom rand;
        SkPaint paint;
        SkPictureRecorder recorder;
        SkCanvas* canvas = NULL;
        for (int i = 0; i < loops; i++) {
            if (0 == i % kMaxLoopsPerCanvas) {
                SkAutoTUnref<SkPicture> picture(recorder.endRecording());
                canvas = recorder.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT, NULL, 0);
            }
            paint.setColor(rand.nextU());
            canvas->drawPaint(paint);
        }
    }
private:
    typedef PictureRecordBench INHERITED;
};
class RecurringPaintDictionaryRecordBench : public PictureRecordBench {
public:
    RecurringPaintDictionaryRecordBench() : INHERITED("recurring_paint_dictionary") {
        SkRandom rand;
        for (int i = 0; i < ObjCount; i++) {
            fPaint[i].setColor(rand.nextU());
        }
    }
    enum {
        ObjCount = 100,      };
protected:
    virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
        SkPictureRecorder recorder;
        SkCanvas* canvas = recorder.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT, NULL, 0);
        for (int i = 0; i < loops; i++) {
            canvas->drawPaint(fPaint[i % ObjCount]);
        }
    }
private:
    SkPaint fPaint [ObjCount];
    typedef PictureRecordBench INHERITED;
};
DEF_BENCH( return new DictionaryRecordBench(); )
DEF_BENCH( return new UniquePaintDictionaryRecordBench(); )
DEF_BENCH( return new RecurringPaintDictionaryRecordBench(); )