/*
 * Copyright 2010 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/core/SkTypes.h"

#ifdef SK_SUPPORT_PDF

#include "include/core/SkStream.h"
#include "include/private/SkTDArray.h"
#include "include/private/SkTemplates.h"
#include "include/private/SkTo.h"
#include "src/pdf/SkPDFGlyphUse.h"
#include "src/pdf/SkPDFMakeToUnicodeCmap.h"
#include "tests/Test.h"

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

static constexpr SkGlyphID kMaximumGlyphIndex = UINT16_MAX;

static bool stream_equals(const SkDynamicMemoryWStream& stream, size_t offset,
                          const char* buffer, size_t len) {
    if (len != strlen(buffer)) {
        return false;
    }

    const size_t streamSize = stream.bytesWritten();

    if (offset + len > streamSize) {
        return false;
    }

    SkAutoTMalloc<char> data(streamSize);
    stream.copyTo(data.get());
    return memcmp(data.get() + offset, buffer, len) == 0;
}

DEF_TEST(SkPDF_ToUnicode, reporter) {
    SkTDArray<SkUnichar> glyphToUnicode;
    SkTDArray<uint16_t> glyphsInSubset;
    SkPDFGlyphUse subset(1, kMaximumGlyphIndex);

    glyphToUnicode.push_back(0);  // 0
    glyphToUnicode.push_back(0);  // 1
    glyphToUnicode.push_back(0);  // 2
    glyphsInSubset.push_back(3);
    glyphToUnicode.push_back(0x20);  // 3
    glyphsInSubset.push_back(4);
    glyphToUnicode.push_back(0x25);  // 4
    glyphsInSubset.push_back(5);
    glyphToUnicode.push_back(0x27);  // 5
    glyphsInSubset.push_back(6);
    glyphToUnicode.push_back(0x28);  // 6
    glyphsInSubset.push_back(7);
    glyphToUnicode.push_back(0x29);  // 7
    glyphsInSubset.push_back(8);
    glyphToUnicode.push_back(0x2F);  // 8
    glyphsInSubset.push_back(9);
    glyphToUnicode.push_back(0x33);  // 9
    glyphToUnicode.push_back(0);  // 10
    glyphsInSubset.push_back(11);
    glyphToUnicode.push_back(0x35);  // 11
    glyphsInSubset.push_back(12);
    glyphToUnicode.push_back(0x36);  // 12
    glyphsInSubset.push_back(13);
    glyphToUnicode.push_back(0x37);  // 13
    for (uint16_t i = 14; i < 0xFE; ++i) {
        glyphToUnicode.push_back(0);  // Zero from index 0x9 to 0xFD
    }
    glyphsInSubset.push_back(0xFE);
    glyphToUnicode.push_back(0x1010);
    glyphsInSubset.push_back(0xFF);
    glyphToUnicode.push_back(0x1011);
    glyphsInSubset.push_back(0x100);
    glyphToUnicode.push_back(0x1012);
    glyphsInSubset.push_back(0x101);
    glyphToUnicode.push_back(0x1013);

    SkGlyphID lastGlyphID = SkToU16(glyphToUnicode.size() - 1);

    SkDynamicMemoryWStream buffer;
    for (uint16_t v : glyphsInSubset) {
        subset.set(v);
    }
    SkPDFAppendCmapSections(&glyphToUnicode[0], &subset, &buffer, true, 0,
                            std::min<SkGlyphID>(0xFFFF,  lastGlyphID));

    char expectedResult[] =
"4 beginbfchar\n\
<0003> <0020>\n\
<0004> <0025>\n\
<0008> <002F>\n\
<0009> <0033>\n\
endbfchar\n\
4 beginbfrange\n\
<0005> <0007> <0027>\n\
<000B> <000D> <0035>\n\
<00FE> <00FF> <1010>\n\
<0100> <0101> <1012>\n\
endbfrange\n";

    REPORTER_ASSERT(reporter, stream_equals(buffer, 0, expectedResult,
                                            buffer.bytesWritten()));

    // Remove characters and ranges.
    buffer.reset();

    SkPDFAppendCmapSections(&glyphToUnicode[0], &subset, &buffer, true, 8,
                            std::min<SkGlyphID>(0x00FF, lastGlyphID));

    char expectedResultChop1[] =
"2 beginbfchar\n\
<0008> <002F>\n\
<0009> <0033>\n\
endbfchar\n\
2 beginbfrange\n\
<000B> <000D> <0035>\n\
<00FE> <00FF> <1010>\n\
endbfrange\n";

    REPORTER_ASSERT(reporter, stream_equals(buffer, 0, expectedResultChop1,
                                            buffer.bytesWritten()));

    // Remove characters from range to downdrade it to one char.
    buffer.reset();

    SkPDFAppendCmapSections(&glyphToUnicode[0], &subset, &buffer, true, 0x00D,
                            std::min<SkGlyphID>(0x00FE, lastGlyphID));

    char expectedResultChop2[] =
"2 beginbfchar\n\
<000D> <0037>\n\
<00FE> <1010>\n\
endbfchar\n";

    REPORTER_ASSERT(reporter, stream_equals(buffer, 0, expectedResultChop2,
                                            buffer.bytesWritten()));

    buffer.reset();

    SkPDFAppendCmapSections(&glyphToUnicode[0], nullptr, &buffer, false, 0xFC,
                            std::min<SkGlyphID>(0x110, lastGlyphID));

    char expectedResultSingleBytes[] =
"2 beginbfchar\n\
<01> <0000>\n\
<02> <0000>\n\
endbfchar\n\
1 beginbfrange\n\
<03> <06> <1010>\n\
endbfrange\n";

    REPORTER_ASSERT(reporter, stream_equals(buffer, 0,
                                            expectedResultSingleBytes,
                                            buffer.bytesWritten()));

    glyphToUnicode.reset();
    glyphsInSubset.reset();
    SkPDFGlyphUse subset2(1, kMaximumGlyphIndex);

    // Test mapping:
    //           I  n  s  t  a  l
    // Glyph id 2c 51 56 57 44 4f
    // Unicode  49 6e 73 74 61 6c
    for (SkUnichar i = 0; i < 100; ++i) {
      glyphToUnicode.push_back(i + 29);
    }
    lastGlyphID = SkToU16(glyphToUnicode.size() - 1);

    glyphsInSubset.push_back(0x2C);
    glyphsInSubset.push_back(0x44);
    glyphsInSubset.push_back(0x4F);
    glyphsInSubset.push_back(0x51);
    glyphsInSubset.push_back(0x56);
    glyphsInSubset.push_back(0x57);

    SkDynamicMemoryWStream buffer2;
    for (uint16_t v : glyphsInSubset) {
        subset2.set(v);
    }
    SkPDFAppendCmapSections(&glyphToUnicode[0], &subset2, &buffer2, true, 0,
                            std::min<SkGlyphID>(0xFFFF, lastGlyphID));

    char expectedResult2[] =
"4 beginbfchar\n\
<002C> <0049>\n\
<0044> <0061>\n\
<004F> <006C>\n\
<0051> <006E>\n\
endbfchar\n\
1 beginbfrange\n\
<0056> <0057> <0073>\n\
endbfrange\n";

    REPORTER_ASSERT(reporter, stream_equals(buffer2, 0, expectedResult2,
                                            buffer2.bytesWritten()));
}

#endif
