"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CharStringEncoder = void 0;
const primitive_1 = require("@ot-builder/primitive");
const CffInterp = require("../../interp/ir");
const EPSILON = 1 / 0x20000;
class CharStringEncoder extends CffInterp.Encoder {
    constructor(frag) {
        super();
        this.frag = frag;
    }
    operand(val) {
        if (Math.abs(val - Math.round(val)) < EPSILON) {
            // Value is integer -- encode as int
            return this.encodeInt(val);
        }
        else {
            return this.encodeReal(val);
        }
    }
    encodeInt(val) {
        if (val >= -107 && val <= 107) {
            return this.frag.uint8(val + 139);
        }
        else if (val >= 108 && val <= 1131) {
            val -= 108;
            return this.frag.uint8((val >> 8) + 247).uint8(val & 0xff);
        }
        else if (val >= -1131 && val <= -108) {
            val = -108 - val;
            return this.frag.uint8((val >> 8) + 251).uint8(val & 0xff);
        }
        else {
            return this.frag.uint8(28).int16(val);
        }
    }
    encodeReal(val) {
        this.frag.uint8(0xff);
        this.frag.push(primitive_1.F16D16, val);
    }
    operator(opCode, flags) {
        if ((opCode & 0xff00) === 0x0c00) {
            this.frag.uint8(0x0c).uint8(opCode & 0xff);
        }
        else {
            this.frag.uint8(opCode);
        }
        // Mask bits
        if (flags) {
            let maskByte = 0;
            let bits = 0;
            for (const bit of flags) {
                maskByte = (maskByte << 1) | (bit ? 1 : 0);
                bits++;
                if (bits === 8) {
                    this.frag.uint8(maskByte);
                    bits = 0;
                }
            }
            if (bits) {
                maskByte = maskByte << (8 - bits);
                this.frag.uint8(maskByte);
            }
        }
    }
    static measureOperand(val) {
        if (Math.abs(val - Math.round(val)) < EPSILON) {
            // Value is integer -- encode as int
            return CharStringEncoder.measureInt(val);
        }
        else {
            return CharStringEncoder.measureReal(val);
        }
    }
    static measureInt(val) {
        if (val >= -107 && val <= 107) {
            return 1;
        }
        else if (val >= 108 && val <= 1131) {
            return 2;
        }
        else if (val >= -1131 && val <= -108) {
            return 2;
        }
        else {
            return 3;
        }
    }
    static measureReal(val) {
        return 5;
    }
    static measureOperator(opCode, flags) {
        let s;
        if ((opCode & 0xff00) === 0x0c00) {
            s = 2;
        }
        else {
            s = 1;
        }
        if (flags) {
            let maskByte = 0;
            let bits = 0;
            for (const bit of flags) {
                maskByte = (maskByte << 1) | (bit ? 1 : 0);
                bits++;
                if (bits === 8) {
                    s++;
                    bits = 0;
                }
            }
            if (bits) {
                maskByte = maskByte << (8 - bits);
                s++;
            }
        }
        return s;
    }
}
exports.CharStringEncoder = CharStringEncoder;
//# sourceMappingURL=encoder.js.map