"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CffFdArrayIo = exports.CffFontDictIo = exports.CffFontDictDataCollector = exports.CffFontDictInterpreter = exports.CffFontDictInterpreterBase = void 0;
const bin_util_1 = require("@ot-builder/bin-util");
const errors_1 = require("@ot-builder/errors");
const ot_glyphs_1 = require("@ot-builder/ot-glyphs");
const variance_1 = require("@ot-builder/variance");
const read_1 = require("../cff-index/read");
const write_1 = require("../cff-index/write");
const draw_call_1 = require("../char-string/write/draw-call");
const operator_1 = require("../interp/operator");
const general_1 = require("./general");
const private_dict_1 = require("./private-dict");
class CffFontDictInterpreterBase extends general_1.CffDictInterpreterBase {
    constructor(ctx) {
        super(null);
        this.ctx = ctx;
        this.fd = new ot_glyphs_1.Cff.FontDict();
    }
    popString() {
        const sid = variance_1.OtVar.Ops.originOf(this.st.pop());
        if (!this.ctx.strings)
            throw errors_1.Errors.Cff.StringsDisallowed();
        return this.ctx.strings.get(sid);
    }
    doOperator(opCode, flags) {
        switch (opCode) {
            // Strings
            case operator_1.CffOperator.Version:
                this.fd.version = this.popString();
                break;
            case operator_1.CffOperator.Notice:
                this.fd.notice = this.popString();
                break;
            case operator_1.CffOperator.Copyright:
                this.fd.copyright = this.popString();
                break;
            case operator_1.CffOperator.FullName:
                this.fd.fullName = this.popString();
                break;
            case operator_1.CffOperator.FamilyName:
                this.fd.familyName = this.popString();
                break;
            case operator_1.CffOperator.Weight:
                this.fd.weight = this.popString();
                break;
            // Numbers
            case operator_1.CffOperator.IsFixedPitch:
                this.fd.isFixedPitch = !!variance_1.OtVar.Ops.originOf(this.st.pop());
                break;
            case operator_1.CffOperator.ItalicAngle:
                this.fd.italicAngle = variance_1.OtVar.Ops.originOf(this.st.pop());
                break;
            case operator_1.CffOperator.UnderlinePosition:
                this.fd.underlinePosition = variance_1.OtVar.Ops.originOf(this.st.pop());
                break;
            case operator_1.CffOperator.UnderlineThickness:
                this.fd.underlineThickness = variance_1.OtVar.Ops.originOf(this.st.pop());
                break;
            case operator_1.CffOperator.PaintType:
                this.fd.paintType = variance_1.OtVar.Ops.originOf(this.st.pop());
                break;
            case operator_1.CffOperator.CharStringType:
                this.st.pop();
                break;
            case operator_1.CffOperator.StrokeWidth:
                this.fd.strokeWidth = variance_1.OtVar.Ops.originOf(this.st.pop());
                break;
            // CID
            case operator_1.CffOperator.FontName:
                this.fd.cidFontName = this.popString();
                break;
            case operator_1.CffOperator.CIDFontVersion:
                this.fd.cidFontVersion = variance_1.OtVar.Ops.originOf(this.st.pop());
                break;
            case operator_1.CffOperator.CIDFontRevision:
                this.fd.cidFontRevision = variance_1.OtVar.Ops.originOf(this.st.pop());
                break;
            case operator_1.CffOperator.CIDFontType:
                this.fd.cidFontType = variance_1.OtVar.Ops.originOf(this.st.pop());
                break;
            case operator_1.CffOperator.CIDCount:
                this.fd.cidCount = variance_1.OtVar.Ops.originOf(this.st.pop());
                break;
            // Unique ID, XUID, etc
            // Omit
            case operator_1.CffOperator.UniqueID:
                this.st.pop();
                break;
            case operator_1.CffOperator.XUID:
                this.st.allArgs();
                break;
            case operator_1.CffOperator.UIDBase:
                this.st.pop();
                break;
            // BBox and FontMatrix
            // Omit, we don't need that
            case operator_1.CffOperator.FontBBox:
                this.st.args(4);
                break;
            case operator_1.CffOperator.FontMatrix:
                this.st.args(6);
                break;
            // Private dict
            case operator_1.CffOperator.Private: {
                const [vvSize, vvOffset] = this.st.args(2);
                this.fd.privateDict = this.ctx.vwCffTable
                    .lift(variance_1.OtVar.Ops.originOf(vvOffset))
                    .next(private_dict_1.CffPrivateDictIo, this.ctx, variance_1.OtVar.Ops.originOf(vvSize));
                break;
            }
            default:
                throw errors_1.Errors.Cff.OperatorNotSupported(opCode);
        }
    }
}
exports.CffFontDictInterpreterBase = CffFontDictInterpreterBase;
class CffFontDictInterpreter extends CffFontDictInterpreterBase {
    getResult() {
        return this.fd;
    }
}
exports.CffFontDictInterpreter = CffFontDictInterpreter;
class CffFontDictDataCollector extends general_1.CffDictDataCollector {
    *emitNum(q, defaultQ, op) {
        if (variance_1.OtVar.Ops.equal(q, defaultQ, 1 / 0x10000))
            return;
        yield new draw_call_1.CffDrawCallRaw([q], op);
    }
    *emitString(ctx, s, op) {
        if (s && ctx.strings) {
            yield new draw_call_1.CffDrawCallRaw([ctx.strings.push(s)], op);
        }
    }
    *collectDrawCalls(pd, ctx, rest) {
        // Strings
        yield* this.emitString(ctx, pd.version, operator_1.CffOperator.Version);
        yield* this.emitString(ctx, pd.notice, operator_1.CffOperator.Notice);
        yield* this.emitString(ctx, pd.copyright, operator_1.CffOperator.Copyright);
        yield* this.emitString(ctx, pd.fullName, operator_1.CffOperator.FullName);
        yield* this.emitString(ctx, pd.familyName, operator_1.CffOperator.FamilyName);
        yield* this.emitString(ctx, pd.weight, operator_1.CffOperator.Weight);
        yield* this.emitString(ctx, pd.cidFontName, operator_1.CffOperator.FontName);
        // Numbers
        const emp = new ot_glyphs_1.Cff.FontDict();
        yield* this.emitNum(pd.isFixedPitch ? 1 : 0, 0, operator_1.CffOperator.IsFixedPitch);
        yield* this.emitNum(pd.italicAngle, emp.italicAngle, operator_1.CffOperator.ItalicAngle);
        yield* this.emitNum(pd.underlinePosition, emp.underlinePosition, operator_1.CffOperator.UnderlinePosition);
        yield* this.emitNum(pd.underlineThickness, emp.underlineThickness, operator_1.CffOperator.UnderlineThickness);
        yield* this.emitNum(pd.paintType, emp.paintType, operator_1.CffOperator.PaintType);
        yield* this.emitNum(pd.charStringType, emp.charStringType, operator_1.CffOperator.CharStringType);
        yield* this.emitNum(pd.strokeWidth, emp.strokeWidth, operator_1.CffOperator.StrokeWidth);
        // CID
        yield* this.emitNum(pd.cidFontVersion, emp.cidFontVersion, operator_1.CffOperator.CIDFontVersion);
        yield* this.emitNum(pd.cidFontRevision, emp.cidFontRevision, operator_1.CffOperator.CIDFontRevision);
        yield* this.emitNum(pd.cidFontType, emp.cidFontType, operator_1.CffOperator.CIDFontType);
        yield* this.emitNum(pd.cidCount, emp.cidCount, operator_1.CffOperator.CIDCount);
    }
    processPointers(encoder, fd, ctx, rest) {
        if (fd.privateDict) {
            const frPrivateDict = bin_util_1.Frag.from(private_dict_1.CffPrivateDictIo, fd.privateDict, ctx, rest);
            encoder.operand(frPrivateDict.size);
            encoder.absPointer(frPrivateDict, operator_1.CffOperator.Private);
        }
    }
}
exports.CffFontDictDataCollector = CffFontDictDataCollector;
exports.CffFontDictIo = {
    ...(0, general_1.CffDictReadT)((vwDict, ctx) => new CffFontDictInterpreter(ctx)),
    ...(0, general_1.CffDictWriteT)(new CffFontDictDataCollector())
};
const CffFontDictIndexWrite = new write_1.CffWriteIndex({
    write: (f, fd, ctx) => f.push(exports.CffFontDictIo, fd, ctx, undefined)
});
exports.CffFdArrayIo = {
    ...(0, bin_util_1.Read)((view, ctx) => {
        return view.next(new read_1.CffReadIndex({ read: (view, ctx, size) => view.next(exports.CffFontDictIo, ctx, size) }), ctx);
    }),
    ...(0, bin_util_1.Write)((frag, fdArray, ctx) => {
        return frag.push(CffFontDictIndexWrite, fdArray, ctx);
    })
};
//# sourceMappingURL=font-dict.js.map