/*
 * 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 "gm.h"
#include "SkCanvas.h"
#include "SkTypeface.h"

/* This test tries to define the effect of using hairline strokes on text.
 * Provides non-hairline images for reference and consistency checks.
 * glyph_pos_(h/n)_(s/f/b)
 *   -> test hairline/non-hairline stroke/fill/stroke+fill.
 */
static const SkScalar kTextHeight = 14.0f;
static const char kText[] = "Proportional Hamburgefons #% fi";

namespace skiagm {

class GlyphPosGM : public GM {
public:
    GlyphPosGM(SkScalar strokeWidth, SkPaint::Style strokeStyle)
        : fStrokeWidth(strokeWidth)
        , fStrokeStyle(strokeStyle) {
        }

protected:
    virtual uint32_t onGetFlags() const SK_OVERRIDE {
        return kSkipTiled_Flag;
    }

    virtual SkString onShortName() SK_OVERRIDE {
        SkString str("glyph_pos");
        if (fStrokeWidth == 0.0f) {
            str.append("_h"); // h == Hairline.
        } else {
            str.append("_n"); // n == Normal.
        }
        if (fStrokeStyle == SkPaint::kStroke_Style) {
            str.append("_s");
        } else if (fStrokeStyle == SkPaint::kFill_Style) {
            str.append("_f");
        } else {
            str.append("_b"); // b == Both.
        }
        return str;
    }

    virtual SkISize onISize() { return SkISize::Make(800, 600); }

    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
        if (!fProp) {
            fProp.reset(SkTypeface::CreateFromName("Helvetica", SkTypeface::kNormal));
        }

        // There's a black pixel at 40, 40 for reference.
        canvas->drawPoint(40.0f, 40.0f, SK_ColorBLACK);

        // Two reference images.
        canvas->translate(50.0f, 50.0f);
        drawTestCase(canvas, 1.0f);

        canvas->translate(0.0f, 50.0f);
        drawTestCase(canvas, 3.0f);

        // Uniform scaling test.
        canvas->translate(0.0f, 100.0f);
        canvas->save();
        canvas->scale(3.0f, 3.0f);
        drawTestCase(canvas, 1.0f);
        canvas->restore();

        // Non-uniform scaling test.
        canvas->translate(0.0f, 100.0f);
        canvas->save();
        canvas->scale(3.0f, 6.0f);
        drawTestCase(canvas, 1.0f);
        canvas->restore();

        // Skew test.
        canvas->translate(0.0f, 80.0f);
        canvas->save();
        canvas->scale(3.0f, 3.0f);
        SkMatrix skew;
        skew.setIdentity();
        skew.setSkewX(SkScalarDiv(8.0f,
                                  25.0f));
        skew.setSkewY(SkScalarDiv(2.0f,
                                  25.0f));
        canvas->concat(skew);
        drawTestCase(canvas, 1.0f);
        canvas->restore();

        // Perspective test.
        canvas->translate(0.0f, 80.0f);
        canvas->save();
        SkMatrix perspective;
        perspective.setIdentity();
        perspective.setPerspX(-SkScalarDiv(SK_Scalar1, 340.0f));
        perspective.setSkewX(SkScalarDiv(8.0f,
                                         25.0f));
        perspective.setSkewY(SkScalarDiv(2.0f,
                                         25.0f));


        canvas->concat(perspective);
        drawTestCase(canvas, 1.0f);
        canvas->restore();
    }

    void drawTestCase(SkCanvas* canvas, SkScalar textScale) {
        SkPaint paint;
        paint.setColor(SK_ColorBLACK);
        paint.setAntiAlias(true);
        paint.setTextSize(kTextHeight * textScale);
        paint.setTypeface(fProp);
        paint.setDevKernText(true);
        paint.setStrokeWidth(fStrokeWidth);
        paint.setStyle(fStrokeStyle);

        // This demonstrates that we can not measure the text if there's a device transform. The
        // canvas total matrix will end up being a device transform.
        bool drawRef = !(canvas->getTotalMatrix().getType() &
                         ~(SkMatrix::kIdentity_Mask | SkMatrix::kTranslate_Mask));

        SkRect bounds;
        if (drawRef) {
            SkScalar advance = paint.measureText(kText, sizeof(kText) - 1, &bounds);

            paint.setStrokeWidth(0.0f);
            paint.setStyle(SkPaint::kStroke_Style);

            // Green box is the measured text bounds.
            paint.setColor(SK_ColorGREEN);
            canvas->drawRect(bounds, paint);

            // Red line is the measured advance from the 0,0 of the text position.
            paint.setColor(SK_ColorRED);
            canvas->drawLine(0.0f, 0.0f, advance, 0.0f, paint);
        }

        // Black text is the testcase, eg. the text.
        paint.setColor(SK_ColorBLACK);
        paint.setStrokeWidth(fStrokeWidth);
        paint.setStyle(fStrokeStyle);
        canvas->drawText(kText, sizeof(kText) - 1, 0.0f, 0.0f, paint);

        if (drawRef) {
            SkScalar widths[sizeof(kText) - 1];
            paint.getTextWidths(kText, sizeof(kText) - 1, widths, NULL);

            paint.setStrokeWidth(0.0f);
            paint.setStyle(SkPaint::kStroke_Style);

            // Magenta lines are the positions for the characters.
            paint.setColor(SK_ColorMAGENTA);
            SkScalar w = bounds.x();
            for (size_t i = 0; i < sizeof(kText) - 1; ++i) {
                canvas->drawLine(w, 0.0f, w, 5.0f, paint);
                w += widths[i];
            }
        }
    }

private:
    SkAutoTUnref<SkTypeface> fProp;
    SkScalar fStrokeWidth;
    SkPaint::Style fStrokeStyle;

    typedef GM INHERITED;
};

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

static GM* GlyphPosHairlineStrokeAndFillFactory(void*) {
    return new GlyphPosGM(0.0f, SkPaint::kStrokeAndFill_Style);
}
static GM* GlyphPosStrokeAndFillFactory(void*) {
    return new GlyphPosGM(1.2f, SkPaint::kStrokeAndFill_Style);
}
static GM* GlyphPosHairlineStrokeFactory(void*) {
    return new GlyphPosGM(0.0f, SkPaint::kStroke_Style);
}
static GM* GlyphPosStrokeFactory(void*) {
    return new GlyphPosGM(1.2f, SkPaint::kStroke_Style);
}
static GM* GlyphPosHairlineFillFactory(void*) {
    return new GlyphPosGM(0.0f, SkPaint::kFill_Style);
}
static GM* GlyphPosFillFactory(void*) {
    return new GlyphPosGM(1.2f, SkPaint::kFill_Style);
}

static GMRegistry reg1(GlyphPosHairlineStrokeAndFillFactory);
static GMRegistry reg2(GlyphPosStrokeAndFillFactory);
static GMRegistry reg3(GlyphPosHairlineStrokeFactory);
static GMRegistry reg4(GlyphPosStrokeFactory);
static GMRegistry reg5(GlyphPosHairlineFillFactory);
static GMRegistry reg6(GlyphPosFillFactory);


}
