/*
 * 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 "SkAutoMalloc.h"
#include "SkEndian.h"
#include "SkFontStream.h"
#include "SkStream.h"

struct SkSFNTHeader {
    uint32_t    fVersion;
    uint16_t    fNumTables;
    uint16_t    fSearchRange;
    uint16_t    fEntrySelector;
    uint16_t    fRangeShift;
};

struct SkTTCFHeader {
    uint32_t    fTag;
    uint32_t    fVersion;
    uint32_t    fNumOffsets;
    uint32_t    fOffset0;   // the first of N (fNumOffsets)
};

union SkSharedTTHeader {
    SkSFNTHeader    fSingle;
    SkTTCFHeader    fCollection;
};

struct SkSFNTDirEntry {
    uint32_t    fTag;
    uint32_t    fChecksum;
    uint32_t    fOffset;
    uint32_t    fLength;
};

static bool read(SkStream* stream, void* buffer, size_t amount) {
    return stream->read(buffer, amount) == amount;
}

static bool skip(SkStream* stream, size_t amount) {
    return stream->skip(amount) == amount;
}

/** Return the number of tables, or if this is a TTC (collection), return the
    number of tables in the first element of the collection. In either case,
    if offsetToDir is not-null, set it to the offset to the beginning of the
    table headers (SkSFNTDirEntry), relative to the start of the stream.

    On an error, return 0 for number of tables, and ignore offsetToDir
 */
static int count_tables(SkStream* stream, int ttcIndex, size_t* offsetToDir) {
    SkASSERT(ttcIndex >= 0);

    SkAutoSMalloc<1024> storage(sizeof(SkSharedTTHeader));
    SkSharedTTHeader* header = (SkSharedTTHeader*)storage.get();

    if (!read(stream, header, sizeof(SkSharedTTHeader))) {
        return 0;
    }

    // by default, SkSFNTHeader is at the start of the stream
    size_t offset = 0;

    // if we're really a collection, the first 4-bytes will be 'ttcf'
    uint32_t tag = SkEndian_SwapBE32(header->fCollection.fTag);
    if (SkSetFourByteTag('t', 't', 'c', 'f') == tag) {
        unsigned count = SkEndian_SwapBE32(header->fCollection.fNumOffsets);
        if ((unsigned)ttcIndex >= count) {
            return 0;
        }

        if (ttcIndex > 0) { // need to read more of the shared header
            stream->rewind();
            size_t amount = sizeof(SkSharedTTHeader) + ttcIndex * sizeof(uint32_t);
            header = (SkSharedTTHeader*)storage.reset(amount);
            if (!read(stream, header, amount)) {
                return 0;
            }
        }
        // this is the offset to the local SkSFNTHeader
        offset = SkEndian_SwapBE32((&header->fCollection.fOffset0)[ttcIndex]);
        stream->rewind();
        if (!skip(stream, offset)) {
            return 0;
        }
        if (!read(stream, header, sizeof(SkSFNTHeader))) {
            return 0;
        }
    }

    if (offsetToDir) {
        // add the size of the header, so we will point to the DirEntries
        *offsetToDir = offset + sizeof(SkSFNTHeader);
    }
    return SkEndian_SwapBE16(header->fSingle.fNumTables);
}

///////////////////////////////////////////////////////////////////////////////

struct SfntHeader {
    SfntHeader() : fCount(0), fDir(nullptr) {}
    ~SfntHeader() { sk_free(fDir); }

    /** If it returns true, then fCount and fDir are properly initialized.
        Note: fDir will point to the raw array of SkSFNTDirEntry values,
        meaning they will still be in the file's native endianness (BE).

        fDir will be automatically freed when this object is destroyed
     */
    bool init(SkStream* stream, int ttcIndex) {
        stream->rewind();

        size_t offsetToDir;
        fCount = count_tables(stream, ttcIndex, &offsetToDir);
        if (0 == fCount) {
            return false;
        }

        stream->rewind();
        if (!skip(stream, offsetToDir)) {
            return false;
        }

        size_t size = fCount * sizeof(SkSFNTDirEntry);
        fDir = reinterpret_cast<SkSFNTDirEntry*>(sk_malloc_throw(size));
        return read(stream, fDir, size);
    }

    int             fCount;
    SkSFNTDirEntry* fDir;
};

///////////////////////////////////////////////////////////////////////////////

int SkFontStream::CountTTCEntries(SkStream* stream) {
    stream->rewind();

    SkSharedTTHeader shared;
    if (!read(stream, &shared, sizeof(shared))) {
        return 0;
    }

    // if we're really a collection, the first 4-bytes will be 'ttcf'
    uint32_t tag = SkEndian_SwapBE32(shared.fCollection.fTag);
    if (SkSetFourByteTag('t', 't', 'c', 'f') == tag) {
        return SkEndian_SwapBE32(shared.fCollection.fNumOffsets);
    } else {
        return 1;   // normal 'sfnt' has 1 dir entry
    }
}

int SkFontStream::GetTableTags(SkStream* stream, int ttcIndex,
                               SkFontTableTag tags[]) {
    SfntHeader  header;
    if (!header.init(stream, ttcIndex)) {
        return 0;
    }

    if (tags) {
        for (int i = 0; i < header.fCount; i++) {
            tags[i] = SkEndian_SwapBE32(header.fDir[i].fTag);
        }
    }
    return header.fCount;
}

size_t SkFontStream::GetTableData(SkStream* stream, int ttcIndex,
                                  SkFontTableTag tag,
                                  size_t offset, size_t length, void* data) {
    SfntHeader  header;
    if (!header.init(stream, ttcIndex)) {
        return 0;
    }

    for (int i = 0; i < header.fCount; i++) {
        if (SkEndian_SwapBE32(header.fDir[i].fTag) == tag) {
            size_t realOffset = SkEndian_SwapBE32(header.fDir[i].fOffset);
            size_t realLength = SkEndian_SwapBE32(header.fDir[i].fLength);
            // now sanity check the caller's offset/length
            if (offset >= realLength) {
                return 0;
            }
            // if the caller is trusting the length from the file, then a
            // hostile file might choose a value which would overflow offset +
            // length.
            if (offset + length < offset) {
                return 0;
            }
            if (length > realLength - offset) {
                length = realLength - offset;
            }
            if (data) {
                // skip the stream to the part of the table we want to copy from
                stream->rewind();
                size_t bytesToSkip = realOffset + offset;
                if (!skip(stream, bytesToSkip)) {
                    return 0;
                }
                if (!read(stream, data, length)) {
                    return 0;
                }
            }
            return length;
        }
    }
    return 0;
}
