"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.IIPHandler = void 0; const ImageRenderer_1 = require("./ImageRenderer"); const ImageStorage_1 = require("./ImageStorage"); const Base64Decoder_wasm_1 = require("xterm-wasm-parts/lib/base64/Base64Decoder.wasm"); const IIPHeaderParser_1 = require("./IIPHeaderParser"); const IIPMetrics_1 = require("./IIPMetrics"); // limit hold memory in base64 decoder const KEEP_DATA = 4194304; // default IIP header values const DEFAULT_HEADER = { name: 'Unnamed file', size: 0, width: 'auto', height: 'auto', preserveAspectRatio: 1, inline: 0 }; class IIPHandler { constructor(_opts, _renderer, _storage, _coreTerminal) { this._opts = _opts; this._renderer = _renderer; this._storage = _storage; this._coreTerminal = _coreTerminal; this._aborted = false; this._hp = new IIPHeaderParser_1.HeaderParser(); this._header = DEFAULT_HEADER; this._dec = new Base64Decoder_wasm_1.default(KEEP_DATA); this._metrics = IIPMetrics_1.UNSUPPORTED_TYPE; } reset() { } start() { this._aborted = false; this._header = DEFAULT_HEADER; this._metrics = IIPMetrics_1.UNSUPPORTED_TYPE; this._hp.reset(); } put(data, start, end) { if (this._aborted) return; if (this._hp.state === 4 /* HeaderState.END */) { if (this._dec.put(data, start, end)) { this._dec.release(); this._aborted = true; } } else { const dataPos = this._hp.parse(data, start, end); if (dataPos === -1) { this._aborted = true; return; } if (dataPos > 0) { this._header = Object.assign({}, DEFAULT_HEADER, this._hp.fields); if (!this._header.inline || !this._header.size || this._header.size > this._opts.iipSizeLimit) { this._aborted = true; return; } this._dec.init(this._header.size); if (this._dec.put(data, dataPos, end)) { this._dec.release(); this._aborted = true; } } } } end(success) { if (this._aborted) return true; let w = 0; let h = 0; // early exit condition chain let cond = true; if (cond = success) { if (cond = !this._dec.end()) { this._metrics = (0, IIPMetrics_1.imageType)(this._dec.data8); if (cond = this._metrics.mime !== 'unsupported') { w = this._metrics.width; h = this._metrics.height; if (cond = w && h && w * h < this._opts.pixelLimit) { [w, h] = this._resize(w, h).map(Math.floor); cond = w && h && w * h < this._opts.pixelLimit; } } } } if (!cond) { this._dec.release(); return true; } const blob = new Blob([this._dec.data8], { type: this._metrics.mime }); this._dec.release(); if (!window.createImageBitmap) { const url = URL.createObjectURL(blob); const img = new Image(); return new Promise(r => { img.addEventListener('load', () => { var _a; URL.revokeObjectURL(url); const canvas = ImageRenderer_1.ImageRenderer.createCanvas(window.document, w, h); (_a = canvas.getContext('2d')) === null || _a === void 0 ? void 0 : _a.drawImage(img, 0, 0, w, h); this._storage.addImage(canvas); r(true); }); img.src = url; // sanity measure to avoid terminal blocking from dangling promise // happens from corrupt data (onload never gets fired) setTimeout(() => r(true), 1000); }); } return createImageBitmap(blob, { resizeWidth: w, resizeHeight: h }) .then(bm => { this._storage.addImage(bm); return true; }); } _resize(w, h) { var _a, _b, _c, _d; const cw = ((_a = this._renderer.dimensions) === null || _a === void 0 ? void 0 : _a.css.cell.width) || ImageStorage_1.CELL_SIZE_DEFAULT.width; const ch = ((_b = this._renderer.dimensions) === null || _b === void 0 ? void 0 : _b.css.cell.height) || ImageStorage_1.CELL_SIZE_DEFAULT.height; const width = ((_c = this._renderer.dimensions) === null || _c === void 0 ? void 0 : _c.css.canvas.width) || cw * this._coreTerminal.cols; const height = ((_d = this._renderer.dimensions) === null || _d === void 0 ? void 0 : _d.css.canvas.height) || ch * this._coreTerminal.rows; const rw = this._dim(this._header.width, width, cw); const rh = this._dim(this._header.height, height, ch); if (!rw && !rh) { const wf = width / w; // TODO: should this respect initial cursor offset? const hf = (height - ch) / h; // TODO: fix offset issues from float cell height const f = Math.min(wf, hf); return f < 1 ? [w * f, h * f] : [w, h]; } return !rw ? [w * rh / h, rh] : this._header.preserveAspectRatio || !rw || !rh ? [rw, h * rw / w] : [rw, rh]; } _dim(s, total, cdim) { if (s === 'auto') return 0; if (s.endsWith('%')) return parseInt(s.slice(0, -1)) * total / 100; if (s.endsWith('px')) return parseInt(s.slice(0, -2)); return parseInt(s) * cdim; } } exports.IIPHandler = IIPHandler;