/*
 * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
 *
 * 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"
#include "SVGToOTFFontConversion.h"

#include "CSSStyleDeclaration.h"
#include "ElementChildIterator.h"
#include "Glyph.h"
#include "HTMLParserIdioms.h"
#include "SVGElementTypeHelpers.h"
#include "SVGFontElement.h"
#include "SVGFontFaceElement.h"
#include "SVGGlyphElement.h"
#include "SVGHKernElement.h"
#include "SVGMissingGlyphElement.h"
#include "SVGPathParser.h"
#include "SVGPathStringSource.h"
#include "SVGVKernElement.h"
#include <wtf/Vector.h>
#include <wtf/text/StringToIntegerConversion.h>
#include <wtf/text/StringView.h>

namespace WebCore {

template <typename V>
static inline void append32(V& result, uint32_t value)
{
    result.append(value >> 24);
    result.append(value >> 16);
    result.append(value >> 8);
    result.append(value);
}

class SVGToOTFFontConverter {
public:
    SVGToOTFFontConverter(const SVGFontElement&);
    bool convertSVGToOTFFont();

    Vector<uint8_t> releaseResult()
    {
        return WTFMove(m_result);
    }

    bool error() const
    {
        return m_error;
    }

private:
    struct GlyphData {
        GlyphData(Vector<char>&& charString, const SVGGlyphElement* glyphElement, float horizontalAdvance, float verticalAdvance, FloatRect boundingBox, const String& codepoints)
            : boundingBox(boundingBox)
            , charString(charString)
            , codepoints(codepoints)
            , glyphElement(glyphElement)
            , horizontalAdvance(horizontalAdvance)
            , verticalAdvance(verticalAdvance)
        {
        }
        FloatRect boundingBox;
        Vector<char> charString;
        String codepoints;
        const SVGGlyphElement* glyphElement;
        float horizontalAdvance;
        float verticalAdvance;
    };

    class Placeholder {
    public:
        Placeholder(SVGToOTFFontConverter& converter, size_t baseOfOffset)
            : m_converter(converter)
            , m_baseOfOffset(baseOfOffset)
            , m_location(m_converter.m_result.size())
        {
            m_converter.append16(0);
        }

        Placeholder(Placeholder&& other)
            : m_converter(other.m_converter)
            , m_baseOfOffset(other.m_baseOfOffset)
            , m_location(other.m_location)
#if ASSERT_ENABLED
            , m_active(other.m_active)
#endif
        {
#if ASSERT_ENABLED
            other.m_active = false;
#endif
        }

        void populate()
        {
            ASSERT(m_active);
            size_t delta = m_converter.m_result.size() - m_baseOfOffset;
            ASSERT(delta < std::numeric_limits<uint16_t>::max());
            m_converter.overwrite16(m_location, delta);
#if ASSERT_ENABLED
            m_active = false;
#endif
        }

        ~Placeholder()
        {
            ASSERT(!m_active);
        }

    private:
        SVGToOTFFontConverter& m_converter;
        const size_t m_baseOfOffset;
        const size_t m_location;
#if ASSERT_ENABLED
        bool m_active = { true };
#endif
    };

    struct KerningData {
        KerningData(uint16_t glyph1, uint16_t glyph2, int16_t adjustment)
            : glyph1(glyph1)
            , glyph2(glyph2)
            , adjustment(adjustment)
        {
        }
        uint16_t glyph1;
        uint16_t glyph2;
        int16_t adjustment;
    };

    Placeholder placeholder(size_t baseOfOffset)
    {
        return Placeholder(*this, baseOfOffset);
    }

    void append32(uint32_t value)
    {
        WebCore::append32(m_result, value);
    }

    void append32BitCode(const char code[4])
    {
        m_result.append(code[0]);
        m_result.append(code[1]);
        m_result.append(code[2]);
        m_result.append(code[3]);
    }

    void append16(uint16_t value)
    {
        m_result.append(value >> 8);
        m_result.append(value);
    }

    void grow(size_t delta)
    {
        m_result.grow(m_result.size() + delta);
    }

    void overwrite32(unsigned location, uint32_t value)
    {
        ASSERT(m_result.size() >= location + 4);
        m_result[location] = value >> 24;
        m_result[location + 1] = value >> 16;
        m_result[location + 2] = value >> 8;
        m_result[location + 3] = value;
    }

    void overwrite16(unsigned location, uint16_t value)
    {
        ASSERT(m_result.size() >= location + 2);
        m_result[location] = value >> 8;
        m_result[location + 1] = value;
    }

    static const size_t headerSize = 12;
    static const size_t directoryEntrySize = 16;

    uint32_t calculateChecksum(size_t startingOffset, size_t endingOffset) const;

    void processGlyphElement(const SVGElement& glyphOrMissingGlyphElement, const SVGGlyphElement*, float defaultHorizontalAdvance, float defaultVerticalAdvance, const String& codepoints, std::optional<FloatRect>& boundingBox);

    typedef void (SVGToOTFFontConverter::*FontAppendingFunction)();
    void appendTable(const char identifier[4], FontAppendingFunction);
    void appendFormat12CMAPTable(const Vector<std::pair<UChar32, Glyph>>& codepointToGlyphMappings);
    void appendFormat4CMAPTable(const Vector<std::pair<UChar32, Glyph>>& codepointToGlyphMappings);
    void appendCMAPTable();
    void appendGSUBTable();
    void appendHEADTable();
    void appendHHEATable();
    void appendHMTXTable();
    void appendVHEATable();
    void appendVMTXTable();
    void appendKERNTable();
    void appendMAXPTable();
    void appendNAMETable();
    void appendOS2Table();
    void appendPOSTTable();
    void appendCFFTable();
    void appendVORGTable();

    void appendLigatureGlyphs();
    static bool compareCodepointsLexicographically(const GlyphData&, const GlyphData&);

    void appendValidCFFString(const String&);

    Vector<char> transcodeGlyphPaths(float width, const SVGElement& glyphOrMissingGlyphElement, std::optional<FloatRect>& boundingBox) const;

    void addCodepointRanges(const UnicodeRanges&, HashSet<Glyph>& glyphSet) const;
    void addCodepoints(const HashSet<String>& codepoints, HashSet<Glyph>& glyphSet) const;
    void addGlyphNames(const HashSet<String>& glyphNames, HashSet<Glyph>& glyphSet) const;
    void addKerningPair(Vector<KerningData>&, SVGKerningPair&&) const;
    template<typename T> size_t appendKERNSubtable(std::optional<SVGKerningPair> (T::*buildKerningPair)() const, uint16_t coverage);
    size_t finishAppendingKERNSubtable(Vector<KerningData>, uint16_t coverage);

    void appendLigatureSubtable(size_t subtableRecordLocation);
    void appendArabicReplacementSubtable(size_t subtableRecordLocation, ASCIILiteral arabicForm);
    void appendScriptSubtable(unsigned featureCount);
    Vector<Glyph, 1> glyphsForCodepoint(UChar32) const;
    Glyph firstGlyph(const Vector<Glyph, 1>&, UChar32) const;

    template<typename T> T scaleUnitsPerEm(T value) const
    {
        return value * s_outputUnitsPerEm / m_inputUnitsPerEm;
    }

    Vector<GlyphData> m_glyphs;
    HashMap<String, Glyph> m_glyphNameToIndexMap; // SVG 1.1: "It is recommended that glyph names be unique within a font."
    HashMap<String, Vector<Glyph, 1>> m_codepointsToIndicesMap;
    Vector<uint8_t> m_result;
    Vector<char, 17> m_emptyGlyphCharString;
    FloatRect m_boundingBox;
    const SVGFontElement& m_fontElement;
    const SVGFontFaceElement* m_fontFaceElement;
    const SVGMissingGlyphElement* m_missingGlyphElement;
    String m_fontFamily;
    float m_advanceWidthMax;
    float m_advanceHeightMax;
    float m_minRightSideBearing;
    static const unsigned s_outputUnitsPerEm = 1000;
    unsigned m_inputUnitsPerEm;
    int m_lineGap;
    int m_xHeight;
    int m_capHeight;
    int m_ascent;
    int m_descent;
    unsigned m_featureCountGSUB;
    unsigned m_tablesAppendedCount;
    uint8_t m_weight;
    bool m_italic;
    bool m_error { false };
};

static uint16_t roundDownToPowerOfTwo(uint16_t x)
{
    x |= x >> 1;
    x |= x >> 2;
    x |= x >> 4;
    x |= x >> 8;
    return (x >> 1) + 1;
}

static uint16_t integralLog2(uint16_t x)
{
    uint16_t result = 0;
    while (x >>= 1)
        ++result;
    return result;
}

void SVGToOTFFontConverter::appendFormat12CMAPTable(const Vector<std::pair<UChar32, Glyph>>& mappings)
{
    // Braindead scheme: One segment for each character
    ASSERT(m_glyphs.size() < 0xFFFF);
    auto subtableLocation = m_result.size();
    append32(12 << 16); // Format 12
    append32(0); // Placeholder for byte length
    append32(0); // Language independent
    append32(0); // Placeholder for nGroups
    for (auto& mapping : mappings) {
        append32(mapping.first); // startCharCode
        append32(mapping.first); // endCharCode
        append32(mapping.second); // startGlyphCode
    }
    overwrite32(subtableLocation + 4, m_result.size() - subtableLocation);
    overwrite32(subtableLocation + 12, mappings.size());
}

void SVGToOTFFontConverter::appendFormat4CMAPTable(const Vector<std::pair<UChar32, Glyph>>& bmpMappings)
{
    auto subtableLocation = m_result.size();
    append16(4); // Format 4
    append16(0); // Placeholder for length in bytes
    append16(0); // Language independent
    uint16_t segCount = bmpMappings.size() + 1;
    append16(clampTo<uint16_t>(2 * segCount)); // segCountX2: "2 x segCount"
    uint16_t originalSearchRange = roundDownToPowerOfTwo(segCount);
    uint16_t searchRange = clampTo<uint16_t>(2 * originalSearchRange); // searchRange: "2 x (2**floor(log2(segCount)))"
    append16(searchRange);
    append16(integralLog2(originalSearchRange)); // entrySelector: "log2(searchRange/2)"  
    append16(clampTo<uint16_t>((2 * segCount) - searchRange)); // rangeShift: "2 x segCount - searchRange"  

    // Ending character codes
    for (auto& mapping : bmpMappings)
        append16(mapping.first); // startCharCode
    append16(0xFFFF);

    append16(0); // reserved

    // Starting character codes
    for (auto& mapping : bmpMappings)
        append16(mapping.first); // startCharCode
    append16(0xFFFF);

    // idDelta
    for (auto& mapping : bmpMappings)
        append16(static_cast<uint16_t>(mapping.second) - static_cast<uint16_t>(mapping.first)); // startCharCode
    append16(0x0001);

    // idRangeOffset
    for (size_t i = 0; i < bmpMappings.size(); ++i)
        append16(0); // startCharCode
    append16(0);

    // Fonts strive to hold 2^16 glyphs, but with the current encoding scheme, we write 8 bytes per codepoint into this subtable.
    // Because the size of this subtable must be represented as a 16-bit number, we are limiting the number of glyphs we support to 2^13.
    // FIXME: If we hit this limit in the wild, use a more compact encoding scheme for this subtable.
    overwrite16(subtableLocation + 2, clampTo<uint16_t>(m_result.size() - subtableLocation));
}

void SVGToOTFFontConverter::appendCMAPTable()
{
    auto startingOffset = m_result.size();
    append16(0);
    append16(3); // Number of subtables

    append16(0); // Unicode
    append16(3); // Unicode version 2.2+
    append32(28); // Byte offset of subtable

    append16(3); // Microsoft
    append16(1); // Unicode BMP
    auto format4OffsetLocation = m_result.size();
    append32(0); // Byte offset of subtable

    append16(3); // Microsoft
    append16(10); // Unicode
    append32(28); // Byte offset of subtable

    Vector<std::pair<UChar32, Glyph>> mappings;
    UChar32 previousCodepoint = std::numeric_limits<UChar32>::max();
    for (size_t i = 0; i < m_glyphs.size(); ++i) {
        auto& glyph = m_glyphs[i];
        UChar32 codepoint;
        auto codePoints = StringView(glyph.codepoints).codePoints();
        auto iterator = codePoints.begin();
        if (iterator == codePoints.end())
            codepoint = 0;
        else {
            codepoint = *iterator;
            ++iterator;
            // Don't map ligatures here.
            if (iterator != codePoints.end() || codepoint == previousCodepoint)
                continue;
        }

        mappings.append(std::make_pair(codepoint, Glyph(i)));
        previousCodepoint = codepoint;
    }

    appendFormat12CMAPTable(mappings);

    Vector<std::pair<UChar32, Glyph>> bmpMappings;
    for (auto& mapping : mappings) {
        if (mapping.first < 0x10000)
            bmpMappings.append(mapping);
    }
    overwrite32(format4OffsetLocation, m_result.size() - startingOffset);
    appendFormat4CMAPTable(bmpMappings);
}

void SVGToOTFFontConverter::appendHEADTable()
{
    append32(0x00010000); // Version
    append32(0x00010000); // Revision
    append32(0); // Checksum placeholder; to be overwritten by the caller.
    append32(0x5F0F3CF5); // Magic number.
    append16((1 << 9) | 1);

    append16(s_outputUnitsPerEm);
    append32(0); // First half of creation date
    append32(0); // Last half of creation date
    append32(0); // First half of modification date
    append32(0); // Last half of modification date
    append16(clampTo<int16_t>(m_boundingBox.x()));
    append16(clampTo<int16_t>(m_boundingBox.y()));
    append16(clampTo<int16_t>(m_boundingBox.maxX()));
    append16(clampTo<int16_t>(m_boundingBox.maxY()));
    append16((m_italic ? 1 << 1 : 0) | (m_weight >= 7 ? 1 : 0));
    append16(3); // Smallest readable size in pixels
    append16(0); // Might contain LTR or RTL glyphs
    append16(0); // Short offsets in the 'loca' table. However, CFF fonts don't have a 'loca' table so this is irrelevant
    append16(0); // Glyph data format
}

void SVGToOTFFontConverter::appendHHEATable()
{
    append32(0x00010000); // Version
    append16(clampTo<int16_t>(m_ascent));
    append16(clampTo<int16_t>(-m_descent));
    // WebKit SVG font rendering has hard coded the line gap to be 1/10th of the font size since 2008 (see r29719).
    append16(clampTo<int16_t>(m_lineGap));
    append16(clampTo<uint16_t>(m_advanceWidthMax));
    append16(clampTo<int16_t>(m_boundingBox.x())); // Minimum left side bearing
    append16(clampTo<int16_t>(m_minRightSideBearing)); // Minimum right side bearing
    append16(clampTo<int16_t>(m_boundingBox.maxX())); // X maximum extent
    // Since WebKit draws the caret and ignores the following values, it doesn't matter what we set them to.
    append16(1); // Vertical caret
    append16(0); // Vertical caret
    append16(0); // "Set value to 0 for non-slanted fonts"
    append32(0); // Reserved
    append32(0); // Reserved
    append16(0); // Current format
    append16(m_glyphs.size()); // Number of advance widths in HMTX table
}

void SVGToOTFFontConverter::appendHMTXTable()
{
    for (auto& glyph : m_glyphs) {
        append16(clampTo<uint16_t>(glyph.horizontalAdvance));
        append16(clampTo<int16_t>(glyph.boundingBox.x()));
    }
}

void SVGToOTFFontConverter::appendMAXPTable()
{
    append32(0x00010000); // Version
    append16(m_glyphs.size());
    append16(0xFFFF); // Maximum number of points in non-compound glyph
    append16(0xFFFF); // Maximum number of contours in non-compound glyph
    append16(0xFFFF); // Maximum number of points in compound glyph
    append16(0xFFFF); // Maximum number of contours in compound glyph
    append16(2); // Maximum number of zones
    append16(0); // Maximum number of points used in zone 0
    append16(0); // Maximum number of storage area locations
    append16(0); // Maximum number of function definitions
    append16(0); // Maximum number of instruction definitions
    append16(0); // Maximum stack depth
    append16(0); // Maximum size of instructions
    append16(m_glyphs.size()); // Maximum number of glyphs referenced at top level
    append16(0); // No compound glyphs
}

void SVGToOTFFontConverter::appendNAMETable()
{
    append16(0); // Format selector
    append16(1); // Number of name records in table
    append16(18); // Offset in bytes to the beginning of name character strings

    append16(0); // Unicode
    append16(3); // Unicode version 2.0 or later
    append16(0); // Language
    append16(1); // Name identifier. 1 = Font family
    append16(m_fontFamily.length() * 2);
    append16(0); // Offset into name data

    for (auto codeUnit : StringView(m_fontFamily).codeUnits())
        append16(codeUnit);
}

void SVGToOTFFontConverter::appendOS2Table()
{
    int16_t averageAdvance = s_outputUnitsPerEm;
    auto horizAdvX = parseHTMLInteger(m_fontElement.attributeWithoutSynchronization(SVGNames::horiz_adv_xAttr));
    if (!horizAdvX && m_missingGlyphElement)
        horizAdvX = parseHTMLInteger(m_missingGlyphElement->attributeWithoutSynchronization(SVGNames::horiz_adv_xAttr));
    if (horizAdvX)
        averageAdvance = clampTo<int16_t>(scaleUnitsPerEm(*horizAdvX));

    append16(2); // Version
    append16(clampTo<int16_t>(averageAdvance));
    append16(m_weight); // Weight class
    append16(5); // Width class
    append16(0); // Protected font
    // WebKit handles these superscripts and subscripts
    append16(0); // Subscript X Size
    append16(0); // Subscript Y Size
    append16(0); // Subscript X Offset
    append16(0); // Subscript Y Offset
    append16(0); // Superscript X Size
    append16(0); // Superscript Y Size
    append16(0); // Superscript X Offset
    append16(0); // Superscript Y Offset
    append16(0); // Strikeout width
    append16(0); // Strikeout Position
    append16(0); // No classification

    unsigned numPanoseBytes = 0;
    const unsigned panoseSize = 10;
    char panoseBytes[panoseSize];
    if (m_fontFaceElement) {
        auto segments = StringView(m_fontFaceElement->attributeWithoutSynchronization(SVGNames::panose_1Attr)).split(' ');
        for (auto segment : segments) {
            if (numPanoseBytes == panoseSize) {
                ++numPanoseBytes;
                break;
            }
            if (auto value = parseIntegerAllowingTrailingJunk<uint8_t>(segment))
                panoseBytes[numPanoseBytes++] = *value;
        }
    }
    if (numPanoseBytes != panoseSize)
        memset(panoseBytes, 0, panoseSize);
    m_result.append(panoseBytes, panoseSize);

    for (int i = 0; i < 4; ++i)
        append32(0); // "Bit assignments are pending. Set to 0"
    append32(0x544B4257); // Font Vendor. "WBKT"
    append16((m_weight >= 7 ? 1 << 5 : 0) | (m_italic ? 1 : 0)); // Font Patterns.
    append16(0); // First unicode index
    append16(0xFFFF); // Last unicode index
    append16(clampTo<int16_t>(m_ascent)); // Typographical ascender
    append16(clampTo<int16_t>(-m_descent)); // Typographical descender
    append16(clampTo<int16_t>(m_lineGap)); // Typographical line gap
    append16(clampTo<uint16_t>(m_ascent)); // Windows-specific ascent
    append16(clampTo<uint16_t>(m_descent)); // Windows-specific descent
    append32(0xFF10FC07); // Bitmask for supported codepages (Part 1). Report all pages as supported.
    append32(0x0000FFFF); // Bitmask for supported codepages (Part 2). Report all pages as supported.
    append16(clampTo<int16_t>(m_xHeight)); // x-height
    append16(clampTo<int16_t>(m_capHeight)); // Cap-height
    append16(0); // Default char
    append16(' '); // Break character
    append16(3); // Maximum context needed to perform font features
    append16(3); // Smallest optical point size
    append16(0xFFFF); // Largest optical point size
}

void SVGToOTFFontConverter::appendPOSTTable()
{
    append32(0x00030000); // Format. Printing is undefined
    append32(0); // Italic angle in degrees
    append16(0); // Underline position
    append16(0); // Underline thickness
    append32(0); // Monospaced
    append32(0); // "Minimum memory usage when a TrueType font is downloaded as a Type 42 font"
    append32(0); // "Maximum memory usage when a TrueType font is downloaded as a Type 42 font"
    append32(0); // "Minimum memory usage when a TrueType font is downloaded as a Type 1 font"
    append32(0); // "Maximum memory usage when a TrueType font is downloaded as a Type 1 font"
}

static bool isValidStringForCFF(const String& string)
{
    for (auto c : StringView(string).codeUnits()) {
        if (c < 33 || c > 126)
            return false;
    }
    return true;
}

void SVGToOTFFontConverter::appendValidCFFString(const String& string)
{
    ASSERT(isValidStringForCFF(string));
    for (auto c : StringView(string).codeUnits())
        m_result.append(c);
}

void SVGToOTFFontConverter::appendCFFTable()
{
    auto startingOffset = m_result.size();

    // Header
    m_result.append(1); // Major version
    m_result.append(0); // Minor version
    m_result.append(4); // Header size
    m_result.append(4); // Offsets within CFF table are 4 bytes long

    // Name INDEX
    String fontName;
    if (m_fontFaceElement) {
        // FIXME: fontFamily() here might not be quite what we want.
        String potentialFontName = m_fontFamily;
        if (isValidStringForCFF(potentialFontName))
            fontName = potentialFontName;
    }
    append16(1); // INDEX contains 1 element
    m_result.append(4); // Offsets in this INDEX are 4 bytes long
    append32(1); // 1-index offset of name data
    append32(fontName.length() + 1); // 1-index offset just past end of name data
    appendValidCFFString(fontName);

    String weight;
    if (m_fontFaceElement) {
        auto& potentialWeight = m_fontFaceElement->attributeWithoutSynchronization(SVGNames::font_weightAttr);
        if (isValidStringForCFF(potentialWeight))
            weight = potentialWeight;
    }

    bool hasWeight = !weight.isNull();

    const char operand32Bit = 29;
    const char fullNameKey = 2;
    const char familyNameKey = 3;
    const char weightKey = 4;
    const char fontBBoxKey = 5;
    const char charsetIndexKey = 15;
    const char charstringsIndexKey = 17;
    const char privateDictIndexKey = 18;
    const uint32_t userDefinedStringStartIndex = 391;
    const unsigned sizeOfTopIndex = 56 + (hasWeight ? 6 : 0);

    // Top DICT INDEX.
    append16(1); // INDEX contains 1 element
    m_result.append(4); // Offsets in this INDEX are 4 bytes long
    append32(1); // 1-index offset of DICT data
    append32(1 + sizeOfTopIndex); // 1-index offset just past end of DICT data

    // DICT information
#if ASSERT_ENABLED
    unsigned topDictStart = m_result.size();
#endif
    m_result.append(operand32Bit);
    append32(userDefinedStringStartIndex);
    m_result.append(fullNameKey);
    m_result.append(operand32Bit);
    append32(userDefinedStringStartIndex);
    m_result.append(familyNameKey);
    if (hasWeight) {
        m_result.append(operand32Bit);
        append32(userDefinedStringStartIndex + 2);
        m_result.append(weightKey);
    }
    m_result.append(operand32Bit);
    append32(clampTo<int32_t>(m_boundingBox.x()));
    m_result.append(operand32Bit);
    append32(clampTo<int32_t>(m_boundingBox.y()));
    m_result.append(operand32Bit);
    append32(clampTo<int32_t>(m_boundingBox.width()));
    m_result.append(operand32Bit);
    append32(clampTo<int32_t>(m_boundingBox.height()));
    m_result.append(fontBBoxKey);
    m_result.append(operand32Bit);
    unsigned charsetOffsetLocation = m_result.size();
    append32(0); // Offset of Charset info. Will be overwritten later.
    m_result.append(charsetIndexKey);
    m_result.append(operand32Bit);
    unsigned charstringsOffsetLocation = m_result.size();
    append32(0); // Offset of CharStrings INDEX. Will be overwritten later.
    m_result.append(charstringsIndexKey);
    m_result.append(operand32Bit);
    append32(0); // 0-sized private dict
    m_result.append(operand32Bit);
    append32(0); // no location for private dict
    m_result.append(privateDictIndexKey); // Private dict size and offset
    ASSERT(m_result.size() == topDictStart + sizeOfTopIndex);

    // String INDEX
    String unknownCharacter = "UnknownChar"_s;
    append16(2 + (hasWeight ? 1 : 0)); // Number of elements in INDEX
    m_result.append(4); // Offsets in this INDEX are 4 bytes long
    uint32_t offset = 1;
    append32(offset);
    offset += fontName.length();
    append32(offset);
    offset += unknownCharacter.length();
    append32(offset);
    if (hasWeight) {
        offset += weight.length();
        append32(offset);
    }
    appendValidCFFString(fontName);
    appendValidCFFString(unknownCharacter);
    appendValidCFFString(weight);

    append16(0); // Empty subroutine INDEX

    // Charset info
    overwrite32(charsetOffsetLocation, m_result.size() - startingOffset);
    m_result.append(0);
    for (Glyph i = 1; i < m_glyphs.size(); ++i)
        append16(userDefinedStringStartIndex + 1);

    // CharStrings INDEX
    overwrite32(charstringsOffsetLocation, m_result.size() - startingOffset);
    append16(m_glyphs.size());
    m_result.append(4); // Offsets in this INDEX are 4 bytes long
    offset = 1;
    append32(offset);
    for (auto& glyph : m_glyphs) {
        offset += glyph.charString.size();
        append32(offset);
    }
    for (auto& glyph : m_glyphs)
        m_result.appendVector(glyph.charString);
}

Glyph SVGToOTFFontConverter::firstGlyph(const Vector<Glyph, 1>& v, UChar32 codepoint) const
{
#if !ASSERT_ENABLED
    UNUSED_PARAM(codepoint);
#endif
    ASSERT(!v.isEmpty());
    if (v.isEmpty())
        return 0;
#if ASSERT_ENABLED
    auto codePoints = StringView(m_glyphs[v[0]].codepoints).codePoints();
    auto codePointsIterator = codePoints.begin();
    ASSERT(codePointsIterator != codePoints.end());
    ASSERT(codepoint == *codePointsIterator);
#endif
    return v[0];
}

void SVGToOTFFontConverter::appendLigatureSubtable(size_t subtableRecordLocation)
{
    typedef std::pair<Vector<Glyph, 3>, Glyph> LigaturePair;
    Vector<LigaturePair> ligaturePairs;
    for (Glyph glyphIndex = 0; glyphIndex < m_glyphs.size(); ++glyphIndex) {
        ligaturePairs.append(LigaturePair(Vector<Glyph, 3>(), glyphIndex));
        Vector<Glyph, 3>& ligatureGlyphs = ligaturePairs.last().first;
        auto codePoints = StringView(m_glyphs[glyphIndex].codepoints).codePoints();
        // FIXME: https://bugs.webkit.org/show_bug.cgi?id=138592 This needs to be done in codepoint space, not glyph space
        for (auto codePoint : codePoints)
            ligatureGlyphs.append(firstGlyph(glyphsForCodepoint(codePoint), codePoint));
        if (ligatureGlyphs.size() < 2)
            ligaturePairs.removeLast();
    }
    if (ligaturePairs.size() > std::numeric_limits<uint16_t>::max())
        ligaturePairs.clear();
    std::sort(ligaturePairs.begin(), ligaturePairs.end(), [](auto& lhs, auto& rhs) {
        return lhs.first[0] < rhs.first[0];
    });
    Vector<size_t> overlappingFirstGlyphSegmentLengths;
    if (!ligaturePairs.isEmpty()) {
        Glyph previousFirstGlyph = ligaturePairs[0].first[0];
        size_t segmentStart = 0;
        for (size_t i = 0; i < ligaturePairs.size(); ++i) {
            auto& ligaturePair = ligaturePairs[i];
            if (ligaturePair.first[0] != previousFirstGlyph) {
                overlappingFirstGlyphSegmentLengths.append(i - segmentStart);
                segmentStart = i;
                previousFirstGlyph = ligaturePairs[0].first[0];
            }
        }
        overlappingFirstGlyphSegmentLengths.append(ligaturePairs.size() - segmentStart);
    }

    overwrite16(subtableRecordLocation + 6, m_result.size() - subtableRecordLocation);
    auto subtableLocation = m_result.size();
    append16(1); // Format 1
    append16(0); // Placeholder for offset to coverage table, relative to beginning of substitution table
    append16(ligaturePairs.size()); // Number of LigatureSet tables
    grow(overlappingFirstGlyphSegmentLengths.size() * 2); // Placeholder for offset to LigatureSet table

    Vector<size_t> ligatureSetTableLocations;
    for (size_t i = 0; i < overlappingFirstGlyphSegmentLengths.size(); ++i) {
        overwrite16(subtableLocation + 6 + 2 * i, m_result.size() - subtableLocation);
        ligatureSetTableLocations.append(m_result.size());
        append16(overlappingFirstGlyphSegmentLengths[i]); // LigatureCount
        grow(overlappingFirstGlyphSegmentLengths[i] * 2); // Placeholder for offset to Ligature table
    }
    ASSERT(ligatureSetTableLocations.size() == overlappingFirstGlyphSegmentLengths.size());

    size_t ligaturePairIndex = 0;
    for (size_t i = 0; i < overlappingFirstGlyphSegmentLengths.size(); ++i) {
        for (size_t j = 0; j < overlappingFirstGlyphSegmentLengths[i]; ++j) {
            overwrite16(ligatureSetTableLocations[i] + 2 + 2 * j, m_result.size() - ligatureSetTableLocations[i]);
            auto& ligaturePair = ligaturePairs[ligaturePairIndex];
            append16(ligaturePair.second);
            append16(ligaturePair.first.size());
            for (size_t k = 1; k < ligaturePair.first.size(); ++k)
                append16(ligaturePair.first[k]);
            ++ligaturePairIndex;
        }
    }
    ASSERT(ligaturePairIndex == ligaturePairs.size());

    // Coverage table
    overwrite16(subtableLocation + 2, m_result.size() - subtableLocation);
    append16(1); // CoverageFormat
    append16(ligatureSetTableLocations.size()); // GlyphCount
    ligaturePairIndex = 0;
    for (auto segmentLength : overlappingFirstGlyphSegmentLengths) {
        auto& ligaturePair = ligaturePairs[ligaturePairIndex];
        ASSERT(ligaturePair.first.size() > 1);
        append16(ligaturePair.first[0]);
        ligaturePairIndex += segmentLength;
    }
}

void SVGToOTFFontConverter::appendArabicReplacementSubtable(size_t subtableRecordLocation, ASCIILiteral arabicForm)
{
    Vector<std::pair<Glyph, Glyph>> arabicFinalReplacements;
    for (auto& pair : m_codepointsToIndicesMap) {
        for (auto glyphIndex : pair.value) {
            auto& glyph = m_glyphs[glyphIndex];
            if (glyph.glyphElement && equalIgnoringASCIICase(glyph.glyphElement->attributeWithoutSynchronization(SVGNames::arabic_formAttr), arabicForm))
                arabicFinalReplacements.append(std::make_pair(pair.value[0], glyphIndex));
        }
    }
    if (arabicFinalReplacements.size() > std::numeric_limits<uint16_t>::max())
        arabicFinalReplacements.clear();

    overwrite16(subtableRecordLocation + 6, m_result.size() - subtableRecordLocation);
    auto subtableLocation = m_result.size();
    append16(2); // Format 2
    Placeholder toCoverageTable = placeholder(subtableLocation);
    append16(arabicFinalReplacements.size()); // GlyphCount
    for (auto& pair : arabicFinalReplacements)
        append16(pair.second);

    toCoverageTable.populate();
    append16(1); // CoverageFormat
    append16(arabicFinalReplacements.size()); // GlyphCount
    for (auto& pair : arabicFinalReplacements)
        append16(pair.first);
}

void SVGToOTFFontConverter::appendScriptSubtable(unsigned featureCount)
{
    auto dfltScriptTableLocation = m_result.size();
    append16(0); // Placeholder for offset of default language system table, relative to beginning of Script table
    append16(0); // Number of following language system tables

    // LangSys table
    overwrite16(dfltScriptTableLocation, m_result.size() - dfltScriptTableLocation);
    append16(0); // LookupOrder "= NULL ... reserved"
    append16(0xFFFF); // No features are required
    append16(featureCount); // Number of FeatureIndex values
    for (uint16_t i = 0; i < featureCount; ++i)
        append16(m_featureCountGSUB++); // Features indices
}

void SVGToOTFFontConverter::appendGSUBTable()
{
    auto tableLocation = m_result.size();
    auto headerSize = 10;

    append32(0x00010000); // Version
    append16(headerSize); // Offset to ScriptList
    Placeholder toFeatureList = placeholder(tableLocation);
    Placeholder toLookupList = placeholder(tableLocation);
    ASSERT(tableLocation + headerSize == m_result.size());

    // ScriptList
    auto scriptListLocation = m_result.size();
    append16(2); // Number of ScriptRecords
    append32BitCode("DFLT");
    append16(0); // Placeholder for offset of Script table, relative to beginning of ScriptList
    append32BitCode("arab");
    append16(0); // Placeholder for offset of Script table, relative to beginning of ScriptList

    overwrite16(scriptListLocation + 6, m_result.size() - scriptListLocation);
    appendScriptSubtable(1);
    overwrite16(scriptListLocation + 12, m_result.size() - scriptListLocation);
    appendScriptSubtable(4);

    const unsigned featureCount = 5;

    // FeatureList
    toFeatureList.populate();
    auto featureListLocation = m_result.size();
    size_t featureListSize = 2 + 6 * featureCount;
    size_t featureTableSize = 6;
    append16(featureCount); // FeatureCount
    append32BitCode("liga");
    append16(featureListSize + featureTableSize * 0); // Offset of feature table, relative to beginning of FeatureList table
    append32BitCode("fina");
    append16(featureListSize + featureTableSize * 1); // Offset of feature table, relative to beginning of FeatureList table
    append32BitCode("medi");
    append16(featureListSize + featureTableSize * 2); // Offset of feature table, relative to beginning of FeatureList table
    append32BitCode("init");
    append16(featureListSize + featureTableSize * 3); // Offset of feature table, relative to beginning of FeatureList table
    append32BitCode("rlig");
    append16(featureListSize + featureTableSize * 4); // Offset of feature table, relative to beginning of FeatureList table
    ASSERT_UNUSED(featureListLocation, featureListLocation + featureListSize == m_result.size());

    for (unsigned i = 0; i < featureCount; ++i) {
        auto featureTableStart = m_result.size();
        append16(0); // FeatureParams "= NULL ... reserved"
        append16(1); // LookupCount
        append16(i); // LookupListIndex
        ASSERT_UNUSED(featureTableStart, featureTableStart + featureTableSize == m_result.size());
    }

    // LookupList
    toLookupList.populate();
    auto lookupListLocation = m_result.size();
    append16(featureCount); // LookupCount
    for (unsigned i = 0; i < featureCount; ++i)
        append16(0); // Placeholder for offset to feature table, relative to beginning of LookupList
    size_t subtableRecordLocations[featureCount];
    for (unsigned i = 0; i < featureCount; ++i) {
        subtableRecordLocations[i] = m_result.size();
        overwrite16(lookupListLocation + 2 + 2 * i, m_result.size() - lookupListLocation);
        switch (i) {
        case 4:
            append16(3); // Type 3: "Replace one glyph with one of many glyphs"
            break;
        case 0:
            append16(4); // Type 4: "Replace multiple glyphs with one glyph"
            break;
        default:
            append16(1); // Type 1: "Replace one glyph with one glyph"
            break;
        }
        append16(0); // LookupFlag
        append16(1); // SubTableCount
        append16(0); // Placeholder for offset to subtable, relative to beginning of Lookup table
    }

    appendLigatureSubtable(subtableRecordLocations[0]);
    appendArabicReplacementSubtable(subtableRecordLocations[1], "terminal"_s);
    appendArabicReplacementSubtable(subtableRecordLocations[2], "medial"_s);
    appendArabicReplacementSubtable(subtableRecordLocations[3], "initial"_s);

    // Manually append empty "rlig" subtable
    overwrite16(subtableRecordLocations[4] + 6, m_result.size() - subtableRecordLocations[4]);
    append16(1); // Format 1
    append16(6); // offset to coverage table, relative to beginning of substitution table
    append16(0); // AlternateSetCount
    append16(1); // CoverageFormat
    append16(0); // GlyphCount
}

void SVGToOTFFontConverter::appendVORGTable()
{
    append16(1); // Major version
    append16(0); // Minor version

    auto vertOriginY = parseHTMLInteger(m_fontElement.attributeWithoutSynchronization(SVGNames::vert_origin_yAttr));
    if (!vertOriginY && m_missingGlyphElement)
        vertOriginY = parseHTMLInteger(m_missingGlyphElement->attributeWithoutSynchronization(SVGNames::vert_origin_yAttr));
    append16(clampTo<int16_t>(scaleUnitsPerEm(vertOriginY.value_or(0))));

    auto tableSizeOffset = m_result.size();
    append16(0); // Place to write table size.
    for (Glyph i = 0; i < m_glyphs.size(); ++i) {
        if (auto* glyph = m_glyphs[i].glyphElement) {
            if (auto verticalOriginY = parseHTMLInteger(glyph->attributeWithoutSynchronization(SVGNames::vert_origin_yAttr))) {
                append16(i);
                append16(clampTo<int16_t>(scaleUnitsPerEm(*verticalOriginY)));
            }
        }
    }
    ASSERT(!((m_result.size() - tableSizeOffset - 2) % 4));
    overwrite16(tableSizeOffset, (m_result.size() - tableSizeOffset - 2) / 4);
}

void SVGToOTFFontConverter::appendVHEATable()
{
    float height = m_ascent + m_descent;
    append32(0x00011000); // Version
    append16(clampTo<int16_t>(height / 2)); // Vertical typographic ascender (vertical baseline to the right)
    append16(clampTo<int16_t>(-static_cast<int>(height / 2))); // Vertical typographic descender
    append16(clampTo<int16_t>(s_outputUnitsPerEm / 10)); // Vertical typographic line gap
    // FIXME: m_unitsPerEm is almost certainly not correct
    append16(clampTo<int16_t>(m_advanceHeightMax));
    append16(clampTo<int16_t>(s_outputUnitsPerEm - m_boundingBox.maxY())); // Minimum top side bearing
    append16(clampTo<int16_t>(m_boundingBox.y())); // Minimum bottom side bearing
    append16(clampTo<int16_t>(s_outputUnitsPerEm - m_boundingBox.y())); // Y maximum extent
    // Since WebKit draws the caret and ignores the following values, it doesn't matter what we set them to.
    append16(1); // Vertical caret
    append16(0); // Vertical caret
    append16(0); // "Set value to 0 for non-slanted fonts"
    append32(0); // Reserved
    append32(0); // Reserved
    append16(0); // "Set to 0"
    append16(m_glyphs.size()); // Number of advance heights in VMTX table
}

void SVGToOTFFontConverter::appendVMTXTable()
{
    for (auto& glyph : m_glyphs) {
        append16(clampTo<uint16_t>(glyph.verticalAdvance));
        append16(clampTo<int16_t>(s_outputUnitsPerEm - glyph.boundingBox.maxY())); // top side bearing
    }
}

static String codepointToString(UChar32 codepoint)
{
    UChar buffer[2];
    uint8_t length = 0;
    UBool error = false;
    U16_APPEND(buffer, length, 2, codepoint, error);
    return error ? String() : String(buffer, length);
}

Vector<Glyph, 1> SVGToOTFFontConverter::glyphsForCodepoint(UChar32 codepoint) const
{
    return m_codepointsToIndicesMap.get(codepointToString(codepoint));
}

void SVGToOTFFontConverter::addCodepointRanges(const UnicodeRanges& unicodeRanges, HashSet<Glyph>& glyphSet) const
{
    for (auto& unicodeRange : unicodeRanges) {
        for (auto codepoint = unicodeRange.first; codepoint <= unicodeRange.second; ++codepoint) {
            for (auto index : glyphsForCodepoint(codepoint))
                glyphSet.add(index);
        }
    }
}

void SVGToOTFFontConverter::addCodepoints(const HashSet<String>& codepoints, HashSet<Glyph>& glyphSet) const
{
    for (auto& codepointString : codepoints) {
        for (auto index : m_codepointsToIndicesMap.get(codepointString))
            glyphSet.add(index);
    }
}

void SVGToOTFFontConverter::addGlyphNames(const HashSet<String>& glyphNames, HashSet<Glyph>& glyphSet) const
{
    for (auto& glyphName : glyphNames) {
        if (Glyph glyph = m_glyphNameToIndexMap.get(glyphName))
            glyphSet.add(glyph);
    }
}

void SVGToOTFFontConverter::addKerningPair(Vector<KerningData>& data, SVGKerningPair&& kerningPair) const
{
    HashSet<Glyph> glyphSet1;
    HashSet<Glyph> glyphSet2;

    addCodepointRanges(kerningPair.unicodeRange1, glyphSet1);
    addCodepointRanges(kerningPair.unicodeRange2, glyphSet2);
    addGlyphNames(kerningPair.glyphName1, glyphSet1);
    addGlyphNames(kerningPair.glyphName2, glyphSet2);
    addCodepoints(kerningPair.unicodeName1, glyphSet1);
    addCodepoints(kerningPair.unicodeName2, glyphSet2);

    // FIXME: Use table format 2 so we don't have to append each of these one by one.
    for (auto& glyph1 : glyphSet1) {
        for (auto& glyph2 : glyphSet2)
            data.append(KerningData(glyph1, glyph2, clampTo<int16_t>(-scaleUnitsPerEm(kerningPair.kerning))));
    }
}

template<typename T> inline size_t SVGToOTFFontConverter::appendKERNSubtable(std::optional<SVGKerningPair> (T::*buildKerningPair)() const, uint16_t coverage)
{
    Vector<KerningData> kerningData;
    for (auto& element : childrenOfType<T>(m_fontElement)) {
        if (auto kerningPair = (element.*buildKerningPair)())
            addKerningPair(kerningData, WTFMove(*kerningPair));
    }
    return finishAppendingKERNSubtable(WTFMove(kerningData), coverage);
}

size_t SVGToOTFFontConverter::finishAppendingKERNSubtable(Vector<KerningData> kerningData, uint16_t coverage)
{
    std::sort(kerningData.begin(), kerningData.end(), [](auto& a, auto& b) {
        return a.glyph1 < b.glyph1 || (a.glyph1 == b.glyph1 && a.glyph2 < b.glyph2);
    });

    size_t sizeOfKerningDataTable = 14 + 6 * kerningData.size();
    if (sizeOfKerningDataTable > std::numeric_limits<uint16_t>::max()) {
        kerningData.clear();
        sizeOfKerningDataTable = 14;
    }

    append16(0); // Version of subtable
    append16(sizeOfKerningDataTable); // Length of this subtable
    append16(coverage); // Table coverage bitfield

    uint16_t roundedNumKerningPairs = roundDownToPowerOfTwo(kerningData.size());

    append16(kerningData.size());
    append16(roundedNumKerningPairs * 6); // searchRange: "The largest power of two less than or equal to the value of nPairs, multiplied by the size in bytes of an entry in the table."
    append16(integralLog2(roundedNumKerningPairs)); // entrySelector: "log2 of the largest power of two less than or equal to the value of nPairs."
    append16((kerningData.size() - roundedNumKerningPairs) * 6); // rangeShift: "The value of nPairs minus the largest power of two less than or equal to nPairs,
                                                                        // and then multiplied by the size in bytes of an entry in the table."

    for (auto& kerningDataElement : kerningData) {
        append16(kerningDataElement.glyph1);
        append16(kerningDataElement.glyph2);
        append16(kerningDataElement.adjustment);
    }

    return sizeOfKerningDataTable;
}

void SVGToOTFFontConverter::appendKERNTable()
{
    append16(0); // Version
    append16(2); // Number of subtables

#if ASSERT_ENABLED
    auto subtablesOffset = m_result.size();
#endif

    size_t sizeOfHorizontalSubtable = appendKERNSubtable<SVGHKernElement>(&SVGHKernElement::buildHorizontalKerningPair, 1);
    ASSERT_UNUSED(sizeOfHorizontalSubtable, subtablesOffset + sizeOfHorizontalSubtable == m_result.size());
    size_t sizeOfVerticalSubtable = appendKERNSubtable<SVGVKernElement>(&SVGVKernElement::buildVerticalKerningPair, 0);
    ASSERT_UNUSED(sizeOfVerticalSubtable, subtablesOffset + sizeOfHorizontalSubtable + sizeOfVerticalSubtable == m_result.size());
}

template <typename V>
static void writeCFFEncodedNumber(V& vector, float number)
{
    vector.append(0xFF);
    // Convert to 16.16 fixed-point
    append32(vector, clampTo<int32_t>(number * 0x10000));
}

static const char rLineTo = 0x05;
static const char rrCurveTo = 0x08;
static const char endChar = 0x0e;
static const char rMoveTo = 0x15;

class CFFBuilder final : public SVGPathConsumer {
public:
    CFFBuilder(Vector<char>& cffData, float width, FloatPoint origin, float unitsPerEmScalar)
        : m_cffData(cffData)
        , m_unitsPerEmScalar(unitsPerEmScalar)
    {
        writeCFFEncodedNumber(m_cffData, std::floor(width)); // hmtx table can't encode fractional FUnit values, and the CFF table needs to agree with hmtx.
        writeCFFEncodedNumber(m_cffData, origin.x());
        writeCFFEncodedNumber(m_cffData, origin.y());
        m_cffData.append(rMoveTo);
    }

    std::optional<FloatRect> boundingBox() const
    {
        return m_boundingBox;
    }

private:
    void updateBoundingBox(FloatPoint point)
    {
        if (!m_boundingBox) {
            m_boundingBox = FloatRect(point, FloatSize());
            return;
        }
        m_boundingBox.value().extend(point);
    }

    void writePoint(FloatPoint destination)
    {
        updateBoundingBox(destination);

        FloatSize delta = destination - m_current;
        writeCFFEncodedNumber(m_cffData, delta.width());
        writeCFFEncodedNumber(m_cffData, delta.height());

        m_current = destination;
    }

    void moveTo(const FloatPoint& targetPoint, bool closed, PathCoordinateMode mode) final
    {
        if (closed && !m_cffData.isEmpty())
            closePath();

        FloatPoint scaledTargetPoint = FloatPoint(targetPoint.x() * m_unitsPerEmScalar, targetPoint.y() * m_unitsPerEmScalar);
        FloatPoint destination = mode == AbsoluteCoordinates ? scaledTargetPoint : m_current + scaledTargetPoint;

        writePoint(destination);
        m_cffData.append(rMoveTo);

        m_startingPoint = m_current;
    }

    void unscaledLineTo(const FloatPoint& targetPoint)
    {
        writePoint(targetPoint);
        m_cffData.append(rLineTo);
    }

    void lineTo(const FloatPoint& targetPoint, PathCoordinateMode mode) final
    {
        FloatPoint scaledTargetPoint = FloatPoint(targetPoint.x() * m_unitsPerEmScalar, targetPoint.y() * m_unitsPerEmScalar);
        FloatPoint destination = mode == AbsoluteCoordinates ? scaledTargetPoint : m_current + scaledTargetPoint;

        unscaledLineTo(destination);
    }

    void curveToCubic(const FloatPoint& point1, const FloatPoint& point2, const FloatPoint& point3, PathCoordinateMode mode) final
    {
        FloatPoint scaledPoint1 = FloatPoint(point1.x() * m_unitsPerEmScalar, point1.y() * m_unitsPerEmScalar);
        FloatPoint scaledPoint2 = FloatPoint(point2.x() * m_unitsPerEmScalar, point2.y() * m_unitsPerEmScalar);
        FloatPoint scaledPoint3 = FloatPoint(point3.x() * m_unitsPerEmScalar, point3.y() * m_unitsPerEmScalar);

        if (mode == RelativeCoordinates) {
            scaledPoint1 += m_current;
            scaledPoint2 += m_current;
            scaledPoint3 += m_current;
        }

        writePoint(scaledPoint1);
        writePoint(scaledPoint2);
        writePoint(scaledPoint3);
        m_cffData.append(rrCurveTo);
    }

    void closePath() final
    {
        if (m_current != m_startingPoint)
            unscaledLineTo(m_startingPoint);
    }

    void incrementPathSegmentCount() final { }
    bool continueConsuming() final { return true; }

    void lineToHorizontal(float, PathCoordinateMode) final { ASSERT_NOT_REACHED(); }
    void lineToVertical(float, PathCoordinateMode) final { ASSERT_NOT_REACHED(); }
    void curveToCubicSmooth(const FloatPoint&, const FloatPoint&, PathCoordinateMode) final { ASSERT_NOT_REACHED(); }
    void curveToQuadratic(const FloatPoint&, const FloatPoint&, PathCoordinateMode) final { ASSERT_NOT_REACHED(); }
    void curveToQuadraticSmooth(const FloatPoint&, PathCoordinateMode) final { ASSERT_NOT_REACHED(); }
    void arcTo(float, float, float, bool, bool, const FloatPoint&, PathCoordinateMode) final { ASSERT_NOT_REACHED(); }

    Vector<char>& m_cffData;
    FloatPoint m_startingPoint;
    FloatPoint m_current;
    std::optional<FloatRect> m_boundingBox;
    float m_unitsPerEmScalar;
};

Vector<char> SVGToOTFFontConverter::transcodeGlyphPaths(float width, const SVGElement& glyphOrMissingGlyphElement, std::optional<FloatRect>& boundingBox) const
{
    Vector<char> result;

    auto& dAttribute = glyphOrMissingGlyphElement.attributeWithoutSynchronization(SVGNames::dAttr);
    if (dAttribute.isEmpty()) {
        writeCFFEncodedNumber(result, width);
        writeCFFEncodedNumber(result, 0);
        writeCFFEncodedNumber(result, 0);
        result.append(rMoveTo);
        result.append(endChar);
        return result;
    }

    // FIXME: If we are vertical, use vert_origin_x and vert_origin_y
    bool ok;
    float horizontalOriginX = scaleUnitsPerEm(glyphOrMissingGlyphElement.attributeWithoutSynchronization(SVGNames::horiz_origin_xAttr).toFloat(&ok));
    if (!ok && m_fontFaceElement)
        horizontalOriginX = scaleUnitsPerEm(m_fontFaceElement->horizontalOriginX());
    float horizontalOriginY = scaleUnitsPerEm(glyphOrMissingGlyphElement.attributeWithoutSynchronization(SVGNames::horiz_origin_yAttr).toFloat(&ok));
    if (!ok && m_fontFaceElement)
        horizontalOriginY = scaleUnitsPerEm(m_fontFaceElement->horizontalOriginY());

    CFFBuilder builder(result, width, FloatPoint(horizontalOriginX, horizontalOriginY), static_cast<float>(s_outputUnitsPerEm) / m_inputUnitsPerEm);
    SVGPathStringSource source(dAttribute);

    ok = SVGPathParser::parse(source, builder);
    if (!ok)
        return { };

    boundingBox = builder.boundingBox();

    result.append(endChar);
    return result;
}

void SVGToOTFFontConverter::processGlyphElement(const SVGElement& glyphOrMissingGlyphElement, const SVGGlyphElement* glyphElement, float defaultHorizontalAdvance, float defaultVerticalAdvance, const String& codepoints, std::optional<FloatRect>& boundingBox)
{
    bool ok;
    float horizontalAdvance = scaleUnitsPerEm(glyphOrMissingGlyphElement.attributeWithoutSynchronization(SVGNames::horiz_adv_xAttr).toFloat(&ok));
    if (!ok)
        horizontalAdvance = defaultHorizontalAdvance;
    m_advanceWidthMax = std::max(m_advanceWidthMax, horizontalAdvance);
    float verticalAdvance = scaleUnitsPerEm(glyphOrMissingGlyphElement.attributeWithoutSynchronization(SVGNames::vert_adv_yAttr).toFloat(&ok));
    if (!ok)
        verticalAdvance = defaultVerticalAdvance;
    m_advanceHeightMax = std::max(m_advanceHeightMax, verticalAdvance);

    std::optional<FloatRect> glyphBoundingBox;
    auto path = transcodeGlyphPaths(horizontalAdvance, glyphOrMissingGlyphElement, glyphBoundingBox);
    if (!path.size()) {
        // It's better to use a fallback font rather than use a font without all its glyphs.
        m_error = true;
    }
    if (!boundingBox)
        boundingBox = glyphBoundingBox;
    else if (glyphBoundingBox)
        boundingBox.value().unite(glyphBoundingBox.value());
    if (glyphBoundingBox)
        m_minRightSideBearing = std::min(m_minRightSideBearing, horizontalAdvance - glyphBoundingBox.value().maxX());

    m_glyphs.append(GlyphData(WTFMove(path), glyphElement, horizontalAdvance, verticalAdvance, valueOrDefault(glyphBoundingBox), codepoints));
}

void SVGToOTFFontConverter::appendLigatureGlyphs()
{
    HashSet<UChar32> ligatureCodepoints;
    HashSet<UChar32> nonLigatureCodepoints;
    for (auto& glyph : m_glyphs) {
        auto codePoints = StringView(glyph.codepoints).codePoints();
        auto codePointsIterator = codePoints.begin();
        if (codePointsIterator == codePoints.end())
            continue;
        UChar32 codepoint = *codePointsIterator;
        ++codePointsIterator;
        if (codePointsIterator == codePoints.end())
            nonLigatureCodepoints.add(codepoint);
        else {
            ligatureCodepoints.add(codepoint);
            for (; codePointsIterator != codePoints.end(); ++codePointsIterator)
                ligatureCodepoints.add(*codePointsIterator);
        }
    }

    for (auto codepoint : nonLigatureCodepoints)
        ligatureCodepoints.remove(codepoint);
    for (auto codepoint : ligatureCodepoints) {
        auto codepoints = codepointToString(codepoint);
        if (!codepoints.isNull())
            m_glyphs.append(GlyphData(Vector<char>(m_emptyGlyphCharString), nullptr, s_outputUnitsPerEm, s_outputUnitsPerEm, FloatRect(), codepoints));
    }
}

bool SVGToOTFFontConverter::compareCodepointsLexicographically(const GlyphData& data1, const GlyphData& data2)
{
    auto codePoints1 = StringView(data1.codepoints).codePoints();
    auto codePoints2 = StringView(data2.codepoints).codePoints();
    auto iterator1 = codePoints1.begin();
    auto iterator2 = codePoints2.begin();
    while (iterator1 != codePoints1.end() && iterator2 != codePoints2.end()) {
        UChar32 codepoint1, codepoint2;
        codepoint1 = *iterator1;
        codepoint2 = *iterator2;

        if (codepoint1 < codepoint2)
            return true;
        if (codepoint1 > codepoint2)
            return false;

        ++iterator1;
        ++iterator2;
    }

    if (iterator1 == codePoints1.end() && iterator2 == codePoints2.end()) {
        bool firstIsIsolated = data1.glyphElement && equalLettersIgnoringASCIICase(data1.glyphElement->attributeWithoutSynchronization(SVGNames::arabic_formAttr), "isolated"_s);
        bool secondIsIsolated = data2.glyphElement && equalLettersIgnoringASCIICase(data2.glyphElement->attributeWithoutSynchronization(SVGNames::arabic_formAttr), "isolated"_s);
        return firstIsIsolated && !secondIsIsolated;
    }
    return iterator1 == codePoints1.end();
}

static void populateEmptyGlyphCharString(Vector<char, 17>& o, unsigned unitsPerEm)
{
    writeCFFEncodedNumber(o, unitsPerEm);
    writeCFFEncodedNumber(o, 0);
    writeCFFEncodedNumber(o, 0);
    o.append(rMoveTo);
    o.append(endChar);
}

SVGToOTFFontConverter::SVGToOTFFontConverter(const SVGFontElement& fontElement)
    : m_fontElement(fontElement)
    , m_fontFaceElement(childrenOfType<SVGFontFaceElement>(m_fontElement).first())
    , m_missingGlyphElement(childrenOfType<SVGMissingGlyphElement>(m_fontElement).first())
    , m_advanceWidthMax(0)
    , m_advanceHeightMax(0)
    , m_minRightSideBearing(std::numeric_limits<float>::max())
    , m_featureCountGSUB(0)
    , m_tablesAppendedCount(0)
    , m_weight(5)
    , m_italic(false)
{
    if (!m_fontFaceElement) {
        m_inputUnitsPerEm = 1;
        m_ascent = s_outputUnitsPerEm;
        m_descent = 1;
        m_xHeight = s_outputUnitsPerEm;
        m_capHeight = m_ascent;
    } else {
        m_inputUnitsPerEm = m_fontFaceElement->unitsPerEm();
        m_ascent = scaleUnitsPerEm(m_fontFaceElement->ascent());
        m_descent = scaleUnitsPerEm(m_fontFaceElement->descent());
        m_xHeight = scaleUnitsPerEm(m_fontFaceElement->xHeight());
        m_capHeight = scaleUnitsPerEm(m_fontFaceElement->capHeight());

        // Some platforms, including OS X, use 0 ascent and descent to mean that the platform should synthesize
        // a value based on a heuristic. However, SVG fonts can legitimately have 0 for ascent or descent.
        // Specifing a single FUnit gets us as close to 0 as we can without triggering the synthesis.
        if (!m_ascent)
            m_ascent = 1;
        if (!m_descent)
            m_descent = 1;
    }

    float defaultHorizontalAdvance = m_fontFaceElement ? scaleUnitsPerEm(m_fontFaceElement->horizontalAdvanceX()) : 0;
    float defaultVerticalAdvance = m_fontFaceElement ? scaleUnitsPerEm(m_fontFaceElement->verticalAdvanceY()) : 0;

    m_lineGap = s_outputUnitsPerEm / 10;

    populateEmptyGlyphCharString(m_emptyGlyphCharString, s_outputUnitsPerEm);

    std::optional<FloatRect> boundingBox;
    if (m_missingGlyphElement)
        processGlyphElement(*m_missingGlyphElement, nullptr, defaultHorizontalAdvance, defaultVerticalAdvance, String(), boundingBox);
    else {
        m_glyphs.append(GlyphData(Vector<char>(m_emptyGlyphCharString), nullptr, s_outputUnitsPerEm, s_outputUnitsPerEm, FloatRect(), String()));
        boundingBox = FloatRect(0, 0, s_outputUnitsPerEm, s_outputUnitsPerEm);
    }

    for (auto& glyphElement : childrenOfType<SVGGlyphElement>(m_fontElement)) {
        auto& unicodeAttribute = glyphElement.attributeWithoutSynchronization(SVGNames::unicodeAttr);
        if (!unicodeAttribute.isEmpty()) // If we can never actually trigger this glyph, ignore it completely
            processGlyphElement(glyphElement, &glyphElement, defaultHorizontalAdvance, defaultVerticalAdvance, unicodeAttribute, boundingBox);
    }

    m_boundingBox = valueOrDefault(boundingBox);

    appendLigatureGlyphs();

    if (m_glyphs.size() > std::numeric_limits<Glyph>::max()) {
        m_glyphs.clear();
        return;
    }

    std::sort(m_glyphs.begin(), m_glyphs.end(), &compareCodepointsLexicographically);

    for (Glyph i = 0; i < m_glyphs.size(); ++i) {
        GlyphData& glyph = m_glyphs[i];
        if (glyph.glyphElement) {
            auto& glyphName = glyph.glyphElement->attributeWithoutSynchronization(SVGNames::glyph_nameAttr);
            if (!glyphName.isNull())
                m_glyphNameToIndexMap.add(glyphName, i);
        }
        if (m_codepointsToIndicesMap.isValidKey(glyph.codepoints)) {
            auto& glyphVector = m_codepointsToIndicesMap.add(glyph.codepoints, Vector<Glyph>()).iterator->value;
            // Prefer isolated arabic forms
            if (glyph.glyphElement && equalLettersIgnoringASCIICase(glyph.glyphElement->attributeWithoutSynchronization(SVGNames::arabic_formAttr), "isolated"_s))
                glyphVector.insert(0, i);
            else
                glyphVector.append(i);
        }
    }

    // FIXME: Handle commas.
    if (m_fontFaceElement) {
        for (auto segment : StringView(m_fontFaceElement->attributeWithoutSynchronization(SVGNames::font_weightAttr)).split(' ')) {
            if (equalLettersIgnoringASCIICase(segment, "bold"_s)) {
                m_weight = 7;
                break;
            }
            if (auto value = parseIntegerAllowingTrailingJunk<uint16_t>(segment); value && *value < 1000) {
                m_weight = (*value + 50) / 100;
                break;
            }
        }
        for (auto segment : StringView(m_fontFaceElement->attributeWithoutSynchronization(SVGNames::font_styleAttr)).split(' ')) {
            if (equalLettersIgnoringASCIICase(segment, "italic"_s) || equalLettersIgnoringASCIICase(segment, "oblique"_s)) {
                m_italic = true;
                break;
            }
        }
    }

    if (m_fontFaceElement)
        m_fontFamily = m_fontFaceElement->fontFamily();
}

static inline bool isFourByteAligned(size_t x)
{
    return !(x & 3);
}

uint32_t SVGToOTFFontConverter::calculateChecksum(size_t startingOffset, size_t endingOffset) const
{
    ASSERT(isFourByteAligned(endingOffset - startingOffset));
    uint32_t sum = 0;
    for (size_t offset = startingOffset; offset < endingOffset; offset += 4) {
        sum += static_cast<unsigned char>(m_result[offset + 3])
            | (static_cast<unsigned char>(m_result[offset + 2]) << 8)
            | (static_cast<unsigned char>(m_result[offset + 1]) << 16)
            | (static_cast<unsigned char>(m_result[offset]) << 24);
    }
    return sum;
}

void SVGToOTFFontConverter::appendTable(const char identifier[4], FontAppendingFunction appendingFunction)
{
    size_t offset = m_result.size();
    ASSERT(isFourByteAligned(offset));
    (this->*appendingFunction)();
    size_t unpaddedSize = m_result.size() - offset;
    while (!isFourByteAligned(m_result.size()))
        m_result.append(0);
    ASSERT(isFourByteAligned(m_result.size()));
    size_t directoryEntryOffset = headerSize + m_tablesAppendedCount * directoryEntrySize;
    m_result[directoryEntryOffset] = identifier[0];
    m_result[directoryEntryOffset + 1] = identifier[1];
    m_result[directoryEntryOffset + 2] = identifier[2];
    m_result[directoryEntryOffset + 3] = identifier[3];
    overwrite32(directoryEntryOffset + 4, calculateChecksum(offset, m_result.size()));
    overwrite32(directoryEntryOffset + 8, offset);
    overwrite32(directoryEntryOffset + 12, unpaddedSize);
    ++m_tablesAppendedCount;
}

bool SVGToOTFFontConverter::convertSVGToOTFFont()
{
    if (m_glyphs.isEmpty())
        return false;

    uint16_t numTables = 14;
    uint16_t roundedNumTables = roundDownToPowerOfTwo(numTables);
    uint16_t searchRange = roundedNumTables * 16; // searchRange: "(Maximum power of 2 <= numTables) x 16."

    m_result.append('O');
    m_result.append('T');
    m_result.append('T');
    m_result.append('O');
    append16(numTables);
    append16(searchRange);
    append16(integralLog2(roundedNumTables)); // entrySelector: "Log2(maximum power of 2 <= numTables)."
    append16(numTables * 16 - searchRange); // rangeShift: "NumTables x 16-searchRange."

    ASSERT(m_result.size() == headerSize);

    // Leave space for the directory entries.
    for (size_t i = 0; i < directoryEntrySize * numTables; ++i)
        m_result.append(0);

    appendTable("CFF ", &SVGToOTFFontConverter::appendCFFTable);
    appendTable("GSUB", &SVGToOTFFontConverter::appendGSUBTable);
    appendTable("OS/2", &SVGToOTFFontConverter::appendOS2Table);
    appendTable("VORG", &SVGToOTFFontConverter::appendVORGTable);
    appendTable("cmap", &SVGToOTFFontConverter::appendCMAPTable);
    auto headTableOffset = m_result.size();
    appendTable("head", &SVGToOTFFontConverter::appendHEADTable);
    appendTable("hhea", &SVGToOTFFontConverter::appendHHEATable);
    appendTable("hmtx", &SVGToOTFFontConverter::appendHMTXTable);
    appendTable("kern", &SVGToOTFFontConverter::appendKERNTable);
    appendTable("maxp", &SVGToOTFFontConverter::appendMAXPTable);
    appendTable("name", &SVGToOTFFontConverter::appendNAMETable);
    appendTable("post", &SVGToOTFFontConverter::appendPOSTTable);
    appendTable("vhea", &SVGToOTFFontConverter::appendVHEATable);
    appendTable("vmtx", &SVGToOTFFontConverter::appendVMTXTable);

    ASSERT(numTables == m_tablesAppendedCount);

    // checksumAdjustment: "To compute: set it to 0, calculate the checksum for the 'head' table and put it in the table directory,
    // sum the entire font as uint32, then store B1B0AFBA - sum. The checksum for the 'head' table will now be wrong. That is OK."
    overwrite32(headTableOffset + 8, 0xB1B0AFBAU - calculateChecksum(0, m_result.size()));
    return true;
}

std::optional<Vector<uint8_t>> convertSVGToOTFFont(const SVGFontElement& element)
{
    SVGToOTFFontConverter converter(element);
    if (converter.error())
        return std::nullopt;
    if (!converter.convertSVGToOTFFont())
        return std::nullopt;
    return converter.releaseResult();
}

}
