/*
 * Copyright (C) 2012 Koji Ishii <kojiishi@gmail.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#if ENABLE(OPENTYPE_VERTICAL)
#include "OpenTypeVerticalData.h"

#include "FloatRect.h"
#include "Font.h"
#include "GlyphPage.h"
#include "OpenTypeTypes.h"
#include "SharedBuffer.h"
#include <wtf/RefPtr.h>


namespace WebCore {
using namespace std;
namespace OpenType {

const uint32_t GSUBTag = OT_MAKE_TAG('G', 'S', 'U', 'B');
const uint32_t HheaTag = OT_MAKE_TAG('h', 'h', 'e', 'a');
const uint32_t HmtxTag = OT_MAKE_TAG('h', 'm', 't', 'x');
const uint32_t VheaTag = OT_MAKE_TAG('v', 'h', 'e', 'a');
const uint32_t VmtxTag = OT_MAKE_TAG('v', 'm', 't', 'x');
const uint32_t VORGTag = OT_MAKE_TAG('V', 'O', 'R', 'G');

const uint32_t DefaultScriptTag = OT_MAKE_TAG('D', 'F', 'L', 'T');

const uint32_t VertFeatureTag = OT_MAKE_TAG('v', 'e', 'r', 't');

#pragma pack(1)

struct HheaTable {
    OpenType::Fixed version;
    OpenType::Int16 ascender;
    OpenType::Int16 descender;
    OpenType::Int16 lineGap;
    OpenType::Int16 advanceWidthMax;
    OpenType::Int16 minLeftSideBearing;
    OpenType::Int16 minRightSideBearing;
    OpenType::Int16 xMaxExtent;
    OpenType::Int16 caretSlopeRise;
    OpenType::Int16 caretSlopeRun;
    OpenType::Int16 caretOffset;
    OpenType::Int16 reserved[4];
    OpenType::Int16 metricDataFormat;
    OpenType::UInt16 numberOfHMetrics;
};

struct VheaTable {
    OpenType::Fixed version;
    OpenType::Int16 ascent;
    OpenType::Int16 descent;
    OpenType::Int16 lineGap;
    OpenType::Int16 advanceHeightMax;
    OpenType::Int16 minTopSideBearing;
    OpenType::Int16 minBottomSideBearing;
    OpenType::Int16 yMaxExtent;
    OpenType::Int16 caretSlopeRise;
    OpenType::Int16 caretSlopeRun;
    OpenType::Int16 caretOffset;
    OpenType::Int16 reserved[4];
    OpenType::Int16 metricDataFormat;
    OpenType::UInt16 numOfLongVerMetrics;
};

struct HmtxTable {
    struct Entry {
        OpenType::UInt16 advanceWidth;
        OpenType::Int16 lsb;
    } entries[1];
};

struct VmtxTable {
    struct Entry {
        OpenType::UInt16 advanceHeight;
        OpenType::Int16 topSideBearing;
    } entries[1];
};

struct VORGTable {
    OpenType::UInt16 majorVersion;
    OpenType::UInt16 minorVersion;
    OpenType::Int16 defaultVertOriginY;
    OpenType::UInt16 numVertOriginYMetrics;
    struct VertOriginYMetrics {
        OpenType::UInt16 glyphIndex;
        OpenType::Int16 vertOriginY;
    } vertOriginYMetrics[1];

    size_t requiredSize() const { return sizeof(*this) + sizeof(VertOriginYMetrics) * (numVertOriginYMetrics - 1); }
};

struct SubstitutionSubTable : TableBase {
    OpenType::UInt16 substFormat;
    OpenType::Offset coverageOffset;

    const CoverageTable* coverage(const SharedBuffer& buffer) const { return validateOffset<CoverageTable>(buffer, coverageOffset); }
};

struct SingleSubstitution2SubTable : SubstitutionSubTable {
    OpenType::UInt16 glyphCount;
    OpenType::GlyphID substitute[1];
};

struct LookupTable : TableBase {
    OpenType::UInt16 lookupType;
    OpenType::UInt16 lookupFlag;
    OpenType::UInt16 subTableCount;
    OpenType::Offset subTableOffsets[1];
    // OpenType::UInt16 markFilteringSet; this field comes after variable length, so offset is determined dynamically.

    bool getSubstitutions(HashMap<Glyph, Glyph>* map, const SharedBuffer& buffer) const
    {
        uint16_t countSubTable = subTableCount;
        if (!isValidEnd(buffer, &subTableOffsets[countSubTable]))
            return false;
        if (lookupType != 1) // "Single Substitution Subtable" is all what we support
            return false;
        for (uint16_t i = 0; i < countSubTable; ++i) {
            const SubstitutionSubTable* substitution = validateOffset<SubstitutionSubTable>(buffer, subTableOffsets[i]);
            if (!substitution)
                return false;
            const CoverageTable* coverage = substitution->coverage(buffer);
            if (!coverage)
                return false;
            if (substitution->substFormat != 2) // "Single Substitution Format 2" is all what we support
                return false;
            const SingleSubstitution2SubTable* singleSubstitution2 = validatePtr<SingleSubstitution2SubTable>(buffer, substitution);
            if (!singleSubstitution2)
                return false;
            uint16_t countTo = singleSubstitution2->glyphCount;
            if (!isValidEnd(buffer, &singleSubstitution2->substitute[countTo]))
                return false;
            switch (coverage->coverageFormat) {
            case 1: { // Coverage Format 1 (e.g., MS Gothic)
                const Coverage1Table* coverage1 = validatePtr<Coverage1Table>(buffer, coverage);
                if (!coverage1)
                    return false;
                uint16_t countFrom = coverage1->glyphCount;
                if (!isValidEnd(buffer, &coverage1->glyphArray[countFrom]) || countTo != countFrom)
                    return false;
                for (uint16_t i = 0; i < countTo; ++i)
                    map->set(coverage1->glyphArray[i], singleSubstitution2->substitute[i]);
                break;
            }
            case 2: { // Coverage Format 2 (e.g., Adobe Kozuka Gothic)
                const Coverage2Table* coverage2 = validatePtr<Coverage2Table>(buffer, coverage);
                if (!coverage2)
                    return false;
                uint16_t countRange = coverage2->rangeCount;
                if (!isValidEnd(buffer, &coverage2->ranges[countRange]))
                    return false;
                for (uint16_t i = 0, indexTo = 0; i < countRange; ++i) {
                    uint16_t from = coverage2->ranges[i].start;
                    uint16_t fromEnd = coverage2->ranges[i].end + 1; // OpenType "end" is inclusive
                    if (indexTo + (fromEnd - from) > countTo)
                        return false;
                    for (; from != fromEnd; ++from, ++indexTo)
                        map->set(from, singleSubstitution2->substitute[indexTo]);
                }
                break;
            }
            default:
                return false;
            }
        }
        return true;
    }
};

struct LookupList : TableBase {
    OpenType::UInt16 lookupCount;
    OpenType::Offset lookupOffsets[1];

    const LookupTable* lookup(uint16_t index, const SharedBuffer& buffer) const
    {
        uint16_t count = lookupCount;
        if (index >= count || !isValidEnd(buffer, &lookupOffsets[count]))
            return 0;
        return validateOffset<LookupTable>(buffer, lookupOffsets[index]);
    }
};

struct FeatureTable : TableBase {
    OpenType::Offset featureParams;
    OpenType::UInt16 lookupCount;
    OpenType::UInt16 lookupListIndex[1];

    bool getGlyphSubstitutions(const LookupList* lookups, HashMap<Glyph, Glyph>* map, const SharedBuffer& buffer) const
    {
        uint16_t count = lookupCount;
        if (!isValidEnd(buffer, &lookupListIndex[count]))
            return false;
        for (uint16_t i = 0; i < count; ++i) {
            const LookupTable* lookup = lookups->lookup(lookupListIndex[i], buffer);
            if (!lookup || !lookup->getSubstitutions(map, buffer))
                return false;
        }
        return true;
    }
};

struct FeatureList : TableBase {
    OpenType::UInt16 featureCount;
    struct FeatureRecord {
        OpenType::Tag featureTag;
        OpenType::Offset featureOffset;
    } features[1];

    const FeatureTable* feature(uint16_t index, OpenType::Tag tag, const SharedBuffer& buffer) const
    {
        uint16_t count = featureCount;
        if (index >= count || !isValidEnd(buffer, &features[count]))
            return 0;
        if (features[index].featureTag == tag)
            return validateOffset<FeatureTable>(buffer, features[index].featureOffset);
        return 0;
    }

    const FeatureTable* findFeature(OpenType::Tag tag, const SharedBuffer& buffer) const
    {
        for (uint16_t i = 0; i < featureCount; ++i) {
            if (isValidEnd(buffer, &features[i]) && features[i].featureTag == tag)
                return validateOffset<FeatureTable>(buffer, features[i].featureOffset);
        }
        return 0;
    }
};

struct LangSysTable : TableBase {
    OpenType::Offset lookupOrder;
    OpenType::UInt16 reqFeatureIndex;
    OpenType::UInt16 featureCount;
    OpenType::UInt16 featureIndex[1];

    const FeatureTable* feature(OpenType::Tag featureTag, const FeatureList* features, const SharedBuffer& buffer) const
    {
        uint16_t count = featureCount;
        if (!isValidEnd(buffer, &featureIndex[count]))
            return 0;
        for (uint16_t i = 0; i < count; ++i) {
            const FeatureTable* featureTable = features->feature(featureIndex[i], featureTag, buffer);
            if (featureTable)
                return featureTable;
        }
        return 0;
    }
};

struct ScriptTable : TableBase {
    OpenType::Offset defaultLangSysOffset;
    OpenType::UInt16 langSysCount;
    struct LangSysRecord {
        OpenType::Tag langSysTag;
        OpenType::Offset langSysOffset;
    } langSysRecords[1];

    const LangSysTable* defaultLangSys(const SharedBuffer& buffer) const
    {
        uint16_t count = langSysCount;
        if (!isValidEnd(buffer, &langSysRecords[count]))
            return 0;
        uint16_t offset = defaultLangSysOffset;
        if (offset)
            return validateOffset<LangSysTable>(buffer, offset);
        if (count)
            return validateOffset<LangSysTable>(buffer, langSysRecords[0].langSysOffset);
        return 0;
    }
};

struct ScriptList : TableBase {
    OpenType::UInt16 scriptCount;
    struct ScriptRecord {
        OpenType::Tag scriptTag;
        OpenType::Offset scriptOffset;
    } scripts[1];

    const ScriptTable* script(OpenType::Tag tag, const SharedBuffer& buffer) const
    {
        uint16_t count = scriptCount;
        if (!isValidEnd(buffer, &scripts[count]))
            return 0;
        for (uint16_t i = 0; i < count; ++i) {
            if (scripts[i].scriptTag == tag)
                return validateOffset<ScriptTable>(buffer, scripts[i].scriptOffset);
        }
        return 0;
    }

    const ScriptTable* defaultScript(const SharedBuffer& buffer) const
    {
        uint16_t count = scriptCount;
        if (!count || !isValidEnd(buffer, &scripts[count]))
            return 0;
        const ScriptTable* scriptOfDefaultTag = script(OpenType::DefaultScriptTag, buffer);
        if (scriptOfDefaultTag)
            return scriptOfDefaultTag;
        return validateOffset<ScriptTable>(buffer, scripts[0].scriptOffset);
    }

    const LangSysTable* defaultLangSys(const SharedBuffer& buffer) const
    {
        const ScriptTable* scriptTable = defaultScript(buffer);
        if (!scriptTable)
            return 0;
        return scriptTable->defaultLangSys(buffer);
    }
};

struct GSUBTable : TableBase {
    OpenType::Fixed version;
    OpenType::Offset scriptListOffset;
    OpenType::Offset featureListOffset;
    OpenType::Offset lookupListOffset;

    const ScriptList* scriptList(const SharedBuffer& buffer) const { return validateOffset<ScriptList>(buffer, scriptListOffset); }
    const FeatureList* featureList(const SharedBuffer& buffer) const { return validateOffset<FeatureList>(buffer, featureListOffset); }
    const LookupList* lookupList(const SharedBuffer& buffer) const { return validateOffset<LookupList>(buffer, lookupListOffset); }

    const LangSysTable* defaultLangSys(const SharedBuffer& buffer) const
    {
        const ScriptList* scripts = scriptList(buffer);
        if (!scripts)
            return 0;
        return scripts->defaultLangSys(buffer);
    }

    const FeatureTable* feature(OpenType::Tag featureTag, const SharedBuffer& buffer) const
    {
        const LangSysTable* langSys = defaultLangSys(buffer);
        const FeatureList* features = featureList(buffer);
        if (!features)
            return 0;
        const FeatureTable* feature = 0;
        if (langSys)
            feature = langSys->feature(featureTag, features, buffer);
        if (!feature) {
            // If the font has no langSys table, or has no default script and the first script doesn't
            // have the requested feature, then use the first matching feature directly.
            feature = features->findFeature(featureTag, buffer);
        }
        return feature;
    }

    bool getVerticalGlyphSubstitutions(HashMap<Glyph, Glyph>* map, const SharedBuffer& buffer) const
    {
        const FeatureTable* verticalFeatureTable = feature(OpenType::VertFeatureTag, buffer);
        if (!verticalFeatureTable)
            return false;
        const LookupList* lookups = lookupList(buffer);
        return lookups && verticalFeatureTable->getGlyphSubstitutions(lookups, map, buffer);
    }
};

#pragma pack()

} // namespace OpenType

static bool loadHmtxTable(const FontPlatformData& platformData, Vector<uint16_t>& advanceWidths)
{
    RefPtr<SharedBuffer> buffer = platformData.openTypeTable(OpenType::HheaTag);
    const OpenType::HheaTable* hhea = OpenType::validateTable<OpenType::HheaTable>(buffer);
    if (!hhea)
        return false;
    uint16_t countHmtxEntries = hhea->numberOfHMetrics;
    if (!countHmtxEntries) {
        LOG_ERROR("Invalid numberOfHMetrics");
        return false;
    }

    buffer = platformData.openTypeTable(OpenType::HmtxTag);
    const OpenType::HmtxTable* hmtx = OpenType::validateTable<OpenType::HmtxTable>(buffer, countHmtxEntries);
    if (!hmtx) {
        LOG_ERROR("hhea exists but hmtx does not (or broken)");
        return false;
    }

    advanceWidths.resize(countHmtxEntries);
    for (uint16_t i = 0; i < countHmtxEntries; ++i)
        advanceWidths[i] = hmtx->entries[i].advanceWidth;
    return true;
}

RefPtr<OpenTypeVerticalData> OpenTypeVerticalData::create(const FontPlatformData& platformData)
{
    // Load hhea and hmtx to get x-component of vertical origins. If these tables are missing, it's not an OpenType font.
    Vector<uint16_t> advanceWidths;
    if (!loadHmtxTable(platformData, advanceWidths))
        return nullptr;

    return adoptRef(new OpenTypeVerticalData(platformData, WTFMove(advanceWidths)));
}

OpenTypeVerticalData::OpenTypeVerticalData(const FontPlatformData& platformData, Vector<uint16_t>&& advanceWidths)
    : m_advanceWidths(WTFMove(advanceWidths))
{
    loadMetrics(platformData);
    loadVerticalGlyphSubstitutions(platformData);
}

void OpenTypeVerticalData::loadMetrics(const FontPlatformData& platformData)
{
    // Load vhea first. This table is required for fonts that support vertical flow.
    RefPtr<SharedBuffer> buffer = platformData.openTypeTable(OpenType::VheaTag);
    const OpenType::VheaTable* vhea = OpenType::validateTable<OpenType::VheaTable>(buffer);
    if (!vhea)
        return;
    uint16_t countVmtxEntries = vhea->numOfLongVerMetrics;
    if (!countVmtxEntries) {
        LOG_ERROR("Invalid numOfLongVerMetrics");
        return;
    }

    // Load VORG. This table is optional.
    buffer = platformData.openTypeTable(OpenType::VORGTag);
    const OpenType::VORGTable* vorg = OpenType::validateTable<OpenType::VORGTable>(buffer);
    if (vorg && buffer->size() >= vorg->requiredSize()) {
        m_defaultVertOriginY = vorg->defaultVertOriginY;
        uint16_t countVertOriginYMetrics = vorg->numVertOriginYMetrics;
        if (!countVertOriginYMetrics) {
            // Add one entry so that hasVORG() becomes true
            m_vertOriginY.set(0, m_defaultVertOriginY);
        } else {
            for (uint16_t i = 0; i < countVertOriginYMetrics; ++i) {
                const OpenType::VORGTable::VertOriginYMetrics& metrics = vorg->vertOriginYMetrics[i];
                m_vertOriginY.set(metrics.glyphIndex, metrics.vertOriginY);
            }
        }
    }

    // Load vmtx then. This table is required for fonts that support vertical flow.
    buffer = platformData.openTypeTable(OpenType::VmtxTag);
    const OpenType::VmtxTable* vmtx = OpenType::validateTable<OpenType::VmtxTable>(buffer, countVmtxEntries);
    if (!vmtx) {
        LOG_ERROR("vhea exists but vmtx does not (or broken)");
        return;
    }
    m_advanceHeights.resize(countVmtxEntries);
    for (uint16_t i = 0; i < countVmtxEntries; ++i)
        m_advanceHeights[i] = vmtx->entries[i].advanceHeight;

    // VORG is preferred way to calculate vertical origin than vmtx,
    // so load topSideBearing from vmtx only if VORG is missing.
    if (hasVORG())
        return;

    size_t sizeExtra = buffer->size() - sizeof(OpenType::VmtxTable::Entry) * countVmtxEntries;
    if (sizeExtra % sizeof(OpenType::Int16)) {
        LOG_ERROR("vmtx has incorrect tsb count");
        return;
    }
    size_t countTopSideBearings = countVmtxEntries + sizeExtra / sizeof(OpenType::Int16);
    m_topSideBearings.resize(countTopSideBearings);
    size_t i;
    for (i = 0; i < countVmtxEntries; ++i)
        m_topSideBearings[i] = vmtx->entries[i].topSideBearing;
    if (i < countTopSideBearings) {
        const OpenType::Int16* pTopSideBearingsExtra = reinterpret_cast<const OpenType::Int16*>(&vmtx->entries[countVmtxEntries]);
        for (; i < countTopSideBearings; ++i, ++pTopSideBearingsExtra)
            m_topSideBearings[i] = *pTopSideBearingsExtra;
    }
}

void OpenTypeVerticalData::loadVerticalGlyphSubstitutions(const FontPlatformData& platformData)
{
    RefPtr<SharedBuffer> buffer = platformData.openTypeTable(OpenType::GSUBTag);
    const OpenType::GSUBTable* gsub = OpenType::validateTable<OpenType::GSUBTable>(buffer);
    if (gsub)
        gsub->getVerticalGlyphSubstitutions(&m_verticalGlyphMap, *buffer.get());
}

float OpenTypeVerticalData::advanceHeight(const Font* font, Glyph glyph) const
{
    size_t countHeights = m_advanceHeights.size();
    if (countHeights) {
        uint16_t advanceFUnit = m_advanceHeights[glyph < countHeights ? glyph : countHeights - 1];
        float advance = advanceFUnit * font->sizePerUnit();
        return advance;
    }

    // No vertical info in the font file; use height as advance.
    return font->fontMetrics().height();
}

void OpenTypeVerticalData::getVerticalTranslationsForGlyphs(const Font* font, const Glyph* glyphs, size_t count, float* outXYArray) const
{
    size_t countWidths = m_advanceWidths.size();
    ASSERT(countWidths > 0);
    const FontMetrics& metrics = font->fontMetrics();
    float sizePerUnit = font->sizePerUnit();
    float ascent = metrics.ascent();
    bool useVORG = hasVORG();
    size_t countTopSideBearings = m_topSideBearings.size();
    float defaultVertOriginY = std::numeric_limits<float>::quiet_NaN();
    for (float* end = &(outXYArray[count * 2]); outXYArray != end; ++glyphs, outXYArray += 2) {
        Glyph glyph = *glyphs;
        uint16_t widthFUnit = m_advanceWidths[glyph < countWidths ? glyph : countWidths - 1];
        float width = widthFUnit * sizePerUnit;
        outXYArray[0] = -width / 2;

        // For Y, try VORG first.
        if (useVORG) {
            int16_t vertOriginYFUnit = m_vertOriginY.get(glyph);
            if (vertOriginYFUnit) {
                outXYArray[1] = -vertOriginYFUnit * sizePerUnit;
                continue;
            }
            if (std::isnan(defaultVertOriginY))
                defaultVertOriginY = -m_defaultVertOriginY * sizePerUnit;
            outXYArray[1] = defaultVertOriginY;
            continue;
        }

        // If no VORG, try vmtx next.
        if (countTopSideBearings) {
            int16_t topSideBearingFUnit = m_topSideBearings[glyph < countTopSideBearings ? glyph : countTopSideBearings - 1];
            float topSideBearing = topSideBearingFUnit * sizePerUnit;
            FloatRect bounds = font->boundsForGlyph(glyph);
            outXYArray[1] = bounds.y() - topSideBearing;
            continue;
        }

        // No vertical info in the font file; use ascent as vertical origin.
        outXYArray[1] = -ascent;
    }
}

void OpenTypeVerticalData::substituteWithVerticalGlyphs(const Font* font, GlyphPage* glyphPage) const
{
    const HashMap<Glyph, Glyph>& map = m_verticalGlyphMap;
    if (map.isEmpty())
        return;

    for (unsigned index = 0; index < GlyphPage::size; ++index) {
        Glyph glyph = glyphPage->glyphForIndex(index);
        if (glyph) {
            ASSERT_UNUSED(font, &glyphPage->font() == font);
            Glyph to = map.get(glyph);
            if (to)
                glyphPage->setGlyphForIndex(index, to);
        }
    }
}

} // namespace WebCore
#endif // ENABLE(OPENTYPE_VERTICAL)
