// Copyright 2018 Google LLC
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

#include "src/pdf/SkPDFSubsetFont.h"

#if defined(SK_PDF_USE_HARFBUZZ_SUBSET)

#include "include/core/SkStream.h"
#include "include/core/SkTypeface.h"
#include "include/private/base/SkAssert.h"
#include "include/private/base/SkMalloc.h"
#include "include/private/base/SkTemplates.h"
#include "include/private/base/SkTo.h"
#include "src/pdf/SkPDFGlyphUse.h"

#include "hb.h"  // NO_G3_REWRITE
#include "hb-subset.h"  // NO_G3_REWRITE

#include <cstddef>
#include <memory>
#include <utility>

namespace {

using HBBlob = std::unique_ptr<hb_blob_t, SkFunctionObject<hb_blob_destroy>>;
using HBFace = std::unique_ptr<hb_face_t, SkFunctionObject<hb_face_destroy>>;
using HBSubsetInput = std::unique_ptr<hb_subset_input_t, SkFunctionObject<hb_subset_input_destroy>>;
using HBSet = std::unique_ptr<hb_set_t, SkFunctionObject<hb_set_destroy>>;

#if HB_VERSION_ATLEAST(10, 0, 0)
unsigned int skhb_get_table_tags_func(const hb_face_t *face,
                                      unsigned int start_offset,
                                      unsigned int *table_count, /* IN/OUT */
                                      hb_tag_t *table_tags /* OUT */,
                                      void *user_data)
{
    SkTypeface& typeface = *reinterpret_cast<SkTypeface*>(user_data);
    int numTables = typeface.countTables();
    if (numTables <= 0 || static_cast<unsigned int>(numTables) <= start_offset) {
        *table_count = 0;
        return 0;
    }
    if (!table_count || *table_count == 0) {
        return numTables;
    }

    std::unique_ptr<SkFontTableTag[]> allTableTags = std::make_unique<SkFontTableTag[]>(numTables);
    int numTableTags = typeface.readTableTags({allTableTags.get(), numTables});
    if (numTableTags != numTables) {
        *table_count = 0;
        return 0;
    }

    static_assert(sizeof(*table_tags) == sizeof(allTableTags[0]), "");
    *table_count = std::min(*table_count, static_cast<unsigned int>(numTableTags) - start_offset);
    memcpy(table_tags, allTableTags.get() + start_offset, *table_count * sizeof(*table_tags));
    return numTableTags;
}
#endif

hb_blob_t* skhb_get_table(hb_face_t* face, hb_tag_t tag, void* user_data) {
    SkTypeface& typeface = *reinterpret_cast<SkTypeface*>(user_data);

    auto data = typeface.copyTableData(tag);
    if (!data) {
        return nullptr;
    }
    SkData* rawData = data.release();
    return hb_blob_create(reinterpret_cast<char*>(rawData->writable_data()), rawData->size(),
                          HB_MEMORY_MODE_READONLY, rawData,
                          [](void* p) { SkSafeUnref(((SkData*)p)); });
}

HBBlob stream_to_blob(std::unique_ptr<SkStreamAsset> asset) {
    size_t size = asset->getLength();
    HBBlob blob;
    if (const void* base = asset->getMemoryBase()) {
        blob.reset(hb_blob_create(const_cast<char*>(static_cast<const char*>(base)), SkToUInt(size),
                                  HB_MEMORY_MODE_READONLY, asset.release(),
                                  [](void* p) { delete (SkStreamAsset*)p; }));
    } else {
        void* ptr = size ? sk_malloc_throw(size) : nullptr;
        asset->read(ptr, size);
        blob.reset(hb_blob_create((char*)ptr, SkToUInt(size),
                                  HB_MEMORY_MODE_READONLY, ptr, sk_free));
    }
    SkASSERT(blob);
    hb_blob_make_immutable(blob.get());
    return blob;
}

HBFace stream_to_face(std::unique_ptr<SkStreamAsset> asset, int index) {
    HBFace face;
    HBBlob blob(stream_to_blob(std::move(asset)));
    // hb_face_create always succeeds. Check that the format is minimally recognized first.
    // See https://github.com/harfbuzz/harfbuzz/issues/248
    unsigned int num_hb_faces = hb_face_count(blob.get());
    if (0 < num_hb_faces && (unsigned)index < num_hb_faces) {
        face.reset(hb_face_create(blob.get(), (unsigned)index));
        // Check the number of glyphs as a basic sanitization step.
        if (face && hb_face_get_glyph_count(face.get()) == 0) {
            face.reset();
        }
    }
    return face;
}

sk_sp<SkData> to_data(HBBlob blob) {
    if (!blob) {
        return nullptr;
    }
    unsigned int length;
    const char* data = hb_blob_get_data(blob.get(), &length);
    if (!data || !length) {
        return nullptr;
    }
    return SkData::MakeWithProc(data, SkToSizeT(length),
                                [](const void*, void* ctx) { hb_blob_destroy((hb_blob_t*)ctx); },
                                blob.release());
}

HBFace make_subset(hb_subset_input_t* input, hb_face_t* face, bool retainZeroGlyph) {
    // TODO: When possible, check if a font is 'tricky' with FT_IS_TRICKY.
    // If it isn't known if a font is 'tricky', retain the hints.
    unsigned int flags = HB_SUBSET_FLAGS_RETAIN_GIDS;
    if (retainZeroGlyph) {
        flags |= HB_SUBSET_FLAGS_NOTDEF_OUTLINE;
    }
    hb_subset_input_set_flags(input, flags);
    return HBFace(hb_subset_or_fail(face, input));
}

sk_sp<SkData> subset_harfbuzz(const SkTypeface& typeface, const SkPDFGlyphUse& glyphUsage) {
    HBFace face;
    if (!SkPDFCanSubsetTableBasedFonts()) {
        int index = 0;
        std::unique_ptr<SkStreamAsset> typefaceAsset = typeface.openStream(&index);
        if (typefaceAsset) {
            face = stream_to_face(std::move(typefaceAsset), index);
        }
    } else {
        int index = 0;
        std::unique_ptr<SkStreamAsset> typefaceAsset = typeface.openExistingStream(&index);
        if (typefaceAsset && typefaceAsset->getMemoryBase()) {
            face = stream_to_face(std::move(typefaceAsset), index);
        }
        if (!face) {
            // Use hb_face_create_for_tables to try creating a working hb_face.
            // Using this creates empty subsets in HarfBuzz until 4.4.0.
            face.reset(hb_face_create_for_tables(
                skhb_get_table,
                const_cast<SkTypeface*>(SkRef(&typeface)),
                [](void* user_data){ SkSafeUnref(reinterpret_cast<SkTypeface*>(user_data)); }));
            hb_face_set_index(face.get(), (unsigned)index);
#if HB_VERSION_ATLEAST(10, 0, 0)
            hb_face_set_get_table_tags_func(
                face.get(), skhb_get_table_tags_func,
                const_cast<SkTypeface*>(SkRef(&typeface)),
                [](void* user_data){ SkSafeUnref(reinterpret_cast<SkTypeface*>(user_data)); });
#endif
            // Check the number of glyphs as a basic sanitization step.
            if (face && hb_face_get_glyph_count(face.get()) == 0) {
                face.reset();
            }
        }
    }

    HBSubsetInput input(hb_subset_input_create_or_fail());
    SkASSERT(input);
    if (!face || !input) {
        return nullptr;
    }
    hb_set_t* glyphs = hb_subset_input_glyph_set(input.get());
    glyphUsage.getSetValues([&glyphs](unsigned gid) { hb_set_add(glyphs, gid);});

    HBFace subset = make_subset(input.get(), face.get(), glyphUsage.has(0));
    if (!subset) {
        return nullptr;
    }

    HBBlob result(hb_face_reference_blob(subset.get()));
    return to_data(std::move(result));
}

}  // namespace

sk_sp<SkData> SkPDFSubsetFont(const SkTypeface& typeface, const SkPDFGlyphUse& glyphUsage) {
    return subset_harfbuzz(typeface, glyphUsage);
}

bool SkPDFCanSubsetTableBasedFonts() {
    // See https://github.com/harfbuzz/harfbuzz/issues/3609
    // See https://github.com/harfbuzz/harfbuzz/issues/1697
    // This file requires HarfBuzz 3.0 or later (when the public subsetter API shipped).
    // The default tables to search for subsetting were added in HarfBuzz 4.4.0.
    // The full fix (hb_face_set_get_table_tags_func) is in HarfBuzz 10.0.0.
    return hb_version_atleast(4, 4, 0);
}

#else

sk_sp<SkData> SkPDFSubsetFont(const SkTypeface&, const SkPDFGlyphUse&) {
    return nullptr;
}

bool SkPDFCanSubsetTableBasedFonts() {
    return false;
}

#endif  // defined(SK_PDF_USE_HARFBUZZ_SUBSET)
