"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MvarTableIo = exports.MvarTag = void 0;
const bin_util_1 = require("@ot-builder/bin-util");
const errors_1 = require("@ot-builder/errors");
const primitive_1 = require("@ot-builder/primitive");
const var_store_1 = require("@ot-builder/var-store");
const variance_1 = require("@ot-builder/variance");
exports.MvarTag = "MVAR";
class MvarPropAccess {
    constructor(table, key) {
        this.table = table;
        this.key = key;
    }
    get() {
        return this.table[this.key];
    }
    set(x) {
        this.table[this.key] = x;
    }
}
class HheaMvarLensSource {
    constructor(hhea) {
        this.hhea = hhea;
    }
    *entries() {
        // yield ["????", new MvarPropAccess(this.hhea, "ascender")];
        // yield ["????", new MvarPropAccess(this.hhea, "descender")];
        // yield ["????", new MvarPropAccess(this.hhea, "lineGap")];
        yield ["hcrs", new MvarPropAccess(this.hhea, "caretSlopeRise")];
        yield ["hcrn", new MvarPropAccess(this.hhea, "caretSlopeRun")];
        yield ["hcof", new MvarPropAccess(this.hhea, "caretOffset")];
    }
}
class VheaMvarLensSource {
    constructor(vhea) {
        this.vhea = vhea;
    }
    *entries() {
        yield ["vasc", new MvarPropAccess(this.vhea, "ascender")];
        yield ["vdsc", new MvarPropAccess(this.vhea, "descender")];
        yield ["vlgp", new MvarPropAccess(this.vhea, "lineGap")];
        yield ["vcrs", new MvarPropAccess(this.vhea, "caretSlopeRise")];
        yield ["vcrn", new MvarPropAccess(this.vhea, "caretSlopeRun")];
        yield ["vcof", new MvarPropAccess(this.vhea, "caretOffset")];
    }
}
class PostMvarLensSource {
    constructor(post) {
        this.post = post;
    }
    *entries() {
        yield ["unds", new MvarPropAccess(this.post, "underlineThickness")];
        yield ["undo", new MvarPropAccess(this.post, "underlinePosition")];
    }
}
class Os2MvarLensSource {
    constructor(os2) {
        this.os2 = os2;
    }
    *entries() {
        yield ["hasc", new MvarPropAccess(this.os2, "sTypoAscender")];
        yield ["hdsc", new MvarPropAccess(this.os2, "sTypoDescender")];
        yield ["hlgp", new MvarPropAccess(this.os2, "sTypoLineGap")];
        yield ["hcla", new MvarPropAccess(this.os2, "usWinAscent")];
        yield ["hcld", new MvarPropAccess(this.os2, "usWinDescent")];
        yield ["xhgt", new MvarPropAccess(this.os2, "sxHeight")];
        yield ["cpht", new MvarPropAccess(this.os2, "sCapHeight")];
        yield ["sbxs", new MvarPropAccess(this.os2, "ySubscriptXSize")];
        yield ["sbys", new MvarPropAccess(this.os2, "ySubscriptYSize")];
        yield ["sbxo", new MvarPropAccess(this.os2, "ySubscriptXOffset")];
        yield ["sbyo", new MvarPropAccess(this.os2, "ySubscriptYOffset")];
        yield ["spxs", new MvarPropAccess(this.os2, "ySuperscriptXSize")];
        yield ["spys", new MvarPropAccess(this.os2, "ySuperscriptYSize")];
        yield ["spxo", new MvarPropAccess(this.os2, "ySuperscriptXOffset")];
        yield ["spyo", new MvarPropAccess(this.os2, "ySuperscriptYOffset")];
        yield ["strs", new MvarPropAccess(this.os2, "yStrikeoutSize")];
        yield ["stro", new MvarPropAccess(this.os2, "yStrikeoutPosition")];
    }
}
class GaspMvarLensSource {
    constructor(gasp) {
        this.gasp = gasp;
    }
    *entries() {
        for (let ri = 0; ri < 10 && ri < this.gasp.ranges.length; ri++) {
            yield [`gsp${ri}`, new MvarPropAccess(this.gasp.ranges[ri], "maxPPEM")];
        }
    }
}
function* lensSourcesFromMd(md) {
    if (md.hhea)
        yield* new HheaMvarLensSource(md.hhea).entries();
    if (md.vhea)
        yield* new VheaMvarLensSource(md.vhea).entries();
    if (md.post)
        yield* new PostMvarLensSource(md.post).entries();
    if (md.os2)
        yield* new Os2MvarLensSource(md.os2).entries();
    if (md.gasp)
        yield* new GaspMvarLensSource(md.gasp).entries();
}
exports.MvarTableIo = {
    read(view, designSpace, md) {
        const majorVersion = view.uint16();
        const minorVersion = view.uint16();
        errors_1.Assert.SubVersionSupported("MvarTable", majorVersion, minorVersion, [1, 0]);
        const reserved = view.uint16();
        const valueRecordSize = view.uint16();
        errors_1.Assert.SizeMatch("MvarTable::valueRecordSize", valueRecordSize, primitive_1.Tag.size + primitive_1.UInt16.size * 2);
        const valueRecordCount = view.uint16();
        const pIVS = view.ptr16Nullable();
        if (!pIVS)
            return;
        const ivs = pIVS.next(var_store_1.ReadTimeIVS, designSpace);
        const lenses = new Map(lensSourcesFromMd(md));
        for (let rid = 0; rid < valueRecordCount; rid++) {
            const tag = view.next(primitive_1.Tag);
            const deltaSetOuterIndex = view.uint16();
            const deltaSetInnerIndex = view.uint16();
            const value = ivs.queryValue(deltaSetOuterIndex, deltaSetInnerIndex);
            const lens = lenses.get(tag);
            if (lens) {
                const current = lens.get();
                lens.set(variance_1.OtVar.Ops.add(current, value));
            }
        }
    },
    write(frag, designSpace, md, afEmpty) {
        const ivs = var_store_1.WriteTimeIVS.create(new variance_1.OtVar.MasterSet());
        const lenses = new Map(lensSourcesFromMd(md));
        const rec = [];
        for (const [tag, lens] of lenses) {
            const r = ivs.valueToInnerOuterID(lens.get());
            if (r)
                rec.push([tag, r.outer, r.inner]);
        }
        // sort records by tag
        rec.sort((a, b) => (a[0] > b[0] ? 1 : -1));
        frag.uint16(1)
            .uint16(0)
            .uint16(0)
            .uint16(primitive_1.Tag.size + primitive_1.UInt16.size * 2)
            .uint16(rec.length);
        if (rec.length) {
            frag.ptr16(bin_util_1.Frag.solidFrom(var_store_1.WriteTimeIVS, ivs, { designSpace }));
            for (const [tag, outer, inner] of rec) {
                frag.push(primitive_1.Tag, tag).uint16(outer).uint16(inner);
            }
        }
        else {
            if (afEmpty)
                afEmpty.set(true);
            frag.uint16(0);
        }
    }
};
//# sourceMappingURL=index.js.map