
/*
 * Copyright 2011 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 "SkColorShader.h"
#include "SkFontHost.h"
#include "SkPaint.h"
#include "SkRandom.h"
#include "SkString.h"
#include "SkTemplates.h"

#define STR     "Hamburgefons"

enum FontQuality {
    kBW,
    kAA,
    kLCD
};

static const char* fontQualityName(const SkPaint& paint) {
    if (!paint.isAntiAlias()) {
        return "BW";
    }
    if (paint.isLCDRenderText()) {
        return "LCD";
    }
    return "AA";
}

class ShaderMaskBench : public SkBenchmark {
    SkPaint     fPaint;
    SkString    fText;
    SkString    fName;
    FontQuality fFQ;
public:
    ShaderMaskBench(void* param, bool isOpaque, FontQuality fq) : INHERITED(param) {
        fFQ = fq;
        fText.set(STR);

        fPaint.setAntiAlias(kBW != fq);
        fPaint.setLCDRenderText(kLCD == fq);
        fPaint.setAlpha(isOpaque ? 0xFF : 0x80);
        fPaint.setShader(new SkColorShader)->unref();
    }

protected:
    virtual const char* onGetName() {
        fName.printf("shadermask");
        fName.appendf("_%s", fontQualityName(fPaint));
        fName.appendf("_%02X", fPaint.getAlpha());
        return fName.c_str();
    }

    virtual void onDraw(SkCanvas* canvas) {
        const SkIPoint dim = this->getSize();
        SkRandom rand;

        SkPaint paint(fPaint);
        this->setupPaint(&paint);
        // explicitly need these
        paint.setAlpha(fPaint.getAlpha());
        paint.setAntiAlias(kBW != fFQ);
        paint.setLCDRenderText(kLCD == fFQ);

        const SkScalar x0 = SkIntToScalar(-10);
        const SkScalar y0 = SkIntToScalar(-10);

        paint.setTextSize(SkIntToScalar(12));
        for (int i = 0; i < this->getLoops(); i++) {
            SkScalar x = x0 + rand.nextUScalar1() * dim.fX;
            SkScalar y = y0 + rand.nextUScalar1() * dim.fY;
            canvas->drawText(fText.c_str(), fText.size(), x, y, paint);
        }

        paint.setTextSize(SkIntToScalar(48));
        for (int i = 0; i < this->getLoops() / 4 ; i++) {
            SkScalar x = x0 + rand.nextUScalar1() * dim.fX;
            SkScalar y = y0 + rand.nextUScalar1() * dim.fY;
            canvas->drawText(fText.c_str(), fText.size(), x, y, paint);
        }
    }

private:
    typedef SkBenchmark INHERITED;
};

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

static SkBenchmark* Fact00(void* p) { return new ShaderMaskBench(p, true,  kBW); }
static SkBenchmark* Fact01(void* p) { return new ShaderMaskBench(p, false, kBW); }
static SkBenchmark* Fact10(void* p) { return new ShaderMaskBench(p, true,  kAA); }
static SkBenchmark* Fact11(void* p) { return new ShaderMaskBench(p, false, kAA); }
static SkBenchmark* Fact20(void* p) { return new ShaderMaskBench(p, true,  kLCD); }
static SkBenchmark* Fact21(void* p) { return new ShaderMaskBench(p, false, kLCD); }

static BenchRegistry gReg00(Fact00);
static BenchRegistry gReg01(Fact01);
static BenchRegistry gReg10(Fact10);
static BenchRegistry gReg11(Fact11);
static BenchRegistry gReg20(Fact20);
static BenchRegistry gReg21(Fact21);
