/*
 * Copyright 2015 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/SkBitmap.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/SkPoint.h"
#include "include/core/SkRRect.h"
#include "include/core/SkRect.h"
#include "include/core/SkScalar.h"
#include "include/core/SkShader.h"
#include "include/core/SkTextBlob.h"
#include "include/core/SkTileMode.h"
#include "include/core/SkTypeface.h"
#include "tools/ToolUtils.h"
#include "tools/fonts/FontToolUtils.h"

#include <string.h>

static void rotated_checkerboard_shader(SkPaint* paint,
                                        SkColor c1,
                                        SkColor c2,
                                        int size) {
    SkBitmap bm;
    bm.allocN32Pixels(2 * size, 2 * size);
    bm.eraseColor(c1);
    bm.eraseArea(SkIRect::MakeLTRB(0, 0, size, size), c2);
    bm.eraseArea(SkIRect::MakeLTRB(size, size, 2 * size, 2 * size), c2);
    SkMatrix matrix;
    matrix.setScale(0.75f, 0.75f);
    matrix.preRotate(30.0f);
    paint->setShader(bm.makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat,
                                   SkSamplingOptions(), matrix));
}

static void exercise_draw_pos_text(SkCanvas* canvas,
                                   const char* text,
                                   SkScalar x, SkScalar y,
                                   const SkFont& font, const SkPaint& paint) {
    const size_t count = font.countText(text, strlen(text), SkTextEncoding::kUTF8);
    SkTextBlobBuilder builder;
    auto rec = builder.allocRunPos(font, count);
    font.textToGlyphs(text, strlen(text), SkTextEncoding::kUTF8, {rec.glyphs, count});
    font.getPos({rec.glyphs, count}, {rec.points(), count}, {x, y});
    canvas->drawTextBlob(builder.make(), 0, 0, paint);
}

static void exercise_draw_pos_text_h(SkCanvas* canvas,
                                     const char* text,
                                     SkScalar x, SkScalar y,
                                     const SkFont& font, const SkPaint& paint) {
    const size_t count = font.countText(text, strlen(text), SkTextEncoding::kUTF8);
    SkTextBlobBuilder builder;
    auto rec = builder.allocRunPosH(font, count, 0);
    font.textToGlyphs(text, strlen(text), SkTextEncoding::kUTF8, {rec.glyphs, count});
    font.getXPos({rec.glyphs, count}, {rec.pos, count});
    canvas->drawTextBlob(builder.make(), x, y, paint);
}

static void test_text(SkCanvas* canvas, SkScalar size,
                      SkColor color, SkScalar Y) {
    SkFont font(ToolUtils::DefaultPortableTypeface(), 24);
    font.setEdging(SkFont::Edging::kAlias);
    SkPaint type;
    type.setColor(color);
    const char text[] = "HELLO WORLD";
    canvas->drawSimpleText(text, strlen(text), SkTextEncoding::kUTF8, 32, size / 2 + Y,
                           font, type);
    SkScalar lineSpacing = font.getSpacing();
    exercise_draw_pos_text(canvas, text, 32, size / 2 + Y + lineSpacing, font, type);
    exercise_draw_pos_text_h(canvas, text, 32,
                             size / 2 + Y + 2 * lineSpacing, font, type);
}

// If this GM works correctly, the cyan layer should be lined up with
// the objects below it.
DEF_SIMPLE_GM(skbug_257, canvas, 512, 512) {
    const SkScalar size = 256;
    SkAutoCanvasRestore autoCanvasRestore0(canvas, true);
    const SkScalar scale = 1.00168f;
    canvas->scale(scale, scale);
    {
        SkPaint checker;
        rotated_checkerboard_shader(&checker, SK_ColorWHITE, SK_ColorBLACK, 16);
        checker.setAntiAlias(true);

        SkAutoCanvasRestore autoCanvasRestore(canvas, true);
        canvas->clear(0xFFCECFCE);
        SkScalar translate = 225364.0f;
        canvas->translate(0, -translate);

        // Test rects
        SkRect rect = SkRect::MakeLTRB(8, 8 + translate, size - 8,
                                       size - 8 + translate);
        canvas->drawRect(rect, checker);

        // Test Paths
        canvas->translate(size, 0);
        SkRRect rrect;
        SkVector radii[4] = {{40, 40}, {40, 40}, {40, 40}, {40, 40}};
        rrect.setRectRadii(rect, radii);
        canvas->drawRRect(rrect, checker);

        // Test Points
        canvas->translate(-size, size);
        SkScalar delta = 1.0 / 64.0;
        SkPoint points[8] = {{size / 2, 8 + translate},
                             {size / 2, 8 + translate + delta},
                             {8, size / 2 + translate},
                             {8, size / 2 + translate + delta},
                             {size / 2, size - 8 + translate},
                             {size / 2, size - 8 + translate + delta},
                             {size - 8, size / 2 + translate},
                             {size - 8, size / 2 + translate + delta}};
        checker.setStyle(SkPaint::kStroke_Style);
        checker.setStrokeWidth(8);
        checker.setStrokeCap(SkPaint::kRound_Cap);
        canvas->drawPoints(SkCanvas::kLines_PointMode, points, checker);

        // Test Text
        canvas->translate(size, 0);
        test_text(canvas, size, SK_ColorBLACK, translate);
    }
    // reference points (without the huge translations).
    SkPaint stroke;
    stroke.setStyle(SkPaint::kStroke_Style);
    stroke.setStrokeWidth(5);
    stroke.setColor(SK_ColorCYAN);
    canvas->drawCircle(size / 2, size / 2, size / 2 - 10, stroke);
    canvas->drawCircle(3 * size / 2, size / 2, size / 2 - 10, stroke);
    canvas->drawCircle(size / 2, 384, size / 2 - 10, stroke);
    canvas->translate(size, size);
    test_text(canvas, size, SK_ColorCYAN, 0.0f);
}
