/*
 * 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 "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkFont.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPathEffect.h"  // IWYU pragma: keep
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTextBlob.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "include/effects/SkDashPathEffect.h"
#include "tests/Test.h"
#include "tools/fonts/FontToolUtils.h"

#include <array>
#include <cmath>
#include <cstring>

static const SkColor bgColor = SK_ColorWHITE;

static void create(SkBitmap* bm, SkIRect bound) {
    bm->allocN32Pixels(bound.width(), bound.height());
}

/** Assumes that the ref draw was completely inside ref canvas --
    implies that everything outside is "bgColor".
    Checks that all overlap is the same and that all non-overlap on the
    ref is "bgColor".
 */
static bool compare(const SkBitmap& ref, const SkIRect& iref,
                    const SkBitmap& test, const SkIRect& itest)
{
    const int xOff = itest.fLeft - iref.fLeft;
    const int yOff = itest.fTop - iref.fTop;

    for (int y = 0; y < test.height(); ++y) {
        for (int x = 0; x < test.width(); ++x) {
            SkColor testColor = test.getColor(x, y);
            int refX = x + xOff;
            int refY = y + yOff;
            SkColor refColor;
            if (refX >= 0 && refX < ref.width() &&
                refY >= 0 && refY < ref.height())
            {
                refColor = ref.getColor(refX, refY);
            } else {
                refColor = bgColor;
            }
            if (refColor != testColor) {
                return false;
            }
        }
    }
    return true;
}

/** Test that drawing glyphs with empty paths is different from drawing glyphs without paths. */
DEF_TEST(DrawText_dashout, reporter) {
    SkIRect size = SkIRect::MakeWH(64, 64);

    SkBitmap drawTextBitmap;
    create(&drawTextBitmap, size);
    SkCanvas drawTextCanvas(drawTextBitmap);

    SkBitmap drawDashedTextBitmap;
    create(&drawDashedTextBitmap, size);
    SkCanvas drawDashedTextCanvas(drawDashedTextBitmap);

    SkBitmap emptyBitmap;
    create(&emptyBitmap, size);
    SkCanvas emptyCanvas(emptyBitmap);

    SkPoint point = SkPoint::Make(25.0f, 25.0f);
    SkFont font(ToolUtils::DefaultTypeface(), 20);
    font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
    font.setSubpixel(true);

    SkPaint paint;
    paint.setColor(SK_ColorGRAY);
    paint.setStyle(SkPaint::kStroke_Style);

    // Draw a stroked "A" without a dash which will draw something.
    drawTextCanvas.drawColor(SK_ColorWHITE);
    drawTextCanvas.drawString("A", point.fX, point.fY, font, paint);

    // Draw an "A" but with a dash which will never draw anything.
    paint.setStrokeWidth(2);
    constexpr SkScalar bigInterval = 10000;
    static constexpr SkScalar intervals[] = { 1, bigInterval };
    paint.setPathEffect(SkDashPathEffect::Make(intervals, std::size(intervals), 2));

    drawDashedTextCanvas.drawColor(SK_ColorWHITE);
    drawDashedTextCanvas.drawString("A", point.fX, point.fY, font, paint);

    // Draw nothing.
    emptyCanvas.drawColor(SK_ColorWHITE);

    REPORTER_ASSERT(reporter, !compare(drawTextBitmap, size, emptyBitmap, size));
    REPORTER_ASSERT(reporter, compare(drawDashedTextBitmap, size, emptyBitmap, size));
}

// Test drawing text at some unusual coordinates.
// We measure success by not crashing or asserting.
DEF_TEST(DrawText_weirdCoordinates, r) {
    auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(10, 10));
    auto canvas = surface->getCanvas();
    SkFont font = ToolUtils::DefaultFont();

    SkScalar oddballs[] = { 0.0f, (float)INFINITY, (float)NAN, 34359738368.0f };

    for (auto x : oddballs) {
        canvas->drawString("a", +x, 0.0f, font, SkPaint());
        canvas->drawString("a", -x, 0.0f, font, SkPaint());
    }
    for (auto y : oddballs) {
        canvas->drawString("a", 0.0f, +y, font, SkPaint());
        canvas->drawString("a", 0.0f, -y, font, SkPaint());
    }
}

// Test drawing text with some unusual matrices.
// We measure success by not crashing or asserting.
DEF_TEST(DrawText_weirdMatricies, r) {
    auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(100, 100));
    auto canvas = surface->getCanvas();

    SkFont font = ToolUtils::DefaultFont();
    font.setEdging(SkFont::Edging::kSubpixelAntiAlias);

    struct {
        SkScalar textSize;
        SkScalar matrix[9];
    } testCases[] = {
        // 2x2 singular
        {10, { 0,  0,  0,  0,  0,  0,  0,  0,  1}},
        {10, { 0,  0,  0,  0,  1,  0,  0,  0,  1}},
        {10, { 0,  0,  0,  1,  0,  0,  0,  0,  1}},
        {10, { 0,  0,  0,  1,  1,  0,  0,  0,  1}},
        {10, { 0,  1,  0,  0,  1,  0,  0,  0,  1}},
        {10, { 1,  0,  0,  0,  0,  0,  0,  0,  1}},
        {10, { 1,  0,  0,  1,  0,  0,  0,  0,  1}},
        {10, { 1,  1,  0,  0,  0,  0,  0,  0,  1}},
        {10, { 1,  1,  0,  1,  1,  0,  0,  0,  1}},
        // See https://bugzilla.mozilla.org/show_bug.cgi?id=1305085 .
        { 1, {10, 20,  0, 20, 40,  0,  0,  0,  1}},
    };

    for (const auto& testCase : testCases) {
        font.setSize(testCase.textSize);
        const SkScalar(&m)[9] = testCase.matrix;
        SkMatrix mat;
        mat.setAll(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);
        canvas->setMatrix(mat);
        canvas->drawString("Hamburgefons", 10, 10, font, SkPaint());
    }
}

// This produces no glyphs, and is to check that buffers from previous draws don't get
// reused.
DEF_TEST(DrawText_noglyphs, r) {
    auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(100, 100));
    auto canvas = surface->getCanvas();
    SkFont font = ToolUtils::DefaultFont();
    auto text = "Hamburgfons";
    {
        // scoped to ensure blob is deleted.
        auto blob = SkTextBlob::MakeFromText(text, strlen(text), font);
        canvas->drawTextBlob(blob, 10, 10, SkPaint());
    }
    canvas->drawString(
            "\x0d\xf3\xf2\xf2\xe9\x0d\x0d\x0d\x05\x0d\x0d\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xe3",
            10, 20, font, SkPaint());
}
