"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.VmtxCoStat = exports.VmtxStat = void 0;
const tslib_1 = require("tslib");
const ImpLib = tslib_1.__importStar(require("@ot-builder/common-impl"));
const ot_glyphs_1 = require("@ot-builder/ot-glyphs");
const variance_1 = require("@ot-builder/variance");
const hmtx_1 = require("./hmtx");
class VmtxStat {
    constructor(vhea, fvar, outer) {
        this.vhea = vhea;
        this.outer = outer;
        // Table triplet
        this.vmtx = new ot_glyphs_1.MetricBasic.Table();
        this.vorg = new ot_glyphs_1.Vorg.Table();
        this.minTopSideBearing = 0x7fff;
        this.minBottomSideBearing = 0x7fff;
        this.yMaxExtent = 0;
        this.yMaxAdvance = 0;
        if (fvar)
            this.vvar = new ot_glyphs_1.MetricVariance.Table(true);
    }
    setNumGlyphs(count) {
        if (this.outer)
            this.outer.setNumGlyphs(count);
    }
    setMetric(gid, horizontal, vertical, extent) {
        const stVOrg = ImpLib.Arith.Round.Coord(variance_1.OtVar.Ops.originOf(vertical.start));
        const advance = variance_1.OtVar.Ops.minus(vertical.start, vertical.end);
        const stTsb = stVOrg - ImpLib.Arith.Round.Coord(extent.yMax);
        const stAdv = ImpLib.Arith.Round.Offset(variance_1.OtVar.Ops.originOf(advance));
        const stBsb = extent.yMin - (stVOrg - stAdv);
        if (stAdv > this.yMaxAdvance)
            this.yMaxAdvance = stAdv;
        if (stTsb < this.minTopSideBearing)
            this.minTopSideBearing = stTsb;
        if (stBsb < this.minBottomSideBearing)
            this.minBottomSideBearing = stBsb;
        if (stTsb + extent.yMax - extent.yMin > this.yMaxExtent) {
            this.yMaxExtent = stTsb + extent.yMax - extent.yMin;
        }
        this.vmtx.measures[gid] = new ot_glyphs_1.MetricBasic.Measure(stAdv, stTsb);
        this.vorg.vertOriginYMetrics[gid] = stVOrg;
        if (this.vvar) {
            this.vvar.measures[gid] = new ot_glyphs_1.MetricVariance.Measure(vertical.start, advance);
        }
        if (this.outer)
            this.outer.setMetric(gid, horizontal, vertical, extent);
    }
    simpleGlyphStat(st) {
        if (this.outer)
            this.outer.simpleGlyphStat(st);
    }
    complexGlyphStat(st) {
        if (this.outer)
            this.outer.complexGlyphStat(st);
    }
    instructionsStat(size) {
        if (this.outer)
            this.outer.instructionsStat(size);
    }
    statVorgFreq() {
        // fill
        for (let gid = 0; gid < this.vorg.vertOriginYMetrics.length; gid++) {
            const org = this.vorg.vertOriginYMetrics[gid];
            if (org == null)
                this.vorg.vertOriginYMetrics[gid] = this.vorg.defaultVertOriginY;
        }
        const freq = [];
        for (let gid = 0; gid < this.vorg.vertOriginYMetrics.length; gid++) {
            const org = this.vorg.vertOriginYMetrics[gid];
            if (org == null || org < 0)
                continue;
            freq[org] = (freq[org] || 0) + 1;
        }
        let maxFreq = 0, maxFreqVorg = 0;
        for (let org = 0; org < freq.length; org++) {
            const f = freq[org] || 0;
            if (f >= maxFreq) {
                maxFreqVorg = org;
                maxFreq = f;
            }
        }
        this.vorg.defaultVertOriginY = maxFreqVorg;
        for (let gid = 0; gid < this.vorg.vertOriginYMetrics.length; gid++) {
            const org = this.vorg.vertOriginYMetrics[gid];
            if (org === maxFreqVorg)
                this.vorg.vertOriginYMetrics[gid] = undefined;
        }
    }
    settle() {
        if (this.outer)
            this.outer.settle();
        this.vhea.minStartSideBearing = this.minTopSideBearing;
        this.vhea.minEndSideBearing = this.minBottomSideBearing;
        this.vhea.maxExtent = this.yMaxExtent;
        this.vhea.advanceMax = this.yMaxAdvance;
        (0, hmtx_1.statLongMetricCount)(this.vhea, this.vmtx);
        this.statVorgFreq();
    }
}
exports.VmtxStat = VmtxStat;
class VmtxCoStat {
    constructor(vmtx, vvar, vorg, outer) {
        this.vmtx = vmtx;
        this.vvar = vvar;
        this.vorg = vorg;
        this.outer = outer;
    }
    getHMetric(gid, extent) {
        if (this.outer)
            return this.outer.getHMetric(gid, extent);
        else
            return undefined;
    }
    getVMetric(gid, extent) {
        let start;
        if (!extent)
            start = 0;
        else
            start = extent.yMax + this.vmtx.measures[gid].startSideBearing;
        if (this.vorg)
            start = this.vorg.get(gid);
        if (this.vvar) {
            start = variance_1.OtVar.Ops.add(start, variance_1.OtVar.Ops.removeOrigin(this.vvar.measures[gid].start));
        }
        const end = variance_1.OtVar.Ops.minus(start, variance_1.OtVar.Ops.add(this.vmtx.measures[gid].advance, this.vvar ? variance_1.OtVar.Ops.removeOrigin(this.vvar.measures[gid].advance) : 0));
        return { start, end };
    }
}
exports.VmtxCoStat = VmtxCoStat;
//# sourceMappingURL=vmtx.js.map