"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SparseGlyphSharer = void 0;
const ot_builder_1 = require("ot-builder");
const glyph_class_1 = require("./glyph-class");
class SparseSharingEntry {
    constructor(glyph, glyphClass, usages) {
        this.glyph = glyph;
        this.glyphClass = glyphClass;
        this.usages = usages;
    }
}
class SparseGlyphSharer extends ot_builder_1.CliProc.GlyphSharer {
    createPadGlyph(name, commonWidth, commonHeight) {
        const g = new ot_builder_1.Ot.Glyph();
        g.name = name;
        g.geometry = new ot_builder_1.Ot.Glyph.ContourSet([[{ x: 0, y: 0, kind: ot_builder_1.Ot.Glyph.PointType.Corner }]]);
        g.horizontal = { start: 0, end: commonWidth };
        g.vertical = { start: commonHeight, end: 0 };
        return g;
    }
    getSparseSharingMap(commonWidth, commonHeight) {
        const speMap = new Map();
        for (const font of this.fonts) {
            for (const [gid, g] of font.glyphs.decideOrder().entries()) {
                if (speMap.has(g)) {
                    speMap.get(g).usages++;
                }
                else {
                    const gk = (0, glyph_class_1.decideGlyphClass)(g, gid, commonWidth, commonHeight);
                    speMap.set(g, new SparseSharingEntry(g, gk, 1));
                }
            }
        }
        return speMap;
    }
    padSparseSharingList(commonWidth, commonHeight) {
        const speMap = this.getSparseSharingMap(commonWidth, commonHeight);
        const speList = Array.from(speMap.values());
        const allSharedEntries = [];
        for (const entry of speList) {
            const isSimple = entry.glyphClass & glyph_class_1.GlyphClass.Simple
                && (entry.glyphClass & glyph_class_1.GlyphClass.KindMask) === glyph_class_1.GlyphClass.Normal;
            const isSharable = entry.usages === this.fonts.length;
            if (isSimple && isSharable)
                allSharedEntries.push(entry);
        }
        // The particular glyph after all spaces must be a simple all-shared glyph
        // Insert a pad glyph if necessary
        let postSpace = allSharedEntries[0] || null;
        if (!postSpace) {
            postSpace = new SparseSharingEntry(this.createPadGlyph(".otb-ttc-bundle/post-space", commonWidth, commonHeight), glyph_class_1.GlyphClass.PostSpacePad, this.fonts.length);
            speList.push(postSpace);
        }
        postSpace.glyphClass = glyph_class_1.GlyphClass.PostSpacePad;
        // The particular glyph at very end must be a simple all-shared glyph
        // Insert a pad glyph if necessary
        const veryLast = allSharedEntries[allSharedEntries.length - 1];
        if (veryLast && veryLast !== postSpace)
            veryLast.glyphClass = glyph_class_1.GlyphClass.VeryLast;
        speList.sort((a, b) => a.glyphClass - b.glyphClass);
        return { speList, postSpace };
    }
    getGidMap(speList) {
        const sharedGlyphMap = new Map();
        for (let gid = 0; gid < speList.length; gid++)
            sharedGlyphMap.set(speList[gid].glyph, gid);
        return sharedGlyphMap;
    }
    sparseSharing(commonWidth, commonHeight) {
        const { speList, postSpace } = this.padSparseSharingList(commonWidth, commonHeight);
        const sharedGlyphMap = this.getGidMap(speList);
        const sharing = [];
        for (let fid = 0; fid < this.fonts.length; fid++) {
            sharing[fid] = [];
            const fontGlyphSet = new Set(this.fonts[fid].glyphs.decideOrder());
            const fontGlyphList = [];
            for (const entry of speList) {
                if (!fontGlyphSet.has(entry.glyph) && entry !== postSpace)
                    continue;
                fontGlyphList.push(entry.glyph);
                sharing[fid].push(sharedGlyphMap.get(entry.glyph));
            }
            this.fonts[fid].glyphs = ot_builder_1.Ot.ListGlyphStoreFactory.createStoreFromList(fontGlyphList);
        }
        return sharing;
    }
}
exports.SparseGlyphSharer = SparseGlyphSharer;
//# sourceMappingURL=sparse-sharer.js.map