"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.HmtxCoStat = exports.HmtxStat = void 0;
exports.statLongMetricCount = statLongMetricCount;
const ImpLib = require("@ot-builder/common-impl");
const ot_glyphs_1 = require("@ot-builder/ot-glyphs");
const ot_metadata_1 = require("@ot-builder/ot-metadata");
const variance_1 = require("@ot-builder/variance");
class HmtxStat {
    constructor(hhea, head, fvar, outer) {
        this.hhea = hhea;
        this.head = head;
        this.outer = outer;
        // Table triplet
        this.hmtx = new ot_glyphs_1.MetricBasic.Table();
        this.minLeftSideBearing = 0x7fff;
        this.minRightSideBearing = 0x7fff;
        this.xMaxExtent = 0;
        this.xMaxAdvance = 0;
        this.hOrgStartAtZero = true;
        if (fvar)
            this.hvar = new ot_glyphs_1.MetricVariance.Table(false);
    }
    setNumGlyphs(count) {
        if (this.outer)
            this.outer.setNumGlyphs(count);
    }
    setMetric(gid, horizontal, vertical, extent) {
        const hOrg = this.hvar ? 0 : horizontal.start;
        const stHOrg = ImpLib.Arith.Round.Coord(variance_1.OtVar.Ops.originOf(hOrg));
        const advance = variance_1.OtVar.Ops.minus(horizontal.end, hOrg);
        const stLsb = ImpLib.Arith.Round.Coord(extent.xMin) - stHOrg;
        const stAdv = ImpLib.Arith.Round.Offset(variance_1.OtVar.Ops.originOf(advance));
        const stRsb = stHOrg + stAdv - ImpLib.Arith.Round.Coord(extent.xMax);
        if (stAdv > this.xMaxAdvance)
            this.xMaxAdvance = stAdv;
        if (stLsb < this.minLeftSideBearing)
            this.minLeftSideBearing = stLsb;
        if (stRsb < this.minRightSideBearing)
            this.minRightSideBearing = stRsb;
        if (stLsb + extent.xMax - extent.xMin > this.xMaxExtent) {
            this.xMaxExtent = stLsb + extent.xMax - extent.xMin;
        }
        this.hmtx.measures[gid] = new ot_glyphs_1.MetricBasic.Measure(stAdv, stLsb);
        if (this.hvar) {
            this.hvar.measures[gid] = new ot_glyphs_1.MetricVariance.Measure(hOrg, advance);
        }
        if (this.outer)
            this.outer.setMetric(gid, horizontal, vertical, extent);
        if (stHOrg)
            this.hOrgStartAtZero = false;
    }
    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);
    }
    settle() {
        if (this.outer)
            this.outer.settle();
        this.hhea.minStartSideBearing = this.minLeftSideBearing;
        this.hhea.minEndSideBearing = this.minRightSideBearing;
        this.hhea.maxExtent = this.xMaxExtent;
        this.hhea.advanceMax = this.xMaxAdvance;
        statLongMetricCount(this.hhea, this.hmtx);
        this.head.flags &= ~ot_metadata_1.Head.Flags.LeftSidebearingAtX0;
        this.head.flags |= this.hOrgStartAtZero ? ot_metadata_1.Head.Flags.LeftSidebearingAtX0 : 0;
    }
}
exports.HmtxStat = HmtxStat;
function statLongMetricCount(hea, mtx) {
    hea.numberOfLongMetrics = mtx.measures.length;
    for (let gid = mtx.measures.length; gid-- > 2;) {
        if (mtx.measures[gid - 1].advance === mtx.measures[gid].advance) {
            hea.numberOfLongMetrics--;
        }
        else {
            break;
        }
    }
}
class HmtxCoStat {
    constructor(alwaysStartAtZero, hmtx, hvar, outer) {
        this.alwaysStartAtZero = alwaysStartAtZero;
        this.hmtx = hmtx;
        this.hvar = hvar;
        this.outer = outer;
    }
    getHMetric(gid, extent) {
        let start;
        if (this.alwaysStartAtZero || !extent) {
            start = 0;
        }
        else {
            start = extent.xMin - this.hmtx.measures[gid].startSideBearing;
            if (this.hvar) {
                start = variance_1.OtVar.Ops.add(start, variance_1.OtVar.Ops.removeOrigin(this.hvar.measures[gid].start));
            }
        }
        const end = variance_1.OtVar.Ops.add(start, variance_1.OtVar.Ops.add(this.hmtx.measures[gid].advance, this.hvar ? variance_1.OtVar.Ops.removeOrigin(this.hvar.measures[gid].advance) : 0));
        return { start, end };
    }
    getVMetric(gid, extent) {
        if (this.outer)
            return this.outer.getVMetric(gid, extent);
        else
            return undefined;
    }
}
exports.HmtxCoStat = HmtxCoStat;
//# sourceMappingURL=hmtx.js.map