/*
 * 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/gm.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkFont.h"
#include "include/core/SkFontTypes.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRect.h"
#include "include/core/SkScalar.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "tools/ToolUtils.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.
 */
constexpr SkScalar kTextHeight = 14.0f;
constexpr char kText[] = "Proportional Hamburgefons #% fi";

static void drawTestCase(SkCanvas* canvas,
                         SkScalar textScale,
                         SkScalar strokeWidth,
                         SkPaint::Style strokeStyle);

static void draw_gm(SkCanvas* canvas,
                    SkScalar strokeWidth,
                    SkPaint::Style strokeStyle) {
    // There's a black pixel at 40, 40 for reference.
    canvas->drawPoint(40, 40, SkPaint());

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

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

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

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

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

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

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

static void drawTestCase(SkCanvas* canvas,
                         SkScalar textScale,
                         SkScalar strokeWidth,
                         SkPaint::Style strokeStyle) {
    SkPaint paint;
    paint.setColor(SK_ColorBLACK);
    paint.setAntiAlias(true);
    paint.setStrokeWidth(strokeWidth);
    paint.setStyle(strokeStyle);

    SkFont font(ToolUtils::create_portable_typeface(), kTextHeight * textScale);

    // 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 = font.measureText(kText, sizeof(kText) - 1, SkTextEncoding::kUTF8,
                                            &bounds, &paint);

        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(strokeWidth);
    paint.setStyle(strokeStyle);
    canvas->drawSimpleText(kText, sizeof(kText) - 1, SkTextEncoding::kUTF8,
                           0.0f, 0.0f, font, paint);

    if (drawRef) {
        const size_t len = sizeof(kText) - 1;
        SkGlyphID glyphs[len];
        const int count = font.textToGlyphs(kText, len, SkTextEncoding::kUTF8, glyphs, len);
        SkScalar widths[len]; // len is conservative. we really only need 'count'
        font.getWidthsBounds(glyphs, count, widths, nullptr, &paint);

        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];
        }
    }
}

DEF_SIMPLE_GM(glyph_pos_h_b, c, 800, 600) {
    draw_gm(c, 0.0f, SkPaint::kStrokeAndFill_Style);
}
DEF_SIMPLE_GM(glyph_pos_n_b, c, 800, 600) {
    draw_gm(c, 1.2f, SkPaint::kStrokeAndFill_Style);
}
DEF_SIMPLE_GM(glyph_pos_h_s, c, 800, 600) {
    draw_gm(c, 0.0f, SkPaint::kStroke_Style);
}
DEF_SIMPLE_GM(glyph_pos_n_s, c, 800, 600) {
    draw_gm(c, 1.2f, SkPaint::kStroke_Style);
}
DEF_SIMPLE_GM(glyph_pos_h_f, c, 800, 600) {
    draw_gm(c, 0.0f, SkPaint::kFill_Style);
}
DEF_SIMPLE_GM(glyph_pos_n_f, c, 800, 600) {
    draw_gm(c, 1.2f, SkPaint::kFill_Style);
}
