/*
 * 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(sk_tool_utils::create_portable_typeface("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);


}
