/*
 * 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 "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkData.h"
#include "include/core/SkFont.h"
#include "include/core/SkFontStyle.h"
#include "include/core/SkFontTypes.h"
#include "include/core/SkImage.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSerialProcs.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTextBlob.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "include/private/base/SkTArray.h"
#include "include/private/base/SkTemplates.h"
#include "include/private/base/SkTo.h"
#include "src/core/SkTextBlobPriv.h"
#include "tests/Test.h"
#include "tools/ToolUtils.h"

#include <algorithm>
#include <cstdint>
#include <cstring>
#include <string>

using namespace skia_private;

class TextBlobTester {
public:
    // This unit test feeds an SkTextBlobBuilder various runs then checks to see if
    // the result contains the provided data and merges runs when appropriate.
    static void TestBuilder(skiatest::Reporter* reporter) {
        SkTextBlobBuilder builder;

        // empty run set
        RunBuilderTest(reporter, builder, nullptr, 0, nullptr, 0);

        RunDef set1[] = {
            { 128, SkTextBlobRunIterator::kDefault_Positioning, 100, 100 },
        };
        RunBuilderTest(reporter, builder, set1, std::size(set1), set1, std::size(set1));

        RunDef set2[] = {
            { 128, SkTextBlobRunIterator::kHorizontal_Positioning, 100, 100 },
        };
        RunBuilderTest(reporter, builder, set2, std::size(set2), set2, std::size(set2));

        RunDef set3[] = {
            { 128, SkTextBlobRunIterator::kFull_Positioning, 100, 100 },
        };
        RunBuilderTest(reporter, builder, set3, std::size(set3), set3, std::size(set3));

        RunDef set4[] = {
            { 128, SkTextBlobRunIterator::kDefault_Positioning, 100, 150 },
            { 128, SkTextBlobRunIterator::kDefault_Positioning, 100, 150 },
            { 128, SkTextBlobRunIterator::kDefault_Positioning, 100, 150 },
        };
        RunBuilderTest(reporter, builder, set4, std::size(set4), set4, std::size(set4));

        RunDef set5[] = {
            { 128, SkTextBlobRunIterator::kHorizontal_Positioning, 100, 150 },
            { 128, SkTextBlobRunIterator::kHorizontal_Positioning, 200, 150 },
            { 128, SkTextBlobRunIterator::kHorizontal_Positioning, 300, 250 },
        };
        RunDef mergedSet5[] = {
            { 256, SkTextBlobRunIterator::kHorizontal_Positioning, 0, 150 },
            { 128, SkTextBlobRunIterator::kHorizontal_Positioning, 0, 250 },
        };
        RunBuilderTest(reporter, builder, set5, std::size(set5), mergedSet5,
                       std::size(mergedSet5));

        RunDef set6[] = {
            { 128, SkTextBlobRunIterator::kFull_Positioning, 100, 100 },
            { 128, SkTextBlobRunIterator::kFull_Positioning, 200, 200 },
            { 128, SkTextBlobRunIterator::kFull_Positioning, 300, 300 },
        };
        RunDef mergedSet6[] = {
            { 384, SkTextBlobRunIterator::kFull_Positioning, 0, 0 },
        };
        RunBuilderTest(reporter, builder, set6, std::size(set6), mergedSet6,
                       std::size(mergedSet6));

        RunDef set7[] = {
            { 128, SkTextBlobRunIterator::kDefault_Positioning, 100, 150 },
            { 128, SkTextBlobRunIterator::kDefault_Positioning, 100, 150 },
            { 128, SkTextBlobRunIterator::kHorizontal_Positioning, 100, 150 },
            { 128, SkTextBlobRunIterator::kHorizontal_Positioning, 200, 150 },
            { 128, SkTextBlobRunIterator::kFull_Positioning, 400, 350 },
            { 128, SkTextBlobRunIterator::kFull_Positioning, 400, 350 },
            { 128, SkTextBlobRunIterator::kDefault_Positioning, 100, 450 },
            { 128, SkTextBlobRunIterator::kDefault_Positioning, 100, 450 },
            { 128, SkTextBlobRunIterator::kHorizontal_Positioning, 100, 550 },
            { 128, SkTextBlobRunIterator::kHorizontal_Positioning, 200, 650 },
            { 128, SkTextBlobRunIterator::kFull_Positioning, 400, 750 },
            { 128, SkTextBlobRunIterator::kFull_Positioning, 400, 850 },
        };
        RunDef mergedSet7[] = {
            { 128, SkTextBlobRunIterator::kDefault_Positioning, 100, 150 },
            { 128, SkTextBlobRunIterator::kDefault_Positioning, 100, 150 },
            { 256, SkTextBlobRunIterator::kHorizontal_Positioning, 0, 150 },
            { 256, SkTextBlobRunIterator::kFull_Positioning, 0, 0 },
            { 128, SkTextBlobRunIterator::kDefault_Positioning, 100, 450 },
            { 128, SkTextBlobRunIterator::kDefault_Positioning, 100, 450 },
            { 128, SkTextBlobRunIterator::kHorizontal_Positioning, 0, 550 },
            { 128, SkTextBlobRunIterator::kHorizontal_Positioning, 0, 650 },
            { 256, SkTextBlobRunIterator::kFull_Positioning, 0, 0 },
        };
        RunBuilderTest(reporter, builder, set7, std::size(set7), mergedSet7,
                       std::size(mergedSet7));
    }

    // This unit test verifies blob bounds computation.
    static void TestBounds(skiatest::Reporter* reporter) {
        SkTextBlobBuilder builder;
        SkFont font;

        // Explicit bounds.
        {
            sk_sp<SkTextBlob> blob(builder.make());
            REPORTER_ASSERT(reporter, !blob);
        }

        {
            SkRect r1 = SkRect::MakeXYWH(10, 10, 20, 20);
            builder.allocRun(font, 16, 0, 0, &r1);
            sk_sp<SkTextBlob> blob(builder.make());
            REPORTER_ASSERT(reporter, blob->bounds() == r1);
        }

        {
            SkRect r1 = SkRect::MakeXYWH(10, 10, 20, 20);
            builder.allocRunPosH(font, 16, 0, &r1);
            sk_sp<SkTextBlob> blob(builder.make());
            REPORTER_ASSERT(reporter, blob->bounds() == r1);
        }

        {
            SkRect r1 = SkRect::MakeXYWH(10, 10, 20, 20);
            builder.allocRunPos(font, 16, &r1);
            sk_sp<SkTextBlob> blob(builder.make());
            REPORTER_ASSERT(reporter, blob->bounds() == r1);
        }

        {
            SkRect r1 = SkRect::MakeXYWH(10, 10, 20, 20);
            SkRect r2 = SkRect::MakeXYWH(15, 20, 50, 50);
            SkRect r3 = SkRect::MakeXYWH(0, 5, 10, 5);

            builder.allocRun(font, 16, 0, 0, &r1);
            builder.allocRunPosH(font, 16, 0, &r2);
            builder.allocRunPos(font, 16, &r3);

            sk_sp<SkTextBlob> blob(builder.make());
            REPORTER_ASSERT(reporter, blob->bounds() == SkRect::MakeXYWH(0, 5, 65, 65));
        }

        {
            sk_sp<SkTextBlob> blob(builder.make());
            REPORTER_ASSERT(reporter, !blob);
        }

        // Implicit bounds

        {
            // Exercise the empty bounds path, and ensure that RunRecord-aligned pos buffers
            // don't trigger asserts (http://crbug.com/542643).
            font.setSize(0);

            const char* txt = "BOOO";
            const size_t txtLen = strlen(txt);
            const int glyphCount = font.countText(txt, txtLen, SkTextEncoding::kUTF8);
            const SkTextBlobBuilder::RunBuffer& buffer = builder.allocRunPos(font, glyphCount);

            font.textToGlyphs(txt, txtLen, SkTextEncoding::kUTF8, buffer.glyphs, glyphCount);

            memset(buffer.pos, 0, sizeof(SkScalar) * glyphCount * 2);
            sk_sp<SkTextBlob> blob(builder.make());
            REPORTER_ASSERT(reporter, blob->bounds().isEmpty());
        }
    }

    // Verify that text-related properties are captured in run paints.
    static void TestPaintProps(skiatest::Reporter* reporter) {
        SkFont font;
        // Kitchen sink font.
        font.setSize(42);
        font.setScaleX(4.2f);
        font.setTypeface(ToolUtils::create_portable_typeface(nullptr, SkFontStyle::Bold()));
        font.setSkewX(0.42f);
        font.setHinting(SkFontHinting::kFull);
        font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
        font.setEmbolden(true);
        font.setLinearMetrics(true);
        font.setSubpixel(true);
        font.setEmbeddedBitmaps(true);
        font.setForceAutoHinting(true);

        // Ensure we didn't pick default values by mistake.
        SkFont defaultFont;
        REPORTER_ASSERT(reporter, defaultFont.getSize() != font.getSize());
        REPORTER_ASSERT(reporter, defaultFont.getScaleX() != font.getScaleX());
        REPORTER_ASSERT(reporter, defaultFont.getTypefaceOrDefault() != font.getTypefaceOrDefault());
        REPORTER_ASSERT(reporter, defaultFont.getSkewX() != font.getSkewX());
        REPORTER_ASSERT(reporter, defaultFont.getHinting() != font.getHinting());
        REPORTER_ASSERT(reporter, defaultFont.getEdging() != font.getEdging());
        REPORTER_ASSERT(reporter, defaultFont.isEmbolden() != font.isEmbolden());
        REPORTER_ASSERT(reporter, defaultFont.isLinearMetrics() != font.isLinearMetrics());
        REPORTER_ASSERT(reporter, defaultFont.isSubpixel() != font.isSubpixel());
        REPORTER_ASSERT(reporter,
                        defaultFont.isEmbeddedBitmaps() != font.isEmbeddedBitmaps());
        REPORTER_ASSERT(reporter, defaultFont.isForceAutoHinting() != font.isForceAutoHinting());

        SkTextBlobBuilder builder;
        AddRun(font, 1, SkTextBlobRunIterator::kDefault_Positioning, SkPoint::Make(0, 0), builder);
        AddRun(font, 1, SkTextBlobRunIterator::kHorizontal_Positioning, SkPoint::Make(0, 0),
               builder);
        AddRun(font, 1, SkTextBlobRunIterator::kFull_Positioning, SkPoint::Make(0, 0), builder);
        sk_sp<SkTextBlob> blob(builder.make());

        SkTextBlobRunIterator it(blob.get());
        while (!it.done()) {
            REPORTER_ASSERT(reporter, it.font() == font);
            it.next();
        }

    }

private:
    struct RunDef {
        unsigned                                count;
        SkTextBlobRunIterator::GlyphPositioning pos;
        SkScalar                                x, y;
    };

    static void RunBuilderTest(skiatest::Reporter* reporter, SkTextBlobBuilder& builder,
                               const RunDef in[], unsigned inCount,
                               const RunDef out[], unsigned outCount) {
        SkFont font;

        for (unsigned i = 0; i < inCount; ++i) {
            AddRun(font, in[i].count, in[i].pos, SkPoint::Make(in[i].x, in[i].y), builder);
        }

        sk_sp<SkTextBlob> blob(builder.make());
        REPORTER_ASSERT(reporter, (inCount > 0) == SkToBool(blob));
        if (!blob) {
            return;
        }

        SkTextBlobRunIterator it(blob.get());
        for (unsigned i = 0; i < outCount; ++i) {
            REPORTER_ASSERT(reporter, !it.done());
            REPORTER_ASSERT(reporter, out[i].pos == it.positioning());
            REPORTER_ASSERT(reporter, out[i].count == it.glyphCount());
            if (SkTextBlobRunIterator::kDefault_Positioning == out[i].pos) {
                REPORTER_ASSERT(reporter, out[i].x == it.offset().x());
                REPORTER_ASSERT(reporter, out[i].y == it.offset().y());
            } else if (SkTextBlobRunIterator::kHorizontal_Positioning == out[i].pos) {
                REPORTER_ASSERT(reporter, out[i].y == it.offset().y());
            }

            for (unsigned k = 0; k < it.glyphCount(); ++k) {
                REPORTER_ASSERT(reporter, k % 128 == it.glyphs()[k]);
                if (SkTextBlobRunIterator::kHorizontal_Positioning == it.positioning()) {
                    REPORTER_ASSERT(reporter, SkIntToScalar(k % 128) == it.pos()[k]);
                } else if (SkTextBlobRunIterator::kFull_Positioning == it.positioning()) {
                    REPORTER_ASSERT(reporter, SkIntToScalar(k % 128) == it.pos()[k * 2]);
                    REPORTER_ASSERT(reporter, -SkIntToScalar(k % 128) == it.pos()[k * 2 + 1]);
                }
            }

            it.next();
        }

        REPORTER_ASSERT(reporter, it.done());
    }

    static void AddRun(const SkFont& font, int count, SkTextBlobRunIterator::GlyphPositioning pos,
                       const SkPoint& offset, SkTextBlobBuilder& builder,
                       const SkRect* bounds = nullptr) {
        switch (pos) {
        case SkTextBlobRunIterator::kDefault_Positioning: {
            const SkTextBlobBuilder::RunBuffer& rb = builder.allocRun(font, count, offset.x(),
                                                                      offset.y(), bounds);
            for (int i = 0; i < count; ++i) {
                rb.glyphs[i] = i;
            }
        } break;
        case SkTextBlobRunIterator::kHorizontal_Positioning: {
            const SkTextBlobBuilder::RunBuffer& rb = builder.allocRunPosH(font, count, offset.y(),
                                                                          bounds);
            for (int i = 0; i < count; ++i) {
                rb.glyphs[i] = i;
                rb.pos[i] = SkIntToScalar(i);
            }
        } break;
        case SkTextBlobRunIterator::kFull_Positioning: {
            const SkTextBlobBuilder::RunBuffer& rb = builder.allocRunPos(font, count, bounds);
            for (int i = 0; i < count; ++i) {
                rb.glyphs[i] = i;
                rb.pos[i * 2] = SkIntToScalar(i);
                rb.pos[i * 2 + 1] = -SkIntToScalar(i);
            }
        } break;
        default:
            SK_ABORT("unhandled positioning value");
        }
    }
};

DEF_TEST(TextBlob_builder, reporter) {
    TextBlobTester::TestBuilder(reporter);
    TextBlobTester::TestBounds(reporter);
}

DEF_TEST(TextBlob_paint, reporter) {
    TextBlobTester::TestPaintProps(reporter);
}

DEF_TEST(TextBlob_extended, reporter) {
    SkTextBlobBuilder textBlobBuilder;
    SkFont font;
    const char text1[] = "Foo";
    const char text2[] = "Bar";

    int glyphCount = font.countText(text1, strlen(text1), SkTextEncoding::kUTF8);
    AutoTMalloc<uint16_t> glyphs(glyphCount);
    (void)font.textToGlyphs(text1, strlen(text1), SkTextEncoding::kUTF8, glyphs.get(), glyphCount);

    auto run = textBlobBuilder.allocRunText(font, glyphCount, 0, 0, SkToInt(strlen(text2)));
    memcpy(run.glyphs, glyphs.get(), sizeof(uint16_t) * glyphCount);
    memcpy(run.utf8text, text2, strlen(text2));
    for (int i = 0; i < glyphCount; ++i) {
        run.clusters[i] = std::min(SkToU32(i), SkToU32(strlen(text2)));
    }
    sk_sp<SkTextBlob> blob(textBlobBuilder.make());
    REPORTER_ASSERT(reporter, blob);

    for (SkTextBlobRunIterator it(blob.get()); !it.done(); it.next()) {
        REPORTER_ASSERT(reporter, it.glyphCount() == (uint32_t)glyphCount);
        for (uint32_t i = 0; i < it.glyphCount(); ++i) {
            REPORTER_ASSERT(reporter, it.glyphs()[i] == glyphs[i]);
        }
        REPORTER_ASSERT(reporter, SkTextBlobRunIterator::kDefault_Positioning == it.positioning());
        REPORTER_ASSERT(reporter, (SkPoint{0.0f, 0.0f}) == it.offset());
        REPORTER_ASSERT(reporter, it.textSize() > 0);
        REPORTER_ASSERT(reporter, it.clusters());
        for (uint32_t i = 0; i < it.glyphCount(); ++i) {
            REPORTER_ASSERT(reporter, i == it.clusters()[i]);
        }
        REPORTER_ASSERT(reporter, 0 == strncmp(text2, it.text(), it.textSize()));
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////
static void add_run(SkTextBlobBuilder* builder, const char text[], SkScalar x, SkScalar y,
                    sk_sp<SkTypeface> tf) {
    SkFont font;
    font.setEdging(SkFont::Edging::kAntiAlias);
    font.setSubpixel(true);
    font.setSize(16);
    font.setTypeface(tf);

    int glyphCount = font.countText(text, strlen(text), SkTextEncoding::kUTF8);

    SkTextBlobBuilder::RunBuffer buffer = builder->allocRun(font, glyphCount, x, y);

    (void)font.textToGlyphs(text, strlen(text), SkTextEncoding::kUTF8, buffer.glyphs, glyphCount);
}

static sk_sp<SkImage> render(const SkTextBlob* blob) {
    auto surf = SkSurface::MakeRasterN32Premul(SkScalarRoundToInt(blob->bounds().width()),
                                               SkScalarRoundToInt(blob->bounds().height()));
    if (!surf) {
        return nullptr; // bounds are empty?
    }
    surf->getCanvas()->clear(SK_ColorWHITE);
    surf->getCanvas()->drawTextBlob(blob, -blob->bounds().left(), -blob->bounds().top(), SkPaint());
    return surf->makeImageSnapshot();
}

static sk_sp<SkData> SerializeTypeface(SkTypeface* tf, void* ctx) {
    auto array = (SkTArray<sk_sp<SkTypeface>>*)ctx;
    const size_t idx = array->size();
    array->emplace_back(sk_ref_sp(tf));
    // In this test, we are deserializing on the same machine, so we don't worry about endianness.
    return SkData::MakeWithCopy(&idx, sizeof(idx));
}

static sk_sp<SkTypeface> DeserializeTypeface(const void* data, size_t length, void* ctx) {
    auto array = (SkTArray<sk_sp<SkTypeface>>*)ctx;
    if (length != sizeof(size_t)) {
        SkASSERT(false);
        return nullptr;
    }
    size_t idx = *reinterpret_cast<const size_t*>(data);
    if (idx >= SkToSizeT(array->size())) {
        SkASSERT(false);
        return nullptr;
    }
    return (*array)[idx];
}

/*
 *  Build a blob with more than one typeface.
 *  Draw it into an offscreen,
 *  then serialize and deserialize,
 *  Then draw the new instance and assert it draws the same as the original.
 */
DEF_TEST(TextBlob_serialize, reporter) {
    sk_sp<SkTextBlob> blob0 = []() {
        sk_sp<SkTypeface> tf = SkTypeface::MakeFromName(nullptr, SkFontStyle::BoldItalic());

        SkTextBlobBuilder builder;
        add_run(&builder, "Hello", 10, 20, nullptr);    // don't flatten a typeface
        add_run(&builder, "World", 10, 40, tf);         // do flatten this typeface
        return builder.make();
    }();

    SkTArray<sk_sp<SkTypeface>> array;
    SkSerialProcs serializeProcs;
    serializeProcs.fTypefaceProc = &SerializeTypeface;
    serializeProcs.fTypefaceCtx = (void*) &array;
    sk_sp<SkData> data = blob0->serialize(serializeProcs);
    REPORTER_ASSERT(reporter, array.size() == 1);
    SkDeserialProcs deserializeProcs;
    deserializeProcs.fTypefaceProc = &DeserializeTypeface;
    deserializeProcs.fTypefaceCtx = (void*) &array;
    sk_sp<SkTextBlob> blob1 = SkTextBlob::Deserialize(data->data(), data->size(), deserializeProcs);

    sk_sp<SkImage> img0 = render(blob0.get());
    sk_sp<SkImage> img1 = render(blob1.get());
    if (img0 && img1) {
        REPORTER_ASSERT(reporter, ToolUtils::equal_pixels(img0.get(), img1.get()));
    }
}

DEF_TEST(TextBlob_MakeAsDrawText, reporter) {
    const char text[] = "Hello";
    auto blob = SkTextBlob::MakeFromString(text, SkFont(), SkTextEncoding::kUTF8);

    int runs = 0;
    for(SkTextBlobRunIterator it(blob.get()); !it.done(); it.next()) {
        REPORTER_ASSERT(reporter, it.glyphCount() == strlen(text));
        REPORTER_ASSERT(reporter, it.positioning() == SkTextBlobRunIterator::kFull_Positioning);
        runs += 1;
    }
    REPORTER_ASSERT(reporter, runs == 1);

}

DEF_TEST(TextBlob_iter, reporter) {
    sk_sp<SkTypeface> tf = SkTypeface::MakeFromName(nullptr, SkFontStyle::BoldItalic());

    SkTextBlobBuilder builder;
    add_run(&builder, "Hello", 10, 20, nullptr);
    add_run(&builder, "World", 10, 40, tf);
    auto blob = builder.make();

    SkTextBlob::Iter::Run expected[] = {
        { nullptr, 5, nullptr },
        { tf.get(), 5, nullptr },
    };

    SkTextBlob::Iter iter(*blob);
    SkTextBlob::Iter::Run run;
    for (auto exp : expected) {
        REPORTER_ASSERT(reporter, iter.next(&run));
        REPORTER_ASSERT(reporter, run.fTypeface == exp.fTypeface);
        REPORTER_ASSERT(reporter, run.fGlyphCount == exp.fGlyphCount);
        for (int i = 0; i < run.fGlyphCount; ++i) {
            REPORTER_ASSERT(reporter, run.fGlyphIndices[i] != 0);
        }
    }
    REPORTER_ASSERT(reporter, !iter.next(&run));    // we're done

    SkTextBlob::Iter iter2(*blob);
    REPORTER_ASSERT(reporter, iter2.next(&run));
    // Hello should have the same glyph repeated for the 'l'
    REPORTER_ASSERT(reporter, run.fGlyphIndices[2] == run.fGlyphIndices[3]);
}

DEF_TEST(TextBlob_getIntercepts, reporter) {
    SkFont font;
    font.setSize(16);

    SkPoint lowPos[1] = { SkPoint::Make(0, 5) };
    SkPoint highPos[1] = { SkPoint::Make(0, -8) };
    SkPoint zeroPos[1] = { SkPoint::Make(0, 0) };

    // 'x' sitting on baseline
    auto blobZeroX = SkTextBlob::MakeFromPosText("x", 1, zeroPos, font);
    // 'x' lowered to intersect baseline
    auto blobLowX = SkTextBlob::MakeFromPosText("x", 1, lowPos, font);
    // 'y' sitting on baseline
    auto blobZeroY = SkTextBlob::MakeFromPosText("y", 1, zeroPos, font);
    // 'y' raised to not intersect baseline
    auto blobHighY = SkTextBlob::MakeFromPosText("y", 1, highPos, font);

    // bounds right below baseline
    SkScalar bounds[2] = { 1, 2 };

    // 'x' on baseline should not intersect
    REPORTER_ASSERT(reporter, blobZeroX->getIntercepts(bounds, nullptr) == 0);
    // lowered 'x' should intersect
    REPORTER_ASSERT(reporter, blobLowX->getIntercepts(bounds, nullptr) == 2);
    // 'y' on baseline should intersect
    REPORTER_ASSERT(reporter, blobZeroY->getIntercepts(bounds, nullptr) == 2);
    // raised 'y' should not intersect
    REPORTER_ASSERT(reporter, blobHighY->getIntercepts(bounds, nullptr) == 0);
}
