/*
 * 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 "SkFont.h"
#include "SkPaint.h"
#include "SkTypeface.h"
#include "Test.h"

static void test_cachedfont(skiatest::Reporter* reporter,
                            const SkPaint& paint, const SkFont& font) {
    // Currently SkFont resolves null into the default, so only test if paint's is not null
    if (paint.getTypeface()) {
        REPORTER_ASSERT(reporter, font.getTypeface() == paint.getTypeface());
    }
    REPORTER_ASSERT(reporter, font.getSize() == paint.getTextSize());
    REPORTER_ASSERT(reporter, font.getScaleX() == paint.getTextScaleX());
    REPORTER_ASSERT(reporter, font.getSkewX() == paint.getTextSkewX());

    uint32_t mask = SkPaint::kLinearText_Flag |
                    SkPaint::kSubpixelText_Flag |
                    SkPaint::kFakeBoldText_Flag |
                    SkPaint::kEmbeddedBitmapText_Flag |
                    SkPaint::kAutoHinting_Flag;

    SkPaint p;
    font.LEGACY_applyToPaint(&p);
    uint32_t oldFlags = paint.getFlags() & mask;
    uint32_t newFlags = p.getFlags() & mask;
    REPORTER_ASSERT(reporter, oldFlags == newFlags);
    REPORTER_ASSERT(reporter, paint.getHinting() == p.getHinting());
}

#ifdef SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
static void test_fontmetrics(skiatest::Reporter* reporter,
                             const SkPaint& paint, const SkFont& font) {
    SkFontMetrics fm0, fm1;
    SkScalar h0 = paint.getFontMetrics(&fm0);
    SkScalar h1 = font.getMetrics(&fm1);

    REPORTER_ASSERT(reporter, h0 == h1);
#define CMP(field) REPORTER_ASSERT(reporter, fm0.field == fm1.field)
    CMP(fFlags);
    CMP(fTop);
    CMP(fAscent);
    CMP(fDescent);
    CMP(fBottom);
    CMP(fLeading);
#undef CMP
}
#endif

static void test_cachedfont(skiatest::Reporter* reporter) {
    static const char* const faces[] = {
        nullptr,
        "Arial", "Times", "Times New Roman", "Helvetica", "Courier",
        "Courier New", "Verdana", "monospace",
    };

    static const struct {
        SkScalar    fScaleX;
        SkScalar    fSkewX;
    } gScaleRec[] = {
        { SK_Scalar1, 0 },
        { SK_Scalar1/2, -SK_Scalar1/4 },
    };

    SkPaint paint;
#ifdef SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
    char txt[] = "long .text .with .lots .of.dots.";
#endif

    unsigned mask = SkPaint::kAntiAlias_Flag            |
                    SkPaint::kFakeBoldText_Flag         |
                    SkPaint::kLinearText_Flag           |
                    SkPaint::kSubpixelText_Flag         |
                    SkPaint::kLCDRenderText_Flag        |
                    SkPaint::kEmbeddedBitmapText_Flag   |
                    SkPaint::kAutoHinting_Flag;

    for (size_t i = 0; i < SK_ARRAY_COUNT(faces); i++) {
        paint.setTypeface(SkTypeface::MakeFromName(faces[i], SkFontStyle()));
        for (unsigned flags = 0; flags <= 0xFFF; ++flags) {
            if (flags & ~mask) {
                continue;
            }
            paint.setFlags(flags);
            for (int hint = 0; hint <= 3; ++hint) {
                paint.setHinting((SkFontHinting)hint);
                for (size_t k = 0; k < SK_ARRAY_COUNT(gScaleRec); ++k) {
                    paint.setTextScaleX(gScaleRec[k].fScaleX);
                    paint.setTextSkewX(gScaleRec[k].fSkewX);

                    const SkFont font(SkFont::LEGACY_ExtractFromPaint(paint));

                    test_cachedfont(reporter, paint, font);
#ifdef SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
                    test_fontmetrics(reporter, paint, font);

                    SkRect pbounds, fbounds;

                    // Requesting the bounds forces a generateMetrics call.
                    SkScalar pwidth = paint.measureText(txt, strlen(txt), &pbounds);
                    SkScalar fwidth = font.measureText(txt, strlen(txt), kUTF8_SkTextEncoding,
                                                      &fbounds);
                    REPORTER_ASSERT(reporter, pwidth == fwidth);
                    REPORTER_ASSERT(reporter, pbounds == fbounds);
#endif
                }
            }
        }
    }
}

static void test_aa_hinting(skiatest::Reporter* reporter) {
    SkPaint paint;

    for (bool aa : {false, true}) {
        paint.setAntiAlias(aa);
        for (int hint = 0; hint <= 3; ++hint) {
            paint.setHinting((SkFontHinting)hint);
            SkFont font = SkFont::LEGACY_ExtractFromPaint(paint);

            SkPaint p2;
            font.LEGACY_applyToPaint(&p2);
            REPORTER_ASSERT(reporter, paint.isAntiAlias() == p2.isAntiAlias());
            REPORTER_ASSERT(reporter, paint.getHinting() == p2.getHinting());
        }
    }
}

DEF_TEST(FontObj, reporter) {
    test_cachedfont(reporter);
    test_aa_hinting(reporter);
}

// need tests for SkStrSearch
