diff --git "a/ts-pdf.mjs" "b/ts-pdf.mjs" new file mode 100644--- /dev/null +++ "b/ts-pdf.mjs" @@ -0,0 +1,67243 @@ +function getAugmentedNamespace(n) { + if (n.__esModule) return n; + var f = n.default; + if (typeof f == "function") { + var a = function a () { + if (this instanceof a) { + return Reflect.construct(f, arguments, this.constructor); + } + return f.apply(this, arguments); + }; + a.prototype = f.prototype; + } else a = {}; + Object.defineProperty(a, '__esModule', {value: true}); + Object.keys(n).forEach(function (k) { + var d = Object.getOwnPropertyDescriptor(n, k); + Object.defineProperty(a, k, d.get ? d : { + enumerable: true, + get: function () { + return n[k]; + } + }); + }); + return a; +} + +function commonjsRequire(path) { + throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.'); +} + +var pdf = {exports: {}}; + +var _nodeResolve_empty = {}; + +var _nodeResolve_empty$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + default: _nodeResolve_empty +}); + +var require$$5 = /*@__PURE__*/getAugmentedNamespace(_nodeResolve_empty$1); + +/** + * @licstart The following is the entire license notice for the + * JavaScript code in this page + * + * Copyright 2022 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @licend The above is the entire license notice for the + * JavaScript code in this page + */ + +(function (module, exports) { + (function webpackUniversalModuleDefinition(root, factory) { + module.exports = factory(); + })(globalThis, () => { + return /******/ (() => { // webpackBootstrap + /******/ var __webpack_modules__ = ([ + /* 0 */, + /* 1 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.VerbosityLevel = exports.Util = exports.UnknownErrorException = exports.UnexpectedResponseException = exports.UNSUPPORTED_FEATURES = exports.TextRenderingMode = exports.StreamType = exports.RenderingIntentFlag = exports.PermissionFlag = exports.PasswordResponses = exports.PasswordException = exports.PageActionEventType = exports.OPS = exports.MissingPDFException = exports.LINE_FACTOR = exports.LINE_DESCENT_FACTOR = exports.InvalidPDFException = exports.ImageKind = exports.IDENTITY_MATRIX = exports.FormatError = exports.FontType = exports.FeatureTest = exports.FONT_IDENTITY_MATRIX = exports.DocumentActionEventType = exports.CMapCompressionType = exports.BaseException = exports.AnnotationType = exports.AnnotationStateModelType = exports.AnnotationReviewState = exports.AnnotationReplyType = exports.AnnotationMode = exports.AnnotationMarkedState = exports.AnnotationFlag = exports.AnnotationFieldFlag = exports.AnnotationEditorType = exports.AnnotationEditorPrefix = exports.AnnotationEditorParamsType = exports.AnnotationBorderStyleType = exports.AnnotationActionEventType = exports.AbortException = void 0; + exports.arrayByteLength = arrayByteLength; + exports.arraysToBytes = arraysToBytes; + exports.assert = assert; + exports.bytesToString = bytesToString; + exports.createPromiseCapability = createPromiseCapability; + exports.createValidAbsoluteUrl = createValidAbsoluteUrl; + exports.escapeString = escapeString; + exports.getModificationDate = getModificationDate; + exports.getVerbosityLevel = getVerbosityLevel; + exports.info = info; + exports.isArrayBuffer = isArrayBuffer; + exports.isArrayEqual = isArrayEqual; + exports.isAscii = isAscii; + exports.objectFromMap = objectFromMap; + exports.objectSize = objectSize; + exports.setVerbosityLevel = setVerbosityLevel; + exports.shadow = shadow; + exports.string32 = string32; + exports.stringToBytes = stringToBytes; + exports.stringToPDFString = stringToPDFString; + exports.stringToUTF16BEString = stringToUTF16BEString; + exports.stringToUTF8String = stringToUTF8String; + exports.unreachable = unreachable; + exports.utf8StringToString = utf8StringToString; + exports.warn = warn; + + __w_pdfjs_require__(2); + + const IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0]; + exports.IDENTITY_MATRIX = IDENTITY_MATRIX; + const FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0]; + exports.FONT_IDENTITY_MATRIX = FONT_IDENTITY_MATRIX; + const LINE_FACTOR = 1.35; + exports.LINE_FACTOR = LINE_FACTOR; + const LINE_DESCENT_FACTOR = 0.35; + exports.LINE_DESCENT_FACTOR = LINE_DESCENT_FACTOR; + const RenderingIntentFlag = { + ANY: 0x01, + DISPLAY: 0x02, + PRINT: 0x04, + ANNOTATIONS_FORMS: 0x10, + ANNOTATIONS_STORAGE: 0x20, + ANNOTATIONS_DISABLE: 0x40, + OPLIST: 0x100 + }; + exports.RenderingIntentFlag = RenderingIntentFlag; + const AnnotationMode = { + DISABLE: 0, + ENABLE: 1, + ENABLE_FORMS: 2, + ENABLE_STORAGE: 3 + }; + exports.AnnotationMode = AnnotationMode; + const AnnotationEditorPrefix = "pdfjs_internal_editor_"; + exports.AnnotationEditorPrefix = AnnotationEditorPrefix; + const AnnotationEditorType = { + DISABLE: -1, + NONE: 0, + FREETEXT: 3, + INK: 15 + }; + exports.AnnotationEditorType = AnnotationEditorType; + const AnnotationEditorParamsType = { + FREETEXT_SIZE: 1, + FREETEXT_COLOR: 2, + FREETEXT_OPACITY: 3, + INK_COLOR: 11, + INK_THICKNESS: 12, + INK_OPACITY: 13 + }; + exports.AnnotationEditorParamsType = AnnotationEditorParamsType; + const PermissionFlag = { + PRINT: 0x04, + MODIFY_CONTENTS: 0x08, + COPY: 0x10, + MODIFY_ANNOTATIONS: 0x20, + FILL_INTERACTIVE_FORMS: 0x100, + COPY_FOR_ACCESSIBILITY: 0x200, + ASSEMBLE: 0x400, + PRINT_HIGH_QUALITY: 0x800 + }; + exports.PermissionFlag = PermissionFlag; + const TextRenderingMode = { + FILL: 0, + STROKE: 1, + FILL_STROKE: 2, + INVISIBLE: 3, + FILL_ADD_TO_PATH: 4, + STROKE_ADD_TO_PATH: 5, + FILL_STROKE_ADD_TO_PATH: 6, + ADD_TO_PATH: 7, + FILL_STROKE_MASK: 3, + ADD_TO_PATH_FLAG: 4 + }; + exports.TextRenderingMode = TextRenderingMode; + const ImageKind = { + GRAYSCALE_1BPP: 1, + RGB_24BPP: 2, + RGBA_32BPP: 3 + }; + exports.ImageKind = ImageKind; + const AnnotationType = { + TEXT: 1, + LINK: 2, + FREETEXT: 3, + LINE: 4, + SQUARE: 5, + CIRCLE: 6, + POLYGON: 7, + POLYLINE: 8, + HIGHLIGHT: 9, + UNDERLINE: 10, + SQUIGGLY: 11, + STRIKEOUT: 12, + STAMP: 13, + CARET: 14, + INK: 15, + POPUP: 16, + FILEATTACHMENT: 17, + SOUND: 18, + MOVIE: 19, + WIDGET: 20, + SCREEN: 21, + PRINTERMARK: 22, + TRAPNET: 23, + WATERMARK: 24, + THREED: 25, + REDACT: 26 + }; + exports.AnnotationType = AnnotationType; + const AnnotationStateModelType = { + MARKED: "Marked", + REVIEW: "Review" + }; + exports.AnnotationStateModelType = AnnotationStateModelType; + const AnnotationMarkedState = { + MARKED: "Marked", + UNMARKED: "Unmarked" + }; + exports.AnnotationMarkedState = AnnotationMarkedState; + const AnnotationReviewState = { + ACCEPTED: "Accepted", + REJECTED: "Rejected", + CANCELLED: "Cancelled", + COMPLETED: "Completed", + NONE: "None" + }; + exports.AnnotationReviewState = AnnotationReviewState; + const AnnotationReplyType = { + GROUP: "Group", + REPLY: "R" + }; + exports.AnnotationReplyType = AnnotationReplyType; + const AnnotationFlag = { + INVISIBLE: 0x01, + HIDDEN: 0x02, + PRINT: 0x04, + NOZOOM: 0x08, + NOROTATE: 0x10, + NOVIEW: 0x20, + READONLY: 0x40, + LOCKED: 0x80, + TOGGLENOVIEW: 0x100, + LOCKEDCONTENTS: 0x200 + }; + exports.AnnotationFlag = AnnotationFlag; + const AnnotationFieldFlag = { + READONLY: 0x0000001, + REQUIRED: 0x0000002, + NOEXPORT: 0x0000004, + MULTILINE: 0x0001000, + PASSWORD: 0x0002000, + NOTOGGLETOOFF: 0x0004000, + RADIO: 0x0008000, + PUSHBUTTON: 0x0010000, + COMBO: 0x0020000, + EDIT: 0x0040000, + SORT: 0x0080000, + FILESELECT: 0x0100000, + MULTISELECT: 0x0200000, + DONOTSPELLCHECK: 0x0400000, + DONOTSCROLL: 0x0800000, + COMB: 0x1000000, + RICHTEXT: 0x2000000, + RADIOSINUNISON: 0x2000000, + COMMITONSELCHANGE: 0x4000000 + }; + exports.AnnotationFieldFlag = AnnotationFieldFlag; + const AnnotationBorderStyleType = { + SOLID: 1, + DASHED: 2, + BEVELED: 3, + INSET: 4, + UNDERLINE: 5 + }; + exports.AnnotationBorderStyleType = AnnotationBorderStyleType; + const AnnotationActionEventType = { + E: "Mouse Enter", + X: "Mouse Exit", + D: "Mouse Down", + U: "Mouse Up", + Fo: "Focus", + Bl: "Blur", + PO: "PageOpen", + PC: "PageClose", + PV: "PageVisible", + PI: "PageInvisible", + K: "Keystroke", + F: "Format", + V: "Validate", + C: "Calculate" + }; + exports.AnnotationActionEventType = AnnotationActionEventType; + const DocumentActionEventType = { + WC: "WillClose", + WS: "WillSave", + DS: "DidSave", + WP: "WillPrint", + DP: "DidPrint" + }; + exports.DocumentActionEventType = DocumentActionEventType; + const PageActionEventType = { + O: "PageOpen", + C: "PageClose" + }; + exports.PageActionEventType = PageActionEventType; + const StreamType = { + UNKNOWN: "UNKNOWN", + FLATE: "FLATE", + LZW: "LZW", + DCT: "DCT", + JPX: "JPX", + JBIG: "JBIG", + A85: "A85", + AHX: "AHX", + CCF: "CCF", + RLX: "RLX" + }; + exports.StreamType = StreamType; + const FontType = { + UNKNOWN: "UNKNOWN", + TYPE1: "TYPE1", + TYPE1STANDARD: "TYPE1STANDARD", + TYPE1C: "TYPE1C", + CIDFONTTYPE0: "CIDFONTTYPE0", + CIDFONTTYPE0C: "CIDFONTTYPE0C", + TRUETYPE: "TRUETYPE", + CIDFONTTYPE2: "CIDFONTTYPE2", + TYPE3: "TYPE3", + OPENTYPE: "OPENTYPE", + TYPE0: "TYPE0", + MMTYPE1: "MMTYPE1" + }; + exports.FontType = FontType; + const VerbosityLevel = { + ERRORS: 0, + WARNINGS: 1, + INFOS: 5 + }; + exports.VerbosityLevel = VerbosityLevel; + const CMapCompressionType = { + NONE: 0, + BINARY: 1, + STREAM: 2 + }; + exports.CMapCompressionType = CMapCompressionType; + const OPS = { + dependency: 1, + setLineWidth: 2, + setLineCap: 3, + setLineJoin: 4, + setMiterLimit: 5, + setDash: 6, + setRenderingIntent: 7, + setFlatness: 8, + setGState: 9, + save: 10, + restore: 11, + transform: 12, + moveTo: 13, + lineTo: 14, + curveTo: 15, + curveTo2: 16, + curveTo3: 17, + closePath: 18, + rectangle: 19, + stroke: 20, + closeStroke: 21, + fill: 22, + eoFill: 23, + fillStroke: 24, + eoFillStroke: 25, + closeFillStroke: 26, + closeEOFillStroke: 27, + endPath: 28, + clip: 29, + eoClip: 30, + beginText: 31, + endText: 32, + setCharSpacing: 33, + setWordSpacing: 34, + setHScale: 35, + setLeading: 36, + setFont: 37, + setTextRenderingMode: 38, + setTextRise: 39, + moveText: 40, + setLeadingMoveText: 41, + setTextMatrix: 42, + nextLine: 43, + showText: 44, + showSpacedText: 45, + nextLineShowText: 46, + nextLineSetSpacingShowText: 47, + setCharWidth: 48, + setCharWidthAndBounds: 49, + setStrokeColorSpace: 50, + setFillColorSpace: 51, + setStrokeColor: 52, + setStrokeColorN: 53, + setFillColor: 54, + setFillColorN: 55, + setStrokeGray: 56, + setFillGray: 57, + setStrokeRGBColor: 58, + setFillRGBColor: 59, + setStrokeCMYKColor: 60, + setFillCMYKColor: 61, + shadingFill: 62, + beginInlineImage: 63, + beginImageData: 64, + endInlineImage: 65, + paintXObject: 66, + markPoint: 67, + markPointProps: 68, + beginMarkedContent: 69, + beginMarkedContentProps: 70, + endMarkedContent: 71, + beginCompat: 72, + endCompat: 73, + paintFormXObjectBegin: 74, + paintFormXObjectEnd: 75, + beginGroup: 76, + endGroup: 77, + beginAnnotations: 78, + endAnnotations: 79, + beginAnnotation: 80, + endAnnotation: 81, + paintJpegXObject: 82, + paintImageMaskXObject: 83, + paintImageMaskXObjectGroup: 84, + paintImageXObject: 85, + paintInlineImageXObject: 86, + paintInlineImageXObjectGroup: 87, + paintImageXObjectRepeat: 88, + paintImageMaskXObjectRepeat: 89, + paintSolidColorImageMask: 90, + constructPath: 91 + }; + exports.OPS = OPS; + const UNSUPPORTED_FEATURES = { + unknown: "unknown", + forms: "forms", + javaScript: "javaScript", + signatures: "signatures", + smask: "smask", + shadingPattern: "shadingPattern", + font: "font", + errorTilingPattern: "errorTilingPattern", + errorExtGState: "errorExtGState", + errorXObject: "errorXObject", + errorFontLoadType3: "errorFontLoadType3", + errorFontState: "errorFontState", + errorFontMissing: "errorFontMissing", + errorFontTranslate: "errorFontTranslate", + errorColorSpace: "errorColorSpace", + errorOperatorList: "errorOperatorList", + errorFontToUnicode: "errorFontToUnicode", + errorFontLoadNative: "errorFontLoadNative", + errorFontBuildPath: "errorFontBuildPath", + errorFontGetPath: "errorFontGetPath", + errorMarkedContent: "errorMarkedContent", + errorContentSubStream: "errorContentSubStream" + }; + exports.UNSUPPORTED_FEATURES = UNSUPPORTED_FEATURES; + const PasswordResponses = { + NEED_PASSWORD: 1, + INCORRECT_PASSWORD: 2 + }; + exports.PasswordResponses = PasswordResponses; + let verbosity = VerbosityLevel.WARNINGS; + + function setVerbosityLevel(level) { + if (Number.isInteger(level)) { + verbosity = level; + } + } + + function getVerbosityLevel() { + return verbosity; + } + + function info(msg) { + if (verbosity >= VerbosityLevel.INFOS) { + console.log(`Info: ${msg}`); + } + } + + function warn(msg) { + if (verbosity >= VerbosityLevel.WARNINGS) { + console.log(`Warning: ${msg}`); + } + } + + function unreachable(msg) { + throw new Error(msg); + } + + function assert(cond, msg) { + if (!cond) { + unreachable(msg); + } + } + + function _isValidProtocol(url) { + if (!url) { + return false; + } + + switch (url.protocol) { + case "http:": + case "https:": + case "ftp:": + case "mailto:": + case "tel:": + return true; + + default: + return false; + } + } + + function createValidAbsoluteUrl(url, baseUrl = null, options = null) { + if (!url) { + return null; + } + + try { + if (options && typeof url === "string") { + if (options.addDefaultProtocol && url.startsWith("www.")) { + const dots = url.match(/\./g); + + if (dots && dots.length >= 2) { + url = `http://${url}`; + } + } + + if (options.tryConvertEncoding) { + try { + url = stringToUTF8String(url); + } catch (ex) {} + } + } + + const absoluteUrl = baseUrl ? new URL(url, baseUrl) : new URL(url); + + if (_isValidProtocol(absoluteUrl)) { + return absoluteUrl; + } + } catch (ex) {} + + return null; + } + + function shadow(obj, prop, value) { + Object.defineProperty(obj, prop, { + value, + enumerable: true, + configurable: true, + writable: false + }); + return value; + } + + const BaseException = function BaseExceptionClosure() { + function BaseException(message, name) { + if (this.constructor === BaseException) { + unreachable("Cannot initialize BaseException."); + } + + this.message = message; + this.name = name; + } + + BaseException.prototype = new Error(); + BaseException.constructor = BaseException; + return BaseException; + }(); + + exports.BaseException = BaseException; + + class PasswordException extends BaseException { + constructor(msg, code) { + super(msg, "PasswordException"); + this.code = code; + } + + } + + exports.PasswordException = PasswordException; + + class UnknownErrorException extends BaseException { + constructor(msg, details) { + super(msg, "UnknownErrorException"); + this.details = details; + } + + } + + exports.UnknownErrorException = UnknownErrorException; + + class InvalidPDFException extends BaseException { + constructor(msg) { + super(msg, "InvalidPDFException"); + } + + } + + exports.InvalidPDFException = InvalidPDFException; + + class MissingPDFException extends BaseException { + constructor(msg) { + super(msg, "MissingPDFException"); + } + + } + + exports.MissingPDFException = MissingPDFException; + + class UnexpectedResponseException extends BaseException { + constructor(msg, status) { + super(msg, "UnexpectedResponseException"); + this.status = status; + } + + } + + exports.UnexpectedResponseException = UnexpectedResponseException; + + class FormatError extends BaseException { + constructor(msg) { + super(msg, "FormatError"); + } + + } + + exports.FormatError = FormatError; + + class AbortException extends BaseException { + constructor(msg) { + super(msg, "AbortException"); + } + + } + + exports.AbortException = AbortException; + + function bytesToString(bytes) { + if (typeof bytes !== "object" || bytes === null || bytes.length === undefined) { + unreachable("Invalid argument for bytesToString"); + } + + const length = bytes.length; + const MAX_ARGUMENT_COUNT = 8192; + + if (length < MAX_ARGUMENT_COUNT) { + return String.fromCharCode.apply(null, bytes); + } + + const strBuf = []; + + for (let i = 0; i < length; i += MAX_ARGUMENT_COUNT) { + const chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length); + const chunk = bytes.subarray(i, chunkEnd); + strBuf.push(String.fromCharCode.apply(null, chunk)); + } + + return strBuf.join(""); + } + + function stringToBytes(str) { + if (typeof str !== "string") { + unreachable("Invalid argument for stringToBytes"); + } + + const length = str.length; + const bytes = new Uint8Array(length); + + for (let i = 0; i < length; ++i) { + bytes[i] = str.charCodeAt(i) & 0xff; + } + + return bytes; + } + + function arrayByteLength(arr) { + if (arr.length !== undefined) { + return arr.length; + } + + if (arr.byteLength !== undefined) { + return arr.byteLength; + } + + unreachable("Invalid argument for arrayByteLength"); + } + + function arraysToBytes(arr) { + const length = arr.length; + + if (length === 1 && arr[0] instanceof Uint8Array) { + return arr[0]; + } + + let resultLength = 0; + + for (let i = 0; i < length; i++) { + resultLength += arrayByteLength(arr[i]); + } + + let pos = 0; + const data = new Uint8Array(resultLength); + + for (let i = 0; i < length; i++) { + let item = arr[i]; + + if (!(item instanceof Uint8Array)) { + if (typeof item === "string") { + item = stringToBytes(item); + } else { + item = new Uint8Array(item); + } + } + + const itemLength = item.byteLength; + data.set(item, pos); + pos += itemLength; + } + + return data; + } + + function string32(value) { + return String.fromCharCode(value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff); + } + + function objectSize(obj) { + return Object.keys(obj).length; + } + + function objectFromMap(map) { + const obj = Object.create(null); + + for (const [key, value] of map) { + obj[key] = value; + } + + return obj; + } + + function isLittleEndian() { + const buffer8 = new Uint8Array(4); + buffer8[0] = 1; + const view32 = new Uint32Array(buffer8.buffer, 0, 1); + return view32[0] === 1; + } + + function isEvalSupported() { + try { + new Function(""); + return true; + } catch (e) { + return false; + } + } + + class FeatureTest { + static get isLittleEndian() { + return shadow(this, "isLittleEndian", isLittleEndian()); + } + + static get isEvalSupported() { + return shadow(this, "isEvalSupported", isEvalSupported()); + } + + static get isOffscreenCanvasSupported() { + return shadow(this, "isOffscreenCanvasSupported", typeof OffscreenCanvas !== "undefined"); + } + + } + + exports.FeatureTest = FeatureTest; + const hexNumbers = [...Array(256).keys()].map(n => n.toString(16).padStart(2, "0")); + + class Util { + static makeHexColor(r, g, b) { + return `#${hexNumbers[r]}${hexNumbers[g]}${hexNumbers[b]}`; + } + + static scaleMinMax(transform, minMax) { + let temp; + + if (transform[0]) { + if (transform[0] < 0) { + temp = minMax[0]; + minMax[0] = minMax[1]; + minMax[1] = temp; + } + + minMax[0] *= transform[0]; + minMax[1] *= transform[0]; + + if (transform[3] < 0) { + temp = minMax[2]; + minMax[2] = minMax[3]; + minMax[3] = temp; + } + + minMax[2] *= transform[3]; + minMax[3] *= transform[3]; + } else { + temp = minMax[0]; + minMax[0] = minMax[2]; + minMax[2] = temp; + temp = minMax[1]; + minMax[1] = minMax[3]; + minMax[3] = temp; + + if (transform[1] < 0) { + temp = minMax[2]; + minMax[2] = minMax[3]; + minMax[3] = temp; + } + + minMax[2] *= transform[1]; + minMax[3] *= transform[1]; + + if (transform[2] < 0) { + temp = minMax[0]; + minMax[0] = minMax[1]; + minMax[1] = temp; + } + + minMax[0] *= transform[2]; + minMax[1] *= transform[2]; + } + + minMax[0] += transform[4]; + minMax[1] += transform[4]; + minMax[2] += transform[5]; + minMax[3] += transform[5]; + } + + static transform(m1, m2) { + return [m1[0] * m2[0] + m1[2] * m2[1], m1[1] * m2[0] + m1[3] * m2[1], m1[0] * m2[2] + m1[2] * m2[3], m1[1] * m2[2] + m1[3] * m2[3], m1[0] * m2[4] + m1[2] * m2[5] + m1[4], m1[1] * m2[4] + m1[3] * m2[5] + m1[5]]; + } + + static applyTransform(p, m) { + const xt = p[0] * m[0] + p[1] * m[2] + m[4]; + const yt = p[0] * m[1] + p[1] * m[3] + m[5]; + return [xt, yt]; + } + + static applyInverseTransform(p, m) { + const d = m[0] * m[3] - m[1] * m[2]; + const xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d; + const yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d; + return [xt, yt]; + } + + static getAxialAlignedBoundingBox(r, m) { + const p1 = Util.applyTransform(r, m); + const p2 = Util.applyTransform(r.slice(2, 4), m); + const p3 = Util.applyTransform([r[0], r[3]], m); + const p4 = Util.applyTransform([r[2], r[1]], m); + return [Math.min(p1[0], p2[0], p3[0], p4[0]), Math.min(p1[1], p2[1], p3[1], p4[1]), Math.max(p1[0], p2[0], p3[0], p4[0]), Math.max(p1[1], p2[1], p3[1], p4[1])]; + } + + static inverseTransform(m) { + const d = m[0] * m[3] - m[1] * m[2]; + return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d, (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d]; + } + + static apply3dTransform(m, v) { + return [m[0] * v[0] + m[1] * v[1] + m[2] * v[2], m[3] * v[0] + m[4] * v[1] + m[5] * v[2], m[6] * v[0] + m[7] * v[1] + m[8] * v[2]]; + } + + static singularValueDecompose2dScale(m) { + const transpose = [m[0], m[2], m[1], m[3]]; + const a = m[0] * transpose[0] + m[1] * transpose[2]; + const b = m[0] * transpose[1] + m[1] * transpose[3]; + const c = m[2] * transpose[0] + m[3] * transpose[2]; + const d = m[2] * transpose[1] + m[3] * transpose[3]; + const first = (a + d) / 2; + const second = Math.sqrt((a + d) ** 2 - 4 * (a * d - c * b)) / 2; + const sx = first + second || 1; + const sy = first - second || 1; + return [Math.sqrt(sx), Math.sqrt(sy)]; + } + + static normalizeRect(rect) { + const r = rect.slice(0); + + if (rect[0] > rect[2]) { + r[0] = rect[2]; + r[2] = rect[0]; + } + + if (rect[1] > rect[3]) { + r[1] = rect[3]; + r[3] = rect[1]; + } + + return r; + } + + static intersect(rect1, rect2) { + const xLow = Math.max(Math.min(rect1[0], rect1[2]), Math.min(rect2[0], rect2[2])); + const xHigh = Math.min(Math.max(rect1[0], rect1[2]), Math.max(rect2[0], rect2[2])); + + if (xLow > xHigh) { + return null; + } + + const yLow = Math.max(Math.min(rect1[1], rect1[3]), Math.min(rect2[1], rect2[3])); + const yHigh = Math.min(Math.max(rect1[1], rect1[3]), Math.max(rect2[1], rect2[3])); + + if (yLow > yHigh) { + return null; + } + + return [xLow, yLow, xHigh, yHigh]; + } + + static bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3) { + const tvalues = [], + bounds = [[], []]; + let a, b, c, t, t1, t2, b2ac, sqrtb2ac; + + for (let i = 0; i < 2; ++i) { + if (i === 0) { + b = 6 * x0 - 12 * x1 + 6 * x2; + a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3; + c = 3 * x1 - 3 * x0; + } else { + b = 6 * y0 - 12 * y1 + 6 * y2; + a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3; + c = 3 * y1 - 3 * y0; + } + + if (Math.abs(a) < 1e-12) { + if (Math.abs(b) < 1e-12) { + continue; + } + + t = -c / b; + + if (0 < t && t < 1) { + tvalues.push(t); + } + + continue; + } + + b2ac = b * b - 4 * c * a; + sqrtb2ac = Math.sqrt(b2ac); + + if (b2ac < 0) { + continue; + } + + t1 = (-b + sqrtb2ac) / (2 * a); + + if (0 < t1 && t1 < 1) { + tvalues.push(t1); + } + + t2 = (-b - sqrtb2ac) / (2 * a); + + if (0 < t2 && t2 < 1) { + tvalues.push(t2); + } + } + + let j = tvalues.length, + mt; + const jlen = j; + + while (j--) { + t = tvalues[j]; + mt = 1 - t; + bounds[0][j] = mt * mt * mt * x0 + 3 * mt * mt * t * x1 + 3 * mt * t * t * x2 + t * t * t * x3; + bounds[1][j] = mt * mt * mt * y0 + 3 * mt * mt * t * y1 + 3 * mt * t * t * y2 + t * t * t * y3; + } + + bounds[0][jlen] = x0; + bounds[1][jlen] = y0; + bounds[0][jlen + 1] = x3; + bounds[1][jlen + 1] = y3; + bounds[0].length = bounds[1].length = jlen + 2; + return [Math.min(...bounds[0]), Math.min(...bounds[1]), Math.max(...bounds[0]), Math.max(...bounds[1])]; + } + + } + + exports.Util = Util; + const PDFStringTranslateTable = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2d8, 0x2c7, 0x2c6, 0x2d9, 0x2dd, 0x2db, 0x2da, 0x2dc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x192, 0x2044, 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018, 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x141, 0x152, 0x160, 0x178, 0x17d, 0x131, 0x142, 0x153, 0x161, 0x17e, 0, 0x20ac]; + + function stringToPDFString(str) { + if (str[0] >= "\xEF") { + let encoding; + + if (str[0] === "\xFE" && str[1] === "\xFF") { + encoding = "utf-16be"; + } else if (str[0] === "\xFF" && str[1] === "\xFE") { + encoding = "utf-16le"; + } else if (str[0] === "\xEF" && str[1] === "\xBB" && str[2] === "\xBF") { + encoding = "utf-8"; + } + + if (encoding) { + try { + const decoder = new TextDecoder(encoding, { + fatal: true + }); + const buffer = stringToBytes(str); + return decoder.decode(buffer); + } catch (ex) { + warn(`stringToPDFString: "${ex}".`); + } + } + } + + const strBuf = []; + + for (let i = 0, ii = str.length; i < ii; i++) { + const code = PDFStringTranslateTable[str.charCodeAt(i)]; + strBuf.push(code ? String.fromCharCode(code) : str.charAt(i)); + } + + return strBuf.join(""); + } + + function escapeString(str) { + return str.replace(/([()\\\n\r])/g, match => { + if (match === "\n") { + return "\\n"; + } else if (match === "\r") { + return "\\r"; + } + + return `\\${match}`; + }); + } + + function isAscii(str) { + return /^[\x00-\x7F]*$/.test(str); + } + + function stringToUTF16BEString(str) { + const buf = ["\xFE\xFF"]; + + for (let i = 0, ii = str.length; i < ii; i++) { + const char = str.charCodeAt(i); + buf.push(String.fromCharCode(char >> 8 & 0xff), String.fromCharCode(char & 0xff)); + } + + return buf.join(""); + } + + function stringToUTF8String(str) { + return decodeURIComponent(escape(str)); + } + + function utf8StringToString(str) { + return unescape(encodeURIComponent(str)); + } + + function isArrayBuffer(v) { + return typeof v === "object" && v !== null && v.byteLength !== undefined; + } + + function isArrayEqual(arr1, arr2) { + if (arr1.length !== arr2.length) { + return false; + } + + for (let i = 0, ii = arr1.length; i < ii; i++) { + if (arr1[i] !== arr2[i]) { + return false; + } + } + + return true; + } + + function getModificationDate(date = new Date()) { + const buffer = [date.getUTCFullYear().toString(), (date.getUTCMonth() + 1).toString().padStart(2, "0"), date.getUTCDate().toString().padStart(2, "0"), date.getUTCHours().toString().padStart(2, "0"), date.getUTCMinutes().toString().padStart(2, "0"), date.getUTCSeconds().toString().padStart(2, "0")]; + return buffer.join(""); + } + + function createPromiseCapability() { + const capability = Object.create(null); + let isSettled = false; + Object.defineProperty(capability, "settled", { + get() { + return isSettled; + } + + }); + capability.promise = new Promise(function (resolve, reject) { + capability.resolve = function (data) { + isSettled = true; + resolve(data); + }; + + capability.reject = function (reason) { + isSettled = true; + reject(reason); + }; + }); + return capability; + } + + /***/ }), + /* 2 */ + /***/ ((__unused_webpack_module, __unused_webpack_exports, __w_pdfjs_require__) => { + + + + __w_pdfjs_require__(3); + + /***/ }), + /* 3 */ + /***/ ((__unused_webpack_module, exports) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.isNodeJS = void 0; + const isNodeJS = typeof process === "object" && process + "" === "[object process]" && !process.versions.nw && !(process.versions.electron && process.type && process.type !== "browser"); + exports.isNodeJS = isNodeJS; + + /***/ }), + /* 4 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.build = exports.RenderTask = exports.PDFWorkerUtil = exports.PDFWorker = exports.PDFPageProxy = exports.PDFDocumentProxy = exports.PDFDocumentLoadingTask = exports.PDFDataRangeTransport = exports.LoopbackPort = exports.DefaultStandardFontDataFactory = exports.DefaultCanvasFactory = exports.DefaultCMapReaderFactory = void 0; + exports.getDocument = getDocument; + exports.setPDFNetworkStreamFactory = setPDFNetworkStreamFactory; + exports.version = void 0; + + var _util = __w_pdfjs_require__(1); + + var _annotation_storage = __w_pdfjs_require__(5); + + var _display_utils = __w_pdfjs_require__(8); + + var _font_loader = __w_pdfjs_require__(11); + + var _canvas = __w_pdfjs_require__(12); + + var _worker_options = __w_pdfjs_require__(15); + + var _is_node = __w_pdfjs_require__(3); + + var _message_handler = __w_pdfjs_require__(16); + + var _metadata = __w_pdfjs_require__(17); + + var _optional_content_config = __w_pdfjs_require__(18); + + var _transport_stream = __w_pdfjs_require__(19); + + var _xfa_text = __w_pdfjs_require__(20); + + const DEFAULT_RANGE_CHUNK_SIZE = 65536; + const RENDERING_CANCELLED_TIMEOUT = 100; + let DefaultCanvasFactory = _display_utils.DOMCanvasFactory; + exports.DefaultCanvasFactory = DefaultCanvasFactory; + let DefaultCMapReaderFactory = _display_utils.DOMCMapReaderFactory; + exports.DefaultCMapReaderFactory = DefaultCMapReaderFactory; + let DefaultStandardFontDataFactory = _display_utils.DOMStandardFontDataFactory; + exports.DefaultStandardFontDataFactory = DefaultStandardFontDataFactory; + + if (_is_node.isNodeJS) { + const { + NodeCanvasFactory, + NodeCMapReaderFactory, + NodeStandardFontDataFactory + } = __w_pdfjs_require__(21); + + exports.DefaultCanvasFactory = DefaultCanvasFactory = NodeCanvasFactory; + exports.DefaultCMapReaderFactory = DefaultCMapReaderFactory = NodeCMapReaderFactory; + exports.DefaultStandardFontDataFactory = DefaultStandardFontDataFactory = NodeStandardFontDataFactory; + } + + let createPDFNetworkStream; + + function setPDFNetworkStreamFactory(pdfNetworkStreamFactory) { + createPDFNetworkStream = pdfNetworkStreamFactory; + } + + function getDocument(src) { + const task = new PDFDocumentLoadingTask(); + let source; + + if (typeof src === "string" || src instanceof URL) { + source = { + url: src + }; + } else if ((0, _util.isArrayBuffer)(src)) { + source = { + data: src + }; + } else if (src instanceof PDFDataRangeTransport) { + source = { + range: src + }; + } else { + if (typeof src !== "object") { + throw new Error("Invalid parameter in getDocument, " + "need either string, URL, TypedArray, or parameter object."); + } + + if (!src.url && !src.data && !src.range) { + throw new Error("Invalid parameter object: need either .data, .range or .url"); + } + + source = src; + } + + const params = Object.create(null); + let rangeTransport = null, + worker = null; + + for (const key in source) { + const value = source[key]; + + switch (key) { + case "url": + if (typeof window !== "undefined") { + try { + params[key] = new URL(value, window.location).href; + continue; + } catch (ex) { + (0, _util.warn)(`Cannot create valid URL: "${ex}".`); + } + } else if (typeof value === "string" || value instanceof URL) { + params[key] = value.toString(); + continue; + } + + throw new Error("Invalid PDF url data: " + "either string or URL-object is expected in the url property."); + + case "range": + rangeTransport = value; + continue; + + case "worker": + worker = value; + continue; + + case "data": + if (_is_node.isNodeJS && typeof Buffer !== "undefined" && value instanceof Buffer) { + params[key] = new Uint8Array(value); + } else if (value instanceof Uint8Array) { + break; + } else if (typeof value === "string") { + params[key] = (0, _util.stringToBytes)(value); + } else if (typeof value === "object" && value !== null && !isNaN(value.length)) { + params[key] = new Uint8Array(value); + } else if ((0, _util.isArrayBuffer)(value)) { + params[key] = new Uint8Array(value); + } else { + throw new Error("Invalid PDF binary data: either TypedArray, " + "string, or array-like object is expected in the data property."); + } + + continue; + } + + params[key] = value; + } + + params.CMapReaderFactory = params.CMapReaderFactory || DefaultCMapReaderFactory; + params.StandardFontDataFactory = params.StandardFontDataFactory || DefaultStandardFontDataFactory; + params.ignoreErrors = params.stopAtErrors !== true; + params.fontExtraProperties = params.fontExtraProperties === true; + params.pdfBug = params.pdfBug === true; + params.enableXfa = params.enableXfa === true; + + if (!Number.isInteger(params.rangeChunkSize) || params.rangeChunkSize < 1) { + params.rangeChunkSize = DEFAULT_RANGE_CHUNK_SIZE; + } + + if (typeof params.docBaseUrl !== "string" || (0, _display_utils.isDataScheme)(params.docBaseUrl)) { + params.docBaseUrl = null; + } + + if (!Number.isInteger(params.maxImageSize) || params.maxImageSize < -1) { + params.maxImageSize = -1; + } + + if (typeof params.cMapUrl !== "string") { + params.cMapUrl = null; + } + + if (typeof params.standardFontDataUrl !== "string") { + params.standardFontDataUrl = null; + } + + if (typeof params.useWorkerFetch !== "boolean") { + params.useWorkerFetch = params.CMapReaderFactory === _display_utils.DOMCMapReaderFactory && params.StandardFontDataFactory === _display_utils.DOMStandardFontDataFactory; + } + + if (typeof params.isEvalSupported !== "boolean") { + params.isEvalSupported = true; + } + + if (typeof params.disableFontFace !== "boolean") { + params.disableFontFace = _is_node.isNodeJS; + } + + if (typeof params.useSystemFonts !== "boolean") { + params.useSystemFonts = !_is_node.isNodeJS && !params.disableFontFace; + } + + if (typeof params.ownerDocument !== "object" || params.ownerDocument === null) { + params.ownerDocument = globalThis.document; + } + + if (typeof params.disableRange !== "boolean") { + params.disableRange = false; + } + + if (typeof params.disableStream !== "boolean") { + params.disableStream = false; + } + + if (typeof params.disableAutoFetch !== "boolean") { + params.disableAutoFetch = false; + } + + (0, _util.setVerbosityLevel)(params.verbosity); + + if (!worker) { + const workerParams = { + verbosity: params.verbosity, + port: _worker_options.GlobalWorkerOptions.workerPort + }; + worker = workerParams.port ? PDFWorker.fromPort(workerParams) : new PDFWorker(workerParams); + task._worker = worker; + } + + const docId = task.docId; + worker.promise.then(function () { + if (task.destroyed) { + throw new Error("Loading aborted"); + } + + const workerIdPromise = _fetchDocument(worker, params, rangeTransport, docId); + + const networkStreamPromise = new Promise(function (resolve) { + let networkStream; + + if (rangeTransport) { + networkStream = new _transport_stream.PDFDataTransportStream({ + length: params.length, + initialData: params.initialData, + progressiveDone: params.progressiveDone, + contentDispositionFilename: params.contentDispositionFilename, + disableRange: params.disableRange, + disableStream: params.disableStream + }, rangeTransport); + } else if (!params.data) { + networkStream = createPDFNetworkStream({ + url: params.url, + length: params.length, + httpHeaders: params.httpHeaders, + withCredentials: params.withCredentials, + rangeChunkSize: params.rangeChunkSize, + disableRange: params.disableRange, + disableStream: params.disableStream + }); + } + + resolve(networkStream); + }); + return Promise.all([workerIdPromise, networkStreamPromise]).then(function ([workerId, networkStream]) { + if (task.destroyed) { + throw new Error("Loading aborted"); + } + + const messageHandler = new _message_handler.MessageHandler(docId, workerId, worker.port); + const transport = new WorkerTransport(messageHandler, task, networkStream, params); + task._transport = transport; + messageHandler.send("Ready", null); + }); + }).catch(task._capability.reject); + return task; + } + + async function _fetchDocument(worker, source, pdfDataRangeTransport, docId) { + if (worker.destroyed) { + throw new Error("Worker was destroyed"); + } + + if (pdfDataRangeTransport) { + source.length = pdfDataRangeTransport.length; + source.initialData = pdfDataRangeTransport.initialData; + source.progressiveDone = pdfDataRangeTransport.progressiveDone; + source.contentDispositionFilename = pdfDataRangeTransport.contentDispositionFilename; + } + + const workerId = await worker.messageHandler.sendWithPromise("GetDocRequest", { + docId, + apiVersion: '2.16.105', + source: { + data: source.data, + url: source.url, + password: source.password, + disableAutoFetch: source.disableAutoFetch, + rangeChunkSize: source.rangeChunkSize, + length: source.length + }, + maxImageSize: source.maxImageSize, + disableFontFace: source.disableFontFace, + docBaseUrl: source.docBaseUrl, + ignoreErrors: source.ignoreErrors, + isEvalSupported: source.isEvalSupported, + fontExtraProperties: source.fontExtraProperties, + enableXfa: source.enableXfa, + useSystemFonts: source.useSystemFonts, + cMapUrl: source.useWorkerFetch ? source.cMapUrl : null, + standardFontDataUrl: source.useWorkerFetch ? source.standardFontDataUrl : null + }); + + if (source.data) { + source.data = null; + } + + if (worker.destroyed) { + throw new Error("Worker was destroyed"); + } + + return workerId; + } + + class PDFDocumentLoadingTask { + static #docId = 0; + + constructor() { + this._capability = (0, _util.createPromiseCapability)(); + this._transport = null; + this._worker = null; + this.docId = `d${PDFDocumentLoadingTask.#docId++}`; + this.destroyed = false; + this.onPassword = null; + this.onProgress = null; + this.onUnsupportedFeature = null; + } + + get promise() { + return this._capability.promise; + } + + async destroy() { + this.destroyed = true; + await this._transport?.destroy(); + this._transport = null; + + if (this._worker) { + this._worker.destroy(); + + this._worker = null; + } + } + + } + + exports.PDFDocumentLoadingTask = PDFDocumentLoadingTask; + + class PDFDataRangeTransport { + constructor(length, initialData, progressiveDone = false, contentDispositionFilename = null) { + this.length = length; + this.initialData = initialData; + this.progressiveDone = progressiveDone; + this.contentDispositionFilename = contentDispositionFilename; + this._rangeListeners = []; + this._progressListeners = []; + this._progressiveReadListeners = []; + this._progressiveDoneListeners = []; + this._readyCapability = (0, _util.createPromiseCapability)(); + } + + addRangeListener(listener) { + this._rangeListeners.push(listener); + } + + addProgressListener(listener) { + this._progressListeners.push(listener); + } + + addProgressiveReadListener(listener) { + this._progressiveReadListeners.push(listener); + } + + addProgressiveDoneListener(listener) { + this._progressiveDoneListeners.push(listener); + } + + onDataRange(begin, chunk) { + for (const listener of this._rangeListeners) { + listener(begin, chunk); + } + } + + onDataProgress(loaded, total) { + this._readyCapability.promise.then(() => { + for (const listener of this._progressListeners) { + listener(loaded, total); + } + }); + } + + onDataProgressiveRead(chunk) { + this._readyCapability.promise.then(() => { + for (const listener of this._progressiveReadListeners) { + listener(chunk); + } + }); + } + + onDataProgressiveDone() { + this._readyCapability.promise.then(() => { + for (const listener of this._progressiveDoneListeners) { + listener(); + } + }); + } + + transportReady() { + this._readyCapability.resolve(); + } + + requestDataRange(begin, end) { + (0, _util.unreachable)("Abstract method PDFDataRangeTransport.requestDataRange"); + } + + abort() {} + + } + + exports.PDFDataRangeTransport = PDFDataRangeTransport; + + class PDFDocumentProxy { + constructor(pdfInfo, transport) { + this._pdfInfo = pdfInfo; + this._transport = transport; + Object.defineProperty(this, "fingerprint", { + get() { + (0, _display_utils.deprecated)("`PDFDocumentProxy.fingerprint`, " + "please use `PDFDocumentProxy.fingerprints` instead."); + return this.fingerprints[0]; + } + + }); + Object.defineProperty(this, "getStats", { + value: async () => { + (0, _display_utils.deprecated)("`PDFDocumentProxy.getStats`, " + "please use the `PDFDocumentProxy.stats`-getter instead."); + return this.stats || { + streamTypes: {}, + fontTypes: {} + }; + } + }); + } + + get annotationStorage() { + return this._transport.annotationStorage; + } + + get numPages() { + return this._pdfInfo.numPages; + } + + get fingerprints() { + return this._pdfInfo.fingerprints; + } + + get stats() { + return this._transport.stats; + } + + get isPureXfa() { + return !!this._transport._htmlForXfa; + } + + get allXfaHtml() { + return this._transport._htmlForXfa; + } + + getPage(pageNumber) { + return this._transport.getPage(pageNumber); + } + + getPageIndex(ref) { + return this._transport.getPageIndex(ref); + } + + getDestinations() { + return this._transport.getDestinations(); + } + + getDestination(id) { + return this._transport.getDestination(id); + } + + getPageLabels() { + return this._transport.getPageLabels(); + } + + getPageLayout() { + return this._transport.getPageLayout(); + } + + getPageMode() { + return this._transport.getPageMode(); + } + + getViewerPreferences() { + return this._transport.getViewerPreferences(); + } + + getOpenAction() { + return this._transport.getOpenAction(); + } + + getAttachments() { + return this._transport.getAttachments(); + } + + getJavaScript() { + return this._transport.getJavaScript(); + } + + getJSActions() { + return this._transport.getDocJSActions(); + } + + getOutline() { + return this._transport.getOutline(); + } + + getOptionalContentConfig() { + return this._transport.getOptionalContentConfig(); + } + + getPermissions() { + return this._transport.getPermissions(); + } + + getMetadata() { + return this._transport.getMetadata(); + } + + getMarkInfo() { + return this._transport.getMarkInfo(); + } + + getData() { + return this._transport.getData(); + } + + getDownloadInfo() { + return this._transport.downloadInfoCapability.promise; + } + + cleanup(keepLoadedFonts = false) { + return this._transport.startCleanup(keepLoadedFonts || this.isPureXfa); + } + + destroy() { + return this.loadingTask.destroy(); + } + + get loadingParams() { + return this._transport.loadingParams; + } + + get loadingTask() { + return this._transport.loadingTask; + } + + saveDocument() { + if (this._transport.annotationStorage.size <= 0) { + (0, _display_utils.deprecated)("saveDocument called while `annotationStorage` is empty, " + "please use the getData-method instead."); + } + + return this._transport.saveDocument(); + } + + getFieldObjects() { + return this._transport.getFieldObjects(); + } + + hasJSActions() { + return this._transport.hasJSActions(); + } + + getCalculationOrderIds() { + return this._transport.getCalculationOrderIds(); + } + + } + + exports.PDFDocumentProxy = PDFDocumentProxy; + + class PDFPageProxy { + constructor(pageIndex, pageInfo, transport, ownerDocument, pdfBug = false) { + this._pageIndex = pageIndex; + this._pageInfo = pageInfo; + this._ownerDocument = ownerDocument; + this._transport = transport; + this._stats = pdfBug ? new _display_utils.StatTimer() : null; + this._pdfBug = pdfBug; + this.commonObjs = transport.commonObjs; + this.objs = new PDFObjects(); + this._bitmaps = new Set(); + this.cleanupAfterRender = false; + this.pendingCleanup = false; + this._intentStates = new Map(); + this._annotationPromises = new Map(); + this.destroyed = false; + } + + get pageNumber() { + return this._pageIndex + 1; + } + + get rotate() { + return this._pageInfo.rotate; + } + + get ref() { + return this._pageInfo.ref; + } + + get userUnit() { + return this._pageInfo.userUnit; + } + + get view() { + return this._pageInfo.view; + } + + getViewport({ + scale, + rotation = this.rotate, + offsetX = 0, + offsetY = 0, + dontFlip = false + } = {}) { + return new _display_utils.PageViewport({ + viewBox: this.view, + scale, + rotation, + offsetX, + offsetY, + dontFlip + }); + } + + getAnnotations({ + intent = "display" + } = {}) { + const intentArgs = this._transport.getRenderingIntent(intent); + + let promise = this._annotationPromises.get(intentArgs.cacheKey); + + if (!promise) { + promise = this._transport.getAnnotations(this._pageIndex, intentArgs.renderingIntent); + + this._annotationPromises.set(intentArgs.cacheKey, promise); + + promise = promise.then(annotations => { + for (const annotation of annotations) { + if (annotation.titleObj !== undefined) { + Object.defineProperty(annotation, "title", { + get() { + (0, _display_utils.deprecated)("`title`-property on annotation, please use `titleObj` instead."); + return annotation.titleObj.str; + } + + }); + } + + if (annotation.contentsObj !== undefined) { + Object.defineProperty(annotation, "contents", { + get() { + (0, _display_utils.deprecated)("`contents`-property on annotation, please use `contentsObj` instead."); + return annotation.contentsObj.str; + } + + }); + } + } + + return annotations; + }); + } + + return promise; + } + + getJSActions() { + return this._jsActionsPromise ||= this._transport.getPageJSActions(this._pageIndex); + } + + async getXfa() { + return this._transport._htmlForXfa?.children[this._pageIndex] || null; + } + + render({ + canvasContext, + viewport, + intent = "display", + annotationMode = _util.AnnotationMode.ENABLE, + transform = null, + imageLayer = null, + canvasFactory = null, + background = null, + optionalContentConfigPromise = null, + annotationCanvasMap = null, + pageColors = null, + printAnnotationStorage = null + }) { + if (arguments[0]?.renderInteractiveForms !== undefined) { + (0, _display_utils.deprecated)("render no longer accepts the `renderInteractiveForms`-option, " + "please use the `annotationMode`-option instead."); + + if (arguments[0].renderInteractiveForms === true && annotationMode === _util.AnnotationMode.ENABLE) { + annotationMode = _util.AnnotationMode.ENABLE_FORMS; + } + } + + if (arguments[0]?.includeAnnotationStorage !== undefined) { + (0, _display_utils.deprecated)("render no longer accepts the `includeAnnotationStorage`-option, " + "please use the `annotationMode`-option instead."); + + if (arguments[0].includeAnnotationStorage === true && annotationMode === _util.AnnotationMode.ENABLE) { + annotationMode = _util.AnnotationMode.ENABLE_STORAGE; + } + } + + if (this._stats) { + this._stats.time("Overall"); + } + + const intentArgs = this._transport.getRenderingIntent(intent, annotationMode, printAnnotationStorage); + + this.pendingCleanup = false; + + if (!optionalContentConfigPromise) { + optionalContentConfigPromise = this._transport.getOptionalContentConfig(); + } + + let intentState = this._intentStates.get(intentArgs.cacheKey); + + if (!intentState) { + intentState = Object.create(null); + + this._intentStates.set(intentArgs.cacheKey, intentState); + } + + if (intentState.streamReaderCancelTimeout) { + clearTimeout(intentState.streamReaderCancelTimeout); + intentState.streamReaderCancelTimeout = null; + } + + const canvasFactoryInstance = canvasFactory || new DefaultCanvasFactory({ + ownerDocument: this._ownerDocument + }); + const intentPrint = !!(intentArgs.renderingIntent & _util.RenderingIntentFlag.PRINT); + + if (!intentState.displayReadyCapability) { + intentState.displayReadyCapability = (0, _util.createPromiseCapability)(); + intentState.operatorList = { + fnArray: [], + argsArray: [], + lastChunk: false, + separateAnnots: null + }; + + if (this._stats) { + this._stats.time("Page Request"); + } + + this._pumpOperatorList(intentArgs); + } + + const complete = error => { + intentState.renderTasks.delete(internalRenderTask); + + if (this.cleanupAfterRender || intentPrint) { + this.pendingCleanup = true; + } + + this._tryCleanup(); + + if (error) { + internalRenderTask.capability.reject(error); + + this._abortOperatorList({ + intentState, + reason: error instanceof Error ? error : new Error(error) + }); + } else { + internalRenderTask.capability.resolve(); + } + + if (this._stats) { + this._stats.timeEnd("Rendering"); + + this._stats.timeEnd("Overall"); + } + }; + + const internalRenderTask = new InternalRenderTask({ + callback: complete, + params: { + canvasContext, + viewport, + transform, + imageLayer, + background + }, + objs: this.objs, + commonObjs: this.commonObjs, + annotationCanvasMap, + operatorList: intentState.operatorList, + pageIndex: this._pageIndex, + canvasFactory: canvasFactoryInstance, + useRequestAnimationFrame: !intentPrint, + pdfBug: this._pdfBug, + pageColors + }); + (intentState.renderTasks ||= new Set()).add(internalRenderTask); + const renderTask = internalRenderTask.task; + Promise.all([intentState.displayReadyCapability.promise, optionalContentConfigPromise]).then(([transparency, optionalContentConfig]) => { + if (this.pendingCleanup) { + complete(); + return; + } + + if (this._stats) { + this._stats.time("Rendering"); + } + + internalRenderTask.initializeGraphics({ + transparency, + optionalContentConfig + }); + internalRenderTask.operatorListChanged(); + }).catch(complete); + return renderTask; + } + + getOperatorList({ + intent = "display", + annotationMode = _util.AnnotationMode.ENABLE, + printAnnotationStorage = null + } = {}) { + function operatorListChanged() { + if (intentState.operatorList.lastChunk) { + intentState.opListReadCapability.resolve(intentState.operatorList); + intentState.renderTasks.delete(opListTask); + } + } + + const intentArgs = this._transport.getRenderingIntent(intent, annotationMode, printAnnotationStorage, true); + + let intentState = this._intentStates.get(intentArgs.cacheKey); + + if (!intentState) { + intentState = Object.create(null); + + this._intentStates.set(intentArgs.cacheKey, intentState); + } + + let opListTask; + + if (!intentState.opListReadCapability) { + opListTask = Object.create(null); + opListTask.operatorListChanged = operatorListChanged; + intentState.opListReadCapability = (0, _util.createPromiseCapability)(); + (intentState.renderTasks ||= new Set()).add(opListTask); + intentState.operatorList = { + fnArray: [], + argsArray: [], + lastChunk: false, + separateAnnots: null + }; + + if (this._stats) { + this._stats.time("Page Request"); + } + + this._pumpOperatorList(intentArgs); + } + + return intentState.opListReadCapability.promise; + } + + streamTextContent({ + disableCombineTextItems = false, + includeMarkedContent = false + } = {}) { + const TEXT_CONTENT_CHUNK_SIZE = 100; + return this._transport.messageHandler.sendWithStream("GetTextContent", { + pageIndex: this._pageIndex, + combineTextItems: disableCombineTextItems !== true, + includeMarkedContent: includeMarkedContent === true + }, { + highWaterMark: TEXT_CONTENT_CHUNK_SIZE, + + size(textContent) { + return textContent.items.length; + } + + }); + } + + getTextContent(params = {}) { + if (this._transport._htmlForXfa) { + return this.getXfa().then(xfa => { + return _xfa_text.XfaText.textContent(xfa); + }); + } + + const readableStream = this.streamTextContent(params); + return new Promise(function (resolve, reject) { + function pump() { + reader.read().then(function ({ + value, + done + }) { + if (done) { + resolve(textContent); + return; + } + + Object.assign(textContent.styles, value.styles); + textContent.items.push(...value.items); + pump(); + }, reject); + } + + const reader = readableStream.getReader(); + const textContent = { + items: [], + styles: Object.create(null) + }; + pump(); + }); + } + + getStructTree() { + return this._structTreePromise ||= this._transport.getStructTree(this._pageIndex); + } + + _destroy() { + this.destroyed = true; + const waitOn = []; + + for (const intentState of this._intentStates.values()) { + this._abortOperatorList({ + intentState, + reason: new Error("Page was destroyed."), + force: true + }); + + if (intentState.opListReadCapability) { + continue; + } + + for (const internalRenderTask of intentState.renderTasks) { + waitOn.push(internalRenderTask.completed); + internalRenderTask.cancel(); + } + } + + this.objs.clear(); + + for (const bitmap of this._bitmaps) { + bitmap.close(); + } + + this._bitmaps.clear(); + + this._annotationPromises.clear(); + + this._jsActionsPromise = null; + this._structTreePromise = null; + this.pendingCleanup = false; + return Promise.all(waitOn); + } + + cleanup(resetStats = false) { + this.pendingCleanup = true; + return this._tryCleanup(resetStats); + } + + _tryCleanup(resetStats = false) { + if (!this.pendingCleanup) { + return false; + } + + for (const { + renderTasks, + operatorList + } of this._intentStates.values()) { + if (renderTasks.size > 0 || !operatorList.lastChunk) { + return false; + } + } + + this._intentStates.clear(); + + this.objs.clear(); + + this._annotationPromises.clear(); + + this._jsActionsPromise = null; + this._structTreePromise = null; + + if (resetStats && this._stats) { + this._stats = new _display_utils.StatTimer(); + } + + for (const bitmap of this._bitmaps) { + bitmap.close(); + } + + this._bitmaps.clear(); + + this.pendingCleanup = false; + return true; + } + + _startRenderPage(transparency, cacheKey) { + const intentState = this._intentStates.get(cacheKey); + + if (!intentState) { + return; + } + + if (this._stats) { + this._stats.timeEnd("Page Request"); + } + + if (intentState.displayReadyCapability) { + intentState.displayReadyCapability.resolve(transparency); + } + } + + _renderPageChunk(operatorListChunk, intentState) { + for (let i = 0, ii = operatorListChunk.length; i < ii; i++) { + intentState.operatorList.fnArray.push(operatorListChunk.fnArray[i]); + intentState.operatorList.argsArray.push(operatorListChunk.argsArray[i]); + } + + intentState.operatorList.lastChunk = operatorListChunk.lastChunk; + intentState.operatorList.separateAnnots = operatorListChunk.separateAnnots; + + for (const internalRenderTask of intentState.renderTasks) { + internalRenderTask.operatorListChanged(); + } + + if (operatorListChunk.lastChunk) { + this._tryCleanup(); + } + } + + _pumpOperatorList({ + renderingIntent, + cacheKey, + annotationStorageMap + }) { + const readableStream = this._transport.messageHandler.sendWithStream("GetOperatorList", { + pageIndex: this._pageIndex, + intent: renderingIntent, + cacheKey, + annotationStorage: annotationStorageMap + }); + + const reader = readableStream.getReader(); + + const intentState = this._intentStates.get(cacheKey); + + intentState.streamReader = reader; + + const pump = () => { + reader.read().then(({ + value, + done + }) => { + if (done) { + intentState.streamReader = null; + return; + } + + if (this._transport.destroyed) { + return; + } + + this._renderPageChunk(value, intentState); + + pump(); + }, reason => { + intentState.streamReader = null; + + if (this._transport.destroyed) { + return; + } + + if (intentState.operatorList) { + intentState.operatorList.lastChunk = true; + + for (const internalRenderTask of intentState.renderTasks) { + internalRenderTask.operatorListChanged(); + } + + this._tryCleanup(); + } + + if (intentState.displayReadyCapability) { + intentState.displayReadyCapability.reject(reason); + } else if (intentState.opListReadCapability) { + intentState.opListReadCapability.reject(reason); + } else { + throw reason; + } + }); + }; + + pump(); + } + + _abortOperatorList({ + intentState, + reason, + force = false + }) { + if (!intentState.streamReader) { + return; + } + + if (!force) { + if (intentState.renderTasks.size > 0) { + return; + } + + if (reason instanceof _display_utils.RenderingCancelledException) { + intentState.streamReaderCancelTimeout = setTimeout(() => { + this._abortOperatorList({ + intentState, + reason, + force: true + }); + + intentState.streamReaderCancelTimeout = null; + }, RENDERING_CANCELLED_TIMEOUT); + return; + } + } + + intentState.streamReader.cancel(new _util.AbortException(reason.message)).catch(() => {}); + intentState.streamReader = null; + + if (this._transport.destroyed) { + return; + } + + for (const [curCacheKey, curIntentState] of this._intentStates) { + if (curIntentState === intentState) { + this._intentStates.delete(curCacheKey); + + break; + } + } + + this.cleanup(); + } + + get stats() { + return this._stats; + } + + } + + exports.PDFPageProxy = PDFPageProxy; + + class LoopbackPort { + constructor() { + this._listeners = []; + this._deferred = Promise.resolve(); + } + + postMessage(obj, transfers) { + const event = { + data: structuredClone(obj, transfers) + }; + + this._deferred.then(() => { + for (const listener of this._listeners) { + listener.call(this, event); + } + }); + } + + addEventListener(name, listener) { + this._listeners.push(listener); + } + + removeEventListener(name, listener) { + const i = this._listeners.indexOf(listener); + + this._listeners.splice(i, 1); + } + + terminate() { + this._listeners.length = 0; + } + + } + + exports.LoopbackPort = LoopbackPort; + const PDFWorkerUtil = { + isWorkerDisabled: false, + fallbackWorkerSrc: null, + fakeWorkerId: 0 + }; + exports.PDFWorkerUtil = PDFWorkerUtil; + { + if (_is_node.isNodeJS && typeof commonjsRequire === "function") { + PDFWorkerUtil.isWorkerDisabled = true; + PDFWorkerUtil.fallbackWorkerSrc = "./pdf.worker.js"; + } else if (typeof document === "object") { + const pdfjsFilePath = document?.currentScript?.src; + + if (pdfjsFilePath) { + PDFWorkerUtil.fallbackWorkerSrc = pdfjsFilePath.replace(/(\.(?:min\.)?js)(\?.*)?$/i, ".worker$1$2"); + } + } + + PDFWorkerUtil.isSameOrigin = function (baseUrl, otherUrl) { + let base; + + try { + base = new URL(baseUrl); + + if (!base.origin || base.origin === "null") { + return false; + } + } catch (e) { + return false; + } + + const other = new URL(otherUrl, base); + return base.origin === other.origin; + }; + + PDFWorkerUtil.createCDNWrapper = function (url) { + const wrapper = `importScripts("${url}");`; + return URL.createObjectURL(new Blob([wrapper])); + }; + } + + class PDFWorker { + static #workerPorts = new WeakMap(); + + constructor({ + name = null, + port = null, + verbosity = (0, _util.getVerbosityLevel)() + } = {}) { + if (port && PDFWorker.#workerPorts.has(port)) { + throw new Error("Cannot use more than one PDFWorker per port."); + } + + this.name = name; + this.destroyed = false; + this.verbosity = verbosity; + this._readyCapability = (0, _util.createPromiseCapability)(); + this._port = null; + this._webWorker = null; + this._messageHandler = null; + + if (port) { + PDFWorker.#workerPorts.set(port, this); + + this._initializeFromPort(port); + + return; + } + + this._initialize(); + } + + get promise() { + return this._readyCapability.promise; + } + + get port() { + return this._port; + } + + get messageHandler() { + return this._messageHandler; + } + + _initializeFromPort(port) { + this._port = port; + this._messageHandler = new _message_handler.MessageHandler("main", "worker", port); + + this._messageHandler.on("ready", function () {}); + + this._readyCapability.resolve(); + } + + _initialize() { + if (!PDFWorkerUtil.isWorkerDisabled && !PDFWorker._mainThreadWorkerMessageHandler) { + let { + workerSrc + } = PDFWorker; + + try { + if (!PDFWorkerUtil.isSameOrigin(window.location.href, workerSrc)) { + workerSrc = PDFWorkerUtil.createCDNWrapper(new URL(workerSrc, window.location).href); + } + + const worker = new Worker(workerSrc); + const messageHandler = new _message_handler.MessageHandler("main", "worker", worker); + + const terminateEarly = () => { + worker.removeEventListener("error", onWorkerError); + messageHandler.destroy(); + worker.terminate(); + + if (this.destroyed) { + this._readyCapability.reject(new Error("Worker was destroyed")); + } else { + this._setupFakeWorker(); + } + }; + + const onWorkerError = () => { + if (!this._webWorker) { + terminateEarly(); + } + }; + + worker.addEventListener("error", onWorkerError); + messageHandler.on("test", data => { + worker.removeEventListener("error", onWorkerError); + + if (this.destroyed) { + terminateEarly(); + return; + } + + if (data) { + this._messageHandler = messageHandler; + this._port = worker; + this._webWorker = worker; + + this._readyCapability.resolve(); + + messageHandler.send("configure", { + verbosity: this.verbosity + }); + } else { + this._setupFakeWorker(); + + messageHandler.destroy(); + worker.terminate(); + } + }); + messageHandler.on("ready", data => { + worker.removeEventListener("error", onWorkerError); + + if (this.destroyed) { + terminateEarly(); + return; + } + + try { + sendTest(); + } catch (e) { + this._setupFakeWorker(); + } + }); + + const sendTest = () => { + const testObj = new Uint8Array(); + messageHandler.send("test", testObj, [testObj.buffer]); + }; + + sendTest(); + return; + } catch (e) { + (0, _util.info)("The worker has been disabled."); + } + } + + this._setupFakeWorker(); + } + + _setupFakeWorker() { + if (!PDFWorkerUtil.isWorkerDisabled) { + (0, _util.warn)("Setting up fake worker."); + PDFWorkerUtil.isWorkerDisabled = true; + } + + PDFWorker._setupFakeWorkerGlobal.then(WorkerMessageHandler => { + if (this.destroyed) { + this._readyCapability.reject(new Error("Worker was destroyed")); + + return; + } + + const port = new LoopbackPort(); + this._port = port; + const id = `fake${PDFWorkerUtil.fakeWorkerId++}`; + const workerHandler = new _message_handler.MessageHandler(id + "_worker", id, port); + WorkerMessageHandler.setup(workerHandler, port); + const messageHandler = new _message_handler.MessageHandler(id, id + "_worker", port); + this._messageHandler = messageHandler; + + this._readyCapability.resolve(); + + messageHandler.send("configure", { + verbosity: this.verbosity + }); + }).catch(reason => { + this._readyCapability.reject(new Error(`Setting up fake worker failed: "${reason.message}".`)); + }); + } + + destroy() { + this.destroyed = true; + + if (this._webWorker) { + this._webWorker.terminate(); + + this._webWorker = null; + } + + PDFWorker.#workerPorts.delete(this._port); + this._port = null; + + if (this._messageHandler) { + this._messageHandler.destroy(); + + this._messageHandler = null; + } + } + + static fromPort(params) { + if (!params?.port) { + throw new Error("PDFWorker.fromPort - invalid method signature."); + } + + if (this.#workerPorts.has(params.port)) { + return this.#workerPorts.get(params.port); + } + + return new PDFWorker(params); + } + + static get workerSrc() { + if (_worker_options.GlobalWorkerOptions.workerSrc) { + return _worker_options.GlobalWorkerOptions.workerSrc; + } + + if (PDFWorkerUtil.fallbackWorkerSrc !== null) { + if (!_is_node.isNodeJS) { + (0, _display_utils.deprecated)('No "GlobalWorkerOptions.workerSrc" specified.'); + } + + return PDFWorkerUtil.fallbackWorkerSrc; + } + + throw new Error('No "GlobalWorkerOptions.workerSrc" specified.'); + } + + static get _mainThreadWorkerMessageHandler() { + try { + return globalThis.pdfjsWorker?.WorkerMessageHandler || null; + } catch (ex) { + return null; + } + } + + static get _setupFakeWorkerGlobal() { + const loader = async () => { + const mainWorkerMessageHandler = this._mainThreadWorkerMessageHandler; + + if (mainWorkerMessageHandler) { + return mainWorkerMessageHandler; + } + + if (_is_node.isNodeJS && typeof commonjsRequire === "function") { + const worker = eval("require")(this.workerSrc); + return worker.WorkerMessageHandler; + } + + await (0, _display_utils.loadScript)(this.workerSrc); + return window.pdfjsWorker.WorkerMessageHandler; + }; + + return (0, _util.shadow)(this, "_setupFakeWorkerGlobal", loader()); + } + + } + + exports.PDFWorker = PDFWorker; + { + PDFWorker.getWorkerSrc = function () { + (0, _display_utils.deprecated)("`PDFWorker.getWorkerSrc()`, please use `PDFWorker.workerSrc` instead."); + return this.workerSrc; + }; + } + + class WorkerTransport { + #docStats = null; + #pageCache = new Map(); + #pagePromises = new Map(); + #metadataPromise = null; + + constructor(messageHandler, loadingTask, networkStream, params) { + this.messageHandler = messageHandler; + this.loadingTask = loadingTask; + this.commonObjs = new PDFObjects(); + this.fontLoader = new _font_loader.FontLoader({ + docId: loadingTask.docId, + onUnsupportedFeature: this._onUnsupportedFeature.bind(this), + ownerDocument: params.ownerDocument, + styleElement: params.styleElement + }); + this._params = params; + + if (!params.useWorkerFetch) { + this.CMapReaderFactory = new params.CMapReaderFactory({ + baseUrl: params.cMapUrl, + isCompressed: params.cMapPacked + }); + this.StandardFontDataFactory = new params.StandardFontDataFactory({ + baseUrl: params.standardFontDataUrl + }); + } + + this.destroyed = false; + this.destroyCapability = null; + this._passwordCapability = null; + this._networkStream = networkStream; + this._fullReader = null; + this._lastProgress = null; + this.downloadInfoCapability = (0, _util.createPromiseCapability)(); + this.setupMessageHandler(); + } + + get annotationStorage() { + return (0, _util.shadow)(this, "annotationStorage", new _annotation_storage.AnnotationStorage()); + } + + get stats() { + return this.#docStats; + } + + getRenderingIntent(intent, annotationMode = _util.AnnotationMode.ENABLE, printAnnotationStorage = null, isOpList = false) { + let renderingIntent = _util.RenderingIntentFlag.DISPLAY; + let annotationMap = null; + + switch (intent) { + case "any": + renderingIntent = _util.RenderingIntentFlag.ANY; + break; + + case "display": + break; + + case "print": + renderingIntent = _util.RenderingIntentFlag.PRINT; + break; + + default: + (0, _util.warn)(`getRenderingIntent - invalid intent: ${intent}`); + } + + switch (annotationMode) { + case _util.AnnotationMode.DISABLE: + renderingIntent += _util.RenderingIntentFlag.ANNOTATIONS_DISABLE; + break; + + case _util.AnnotationMode.ENABLE: + break; + + case _util.AnnotationMode.ENABLE_FORMS: + renderingIntent += _util.RenderingIntentFlag.ANNOTATIONS_FORMS; + break; + + case _util.AnnotationMode.ENABLE_STORAGE: + renderingIntent += _util.RenderingIntentFlag.ANNOTATIONS_STORAGE; + const annotationStorage = renderingIntent & _util.RenderingIntentFlag.PRINT && printAnnotationStorage instanceof _annotation_storage.PrintAnnotationStorage ? printAnnotationStorage : this.annotationStorage; + annotationMap = annotationStorage.serializable; + break; + + default: + (0, _util.warn)(`getRenderingIntent - invalid annotationMode: ${annotationMode}`); + } + + if (isOpList) { + renderingIntent += _util.RenderingIntentFlag.OPLIST; + } + + return { + renderingIntent, + cacheKey: `${renderingIntent}_${_annotation_storage.AnnotationStorage.getHash(annotationMap)}`, + annotationStorageMap: annotationMap + }; + } + + destroy() { + if (this.destroyCapability) { + return this.destroyCapability.promise; + } + + this.destroyed = true; + this.destroyCapability = (0, _util.createPromiseCapability)(); + + if (this._passwordCapability) { + this._passwordCapability.reject(new Error("Worker was destroyed during onPassword callback")); + } + + const waitOn = []; + + for (const page of this.#pageCache.values()) { + waitOn.push(page._destroy()); + } + + this.#pageCache.clear(); + this.#pagePromises.clear(); + + if (this.hasOwnProperty("annotationStorage")) { + this.annotationStorage.resetModified(); + } + + const terminated = this.messageHandler.sendWithPromise("Terminate", null); + waitOn.push(terminated); + Promise.all(waitOn).then(() => { + this.commonObjs.clear(); + this.fontLoader.clear(); + this.#metadataPromise = null; + this._getFieldObjectsPromise = null; + this._hasJSActionsPromise = null; + + if (this._networkStream) { + this._networkStream.cancelAllRequests(new _util.AbortException("Worker was terminated.")); + } + + if (this.messageHandler) { + this.messageHandler.destroy(); + this.messageHandler = null; + } + + this.destroyCapability.resolve(); + }, this.destroyCapability.reject); + return this.destroyCapability.promise; + } + + setupMessageHandler() { + const { + messageHandler, + loadingTask + } = this; + messageHandler.on("GetReader", (data, sink) => { + (0, _util.assert)(this._networkStream, "GetReader - no `IPDFStream` instance available."); + this._fullReader = this._networkStream.getFullReader(); + + this._fullReader.onProgress = evt => { + this._lastProgress = { + loaded: evt.loaded, + total: evt.total + }; + }; + + sink.onPull = () => { + this._fullReader.read().then(function ({ + value, + done + }) { + if (done) { + sink.close(); + return; + } + + (0, _util.assert)((0, _util.isArrayBuffer)(value), "GetReader - expected an ArrayBuffer."); + sink.enqueue(new Uint8Array(value), 1, [value]); + }).catch(reason => { + sink.error(reason); + }); + }; + + sink.onCancel = reason => { + this._fullReader.cancel(reason); + + sink.ready.catch(readyReason => { + if (this.destroyed) { + return; + } + + throw readyReason; + }); + }; + }); + messageHandler.on("ReaderHeadersReady", data => { + const headersCapability = (0, _util.createPromiseCapability)(); + const fullReader = this._fullReader; + fullReader.headersReady.then(() => { + if (!fullReader.isStreamingSupported || !fullReader.isRangeSupported) { + if (this._lastProgress) { + loadingTask.onProgress?.(this._lastProgress); + } + + fullReader.onProgress = evt => { + loadingTask.onProgress?.({ + loaded: evt.loaded, + total: evt.total + }); + }; + } + + headersCapability.resolve({ + isStreamingSupported: fullReader.isStreamingSupported, + isRangeSupported: fullReader.isRangeSupported, + contentLength: fullReader.contentLength + }); + }, headersCapability.reject); + return headersCapability.promise; + }); + messageHandler.on("GetRangeReader", (data, sink) => { + (0, _util.assert)(this._networkStream, "GetRangeReader - no `IPDFStream` instance available."); + + const rangeReader = this._networkStream.getRangeReader(data.begin, data.end); + + if (!rangeReader) { + sink.close(); + return; + } + + sink.onPull = () => { + rangeReader.read().then(function ({ + value, + done + }) { + if (done) { + sink.close(); + return; + } + + (0, _util.assert)((0, _util.isArrayBuffer)(value), "GetRangeReader - expected an ArrayBuffer."); + sink.enqueue(new Uint8Array(value), 1, [value]); + }).catch(reason => { + sink.error(reason); + }); + }; + + sink.onCancel = reason => { + rangeReader.cancel(reason); + sink.ready.catch(readyReason => { + if (this.destroyed) { + return; + } + + throw readyReason; + }); + }; + }); + messageHandler.on("GetDoc", ({ + pdfInfo + }) => { + this._numPages = pdfInfo.numPages; + this._htmlForXfa = pdfInfo.htmlForXfa; + delete pdfInfo.htmlForXfa; + + loadingTask._capability.resolve(new PDFDocumentProxy(pdfInfo, this)); + }); + messageHandler.on("DocException", function (ex) { + let reason; + + switch (ex.name) { + case "PasswordException": + reason = new _util.PasswordException(ex.message, ex.code); + break; + + case "InvalidPDFException": + reason = new _util.InvalidPDFException(ex.message); + break; + + case "MissingPDFException": + reason = new _util.MissingPDFException(ex.message); + break; + + case "UnexpectedResponseException": + reason = new _util.UnexpectedResponseException(ex.message, ex.status); + break; + + case "UnknownErrorException": + reason = new _util.UnknownErrorException(ex.message, ex.details); + break; + + default: + (0, _util.unreachable)("DocException - expected a valid Error."); + } + + loadingTask._capability.reject(reason); + }); + messageHandler.on("PasswordRequest", exception => { + this._passwordCapability = (0, _util.createPromiseCapability)(); + + if (loadingTask.onPassword) { + const updatePassword = password => { + if (password instanceof Error) { + this._passwordCapability.reject(password); + } else { + this._passwordCapability.resolve({ + password + }); + } + }; + + try { + loadingTask.onPassword(updatePassword, exception.code); + } catch (ex) { + this._passwordCapability.reject(ex); + } + } else { + this._passwordCapability.reject(new _util.PasswordException(exception.message, exception.code)); + } + + return this._passwordCapability.promise; + }); + messageHandler.on("DataLoaded", data => { + loadingTask.onProgress?.({ + loaded: data.length, + total: data.length + }); + this.downloadInfoCapability.resolve(data); + }); + messageHandler.on("StartRenderPage", data => { + if (this.destroyed) { + return; + } + + const page = this.#pageCache.get(data.pageIndex); + + page._startRenderPage(data.transparency, data.cacheKey); + }); + messageHandler.on("commonobj", ([id, type, exportedData]) => { + if (this.destroyed) { + return; + } + + if (this.commonObjs.has(id)) { + return; + } + + switch (type) { + case "Font": + const params = this._params; + + if ("error" in exportedData) { + const exportedError = exportedData.error; + (0, _util.warn)(`Error during font loading: ${exportedError}`); + this.commonObjs.resolve(id, exportedError); + break; + } + + let fontRegistry = null; + + if (params.pdfBug && globalThis.FontInspector?.enabled) { + fontRegistry = { + registerFont(font, url) { + globalThis.FontInspector.fontAdded(font, url); + } + + }; + } + + const font = new _font_loader.FontFaceObject(exportedData, { + isEvalSupported: params.isEvalSupported, + disableFontFace: params.disableFontFace, + ignoreErrors: params.ignoreErrors, + onUnsupportedFeature: this._onUnsupportedFeature.bind(this), + fontRegistry + }); + this.fontLoader.bind(font).catch(reason => { + return messageHandler.sendWithPromise("FontFallback", { + id + }); + }).finally(() => { + if (!params.fontExtraProperties && font.data) { + font.data = null; + } + + this.commonObjs.resolve(id, font); + }); + break; + + case "FontPath": + case "Image": + this.commonObjs.resolve(id, exportedData); + break; + + default: + throw new Error(`Got unknown common object type ${type}`); + } + }); + messageHandler.on("obj", ([id, pageIndex, type, imageData]) => { + if (this.destroyed) { + return; + } + + const pageProxy = this.#pageCache.get(pageIndex); + + if (pageProxy.objs.has(id)) { + return; + } + + switch (type) { + case "Image": + pageProxy.objs.resolve(id, imageData); + const MAX_IMAGE_SIZE_TO_STORE = 8000000; + + if (imageData) { + let length; + + if (imageData.bitmap) { + const { + bitmap, + width, + height + } = imageData; + length = width * height * 4; + + pageProxy._bitmaps.add(bitmap); + } else { + length = imageData.data?.length || 0; + } + + if (length > MAX_IMAGE_SIZE_TO_STORE) { + pageProxy.cleanupAfterRender = true; + } + } + + break; + + case "Pattern": + pageProxy.objs.resolve(id, imageData); + break; + + default: + throw new Error(`Got unknown object type ${type}`); + } + }); + messageHandler.on("DocProgress", data => { + if (this.destroyed) { + return; + } + + loadingTask.onProgress?.({ + loaded: data.loaded, + total: data.total + }); + }); + messageHandler.on("DocStats", data => { + if (this.destroyed) { + return; + } + + this.#docStats = Object.freeze({ + streamTypes: Object.freeze(data.streamTypes), + fontTypes: Object.freeze(data.fontTypes) + }); + }); + messageHandler.on("UnsupportedFeature", this._onUnsupportedFeature.bind(this)); + messageHandler.on("FetchBuiltInCMap", data => { + if (this.destroyed) { + return Promise.reject(new Error("Worker was destroyed.")); + } + + if (!this.CMapReaderFactory) { + return Promise.reject(new Error("CMapReaderFactory not initialized, see the `useWorkerFetch` parameter.")); + } + + return this.CMapReaderFactory.fetch(data); + }); + messageHandler.on("FetchStandardFontData", data => { + if (this.destroyed) { + return Promise.reject(new Error("Worker was destroyed.")); + } + + if (!this.StandardFontDataFactory) { + return Promise.reject(new Error("StandardFontDataFactory not initialized, see the `useWorkerFetch` parameter.")); + } + + return this.StandardFontDataFactory.fetch(data); + }); + } + + _onUnsupportedFeature({ + featureId + }) { + if (this.destroyed) { + return; + } + + this.loadingTask.onUnsupportedFeature?.(featureId); + } + + getData() { + return this.messageHandler.sendWithPromise("GetData", null); + } + + getPage(pageNumber) { + if (!Number.isInteger(pageNumber) || pageNumber <= 0 || pageNumber > this._numPages) { + return Promise.reject(new Error("Invalid page request.")); + } + + const pageIndex = pageNumber - 1, + cachedPromise = this.#pagePromises.get(pageIndex); + + if (cachedPromise) { + return cachedPromise; + } + + const promise = this.messageHandler.sendWithPromise("GetPage", { + pageIndex + }).then(pageInfo => { + if (this.destroyed) { + throw new Error("Transport destroyed"); + } + + const page = new PDFPageProxy(pageIndex, pageInfo, this, this._params.ownerDocument, this._params.pdfBug); + this.#pageCache.set(pageIndex, page); + return page; + }); + this.#pagePromises.set(pageIndex, promise); + return promise; + } + + getPageIndex(ref) { + if (typeof ref !== "object" || ref === null || !Number.isInteger(ref.num) || ref.num < 0 || !Number.isInteger(ref.gen) || ref.gen < 0) { + return Promise.reject(new Error("Invalid pageIndex request.")); + } + + return this.messageHandler.sendWithPromise("GetPageIndex", { + num: ref.num, + gen: ref.gen + }); + } + + getAnnotations(pageIndex, intent) { + return this.messageHandler.sendWithPromise("GetAnnotations", { + pageIndex, + intent + }); + } + + saveDocument() { + return this.messageHandler.sendWithPromise("SaveDocument", { + isPureXfa: !!this._htmlForXfa, + numPages: this._numPages, + annotationStorage: this.annotationStorage.serializable, + filename: this._fullReader?.filename ?? null + }).finally(() => { + this.annotationStorage.resetModified(); + }); + } + + getFieldObjects() { + return this._getFieldObjectsPromise ||= this.messageHandler.sendWithPromise("GetFieldObjects", null); + } + + hasJSActions() { + return this._hasJSActionsPromise ||= this.messageHandler.sendWithPromise("HasJSActions", null); + } + + getCalculationOrderIds() { + return this.messageHandler.sendWithPromise("GetCalculationOrderIds", null); + } + + getDestinations() { + return this.messageHandler.sendWithPromise("GetDestinations", null); + } + + getDestination(id) { + if (typeof id !== "string") { + return Promise.reject(new Error("Invalid destination request.")); + } + + return this.messageHandler.sendWithPromise("GetDestination", { + id + }); + } + + getPageLabels() { + return this.messageHandler.sendWithPromise("GetPageLabels", null); + } + + getPageLayout() { + return this.messageHandler.sendWithPromise("GetPageLayout", null); + } + + getPageMode() { + return this.messageHandler.sendWithPromise("GetPageMode", null); + } + + getViewerPreferences() { + return this.messageHandler.sendWithPromise("GetViewerPreferences", null); + } + + getOpenAction() { + return this.messageHandler.sendWithPromise("GetOpenAction", null); + } + + getAttachments() { + return this.messageHandler.sendWithPromise("GetAttachments", null); + } + + getJavaScript() { + return this.messageHandler.sendWithPromise("GetJavaScript", null); + } + + getDocJSActions() { + return this.messageHandler.sendWithPromise("GetDocJSActions", null); + } + + getPageJSActions(pageIndex) { + return this.messageHandler.sendWithPromise("GetPageJSActions", { + pageIndex + }); + } + + getStructTree(pageIndex) { + return this.messageHandler.sendWithPromise("GetStructTree", { + pageIndex + }); + } + + getOutline() { + return this.messageHandler.sendWithPromise("GetOutline", null); + } + + getOptionalContentConfig() { + return this.messageHandler.sendWithPromise("GetOptionalContentConfig", null).then(results => { + return new _optional_content_config.OptionalContentConfig(results); + }); + } + + getPermissions() { + return this.messageHandler.sendWithPromise("GetPermissions", null); + } + + getMetadata() { + return this.#metadataPromise ||= this.messageHandler.sendWithPromise("GetMetadata", null).then(results => { + return { + info: results[0], + metadata: results[1] ? new _metadata.Metadata(results[1]) : null, + contentDispositionFilename: this._fullReader?.filename ?? null, + contentLength: this._fullReader?.contentLength ?? null + }; + }); + } + + getMarkInfo() { + return this.messageHandler.sendWithPromise("GetMarkInfo", null); + } + + async startCleanup(keepLoadedFonts = false) { + await this.messageHandler.sendWithPromise("Cleanup", null); + + if (this.destroyed) { + return; + } + + for (const page of this.#pageCache.values()) { + const cleanupSuccessful = page.cleanup(); + + if (!cleanupSuccessful) { + throw new Error(`startCleanup: Page ${page.pageNumber} is currently rendering.`); + } + } + + this.commonObjs.clear(); + + if (!keepLoadedFonts) { + this.fontLoader.clear(); + } + + this.#metadataPromise = null; + this._getFieldObjectsPromise = null; + this._hasJSActionsPromise = null; + } + + get loadingParams() { + const params = this._params; + return (0, _util.shadow)(this, "loadingParams", { + disableAutoFetch: params.disableAutoFetch, + enableXfa: params.enableXfa + }); + } + + } + + class PDFObjects { + #objs = Object.create(null); + + #ensureObj(objId) { + const obj = this.#objs[objId]; + + if (obj) { + return obj; + } + + return this.#objs[objId] = { + capability: (0, _util.createPromiseCapability)(), + data: null + }; + } + + get(objId, callback = null) { + if (callback) { + const obj = this.#ensureObj(objId); + obj.capability.promise.then(() => callback(obj.data)); + return null; + } + + const obj = this.#objs[objId]; + + if (!obj?.capability.settled) { + throw new Error(`Requesting object that isn't resolved yet ${objId}.`); + } + + return obj.data; + } + + has(objId) { + const obj = this.#objs[objId]; + return obj?.capability.settled || false; + } + + resolve(objId, data = null) { + const obj = this.#ensureObj(objId); + obj.data = data; + obj.capability.resolve(); + } + + clear() { + this.#objs = Object.create(null); + } + + } + + class RenderTask { + #internalRenderTask = null; + + constructor(internalRenderTask) { + this.#internalRenderTask = internalRenderTask; + this.onContinue = null; + } + + get promise() { + return this.#internalRenderTask.capability.promise; + } + + cancel() { + this.#internalRenderTask.cancel(); + } + + get separateAnnots() { + const { + separateAnnots + } = this.#internalRenderTask.operatorList; + + if (!separateAnnots) { + return false; + } + + const { + annotationCanvasMap + } = this.#internalRenderTask; + return separateAnnots.form || separateAnnots.canvas && annotationCanvasMap?.size > 0; + } + + } + + exports.RenderTask = RenderTask; + + class InternalRenderTask { + static #canvasInUse = new WeakSet(); + + constructor({ + callback, + params, + objs, + commonObjs, + annotationCanvasMap, + operatorList, + pageIndex, + canvasFactory, + useRequestAnimationFrame = false, + pdfBug = false, + pageColors = null + }) { + this.callback = callback; + this.params = params; + this.objs = objs; + this.commonObjs = commonObjs; + this.annotationCanvasMap = annotationCanvasMap; + this.operatorListIdx = null; + this.operatorList = operatorList; + this._pageIndex = pageIndex; + this.canvasFactory = canvasFactory; + this._pdfBug = pdfBug; + this.pageColors = pageColors; + this.running = false; + this.graphicsReadyCallback = null; + this.graphicsReady = false; + this._useRequestAnimationFrame = useRequestAnimationFrame === true && typeof window !== "undefined"; + this.cancelled = false; + this.capability = (0, _util.createPromiseCapability)(); + this.task = new RenderTask(this); + this._cancelBound = this.cancel.bind(this); + this._continueBound = this._continue.bind(this); + this._scheduleNextBound = this._scheduleNext.bind(this); + this._nextBound = this._next.bind(this); + this._canvas = params.canvasContext.canvas; + } + + get completed() { + return this.capability.promise.catch(function () {}); + } + + initializeGraphics({ + transparency = false, + optionalContentConfig + }) { + if (this.cancelled) { + return; + } + + if (this._canvas) { + if (InternalRenderTask.#canvasInUse.has(this._canvas)) { + throw new Error("Cannot use the same canvas during multiple render() operations. " + "Use different canvas or ensure previous operations were " + "cancelled or completed."); + } + + InternalRenderTask.#canvasInUse.add(this._canvas); + } + + if (this._pdfBug && globalThis.StepperManager?.enabled) { + this.stepper = globalThis.StepperManager.create(this._pageIndex); + this.stepper.init(this.operatorList); + this.stepper.nextBreakPoint = this.stepper.getNextBreakPoint(); + } + + const { + canvasContext, + viewport, + transform, + imageLayer, + background + } = this.params; + this.gfx = new _canvas.CanvasGraphics(canvasContext, this.commonObjs, this.objs, this.canvasFactory, imageLayer, optionalContentConfig, this.annotationCanvasMap, this.pageColors); + this.gfx.beginDrawing({ + transform, + viewport, + transparency, + background + }); + this.operatorListIdx = 0; + this.graphicsReady = true; + + if (this.graphicsReadyCallback) { + this.graphicsReadyCallback(); + } + } + + cancel(error = null) { + this.running = false; + this.cancelled = true; + + if (this.gfx) { + this.gfx.endDrawing(); + } + + if (this._canvas) { + InternalRenderTask.#canvasInUse.delete(this._canvas); + } + + this.callback(error || new _display_utils.RenderingCancelledException(`Rendering cancelled, page ${this._pageIndex + 1}`, "canvas")); + } + + operatorListChanged() { + if (!this.graphicsReady) { + if (!this.graphicsReadyCallback) { + this.graphicsReadyCallback = this._continueBound; + } + + return; + } + + if (this.stepper) { + this.stepper.updateOperatorList(this.operatorList); + } + + if (this.running) { + return; + } + + this._continue(); + } + + _continue() { + this.running = true; + + if (this.cancelled) { + return; + } + + if (this.task.onContinue) { + this.task.onContinue(this._scheduleNextBound); + } else { + this._scheduleNext(); + } + } + + _scheduleNext() { + if (this._useRequestAnimationFrame) { + window.requestAnimationFrame(() => { + this._nextBound().catch(this._cancelBound); + }); + } else { + Promise.resolve().then(this._nextBound).catch(this._cancelBound); + } + } + + async _next() { + if (this.cancelled) { + return; + } + + this.operatorListIdx = this.gfx.executeOperatorList(this.operatorList, this.operatorListIdx, this._continueBound, this.stepper); + + if (this.operatorListIdx === this.operatorList.argsArray.length) { + this.running = false; + + if (this.operatorList.lastChunk) { + this.gfx.endDrawing(); + + if (this._canvas) { + InternalRenderTask.#canvasInUse.delete(this._canvas); + } + + this.callback(); + } + } + } + + } + + const version = '2.16.105'; + exports.version = version; + const build = '172ccdbe5'; + exports.build = build; + + /***/ }), + /* 5 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.PrintAnnotationStorage = exports.AnnotationStorage = void 0; + + var _util = __w_pdfjs_require__(1); + + var _editor = __w_pdfjs_require__(6); + + var _murmurhash = __w_pdfjs_require__(10); + + class AnnotationStorage { + constructor() { + this._storage = new Map(); + this._modified = false; + this.onSetModified = null; + this.onResetModified = null; + this.onAnnotationEditor = null; + } + + getValue(key, defaultValue) { + const value = this._storage.get(key); + + if (value === undefined) { + return defaultValue; + } + + return Object.assign(defaultValue, value); + } + + getRawValue(key) { + return this._storage.get(key); + } + + remove(key) { + this._storage.delete(key); + + if (this._storage.size === 0) { + this.resetModified(); + } + + if (typeof this.onAnnotationEditor === "function") { + for (const value of this._storage.values()) { + if (value instanceof _editor.AnnotationEditor) { + return; + } + } + + this.onAnnotationEditor(null); + } + } + + setValue(key, value) { + const obj = this._storage.get(key); + + let modified = false; + + if (obj !== undefined) { + for (const [entry, val] of Object.entries(value)) { + if (obj[entry] !== val) { + modified = true; + obj[entry] = val; + } + } + } else { + modified = true; + + this._storage.set(key, value); + } + + if (modified) { + this.#setModified(); + } + + if (value instanceof _editor.AnnotationEditor && typeof this.onAnnotationEditor === "function") { + this.onAnnotationEditor(value.constructor._type); + } + } + + has(key) { + return this._storage.has(key); + } + + getAll() { + return this._storage.size > 0 ? (0, _util.objectFromMap)(this._storage) : null; + } + + get size() { + return this._storage.size; + } + + #setModified() { + if (!this._modified) { + this._modified = true; + + if (typeof this.onSetModified === "function") { + this.onSetModified(); + } + } + } + + resetModified() { + if (this._modified) { + this._modified = false; + + if (typeof this.onResetModified === "function") { + this.onResetModified(); + } + } + } + + get print() { + return new PrintAnnotationStorage(this); + } + + get serializable() { + if (this._storage.size === 0) { + return null; + } + + const clone = new Map(); + + for (const [key, val] of this._storage) { + const serialized = val instanceof _editor.AnnotationEditor ? val.serialize() : val; + + if (serialized) { + clone.set(key, serialized); + } + } + + return clone; + } + + static getHash(map) { + if (!map) { + return ""; + } + + const hash = new _murmurhash.MurmurHash3_64(); + + for (const [key, val] of map) { + hash.update(`${key}:${JSON.stringify(val)}`); + } + + return hash.hexdigest(); + } + + } + + exports.AnnotationStorage = AnnotationStorage; + + class PrintAnnotationStorage extends AnnotationStorage { + #serializable = null; + + constructor(parent) { + super(); + this.#serializable = structuredClone(parent.serializable); + } + + get print() { + (0, _util.unreachable)("Should not call PrintAnnotationStorage.print"); + } + + get serializable() { + return this.#serializable; + } + + } + + exports.PrintAnnotationStorage = PrintAnnotationStorage; + + /***/ }), + /* 6 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.AnnotationEditor = void 0; + + var _tools = __w_pdfjs_require__(7); + + var _util = __w_pdfjs_require__(1); + + class AnnotationEditor { + #boundFocusin = this.focusin.bind(this); + #boundFocusout = this.focusout.bind(this); + #hasBeenSelected = false; + #isEditing = false; + #isInEditMode = false; + #zIndex = AnnotationEditor._zIndex++; + static _colorManager = new _tools.ColorManager(); + static _zIndex = 1; + + constructor(parameters) { + if (this.constructor === AnnotationEditor) { + (0, _util.unreachable)("Cannot initialize AnnotationEditor."); + } + + this.parent = parameters.parent; + this.id = parameters.id; + this.width = this.height = null; + this.pageIndex = parameters.parent.pageIndex; + this.name = parameters.name; + this.div = null; + const [width, height] = this.parent.viewportBaseDimensions; + this.x = parameters.x / width; + this.y = parameters.y / height; + this.rotation = this.parent.viewport.rotation; + this.isAttachedToDOM = false; + } + + static get _defaultLineColor() { + return (0, _util.shadow)(this, "_defaultLineColor", this._colorManager.getHexCode("CanvasText")); + } + + setInBackground() { + this.div.style.zIndex = 0; + } + + setInForeground() { + this.div.style.zIndex = this.#zIndex; + } + + focusin(event) { + if (!this.#hasBeenSelected) { + this.parent.setSelected(this); + } else { + this.#hasBeenSelected = false; + } + } + + focusout(event) { + if (!this.isAttachedToDOM) { + return; + } + + const target = event.relatedTarget; + + if (target?.closest(`#${this.id}`)) { + return; + } + + event.preventDefault(); + + if (!this.parent.isMultipleSelection) { + this.commitOrRemove(); + } + } + + commitOrRemove() { + if (this.isEmpty()) { + this.remove(); + } else { + this.commit(); + } + } + + commit() { + this.parent.addToAnnotationStorage(this); + } + + dragstart(event) { + const rect = this.parent.div.getBoundingClientRect(); + this.startX = event.clientX - rect.x; + this.startY = event.clientY - rect.y; + event.dataTransfer.setData("text/plain", this.id); + event.dataTransfer.effectAllowed = "move"; + } + + setAt(x, y, tx, ty) { + const [width, height] = this.parent.viewportBaseDimensions; + [tx, ty] = this.screenToPageTranslation(tx, ty); + this.x = (x + tx) / width; + this.y = (y + ty) / height; + this.div.style.left = `${100 * this.x}%`; + this.div.style.top = `${100 * this.y}%`; + } + + translate(x, y) { + const [width, height] = this.parent.viewportBaseDimensions; + [x, y] = this.screenToPageTranslation(x, y); + this.x += x / width; + this.y += y / height; + this.div.style.left = `${100 * this.x}%`; + this.div.style.top = `${100 * this.y}%`; + } + + screenToPageTranslation(x, y) { + const { + rotation + } = this.parent.viewport; + + switch (rotation) { + case 90: + return [y, -x]; + + case 180: + return [-x, -y]; + + case 270: + return [-y, x]; + + default: + return [x, y]; + } + } + + setDims(width, height) { + const [parentWidth, parentHeight] = this.parent.viewportBaseDimensions; + this.div.style.width = `${100 * width / parentWidth}%`; + this.div.style.height = `${100 * height / parentHeight}%`; + } + + getInitialTranslation() { + return [0, 0]; + } + + render() { + this.div = document.createElement("div"); + this.div.setAttribute("data-editor-rotation", (360 - this.rotation) % 360); + this.div.className = this.name; + this.div.setAttribute("id", this.id); + this.div.setAttribute("tabIndex", 0); + this.setInForeground(); + this.div.addEventListener("focusin", this.#boundFocusin); + this.div.addEventListener("focusout", this.#boundFocusout); + const [tx, ty] = this.getInitialTranslation(); + this.translate(tx, ty); + (0, _tools.bindEvents)(this, this.div, ["dragstart", "pointerdown"]); + return this.div; + } + + pointerdown(event) { + const isMac = _tools.KeyboardManager.platform.isMac; + + if (event.button !== 0 || event.ctrlKey && isMac) { + event.preventDefault(); + return; + } + + if (event.ctrlKey && !isMac || event.shiftKey || event.metaKey && isMac) { + this.parent.toggleSelected(this); + } else { + this.parent.setSelected(this); + } + + this.#hasBeenSelected = true; + } + + getRect(tx, ty) { + const [parentWidth, parentHeight] = this.parent.viewportBaseDimensions; + const [pageWidth, pageHeight] = this.parent.pageDimensions; + const shiftX = pageWidth * tx / parentWidth; + const shiftY = pageHeight * ty / parentHeight; + const x = this.x * pageWidth; + const y = this.y * pageHeight; + const width = this.width * pageWidth; + const height = this.height * pageHeight; + + switch (this.rotation) { + case 0: + return [x + shiftX, pageHeight - y - shiftY - height, x + shiftX + width, pageHeight - y - shiftY]; + + case 90: + return [x + shiftY, pageHeight - y + shiftX, x + shiftY + height, pageHeight - y + shiftX + width]; + + case 180: + return [x - shiftX - width, pageHeight - y + shiftY, x - shiftX, pageHeight - y + shiftY + height]; + + case 270: + return [x - shiftY - height, pageHeight - y - shiftX - width, x - shiftY, pageHeight - y - shiftX]; + + default: + throw new Error("Invalid rotation"); + } + } + + getRectInCurrentCoords(rect, pageHeight) { + const [x1, y1, x2, y2] = rect; + const width = x2 - x1; + const height = y2 - y1; + + switch (this.rotation) { + case 0: + return [x1, pageHeight - y2, width, height]; + + case 90: + return [x1, pageHeight - y1, height, width]; + + case 180: + return [x2, pageHeight - y1, width, height]; + + case 270: + return [x2, pageHeight - y2, height, width]; + + default: + throw new Error("Invalid rotation"); + } + } + + onceAdded() {} + + isEmpty() { + return false; + } + + enableEditMode() { + this.#isInEditMode = true; + } + + disableEditMode() { + this.#isInEditMode = false; + } + + isInEditMode() { + return this.#isInEditMode; + } + + shouldGetKeyboardEvents() { + return false; + } + + needsToBeRebuilt() { + return this.div && !this.isAttachedToDOM; + } + + rebuild() { + this.div?.addEventListener("focusin", this.#boundFocusin); + } + + serialize() { + (0, _util.unreachable)("An editor must be serializable"); + } + + static deserialize(data, parent) { + const editor = new this.prototype.constructor({ + parent, + id: parent.getNextId() + }); + editor.rotation = data.rotation; + const [pageWidth, pageHeight] = parent.pageDimensions; + const [x, y, width, height] = editor.getRectInCurrentCoords(data.rect, pageHeight); + editor.x = x / pageWidth; + editor.y = y / pageHeight; + editor.width = width / pageWidth; + editor.height = height / pageHeight; + return editor; + } + + remove() { + this.div.removeEventListener("focusin", this.#boundFocusin); + this.div.removeEventListener("focusout", this.#boundFocusout); + + if (!this.isEmpty()) { + this.commit(); + } + + this.parent.remove(this); + } + + select() { + this.div?.classList.add("selectedEditor"); + } + + unselect() { + this.div?.classList.remove("selectedEditor"); + } + + updateParams(type, value) {} + + disableEditing() {} + + enableEditing() {} + + get propertiesToUpdate() { + return {}; + } + + get contentDiv() { + return this.div; + } + + get isEditing() { + return this.#isEditing; + } + + set isEditing(value) { + this.#isEditing = value; + + if (value) { + this.parent.setSelected(this); + this.parent.setActiveEditor(this); + } else { + this.parent.setActiveEditor(null); + } + } + + } + + exports.AnnotationEditor = AnnotationEditor; + + /***/ }), + /* 7 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.KeyboardManager = exports.CommandManager = exports.ColorManager = exports.AnnotationEditorUIManager = void 0; + exports.bindEvents = bindEvents; + exports.opacityToHex = opacityToHex; + + var _util = __w_pdfjs_require__(1); + + var _display_utils = __w_pdfjs_require__(8); + + function bindEvents(obj, element, names) { + for (const name of names) { + element.addEventListener(name, obj[name].bind(obj)); + } + } + + function opacityToHex(opacity) { + return Math.round(Math.min(255, Math.max(1, 255 * opacity))).toString(16).padStart(2, "0"); + } + + class IdManager { + #id = 0; + + getId() { + return `${_util.AnnotationEditorPrefix}${this.#id++}`; + } + + } + + class CommandManager { + #commands = []; + #locked = false; + #maxSize; + #position = -1; + + constructor(maxSize = 128) { + this.#maxSize = maxSize; + } + + add({ + cmd, + undo, + mustExec, + type = NaN, + overwriteIfSameType = false, + keepUndo = false + }) { + if (mustExec) { + cmd(); + } + + if (this.#locked) { + return; + } + + const save = { + cmd, + undo, + type + }; + + if (this.#position === -1) { + if (this.#commands.length > 0) { + this.#commands.length = 0; + } + + this.#position = 0; + this.#commands.push(save); + return; + } + + if (overwriteIfSameType && this.#commands[this.#position].type === type) { + if (keepUndo) { + save.undo = this.#commands[this.#position].undo; + } + + this.#commands[this.#position] = save; + return; + } + + const next = this.#position + 1; + + if (next === this.#maxSize) { + this.#commands.splice(0, 1); + } else { + this.#position = next; + + if (next < this.#commands.length) { + this.#commands.splice(next); + } + } + + this.#commands.push(save); + } + + undo() { + if (this.#position === -1) { + return; + } + + this.#locked = true; + this.#commands[this.#position].undo(); + this.#locked = false; + this.#position -= 1; + } + + redo() { + if (this.#position < this.#commands.length - 1) { + this.#position += 1; + this.#locked = true; + this.#commands[this.#position].cmd(); + this.#locked = false; + } + } + + hasSomethingToUndo() { + return this.#position !== -1; + } + + hasSomethingToRedo() { + return this.#position < this.#commands.length - 1; + } + + destroy() { + this.#commands = null; + } + + } + + exports.CommandManager = CommandManager; + + class KeyboardManager { + constructor(callbacks) { + this.buffer = []; + this.callbacks = new Map(); + this.allKeys = new Set(); + const isMac = KeyboardManager.platform.isMac; + + for (const [keys, callback] of callbacks) { + for (const key of keys) { + const isMacKey = key.startsWith("mac+"); + + if (isMac && isMacKey) { + this.callbacks.set(key.slice(4), callback); + this.allKeys.add(key.split("+").at(-1)); + } else if (!isMac && !isMacKey) { + this.callbacks.set(key, callback); + this.allKeys.add(key.split("+").at(-1)); + } + } + } + } + + static get platform() { + const platform = typeof navigator !== "undefined" ? navigator.platform : ""; + return (0, _util.shadow)(this, "platform", { + isWin: platform.includes("Win"), + isMac: platform.includes("Mac") + }); + } + + #serialize(event) { + if (event.altKey) { + this.buffer.push("alt"); + } + + if (event.ctrlKey) { + this.buffer.push("ctrl"); + } + + if (event.metaKey) { + this.buffer.push("meta"); + } + + if (event.shiftKey) { + this.buffer.push("shift"); + } + + this.buffer.push(event.key); + const str = this.buffer.join("+"); + this.buffer.length = 0; + return str; + } + + exec(self, event) { + if (!this.allKeys.has(event.key)) { + return; + } + + const callback = this.callbacks.get(this.#serialize(event)); + + if (!callback) { + return; + } + + callback.bind(self)(); + event.stopPropagation(); + event.preventDefault(); + } + + } + + exports.KeyboardManager = KeyboardManager; + + class ClipboardManager { + #elements = null; + + copy(element) { + if (!element) { + return; + } + + if (Array.isArray(element)) { + this.#elements = element.map(el => el.serialize()); + } else { + this.#elements = [element.serialize()]; + } + + this.#elements = this.#elements.filter(el => !!el); + + if (this.#elements.length === 0) { + this.#elements = null; + } + } + + paste() { + return this.#elements; + } + + isEmpty() { + return this.#elements === null; + } + + destroy() { + this.#elements = null; + } + + } + + class ColorManager { + static _colorsMapping = new Map([["CanvasText", [0, 0, 0]], ["Canvas", [255, 255, 255]]]); + + get _colors() { + const colors = new Map([["CanvasText", null], ["Canvas", null]]); + (0, _display_utils.getColorValues)(colors); + return (0, _util.shadow)(this, "_colors", colors); + } + + convert(color) { + const rgb = (0, _display_utils.getRGB)(color); + + if (!window.matchMedia("(forced-colors: active)").matches) { + return rgb; + } + + for (const [name, RGB] of this._colors) { + if (RGB.every((x, i) => x === rgb[i])) { + return ColorManager._colorsMapping.get(name); + } + } + + return rgb; + } + + getHexCode(name) { + const rgb = this._colors.get(name); + + if (!rgb) { + return name; + } + + return _util.Util.makeHexColor(...rgb); + } + + } + + exports.ColorManager = ColorManager; + + class AnnotationEditorUIManager { + #activeEditor = null; + #allEditors = new Map(); + #allLayers = new Map(); + #clipboardManager = new ClipboardManager(); + #commandManager = new CommandManager(); + #currentPageIndex = 0; + #editorTypes = null; + #eventBus = null; + #idManager = new IdManager(); + #isEnabled = false; + #mode = _util.AnnotationEditorType.NONE; + #selectedEditors = new Set(); + #boundKeydown = this.keydown.bind(this); + #boundOnEditingAction = this.onEditingAction.bind(this); + #boundOnPageChanging = this.onPageChanging.bind(this); + #previousStates = { + isEditing: false, + isEmpty: true, + hasEmptyClipboard: true, + hasSomethingToUndo: false, + hasSomethingToRedo: false, + hasSelectedEditor: false + }; + #container = null; + static _keyboardManager = new KeyboardManager([[["ctrl+a", "mac+meta+a"], AnnotationEditorUIManager.prototype.selectAll], [["ctrl+c", "mac+meta+c"], AnnotationEditorUIManager.prototype.copy], [["ctrl+v", "mac+meta+v"], AnnotationEditorUIManager.prototype.paste], [["ctrl+x", "mac+meta+x"], AnnotationEditorUIManager.prototype.cut], [["ctrl+z", "mac+meta+z"], AnnotationEditorUIManager.prototype.undo], [["ctrl+y", "ctrl+shift+Z", "mac+meta+shift+Z"], AnnotationEditorUIManager.prototype.redo], [["Backspace", "alt+Backspace", "ctrl+Backspace", "shift+Backspace", "mac+Backspace", "mac+alt+Backspace", "mac+ctrl+Backspace", "Delete", "ctrl+Delete", "shift+Delete"], AnnotationEditorUIManager.prototype.delete], [["Escape", "mac+Escape"], AnnotationEditorUIManager.prototype.unselectAll]]); + + constructor(container, eventBus) { + this.#container = container; + this.#eventBus = eventBus; + + this.#eventBus._on("editingaction", this.#boundOnEditingAction); + + this.#eventBus._on("pagechanging", this.#boundOnPageChanging); + } + + destroy() { + this.#removeKeyboardManager(); + + this.#eventBus._off("editingaction", this.#boundOnEditingAction); + + this.#eventBus._off("pagechanging", this.#boundOnPageChanging); + + for (const layer of this.#allLayers.values()) { + layer.destroy(); + } + + this.#allLayers.clear(); + this.#allEditors.clear(); + this.#activeEditor = null; + this.#selectedEditors.clear(); + this.#clipboardManager.destroy(); + this.#commandManager.destroy(); + } + + onPageChanging({ + pageNumber + }) { + this.#currentPageIndex = pageNumber - 1; + } + + focusMainContainer() { + this.#container.focus(); + } + + #addKeyboardManager() { + this.#container.addEventListener("keydown", this.#boundKeydown); + } + + #removeKeyboardManager() { + this.#container.removeEventListener("keydown", this.#boundKeydown); + } + + keydown(event) { + if (!this.getActive()?.shouldGetKeyboardEvents()) { + AnnotationEditorUIManager._keyboardManager.exec(this, event); + } + } + + onEditingAction(details) { + if (["undo", "redo", "cut", "copy", "paste", "delete", "selectAll"].includes(details.name)) { + this[details.name](); + } + } + + #dispatchUpdateStates(details) { + const hasChanged = Object.entries(details).some(([key, value]) => this.#previousStates[key] !== value); + + if (hasChanged) { + this.#eventBus.dispatch("annotationeditorstateschanged", { + source: this, + details: Object.assign(this.#previousStates, details) + }); + } + } + + #dispatchUpdateUI(details) { + this.#eventBus.dispatch("annotationeditorparamschanged", { + source: this, + details + }); + } + + setEditingState(isEditing) { + if (isEditing) { + this.#addKeyboardManager(); + this.#dispatchUpdateStates({ + isEditing: this.#mode !== _util.AnnotationEditorType.NONE, + isEmpty: this.#isEmpty(), + hasSomethingToUndo: this.#commandManager.hasSomethingToUndo(), + hasSomethingToRedo: this.#commandManager.hasSomethingToRedo(), + hasSelectedEditor: false, + hasEmptyClipboard: this.#clipboardManager.isEmpty() + }); + } else { + this.#removeKeyboardManager(); + this.#dispatchUpdateStates({ + isEditing: false + }); + } + } + + registerEditorTypes(types) { + this.#editorTypes = types; + + for (const editorType of this.#editorTypes) { + this.#dispatchUpdateUI(editorType.defaultPropertiesToUpdate); + } + } + + getId() { + return this.#idManager.getId(); + } + + addLayer(layer) { + this.#allLayers.set(layer.pageIndex, layer); + + if (this.#isEnabled) { + layer.enable(); + } else { + layer.disable(); + } + } + + removeLayer(layer) { + this.#allLayers.delete(layer.pageIndex); + } + + updateMode(mode) { + this.#mode = mode; + + if (mode === _util.AnnotationEditorType.NONE) { + this.setEditingState(false); + this.#disableAll(); + } else { + this.setEditingState(true); + this.#enableAll(); + + for (const layer of this.#allLayers.values()) { + layer.updateMode(mode); + } + } + } + + updateToolbar(mode) { + if (mode === this.#mode) { + return; + } + + this.#eventBus.dispatch("switchannotationeditormode", { + source: this, + mode + }); + } + + updateParams(type, value) { + for (const editor of this.#selectedEditors) { + editor.updateParams(type, value); + } + + for (const editorType of this.#editorTypes) { + editorType.updateDefaultParams(type, value); + } + } + + #enableAll() { + if (!this.#isEnabled) { + this.#isEnabled = true; + + for (const layer of this.#allLayers.values()) { + layer.enable(); + } + } + } + + #disableAll() { + this.unselectAll(); + + if (this.#isEnabled) { + this.#isEnabled = false; + + for (const layer of this.#allLayers.values()) { + layer.disable(); + } + } + } + + getEditors(pageIndex) { + const editors = []; + + for (const editor of this.#allEditors.values()) { + if (editor.pageIndex === pageIndex) { + editors.push(editor); + } + } + + return editors; + } + + getEditor(id) { + return this.#allEditors.get(id); + } + + addEditor(editor) { + this.#allEditors.set(editor.id, editor); + } + + removeEditor(editor) { + this.#allEditors.delete(editor.id); + this.unselect(editor); + } + + #addEditorToLayer(editor) { + const layer = this.#allLayers.get(editor.pageIndex); + + if (layer) { + layer.addOrRebuild(editor); + } else { + this.addEditor(editor); + } + } + + setActiveEditor(editor) { + if (this.#activeEditor === editor) { + return; + } + + this.#activeEditor = editor; + + if (editor) { + this.#dispatchUpdateUI(editor.propertiesToUpdate); + } + } + + toggleSelected(editor) { + if (this.#selectedEditors.has(editor)) { + this.#selectedEditors.delete(editor); + editor.unselect(); + this.#dispatchUpdateStates({ + hasSelectedEditor: this.hasSelection + }); + return; + } + + this.#selectedEditors.add(editor); + editor.select(); + this.#dispatchUpdateUI(editor.propertiesToUpdate); + this.#dispatchUpdateStates({ + hasSelectedEditor: true + }); + } + + setSelected(editor) { + for (const ed of this.#selectedEditors) { + if (ed !== editor) { + ed.unselect(); + } + } + + this.#selectedEditors.clear(); + this.#selectedEditors.add(editor); + editor.select(); + this.#dispatchUpdateUI(editor.propertiesToUpdate); + this.#dispatchUpdateStates({ + hasSelectedEditor: true + }); + } + + isSelected(editor) { + return this.#selectedEditors.has(editor); + } + + unselect(editor) { + editor.unselect(); + this.#selectedEditors.delete(editor); + this.#dispatchUpdateStates({ + hasSelectedEditor: this.hasSelection + }); + } + + get hasSelection() { + return this.#selectedEditors.size !== 0; + } + + undo() { + this.#commandManager.undo(); + this.#dispatchUpdateStates({ + hasSomethingToUndo: this.#commandManager.hasSomethingToUndo(), + hasSomethingToRedo: true, + isEmpty: this.#isEmpty() + }); + } + + redo() { + this.#commandManager.redo(); + this.#dispatchUpdateStates({ + hasSomethingToUndo: true, + hasSomethingToRedo: this.#commandManager.hasSomethingToRedo(), + isEmpty: this.#isEmpty() + }); + } + + addCommands(params) { + this.#commandManager.add(params); + this.#dispatchUpdateStates({ + hasSomethingToUndo: true, + hasSomethingToRedo: false, + isEmpty: this.#isEmpty() + }); + } + + #isEmpty() { + if (this.#allEditors.size === 0) { + return true; + } + + if (this.#allEditors.size === 1) { + for (const editor of this.#allEditors.values()) { + return editor.isEmpty(); + } + } + + return false; + } + + delete() { + if (this.#activeEditor) { + this.#activeEditor.commitOrRemove(); + } + + if (!this.hasSelection) { + return; + } + + const editors = [...this.#selectedEditors]; + + const cmd = () => { + for (const editor of editors) { + editor.remove(); + } + }; + + const undo = () => { + for (const editor of editors) { + this.#addEditorToLayer(editor); + } + }; + + this.addCommands({ + cmd, + undo, + mustExec: true + }); + } + + copy() { + if (this.#activeEditor) { + this.#activeEditor.commitOrRemove(); + } + + if (this.hasSelection) { + const editors = []; + + for (const editor of this.#selectedEditors) { + if (!editor.isEmpty()) { + editors.push(editor); + } + } + + if (editors.length === 0) { + return; + } + + this.#clipboardManager.copy(editors); + this.#dispatchUpdateStates({ + hasEmptyClipboard: false + }); + } + } + + cut() { + this.copy(); + this.delete(); + } + + paste() { + if (this.#clipboardManager.isEmpty()) { + return; + } + + this.unselectAll(); + const layer = this.#allLayers.get(this.#currentPageIndex); + const newEditors = this.#clipboardManager.paste().map(data => layer.deserialize(data)); + + const cmd = () => { + for (const editor of newEditors) { + this.#addEditorToLayer(editor); + } + + this.#selectEditors(newEditors); + }; + + const undo = () => { + for (const editor of newEditors) { + editor.remove(); + } + }; + + this.addCommands({ + cmd, + undo, + mustExec: true + }); + } + + #selectEditors(editors) { + this.#selectedEditors.clear(); + + for (const editor of editors) { + if (editor.isEmpty()) { + continue; + } + + this.#selectedEditors.add(editor); + editor.select(); + } + + this.#dispatchUpdateStates({ + hasSelectedEditor: true + }); + } + + selectAll() { + for (const editor of this.#selectedEditors) { + editor.commit(); + } + + this.#selectEditors(this.#allEditors.values()); + } + + unselectAll() { + if (this.#activeEditor) { + this.#activeEditor.commitOrRemove(); + return; + } + + if (this.#selectEditors.size === 0) { + return; + } + + for (const editor of this.#selectedEditors) { + editor.unselect(); + } + + this.#selectedEditors.clear(); + this.#dispatchUpdateStates({ + hasSelectedEditor: false + }); + } + + isActive(editor) { + return this.#activeEditor === editor; + } + + getActive() { + return this.#activeEditor; + } + + getMode() { + return this.#mode; + } + + } + + exports.AnnotationEditorUIManager = AnnotationEditorUIManager; + + /***/ }), + /* 8 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.StatTimer = exports.RenderingCancelledException = exports.PixelsPerInch = exports.PageViewport = exports.PDFDateString = exports.DOMStandardFontDataFactory = exports.DOMSVGFactory = exports.DOMCanvasFactory = exports.DOMCMapReaderFactory = exports.AnnotationPrefix = void 0; + exports.deprecated = deprecated; + exports.getColorValues = getColorValues; + exports.getCurrentTransform = getCurrentTransform; + exports.getCurrentTransformInverse = getCurrentTransformInverse; + exports.getFilenameFromUrl = getFilenameFromUrl; + exports.getPdfFilenameFromUrl = getPdfFilenameFromUrl; + exports.getRGB = getRGB; + exports.getXfaPageViewport = getXfaPageViewport; + exports.isDataScheme = isDataScheme; + exports.isPdfFile = isPdfFile; + exports.isValidFetchUrl = isValidFetchUrl; + exports.loadScript = loadScript; + + var _base_factory = __w_pdfjs_require__(9); + + var _util = __w_pdfjs_require__(1); + + const SVG_NS = "http://www.w3.org/2000/svg"; + const AnnotationPrefix = "pdfjs_internal_id_"; + exports.AnnotationPrefix = AnnotationPrefix; + + class PixelsPerInch { + static CSS = 96.0; + static PDF = 72.0; + static PDF_TO_CSS_UNITS = this.CSS / this.PDF; + } + + exports.PixelsPerInch = PixelsPerInch; + + class DOMCanvasFactory extends _base_factory.BaseCanvasFactory { + constructor({ + ownerDocument = globalThis.document + } = {}) { + super(); + this._document = ownerDocument; + } + + _createCanvas(width, height) { + const canvas = this._document.createElement("canvas"); + + canvas.width = width; + canvas.height = height; + return canvas; + } + + } + + exports.DOMCanvasFactory = DOMCanvasFactory; + + async function fetchData(url, asTypedArray = false) { + if (isValidFetchUrl(url, document.baseURI)) { + const response = await fetch(url); + + if (!response.ok) { + throw new Error(response.statusText); + } + + return asTypedArray ? new Uint8Array(await response.arrayBuffer()) : (0, _util.stringToBytes)(await response.text()); + } + + return new Promise((resolve, reject) => { + const request = new XMLHttpRequest(); + request.open("GET", url, true); + + if (asTypedArray) { + request.responseType = "arraybuffer"; + } + + request.onreadystatechange = () => { + if (request.readyState !== XMLHttpRequest.DONE) { + return; + } + + if (request.status === 200 || request.status === 0) { + let data; + + if (asTypedArray && request.response) { + data = new Uint8Array(request.response); + } else if (!asTypedArray && request.responseText) { + data = (0, _util.stringToBytes)(request.responseText); + } + + if (data) { + resolve(data); + return; + } + } + + reject(new Error(request.statusText)); + }; + + request.send(null); + }); + } + + class DOMCMapReaderFactory extends _base_factory.BaseCMapReaderFactory { + _fetchData(url, compressionType) { + return fetchData(url, this.isCompressed).then(data => { + return { + cMapData: data, + compressionType + }; + }); + } + + } + + exports.DOMCMapReaderFactory = DOMCMapReaderFactory; + + class DOMStandardFontDataFactory extends _base_factory.BaseStandardFontDataFactory { + _fetchData(url) { + return fetchData(url, true); + } + + } + + exports.DOMStandardFontDataFactory = DOMStandardFontDataFactory; + + class DOMSVGFactory extends _base_factory.BaseSVGFactory { + _createSVG(type) { + return document.createElementNS(SVG_NS, type); + } + + } + + exports.DOMSVGFactory = DOMSVGFactory; + + class PageViewport { + constructor({ + viewBox, + scale, + rotation, + offsetX = 0, + offsetY = 0, + dontFlip = false + }) { + this.viewBox = viewBox; + this.scale = scale; + this.rotation = rotation; + this.offsetX = offsetX; + this.offsetY = offsetY; + const centerX = (viewBox[2] + viewBox[0]) / 2; + const centerY = (viewBox[3] + viewBox[1]) / 2; + let rotateA, rotateB, rotateC, rotateD; + rotation %= 360; + + if (rotation < 0) { + rotation += 360; + } + + switch (rotation) { + case 180: + rotateA = -1; + rotateB = 0; + rotateC = 0; + rotateD = 1; + break; + + case 90: + rotateA = 0; + rotateB = 1; + rotateC = 1; + rotateD = 0; + break; + + case 270: + rotateA = 0; + rotateB = -1; + rotateC = -1; + rotateD = 0; + break; + + case 0: + rotateA = 1; + rotateB = 0; + rotateC = 0; + rotateD = -1; + break; + + default: + throw new Error("PageViewport: Invalid rotation, must be a multiple of 90 degrees."); + } + + if (dontFlip) { + rotateC = -rotateC; + rotateD = -rotateD; + } + + let offsetCanvasX, offsetCanvasY; + let width, height; + + if (rotateA === 0) { + offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX; + offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY; + width = Math.abs(viewBox[3] - viewBox[1]) * scale; + height = Math.abs(viewBox[2] - viewBox[0]) * scale; + } else { + offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX; + offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY; + width = Math.abs(viewBox[2] - viewBox[0]) * scale; + height = Math.abs(viewBox[3] - viewBox[1]) * scale; + } + + this.transform = [rotateA * scale, rotateB * scale, rotateC * scale, rotateD * scale, offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY, offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY]; + this.width = width; + this.height = height; + } + + clone({ + scale = this.scale, + rotation = this.rotation, + offsetX = this.offsetX, + offsetY = this.offsetY, + dontFlip = false + } = {}) { + return new PageViewport({ + viewBox: this.viewBox.slice(), + scale, + rotation, + offsetX, + offsetY, + dontFlip + }); + } + + convertToViewportPoint(x, y) { + return _util.Util.applyTransform([x, y], this.transform); + } + + convertToViewportRectangle(rect) { + const topLeft = _util.Util.applyTransform([rect[0], rect[1]], this.transform); + + const bottomRight = _util.Util.applyTransform([rect[2], rect[3]], this.transform); + + return [topLeft[0], topLeft[1], bottomRight[0], bottomRight[1]]; + } + + convertToPdfPoint(x, y) { + return _util.Util.applyInverseTransform([x, y], this.transform); + } + + } + + exports.PageViewport = PageViewport; + + class RenderingCancelledException extends _util.BaseException { + constructor(msg, type) { + super(msg, "RenderingCancelledException"); + this.type = type; + } + + } + + exports.RenderingCancelledException = RenderingCancelledException; + + function isDataScheme(url) { + const ii = url.length; + let i = 0; + + while (i < ii && url[i].trim() === "") { + i++; + } + + return url.substring(i, i + 5).toLowerCase() === "data:"; + } + + function isPdfFile(filename) { + return typeof filename === "string" && /\.pdf$/i.test(filename); + } + + function getFilenameFromUrl(url) { + const anchor = url.indexOf("#"); + const query = url.indexOf("?"); + const end = Math.min(anchor > 0 ? anchor : url.length, query > 0 ? query : url.length); + return url.substring(url.lastIndexOf("/", end) + 1, end); + } + + function getPdfFilenameFromUrl(url, defaultFilename = "document.pdf") { + if (typeof url !== "string") { + return defaultFilename; + } + + if (isDataScheme(url)) { + (0, _util.warn)('getPdfFilenameFromUrl: ignore "data:"-URL for performance reasons.'); + return defaultFilename; + } + + const reURI = /^(?:(?:[^:]+:)?\/\/[^/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/; + const reFilename = /[^/?#=]+\.pdf\b(?!.*\.pdf\b)/i; + const splitURI = reURI.exec(url); + let suggestedFilename = reFilename.exec(splitURI[1]) || reFilename.exec(splitURI[2]) || reFilename.exec(splitURI[3]); + + if (suggestedFilename) { + suggestedFilename = suggestedFilename[0]; + + if (suggestedFilename.includes("%")) { + try { + suggestedFilename = reFilename.exec(decodeURIComponent(suggestedFilename))[0]; + } catch (ex) {} + } + } + + return suggestedFilename || defaultFilename; + } + + class StatTimer { + constructor() { + this.started = Object.create(null); + this.times = []; + } + + time(name) { + if (name in this.started) { + (0, _util.warn)(`Timer is already running for ${name}`); + } + + this.started[name] = Date.now(); + } + + timeEnd(name) { + if (!(name in this.started)) { + (0, _util.warn)(`Timer has not been started for ${name}`); + } + + this.times.push({ + name, + start: this.started[name], + end: Date.now() + }); + delete this.started[name]; + } + + toString() { + const outBuf = []; + let longest = 0; + + for (const time of this.times) { + const name = time.name; + + if (name.length > longest) { + longest = name.length; + } + } + + for (const time of this.times) { + const duration = time.end - time.start; + outBuf.push(`${time.name.padEnd(longest)} ${duration}ms\n`); + } + + return outBuf.join(""); + } + + } + + exports.StatTimer = StatTimer; + + function isValidFetchUrl(url, baseUrl) { + try { + const { + protocol + } = baseUrl ? new URL(url, baseUrl) : new URL(url); + return protocol === "http:" || protocol === "https:"; + } catch (ex) { + return false; + } + } + + function loadScript(src, removeScriptElement = false) { + return new Promise((resolve, reject) => { + const script = document.createElement("script"); + script.src = src; + + script.onload = function (evt) { + if (removeScriptElement) { + script.remove(); + } + + resolve(evt); + }; + + script.onerror = function () { + reject(new Error(`Cannot load script at: ${script.src}`)); + }; + + (document.head || document.documentElement).append(script); + }); + } + + function deprecated(details) { + console.log("Deprecated API usage: " + details); + } + + let pdfDateStringRegex; + + class PDFDateString { + static toDateObject(input) { + if (!input || typeof input !== "string") { + return null; + } + + if (!pdfDateStringRegex) { + pdfDateStringRegex = new RegExp("^D:" + "(\\d{4})" + "(\\d{2})?" + "(\\d{2})?" + "(\\d{2})?" + "(\\d{2})?" + "(\\d{2})?" + "([Z|+|-])?" + "(\\d{2})?" + "'?" + "(\\d{2})?" + "'?"); + } + + const matches = pdfDateStringRegex.exec(input); + + if (!matches) { + return null; + } + + const year = parseInt(matches[1], 10); + let month = parseInt(matches[2], 10); + month = month >= 1 && month <= 12 ? month - 1 : 0; + let day = parseInt(matches[3], 10); + day = day >= 1 && day <= 31 ? day : 1; + let hour = parseInt(matches[4], 10); + hour = hour >= 0 && hour <= 23 ? hour : 0; + let minute = parseInt(matches[5], 10); + minute = minute >= 0 && minute <= 59 ? minute : 0; + let second = parseInt(matches[6], 10); + second = second >= 0 && second <= 59 ? second : 0; + const universalTimeRelation = matches[7] || "Z"; + let offsetHour = parseInt(matches[8], 10); + offsetHour = offsetHour >= 0 && offsetHour <= 23 ? offsetHour : 0; + let offsetMinute = parseInt(matches[9], 10) || 0; + offsetMinute = offsetMinute >= 0 && offsetMinute <= 59 ? offsetMinute : 0; + + if (universalTimeRelation === "-") { + hour += offsetHour; + minute += offsetMinute; + } else if (universalTimeRelation === "+") { + hour -= offsetHour; + minute -= offsetMinute; + } + + return new Date(Date.UTC(year, month, day, hour, minute, second)); + } + + } + + exports.PDFDateString = PDFDateString; + + function getXfaPageViewport(xfaPage, { + scale = 1, + rotation = 0 + }) { + const { + width, + height + } = xfaPage.attributes.style; + const viewBox = [0, 0, parseInt(width), parseInt(height)]; + return new PageViewport({ + viewBox, + scale, + rotation + }); + } + + function getRGB(color) { + if (color.startsWith("#")) { + const colorRGB = parseInt(color.slice(1), 16); + return [(colorRGB & 0xff0000) >> 16, (colorRGB & 0x00ff00) >> 8, colorRGB & 0x0000ff]; + } + + if (color.startsWith("rgb(")) { + return color.slice(4, -1).split(",").map(x => parseInt(x)); + } + + if (color.startsWith("rgba(")) { + return color.slice(5, -1).split(",").map(x => parseInt(x)).slice(0, 3); + } + + (0, _util.warn)(`Not a valid color format: "${color}"`); + return [0, 0, 0]; + } + + function getColorValues(colors) { + const span = document.createElement("span"); + span.style.visibility = "hidden"; + document.body.append(span); + + for (const name of colors.keys()) { + span.style.color = name; + const computedColor = window.getComputedStyle(span).color; + colors.set(name, getRGB(computedColor)); + } + + span.remove(); + } + + function getCurrentTransform(ctx) { + const { + a, + b, + c, + d, + e, + f + } = ctx.getTransform(); + return [a, b, c, d, e, f]; + } + + function getCurrentTransformInverse(ctx) { + const { + a, + b, + c, + d, + e, + f + } = ctx.getTransform().invertSelf(); + return [a, b, c, d, e, f]; + } + + /***/ }), + /* 9 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.BaseStandardFontDataFactory = exports.BaseSVGFactory = exports.BaseCanvasFactory = exports.BaseCMapReaderFactory = void 0; + + var _util = __w_pdfjs_require__(1); + + class BaseCanvasFactory { + constructor() { + if (this.constructor === BaseCanvasFactory) { + (0, _util.unreachable)("Cannot initialize BaseCanvasFactory."); + } + } + + create(width, height) { + if (width <= 0 || height <= 0) { + throw new Error("Invalid canvas size"); + } + + const canvas = this._createCanvas(width, height); + + return { + canvas, + context: canvas.getContext("2d") + }; + } + + reset(canvasAndContext, width, height) { + if (!canvasAndContext.canvas) { + throw new Error("Canvas is not specified"); + } + + if (width <= 0 || height <= 0) { + throw new Error("Invalid canvas size"); + } + + canvasAndContext.canvas.width = width; + canvasAndContext.canvas.height = height; + } + + destroy(canvasAndContext) { + if (!canvasAndContext.canvas) { + throw new Error("Canvas is not specified"); + } + + canvasAndContext.canvas.width = 0; + canvasAndContext.canvas.height = 0; + canvasAndContext.canvas = null; + canvasAndContext.context = null; + } + + _createCanvas(width, height) { + (0, _util.unreachable)("Abstract method `_createCanvas` called."); + } + + } + + exports.BaseCanvasFactory = BaseCanvasFactory; + + class BaseCMapReaderFactory { + constructor({ + baseUrl = null, + isCompressed = false + }) { + if (this.constructor === BaseCMapReaderFactory) { + (0, _util.unreachable)("Cannot initialize BaseCMapReaderFactory."); + } + + this.baseUrl = baseUrl; + this.isCompressed = isCompressed; + } + + async fetch({ + name + }) { + if (!this.baseUrl) { + throw new Error('The CMap "baseUrl" parameter must be specified, ensure that ' + 'the "cMapUrl" and "cMapPacked" API parameters are provided.'); + } + + if (!name) { + throw new Error("CMap name must be specified."); + } + + const url = this.baseUrl + name + (this.isCompressed ? ".bcmap" : ""); + const compressionType = this.isCompressed ? _util.CMapCompressionType.BINARY : _util.CMapCompressionType.NONE; + return this._fetchData(url, compressionType).catch(reason => { + throw new Error(`Unable to load ${this.isCompressed ? "binary " : ""}CMap at: ${url}`); + }); + } + + _fetchData(url, compressionType) { + (0, _util.unreachable)("Abstract method `_fetchData` called."); + } + + } + + exports.BaseCMapReaderFactory = BaseCMapReaderFactory; + + class BaseStandardFontDataFactory { + constructor({ + baseUrl = null + }) { + if (this.constructor === BaseStandardFontDataFactory) { + (0, _util.unreachable)("Cannot initialize BaseStandardFontDataFactory."); + } + + this.baseUrl = baseUrl; + } + + async fetch({ + filename + }) { + if (!this.baseUrl) { + throw new Error('The standard font "baseUrl" parameter must be specified, ensure that ' + 'the "standardFontDataUrl" API parameter is provided.'); + } + + if (!filename) { + throw new Error("Font filename must be specified."); + } + + const url = `${this.baseUrl}${filename}`; + return this._fetchData(url).catch(reason => { + throw new Error(`Unable to load font data at: ${url}`); + }); + } + + _fetchData(url) { + (0, _util.unreachable)("Abstract method `_fetchData` called."); + } + + } + + exports.BaseStandardFontDataFactory = BaseStandardFontDataFactory; + + class BaseSVGFactory { + constructor() { + if (this.constructor === BaseSVGFactory) { + (0, _util.unreachable)("Cannot initialize BaseSVGFactory."); + } + } + + create(width, height, skipDimensions = false) { + if (width <= 0 || height <= 0) { + throw new Error("Invalid SVG dimensions"); + } + + const svg = this._createSVG("svg:svg"); + + svg.setAttribute("version", "1.1"); + + if (!skipDimensions) { + svg.setAttribute("width", `${width}px`); + svg.setAttribute("height", `${height}px`); + } + + svg.setAttribute("preserveAspectRatio", "none"); + svg.setAttribute("viewBox", `0 0 ${width} ${height}`); + return svg; + } + + createElement(type) { + if (typeof type !== "string") { + throw new Error("Invalid SVG element type"); + } + + return this._createSVG(type); + } + + _createSVG(type) { + (0, _util.unreachable)("Abstract method `_createSVG` called."); + } + + } + + exports.BaseSVGFactory = BaseSVGFactory; + + /***/ }), + /* 10 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.MurmurHash3_64 = void 0; + + var _util = __w_pdfjs_require__(1); + + const SEED = 0xc3d2e1f0; + const MASK_HIGH = 0xffff0000; + const MASK_LOW = 0xffff; + + class MurmurHash3_64 { + constructor(seed) { + this.h1 = seed ? seed & 0xffffffff : SEED; + this.h2 = seed ? seed & 0xffffffff : SEED; + } + + update(input) { + let data, length; + + if (typeof input === "string") { + data = new Uint8Array(input.length * 2); + length = 0; + + for (let i = 0, ii = input.length; i < ii; i++) { + const code = input.charCodeAt(i); + + if (code <= 0xff) { + data[length++] = code; + } else { + data[length++] = code >>> 8; + data[length++] = code & 0xff; + } + } + } else if ((0, _util.isArrayBuffer)(input)) { + data = input.slice(); + length = data.byteLength; + } else { + throw new Error("Wrong data format in MurmurHash3_64_update. " + "Input must be a string or array."); + } + + const blockCounts = length >> 2; + const tailLength = length - blockCounts * 4; + const dataUint32 = new Uint32Array(data.buffer, 0, blockCounts); + let k1 = 0, + k2 = 0; + let h1 = this.h1, + h2 = this.h2; + const C1 = 0xcc9e2d51, + C2 = 0x1b873593; + const C1_LOW = C1 & MASK_LOW, + C2_LOW = C2 & MASK_LOW; + + for (let i = 0; i < blockCounts; i++) { + if (i & 1) { + k1 = dataUint32[i]; + k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW; + k1 = k1 << 15 | k1 >>> 17; + k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW; + h1 ^= k1; + h1 = h1 << 13 | h1 >>> 19; + h1 = h1 * 5 + 0xe6546b64; + } else { + k2 = dataUint32[i]; + k2 = k2 * C1 & MASK_HIGH | k2 * C1_LOW & MASK_LOW; + k2 = k2 << 15 | k2 >>> 17; + k2 = k2 * C2 & MASK_HIGH | k2 * C2_LOW & MASK_LOW; + h2 ^= k2; + h2 = h2 << 13 | h2 >>> 19; + h2 = h2 * 5 + 0xe6546b64; + } + } + + k1 = 0; + + switch (tailLength) { + case 3: + k1 ^= data[blockCounts * 4 + 2] << 16; + + case 2: + k1 ^= data[blockCounts * 4 + 1] << 8; + + case 1: + k1 ^= data[blockCounts * 4]; + k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW; + k1 = k1 << 15 | k1 >>> 17; + k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW; + + if (blockCounts & 1) { + h1 ^= k1; + } else { + h2 ^= k1; + } + + } + + this.h1 = h1; + this.h2 = h2; + } + + hexdigest() { + let h1 = this.h1, + h2 = this.h2; + h1 ^= h2 >>> 1; + h1 = h1 * 0xed558ccd & MASK_HIGH | h1 * 0x8ccd & MASK_LOW; + h2 = h2 * 0xff51afd7 & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xafd7ed55 & MASK_HIGH) >>> 16; + h1 ^= h2 >>> 1; + h1 = h1 * 0x1a85ec53 & MASK_HIGH | h1 * 0xec53 & MASK_LOW; + h2 = h2 * 0xc4ceb9fe & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xb9fe1a85 & MASK_HIGH) >>> 16; + h1 ^= h2 >>> 1; + const hex1 = (h1 >>> 0).toString(16), + hex2 = (h2 >>> 0).toString(16); + return hex1.padStart(8, "0") + hex2.padStart(8, "0"); + } + + } + + exports.MurmurHash3_64 = MurmurHash3_64; + + /***/ }), + /* 11 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.FontLoader = exports.FontFaceObject = void 0; + + var _util = __w_pdfjs_require__(1); + + class BaseFontLoader { + constructor({ + docId, + onUnsupportedFeature, + ownerDocument = globalThis.document, + styleElement = null + }) { + if (this.constructor === BaseFontLoader) { + (0, _util.unreachable)("Cannot initialize BaseFontLoader."); + } + + this.docId = docId; + this._onUnsupportedFeature = onUnsupportedFeature; + this._document = ownerDocument; + this.nativeFontFaces = []; + this.styleElement = null; + } + + addNativeFontFace(nativeFontFace) { + this.nativeFontFaces.push(nativeFontFace); + + this._document.fonts.add(nativeFontFace); + } + + insertRule(rule) { + let styleElement = this.styleElement; + + if (!styleElement) { + styleElement = this.styleElement = this._document.createElement("style"); + styleElement.id = `PDFJS_FONT_STYLE_TAG_${this.docId}`; + + this._document.documentElement.getElementsByTagName("head")[0].append(styleElement); + } + + const styleSheet = styleElement.sheet; + styleSheet.insertRule(rule, styleSheet.cssRules.length); + } + + clear() { + for (const nativeFontFace of this.nativeFontFaces) { + this._document.fonts.delete(nativeFontFace); + } + + this.nativeFontFaces.length = 0; + + if (this.styleElement) { + this.styleElement.remove(); + this.styleElement = null; + } + } + + async bind(font) { + if (font.attached || font.missingFile) { + return; + } + + font.attached = true; + + if (this.isFontLoadingAPISupported) { + const nativeFontFace = font.createNativeFontFace(); + + if (nativeFontFace) { + this.addNativeFontFace(nativeFontFace); + + try { + await nativeFontFace.loaded; + } catch (ex) { + this._onUnsupportedFeature({ + featureId: _util.UNSUPPORTED_FEATURES.errorFontLoadNative + }); + + (0, _util.warn)(`Failed to load font '${nativeFontFace.family}': '${ex}'.`); + font.disableFontFace = true; + throw ex; + } + } + + return; + } + + const rule = font.createFontFaceRule(); + + if (rule) { + this.insertRule(rule); + + if (this.isSyncFontLoadingSupported) { + return; + } + + await new Promise(resolve => { + const request = this._queueLoadingCallback(resolve); + + this._prepareFontLoadEvent([rule], [font], request); + }); + } + } + + _queueLoadingCallback(callback) { + (0, _util.unreachable)("Abstract method `_queueLoadingCallback`."); + } + + get isFontLoadingAPISupported() { + const hasFonts = !!this._document?.fonts; + return (0, _util.shadow)(this, "isFontLoadingAPISupported", hasFonts); + } + + get isSyncFontLoadingSupported() { + (0, _util.unreachable)("Abstract method `isSyncFontLoadingSupported`."); + } + + get _loadTestFont() { + (0, _util.unreachable)("Abstract method `_loadTestFont`."); + } + + _prepareFontLoadEvent(rules, fontsToLoad, request) { + (0, _util.unreachable)("Abstract method `_prepareFontLoadEvent`."); + } + + } + + let FontLoader; + exports.FontLoader = FontLoader; + { + exports.FontLoader = FontLoader = class GenericFontLoader extends BaseFontLoader { + constructor(params) { + super(params); + this.loadingContext = { + requests: [], + nextRequestId: 0 + }; + this.loadTestFontId = 0; + } + + get isSyncFontLoadingSupported() { + let supported = false; + + if (typeof navigator === "undefined") { + supported = true; + } else { + const m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(navigator.userAgent); + + if (m?.[1] >= 14) { + supported = true; + } + } + + return (0, _util.shadow)(this, "isSyncFontLoadingSupported", supported); + } + + _queueLoadingCallback(callback) { + function completeRequest() { + (0, _util.assert)(!request.done, "completeRequest() cannot be called twice."); + request.done = true; + + while (context.requests.length > 0 && context.requests[0].done) { + const otherRequest = context.requests.shift(); + setTimeout(otherRequest.callback, 0); + } + } + + const context = this.loadingContext; + const request = { + id: `pdfjs-font-loading-${context.nextRequestId++}`, + done: false, + complete: completeRequest, + callback + }; + context.requests.push(request); + return request; + } + + get _loadTestFont() { + const getLoadTestFont = function () { + return atob("T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQA" + "FQAABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAA" + "ALwAAAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgA" + "AAAGbmFtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1" + "AAsD6AAAAADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD" + "6AAAAAAD6AABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACM" + "AooCvAAAAeAAMQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4D" + "IP84AFoDIQAAAAAAAQAAAAAAAAAAACAAIAABAAAADgCuAAEAAAAAAAAAAQAAAAEAAAAA" + "AAEAAQAAAAEAAAAAAAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUA" + "AQAAAAEAAAAAAAYAAQAAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgAB" + "AAMAAQQJAAMAAgABAAMAAQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABY" + "AAAAAAAAAwAAAAMAAAAcAAEAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAA" + "AC7////TAAEAAAAAAAABBgAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAA" + "AAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgcA/gXBIwMAYuL+nz5tQXkD5j3CBLnEQAC" + "AQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYAAABAQAADwACAQEEE/t3" + "Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQAAAAAAAABAAAAAMmJbzEAAAAAzgTj" + "FQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAgABAAAAAAAAAAAD6AAAAAAAAA=="); + }; + + return (0, _util.shadow)(this, "_loadTestFont", getLoadTestFont()); + } + + _prepareFontLoadEvent(rules, fonts, request) { + function int32(data, offset) { + return data.charCodeAt(offset) << 24 | data.charCodeAt(offset + 1) << 16 | data.charCodeAt(offset + 2) << 8 | data.charCodeAt(offset + 3) & 0xff; + } + + function spliceString(s, offset, remove, insert) { + const chunk1 = s.substring(0, offset); + const chunk2 = s.substring(offset + remove); + return chunk1 + insert + chunk2; + } + + let i, ii; + + const canvas = this._document.createElement("canvas"); + + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext("2d"); + let called = 0; + + function isFontReady(name, callback) { + called++; + + if (called > 30) { + (0, _util.warn)("Load test font never loaded."); + callback(); + return; + } + + ctx.font = "30px " + name; + ctx.fillText(".", 0, 20); + const imageData = ctx.getImageData(0, 0, 1, 1); + + if (imageData.data[3] > 0) { + callback(); + return; + } + + setTimeout(isFontReady.bind(null, name, callback)); + } + + const loadTestFontId = `lt${Date.now()}${this.loadTestFontId++}`; + let data = this._loadTestFont; + const COMMENT_OFFSET = 976; + data = spliceString(data, COMMENT_OFFSET, loadTestFontId.length, loadTestFontId); + const CFF_CHECKSUM_OFFSET = 16; + const XXXX_VALUE = 0x58585858; + let checksum = int32(data, CFF_CHECKSUM_OFFSET); + + for (i = 0, ii = loadTestFontId.length - 3; i < ii; i += 4) { + checksum = checksum - XXXX_VALUE + int32(loadTestFontId, i) | 0; + } + + if (i < loadTestFontId.length) { + checksum = checksum - XXXX_VALUE + int32(loadTestFontId + "XXX", i) | 0; + } + + data = spliceString(data, CFF_CHECKSUM_OFFSET, 4, (0, _util.string32)(checksum)); + const url = `url(data:font/opentype;base64,${btoa(data)});`; + const rule = `@font-face {font-family:"${loadTestFontId}";src:${url}}`; + this.insertRule(rule); + const names = []; + + for (const font of fonts) { + names.push(font.loadedName); + } + + names.push(loadTestFontId); + + const div = this._document.createElement("div"); + + div.style.visibility = "hidden"; + div.style.width = div.style.height = "10px"; + div.style.position = "absolute"; + div.style.top = div.style.left = "0px"; + + for (const name of names) { + const span = this._document.createElement("span"); + + span.textContent = "Hi"; + span.style.fontFamily = name; + div.append(span); + } + + this._document.body.append(div); + + isFontReady(loadTestFontId, () => { + div.remove(); + request.complete(); + }); + } + + }; + } + + class FontFaceObject { + constructor(translatedData, { + isEvalSupported = true, + disableFontFace = false, + ignoreErrors = false, + onUnsupportedFeature, + fontRegistry = null + }) { + this.compiledGlyphs = Object.create(null); + + for (const i in translatedData) { + this[i] = translatedData[i]; + } + + this.isEvalSupported = isEvalSupported !== false; + this.disableFontFace = disableFontFace === true; + this.ignoreErrors = ignoreErrors === true; + this._onUnsupportedFeature = onUnsupportedFeature; + this.fontRegistry = fontRegistry; + } + + createNativeFontFace() { + if (!this.data || this.disableFontFace) { + return null; + } + + let nativeFontFace; + + if (!this.cssFontInfo) { + nativeFontFace = new FontFace(this.loadedName, this.data, {}); + } else { + const css = { + weight: this.cssFontInfo.fontWeight + }; + + if (this.cssFontInfo.italicAngle) { + css.style = `oblique ${this.cssFontInfo.italicAngle}deg`; + } + + nativeFontFace = new FontFace(this.cssFontInfo.fontFamily, this.data, css); + } + + if (this.fontRegistry) { + this.fontRegistry.registerFont(this); + } + + return nativeFontFace; + } + + createFontFaceRule() { + if (!this.data || this.disableFontFace) { + return null; + } + + const data = (0, _util.bytesToString)(this.data); + const url = `url(data:${this.mimetype};base64,${btoa(data)});`; + let rule; + + if (!this.cssFontInfo) { + rule = `@font-face {font-family:"${this.loadedName}";src:${url}}`; + } else { + let css = `font-weight: ${this.cssFontInfo.fontWeight};`; + + if (this.cssFontInfo.italicAngle) { + css += `font-style: oblique ${this.cssFontInfo.italicAngle}deg;`; + } + + rule = `@font-face {font-family:"${this.cssFontInfo.fontFamily}";${css}src:${url}}`; + } + + if (this.fontRegistry) { + this.fontRegistry.registerFont(this, url); + } + + return rule; + } + + getPathGenerator(objs, character) { + if (this.compiledGlyphs[character] !== undefined) { + return this.compiledGlyphs[character]; + } + + let cmds; + + try { + cmds = objs.get(this.loadedName + "_path_" + character); + } catch (ex) { + if (!this.ignoreErrors) { + throw ex; + } + + this._onUnsupportedFeature({ + featureId: _util.UNSUPPORTED_FEATURES.errorFontGetPath + }); + + (0, _util.warn)(`getPathGenerator - ignoring character: "${ex}".`); + return this.compiledGlyphs[character] = function (c, size) {}; + } + + if (this.isEvalSupported && _util.FeatureTest.isEvalSupported) { + const jsBuf = []; + + for (const current of cmds) { + const args = current.args !== undefined ? current.args.join(",") : ""; + jsBuf.push("c.", current.cmd, "(", args, ");\n"); + } + + return this.compiledGlyphs[character] = new Function("c", "size", jsBuf.join("")); + } + + return this.compiledGlyphs[character] = function (c, size) { + for (const current of cmds) { + if (current.cmd === "scale") { + current.args = [size, -size]; + } + + c[current.cmd].apply(c, current.args); + } + }; + } + + } + + exports.FontFaceObject = FontFaceObject; + + /***/ }), + /* 12 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.CanvasGraphics = void 0; + + var _display_utils = __w_pdfjs_require__(8); + + var _util = __w_pdfjs_require__(1); + + var _pattern_helper = __w_pdfjs_require__(13); + + var _image_utils = __w_pdfjs_require__(14); + + var _is_node = __w_pdfjs_require__(3); + + const MIN_FONT_SIZE = 16; + const MAX_FONT_SIZE = 100; + const MAX_GROUP_SIZE = 4096; + const EXECUTION_TIME = 15; + const EXECUTION_STEPS = 10; + const MAX_SIZE_TO_COMPILE = _is_node.isNodeJS && typeof Path2D === "undefined" ? -1 : 1000; + const FULL_CHUNK_HEIGHT = 16; + + function mirrorContextOperations(ctx, destCtx) { + if (ctx._removeMirroring) { + throw new Error("Context is already forwarding operations."); + } + + ctx.__originalSave = ctx.save; + ctx.__originalRestore = ctx.restore; + ctx.__originalRotate = ctx.rotate; + ctx.__originalScale = ctx.scale; + ctx.__originalTranslate = ctx.translate; + ctx.__originalTransform = ctx.transform; + ctx.__originalSetTransform = ctx.setTransform; + ctx.__originalResetTransform = ctx.resetTransform; + ctx.__originalClip = ctx.clip; + ctx.__originalMoveTo = ctx.moveTo; + ctx.__originalLineTo = ctx.lineTo; + ctx.__originalBezierCurveTo = ctx.bezierCurveTo; + ctx.__originalRect = ctx.rect; + ctx.__originalClosePath = ctx.closePath; + ctx.__originalBeginPath = ctx.beginPath; + + ctx._removeMirroring = () => { + ctx.save = ctx.__originalSave; + ctx.restore = ctx.__originalRestore; + ctx.rotate = ctx.__originalRotate; + ctx.scale = ctx.__originalScale; + ctx.translate = ctx.__originalTranslate; + ctx.transform = ctx.__originalTransform; + ctx.setTransform = ctx.__originalSetTransform; + ctx.resetTransform = ctx.__originalResetTransform; + ctx.clip = ctx.__originalClip; + ctx.moveTo = ctx.__originalMoveTo; + ctx.lineTo = ctx.__originalLineTo; + ctx.bezierCurveTo = ctx.__originalBezierCurveTo; + ctx.rect = ctx.__originalRect; + ctx.closePath = ctx.__originalClosePath; + ctx.beginPath = ctx.__originalBeginPath; + delete ctx._removeMirroring; + }; + + ctx.save = function ctxSave() { + destCtx.save(); + + this.__originalSave(); + }; + + ctx.restore = function ctxRestore() { + destCtx.restore(); + + this.__originalRestore(); + }; + + ctx.translate = function ctxTranslate(x, y) { + destCtx.translate(x, y); + + this.__originalTranslate(x, y); + }; + + ctx.scale = function ctxScale(x, y) { + destCtx.scale(x, y); + + this.__originalScale(x, y); + }; + + ctx.transform = function ctxTransform(a, b, c, d, e, f) { + destCtx.transform(a, b, c, d, e, f); + + this.__originalTransform(a, b, c, d, e, f); + }; + + ctx.setTransform = function ctxSetTransform(a, b, c, d, e, f) { + destCtx.setTransform(a, b, c, d, e, f); + + this.__originalSetTransform(a, b, c, d, e, f); + }; + + ctx.resetTransform = function ctxResetTransform() { + destCtx.resetTransform(); + + this.__originalResetTransform(); + }; + + ctx.rotate = function ctxRotate(angle) { + destCtx.rotate(angle); + + this.__originalRotate(angle); + }; + + ctx.clip = function ctxRotate(rule) { + destCtx.clip(rule); + + this.__originalClip(rule); + }; + + ctx.moveTo = function (x, y) { + destCtx.moveTo(x, y); + + this.__originalMoveTo(x, y); + }; + + ctx.lineTo = function (x, y) { + destCtx.lineTo(x, y); + + this.__originalLineTo(x, y); + }; + + ctx.bezierCurveTo = function (cp1x, cp1y, cp2x, cp2y, x, y) { + destCtx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); + + this.__originalBezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); + }; + + ctx.rect = function (x, y, width, height) { + destCtx.rect(x, y, width, height); + + this.__originalRect(x, y, width, height); + }; + + ctx.closePath = function () { + destCtx.closePath(); + + this.__originalClosePath(); + }; + + ctx.beginPath = function () { + destCtx.beginPath(); + + this.__originalBeginPath(); + }; + } + + class CachedCanvases { + constructor(canvasFactory) { + this.canvasFactory = canvasFactory; + this.cache = Object.create(null); + } + + getCanvas(id, width, height) { + let canvasEntry; + + if (this.cache[id] !== undefined) { + canvasEntry = this.cache[id]; + this.canvasFactory.reset(canvasEntry, width, height); + } else { + canvasEntry = this.canvasFactory.create(width, height); + this.cache[id] = canvasEntry; + } + + return canvasEntry; + } + + delete(id) { + delete this.cache[id]; + } + + clear() { + for (const id in this.cache) { + const canvasEntry = this.cache[id]; + this.canvasFactory.destroy(canvasEntry); + delete this.cache[id]; + } + } + + } + + function drawImageAtIntegerCoords(ctx, srcImg, srcX, srcY, srcW, srcH, destX, destY, destW, destH) { + const [a, b, c, d, tx, ty] = (0, _display_utils.getCurrentTransform)(ctx); + + if (b === 0 && c === 0) { + const tlX = destX * a + tx; + const rTlX = Math.round(tlX); + const tlY = destY * d + ty; + const rTlY = Math.round(tlY); + const brX = (destX + destW) * a + tx; + const rWidth = Math.abs(Math.round(brX) - rTlX) || 1; + const brY = (destY + destH) * d + ty; + const rHeight = Math.abs(Math.round(brY) - rTlY) || 1; + ctx.setTransform(Math.sign(a), 0, 0, Math.sign(d), rTlX, rTlY); + ctx.drawImage(srcImg, srcX, srcY, srcW, srcH, 0, 0, rWidth, rHeight); + ctx.setTransform(a, b, c, d, tx, ty); + return [rWidth, rHeight]; + } + + if (a === 0 && d === 0) { + const tlX = destY * c + tx; + const rTlX = Math.round(tlX); + const tlY = destX * b + ty; + const rTlY = Math.round(tlY); + const brX = (destY + destH) * c + tx; + const rWidth = Math.abs(Math.round(brX) - rTlX) || 1; + const brY = (destX + destW) * b + ty; + const rHeight = Math.abs(Math.round(brY) - rTlY) || 1; + ctx.setTransform(0, Math.sign(b), Math.sign(c), 0, rTlX, rTlY); + ctx.drawImage(srcImg, srcX, srcY, srcW, srcH, 0, 0, rHeight, rWidth); + ctx.setTransform(a, b, c, d, tx, ty); + return [rHeight, rWidth]; + } + + ctx.drawImage(srcImg, srcX, srcY, srcW, srcH, destX, destY, destW, destH); + const scaleX = Math.hypot(a, b); + const scaleY = Math.hypot(c, d); + return [scaleX * destW, scaleY * destH]; + } + + function compileType3Glyph(imgData) { + const { + width, + height + } = imgData; + + if (width > MAX_SIZE_TO_COMPILE || height > MAX_SIZE_TO_COMPILE) { + return null; + } + + const POINT_TO_PROCESS_LIMIT = 1000; + const POINT_TYPES = new Uint8Array([0, 2, 4, 0, 1, 0, 5, 4, 8, 10, 0, 8, 0, 2, 1, 0]); + const width1 = width + 1; + let points = new Uint8Array(width1 * (height + 1)); + let i, j, j0; + const lineSize = width + 7 & ~7; + let data = new Uint8Array(lineSize * height), + pos = 0; + + for (const elem of imgData.data) { + let mask = 128; + + while (mask > 0) { + data[pos++] = elem & mask ? 0 : 255; + mask >>= 1; + } + } + + let count = 0; + pos = 0; + + if (data[pos] !== 0) { + points[0] = 1; + ++count; + } + + for (j = 1; j < width; j++) { + if (data[pos] !== data[pos + 1]) { + points[j] = data[pos] ? 2 : 1; + ++count; + } + + pos++; + } + + if (data[pos] !== 0) { + points[j] = 2; + ++count; + } + + for (i = 1; i < height; i++) { + pos = i * lineSize; + j0 = i * width1; + + if (data[pos - lineSize] !== data[pos]) { + points[j0] = data[pos] ? 1 : 8; + ++count; + } + + let sum = (data[pos] ? 4 : 0) + (data[pos - lineSize] ? 8 : 0); + + for (j = 1; j < width; j++) { + sum = (sum >> 2) + (data[pos + 1] ? 4 : 0) + (data[pos - lineSize + 1] ? 8 : 0); + + if (POINT_TYPES[sum]) { + points[j0 + j] = POINT_TYPES[sum]; + ++count; + } + + pos++; + } + + if (data[pos - lineSize] !== data[pos]) { + points[j0 + j] = data[pos] ? 2 : 4; + ++count; + } + + if (count > POINT_TO_PROCESS_LIMIT) { + return null; + } + } + + pos = lineSize * (height - 1); + j0 = i * width1; + + if (data[pos] !== 0) { + points[j0] = 8; + ++count; + } + + for (j = 1; j < width; j++) { + if (data[pos] !== data[pos + 1]) { + points[j0 + j] = data[pos] ? 4 : 8; + ++count; + } + + pos++; + } + + if (data[pos] !== 0) { + points[j0 + j] = 4; + ++count; + } + + if (count > POINT_TO_PROCESS_LIMIT) { + return null; + } + + const steps = new Int32Array([0, width1, -1, 0, -width1, 0, 0, 0, 1]); + const path = new Path2D(); + + for (i = 0; count && i <= height; i++) { + let p = i * width1; + const end = p + width; + + while (p < end && !points[p]) { + p++; + } + + if (p === end) { + continue; + } + + path.moveTo(p % width1, i); + const p0 = p; + let type = points[p]; + + do { + const step = steps[type]; + + do { + p += step; + } while (!points[p]); + + const pp = points[p]; + + if (pp !== 5 && pp !== 10) { + type = pp; + points[p] = 0; + } else { + type = pp & 0x33 * type >> 4; + points[p] &= type >> 2 | type << 2; + } + + path.lineTo(p % width1, p / width1 | 0); + + if (!points[p]) { + --count; + } + } while (p0 !== p); + + --i; + } + + data = null; + points = null; + + const drawOutline = function (c) { + c.save(); + c.scale(1 / width, -1 / height); + c.translate(0, -height); + c.fill(path); + c.beginPath(); + c.restore(); + }; + + return drawOutline; + } + + class CanvasExtraState { + constructor(width, height) { + this.alphaIsShape = false; + this.fontSize = 0; + this.fontSizeScale = 1; + this.textMatrix = _util.IDENTITY_MATRIX; + this.textMatrixScale = 1; + this.fontMatrix = _util.FONT_IDENTITY_MATRIX; + this.leading = 0; + this.x = 0; + this.y = 0; + this.lineX = 0; + this.lineY = 0; + this.charSpacing = 0; + this.wordSpacing = 0; + this.textHScale = 1; + this.textRenderingMode = _util.TextRenderingMode.FILL; + this.textRise = 0; + this.fillColor = "#000000"; + this.strokeColor = "#000000"; + this.patternFill = false; + this.fillAlpha = 1; + this.strokeAlpha = 1; + this.lineWidth = 1; + this.activeSMask = null; + this.transferMaps = null; + this.startNewPathAndClipBox([0, 0, width, height]); + } + + clone() { + const clone = Object.create(this); + clone.clipBox = this.clipBox.slice(); + return clone; + } + + setCurrentPoint(x, y) { + this.x = x; + this.y = y; + } + + updatePathMinMax(transform, x, y) { + [x, y] = _util.Util.applyTransform([x, y], transform); + this.minX = Math.min(this.minX, x); + this.minY = Math.min(this.minY, y); + this.maxX = Math.max(this.maxX, x); + this.maxY = Math.max(this.maxY, y); + } + + updateRectMinMax(transform, rect) { + const p1 = _util.Util.applyTransform(rect, transform); + + const p2 = _util.Util.applyTransform(rect.slice(2), transform); + + this.minX = Math.min(this.minX, p1[0], p2[0]); + this.minY = Math.min(this.minY, p1[1], p2[1]); + this.maxX = Math.max(this.maxX, p1[0], p2[0]); + this.maxY = Math.max(this.maxY, p1[1], p2[1]); + } + + updateScalingPathMinMax(transform, minMax) { + _util.Util.scaleMinMax(transform, minMax); + + this.minX = Math.min(this.minX, minMax[0]); + this.maxX = Math.max(this.maxX, minMax[1]); + this.minY = Math.min(this.minY, minMax[2]); + this.maxY = Math.max(this.maxY, minMax[3]); + } + + updateCurvePathMinMax(transform, x0, y0, x1, y1, x2, y2, x3, y3, minMax) { + const box = _util.Util.bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3); + + if (minMax) { + minMax[0] = Math.min(minMax[0], box[0], box[2]); + minMax[1] = Math.max(minMax[1], box[0], box[2]); + minMax[2] = Math.min(minMax[2], box[1], box[3]); + minMax[3] = Math.max(minMax[3], box[1], box[3]); + return; + } + + this.updateRectMinMax(transform, box); + } + + getPathBoundingBox(pathType = _pattern_helper.PathType.FILL, transform = null) { + const box = [this.minX, this.minY, this.maxX, this.maxY]; + + if (pathType === _pattern_helper.PathType.STROKE) { + if (!transform) { + (0, _util.unreachable)("Stroke bounding box must include transform."); + } + + const scale = _util.Util.singularValueDecompose2dScale(transform); + + const xStrokePad = scale[0] * this.lineWidth / 2; + const yStrokePad = scale[1] * this.lineWidth / 2; + box[0] -= xStrokePad; + box[1] -= yStrokePad; + box[2] += xStrokePad; + box[3] += yStrokePad; + } + + return box; + } + + updateClipFromPath() { + const intersect = _util.Util.intersect(this.clipBox, this.getPathBoundingBox()); + + this.startNewPathAndClipBox(intersect || [0, 0, 0, 0]); + } + + isEmptyClip() { + return this.minX === Infinity; + } + + startNewPathAndClipBox(box) { + this.clipBox = box; + this.minX = Infinity; + this.minY = Infinity; + this.maxX = 0; + this.maxY = 0; + } + + getClippedPathBoundingBox(pathType = _pattern_helper.PathType.FILL, transform = null) { + return _util.Util.intersect(this.clipBox, this.getPathBoundingBox(pathType, transform)); + } + + } + + function putBinaryImageData(ctx, imgData, transferMaps = null) { + if (typeof ImageData !== "undefined" && imgData instanceof ImageData) { + ctx.putImageData(imgData, 0, 0); + return; + } + + const height = imgData.height, + width = imgData.width; + const partialChunkHeight = height % FULL_CHUNK_HEIGHT; + const fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT; + const totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1; + const chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT); + let srcPos = 0, + destPos; + const src = imgData.data; + const dest = chunkImgData.data; + let i, j, thisChunkHeight, elemsInThisChunk; + let transferMapRed, transferMapGreen, transferMapBlue, transferMapGray; + + if (transferMaps) { + switch (transferMaps.length) { + case 1: + transferMapRed = transferMaps[0]; + transferMapGreen = transferMaps[0]; + transferMapBlue = transferMaps[0]; + transferMapGray = transferMaps[0]; + break; + + case 4: + transferMapRed = transferMaps[0]; + transferMapGreen = transferMaps[1]; + transferMapBlue = transferMaps[2]; + transferMapGray = transferMaps[3]; + break; + } + } + + if (imgData.kind === _util.ImageKind.GRAYSCALE_1BPP) { + const srcLength = src.byteLength; + const dest32 = new Uint32Array(dest.buffer, 0, dest.byteLength >> 2); + const dest32DataLength = dest32.length; + const fullSrcDiff = width + 7 >> 3; + let white = 0xffffffff; + let black = _util.FeatureTest.isLittleEndian ? 0xff000000 : 0x000000ff; + + if (transferMapGray) { + if (transferMapGray[0] === 0xff && transferMapGray[0xff] === 0) { + [white, black] = [black, white]; + } + } + + for (i = 0; i < totalChunks; i++) { + thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight; + destPos = 0; + + for (j = 0; j < thisChunkHeight; j++) { + const srcDiff = srcLength - srcPos; + let k = 0; + const kEnd = srcDiff > fullSrcDiff ? width : srcDiff * 8 - 7; + const kEndUnrolled = kEnd & ~7; + let mask = 0; + let srcByte = 0; + + for (; k < kEndUnrolled; k += 8) { + srcByte = src[srcPos++]; + dest32[destPos++] = srcByte & 128 ? white : black; + dest32[destPos++] = srcByte & 64 ? white : black; + dest32[destPos++] = srcByte & 32 ? white : black; + dest32[destPos++] = srcByte & 16 ? white : black; + dest32[destPos++] = srcByte & 8 ? white : black; + dest32[destPos++] = srcByte & 4 ? white : black; + dest32[destPos++] = srcByte & 2 ? white : black; + dest32[destPos++] = srcByte & 1 ? white : black; + } + + for (; k < kEnd; k++) { + if (mask === 0) { + srcByte = src[srcPos++]; + mask = 128; + } + + dest32[destPos++] = srcByte & mask ? white : black; + mask >>= 1; + } + } + + while (destPos < dest32DataLength) { + dest32[destPos++] = 0; + } + + ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT); + } + } else if (imgData.kind === _util.ImageKind.RGBA_32BPP) { + const hasTransferMaps = !!(transferMapRed || transferMapGreen || transferMapBlue); + j = 0; + elemsInThisChunk = width * FULL_CHUNK_HEIGHT * 4; + + for (i = 0; i < fullChunks; i++) { + dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk)); + srcPos += elemsInThisChunk; + + if (hasTransferMaps) { + for (let k = 0; k < elemsInThisChunk; k += 4) { + if (transferMapRed) { + dest[k + 0] = transferMapRed[dest[k + 0]]; + } + + if (transferMapGreen) { + dest[k + 1] = transferMapGreen[dest[k + 1]]; + } + + if (transferMapBlue) { + dest[k + 2] = transferMapBlue[dest[k + 2]]; + } + } + } + + ctx.putImageData(chunkImgData, 0, j); + j += FULL_CHUNK_HEIGHT; + } + + if (i < totalChunks) { + elemsInThisChunk = width * partialChunkHeight * 4; + dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk)); + + if (hasTransferMaps) { + for (let k = 0; k < elemsInThisChunk; k += 4) { + if (transferMapRed) { + dest[k + 0] = transferMapRed[dest[k + 0]]; + } + + if (transferMapGreen) { + dest[k + 1] = transferMapGreen[dest[k + 1]]; + } + + if (transferMapBlue) { + dest[k + 2] = transferMapBlue[dest[k + 2]]; + } + } + } + + ctx.putImageData(chunkImgData, 0, j); + } + } else if (imgData.kind === _util.ImageKind.RGB_24BPP) { + const hasTransferMaps = !!(transferMapRed || transferMapGreen || transferMapBlue); + thisChunkHeight = FULL_CHUNK_HEIGHT; + elemsInThisChunk = width * thisChunkHeight; + + for (i = 0; i < totalChunks; i++) { + if (i >= fullChunks) { + thisChunkHeight = partialChunkHeight; + elemsInThisChunk = width * thisChunkHeight; + } + + destPos = 0; + + for (j = elemsInThisChunk; j--;) { + dest[destPos++] = src[srcPos++]; + dest[destPos++] = src[srcPos++]; + dest[destPos++] = src[srcPos++]; + dest[destPos++] = 255; + } + + if (hasTransferMaps) { + for (let k = 0; k < destPos; k += 4) { + if (transferMapRed) { + dest[k + 0] = transferMapRed[dest[k + 0]]; + } + + if (transferMapGreen) { + dest[k + 1] = transferMapGreen[dest[k + 1]]; + } + + if (transferMapBlue) { + dest[k + 2] = transferMapBlue[dest[k + 2]]; + } + } + } + + ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT); + } + } else { + throw new Error(`bad image kind: ${imgData.kind}`); + } + } + + function putBinaryImageMask(ctx, imgData) { + if (imgData.bitmap) { + ctx.drawImage(imgData.bitmap, 0, 0); + return; + } + + const height = imgData.height, + width = imgData.width; + const partialChunkHeight = height % FULL_CHUNK_HEIGHT; + const fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT; + const totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1; + const chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT); + let srcPos = 0; + const src = imgData.data; + const dest = chunkImgData.data; + + for (let i = 0; i < totalChunks; i++) { + const thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight; + ({ + srcPos + } = (0, _image_utils.applyMaskImageData)({ + src, + srcPos, + dest, + width, + height: thisChunkHeight + })); + ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT); + } + } + + function copyCtxState(sourceCtx, destCtx) { + const properties = ["strokeStyle", "fillStyle", "fillRule", "globalAlpha", "lineWidth", "lineCap", "lineJoin", "miterLimit", "globalCompositeOperation", "font"]; + + for (let i = 0, ii = properties.length; i < ii; i++) { + const property = properties[i]; + + if (sourceCtx[property] !== undefined) { + destCtx[property] = sourceCtx[property]; + } + } + + if (sourceCtx.setLineDash !== undefined) { + destCtx.setLineDash(sourceCtx.getLineDash()); + destCtx.lineDashOffset = sourceCtx.lineDashOffset; + } + } + + function resetCtxToDefault(ctx, foregroundColor) { + ctx.strokeStyle = ctx.fillStyle = foregroundColor || "#000000"; + ctx.fillRule = "nonzero"; + ctx.globalAlpha = 1; + ctx.lineWidth = 1; + ctx.lineCap = "butt"; + ctx.lineJoin = "miter"; + ctx.miterLimit = 10; + ctx.globalCompositeOperation = "source-over"; + ctx.font = "10px sans-serif"; + + if (ctx.setLineDash !== undefined) { + ctx.setLineDash([]); + ctx.lineDashOffset = 0; + } + } + + function composeSMaskBackdrop(bytes, r0, g0, b0) { + const length = bytes.length; + + for (let i = 3; i < length; i += 4) { + const alpha = bytes[i]; + + if (alpha === 0) { + bytes[i - 3] = r0; + bytes[i - 2] = g0; + bytes[i - 1] = b0; + } else if (alpha < 255) { + const alpha_ = 255 - alpha; + bytes[i - 3] = bytes[i - 3] * alpha + r0 * alpha_ >> 8; + bytes[i - 2] = bytes[i - 2] * alpha + g0 * alpha_ >> 8; + bytes[i - 1] = bytes[i - 1] * alpha + b0 * alpha_ >> 8; + } + } + } + + function composeSMaskAlpha(maskData, layerData, transferMap) { + const length = maskData.length; + const scale = 1 / 255; + + for (let i = 3; i < length; i += 4) { + const alpha = transferMap ? transferMap[maskData[i]] : maskData[i]; + layerData[i] = layerData[i] * alpha * scale | 0; + } + } + + function composeSMaskLuminosity(maskData, layerData, transferMap) { + const length = maskData.length; + + for (let i = 3; i < length; i += 4) { + const y = maskData[i - 3] * 77 + maskData[i - 2] * 152 + maskData[i - 1] * 28; + layerData[i] = transferMap ? layerData[i] * transferMap[y >> 8] >> 8 : layerData[i] * y >> 16; + } + } + + function genericComposeSMask(maskCtx, layerCtx, width, height, subtype, backdrop, transferMap, layerOffsetX, layerOffsetY, maskOffsetX, maskOffsetY) { + const hasBackdrop = !!backdrop; + const r0 = hasBackdrop ? backdrop[0] : 0; + const g0 = hasBackdrop ? backdrop[1] : 0; + const b0 = hasBackdrop ? backdrop[2] : 0; + let composeFn; + + if (subtype === "Luminosity") { + composeFn = composeSMaskLuminosity; + } else { + composeFn = composeSMaskAlpha; + } + + const PIXELS_TO_PROCESS = 1048576; + const chunkSize = Math.min(height, Math.ceil(PIXELS_TO_PROCESS / width)); + + for (let row = 0; row < height; row += chunkSize) { + const chunkHeight = Math.min(chunkSize, height - row); + const maskData = maskCtx.getImageData(layerOffsetX - maskOffsetX, row + (layerOffsetY - maskOffsetY), width, chunkHeight); + const layerData = layerCtx.getImageData(layerOffsetX, row + layerOffsetY, width, chunkHeight); + + if (hasBackdrop) { + composeSMaskBackdrop(maskData.data, r0, g0, b0); + } + + composeFn(maskData.data, layerData.data, transferMap); + layerCtx.putImageData(layerData, layerOffsetX, row + layerOffsetY); + } + } + + function composeSMask(ctx, smask, layerCtx, layerBox) { + const layerOffsetX = layerBox[0]; + const layerOffsetY = layerBox[1]; + const layerWidth = layerBox[2] - layerOffsetX; + const layerHeight = layerBox[3] - layerOffsetY; + + if (layerWidth === 0 || layerHeight === 0) { + return; + } + + genericComposeSMask(smask.context, layerCtx, layerWidth, layerHeight, smask.subtype, smask.backdrop, smask.transferMap, layerOffsetX, layerOffsetY, smask.offsetX, smask.offsetY); + ctx.save(); + ctx.globalAlpha = 1; + ctx.globalCompositeOperation = "source-over"; + ctx.setTransform(1, 0, 0, 1, 0, 0); + ctx.drawImage(layerCtx.canvas, 0, 0); + ctx.restore(); + } + + function getImageSmoothingEnabled(transform, interpolate) { + const scale = _util.Util.singularValueDecompose2dScale(transform); + + scale[0] = Math.fround(scale[0]); + scale[1] = Math.fround(scale[1]); + const actualScale = Math.fround((globalThis.devicePixelRatio || 1) * _display_utils.PixelsPerInch.PDF_TO_CSS_UNITS); + + if (interpolate !== undefined) { + return interpolate; + } else if (scale[0] <= actualScale || scale[1] <= actualScale) { + return true; + } + + return false; + } + + const LINE_CAP_STYLES = ["butt", "round", "square"]; + const LINE_JOIN_STYLES = ["miter", "round", "bevel"]; + const NORMAL_CLIP = {}; + const EO_CLIP = {}; + + class CanvasGraphics { + constructor(canvasCtx, commonObjs, objs, canvasFactory, imageLayer, optionalContentConfig, annotationCanvasMap, pageColors) { + this.ctx = canvasCtx; + this.current = new CanvasExtraState(this.ctx.canvas.width, this.ctx.canvas.height); + this.stateStack = []; + this.pendingClip = null; + this.pendingEOFill = false; + this.res = null; + this.xobjs = null; + this.commonObjs = commonObjs; + this.objs = objs; + this.canvasFactory = canvasFactory; + this.imageLayer = imageLayer; + this.groupStack = []; + this.processingType3 = null; + this.baseTransform = null; + this.baseTransformStack = []; + this.groupLevel = 0; + this.smaskStack = []; + this.smaskCounter = 0; + this.tempSMask = null; + this.suspendedCtx = null; + this.contentVisible = true; + this.markedContentStack = []; + this.optionalContentConfig = optionalContentConfig; + this.cachedCanvases = new CachedCanvases(this.canvasFactory); + this.cachedPatterns = new Map(); + this.annotationCanvasMap = annotationCanvasMap; + this.viewportScale = 1; + this.outputScaleX = 1; + this.outputScaleY = 1; + this.backgroundColor = pageColors?.background || null; + this.foregroundColor = pageColors?.foreground || null; + this._cachedScaleForStroking = null; + this._cachedGetSinglePixelWidth = null; + this._cachedBitmapsMap = new Map(); + } + + getObject(data, fallback = null) { + if (typeof data === "string") { + return data.startsWith("g_") ? this.commonObjs.get(data) : this.objs.get(data); + } + + return fallback; + } + + beginDrawing({ + transform, + viewport, + transparency = false, + background = null + }) { + const width = this.ctx.canvas.width; + const height = this.ctx.canvas.height; + const defaultBackgroundColor = background || "#ffffff"; + this.ctx.save(); + + if (this.foregroundColor && this.backgroundColor) { + this.ctx.fillStyle = this.foregroundColor; + const fg = this.foregroundColor = this.ctx.fillStyle; + this.ctx.fillStyle = this.backgroundColor; + const bg = this.backgroundColor = this.ctx.fillStyle; + let isValidDefaultBg = true; + let defaultBg = defaultBackgroundColor; + this.ctx.fillStyle = defaultBackgroundColor; + defaultBg = this.ctx.fillStyle; + isValidDefaultBg = typeof defaultBg === "string" && /^#[0-9A-Fa-f]{6}$/.test(defaultBg); + + if (fg === "#000000" && bg === "#ffffff" || fg === bg || !isValidDefaultBg) { + this.foregroundColor = this.backgroundColor = null; + } else { + const [rB, gB, bB] = (0, _display_utils.getRGB)(defaultBg); + + const newComp = x => { + x /= 255; + return x <= 0.03928 ? x / 12.92 : ((x + 0.055) / 1.055) ** 2.4; + }; + + const lumB = Math.round(0.2126 * newComp(rB) + 0.7152 * newComp(gB) + 0.0722 * newComp(bB)); + + this.selectColor = (r, g, b) => { + const lumC = 0.2126 * newComp(r) + 0.7152 * newComp(g) + 0.0722 * newComp(b); + return Math.round(lumC) === lumB ? bg : fg; + }; + } + } + + this.ctx.fillStyle = this.backgroundColor || defaultBackgroundColor; + this.ctx.fillRect(0, 0, width, height); + this.ctx.restore(); + + if (transparency) { + const transparentCanvas = this.cachedCanvases.getCanvas("transparent", width, height); + this.compositeCtx = this.ctx; + this.transparentCanvas = transparentCanvas.canvas; + this.ctx = transparentCanvas.context; + this.ctx.save(); + this.ctx.transform(...(0, _display_utils.getCurrentTransform)(this.compositeCtx)); + } + + this.ctx.save(); + resetCtxToDefault(this.ctx, this.foregroundColor); + + if (transform) { + this.ctx.transform(...transform); + this.outputScaleX = transform[0]; + this.outputScaleY = transform[0]; + } + + this.ctx.transform(...viewport.transform); + this.viewportScale = viewport.scale; + this.baseTransform = (0, _display_utils.getCurrentTransform)(this.ctx); + + if (this.imageLayer) { + (0, _display_utils.deprecated)("The `imageLayer` functionality will be removed in the future."); + this.imageLayer.beginLayout(); + } + } + + executeOperatorList(operatorList, executionStartIdx, continueCallback, stepper) { + const argsArray = operatorList.argsArray; + const fnArray = operatorList.fnArray; + let i = executionStartIdx || 0; + const argsArrayLen = argsArray.length; + + if (argsArrayLen === i) { + return i; + } + + const chunkOperations = argsArrayLen - i > EXECUTION_STEPS && typeof continueCallback === "function"; + const endTime = chunkOperations ? Date.now() + EXECUTION_TIME : 0; + let steps = 0; + const commonObjs = this.commonObjs; + const objs = this.objs; + let fnId; + + while (true) { + if (stepper !== undefined && i === stepper.nextBreakPoint) { + stepper.breakIt(i, continueCallback); + return i; + } + + fnId = fnArray[i]; + + if (fnId !== _util.OPS.dependency) { + this[fnId].apply(this, argsArray[i]); + } else { + for (const depObjId of argsArray[i]) { + const objsPool = depObjId.startsWith("g_") ? commonObjs : objs; + + if (!objsPool.has(depObjId)) { + objsPool.get(depObjId, continueCallback); + return i; + } + } + } + + i++; + + if (i === argsArrayLen) { + return i; + } + + if (chunkOperations && ++steps > EXECUTION_STEPS) { + if (Date.now() > endTime) { + continueCallback(); + return i; + } + + steps = 0; + } + } + } + + #restoreInitialState() { + while (this.stateStack.length || this.inSMaskMode) { + this.restore(); + } + + this.ctx.restore(); + + if (this.transparentCanvas) { + this.ctx = this.compositeCtx; + this.ctx.save(); + this.ctx.setTransform(1, 0, 0, 1, 0, 0); + this.ctx.drawImage(this.transparentCanvas, 0, 0); + this.ctx.restore(); + this.transparentCanvas = null; + } + } + + endDrawing() { + this.#restoreInitialState(); + this.cachedCanvases.clear(); + this.cachedPatterns.clear(); + + for (const cache of this._cachedBitmapsMap.values()) { + for (const canvas of cache.values()) { + if (typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement) { + canvas.width = canvas.height = 0; + } + } + + cache.clear(); + } + + this._cachedBitmapsMap.clear(); + + if (this.imageLayer) { + this.imageLayer.endLayout(); + } + } + + _scaleImage(img, inverseTransform) { + const width = img.width; + const height = img.height; + let widthScale = Math.max(Math.hypot(inverseTransform[0], inverseTransform[1]), 1); + let heightScale = Math.max(Math.hypot(inverseTransform[2], inverseTransform[3]), 1); + let paintWidth = width, + paintHeight = height; + let tmpCanvasId = "prescale1"; + let tmpCanvas, tmpCtx; + + while (widthScale > 2 && paintWidth > 1 || heightScale > 2 && paintHeight > 1) { + let newWidth = paintWidth, + newHeight = paintHeight; + + if (widthScale > 2 && paintWidth > 1) { + newWidth = Math.ceil(paintWidth / 2); + widthScale /= paintWidth / newWidth; + } + + if (heightScale > 2 && paintHeight > 1) { + newHeight = Math.ceil(paintHeight / 2); + heightScale /= paintHeight / newHeight; + } + + tmpCanvas = this.cachedCanvases.getCanvas(tmpCanvasId, newWidth, newHeight); + tmpCtx = tmpCanvas.context; + tmpCtx.clearRect(0, 0, newWidth, newHeight); + tmpCtx.drawImage(img, 0, 0, paintWidth, paintHeight, 0, 0, newWidth, newHeight); + img = tmpCanvas.canvas; + paintWidth = newWidth; + paintHeight = newHeight; + tmpCanvasId = tmpCanvasId === "prescale1" ? "prescale2" : "prescale1"; + } + + return { + img, + paintWidth, + paintHeight + }; + } + + _createMaskCanvas(img) { + const ctx = this.ctx; + const { + width, + height + } = img; + const fillColor = this.current.fillColor; + const isPatternFill = this.current.patternFill; + const currentTransform = (0, _display_utils.getCurrentTransform)(ctx); + let cache, cacheKey, scaled, maskCanvas; + + if ((img.bitmap || img.data) && img.count > 1) { + const mainKey = img.bitmap || img.data.buffer; + const withoutTranslation = currentTransform.slice(0, 4); + cacheKey = JSON.stringify(isPatternFill ? withoutTranslation : [withoutTranslation, fillColor]); + cache = this._cachedBitmapsMap.get(mainKey); + + if (!cache) { + cache = new Map(); + + this._cachedBitmapsMap.set(mainKey, cache); + } + + const cachedImage = cache.get(cacheKey); + + if (cachedImage && !isPatternFill) { + const offsetX = Math.round(Math.min(currentTransform[0], currentTransform[2]) + currentTransform[4]); + const offsetY = Math.round(Math.min(currentTransform[1], currentTransform[3]) + currentTransform[5]); + return { + canvas: cachedImage, + offsetX, + offsetY + }; + } + + scaled = cachedImage; + } + + if (!scaled) { + maskCanvas = this.cachedCanvases.getCanvas("maskCanvas", width, height); + putBinaryImageMask(maskCanvas.context, img); + } + + let maskToCanvas = _util.Util.transform(currentTransform, [1 / width, 0, 0, -1 / height, 0, 0]); + + maskToCanvas = _util.Util.transform(maskToCanvas, [1, 0, 0, 1, 0, -height]); + + const cord1 = _util.Util.applyTransform([0, 0], maskToCanvas); + + const cord2 = _util.Util.applyTransform([width, height], maskToCanvas); + + const rect = _util.Util.normalizeRect([cord1[0], cord1[1], cord2[0], cord2[1]]); + + const drawnWidth = Math.round(rect[2] - rect[0]) || 1; + const drawnHeight = Math.round(rect[3] - rect[1]) || 1; + const fillCanvas = this.cachedCanvases.getCanvas("fillCanvas", drawnWidth, drawnHeight); + const fillCtx = fillCanvas.context; + const offsetX = Math.min(cord1[0], cord2[0]); + const offsetY = Math.min(cord1[1], cord2[1]); + fillCtx.translate(-offsetX, -offsetY); + fillCtx.transform(...maskToCanvas); + + if (!scaled) { + scaled = this._scaleImage(maskCanvas.canvas, (0, _display_utils.getCurrentTransformInverse)(fillCtx)); + scaled = scaled.img; + + if (cache && isPatternFill) { + cache.set(cacheKey, scaled); + } + } + + fillCtx.imageSmoothingEnabled = getImageSmoothingEnabled((0, _display_utils.getCurrentTransform)(fillCtx), img.interpolate); + drawImageAtIntegerCoords(fillCtx, scaled, 0, 0, scaled.width, scaled.height, 0, 0, width, height); + fillCtx.globalCompositeOperation = "source-in"; + + const inverse = _util.Util.transform((0, _display_utils.getCurrentTransformInverse)(fillCtx), [1, 0, 0, 1, -offsetX, -offsetY]); + + fillCtx.fillStyle = isPatternFill ? fillColor.getPattern(ctx, this, inverse, _pattern_helper.PathType.FILL) : fillColor; + fillCtx.fillRect(0, 0, width, height); + + if (cache && !isPatternFill) { + this.cachedCanvases.delete("fillCanvas"); + cache.set(cacheKey, fillCanvas.canvas); + } + + return { + canvas: fillCanvas.canvas, + offsetX: Math.round(offsetX), + offsetY: Math.round(offsetY) + }; + } + + setLineWidth(width) { + if (width !== this.current.lineWidth) { + this._cachedScaleForStroking = null; + } + + this.current.lineWidth = width; + this.ctx.lineWidth = width; + } + + setLineCap(style) { + this.ctx.lineCap = LINE_CAP_STYLES[style]; + } + + setLineJoin(style) { + this.ctx.lineJoin = LINE_JOIN_STYLES[style]; + } + + setMiterLimit(limit) { + this.ctx.miterLimit = limit; + } + + setDash(dashArray, dashPhase) { + const ctx = this.ctx; + + if (ctx.setLineDash !== undefined) { + ctx.setLineDash(dashArray); + ctx.lineDashOffset = dashPhase; + } + } + + setRenderingIntent(intent) {} + + setFlatness(flatness) {} + + setGState(states) { + for (let i = 0, ii = states.length; i < ii; i++) { + const state = states[i]; + const key = state[0]; + const value = state[1]; + + switch (key) { + case "LW": + this.setLineWidth(value); + break; + + case "LC": + this.setLineCap(value); + break; + + case "LJ": + this.setLineJoin(value); + break; + + case "ML": + this.setMiterLimit(value); + break; + + case "D": + this.setDash(value[0], value[1]); + break; + + case "RI": + this.setRenderingIntent(value); + break; + + case "FL": + this.setFlatness(value); + break; + + case "Font": + this.setFont(value[0], value[1]); + break; + + case "CA": + this.current.strokeAlpha = state[1]; + break; + + case "ca": + this.current.fillAlpha = state[1]; + this.ctx.globalAlpha = state[1]; + break; + + case "BM": + this.ctx.globalCompositeOperation = value; + break; + + case "SMask": + this.current.activeSMask = value ? this.tempSMask : null; + this.tempSMask = null; + this.checkSMaskState(); + break; + + case "TR": + this.current.transferMaps = value; + } + } + } + + get inSMaskMode() { + return !!this.suspendedCtx; + } + + checkSMaskState() { + const inSMaskMode = this.inSMaskMode; + + if (this.current.activeSMask && !inSMaskMode) { + this.beginSMaskMode(); + } else if (!this.current.activeSMask && inSMaskMode) { + this.endSMaskMode(); + } + } + + beginSMaskMode() { + if (this.inSMaskMode) { + throw new Error("beginSMaskMode called while already in smask mode"); + } + + const drawnWidth = this.ctx.canvas.width; + const drawnHeight = this.ctx.canvas.height; + const cacheId = "smaskGroupAt" + this.groupLevel; + const scratchCanvas = this.cachedCanvases.getCanvas(cacheId, drawnWidth, drawnHeight); + this.suspendedCtx = this.ctx; + this.ctx = scratchCanvas.context; + const ctx = this.ctx; + ctx.setTransform(...(0, _display_utils.getCurrentTransform)(this.suspendedCtx)); + copyCtxState(this.suspendedCtx, ctx); + mirrorContextOperations(ctx, this.suspendedCtx); + this.setGState([["BM", "source-over"], ["ca", 1], ["CA", 1]]); + } + + endSMaskMode() { + if (!this.inSMaskMode) { + throw new Error("endSMaskMode called while not in smask mode"); + } + + this.ctx._removeMirroring(); + + copyCtxState(this.ctx, this.suspendedCtx); + this.ctx = this.suspendedCtx; + this.suspendedCtx = null; + } + + compose(dirtyBox) { + if (!this.current.activeSMask) { + return; + } + + if (!dirtyBox) { + dirtyBox = [0, 0, this.ctx.canvas.width, this.ctx.canvas.height]; + } else { + dirtyBox[0] = Math.floor(dirtyBox[0]); + dirtyBox[1] = Math.floor(dirtyBox[1]); + dirtyBox[2] = Math.ceil(dirtyBox[2]); + dirtyBox[3] = Math.ceil(dirtyBox[3]); + } + + const smask = this.current.activeSMask; + const suspendedCtx = this.suspendedCtx; + composeSMask(suspendedCtx, smask, this.ctx, dirtyBox); + this.ctx.save(); + this.ctx.setTransform(1, 0, 0, 1, 0, 0); + this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height); + this.ctx.restore(); + } + + save() { + if (this.inSMaskMode) { + copyCtxState(this.ctx, this.suspendedCtx); + this.suspendedCtx.save(); + } else { + this.ctx.save(); + } + + const old = this.current; + this.stateStack.push(old); + this.current = old.clone(); + } + + restore() { + if (this.stateStack.length === 0 && this.inSMaskMode) { + this.endSMaskMode(); + } + + if (this.stateStack.length !== 0) { + this.current = this.stateStack.pop(); + + if (this.inSMaskMode) { + this.suspendedCtx.restore(); + copyCtxState(this.suspendedCtx, this.ctx); + } else { + this.ctx.restore(); + } + + this.checkSMaskState(); + this.pendingClip = null; + this._cachedScaleForStroking = null; + this._cachedGetSinglePixelWidth = null; + } + } + + transform(a, b, c, d, e, f) { + this.ctx.transform(a, b, c, d, e, f); + this._cachedScaleForStroking = null; + this._cachedGetSinglePixelWidth = null; + } + + constructPath(ops, args, minMax) { + const ctx = this.ctx; + const current = this.current; + let x = current.x, + y = current.y; + let startX, startY; + const currentTransform = (0, _display_utils.getCurrentTransform)(ctx); + const isScalingMatrix = currentTransform[0] === 0 && currentTransform[3] === 0 || currentTransform[1] === 0 && currentTransform[2] === 0; + const minMaxForBezier = isScalingMatrix ? minMax.slice(0) : null; + + for (let i = 0, j = 0, ii = ops.length; i < ii; i++) { + switch (ops[i] | 0) { + case _util.OPS.rectangle: + x = args[j++]; + y = args[j++]; + const width = args[j++]; + const height = args[j++]; + const xw = x + width; + const yh = y + height; + ctx.moveTo(x, y); + + if (width === 0 || height === 0) { + ctx.lineTo(xw, yh); + } else { + ctx.lineTo(xw, y); + ctx.lineTo(xw, yh); + ctx.lineTo(x, yh); + } + + if (!isScalingMatrix) { + current.updateRectMinMax(currentTransform, [x, y, xw, yh]); + } + + ctx.closePath(); + break; + + case _util.OPS.moveTo: + x = args[j++]; + y = args[j++]; + ctx.moveTo(x, y); + + if (!isScalingMatrix) { + current.updatePathMinMax(currentTransform, x, y); + } + + break; + + case _util.OPS.lineTo: + x = args[j++]; + y = args[j++]; + ctx.lineTo(x, y); + + if (!isScalingMatrix) { + current.updatePathMinMax(currentTransform, x, y); + } + + break; + + case _util.OPS.curveTo: + startX = x; + startY = y; + x = args[j + 4]; + y = args[j + 5]; + ctx.bezierCurveTo(args[j], args[j + 1], args[j + 2], args[j + 3], x, y); + current.updateCurvePathMinMax(currentTransform, startX, startY, args[j], args[j + 1], args[j + 2], args[j + 3], x, y, minMaxForBezier); + j += 6; + break; + + case _util.OPS.curveTo2: + startX = x; + startY = y; + ctx.bezierCurveTo(x, y, args[j], args[j + 1], args[j + 2], args[j + 3]); + current.updateCurvePathMinMax(currentTransform, startX, startY, x, y, args[j], args[j + 1], args[j + 2], args[j + 3], minMaxForBezier); + x = args[j + 2]; + y = args[j + 3]; + j += 4; + break; + + case _util.OPS.curveTo3: + startX = x; + startY = y; + x = args[j + 2]; + y = args[j + 3]; + ctx.bezierCurveTo(args[j], args[j + 1], x, y, x, y); + current.updateCurvePathMinMax(currentTransform, startX, startY, args[j], args[j + 1], x, y, x, y, minMaxForBezier); + j += 4; + break; + + case _util.OPS.closePath: + ctx.closePath(); + break; + } + } + + if (isScalingMatrix) { + current.updateScalingPathMinMax(currentTransform, minMaxForBezier); + } + + current.setCurrentPoint(x, y); + } + + closePath() { + this.ctx.closePath(); + } + + stroke(consumePath) { + consumePath = typeof consumePath !== "undefined" ? consumePath : true; + const ctx = this.ctx; + const strokeColor = this.current.strokeColor; + ctx.globalAlpha = this.current.strokeAlpha; + + if (this.contentVisible) { + if (typeof strokeColor === "object" && strokeColor?.getPattern) { + ctx.save(); + ctx.strokeStyle = strokeColor.getPattern(ctx, this, (0, _display_utils.getCurrentTransformInverse)(ctx), _pattern_helper.PathType.STROKE); + this.rescaleAndStroke(false); + ctx.restore(); + } else { + this.rescaleAndStroke(true); + } + } + + if (consumePath) { + this.consumePath(this.current.getClippedPathBoundingBox()); + } + + ctx.globalAlpha = this.current.fillAlpha; + } + + closeStroke() { + this.closePath(); + this.stroke(); + } + + fill(consumePath) { + consumePath = typeof consumePath !== "undefined" ? consumePath : true; + const ctx = this.ctx; + const fillColor = this.current.fillColor; + const isPatternFill = this.current.patternFill; + let needRestore = false; + + if (isPatternFill) { + ctx.save(); + ctx.fillStyle = fillColor.getPattern(ctx, this, (0, _display_utils.getCurrentTransformInverse)(ctx), _pattern_helper.PathType.FILL); + needRestore = true; + } + + const intersect = this.current.getClippedPathBoundingBox(); + + if (this.contentVisible && intersect !== null) { + if (this.pendingEOFill) { + ctx.fill("evenodd"); + this.pendingEOFill = false; + } else { + ctx.fill(); + } + } + + if (needRestore) { + ctx.restore(); + } + + if (consumePath) { + this.consumePath(intersect); + } + } + + eoFill() { + this.pendingEOFill = true; + this.fill(); + } + + fillStroke() { + this.fill(false); + this.stroke(false); + this.consumePath(); + } + + eoFillStroke() { + this.pendingEOFill = true; + this.fillStroke(); + } + + closeFillStroke() { + this.closePath(); + this.fillStroke(); + } + + closeEOFillStroke() { + this.pendingEOFill = true; + this.closePath(); + this.fillStroke(); + } + + endPath() { + this.consumePath(); + } + + clip() { + this.pendingClip = NORMAL_CLIP; + } + + eoClip() { + this.pendingClip = EO_CLIP; + } + + beginText() { + this.current.textMatrix = _util.IDENTITY_MATRIX; + this.current.textMatrixScale = 1; + this.current.x = this.current.lineX = 0; + this.current.y = this.current.lineY = 0; + } + + endText() { + const paths = this.pendingTextPaths; + const ctx = this.ctx; + + if (paths === undefined) { + ctx.beginPath(); + return; + } + + ctx.save(); + ctx.beginPath(); + + for (const path of paths) { + ctx.setTransform(...path.transform); + ctx.translate(path.x, path.y); + path.addToPath(ctx, path.fontSize); + } + + ctx.restore(); + ctx.clip(); + ctx.beginPath(); + delete this.pendingTextPaths; + } + + setCharSpacing(spacing) { + this.current.charSpacing = spacing; + } + + setWordSpacing(spacing) { + this.current.wordSpacing = spacing; + } + + setHScale(scale) { + this.current.textHScale = scale / 100; + } + + setLeading(leading) { + this.current.leading = -leading; + } + + setFont(fontRefName, size) { + const fontObj = this.commonObjs.get(fontRefName); + const current = this.current; + + if (!fontObj) { + throw new Error(`Can't find font for ${fontRefName}`); + } + + current.fontMatrix = fontObj.fontMatrix || _util.FONT_IDENTITY_MATRIX; + + if (current.fontMatrix[0] === 0 || current.fontMatrix[3] === 0) { + (0, _util.warn)("Invalid font matrix for font " + fontRefName); + } + + if (size < 0) { + size = -size; + current.fontDirection = -1; + } else { + current.fontDirection = 1; + } + + this.current.font = fontObj; + this.current.fontSize = size; + + if (fontObj.isType3Font) { + return; + } + + const name = fontObj.loadedName || "sans-serif"; + let bold = "normal"; + + if (fontObj.black) { + bold = "900"; + } else if (fontObj.bold) { + bold = "bold"; + } + + const italic = fontObj.italic ? "italic" : "normal"; + const typeface = `"${name}", ${fontObj.fallbackName}`; + let browserFontSize = size; + + if (size < MIN_FONT_SIZE) { + browserFontSize = MIN_FONT_SIZE; + } else if (size > MAX_FONT_SIZE) { + browserFontSize = MAX_FONT_SIZE; + } + + this.current.fontSizeScale = size / browserFontSize; + this.ctx.font = `${italic} ${bold} ${browserFontSize}px ${typeface}`; + } + + setTextRenderingMode(mode) { + this.current.textRenderingMode = mode; + } + + setTextRise(rise) { + this.current.textRise = rise; + } + + moveText(x, y) { + this.current.x = this.current.lineX += x; + this.current.y = this.current.lineY += y; + } + + setLeadingMoveText(x, y) { + this.setLeading(-y); + this.moveText(x, y); + } + + setTextMatrix(a, b, c, d, e, f) { + this.current.textMatrix = [a, b, c, d, e, f]; + this.current.textMatrixScale = Math.hypot(a, b); + this.current.x = this.current.lineX = 0; + this.current.y = this.current.lineY = 0; + } + + nextLine() { + this.moveText(0, this.current.leading); + } + + paintChar(character, x, y, patternTransform) { + const ctx = this.ctx; + const current = this.current; + const font = current.font; + const textRenderingMode = current.textRenderingMode; + const fontSize = current.fontSize / current.fontSizeScale; + const fillStrokeMode = textRenderingMode & _util.TextRenderingMode.FILL_STROKE_MASK; + const isAddToPathSet = !!(textRenderingMode & _util.TextRenderingMode.ADD_TO_PATH_FLAG); + const patternFill = current.patternFill && !font.missingFile; + let addToPath; + + if (font.disableFontFace || isAddToPathSet || patternFill) { + addToPath = font.getPathGenerator(this.commonObjs, character); + } + + if (font.disableFontFace || patternFill) { + ctx.save(); + ctx.translate(x, y); + ctx.beginPath(); + addToPath(ctx, fontSize); + + if (patternTransform) { + ctx.setTransform(...patternTransform); + } + + if (fillStrokeMode === _util.TextRenderingMode.FILL || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) { + ctx.fill(); + } + + if (fillStrokeMode === _util.TextRenderingMode.STROKE || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) { + ctx.stroke(); + } + + ctx.restore(); + } else { + if (fillStrokeMode === _util.TextRenderingMode.FILL || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) { + ctx.fillText(character, x, y); + } + + if (fillStrokeMode === _util.TextRenderingMode.STROKE || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) { + ctx.strokeText(character, x, y); + } + } + + if (isAddToPathSet) { + const paths = this.pendingTextPaths || (this.pendingTextPaths = []); + paths.push({ + transform: (0, _display_utils.getCurrentTransform)(ctx), + x, + y, + fontSize, + addToPath + }); + } + } + + get isFontSubpixelAAEnabled() { + const { + context: ctx + } = this.cachedCanvases.getCanvas("isFontSubpixelAAEnabled", 10, 10); + ctx.scale(1.5, 1); + ctx.fillText("I", 0, 10); + const data = ctx.getImageData(0, 0, 10, 10).data; + let enabled = false; + + for (let i = 3; i < data.length; i += 4) { + if (data[i] > 0 && data[i] < 255) { + enabled = true; + break; + } + } + + return (0, _util.shadow)(this, "isFontSubpixelAAEnabled", enabled); + } + + showText(glyphs) { + const current = this.current; + const font = current.font; + + if (font.isType3Font) { + return this.showType3Text(glyphs); + } + + const fontSize = current.fontSize; + + if (fontSize === 0) { + return undefined; + } + + const ctx = this.ctx; + const fontSizeScale = current.fontSizeScale; + const charSpacing = current.charSpacing; + const wordSpacing = current.wordSpacing; + const fontDirection = current.fontDirection; + const textHScale = current.textHScale * fontDirection; + const glyphsLength = glyphs.length; + const vertical = font.vertical; + const spacingDir = vertical ? 1 : -1; + const defaultVMetrics = font.defaultVMetrics; + const widthAdvanceScale = fontSize * current.fontMatrix[0]; + const simpleFillText = current.textRenderingMode === _util.TextRenderingMode.FILL && !font.disableFontFace && !current.patternFill; + ctx.save(); + ctx.transform(...current.textMatrix); + ctx.translate(current.x, current.y + current.textRise); + + if (fontDirection > 0) { + ctx.scale(textHScale, -1); + } else { + ctx.scale(textHScale, 1); + } + + let patternTransform; + + if (current.patternFill) { + ctx.save(); + const pattern = current.fillColor.getPattern(ctx, this, (0, _display_utils.getCurrentTransformInverse)(ctx), _pattern_helper.PathType.FILL); + patternTransform = (0, _display_utils.getCurrentTransform)(ctx); + ctx.restore(); + ctx.fillStyle = pattern; + } + + let lineWidth = current.lineWidth; + const scale = current.textMatrixScale; + + if (scale === 0 || lineWidth === 0) { + const fillStrokeMode = current.textRenderingMode & _util.TextRenderingMode.FILL_STROKE_MASK; + + if (fillStrokeMode === _util.TextRenderingMode.STROKE || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) { + lineWidth = this.getSinglePixelWidth(); + } + } else { + lineWidth /= scale; + } + + if (fontSizeScale !== 1.0) { + ctx.scale(fontSizeScale, fontSizeScale); + lineWidth /= fontSizeScale; + } + + ctx.lineWidth = lineWidth; + let x = 0, + i; + + for (i = 0; i < glyphsLength; ++i) { + const glyph = glyphs[i]; + + if (typeof glyph === "number") { + x += spacingDir * glyph * fontSize / 1000; + continue; + } + + let restoreNeeded = false; + const spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing; + const character = glyph.fontChar; + const accent = glyph.accent; + let scaledX, scaledY; + let width = glyph.width; + + if (vertical) { + const vmetric = glyph.vmetric || defaultVMetrics; + const vx = -(glyph.vmetric ? vmetric[1] : width * 0.5) * widthAdvanceScale; + const vy = vmetric[2] * widthAdvanceScale; + width = vmetric ? -vmetric[0] : width; + scaledX = vx / fontSizeScale; + scaledY = (x + vy) / fontSizeScale; + } else { + scaledX = x / fontSizeScale; + scaledY = 0; + } + + if (font.remeasure && width > 0) { + const measuredWidth = ctx.measureText(character).width * 1000 / fontSize * fontSizeScale; + + if (width < measuredWidth && this.isFontSubpixelAAEnabled) { + const characterScaleX = width / measuredWidth; + restoreNeeded = true; + ctx.save(); + ctx.scale(characterScaleX, 1); + scaledX /= characterScaleX; + } else if (width !== measuredWidth) { + scaledX += (width - measuredWidth) / 2000 * fontSize / fontSizeScale; + } + } + + if (this.contentVisible && (glyph.isInFont || font.missingFile)) { + if (simpleFillText && !accent) { + ctx.fillText(character, scaledX, scaledY); + } else { + this.paintChar(character, scaledX, scaledY, patternTransform); + + if (accent) { + const scaledAccentX = scaledX + fontSize * accent.offset.x / fontSizeScale; + const scaledAccentY = scaledY - fontSize * accent.offset.y / fontSizeScale; + this.paintChar(accent.fontChar, scaledAccentX, scaledAccentY, patternTransform); + } + } + } + + let charWidth; + + if (vertical) { + charWidth = width * widthAdvanceScale - spacing * fontDirection; + } else { + charWidth = width * widthAdvanceScale + spacing * fontDirection; + } + + x += charWidth; + + if (restoreNeeded) { + ctx.restore(); + } + } + + if (vertical) { + current.y -= x; + } else { + current.x += x * textHScale; + } + + ctx.restore(); + this.compose(); + return undefined; + } + + showType3Text(glyphs) { + const ctx = this.ctx; + const current = this.current; + const font = current.font; + const fontSize = current.fontSize; + const fontDirection = current.fontDirection; + const spacingDir = font.vertical ? 1 : -1; + const charSpacing = current.charSpacing; + const wordSpacing = current.wordSpacing; + const textHScale = current.textHScale * fontDirection; + const fontMatrix = current.fontMatrix || _util.FONT_IDENTITY_MATRIX; + const glyphsLength = glyphs.length; + const isTextInvisible = current.textRenderingMode === _util.TextRenderingMode.INVISIBLE; + let i, glyph, width, spacingLength; + + if (isTextInvisible || fontSize === 0) { + return; + } + + this._cachedScaleForStroking = null; + this._cachedGetSinglePixelWidth = null; + ctx.save(); + ctx.transform(...current.textMatrix); + ctx.translate(current.x, current.y); + ctx.scale(textHScale, fontDirection); + + for (i = 0; i < glyphsLength; ++i) { + glyph = glyphs[i]; + + if (typeof glyph === "number") { + spacingLength = spacingDir * glyph * fontSize / 1000; + this.ctx.translate(spacingLength, 0); + current.x += spacingLength * textHScale; + continue; + } + + const spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing; + const operatorList = font.charProcOperatorList[glyph.operatorListId]; + + if (!operatorList) { + (0, _util.warn)(`Type3 character "${glyph.operatorListId}" is not available.`); + continue; + } + + if (this.contentVisible) { + this.processingType3 = glyph; + this.save(); + ctx.scale(fontSize, fontSize); + ctx.transform(...fontMatrix); + this.executeOperatorList(operatorList); + this.restore(); + } + + const transformed = _util.Util.applyTransform([glyph.width, 0], fontMatrix); + + width = transformed[0] * fontSize + spacing; + ctx.translate(width, 0); + current.x += width * textHScale; + } + + ctx.restore(); + this.processingType3 = null; + } + + setCharWidth(xWidth, yWidth) {} + + setCharWidthAndBounds(xWidth, yWidth, llx, lly, urx, ury) { + this.ctx.rect(llx, lly, urx - llx, ury - lly); + this.ctx.clip(); + this.endPath(); + } + + getColorN_Pattern(IR) { + let pattern; + + if (IR[0] === "TilingPattern") { + const color = IR[1]; + const baseTransform = this.baseTransform || (0, _display_utils.getCurrentTransform)(this.ctx); + const canvasGraphicsFactory = { + createCanvasGraphics: ctx => { + return new CanvasGraphics(ctx, this.commonObjs, this.objs, this.canvasFactory); + } + }; + pattern = new _pattern_helper.TilingPattern(IR, color, this.ctx, canvasGraphicsFactory, baseTransform); + } else { + pattern = this._getPattern(IR[1], IR[2]); + } + + return pattern; + } + + setStrokeColorN() { + this.current.strokeColor = this.getColorN_Pattern(arguments); + } + + setFillColorN() { + this.current.fillColor = this.getColorN_Pattern(arguments); + this.current.patternFill = true; + } + + setStrokeRGBColor(r, g, b) { + const color = this.selectColor?.(r, g, b) || _util.Util.makeHexColor(r, g, b); + + this.ctx.strokeStyle = color; + this.current.strokeColor = color; + } + + setFillRGBColor(r, g, b) { + const color = this.selectColor?.(r, g, b) || _util.Util.makeHexColor(r, g, b); + + this.ctx.fillStyle = color; + this.current.fillColor = color; + this.current.patternFill = false; + } + + _getPattern(objId, matrix = null) { + let pattern; + + if (this.cachedPatterns.has(objId)) { + pattern = this.cachedPatterns.get(objId); + } else { + pattern = (0, _pattern_helper.getShadingPattern)(this.objs.get(objId)); + this.cachedPatterns.set(objId, pattern); + } + + if (matrix) { + pattern.matrix = matrix; + } + + return pattern; + } + + shadingFill(objId) { + if (!this.contentVisible) { + return; + } + + const ctx = this.ctx; + this.save(); + + const pattern = this._getPattern(objId); + + ctx.fillStyle = pattern.getPattern(ctx, this, (0, _display_utils.getCurrentTransformInverse)(ctx), _pattern_helper.PathType.SHADING); + const inv = (0, _display_utils.getCurrentTransformInverse)(ctx); + + if (inv) { + const canvas = ctx.canvas; + const width = canvas.width; + const height = canvas.height; + + const bl = _util.Util.applyTransform([0, 0], inv); + + const br = _util.Util.applyTransform([0, height], inv); + + const ul = _util.Util.applyTransform([width, 0], inv); + + const ur = _util.Util.applyTransform([width, height], inv); + + const x0 = Math.min(bl[0], br[0], ul[0], ur[0]); + const y0 = Math.min(bl[1], br[1], ul[1], ur[1]); + const x1 = Math.max(bl[0], br[0], ul[0], ur[0]); + const y1 = Math.max(bl[1], br[1], ul[1], ur[1]); + this.ctx.fillRect(x0, y0, x1 - x0, y1 - y0); + } else { + this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10); + } + + this.compose(this.current.getClippedPathBoundingBox()); + this.restore(); + } + + beginInlineImage() { + (0, _util.unreachable)("Should not call beginInlineImage"); + } + + beginImageData() { + (0, _util.unreachable)("Should not call beginImageData"); + } + + paintFormXObjectBegin(matrix, bbox) { + if (!this.contentVisible) { + return; + } + + this.save(); + this.baseTransformStack.push(this.baseTransform); + + if (Array.isArray(matrix) && matrix.length === 6) { + this.transform(...matrix); + } + + this.baseTransform = (0, _display_utils.getCurrentTransform)(this.ctx); + + if (bbox) { + const width = bbox[2] - bbox[0]; + const height = bbox[3] - bbox[1]; + this.ctx.rect(bbox[0], bbox[1], width, height); + this.current.updateRectMinMax((0, _display_utils.getCurrentTransform)(this.ctx), bbox); + this.clip(); + this.endPath(); + } + } + + paintFormXObjectEnd() { + if (!this.contentVisible) { + return; + } + + this.restore(); + this.baseTransform = this.baseTransformStack.pop(); + } + + beginGroup(group) { + if (!this.contentVisible) { + return; + } + + this.save(); + + if (this.inSMaskMode) { + this.endSMaskMode(); + this.current.activeSMask = null; + } + + const currentCtx = this.ctx; + + if (!group.isolated) { + (0, _util.info)("TODO: Support non-isolated groups."); + } + + if (group.knockout) { + (0, _util.warn)("Knockout groups not supported."); + } + + const currentTransform = (0, _display_utils.getCurrentTransform)(currentCtx); + + if (group.matrix) { + currentCtx.transform(...group.matrix); + } + + if (!group.bbox) { + throw new Error("Bounding box is required."); + } + + let bounds = _util.Util.getAxialAlignedBoundingBox(group.bbox, (0, _display_utils.getCurrentTransform)(currentCtx)); + + const canvasBounds = [0, 0, currentCtx.canvas.width, currentCtx.canvas.height]; + bounds = _util.Util.intersect(bounds, canvasBounds) || [0, 0, 0, 0]; + const offsetX = Math.floor(bounds[0]); + const offsetY = Math.floor(bounds[1]); + let drawnWidth = Math.max(Math.ceil(bounds[2]) - offsetX, 1); + let drawnHeight = Math.max(Math.ceil(bounds[3]) - offsetY, 1); + let scaleX = 1, + scaleY = 1; + + if (drawnWidth > MAX_GROUP_SIZE) { + scaleX = drawnWidth / MAX_GROUP_SIZE; + drawnWidth = MAX_GROUP_SIZE; + } + + if (drawnHeight > MAX_GROUP_SIZE) { + scaleY = drawnHeight / MAX_GROUP_SIZE; + drawnHeight = MAX_GROUP_SIZE; + } + + this.current.startNewPathAndClipBox([0, 0, drawnWidth, drawnHeight]); + let cacheId = "groupAt" + this.groupLevel; + + if (group.smask) { + cacheId += "_smask_" + this.smaskCounter++ % 2; + } + + const scratchCanvas = this.cachedCanvases.getCanvas(cacheId, drawnWidth, drawnHeight); + const groupCtx = scratchCanvas.context; + groupCtx.scale(1 / scaleX, 1 / scaleY); + groupCtx.translate(-offsetX, -offsetY); + groupCtx.transform(...currentTransform); + + if (group.smask) { + this.smaskStack.push({ + canvas: scratchCanvas.canvas, + context: groupCtx, + offsetX, + offsetY, + scaleX, + scaleY, + subtype: group.smask.subtype, + backdrop: group.smask.backdrop, + transferMap: group.smask.transferMap || null, + startTransformInverse: null + }); + } else { + currentCtx.setTransform(1, 0, 0, 1, 0, 0); + currentCtx.translate(offsetX, offsetY); + currentCtx.scale(scaleX, scaleY); + currentCtx.save(); + } + + copyCtxState(currentCtx, groupCtx); + this.ctx = groupCtx; + this.setGState([["BM", "source-over"], ["ca", 1], ["CA", 1]]); + this.groupStack.push(currentCtx); + this.groupLevel++; + } + + endGroup(group) { + if (!this.contentVisible) { + return; + } + + this.groupLevel--; + const groupCtx = this.ctx; + const ctx = this.groupStack.pop(); + this.ctx = ctx; + this.ctx.imageSmoothingEnabled = false; + + if (group.smask) { + this.tempSMask = this.smaskStack.pop(); + this.restore(); + } else { + this.ctx.restore(); + const currentMtx = (0, _display_utils.getCurrentTransform)(this.ctx); + this.restore(); + this.ctx.save(); + this.ctx.setTransform(...currentMtx); + + const dirtyBox = _util.Util.getAxialAlignedBoundingBox([0, 0, groupCtx.canvas.width, groupCtx.canvas.height], currentMtx); + + this.ctx.drawImage(groupCtx.canvas, 0, 0); + this.ctx.restore(); + this.compose(dirtyBox); + } + } + + beginAnnotation(id, rect, transform, matrix, hasOwnCanvas) { + this.#restoreInitialState(); + resetCtxToDefault(this.ctx, this.foregroundColor); + this.ctx.save(); + this.save(); + + if (this.baseTransform) { + this.ctx.setTransform(...this.baseTransform); + } + + if (Array.isArray(rect) && rect.length === 4) { + const width = rect[2] - rect[0]; + const height = rect[3] - rect[1]; + + if (hasOwnCanvas && this.annotationCanvasMap) { + transform = transform.slice(); + transform[4] -= rect[0]; + transform[5] -= rect[1]; + rect = rect.slice(); + rect[0] = rect[1] = 0; + rect[2] = width; + rect[3] = height; + + const [scaleX, scaleY] = _util.Util.singularValueDecompose2dScale((0, _display_utils.getCurrentTransform)(this.ctx)); + + const { + viewportScale + } = this; + const canvasWidth = Math.ceil(width * this.outputScaleX * viewportScale); + const canvasHeight = Math.ceil(height * this.outputScaleY * viewportScale); + this.annotationCanvas = this.canvasFactory.create(canvasWidth, canvasHeight); + const { + canvas, + context + } = this.annotationCanvas; + this.annotationCanvasMap.set(id, canvas); + this.annotationCanvas.savedCtx = this.ctx; + this.ctx = context; + this.ctx.setTransform(scaleX, 0, 0, -scaleY, 0, height * scaleY); + resetCtxToDefault(this.ctx, this.foregroundColor); + } else { + resetCtxToDefault(this.ctx, this.foregroundColor); + this.ctx.rect(rect[0], rect[1], width, height); + this.ctx.clip(); + this.endPath(); + } + } + + this.current = new CanvasExtraState(this.ctx.canvas.width, this.ctx.canvas.height); + this.transform(...transform); + this.transform(...matrix); + } + + endAnnotation() { + if (this.annotationCanvas) { + this.ctx = this.annotationCanvas.savedCtx; + delete this.annotationCanvas.savedCtx; + delete this.annotationCanvas; + } + } + + paintImageMaskXObject(img) { + if (!this.contentVisible) { + return; + } + + const count = img.count; + img = this.getObject(img.data, img); + img.count = count; + const ctx = this.ctx; + const glyph = this.processingType3; + + if (glyph) { + if (glyph.compiled === undefined) { + glyph.compiled = compileType3Glyph(img); + } + + if (glyph.compiled) { + glyph.compiled(ctx); + return; + } + } + + const mask = this._createMaskCanvas(img); + + const maskCanvas = mask.canvas; + ctx.save(); + ctx.setTransform(1, 0, 0, 1, 0, 0); + ctx.drawImage(maskCanvas, mask.offsetX, mask.offsetY); + ctx.restore(); + this.compose(); + } + + paintImageMaskXObjectRepeat(img, scaleX, skewX = 0, skewY = 0, scaleY, positions) { + if (!this.contentVisible) { + return; + } + + img = this.getObject(img.data, img); + const ctx = this.ctx; + ctx.save(); + const currentTransform = (0, _display_utils.getCurrentTransform)(ctx); + ctx.transform(scaleX, skewX, skewY, scaleY, 0, 0); + + const mask = this._createMaskCanvas(img); + + ctx.setTransform(1, 0, 0, 1, 0, 0); + + for (let i = 0, ii = positions.length; i < ii; i += 2) { + const trans = _util.Util.transform(currentTransform, [scaleX, skewX, skewY, scaleY, positions[i], positions[i + 1]]); + + const [x, y] = _util.Util.applyTransform([0, 0], trans); + + ctx.drawImage(mask.canvas, x, y); + } + + ctx.restore(); + this.compose(); + } + + paintImageMaskXObjectGroup(images) { + if (!this.contentVisible) { + return; + } + + const ctx = this.ctx; + const fillColor = this.current.fillColor; + const isPatternFill = this.current.patternFill; + + for (const image of images) { + const { + data, + width, + height, + transform + } = image; + const maskCanvas = this.cachedCanvases.getCanvas("maskCanvas", width, height); + const maskCtx = maskCanvas.context; + maskCtx.save(); + const img = this.getObject(data, image); + putBinaryImageMask(maskCtx, img); + maskCtx.globalCompositeOperation = "source-in"; + maskCtx.fillStyle = isPatternFill ? fillColor.getPattern(maskCtx, this, (0, _display_utils.getCurrentTransformInverse)(ctx), _pattern_helper.PathType.FILL) : fillColor; + maskCtx.fillRect(0, 0, width, height); + maskCtx.restore(); + ctx.save(); + ctx.transform(...transform); + ctx.scale(1, -1); + drawImageAtIntegerCoords(ctx, maskCanvas.canvas, 0, 0, width, height, 0, -1, 1, 1); + ctx.restore(); + } + + this.compose(); + } + + paintImageXObject(objId) { + if (!this.contentVisible) { + return; + } + + const imgData = this.getObject(objId); + + if (!imgData) { + (0, _util.warn)("Dependent image isn't ready yet"); + return; + } + + this.paintInlineImageXObject(imgData); + } + + paintImageXObjectRepeat(objId, scaleX, scaleY, positions) { + if (!this.contentVisible) { + return; + } + + const imgData = this.getObject(objId); + + if (!imgData) { + (0, _util.warn)("Dependent image isn't ready yet"); + return; + } + + const width = imgData.width; + const height = imgData.height; + const map = []; + + for (let i = 0, ii = positions.length; i < ii; i += 2) { + map.push({ + transform: [scaleX, 0, 0, scaleY, positions[i], positions[i + 1]], + x: 0, + y: 0, + w: width, + h: height + }); + } + + this.paintInlineImageXObjectGroup(imgData, map); + } + + paintInlineImageXObject(imgData) { + if (!this.contentVisible) { + return; + } + + const width = imgData.width; + const height = imgData.height; + const ctx = this.ctx; + this.save(); + ctx.scale(1 / width, -1 / height); + let imgToPaint; + + if (typeof HTMLElement === "function" && imgData instanceof HTMLElement || !imgData.data) { + imgToPaint = imgData; + } else { + const tmpCanvas = this.cachedCanvases.getCanvas("inlineImage", width, height); + const tmpCtx = tmpCanvas.context; + putBinaryImageData(tmpCtx, imgData, this.current.transferMaps); + imgToPaint = tmpCanvas.canvas; + } + + const scaled = this._scaleImage(imgToPaint, (0, _display_utils.getCurrentTransformInverse)(ctx)); + + ctx.imageSmoothingEnabled = getImageSmoothingEnabled((0, _display_utils.getCurrentTransform)(ctx), imgData.interpolate); + const [rWidth, rHeight] = drawImageAtIntegerCoords(ctx, scaled.img, 0, 0, scaled.paintWidth, scaled.paintHeight, 0, -height, width, height); + + if (this.imageLayer) { + const [left, top] = _util.Util.applyTransform([0, -height], (0, _display_utils.getCurrentTransform)(this.ctx)); + + this.imageLayer.appendImage({ + imgData, + left, + top, + width: rWidth, + height: rHeight + }); + } + + this.compose(); + this.restore(); + } + + paintInlineImageXObjectGroup(imgData, map) { + if (!this.contentVisible) { + return; + } + + const ctx = this.ctx; + const w = imgData.width; + const h = imgData.height; + const tmpCanvas = this.cachedCanvases.getCanvas("inlineImage", w, h); + const tmpCtx = tmpCanvas.context; + putBinaryImageData(tmpCtx, imgData, this.current.transferMaps); + + for (const entry of map) { + ctx.save(); + ctx.transform(...entry.transform); + ctx.scale(1, -1); + drawImageAtIntegerCoords(ctx, tmpCanvas.canvas, entry.x, entry.y, entry.w, entry.h, 0, -1, 1, 1); + + if (this.imageLayer) { + const [left, top] = _util.Util.applyTransform([entry.x, entry.y], (0, _display_utils.getCurrentTransform)(this.ctx)); + + this.imageLayer.appendImage({ + imgData, + left, + top, + width: w, + height: h + }); + } + + ctx.restore(); + } + + this.compose(); + } + + paintSolidColorImageMask() { + if (!this.contentVisible) { + return; + } + + this.ctx.fillRect(0, 0, 1, 1); + this.compose(); + } + + markPoint(tag) {} + + markPointProps(tag, properties) {} + + beginMarkedContent(tag) { + this.markedContentStack.push({ + visible: true + }); + } + + beginMarkedContentProps(tag, properties) { + if (tag === "OC") { + this.markedContentStack.push({ + visible: this.optionalContentConfig.isVisible(properties) + }); + } else { + this.markedContentStack.push({ + visible: true + }); + } + + this.contentVisible = this.isContentVisible(); + } + + endMarkedContent() { + this.markedContentStack.pop(); + this.contentVisible = this.isContentVisible(); + } + + beginCompat() {} + + endCompat() {} + + consumePath(clipBox) { + const isEmpty = this.current.isEmptyClip(); + + if (this.pendingClip) { + this.current.updateClipFromPath(); + } + + if (!this.pendingClip) { + this.compose(clipBox); + } + + const ctx = this.ctx; + + if (this.pendingClip) { + if (!isEmpty) { + if (this.pendingClip === EO_CLIP) { + ctx.clip("evenodd"); + } else { + ctx.clip(); + } + } + + this.pendingClip = null; + } + + this.current.startNewPathAndClipBox(this.current.clipBox); + ctx.beginPath(); + } + + getSinglePixelWidth() { + if (!this._cachedGetSinglePixelWidth) { + const m = (0, _display_utils.getCurrentTransform)(this.ctx); + + if (m[1] === 0 && m[2] === 0) { + this._cachedGetSinglePixelWidth = 1 / Math.min(Math.abs(m[0]), Math.abs(m[3])); + } else { + const absDet = Math.abs(m[0] * m[3] - m[2] * m[1]); + const normX = Math.hypot(m[0], m[2]); + const normY = Math.hypot(m[1], m[3]); + this._cachedGetSinglePixelWidth = Math.max(normX, normY) / absDet; + } + } + + return this._cachedGetSinglePixelWidth; + } + + getScaleForStroking() { + if (!this._cachedScaleForStroking) { + const { + lineWidth + } = this.current; + const m = (0, _display_utils.getCurrentTransform)(this.ctx); + let scaleX, scaleY; + + if (m[1] === 0 && m[2] === 0) { + const normX = Math.abs(m[0]); + const normY = Math.abs(m[3]); + + if (lineWidth === 0) { + scaleX = 1 / normX; + scaleY = 1 / normY; + } else { + const scaledXLineWidth = normX * lineWidth; + const scaledYLineWidth = normY * lineWidth; + scaleX = scaledXLineWidth < 1 ? 1 / scaledXLineWidth : 1; + scaleY = scaledYLineWidth < 1 ? 1 / scaledYLineWidth : 1; + } + } else { + const absDet = Math.abs(m[0] * m[3] - m[2] * m[1]); + const normX = Math.hypot(m[0], m[1]); + const normY = Math.hypot(m[2], m[3]); + + if (lineWidth === 0) { + scaleX = normY / absDet; + scaleY = normX / absDet; + } else { + const baseArea = lineWidth * absDet; + scaleX = normY > baseArea ? normY / baseArea : 1; + scaleY = normX > baseArea ? normX / baseArea : 1; + } + } + + this._cachedScaleForStroking = [scaleX, scaleY]; + } + + return this._cachedScaleForStroking; + } + + rescaleAndStroke(saveRestore) { + const { + ctx + } = this; + const { + lineWidth + } = this.current; + const [scaleX, scaleY] = this.getScaleForStroking(); + ctx.lineWidth = lineWidth || 1; + + if (scaleX === 1 && scaleY === 1) { + ctx.stroke(); + return; + } + + let savedMatrix, savedDashes, savedDashOffset; + + if (saveRestore) { + savedMatrix = (0, _display_utils.getCurrentTransform)(ctx); + savedDashes = ctx.getLineDash().slice(); + savedDashOffset = ctx.lineDashOffset; + } + + ctx.scale(scaleX, scaleY); + const scale = Math.max(scaleX, scaleY); + ctx.setLineDash(ctx.getLineDash().map(x => x / scale)); + ctx.lineDashOffset /= scale; + ctx.stroke(); + + if (saveRestore) { + ctx.setTransform(...savedMatrix); + ctx.setLineDash(savedDashes); + ctx.lineDashOffset = savedDashOffset; + } + } + + isContentVisible() { + for (let i = this.markedContentStack.length - 1; i >= 0; i--) { + if (!this.markedContentStack[i].visible) { + return false; + } + } + + return true; + } + + } + + exports.CanvasGraphics = CanvasGraphics; + + for (const op in _util.OPS) { + if (CanvasGraphics.prototype[op] !== undefined) { + CanvasGraphics.prototype[_util.OPS[op]] = CanvasGraphics.prototype[op]; + } + } + + /***/ }), + /* 13 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.TilingPattern = exports.PathType = void 0; + exports.getShadingPattern = getShadingPattern; + + var _util = __w_pdfjs_require__(1); + + var _display_utils = __w_pdfjs_require__(8); + + var _is_node = __w_pdfjs_require__(3); + + const PathType = { + FILL: "Fill", + STROKE: "Stroke", + SHADING: "Shading" + }; + exports.PathType = PathType; + + function applyBoundingBox(ctx, bbox) { + if (!bbox || _is_node.isNodeJS) { + return; + } + + const width = bbox[2] - bbox[0]; + const height = bbox[3] - bbox[1]; + const region = new Path2D(); + region.rect(bbox[0], bbox[1], width, height); + ctx.clip(region); + } + + class BaseShadingPattern { + constructor() { + if (this.constructor === BaseShadingPattern) { + (0, _util.unreachable)("Cannot initialize BaseShadingPattern."); + } + } + + getPattern() { + (0, _util.unreachable)("Abstract method `getPattern` called."); + } + + } + + class RadialAxialShadingPattern extends BaseShadingPattern { + constructor(IR) { + super(); + this._type = IR[1]; + this._bbox = IR[2]; + this._colorStops = IR[3]; + this._p0 = IR[4]; + this._p1 = IR[5]; + this._r0 = IR[6]; + this._r1 = IR[7]; + this.matrix = null; + } + + _createGradient(ctx) { + let grad; + + if (this._type === "axial") { + grad = ctx.createLinearGradient(this._p0[0], this._p0[1], this._p1[0], this._p1[1]); + } else if (this._type === "radial") { + grad = ctx.createRadialGradient(this._p0[0], this._p0[1], this._r0, this._p1[0], this._p1[1], this._r1); + } + + for (const colorStop of this._colorStops) { + grad.addColorStop(colorStop[0], colorStop[1]); + } + + return grad; + } + + getPattern(ctx, owner, inverse, pathType) { + let pattern; + + if (pathType === PathType.STROKE || pathType === PathType.FILL) { + const ownerBBox = owner.current.getClippedPathBoundingBox(pathType, (0, _display_utils.getCurrentTransform)(ctx)) || [0, 0, 0, 0]; + const width = Math.ceil(ownerBBox[2] - ownerBBox[0]) || 1; + const height = Math.ceil(ownerBBox[3] - ownerBBox[1]) || 1; + const tmpCanvas = owner.cachedCanvases.getCanvas("pattern", width, height, true); + const tmpCtx = tmpCanvas.context; + tmpCtx.clearRect(0, 0, tmpCtx.canvas.width, tmpCtx.canvas.height); + tmpCtx.beginPath(); + tmpCtx.rect(0, 0, tmpCtx.canvas.width, tmpCtx.canvas.height); + tmpCtx.translate(-ownerBBox[0], -ownerBBox[1]); + inverse = _util.Util.transform(inverse, [1, 0, 0, 1, ownerBBox[0], ownerBBox[1]]); + tmpCtx.transform(...owner.baseTransform); + + if (this.matrix) { + tmpCtx.transform(...this.matrix); + } + + applyBoundingBox(tmpCtx, this._bbox); + tmpCtx.fillStyle = this._createGradient(tmpCtx); + tmpCtx.fill(); + pattern = ctx.createPattern(tmpCanvas.canvas, "no-repeat"); + const domMatrix = new DOMMatrix(inverse); + + try { + pattern.setTransform(domMatrix); + } catch (ex) { + (0, _util.warn)(`RadialAxialShadingPattern.getPattern: "${ex?.message}".`); + } + } else { + applyBoundingBox(ctx, this._bbox); + pattern = this._createGradient(ctx); + } + + return pattern; + } + + } + + function drawTriangle(data, context, p1, p2, p3, c1, c2, c3) { + const coords = context.coords, + colors = context.colors; + const bytes = data.data, + rowSize = data.width * 4; + let tmp; + + if (coords[p1 + 1] > coords[p2 + 1]) { + tmp = p1; + p1 = p2; + p2 = tmp; + tmp = c1; + c1 = c2; + c2 = tmp; + } + + if (coords[p2 + 1] > coords[p3 + 1]) { + tmp = p2; + p2 = p3; + p3 = tmp; + tmp = c2; + c2 = c3; + c3 = tmp; + } + + if (coords[p1 + 1] > coords[p2 + 1]) { + tmp = p1; + p1 = p2; + p2 = tmp; + tmp = c1; + c1 = c2; + c2 = tmp; + } + + const x1 = (coords[p1] + context.offsetX) * context.scaleX; + const y1 = (coords[p1 + 1] + context.offsetY) * context.scaleY; + const x2 = (coords[p2] + context.offsetX) * context.scaleX; + const y2 = (coords[p2 + 1] + context.offsetY) * context.scaleY; + const x3 = (coords[p3] + context.offsetX) * context.scaleX; + const y3 = (coords[p3 + 1] + context.offsetY) * context.scaleY; + + if (y1 >= y3) { + return; + } + + const c1r = colors[c1], + c1g = colors[c1 + 1], + c1b = colors[c1 + 2]; + const c2r = colors[c2], + c2g = colors[c2 + 1], + c2b = colors[c2 + 2]; + const c3r = colors[c3], + c3g = colors[c3 + 1], + c3b = colors[c3 + 2]; + const minY = Math.round(y1), + maxY = Math.round(y3); + let xa, car, cag, cab; + let xb, cbr, cbg, cbb; + + for (let y = minY; y <= maxY; y++) { + if (y < y2) { + let k; + + if (y < y1) { + k = 0; + } else { + k = (y1 - y) / (y1 - y2); + } + + xa = x1 - (x1 - x2) * k; + car = c1r - (c1r - c2r) * k; + cag = c1g - (c1g - c2g) * k; + cab = c1b - (c1b - c2b) * k; + } else { + let k; + + if (y > y3) { + k = 1; + } else if (y2 === y3) { + k = 0; + } else { + k = (y2 - y) / (y2 - y3); + } + + xa = x2 - (x2 - x3) * k; + car = c2r - (c2r - c3r) * k; + cag = c2g - (c2g - c3g) * k; + cab = c2b - (c2b - c3b) * k; + } + + let k; + + if (y < y1) { + k = 0; + } else if (y > y3) { + k = 1; + } else { + k = (y1 - y) / (y1 - y3); + } + + xb = x1 - (x1 - x3) * k; + cbr = c1r - (c1r - c3r) * k; + cbg = c1g - (c1g - c3g) * k; + cbb = c1b - (c1b - c3b) * k; + const x1_ = Math.round(Math.min(xa, xb)); + const x2_ = Math.round(Math.max(xa, xb)); + let j = rowSize * y + x1_ * 4; + + for (let x = x1_; x <= x2_; x++) { + k = (xa - x) / (xa - xb); + + if (k < 0) { + k = 0; + } else if (k > 1) { + k = 1; + } + + bytes[j++] = car - (car - cbr) * k | 0; + bytes[j++] = cag - (cag - cbg) * k | 0; + bytes[j++] = cab - (cab - cbb) * k | 0; + bytes[j++] = 255; + } + } + } + + function drawFigure(data, figure, context) { + const ps = figure.coords; + const cs = figure.colors; + let i, ii; + + switch (figure.type) { + case "lattice": + const verticesPerRow = figure.verticesPerRow; + const rows = Math.floor(ps.length / verticesPerRow) - 1; + const cols = verticesPerRow - 1; + + for (i = 0; i < rows; i++) { + let q = i * verticesPerRow; + + for (let j = 0; j < cols; j++, q++) { + drawTriangle(data, context, ps[q], ps[q + 1], ps[q + verticesPerRow], cs[q], cs[q + 1], cs[q + verticesPerRow]); + drawTriangle(data, context, ps[q + verticesPerRow + 1], ps[q + 1], ps[q + verticesPerRow], cs[q + verticesPerRow + 1], cs[q + 1], cs[q + verticesPerRow]); + } + } + + break; + + case "triangles": + for (i = 0, ii = ps.length; i < ii; i += 3) { + drawTriangle(data, context, ps[i], ps[i + 1], ps[i + 2], cs[i], cs[i + 1], cs[i + 2]); + } + + break; + + default: + throw new Error("illegal figure"); + } + } + + class MeshShadingPattern extends BaseShadingPattern { + constructor(IR) { + super(); + this._coords = IR[2]; + this._colors = IR[3]; + this._figures = IR[4]; + this._bounds = IR[5]; + this._bbox = IR[7]; + this._background = IR[8]; + this.matrix = null; + } + + _createMeshCanvas(combinedScale, backgroundColor, cachedCanvases) { + const EXPECTED_SCALE = 1.1; + const MAX_PATTERN_SIZE = 3000; + const BORDER_SIZE = 2; + const offsetX = Math.floor(this._bounds[0]); + const offsetY = Math.floor(this._bounds[1]); + const boundsWidth = Math.ceil(this._bounds[2]) - offsetX; + const boundsHeight = Math.ceil(this._bounds[3]) - offsetY; + const width = Math.min(Math.ceil(Math.abs(boundsWidth * combinedScale[0] * EXPECTED_SCALE)), MAX_PATTERN_SIZE); + const height = Math.min(Math.ceil(Math.abs(boundsHeight * combinedScale[1] * EXPECTED_SCALE)), MAX_PATTERN_SIZE); + const scaleX = boundsWidth / width; + const scaleY = boundsHeight / height; + const context = { + coords: this._coords, + colors: this._colors, + offsetX: -offsetX, + offsetY: -offsetY, + scaleX: 1 / scaleX, + scaleY: 1 / scaleY + }; + const paddedWidth = width + BORDER_SIZE * 2; + const paddedHeight = height + BORDER_SIZE * 2; + const tmpCanvas = cachedCanvases.getCanvas("mesh", paddedWidth, paddedHeight, false); + const tmpCtx = tmpCanvas.context; + const data = tmpCtx.createImageData(width, height); + + if (backgroundColor) { + const bytes = data.data; + + for (let i = 0, ii = bytes.length; i < ii; i += 4) { + bytes[i] = backgroundColor[0]; + bytes[i + 1] = backgroundColor[1]; + bytes[i + 2] = backgroundColor[2]; + bytes[i + 3] = 255; + } + } + + for (const figure of this._figures) { + drawFigure(data, figure, context); + } + + tmpCtx.putImageData(data, BORDER_SIZE, BORDER_SIZE); + const canvas = tmpCanvas.canvas; + return { + canvas, + offsetX: offsetX - BORDER_SIZE * scaleX, + offsetY: offsetY - BORDER_SIZE * scaleY, + scaleX, + scaleY + }; + } + + getPattern(ctx, owner, inverse, pathType) { + applyBoundingBox(ctx, this._bbox); + let scale; + + if (pathType === PathType.SHADING) { + scale = _util.Util.singularValueDecompose2dScale((0, _display_utils.getCurrentTransform)(ctx)); + } else { + scale = _util.Util.singularValueDecompose2dScale(owner.baseTransform); + + if (this.matrix) { + const matrixScale = _util.Util.singularValueDecompose2dScale(this.matrix); + + scale = [scale[0] * matrixScale[0], scale[1] * matrixScale[1]]; + } + } + + const temporaryPatternCanvas = this._createMeshCanvas(scale, pathType === PathType.SHADING ? null : this._background, owner.cachedCanvases); + + if (pathType !== PathType.SHADING) { + ctx.setTransform(...owner.baseTransform); + + if (this.matrix) { + ctx.transform(...this.matrix); + } + } + + ctx.translate(temporaryPatternCanvas.offsetX, temporaryPatternCanvas.offsetY); + ctx.scale(temporaryPatternCanvas.scaleX, temporaryPatternCanvas.scaleY); + return ctx.createPattern(temporaryPatternCanvas.canvas, "no-repeat"); + } + + } + + class DummyShadingPattern extends BaseShadingPattern { + getPattern() { + return "hotpink"; + } + + } + + function getShadingPattern(IR) { + switch (IR[0]) { + case "RadialAxial": + return new RadialAxialShadingPattern(IR); + + case "Mesh": + return new MeshShadingPattern(IR); + + case "Dummy": + return new DummyShadingPattern(); + } + + throw new Error(`Unknown IR type: ${IR[0]}`); + } + + const PaintType = { + COLORED: 1, + UNCOLORED: 2 + }; + + class TilingPattern { + static get MAX_PATTERN_SIZE() { + return (0, _util.shadow)(this, "MAX_PATTERN_SIZE", 3000); + } + + constructor(IR, color, ctx, canvasGraphicsFactory, baseTransform) { + this.operatorList = IR[2]; + this.matrix = IR[3] || [1, 0, 0, 1, 0, 0]; + this.bbox = IR[4]; + this.xstep = IR[5]; + this.ystep = IR[6]; + this.paintType = IR[7]; + this.tilingType = IR[8]; + this.color = color; + this.ctx = ctx; + this.canvasGraphicsFactory = canvasGraphicsFactory; + this.baseTransform = baseTransform; + } + + createPatternCanvas(owner) { + const operatorList = this.operatorList; + const bbox = this.bbox; + const xstep = this.xstep; + const ystep = this.ystep; + const paintType = this.paintType; + const tilingType = this.tilingType; + const color = this.color; + const canvasGraphicsFactory = this.canvasGraphicsFactory; + (0, _util.info)("TilingType: " + tilingType); + const x0 = bbox[0], + y0 = bbox[1], + x1 = bbox[2], + y1 = bbox[3]; + + const matrixScale = _util.Util.singularValueDecompose2dScale(this.matrix); + + const curMatrixScale = _util.Util.singularValueDecompose2dScale(this.baseTransform); + + const combinedScale = [matrixScale[0] * curMatrixScale[0], matrixScale[1] * curMatrixScale[1]]; + const dimx = this.getSizeAndScale(xstep, this.ctx.canvas.width, combinedScale[0]); + const dimy = this.getSizeAndScale(ystep, this.ctx.canvas.height, combinedScale[1]); + const tmpCanvas = owner.cachedCanvases.getCanvas("pattern", dimx.size, dimy.size, true); + const tmpCtx = tmpCanvas.context; + const graphics = canvasGraphicsFactory.createCanvasGraphics(tmpCtx); + graphics.groupLevel = owner.groupLevel; + this.setFillAndStrokeStyleToContext(graphics, paintType, color); + let adjustedX0 = x0; + let adjustedY0 = y0; + let adjustedX1 = x1; + let adjustedY1 = y1; + + if (x0 < 0) { + adjustedX0 = 0; + adjustedX1 += Math.abs(x0); + } + + if (y0 < 0) { + adjustedY0 = 0; + adjustedY1 += Math.abs(y0); + } + + tmpCtx.translate(-(dimx.scale * adjustedX0), -(dimy.scale * adjustedY0)); + graphics.transform(dimx.scale, 0, 0, dimy.scale, 0, 0); + tmpCtx.save(); + this.clipBbox(graphics, adjustedX0, adjustedY0, adjustedX1, adjustedY1); + graphics.baseTransform = (0, _display_utils.getCurrentTransform)(graphics.ctx); + graphics.executeOperatorList(operatorList); + graphics.endDrawing(); + return { + canvas: tmpCanvas.canvas, + scaleX: dimx.scale, + scaleY: dimy.scale, + offsetX: adjustedX0, + offsetY: adjustedY0 + }; + } + + getSizeAndScale(step, realOutputSize, scale) { + step = Math.abs(step); + const maxSize = Math.max(TilingPattern.MAX_PATTERN_SIZE, realOutputSize); + let size = Math.ceil(step * scale); + + if (size >= maxSize) { + size = maxSize; + } else { + scale = size / step; + } + + return { + scale, + size + }; + } + + clipBbox(graphics, x0, y0, x1, y1) { + const bboxWidth = x1 - x0; + const bboxHeight = y1 - y0; + graphics.ctx.rect(x0, y0, bboxWidth, bboxHeight); + graphics.current.updateRectMinMax((0, _display_utils.getCurrentTransform)(graphics.ctx), [x0, y0, x1, y1]); + graphics.clip(); + graphics.endPath(); + } + + setFillAndStrokeStyleToContext(graphics, paintType, color) { + const context = graphics.ctx, + current = graphics.current; + + switch (paintType) { + case PaintType.COLORED: + const ctx = this.ctx; + context.fillStyle = ctx.fillStyle; + context.strokeStyle = ctx.strokeStyle; + current.fillColor = ctx.fillStyle; + current.strokeColor = ctx.strokeStyle; + break; + + case PaintType.UNCOLORED: + const cssColor = _util.Util.makeHexColor(color[0], color[1], color[2]); + + context.fillStyle = cssColor; + context.strokeStyle = cssColor; + current.fillColor = cssColor; + current.strokeColor = cssColor; + break; + + default: + throw new _util.FormatError(`Unsupported paint type: ${paintType}`); + } + } + + getPattern(ctx, owner, inverse, pathType) { + let matrix = inverse; + + if (pathType !== PathType.SHADING) { + matrix = _util.Util.transform(matrix, owner.baseTransform); + + if (this.matrix) { + matrix = _util.Util.transform(matrix, this.matrix); + } + } + + const temporaryPatternCanvas = this.createPatternCanvas(owner); + let domMatrix = new DOMMatrix(matrix); + domMatrix = domMatrix.translate(temporaryPatternCanvas.offsetX, temporaryPatternCanvas.offsetY); + domMatrix = domMatrix.scale(1 / temporaryPatternCanvas.scaleX, 1 / temporaryPatternCanvas.scaleY); + const pattern = ctx.createPattern(temporaryPatternCanvas.canvas, "repeat"); + + try { + pattern.setTransform(domMatrix); + } catch (ex) { + (0, _util.warn)(`TilingPattern.getPattern: "${ex?.message}".`); + } + + return pattern; + } + + } + + exports.TilingPattern = TilingPattern; + + /***/ }), + /* 14 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.applyMaskImageData = applyMaskImageData; + + var _util = __w_pdfjs_require__(1); + + function applyMaskImageData({ + src, + srcPos = 0, + dest, + destPos = 0, + width, + height, + inverseDecode = false + }) { + const opaque = _util.FeatureTest.isLittleEndian ? 0xff000000 : 0x000000ff; + const [zeroMapping, oneMapping] = !inverseDecode ? [opaque, 0] : [0, opaque]; + const widthInSource = width >> 3; + const widthRemainder = width & 7; + const srcLength = src.length; + dest = new Uint32Array(dest.buffer); + + for (let i = 0; i < height; i++) { + for (const max = srcPos + widthInSource; srcPos < max; srcPos++) { + const elem = srcPos < srcLength ? src[srcPos] : 255; + dest[destPos++] = elem & 0b10000000 ? oneMapping : zeroMapping; + dest[destPos++] = elem & 0b1000000 ? oneMapping : zeroMapping; + dest[destPos++] = elem & 0b100000 ? oneMapping : zeroMapping; + dest[destPos++] = elem & 0b10000 ? oneMapping : zeroMapping; + dest[destPos++] = elem & 0b1000 ? oneMapping : zeroMapping; + dest[destPos++] = elem & 0b100 ? oneMapping : zeroMapping; + dest[destPos++] = elem & 0b10 ? oneMapping : zeroMapping; + dest[destPos++] = elem & 0b1 ? oneMapping : zeroMapping; + } + + if (widthRemainder === 0) { + continue; + } + + const elem = srcPos < srcLength ? src[srcPos++] : 255; + + for (let j = 0; j < widthRemainder; j++) { + dest[destPos++] = elem & 1 << 7 - j ? oneMapping : zeroMapping; + } + } + + return { + srcPos, + destPos + }; + } + + /***/ }), + /* 15 */ + /***/ ((__unused_webpack_module, exports) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.GlobalWorkerOptions = void 0; + const GlobalWorkerOptions = Object.create(null); + exports.GlobalWorkerOptions = GlobalWorkerOptions; + GlobalWorkerOptions.workerPort = GlobalWorkerOptions.workerPort === undefined ? null : GlobalWorkerOptions.workerPort; + GlobalWorkerOptions.workerSrc = GlobalWorkerOptions.workerSrc === undefined ? "" : GlobalWorkerOptions.workerSrc; + + /***/ }), + /* 16 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.MessageHandler = void 0; + + var _util = __w_pdfjs_require__(1); + + const CallbackKind = { + UNKNOWN: 0, + DATA: 1, + ERROR: 2 + }; + const StreamKind = { + UNKNOWN: 0, + CANCEL: 1, + CANCEL_COMPLETE: 2, + CLOSE: 3, + ENQUEUE: 4, + ERROR: 5, + PULL: 6, + PULL_COMPLETE: 7, + START_COMPLETE: 8 + }; + + function wrapReason(reason) { + if (!(reason instanceof Error || typeof reason === "object" && reason !== null)) { + (0, _util.unreachable)('wrapReason: Expected "reason" to be a (possibly cloned) Error.'); + } + + switch (reason.name) { + case "AbortException": + return new _util.AbortException(reason.message); + + case "MissingPDFException": + return new _util.MissingPDFException(reason.message); + + case "PasswordException": + return new _util.PasswordException(reason.message, reason.code); + + case "UnexpectedResponseException": + return new _util.UnexpectedResponseException(reason.message, reason.status); + + case "UnknownErrorException": + return new _util.UnknownErrorException(reason.message, reason.details); + + default: + return new _util.UnknownErrorException(reason.message, reason.toString()); + } + } + + class MessageHandler { + constructor(sourceName, targetName, comObj) { + this.sourceName = sourceName; + this.targetName = targetName; + this.comObj = comObj; + this.callbackId = 1; + this.streamId = 1; + this.streamSinks = Object.create(null); + this.streamControllers = Object.create(null); + this.callbackCapabilities = Object.create(null); + this.actionHandler = Object.create(null); + + this._onComObjOnMessage = event => { + const data = event.data; + + if (data.targetName !== this.sourceName) { + return; + } + + if (data.stream) { + this._processStreamMessage(data); + + return; + } + + if (data.callback) { + const callbackId = data.callbackId; + const capability = this.callbackCapabilities[callbackId]; + + if (!capability) { + throw new Error(`Cannot resolve callback ${callbackId}`); + } + + delete this.callbackCapabilities[callbackId]; + + if (data.callback === CallbackKind.DATA) { + capability.resolve(data.data); + } else if (data.callback === CallbackKind.ERROR) { + capability.reject(wrapReason(data.reason)); + } else { + throw new Error("Unexpected callback case"); + } + + return; + } + + const action = this.actionHandler[data.action]; + + if (!action) { + throw new Error(`Unknown action from worker: ${data.action}`); + } + + if (data.callbackId) { + const cbSourceName = this.sourceName; + const cbTargetName = data.sourceName; + new Promise(function (resolve) { + resolve(action(data.data)); + }).then(function (result) { + comObj.postMessage({ + sourceName: cbSourceName, + targetName: cbTargetName, + callback: CallbackKind.DATA, + callbackId: data.callbackId, + data: result + }); + }, function (reason) { + comObj.postMessage({ + sourceName: cbSourceName, + targetName: cbTargetName, + callback: CallbackKind.ERROR, + callbackId: data.callbackId, + reason: wrapReason(reason) + }); + }); + return; + } + + if (data.streamId) { + this._createStreamSink(data); + + return; + } + + action(data.data); + }; + + comObj.addEventListener("message", this._onComObjOnMessage); + } + + on(actionName, handler) { + const ah = this.actionHandler; + + if (ah[actionName]) { + throw new Error(`There is already an actionName called "${actionName}"`); + } + + ah[actionName] = handler; + } + + send(actionName, data, transfers) { + this.comObj.postMessage({ + sourceName: this.sourceName, + targetName: this.targetName, + action: actionName, + data + }, transfers); + } + + sendWithPromise(actionName, data, transfers) { + const callbackId = this.callbackId++; + const capability = (0, _util.createPromiseCapability)(); + this.callbackCapabilities[callbackId] = capability; + + try { + this.comObj.postMessage({ + sourceName: this.sourceName, + targetName: this.targetName, + action: actionName, + callbackId, + data + }, transfers); + } catch (ex) { + capability.reject(ex); + } + + return capability.promise; + } + + sendWithStream(actionName, data, queueingStrategy, transfers) { + const streamId = this.streamId++, + sourceName = this.sourceName, + targetName = this.targetName, + comObj = this.comObj; + return new ReadableStream({ + start: controller => { + const startCapability = (0, _util.createPromiseCapability)(); + this.streamControllers[streamId] = { + controller, + startCall: startCapability, + pullCall: null, + cancelCall: null, + isClosed: false + }; + comObj.postMessage({ + sourceName, + targetName, + action: actionName, + streamId, + data, + desiredSize: controller.desiredSize + }, transfers); + return startCapability.promise; + }, + pull: controller => { + const pullCapability = (0, _util.createPromiseCapability)(); + this.streamControllers[streamId].pullCall = pullCapability; + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.PULL, + streamId, + desiredSize: controller.desiredSize + }); + return pullCapability.promise; + }, + cancel: reason => { + (0, _util.assert)(reason instanceof Error, "cancel must have a valid reason"); + const cancelCapability = (0, _util.createPromiseCapability)(); + this.streamControllers[streamId].cancelCall = cancelCapability; + this.streamControllers[streamId].isClosed = true; + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.CANCEL, + streamId, + reason: wrapReason(reason) + }); + return cancelCapability.promise; + } + }, queueingStrategy); + } + + _createStreamSink(data) { + const streamId = data.streamId, + sourceName = this.sourceName, + targetName = data.sourceName, + comObj = this.comObj; + const self = this, + action = this.actionHandler[data.action]; + const streamSink = { + enqueue(chunk, size = 1, transfers) { + if (this.isCancelled) { + return; + } + + const lastDesiredSize = this.desiredSize; + this.desiredSize -= size; + + if (lastDesiredSize > 0 && this.desiredSize <= 0) { + this.sinkCapability = (0, _util.createPromiseCapability)(); + this.ready = this.sinkCapability.promise; + } + + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.ENQUEUE, + streamId, + chunk + }, transfers); + }, + + close() { + if (this.isCancelled) { + return; + } + + this.isCancelled = true; + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.CLOSE, + streamId + }); + delete self.streamSinks[streamId]; + }, + + error(reason) { + (0, _util.assert)(reason instanceof Error, "error must have a valid reason"); + + if (this.isCancelled) { + return; + } + + this.isCancelled = true; + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.ERROR, + streamId, + reason: wrapReason(reason) + }); + }, + + sinkCapability: (0, _util.createPromiseCapability)(), + onPull: null, + onCancel: null, + isCancelled: false, + desiredSize: data.desiredSize, + ready: null + }; + streamSink.sinkCapability.resolve(); + streamSink.ready = streamSink.sinkCapability.promise; + this.streamSinks[streamId] = streamSink; + new Promise(function (resolve) { + resolve(action(data.data, streamSink)); + }).then(function () { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.START_COMPLETE, + streamId, + success: true + }); + }, function (reason) { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.START_COMPLETE, + streamId, + reason: wrapReason(reason) + }); + }); + } + + _processStreamMessage(data) { + const streamId = data.streamId, + sourceName = this.sourceName, + targetName = data.sourceName, + comObj = this.comObj; + const streamController = this.streamControllers[streamId], + streamSink = this.streamSinks[streamId]; + + switch (data.stream) { + case StreamKind.START_COMPLETE: + if (data.success) { + streamController.startCall.resolve(); + } else { + streamController.startCall.reject(wrapReason(data.reason)); + } + + break; + + case StreamKind.PULL_COMPLETE: + if (data.success) { + streamController.pullCall.resolve(); + } else { + streamController.pullCall.reject(wrapReason(data.reason)); + } + + break; + + case StreamKind.PULL: + if (!streamSink) { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.PULL_COMPLETE, + streamId, + success: true + }); + break; + } + + if (streamSink.desiredSize <= 0 && data.desiredSize > 0) { + streamSink.sinkCapability.resolve(); + } + + streamSink.desiredSize = data.desiredSize; + new Promise(function (resolve) { + resolve(streamSink.onPull && streamSink.onPull()); + }).then(function () { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.PULL_COMPLETE, + streamId, + success: true + }); + }, function (reason) { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.PULL_COMPLETE, + streamId, + reason: wrapReason(reason) + }); + }); + break; + + case StreamKind.ENQUEUE: + (0, _util.assert)(streamController, "enqueue should have stream controller"); + + if (streamController.isClosed) { + break; + } + + streamController.controller.enqueue(data.chunk); + break; + + case StreamKind.CLOSE: + (0, _util.assert)(streamController, "close should have stream controller"); + + if (streamController.isClosed) { + break; + } + + streamController.isClosed = true; + streamController.controller.close(); + + this._deleteStreamController(streamController, streamId); + + break; + + case StreamKind.ERROR: + (0, _util.assert)(streamController, "error should have stream controller"); + streamController.controller.error(wrapReason(data.reason)); + + this._deleteStreamController(streamController, streamId); + + break; + + case StreamKind.CANCEL_COMPLETE: + if (data.success) { + streamController.cancelCall.resolve(); + } else { + streamController.cancelCall.reject(wrapReason(data.reason)); + } + + this._deleteStreamController(streamController, streamId); + + break; + + case StreamKind.CANCEL: + if (!streamSink) { + break; + } + + new Promise(function (resolve) { + resolve(streamSink.onCancel && streamSink.onCancel(wrapReason(data.reason))); + }).then(function () { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.CANCEL_COMPLETE, + streamId, + success: true + }); + }, function (reason) { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.CANCEL_COMPLETE, + streamId, + reason: wrapReason(reason) + }); + }); + streamSink.sinkCapability.reject(wrapReason(data.reason)); + streamSink.isCancelled = true; + delete this.streamSinks[streamId]; + break; + + default: + throw new Error("Unexpected stream case"); + } + } + + async _deleteStreamController(streamController, streamId) { + await Promise.allSettled([streamController.startCall && streamController.startCall.promise, streamController.pullCall && streamController.pullCall.promise, streamController.cancelCall && streamController.cancelCall.promise]); + delete this.streamControllers[streamId]; + } + + destroy() { + this.comObj.removeEventListener("message", this._onComObjOnMessage); + } + + } + + exports.MessageHandler = MessageHandler; + + /***/ }), + /* 17 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.Metadata = void 0; + + var _util = __w_pdfjs_require__(1); + + class Metadata { + #metadataMap; + #data; + + constructor({ + parsedData, + rawData + }) { + this.#metadataMap = parsedData; + this.#data = rawData; + } + + getRaw() { + return this.#data; + } + + get(name) { + return this.#metadataMap.get(name) ?? null; + } + + getAll() { + return (0, _util.objectFromMap)(this.#metadataMap); + } + + has(name) { + return this.#metadataMap.has(name); + } + + } + + exports.Metadata = Metadata; + + /***/ }), + /* 18 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.OptionalContentConfig = void 0; + + var _util = __w_pdfjs_require__(1); + + const INTERNAL = Symbol("INTERNAL"); + + class OptionalContentGroup { + #visible = true; + + constructor(name, intent) { + this.name = name; + this.intent = intent; + } + + get visible() { + return this.#visible; + } + + _setVisible(internal, visible) { + if (internal !== INTERNAL) { + (0, _util.unreachable)("Internal method `_setVisible` called."); + } + + this.#visible = visible; + } + + } + + class OptionalContentConfig { + #cachedHasInitialVisibility = true; + #groups = new Map(); + #initialVisibility = null; + #order = null; + + constructor(data) { + this.name = null; + this.creator = null; + + if (data === null) { + return; + } + + this.name = data.name; + this.creator = data.creator; + this.#order = data.order; + + for (const group of data.groups) { + this.#groups.set(group.id, new OptionalContentGroup(group.name, group.intent)); + } + + if (data.baseState === "OFF") { + for (const group of this.#groups.values()) { + group._setVisible(INTERNAL, false); + } + } + + for (const on of data.on) { + this.#groups.get(on)._setVisible(INTERNAL, true); + } + + for (const off of data.off) { + this.#groups.get(off)._setVisible(INTERNAL, false); + } + + this.#initialVisibility = new Map(); + + for (const [id, group] of this.#groups) { + this.#initialVisibility.set(id, group.visible); + } + } + + #evaluateVisibilityExpression(array) { + const length = array.length; + + if (length < 2) { + return true; + } + + const operator = array[0]; + + for (let i = 1; i < length; i++) { + const element = array[i]; + let state; + + if (Array.isArray(element)) { + state = this.#evaluateVisibilityExpression(element); + } else if (this.#groups.has(element)) { + state = this.#groups.get(element).visible; + } else { + (0, _util.warn)(`Optional content group not found: ${element}`); + return true; + } + + switch (operator) { + case "And": + if (!state) { + return false; + } + + break; + + case "Or": + if (state) { + return true; + } + + break; + + case "Not": + return !state; + + default: + return true; + } + } + + return operator === "And"; + } + + isVisible(group) { + if (this.#groups.size === 0) { + return true; + } + + if (!group) { + (0, _util.warn)("Optional content group not defined."); + return true; + } + + if (group.type === "OCG") { + if (!this.#groups.has(group.id)) { + (0, _util.warn)(`Optional content group not found: ${group.id}`); + return true; + } + + return this.#groups.get(group.id).visible; + } else if (group.type === "OCMD") { + if (group.expression) { + return this.#evaluateVisibilityExpression(group.expression); + } + + if (!group.policy || group.policy === "AnyOn") { + for (const id of group.ids) { + if (!this.#groups.has(id)) { + (0, _util.warn)(`Optional content group not found: ${id}`); + return true; + } + + if (this.#groups.get(id).visible) { + return true; + } + } + + return false; + } else if (group.policy === "AllOn") { + for (const id of group.ids) { + if (!this.#groups.has(id)) { + (0, _util.warn)(`Optional content group not found: ${id}`); + return true; + } + + if (!this.#groups.get(id).visible) { + return false; + } + } + + return true; + } else if (group.policy === "AnyOff") { + for (const id of group.ids) { + if (!this.#groups.has(id)) { + (0, _util.warn)(`Optional content group not found: ${id}`); + return true; + } + + if (!this.#groups.get(id).visible) { + return true; + } + } + + return false; + } else if (group.policy === "AllOff") { + for (const id of group.ids) { + if (!this.#groups.has(id)) { + (0, _util.warn)(`Optional content group not found: ${id}`); + return true; + } + + if (this.#groups.get(id).visible) { + return false; + } + } + + return true; + } + + (0, _util.warn)(`Unknown optional content policy ${group.policy}.`); + return true; + } + + (0, _util.warn)(`Unknown group type ${group.type}.`); + return true; + } + + setVisibility(id, visible = true) { + if (!this.#groups.has(id)) { + (0, _util.warn)(`Optional content group not found: ${id}`); + return; + } + + this.#groups.get(id)._setVisible(INTERNAL, !!visible); + + this.#cachedHasInitialVisibility = null; + } + + get hasInitialVisibility() { + if (this.#cachedHasInitialVisibility !== null) { + return this.#cachedHasInitialVisibility; + } + + for (const [id, group] of this.#groups) { + const visible = this.#initialVisibility.get(id); + + if (group.visible !== visible) { + return this.#cachedHasInitialVisibility = false; + } + } + + return this.#cachedHasInitialVisibility = true; + } + + getOrder() { + if (!this.#groups.size) { + return null; + } + + if (this.#order) { + return this.#order.slice(); + } + + return [...this.#groups.keys()]; + } + + getGroups() { + return this.#groups.size > 0 ? (0, _util.objectFromMap)(this.#groups) : null; + } + + getGroup(id) { + return this.#groups.get(id) || null; + } + + } + + exports.OptionalContentConfig = OptionalContentConfig; + + /***/ }), + /* 19 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.PDFDataTransportStream = void 0; + + var _util = __w_pdfjs_require__(1); + + var _display_utils = __w_pdfjs_require__(8); + + class PDFDataTransportStream { + constructor(params, pdfDataRangeTransport) { + (0, _util.assert)(pdfDataRangeTransport, 'PDFDataTransportStream - missing required "pdfDataRangeTransport" argument.'); + this._queuedChunks = []; + this._progressiveDone = params.progressiveDone || false; + this._contentDispositionFilename = params.contentDispositionFilename || null; + const initialData = params.initialData; + + if (initialData?.length > 0) { + const buffer = new Uint8Array(initialData).buffer; + + this._queuedChunks.push(buffer); + } + + this._pdfDataRangeTransport = pdfDataRangeTransport; + this._isStreamingSupported = !params.disableStream; + this._isRangeSupported = !params.disableRange; + this._contentLength = params.length; + this._fullRequestReader = null; + this._rangeReaders = []; + + this._pdfDataRangeTransport.addRangeListener((begin, chunk) => { + this._onReceiveData({ + begin, + chunk + }); + }); + + this._pdfDataRangeTransport.addProgressListener((loaded, total) => { + this._onProgress({ + loaded, + total + }); + }); + + this._pdfDataRangeTransport.addProgressiveReadListener(chunk => { + this._onReceiveData({ + chunk + }); + }); + + this._pdfDataRangeTransport.addProgressiveDoneListener(() => { + this._onProgressiveDone(); + }); + + this._pdfDataRangeTransport.transportReady(); + } + + _onReceiveData(args) { + const buffer = new Uint8Array(args.chunk).buffer; + + if (args.begin === undefined) { + if (this._fullRequestReader) { + this._fullRequestReader._enqueue(buffer); + } else { + this._queuedChunks.push(buffer); + } + } else { + const found = this._rangeReaders.some(function (rangeReader) { + if (rangeReader._begin !== args.begin) { + return false; + } + + rangeReader._enqueue(buffer); + + return true; + }); + + (0, _util.assert)(found, "_onReceiveData - no `PDFDataTransportStreamRangeReader` instance found."); + } + } + + get _progressiveDataLength() { + return this._fullRequestReader?._loaded ?? 0; + } + + _onProgress(evt) { + if (evt.total === undefined) { + const firstReader = this._rangeReaders[0]; + + if (firstReader?.onProgress) { + firstReader.onProgress({ + loaded: evt.loaded + }); + } + } else { + const fullReader = this._fullRequestReader; + + if (fullReader?.onProgress) { + fullReader.onProgress({ + loaded: evt.loaded, + total: evt.total + }); + } + } + } + + _onProgressiveDone() { + if (this._fullRequestReader) { + this._fullRequestReader.progressiveDone(); + } + + this._progressiveDone = true; + } + + _removeRangeReader(reader) { + const i = this._rangeReaders.indexOf(reader); + + if (i >= 0) { + this._rangeReaders.splice(i, 1); + } + } + + getFullReader() { + (0, _util.assert)(!this._fullRequestReader, "PDFDataTransportStream.getFullReader can only be called once."); + const queuedChunks = this._queuedChunks; + this._queuedChunks = null; + return new PDFDataTransportStreamReader(this, queuedChunks, this._progressiveDone, this._contentDispositionFilename); + } + + getRangeReader(begin, end) { + if (end <= this._progressiveDataLength) { + return null; + } + + const reader = new PDFDataTransportStreamRangeReader(this, begin, end); + + this._pdfDataRangeTransport.requestDataRange(begin, end); + + this._rangeReaders.push(reader); + + return reader; + } + + cancelAllRequests(reason) { + if (this._fullRequestReader) { + this._fullRequestReader.cancel(reason); + } + + for (const reader of this._rangeReaders.slice(0)) { + reader.cancel(reason); + } + + this._pdfDataRangeTransport.abort(); + } + + } + + exports.PDFDataTransportStream = PDFDataTransportStream; + + class PDFDataTransportStreamReader { + constructor(stream, queuedChunks, progressiveDone = false, contentDispositionFilename = null) { + this._stream = stream; + this._done = progressiveDone || false; + this._filename = (0, _display_utils.isPdfFile)(contentDispositionFilename) ? contentDispositionFilename : null; + this._queuedChunks = queuedChunks || []; + this._loaded = 0; + + for (const chunk of this._queuedChunks) { + this._loaded += chunk.byteLength; + } + + this._requests = []; + this._headersReady = Promise.resolve(); + stream._fullRequestReader = this; + this.onProgress = null; + } + + _enqueue(chunk) { + if (this._done) { + return; + } + + if (this._requests.length > 0) { + const requestCapability = this._requests.shift(); + + requestCapability.resolve({ + value: chunk, + done: false + }); + } else { + this._queuedChunks.push(chunk); + } + + this._loaded += chunk.byteLength; + } + + get headersReady() { + return this._headersReady; + } + + get filename() { + return this._filename; + } + + get isRangeSupported() { + return this._stream._isRangeSupported; + } + + get isStreamingSupported() { + return this._stream._isStreamingSupported; + } + + get contentLength() { + return this._stream._contentLength; + } + + async read() { + if (this._queuedChunks.length > 0) { + const chunk = this._queuedChunks.shift(); + + return { + value: chunk, + done: false + }; + } + + if (this._done) { + return { + value: undefined, + done: true + }; + } + + const requestCapability = (0, _util.createPromiseCapability)(); + + this._requests.push(requestCapability); + + return requestCapability.promise; + } + + cancel(reason) { + this._done = true; + + for (const requestCapability of this._requests) { + requestCapability.resolve({ + value: undefined, + done: true + }); + } + + this._requests.length = 0; + } + + progressiveDone() { + if (this._done) { + return; + } + + this._done = true; + } + + } + + class PDFDataTransportStreamRangeReader { + constructor(stream, begin, end) { + this._stream = stream; + this._begin = begin; + this._end = end; + this._queuedChunk = null; + this._requests = []; + this._done = false; + this.onProgress = null; + } + + _enqueue(chunk) { + if (this._done) { + return; + } + + if (this._requests.length === 0) { + this._queuedChunk = chunk; + } else { + const requestsCapability = this._requests.shift(); + + requestsCapability.resolve({ + value: chunk, + done: false + }); + + for (const requestCapability of this._requests) { + requestCapability.resolve({ + value: undefined, + done: true + }); + } + + this._requests.length = 0; + } + + this._done = true; + + this._stream._removeRangeReader(this); + } + + get isStreamingSupported() { + return false; + } + + async read() { + if (this._queuedChunk) { + const chunk = this._queuedChunk; + this._queuedChunk = null; + return { + value: chunk, + done: false + }; + } + + if (this._done) { + return { + value: undefined, + done: true + }; + } + + const requestCapability = (0, _util.createPromiseCapability)(); + + this._requests.push(requestCapability); + + return requestCapability.promise; + } + + cancel(reason) { + this._done = true; + + for (const requestCapability of this._requests) { + requestCapability.resolve({ + value: undefined, + done: true + }); + } + + this._requests.length = 0; + + this._stream._removeRangeReader(this); + } + + } + + /***/ }), + /* 20 */ + /***/ ((__unused_webpack_module, exports) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.XfaText = void 0; + + class XfaText { + static textContent(xfa) { + const items = []; + const output = { + items, + styles: Object.create(null) + }; + + function walk(node) { + if (!node) { + return; + } + + let str = null; + const name = node.name; + + if (name === "#text") { + str = node.value; + } else if (!XfaText.shouldBuildText(name)) { + return; + } else if (node?.attributes?.textContent) { + str = node.attributes.textContent; + } else if (node.value) { + str = node.value; + } + + if (str !== null) { + items.push({ + str + }); + } + + if (!node.children) { + return; + } + + for (const child of node.children) { + walk(child); + } + } + + walk(xfa); + return output; + } + + static shouldBuildText(name) { + return !(name === "textarea" || name === "input" || name === "option" || name === "select"); + } + + } + + exports.XfaText = XfaText; + + /***/ }), + /* 21 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.NodeStandardFontDataFactory = exports.NodeCanvasFactory = exports.NodeCMapReaderFactory = void 0; + + var _base_factory = __w_pdfjs_require__(9); + + const fetchData = function (url) { + return new Promise((resolve, reject) => { + const fs = require$$5; + + fs.readFile(url, (error, data) => { + if (error || !data) { + reject(new Error(error)); + return; + } + + resolve(new Uint8Array(data)); + }); + }); + }; + + class NodeCanvasFactory extends _base_factory.BaseCanvasFactory { + _createCanvas(width, height) { + const Canvas = require$$5; + + return Canvas.createCanvas(width, height); + } + + } + + exports.NodeCanvasFactory = NodeCanvasFactory; + + class NodeCMapReaderFactory extends _base_factory.BaseCMapReaderFactory { + _fetchData(url, compressionType) { + return fetchData(url).then(data => { + return { + cMapData: data, + compressionType + }; + }); + } + + } + + exports.NodeCMapReaderFactory = NodeCMapReaderFactory; + + class NodeStandardFontDataFactory extends _base_factory.BaseStandardFontDataFactory { + _fetchData(url) { + return fetchData(url); + } + + } + + exports.NodeStandardFontDataFactory = NodeStandardFontDataFactory; + + /***/ }), + /* 22 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.AnnotationEditorLayer = void 0; + + var _tools = __w_pdfjs_require__(7); + + var _util = __w_pdfjs_require__(1); + + var _freetext = __w_pdfjs_require__(23); + + var _ink = __w_pdfjs_require__(24); + + class AnnotationEditorLayer { + #accessibilityManager; + #allowClick = false; + #boundPointerup = this.pointerup.bind(this); + #boundPointerdown = this.pointerdown.bind(this); + #editors = new Map(); + #hadPointerDown = false; + #isCleaningUp = false; + #uiManager; + static _initialized = false; + + constructor(options) { + if (!AnnotationEditorLayer._initialized) { + AnnotationEditorLayer._initialized = true; + + _freetext.FreeTextEditor.initialize(options.l10n); + + _ink.InkEditor.initialize(options.l10n); + + options.uiManager.registerEditorTypes([_freetext.FreeTextEditor, _ink.InkEditor]); + } + + this.#uiManager = options.uiManager; + this.annotationStorage = options.annotationStorage; + this.pageIndex = options.pageIndex; + this.div = options.div; + this.#accessibilityManager = options.accessibilityManager; + this.#uiManager.addLayer(this); + } + + updateToolbar(mode) { + this.#uiManager.updateToolbar(mode); + } + + updateMode(mode = this.#uiManager.getMode()) { + this.#cleanup(); + + if (mode === _util.AnnotationEditorType.INK) { + this.addInkEditorIfNeeded(false); + this.disableClick(); + } else { + this.enableClick(); + } + + this.#uiManager.unselectAll(); + } + + addInkEditorIfNeeded(isCommitting) { + if (!isCommitting && this.#uiManager.getMode() !== _util.AnnotationEditorType.INK) { + return; + } + + if (!isCommitting) { + for (const editor of this.#editors.values()) { + if (editor.isEmpty()) { + editor.setInBackground(); + return; + } + } + } + + const editor = this.#createAndAddNewEditor({ + offsetX: 0, + offsetY: 0 + }); + editor.setInBackground(); + } + + setEditingState(isEditing) { + this.#uiManager.setEditingState(isEditing); + } + + addCommands(params) { + this.#uiManager.addCommands(params); + } + + enable() { + this.div.style.pointerEvents = "auto"; + + for (const editor of this.#editors.values()) { + editor.enableEditing(); + } + } + + disable() { + this.div.style.pointerEvents = "none"; + + for (const editor of this.#editors.values()) { + editor.disableEditing(); + } + } + + setActiveEditor(editor) { + const currentActive = this.#uiManager.getActive(); + + if (currentActive === editor) { + return; + } + + this.#uiManager.setActiveEditor(editor); + } + + enableClick() { + this.div.addEventListener("pointerdown", this.#boundPointerdown); + this.div.addEventListener("pointerup", this.#boundPointerup); + } + + disableClick() { + this.div.removeEventListener("pointerdown", this.#boundPointerdown); + this.div.removeEventListener("pointerup", this.#boundPointerup); + } + + attach(editor) { + this.#editors.set(editor.id, editor); + } + + detach(editor) { + this.#editors.delete(editor.id); + this.#accessibilityManager?.removePointerInTextLayer(editor.contentDiv); + } + + remove(editor) { + this.#uiManager.removeEditor(editor); + this.detach(editor); + this.annotationStorage.remove(editor.id); + editor.div.style.display = "none"; + setTimeout(() => { + editor.div.style.display = ""; + editor.div.remove(); + editor.isAttachedToDOM = false; + + if (document.activeElement === document.body) { + this.#uiManager.focusMainContainer(); + } + }, 0); + + if (!this.#isCleaningUp) { + this.addInkEditorIfNeeded(false); + } + } + + #changeParent(editor) { + if (editor.parent === this) { + return; + } + + this.attach(editor); + editor.pageIndex = this.pageIndex; + editor.parent?.detach(editor); + editor.parent = this; + + if (editor.div && editor.isAttachedToDOM) { + editor.div.remove(); + this.div.append(editor.div); + } + } + + add(editor) { + this.#changeParent(editor); + this.#uiManager.addEditor(editor); + this.attach(editor); + + if (!editor.isAttachedToDOM) { + const div = editor.render(); + this.div.append(div); + editor.isAttachedToDOM = true; + } + + this.moveEditorInDOM(editor); + editor.onceAdded(); + this.addToAnnotationStorage(editor); + } + + moveEditorInDOM(editor) { + this.#accessibilityManager?.moveElementInDOM(this.div, editor.div, editor.contentDiv, true); + } + + addToAnnotationStorage(editor) { + if (!editor.isEmpty() && !this.annotationStorage.has(editor.id)) { + this.annotationStorage.setValue(editor.id, editor); + } + } + + addOrRebuild(editor) { + if (editor.needsToBeRebuilt()) { + editor.rebuild(); + } else { + this.add(editor); + } + } + + addANewEditor(editor) { + const cmd = () => { + this.addOrRebuild(editor); + }; + + const undo = () => { + editor.remove(); + }; + + this.addCommands({ + cmd, + undo, + mustExec: true + }); + } + + addUndoableEditor(editor) { + const cmd = () => { + this.addOrRebuild(editor); + }; + + const undo = () => { + editor.remove(); + }; + + this.addCommands({ + cmd, + undo, + mustExec: false + }); + } + + getNextId() { + return this.#uiManager.getId(); + } + + #createNewEditor(params) { + switch (this.#uiManager.getMode()) { + case _util.AnnotationEditorType.FREETEXT: + return new _freetext.FreeTextEditor(params); + + case _util.AnnotationEditorType.INK: + return new _ink.InkEditor(params); + } + + return null; + } + + deserialize(data) { + switch (data.annotationType) { + case _util.AnnotationEditorType.FREETEXT: + return _freetext.FreeTextEditor.deserialize(data, this); + + case _util.AnnotationEditorType.INK: + return _ink.InkEditor.deserialize(data, this); + } + + return null; + } + + #createAndAddNewEditor(event) { + const id = this.getNextId(); + const editor = this.#createNewEditor({ + parent: this, + id, + x: event.offsetX, + y: event.offsetY + }); + + if (editor) { + this.add(editor); + } + + return editor; + } + + setSelected(editor) { + this.#uiManager.setSelected(editor); + } + + toggleSelected(editor) { + this.#uiManager.toggleSelected(editor); + } + + isSelected(editor) { + return this.#uiManager.isSelected(editor); + } + + unselect(editor) { + this.#uiManager.unselect(editor); + } + + pointerup(event) { + const isMac = _tools.KeyboardManager.platform.isMac; + + if (event.button !== 0 || event.ctrlKey && isMac) { + return; + } + + if (event.target !== this.div) { + return; + } + + if (!this.#hadPointerDown) { + return; + } + + this.#hadPointerDown = false; + + if (!this.#allowClick) { + this.#allowClick = true; + return; + } + + this.#createAndAddNewEditor(event); + } + + pointerdown(event) { + const isMac = _tools.KeyboardManager.platform.isMac; + + if (event.button !== 0 || event.ctrlKey && isMac) { + return; + } + + if (event.target !== this.div) { + return; + } + + this.#hadPointerDown = true; + const editor = this.#uiManager.getActive(); + this.#allowClick = !editor || editor.isEmpty(); + } + + drop(event) { + const id = event.dataTransfer.getData("text/plain"); + const editor = this.#uiManager.getEditor(id); + + if (!editor) { + return; + } + + event.preventDefault(); + event.dataTransfer.dropEffect = "move"; + this.#changeParent(editor); + const rect = this.div.getBoundingClientRect(); + const endX = event.clientX - rect.x; + const endY = event.clientY - rect.y; + editor.translate(endX - editor.startX, endY - editor.startY); + this.moveEditorInDOM(editor); + editor.div.focus(); + } + + dragover(event) { + event.preventDefault(); + } + + destroy() { + if (this.#uiManager.getActive()?.parent === this) { + this.#uiManager.setActiveEditor(null); + } + + for (const editor of this.#editors.values()) { + this.#accessibilityManager?.removePointerInTextLayer(editor.contentDiv); + editor.isAttachedToDOM = false; + editor.div.remove(); + editor.parent = null; + } + + this.div = null; + this.#editors.clear(); + this.#uiManager.removeLayer(this); + } + + #cleanup() { + this.#isCleaningUp = true; + + for (const editor of this.#editors.values()) { + if (editor.isEmpty()) { + editor.remove(); + } + } + + this.#isCleaningUp = false; + } + + render(parameters) { + this.viewport = parameters.viewport; + (0, _tools.bindEvents)(this, this.div, ["dragover", "drop"]); + this.setDimensions(); + + for (const editor of this.#uiManager.getEditors(this.pageIndex)) { + this.add(editor); + } + + this.updateMode(); + } + + update(parameters) { + this.viewport = parameters.viewport; + this.setDimensions(); + this.updateMode(); + } + + get scaleFactor() { + return this.viewport.scale; + } + + get pageDimensions() { + const [pageLLx, pageLLy, pageURx, pageURy] = this.viewport.viewBox; + const width = pageURx - pageLLx; + const height = pageURy - pageLLy; + return [width, height]; + } + + get viewportBaseDimensions() { + const { + width, + height, + rotation + } = this.viewport; + return rotation % 180 === 0 ? [width, height] : [height, width]; + } + + setDimensions() { + const { + width, + height, + rotation + } = this.viewport; + const flipOrientation = rotation % 180 !== 0, + widthStr = Math.floor(width) + "px", + heightStr = Math.floor(height) + "px"; + this.div.style.width = flipOrientation ? heightStr : widthStr; + this.div.style.height = flipOrientation ? widthStr : heightStr; + this.div.setAttribute("data-main-rotation", rotation); + } + + } + + exports.AnnotationEditorLayer = AnnotationEditorLayer; + + /***/ }), + /* 23 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.FreeTextEditor = void 0; + + var _util = __w_pdfjs_require__(1); + + var _tools = __w_pdfjs_require__(7); + + var _editor = __w_pdfjs_require__(6); + + class FreeTextEditor extends _editor.AnnotationEditor { + #boundEditorDivBlur = this.editorDivBlur.bind(this); + #boundEditorDivFocus = this.editorDivFocus.bind(this); + #boundEditorDivKeydown = this.editorDivKeydown.bind(this); + #color; + #content = ""; + #hasAlreadyBeenCommitted = false; + #fontSize; + static _freeTextDefaultContent = ""; + static _l10nPromise; + static _internalPadding = 0; + static _defaultColor = null; + static _defaultFontSize = 10; + static _keyboardManager = new _tools.KeyboardManager([[["ctrl+Enter", "mac+meta+Enter", "Escape", "mac+Escape"], FreeTextEditor.prototype.commitOrRemove]]); + static _type = "freetext"; + + constructor(params) { + super({ ...params, + name: "freeTextEditor" + }); + this.#color = params.color || FreeTextEditor._defaultColor || _editor.AnnotationEditor._defaultLineColor; + this.#fontSize = params.fontSize || FreeTextEditor._defaultFontSize; + } + + static initialize(l10n) { + this._l10nPromise = new Map(["free_text_default_content", "editor_free_text_aria_label"].map(str => [str, l10n.get(str)])); + const style = getComputedStyle(document.documentElement); + this._internalPadding = parseFloat(style.getPropertyValue("--freetext-padding")); + } + + static updateDefaultParams(type, value) { + switch (type) { + case _util.AnnotationEditorParamsType.FREETEXT_SIZE: + FreeTextEditor._defaultFontSize = value; + break; + + case _util.AnnotationEditorParamsType.FREETEXT_COLOR: + FreeTextEditor._defaultColor = value; + break; + } + } + + updateParams(type, value) { + switch (type) { + case _util.AnnotationEditorParamsType.FREETEXT_SIZE: + this.#updateFontSize(value); + break; + + case _util.AnnotationEditorParamsType.FREETEXT_COLOR: + this.#updateColor(value); + break; + } + } + + static get defaultPropertiesToUpdate() { + return [[_util.AnnotationEditorParamsType.FREETEXT_SIZE, FreeTextEditor._defaultFontSize], [_util.AnnotationEditorParamsType.FREETEXT_COLOR, FreeTextEditor._defaultColor || _editor.AnnotationEditor._defaultLineColor]]; + } + + get propertiesToUpdate() { + return [[_util.AnnotationEditorParamsType.FREETEXT_SIZE, this.#fontSize], [_util.AnnotationEditorParamsType.FREETEXT_COLOR, this.#color]]; + } + + #updateFontSize(fontSize) { + const setFontsize = size => { + this.editorDiv.style.fontSize = `calc(${size}px * var(--scale-factor))`; + this.translate(0, -(size - this.#fontSize) * this.parent.scaleFactor); + this.#fontSize = size; + this.#setEditorDimensions(); + }; + + const savedFontsize = this.#fontSize; + this.parent.addCommands({ + cmd: () => { + setFontsize(fontSize); + }, + undo: () => { + setFontsize(savedFontsize); + }, + mustExec: true, + type: _util.AnnotationEditorParamsType.FREETEXT_SIZE, + overwriteIfSameType: true, + keepUndo: true + }); + } + + #updateColor(color) { + const savedColor = this.#color; + this.parent.addCommands({ + cmd: () => { + this.#color = color; + this.editorDiv.style.color = color; + }, + undo: () => { + this.#color = savedColor; + this.editorDiv.style.color = savedColor; + }, + mustExec: true, + type: _util.AnnotationEditorParamsType.FREETEXT_COLOR, + overwriteIfSameType: true, + keepUndo: true + }); + } + + getInitialTranslation() { + return [-FreeTextEditor._internalPadding * this.parent.scaleFactor, -(FreeTextEditor._internalPadding + this.#fontSize) * this.parent.scaleFactor]; + } + + rebuild() { + super.rebuild(); + + if (this.div === null) { + return; + } + + if (!this.isAttachedToDOM) { + this.parent.add(this); + } + } + + enableEditMode() { + if (this.isInEditMode()) { + return; + } + + this.parent.setEditingState(false); + this.parent.updateToolbar(_util.AnnotationEditorType.FREETEXT); + super.enableEditMode(); + this.enableEditing(); + this.overlayDiv.classList.remove("enabled"); + this.editorDiv.contentEditable = true; + this.div.draggable = false; + this.editorDiv.addEventListener("keydown", this.#boundEditorDivKeydown); + this.editorDiv.addEventListener("focus", this.#boundEditorDivFocus); + this.editorDiv.addEventListener("blur", this.#boundEditorDivBlur); + } + + disableEditMode() { + if (!this.isInEditMode()) { + return; + } + + this.parent.setEditingState(true); + super.disableEditMode(); + this.disableEditing(); + this.overlayDiv.classList.add("enabled"); + this.editorDiv.contentEditable = false; + this.div.draggable = true; + this.editorDiv.removeEventListener("keydown", this.#boundEditorDivKeydown); + this.editorDiv.removeEventListener("focus", this.#boundEditorDivFocus); + this.editorDiv.removeEventListener("blur", this.#boundEditorDivBlur); + this.div.focus(); + this.isEditing = false; + } + + focusin(event) { + super.focusin(event); + + if (event.target !== this.editorDiv) { + this.editorDiv.focus(); + } + } + + onceAdded() { + if (this.width) { + return; + } + + this.enableEditMode(); + this.editorDiv.focus(); + } + + isEmpty() { + return !this.editorDiv || this.editorDiv.innerText.trim() === ""; + } + + remove() { + this.isEditing = false; + this.parent.setEditingState(true); + super.remove(); + } + + #extractText() { + const divs = this.editorDiv.getElementsByTagName("div"); + + if (divs.length === 0) { + return this.editorDiv.innerText; + } + + const buffer = []; + + for (let i = 0, ii = divs.length; i < ii; i++) { + const div = divs[i]; + const first = div.firstChild; + + if (first?.nodeName === "#text") { + buffer.push(first.data); + } else { + buffer.push(""); + } + } + + return buffer.join("\n"); + } + + #setEditorDimensions() { + const [parentWidth, parentHeight] = this.parent.viewportBaseDimensions; + const rect = this.div.getBoundingClientRect(); + this.width = rect.width / parentWidth; + this.height = rect.height / parentHeight; + } + + commit() { + super.commit(); + + if (!this.#hasAlreadyBeenCommitted) { + this.#hasAlreadyBeenCommitted = true; + this.parent.addUndoableEditor(this); + } + + this.disableEditMode(); + this.#content = this.#extractText().trimEnd(); + this.#setEditorDimensions(); + } + + shouldGetKeyboardEvents() { + return this.isInEditMode(); + } + + dblclick(event) { + this.enableEditMode(); + this.editorDiv.focus(); + } + + keydown(event) { + if (event.target === this.div && event.key === "Enter") { + this.enableEditMode(); + this.editorDiv.focus(); + } + } + + editorDivKeydown(event) { + FreeTextEditor._keyboardManager.exec(this, event); + } + + editorDivFocus(event) { + this.isEditing = true; + } + + editorDivBlur(event) { + this.isEditing = false; + } + + disableEditing() { + this.editorDiv.setAttribute("role", "comment"); + this.editorDiv.removeAttribute("aria-multiline"); + } + + enableEditing() { + this.editorDiv.setAttribute("role", "textbox"); + this.editorDiv.setAttribute("aria-multiline", true); + } + + render() { + if (this.div) { + return this.div; + } + + let baseX, baseY; + + if (this.width) { + baseX = this.x; + baseY = this.y; + } + + super.render(); + this.editorDiv = document.createElement("div"); + this.editorDiv.className = "internal"; + this.editorDiv.setAttribute("id", `${this.id}-editor`); + this.enableEditing(); + + FreeTextEditor._l10nPromise.get("editor_free_text_aria_label").then(msg => this.editorDiv?.setAttribute("aria-label", msg)); + + FreeTextEditor._l10nPromise.get("free_text_default_content").then(msg => this.editorDiv?.setAttribute("default-content", msg)); + + this.editorDiv.contentEditable = true; + const { + style + } = this.editorDiv; + style.fontSize = `calc(${this.#fontSize}px * var(--scale-factor))`; + style.color = this.#color; + this.div.append(this.editorDiv); + this.overlayDiv = document.createElement("div"); + this.overlayDiv.classList.add("overlay", "enabled"); + this.div.append(this.overlayDiv); + (0, _tools.bindEvents)(this, this.div, ["dblclick", "keydown"]); + + if (this.width) { + const [parentWidth, parentHeight] = this.parent.viewportBaseDimensions; + this.setAt(baseX * parentWidth, baseY * parentHeight, this.width * parentWidth, this.height * parentHeight); + + for (const line of this.#content.split("\n")) { + const div = document.createElement("div"); + div.append(line ? document.createTextNode(line) : document.createElement("br")); + this.editorDiv.append(div); + } + + this.div.draggable = true; + this.editorDiv.contentEditable = false; + } else { + this.div.draggable = false; + this.editorDiv.contentEditable = true; + } + + return this.div; + } + + get contentDiv() { + return this.editorDiv; + } + + static deserialize(data, parent) { + const editor = super.deserialize(data, parent); + editor.#fontSize = data.fontSize; + editor.#color = _util.Util.makeHexColor(...data.color); + editor.#content = data.value; + return editor; + } + + serialize() { + if (this.isEmpty()) { + return null; + } + + const padding = FreeTextEditor._internalPadding * this.parent.scaleFactor; + const rect = this.getRect(padding, padding); + + const color = _editor.AnnotationEditor._colorManager.convert(getComputedStyle(this.editorDiv).color); + + return { + annotationType: _util.AnnotationEditorType.FREETEXT, + color, + fontSize: this.#fontSize, + value: this.#content, + pageIndex: this.parent.pageIndex, + rect, + rotation: this.rotation + }; + } + + } + + exports.FreeTextEditor = FreeTextEditor; + + /***/ }), + /* 24 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.InkEditor = void 0; + Object.defineProperty(exports, "fitCurve", ({ + enumerable: true, + get: function () { + return _pdfjsFitCurve.fitCurve; + } + })); + + var _util = __w_pdfjs_require__(1); + + var _editor = __w_pdfjs_require__(6); + + var _pdfjsFitCurve = __w_pdfjs_require__(25); + + var _tools = __w_pdfjs_require__(7); + + const RESIZER_SIZE = 16; + + class InkEditor extends _editor.AnnotationEditor { + #aspectRatio = 0; + #baseHeight = 0; + #baseWidth = 0; + #boundCanvasPointermove = this.canvasPointermove.bind(this); + #boundCanvasPointerleave = this.canvasPointerleave.bind(this); + #boundCanvasPointerup = this.canvasPointerup.bind(this); + #boundCanvasPointerdown = this.canvasPointerdown.bind(this); + #disableEditing = false; + #isCanvasInitialized = false; + #lastPoint = null; + #observer = null; + #realWidth = 0; + #realHeight = 0; + #requestFrameCallback = null; + static _defaultColor = null; + static _defaultOpacity = 1; + static _defaultThickness = 1; + static _l10nPromise; + static _type = "ink"; + + constructor(params) { + super({ ...params, + name: "inkEditor" + }); + this.color = params.color || null; + this.thickness = params.thickness || null; + this.opacity = params.opacity || null; + this.paths = []; + this.bezierPath2D = []; + this.currentPath = []; + this.scaleFactor = 1; + this.translationX = this.translationY = 0; + this.x = 0; + this.y = 0; + } + + static initialize(l10n) { + this._l10nPromise = new Map(["editor_ink_canvas_aria_label", "editor_ink_aria_label"].map(str => [str, l10n.get(str)])); + } + + static updateDefaultParams(type, value) { + switch (type) { + case _util.AnnotationEditorParamsType.INK_THICKNESS: + InkEditor._defaultThickness = value; + break; + + case _util.AnnotationEditorParamsType.INK_COLOR: + InkEditor._defaultColor = value; + break; + + case _util.AnnotationEditorParamsType.INK_OPACITY: + InkEditor._defaultOpacity = value / 100; + break; + } + } + + updateParams(type, value) { + switch (type) { + case _util.AnnotationEditorParamsType.INK_THICKNESS: + this.#updateThickness(value); + break; + + case _util.AnnotationEditorParamsType.INK_COLOR: + this.#updateColor(value); + break; + + case _util.AnnotationEditorParamsType.INK_OPACITY: + this.#updateOpacity(value); + break; + } + } + + static get defaultPropertiesToUpdate() { + return [[_util.AnnotationEditorParamsType.INK_THICKNESS, InkEditor._defaultThickness], [_util.AnnotationEditorParamsType.INK_COLOR, InkEditor._defaultColor || _editor.AnnotationEditor._defaultLineColor], [_util.AnnotationEditorParamsType.INK_OPACITY, Math.round(InkEditor._defaultOpacity * 100)]]; + } + + get propertiesToUpdate() { + return [[_util.AnnotationEditorParamsType.INK_THICKNESS, this.thickness || InkEditor._defaultThickness], [_util.AnnotationEditorParamsType.INK_COLOR, this.color || InkEditor._defaultColor || _editor.AnnotationEditor._defaultLineColor], [_util.AnnotationEditorParamsType.INK_OPACITY, Math.round(100 * (this.opacity ?? InkEditor._defaultOpacity))]]; + } + + #updateThickness(thickness) { + const savedThickness = this.thickness; + this.parent.addCommands({ + cmd: () => { + this.thickness = thickness; + this.#fitToContent(); + }, + undo: () => { + this.thickness = savedThickness; + this.#fitToContent(); + }, + mustExec: true, + type: _util.AnnotationEditorParamsType.INK_THICKNESS, + overwriteIfSameType: true, + keepUndo: true + }); + } + + #updateColor(color) { + const savedColor = this.color; + this.parent.addCommands({ + cmd: () => { + this.color = color; + this.#redraw(); + }, + undo: () => { + this.color = savedColor; + this.#redraw(); + }, + mustExec: true, + type: _util.AnnotationEditorParamsType.INK_COLOR, + overwriteIfSameType: true, + keepUndo: true + }); + } + + #updateOpacity(opacity) { + opacity /= 100; + const savedOpacity = this.opacity; + this.parent.addCommands({ + cmd: () => { + this.opacity = opacity; + this.#redraw(); + }, + undo: () => { + this.opacity = savedOpacity; + this.#redraw(); + }, + mustExec: true, + type: _util.AnnotationEditorParamsType.INK_OPACITY, + overwriteIfSameType: true, + keepUndo: true + }); + } + + rebuild() { + super.rebuild(); + + if (this.div === null) { + return; + } + + if (!this.canvas) { + this.#createCanvas(); + this.#createObserver(); + } + + if (!this.isAttachedToDOM) { + this.parent.add(this); + this.#setCanvasDims(); + } + + this.#fitToContent(); + } + + remove() { + if (this.canvas === null) { + return; + } + + if (!this.isEmpty()) { + this.commit(); + } + + this.canvas.width = this.canvas.height = 0; + this.canvas.remove(); + this.canvas = null; + this.#observer.disconnect(); + this.#observer = null; + super.remove(); + } + + enableEditMode() { + if (this.#disableEditing || this.canvas === null) { + return; + } + + super.enableEditMode(); + this.div.draggable = false; + this.canvas.addEventListener("pointerdown", this.#boundCanvasPointerdown); + this.canvas.addEventListener("pointerup", this.#boundCanvasPointerup); + } + + disableEditMode() { + if (!this.isInEditMode() || this.canvas === null) { + return; + } + + super.disableEditMode(); + this.div.draggable = !this.isEmpty(); + this.div.classList.remove("editing"); + this.canvas.removeEventListener("pointerdown", this.#boundCanvasPointerdown); + this.canvas.removeEventListener("pointerup", this.#boundCanvasPointerup); + } + + onceAdded() { + this.div.draggable = !this.isEmpty(); + } + + isEmpty() { + return this.paths.length === 0 || this.paths.length === 1 && this.paths[0].length === 0; + } + + #getInitialBBox() { + const { + width, + height, + rotation + } = this.parent.viewport; + + switch (rotation) { + case 90: + return [0, width, width, height]; + + case 180: + return [width, height, width, height]; + + case 270: + return [height, 0, width, height]; + + default: + return [0, 0, width, height]; + } + } + + #setStroke() { + this.ctx.lineWidth = this.thickness * this.parent.scaleFactor / this.scaleFactor; + this.ctx.lineCap = "round"; + this.ctx.lineJoin = "round"; + this.ctx.miterLimit = 10; + this.ctx.strokeStyle = `${this.color}${(0, _tools.opacityToHex)(this.opacity)}`; + } + + #startDrawing(x, y) { + this.isEditing = true; + + if (!this.#isCanvasInitialized) { + this.#isCanvasInitialized = true; + this.#setCanvasDims(); + this.thickness ||= InkEditor._defaultThickness; + this.color ||= InkEditor._defaultColor || _editor.AnnotationEditor._defaultLineColor; + this.opacity ??= InkEditor._defaultOpacity; + } + + this.currentPath.push([x, y]); + this.#lastPoint = null; + this.#setStroke(); + this.ctx.beginPath(); + this.ctx.moveTo(x, y); + + this.#requestFrameCallback = () => { + if (!this.#requestFrameCallback) { + return; + } + + if (this.#lastPoint) { + if (this.isEmpty()) { + this.ctx.setTransform(1, 0, 0, 1, 0, 0); + this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); + } else { + this.#redraw(); + } + + this.ctx.lineTo(...this.#lastPoint); + this.#lastPoint = null; + this.ctx.stroke(); + } + + window.requestAnimationFrame(this.#requestFrameCallback); + }; + + window.requestAnimationFrame(this.#requestFrameCallback); + } + + #draw(x, y) { + const [lastX, lastY] = this.currentPath.at(-1); + + if (x === lastX && y === lastY) { + return; + } + + this.currentPath.push([x, y]); + this.#lastPoint = [x, y]; + } + + #stopDrawing(x, y) { + this.ctx.closePath(); + this.#requestFrameCallback = null; + x = Math.min(Math.max(x, 0), this.canvas.width); + y = Math.min(Math.max(y, 0), this.canvas.height); + const [lastX, lastY] = this.currentPath.at(-1); + + if (x !== lastX || y !== lastY) { + this.currentPath.push([x, y]); + } + + let bezier; + + if (this.currentPath.length !== 1) { + bezier = (0, _pdfjsFitCurve.fitCurve)(this.currentPath, 30, null); + } else { + const xy = [x, y]; + bezier = [[xy, xy.slice(), xy.slice(), xy]]; + } + + const path2D = InkEditor.#buildPath2D(bezier); + this.currentPath.length = 0; + + const cmd = () => { + this.paths.push(bezier); + this.bezierPath2D.push(path2D); + this.rebuild(); + }; + + const undo = () => { + this.paths.pop(); + this.bezierPath2D.pop(); + + if (this.paths.length === 0) { + this.remove(); + } else { + if (!this.canvas) { + this.#createCanvas(); + this.#createObserver(); + } + + this.#fitToContent(); + } + }; + + this.parent.addCommands({ + cmd, + undo, + mustExec: true + }); + } + + #redraw() { + if (this.isEmpty()) { + this.#updateTransform(); + return; + } + + this.#setStroke(); + const { + canvas, + ctx + } = this; + ctx.setTransform(1, 0, 0, 1, 0, 0); + ctx.clearRect(0, 0, canvas.width, canvas.height); + this.#updateTransform(); + + for (const path of this.bezierPath2D) { + ctx.stroke(path); + } + } + + commit() { + if (this.#disableEditing) { + return; + } + + super.commit(); + this.isEditing = false; + this.disableEditMode(); + this.setInForeground(); + this.#disableEditing = true; + this.div.classList.add("disabled"); + this.#fitToContent(true); + this.parent.addInkEditorIfNeeded(true); + this.parent.moveEditorInDOM(this); + this.div.focus(); + } + + focusin(event) { + super.focusin(event); + this.enableEditMode(); + } + + canvasPointerdown(event) { + if (event.button !== 0 || !this.isInEditMode() || this.#disableEditing) { + return; + } + + this.setInForeground(); + + if (event.type !== "mouse") { + this.div.focus(); + } + + event.stopPropagation(); + this.canvas.addEventListener("pointerleave", this.#boundCanvasPointerleave); + this.canvas.addEventListener("pointermove", this.#boundCanvasPointermove); + this.#startDrawing(event.offsetX, event.offsetY); + } + + canvasPointermove(event) { + event.stopPropagation(); + this.#draw(event.offsetX, event.offsetY); + } + + canvasPointerup(event) { + if (event.button !== 0) { + return; + } + + if (this.isInEditMode() && this.currentPath.length !== 0) { + event.stopPropagation(); + this.#endDrawing(event); + this.setInBackground(); + } + } + + canvasPointerleave(event) { + this.#endDrawing(event); + this.setInBackground(); + } + + #endDrawing(event) { + this.#stopDrawing(event.offsetX, event.offsetY); + this.canvas.removeEventListener("pointerleave", this.#boundCanvasPointerleave); + this.canvas.removeEventListener("pointermove", this.#boundCanvasPointermove); + this.parent.addToAnnotationStorage(this); + } + + #createCanvas() { + this.canvas = document.createElement("canvas"); + this.canvas.width = this.canvas.height = 0; + this.canvas.className = "inkEditorCanvas"; + + InkEditor._l10nPromise.get("editor_ink_canvas_aria_label").then(msg => this.canvas?.setAttribute("aria-label", msg)); + + this.div.append(this.canvas); + this.ctx = this.canvas.getContext("2d"); + } + + #createObserver() { + this.#observer = new ResizeObserver(entries => { + const rect = entries[0].contentRect; + + if (rect.width && rect.height) { + this.setDimensions(rect.width, rect.height); + } + }); + this.#observer.observe(this.div); + } + + render() { + if (this.div) { + return this.div; + } + + let baseX, baseY; + + if (this.width) { + baseX = this.x; + baseY = this.y; + } + + super.render(); + + InkEditor._l10nPromise.get("editor_ink_aria_label").then(msg => this.div?.setAttribute("aria-label", msg)); + + const [x, y, w, h] = this.#getInitialBBox(); + this.setAt(x, y, 0, 0); + this.setDims(w, h); + this.#createCanvas(); + + if (this.width) { + const [parentWidth, parentHeight] = this.parent.viewportBaseDimensions; + this.setAt(baseX * parentWidth, baseY * parentHeight, this.width * parentWidth, this.height * parentHeight); + this.#isCanvasInitialized = true; + this.#setCanvasDims(); + this.setDims(this.width * parentWidth, this.height * parentHeight); + this.#redraw(); + this.#setMinDims(); + this.div.classList.add("disabled"); + } else { + this.div.classList.add("editing"); + this.enableEditMode(); + } + + this.#createObserver(); + return this.div; + } + + #setCanvasDims() { + if (!this.#isCanvasInitialized) { + return; + } + + const [parentWidth, parentHeight] = this.parent.viewportBaseDimensions; + this.canvas.width = Math.ceil(this.width * parentWidth); + this.canvas.height = Math.ceil(this.height * parentHeight); + this.#updateTransform(); + } + + setDimensions(width, height) { + const roundedWidth = Math.round(width); + const roundedHeight = Math.round(height); + + if (this.#realWidth === roundedWidth && this.#realHeight === roundedHeight) { + return; + } + + this.#realWidth = roundedWidth; + this.#realHeight = roundedHeight; + this.canvas.style.visibility = "hidden"; + + if (this.#aspectRatio && Math.abs(this.#aspectRatio - width / height) > 1e-2) { + height = Math.ceil(width / this.#aspectRatio); + this.setDims(width, height); + } + + const [parentWidth, parentHeight] = this.parent.viewportBaseDimensions; + this.width = width / parentWidth; + this.height = height / parentHeight; + + if (this.#disableEditing) { + this.#setScaleFactor(width, height); + } + + this.#setCanvasDims(); + this.#redraw(); + this.canvas.style.visibility = "visible"; + } + + #setScaleFactor(width, height) { + const padding = this.#getPadding(); + const scaleFactorW = (width - padding) / this.#baseWidth; + const scaleFactorH = (height - padding) / this.#baseHeight; + this.scaleFactor = Math.min(scaleFactorW, scaleFactorH); + } + + #updateTransform() { + const padding = this.#getPadding() / 2; + this.ctx.setTransform(this.scaleFactor, 0, 0, this.scaleFactor, this.translationX * this.scaleFactor + padding, this.translationY * this.scaleFactor + padding); + } + + static #buildPath2D(bezier) { + const path2D = new Path2D(); + + for (let i = 0, ii = bezier.length; i < ii; i++) { + const [first, control1, control2, second] = bezier[i]; + + if (i === 0) { + path2D.moveTo(...first); + } + + path2D.bezierCurveTo(control1[0], control1[1], control2[0], control2[1], second[0], second[1]); + } + + return path2D; + } + + #serializePaths(s, tx, ty, h) { + const NUMBER_OF_POINTS_ON_BEZIER_CURVE = 4; + const paths = []; + const padding = this.thickness / 2; + let buffer, points; + + for (const bezier of this.paths) { + buffer = []; + points = []; + + for (let i = 0, ii = bezier.length; i < ii; i++) { + const [first, control1, control2, second] = bezier[i]; + const p10 = s * (first[0] + tx) + padding; + const p11 = h - s * (first[1] + ty) - padding; + const p20 = s * (control1[0] + tx) + padding; + const p21 = h - s * (control1[1] + ty) - padding; + const p30 = s * (control2[0] + tx) + padding; + const p31 = h - s * (control2[1] + ty) - padding; + const p40 = s * (second[0] + tx) + padding; + const p41 = h - s * (second[1] + ty) - padding; + + if (i === 0) { + buffer.push(p10, p11); + points.push(p10, p11); + } + + buffer.push(p20, p21, p30, p31, p40, p41); + this.#extractPointsOnBezier(p10, p11, p20, p21, p30, p31, p40, p41, NUMBER_OF_POINTS_ON_BEZIER_CURVE, points); + } + + paths.push({ + bezier: buffer, + points + }); + } + + return paths; + } + + #extractPointsOnBezier(p10, p11, p20, p21, p30, p31, p40, p41, n, points) { + if (this.#isAlmostFlat(p10, p11, p20, p21, p30, p31, p40, p41)) { + points.push(p40, p41); + return; + } + + for (let i = 1; i < n - 1; i++) { + const t = i / n; + const mt = 1 - t; + let q10 = t * p10 + mt * p20; + let q11 = t * p11 + mt * p21; + let q20 = t * p20 + mt * p30; + let q21 = t * p21 + mt * p31; + const q30 = t * p30 + mt * p40; + const q31 = t * p31 + mt * p41; + q10 = t * q10 + mt * q20; + q11 = t * q11 + mt * q21; + q20 = t * q20 + mt * q30; + q21 = t * q21 + mt * q31; + q10 = t * q10 + mt * q20; + q11 = t * q11 + mt * q21; + points.push(q10, q11); + } + + points.push(p40, p41); + } + + #isAlmostFlat(p10, p11, p20, p21, p30, p31, p40, p41) { + const tol = 10; + const ax = (3 * p20 - 2 * p10 - p40) ** 2; + const ay = (3 * p21 - 2 * p11 - p41) ** 2; + const bx = (3 * p30 - p10 - 2 * p40) ** 2; + const by = (3 * p31 - p11 - 2 * p41) ** 2; + return Math.max(ax, bx) + Math.max(ay, by) <= tol; + } + + #getBbox() { + let xMin = Infinity; + let xMax = -Infinity; + let yMin = Infinity; + let yMax = -Infinity; + + for (const path of this.paths) { + for (const [first, control1, control2, second] of path) { + const bbox = _util.Util.bezierBoundingBox(...first, ...control1, ...control2, ...second); + + xMin = Math.min(xMin, bbox[0]); + yMin = Math.min(yMin, bbox[1]); + xMax = Math.max(xMax, bbox[2]); + yMax = Math.max(yMax, bbox[3]); + } + } + + return [xMin, yMin, xMax, yMax]; + } + + #getPadding() { + return this.#disableEditing ? Math.ceil(this.thickness * this.parent.scaleFactor) : 0; + } + + #fitToContent(firstTime = false) { + if (this.isEmpty()) { + return; + } + + if (!this.#disableEditing) { + this.#redraw(); + return; + } + + const bbox = this.#getBbox(); + const padding = this.#getPadding(); + this.#baseWidth = Math.max(RESIZER_SIZE, bbox[2] - bbox[0]); + this.#baseHeight = Math.max(RESIZER_SIZE, bbox[3] - bbox[1]); + const width = Math.ceil(padding + this.#baseWidth * this.scaleFactor); + const height = Math.ceil(padding + this.#baseHeight * this.scaleFactor); + const [parentWidth, parentHeight] = this.parent.viewportBaseDimensions; + this.width = width / parentWidth; + this.height = height / parentHeight; + this.#aspectRatio = width / height; + this.#setMinDims(); + const prevTranslationX = this.translationX; + const prevTranslationY = this.translationY; + this.translationX = -bbox[0]; + this.translationY = -bbox[1]; + this.#setCanvasDims(); + this.#redraw(); + this.#realWidth = width; + this.#realHeight = height; + this.setDims(width, height); + const unscaledPadding = firstTime ? padding / this.scaleFactor / 2 : 0; + this.translate(prevTranslationX - this.translationX - unscaledPadding, prevTranslationY - this.translationY - unscaledPadding); + } + + #setMinDims() { + const { + style + } = this.div; + + if (this.#aspectRatio >= 1) { + style.minHeight = `${RESIZER_SIZE}px`; + style.minWidth = `${Math.round(this.#aspectRatio * RESIZER_SIZE)}px`; + } else { + style.minWidth = `${RESIZER_SIZE}px`; + style.minHeight = `${Math.round(RESIZER_SIZE / this.#aspectRatio)}px`; + } + } + + static deserialize(data, parent) { + const editor = super.deserialize(data, parent); + editor.thickness = data.thickness; + editor.color = _util.Util.makeHexColor(...data.color); + editor.opacity = data.opacity; + const [pageWidth, pageHeight] = parent.pageDimensions; + const width = editor.width * pageWidth; + const height = editor.height * pageHeight; + const scaleFactor = parent.scaleFactor; + const padding = data.thickness / 2; + editor.#aspectRatio = width / height; + editor.#disableEditing = true; + editor.#realWidth = Math.round(width); + editor.#realHeight = Math.round(height); + + for (const { + bezier + } of data.paths) { + const path = []; + editor.paths.push(path); + let p0 = scaleFactor * (bezier[0] - padding); + let p1 = scaleFactor * (height - bezier[1] - padding); + + for (let i = 2, ii = bezier.length; i < ii; i += 6) { + const p10 = scaleFactor * (bezier[i] - padding); + const p11 = scaleFactor * (height - bezier[i + 1] - padding); + const p20 = scaleFactor * (bezier[i + 2] - padding); + const p21 = scaleFactor * (height - bezier[i + 3] - padding); + const p30 = scaleFactor * (bezier[i + 4] - padding); + const p31 = scaleFactor * (height - bezier[i + 5] - padding); + path.push([[p0, p1], [p10, p11], [p20, p21], [p30, p31]]); + p0 = p30; + p1 = p31; + } + + const path2D = this.#buildPath2D(path); + editor.bezierPath2D.push(path2D); + } + + const bbox = editor.#getBbox(); + editor.#baseWidth = Math.max(RESIZER_SIZE, bbox[2] - bbox[0]); + editor.#baseHeight = Math.max(RESIZER_SIZE, bbox[3] - bbox[1]); + editor.#setScaleFactor(width, height); + return editor; + } + + serialize() { + if (this.isEmpty()) { + return null; + } + + const rect = this.getRect(0, 0); + const height = this.rotation % 180 === 0 ? rect[3] - rect[1] : rect[2] - rect[0]; + + const color = _editor.AnnotationEditor._colorManager.convert(this.ctx.strokeStyle); + + return { + annotationType: _util.AnnotationEditorType.INK, + color, + thickness: this.thickness, + opacity: this.opacity, + paths: this.#serializePaths(this.scaleFactor / this.parent.scaleFactor, this.translationX, this.translationY, height), + pageIndex: this.parent.pageIndex, + rect, + rotation: this.rotation + }; + } + + } + + exports.InkEditor = InkEditor; + + /***/ }), + /* 25 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.fitCurve = void 0; + + const fitCurve = __w_pdfjs_require__(26); + + exports.fitCurve = fitCurve; + + /***/ }), + /* 26 */ + /***/ ((module) => { + + + + function fitCurve(points, maxError, progressCallback) { + if (!Array.isArray(points)) { + throw new TypeError("First argument should be an array"); + } + + points.forEach(point => { + if (!Array.isArray(point) || point.some(item => typeof item !== 'number') || point.length !== points[0].length) { + throw Error("Each point should be an array of numbers. Each point should have the same amount of numbers."); + } + }); + points = points.filter((point, i) => i === 0 || !point.every((val, j) => val === points[i - 1][j])); + + if (points.length < 2) { + return []; + } + + const len = points.length; + const leftTangent = createTangent(points[1], points[0]); + const rightTangent = createTangent(points[len - 2], points[len - 1]); + return fitCubic(points, leftTangent, rightTangent, maxError, progressCallback); + } + + function fitCubic(points, leftTangent, rightTangent, error, progressCallback) { + const MaxIterations = 20; + var bezCurve, u, uPrime, maxError, prevErr, splitPoint, prevSplit, centerVector, toCenterTangent, fromCenterTangent, beziers, dist, i; + + if (points.length === 2) { + dist = maths.vectorLen(maths.subtract(points[0], points[1])) / 3.0; + bezCurve = [points[0], maths.addArrays(points[0], maths.mulItems(leftTangent, dist)), maths.addArrays(points[1], maths.mulItems(rightTangent, dist)), points[1]]; + return [bezCurve]; + } + + u = chordLengthParameterize(points); + [bezCurve, maxError, splitPoint] = generateAndReport(points, u, u, leftTangent, rightTangent, progressCallback); + + if (maxError === 0 || maxError < error) { + return [bezCurve]; + } + + if (maxError < error * error) { + uPrime = u; + prevErr = maxError; + prevSplit = splitPoint; + + for (i = 0; i < MaxIterations; i++) { + uPrime = reparameterize(bezCurve, points, uPrime); + [bezCurve, maxError, splitPoint] = generateAndReport(points, u, uPrime, leftTangent, rightTangent, progressCallback); + + if (maxError < error) { + return [bezCurve]; + } else if (splitPoint === prevSplit) { + let errChange = maxError / prevErr; + + if (errChange > .9999 && errChange < 1.0001) { + break; + } + } + + prevErr = maxError; + prevSplit = splitPoint; + } + } + + beziers = []; + centerVector = maths.subtract(points[splitPoint - 1], points[splitPoint + 1]); + + if (centerVector.every(val => val === 0)) { + centerVector = maths.subtract(points[splitPoint - 1], points[splitPoint]); + [centerVector[0], centerVector[1]] = [-centerVector[1], centerVector[0]]; + } + + toCenterTangent = maths.normalize(centerVector); + fromCenterTangent = maths.mulItems(toCenterTangent, -1); + beziers = beziers.concat(fitCubic(points.slice(0, splitPoint + 1), leftTangent, toCenterTangent, error, progressCallback)); + beziers = beziers.concat(fitCubic(points.slice(splitPoint), fromCenterTangent, rightTangent, error, progressCallback)); + return beziers; + } + + function generateAndReport(points, paramsOrig, paramsPrime, leftTangent, rightTangent, progressCallback) { + var bezCurve, maxError, splitPoint; + bezCurve = generateBezier(points, paramsPrime, leftTangent, rightTangent); + [maxError, splitPoint] = computeMaxError(points, bezCurve, paramsOrig); + + if (progressCallback) { + progressCallback({ + bez: bezCurve, + points: points, + params: paramsOrig, + maxErr: maxError, + maxPoint: splitPoint + }); + } + + return [bezCurve, maxError, splitPoint]; + } + + function generateBezier(points, parameters, leftTangent, rightTangent) { + var bezCurve, + A, + a, + C, + X, + det_C0_C1, + det_C0_X, + det_X_C1, + alpha_l, + alpha_r, + epsilon, + segLength, + i, + len, + tmp, + u, + ux, + firstPoint = points[0], + lastPoint = points[points.length - 1]; + bezCurve = [firstPoint, null, null, lastPoint]; + A = maths.zeros_Xx2x2(parameters.length); + + for (i = 0, len = parameters.length; i < len; i++) { + u = parameters[i]; + ux = 1 - u; + a = A[i]; + a[0] = maths.mulItems(leftTangent, 3 * u * (ux * ux)); + a[1] = maths.mulItems(rightTangent, 3 * ux * (u * u)); + } + + C = [[0, 0], [0, 0]]; + X = [0, 0]; + + for (i = 0, len = points.length; i < len; i++) { + u = parameters[i]; + a = A[i]; + C[0][0] += maths.dot(a[0], a[0]); + C[0][1] += maths.dot(a[0], a[1]); + C[1][0] += maths.dot(a[0], a[1]); + C[1][1] += maths.dot(a[1], a[1]); + tmp = maths.subtract(points[i], bezier.q([firstPoint, firstPoint, lastPoint, lastPoint], u)); + X[0] += maths.dot(a[0], tmp); + X[1] += maths.dot(a[1], tmp); + } + + det_C0_C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1]; + det_C0_X = C[0][0] * X[1] - C[1][0] * X[0]; + det_X_C1 = X[0] * C[1][1] - X[1] * C[0][1]; + alpha_l = det_C0_C1 === 0 ? 0 : det_X_C1 / det_C0_C1; + alpha_r = det_C0_C1 === 0 ? 0 : det_C0_X / det_C0_C1; + segLength = maths.vectorLen(maths.subtract(firstPoint, lastPoint)); + epsilon = 1.0e-6 * segLength; + + if (alpha_l < epsilon || alpha_r < epsilon) { + bezCurve[1] = maths.addArrays(firstPoint, maths.mulItems(leftTangent, segLength / 3.0)); + bezCurve[2] = maths.addArrays(lastPoint, maths.mulItems(rightTangent, segLength / 3.0)); + } else { + bezCurve[1] = maths.addArrays(firstPoint, maths.mulItems(leftTangent, alpha_l)); + bezCurve[2] = maths.addArrays(lastPoint, maths.mulItems(rightTangent, alpha_r)); + } + + return bezCurve; + } + + function reparameterize(bezier, points, parameters) { + return parameters.map((p, i) => newtonRaphsonRootFind(bezier, points[i], p)); + } + + function newtonRaphsonRootFind(bez, point, u) { + var d = maths.subtract(bezier.q(bez, u), point), + qprime = bezier.qprime(bez, u), + numerator = maths.mulMatrix(d, qprime), + denominator = maths.sum(maths.squareItems(qprime)) + 2 * maths.mulMatrix(d, bezier.qprimeprime(bez, u)); + + if (denominator === 0) { + return u; + } else { + return u - numerator / denominator; + } + } + + function chordLengthParameterize(points) { + var u = [], + currU, + prevU, + prevP; + points.forEach((p, i) => { + currU = i ? prevU + maths.vectorLen(maths.subtract(p, prevP)) : 0; + u.push(currU); + prevU = currU; + prevP = p; + }); + u = u.map(x => x / prevU); + return u; + } + + function computeMaxError(points, bez, parameters) { + var dist, maxDist, splitPoint, v, i, count, point, t; + maxDist = 0; + splitPoint = Math.floor(points.length / 2); + const t_distMap = mapTtoRelativeDistances(bez, 10); + + for (i = 0, count = points.length; i < count; i++) { + point = points[i]; + t = find_t(bez, parameters[i], t_distMap, 10); + v = maths.subtract(bezier.q(bez, t), point); + dist = v[0] * v[0] + v[1] * v[1]; + + if (dist > maxDist) { + maxDist = dist; + splitPoint = i; + } + } + + return [maxDist, splitPoint]; + } + + var mapTtoRelativeDistances = function (bez, B_parts) { + var B_t_curr; + var B_t_dist = [0]; + var B_t_prev = bez[0]; + var sumLen = 0; + + for (var i = 1; i <= B_parts; i++) { + B_t_curr = bezier.q(bez, i / B_parts); + sumLen += maths.vectorLen(maths.subtract(B_t_curr, B_t_prev)); + B_t_dist.push(sumLen); + B_t_prev = B_t_curr; + } + + B_t_dist = B_t_dist.map(x => x / sumLen); + return B_t_dist; + }; + + function find_t(bez, param, t_distMap, B_parts) { + if (param < 0) { + return 0; + } + + if (param > 1) { + return 1; + } + + var lenMax, lenMin, tMax, tMin, t; + + for (var i = 1; i <= B_parts; i++) { + if (param <= t_distMap[i]) { + tMin = (i - 1) / B_parts; + tMax = i / B_parts; + lenMin = t_distMap[i - 1]; + lenMax = t_distMap[i]; + t = (param - lenMin) / (lenMax - lenMin) * (tMax - tMin) + tMin; + break; + } + } + + return t; + } + + function createTangent(pointA, pointB) { + return maths.normalize(maths.subtract(pointA, pointB)); + } + + class maths { + static zeros_Xx2x2(x) { + var zs = []; + + while (x--) { + zs.push([0, 0]); + } + + return zs; + } + + static mulItems(items, multiplier) { + return items.map(x => x * multiplier); + } + + static mulMatrix(m1, m2) { + return m1.reduce((sum, x1, i) => sum + x1 * m2[i], 0); + } + + static subtract(arr1, arr2) { + return arr1.map((x1, i) => x1 - arr2[i]); + } + + static addArrays(arr1, arr2) { + return arr1.map((x1, i) => x1 + arr2[i]); + } + + static addItems(items, addition) { + return items.map(x => x + addition); + } + + static sum(items) { + return items.reduce((sum, x) => sum + x); + } + + static dot(m1, m2) { + return maths.mulMatrix(m1, m2); + } + + static vectorLen(v) { + return Math.hypot(...v); + } + + static divItems(items, divisor) { + return items.map(x => x / divisor); + } + + static squareItems(items) { + return items.map(x => x * x); + } + + static normalize(v) { + return this.divItems(v, this.vectorLen(v)); + } + + } + + class bezier { + static q(ctrlPoly, t) { + var tx = 1.0 - t; + var pA = maths.mulItems(ctrlPoly[0], tx * tx * tx), + pB = maths.mulItems(ctrlPoly[1], 3 * tx * tx * t), + pC = maths.mulItems(ctrlPoly[2], 3 * tx * t * t), + pD = maths.mulItems(ctrlPoly[3], t * t * t); + return maths.addArrays(maths.addArrays(pA, pB), maths.addArrays(pC, pD)); + } + + static qprime(ctrlPoly, t) { + var tx = 1.0 - t; + var pA = maths.mulItems(maths.subtract(ctrlPoly[1], ctrlPoly[0]), 3 * tx * tx), + pB = maths.mulItems(maths.subtract(ctrlPoly[2], ctrlPoly[1]), 6 * tx * t), + pC = maths.mulItems(maths.subtract(ctrlPoly[3], ctrlPoly[2]), 3 * t * t); + return maths.addArrays(maths.addArrays(pA, pB), pC); + } + + static qprimeprime(ctrlPoly, t) { + return maths.addArrays(maths.mulItems(maths.addArrays(maths.subtract(ctrlPoly[2], maths.mulItems(ctrlPoly[1], 2)), ctrlPoly[0]), 6 * (1.0 - t)), maths.mulItems(maths.addArrays(maths.subtract(ctrlPoly[3], maths.mulItems(ctrlPoly[2], 2)), ctrlPoly[1]), 6 * t)); + } + + } + + module.exports = fitCurve; + module.exports.fitCubic = fitCubic; + module.exports.createTangent = createTangent; + + /***/ }), + /* 27 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.AnnotationLayer = void 0; + + var _util = __w_pdfjs_require__(1); + + var _display_utils = __w_pdfjs_require__(8); + + var _annotation_storage = __w_pdfjs_require__(5); + + var _scripting_utils = __w_pdfjs_require__(28); + + var _xfa_layer = __w_pdfjs_require__(29); + + const DEFAULT_TAB_INDEX = 1000; + const DEFAULT_FONT_SIZE = 9; + const GetElementsByNameSet = new WeakSet(); + + function getRectDims(rect) { + return { + width: rect[2] - rect[0], + height: rect[3] - rect[1] + }; + } + + class AnnotationElementFactory { + static create(parameters) { + const subtype = parameters.data.annotationType; + + switch (subtype) { + case _util.AnnotationType.LINK: + return new LinkAnnotationElement(parameters); + + case _util.AnnotationType.TEXT: + return new TextAnnotationElement(parameters); + + case _util.AnnotationType.WIDGET: + const fieldType = parameters.data.fieldType; + + switch (fieldType) { + case "Tx": + return new TextWidgetAnnotationElement(parameters); + + case "Btn": + if (parameters.data.radioButton) { + return new RadioButtonWidgetAnnotationElement(parameters); + } else if (parameters.data.checkBox) { + return new CheckboxWidgetAnnotationElement(parameters); + } + + return new PushButtonWidgetAnnotationElement(parameters); + + case "Ch": + return new ChoiceWidgetAnnotationElement(parameters); + } + + return new WidgetAnnotationElement(parameters); + + case _util.AnnotationType.POPUP: + return new PopupAnnotationElement(parameters); + + case _util.AnnotationType.FREETEXT: + return new FreeTextAnnotationElement(parameters); + + case _util.AnnotationType.LINE: + return new LineAnnotationElement(parameters); + + case _util.AnnotationType.SQUARE: + return new SquareAnnotationElement(parameters); + + case _util.AnnotationType.CIRCLE: + return new CircleAnnotationElement(parameters); + + case _util.AnnotationType.POLYLINE: + return new PolylineAnnotationElement(parameters); + + case _util.AnnotationType.CARET: + return new CaretAnnotationElement(parameters); + + case _util.AnnotationType.INK: + return new InkAnnotationElement(parameters); + + case _util.AnnotationType.POLYGON: + return new PolygonAnnotationElement(parameters); + + case _util.AnnotationType.HIGHLIGHT: + return new HighlightAnnotationElement(parameters); + + case _util.AnnotationType.UNDERLINE: + return new UnderlineAnnotationElement(parameters); + + case _util.AnnotationType.SQUIGGLY: + return new SquigglyAnnotationElement(parameters); + + case _util.AnnotationType.STRIKEOUT: + return new StrikeOutAnnotationElement(parameters); + + case _util.AnnotationType.STAMP: + return new StampAnnotationElement(parameters); + + case _util.AnnotationType.FILEATTACHMENT: + return new FileAttachmentAnnotationElement(parameters); + + default: + return new AnnotationElement(parameters); + } + } + + } + + class AnnotationElement { + constructor(parameters, { + isRenderable = false, + ignoreBorder = false, + createQuadrilaterals = false + } = {}) { + this.isRenderable = isRenderable; + this.data = parameters.data; + this.layer = parameters.layer; + this.page = parameters.page; + this.viewport = parameters.viewport; + this.linkService = parameters.linkService; + this.downloadManager = parameters.downloadManager; + this.imageResourcesPath = parameters.imageResourcesPath; + this.renderForms = parameters.renderForms; + this.svgFactory = parameters.svgFactory; + this.annotationStorage = parameters.annotationStorage; + this.enableScripting = parameters.enableScripting; + this.hasJSActions = parameters.hasJSActions; + this._fieldObjects = parameters.fieldObjects; + this._mouseState = parameters.mouseState; + + if (isRenderable) { + this.container = this._createContainer(ignoreBorder); + } + + if (createQuadrilaterals) { + this.quadrilaterals = this._createQuadrilaterals(ignoreBorder); + } + } + + _createContainer(ignoreBorder = false) { + const data = this.data, + page = this.page, + viewport = this.viewport; + const container = document.createElement("section"); + const { + width, + height + } = getRectDims(data.rect); + const [pageLLx, pageLLy, pageURx, pageURy] = viewport.viewBox; + const pageWidth = pageURx - pageLLx; + const pageHeight = pageURy - pageLLy; + container.setAttribute("data-annotation-id", data.id); + + const rect = _util.Util.normalizeRect([data.rect[0], page.view[3] - data.rect[1] + page.view[1], data.rect[2], page.view[3] - data.rect[3] + page.view[1]]); + + if (!ignoreBorder && data.borderStyle.width > 0) { + container.style.borderWidth = `${data.borderStyle.width}px`; + const horizontalRadius = data.borderStyle.horizontalCornerRadius; + const verticalRadius = data.borderStyle.verticalCornerRadius; + + if (horizontalRadius > 0 || verticalRadius > 0) { + const radius = `calc(${horizontalRadius}px * var(--scale-factor)) / calc(${verticalRadius}px * var(--scale-factor))`; + container.style.borderRadius = radius; + } else if (this instanceof RadioButtonWidgetAnnotationElement) { + const radius = `calc(${width}px * var(--scale-factor)) / calc(${height}px * var(--scale-factor))`; + container.style.borderRadius = radius; + } + + switch (data.borderStyle.style) { + case _util.AnnotationBorderStyleType.SOLID: + container.style.borderStyle = "solid"; + break; + + case _util.AnnotationBorderStyleType.DASHED: + container.style.borderStyle = "dashed"; + break; + + case _util.AnnotationBorderStyleType.BEVELED: + (0, _util.warn)("Unimplemented border style: beveled"); + break; + + case _util.AnnotationBorderStyleType.INSET: + (0, _util.warn)("Unimplemented border style: inset"); + break; + + case _util.AnnotationBorderStyleType.UNDERLINE: + container.style.borderBottomStyle = "solid"; + break; + } + + const borderColor = data.borderColor || null; + + if (borderColor) { + container.style.borderColor = _util.Util.makeHexColor(borderColor[0] | 0, borderColor[1] | 0, borderColor[2] | 0); + } else { + container.style.borderWidth = 0; + } + } + + container.style.left = `${100 * (rect[0] - pageLLx) / pageWidth}%`; + container.style.top = `${100 * (rect[1] - pageLLy) / pageHeight}%`; + const { + rotation + } = data; + + if (data.hasOwnCanvas || rotation === 0) { + container.style.width = `${100 * width / pageWidth}%`; + container.style.height = `${100 * height / pageHeight}%`; + } else { + this.setRotation(rotation, container); + } + + return container; + } + + setRotation(angle, container = this.container) { + const [pageLLx, pageLLy, pageURx, pageURy] = this.viewport.viewBox; + const pageWidth = pageURx - pageLLx; + const pageHeight = pageURy - pageLLy; + const { + width, + height + } = getRectDims(this.data.rect); + let elementWidth, elementHeight; + + if (angle % 180 === 0) { + elementWidth = 100 * width / pageWidth; + elementHeight = 100 * height / pageHeight; + } else { + elementWidth = 100 * height / pageWidth; + elementHeight = 100 * width / pageHeight; + } + + container.style.width = `${elementWidth}%`; + container.style.height = `${elementHeight}%`; + container.setAttribute("data-main-rotation", (360 - angle) % 360); + } + + get _commonActions() { + const setColor = (jsName, styleName, event) => { + const color = event.detail[jsName]; + event.target.style[styleName] = _scripting_utils.ColorConverters[`${color[0]}_HTML`](color.slice(1)); + }; + + return (0, _util.shadow)(this, "_commonActions", { + display: event => { + const hidden = event.detail.display % 2 === 1; + this.container.style.visibility = hidden ? "hidden" : "visible"; + this.annotationStorage.setValue(this.data.id, { + hidden, + print: event.detail.display === 0 || event.detail.display === 3 + }); + }, + print: event => { + this.annotationStorage.setValue(this.data.id, { + print: event.detail.print + }); + }, + hidden: event => { + this.container.style.visibility = event.detail.hidden ? "hidden" : "visible"; + this.annotationStorage.setValue(this.data.id, { + hidden: event.detail.hidden + }); + }, + focus: event => { + setTimeout(() => event.target.focus({ + preventScroll: false + }), 0); + }, + userName: event => { + event.target.title = event.detail.userName; + }, + readonly: event => { + if (event.detail.readonly) { + event.target.setAttribute("readonly", ""); + } else { + event.target.removeAttribute("readonly"); + } + }, + required: event => { + this._setRequired(event.target, event.detail.required); + }, + bgColor: event => { + setColor("bgColor", "backgroundColor", event); + }, + fillColor: event => { + setColor("fillColor", "backgroundColor", event); + }, + fgColor: event => { + setColor("fgColor", "color", event); + }, + textColor: event => { + setColor("textColor", "color", event); + }, + borderColor: event => { + setColor("borderColor", "borderColor", event); + }, + strokeColor: event => { + setColor("strokeColor", "borderColor", event); + }, + rotation: event => { + const angle = event.detail.rotation; + this.setRotation(angle); + this.annotationStorage.setValue(this.data.id, { + rotation: angle + }); + } + }); + } + + _dispatchEventFromSandbox(actions, jsEvent) { + const commonActions = this._commonActions; + + for (const name of Object.keys(jsEvent.detail)) { + const action = actions[name] || commonActions[name]; + + if (action) { + action(jsEvent); + } + } + } + + _setDefaultPropertiesFromJS(element) { + if (!this.enableScripting) { + return; + } + + const storedData = this.annotationStorage.getRawValue(this.data.id); + + if (!storedData) { + return; + } + + const commonActions = this._commonActions; + + for (const [actionName, detail] of Object.entries(storedData)) { + const action = commonActions[actionName]; + + if (action) { + const eventProxy = { + detail: { + [actionName]: detail + }, + target: element + }; + action(eventProxy); + delete storedData[actionName]; + } + } + } + + _createQuadrilaterals(ignoreBorder = false) { + if (!this.data.quadPoints) { + return null; + } + + const quadrilaterals = []; + const savedRect = this.data.rect; + + for (const quadPoint of this.data.quadPoints) { + this.data.rect = [quadPoint[2].x, quadPoint[2].y, quadPoint[1].x, quadPoint[1].y]; + quadrilaterals.push(this._createContainer(ignoreBorder)); + } + + this.data.rect = savedRect; + return quadrilaterals; + } + + _createPopup(trigger, data) { + let container = this.container; + + if (this.quadrilaterals) { + trigger = trigger || this.quadrilaterals; + container = this.quadrilaterals[0]; + } + + if (!trigger) { + trigger = document.createElement("div"); + trigger.className = "popupTriggerArea"; + container.append(trigger); + } + + const popupElement = new PopupElement({ + container, + trigger, + color: data.color, + titleObj: data.titleObj, + modificationDate: data.modificationDate, + contentsObj: data.contentsObj, + richText: data.richText, + hideWrapper: true + }); + const popup = popupElement.render(); + popup.style.left = "100%"; + container.append(popup); + } + + _renderQuadrilaterals(className) { + for (const quadrilateral of this.quadrilaterals) { + quadrilateral.className = className; + } + + return this.quadrilaterals; + } + + render() { + (0, _util.unreachable)("Abstract method `AnnotationElement.render` called"); + } + + _getElementsByName(name, skipId = null) { + const fields = []; + + if (this._fieldObjects) { + const fieldObj = this._fieldObjects[name]; + + if (fieldObj) { + for (const { + page, + id, + exportValues + } of fieldObj) { + if (page === -1) { + continue; + } + + if (id === skipId) { + continue; + } + + const exportValue = typeof exportValues === "string" ? exportValues : null; + const domElement = document.querySelector(`[data-element-id="${id}"]`); + + if (domElement && !GetElementsByNameSet.has(domElement)) { + (0, _util.warn)(`_getElementsByName - element not allowed: ${id}`); + continue; + } + + fields.push({ + id, + exportValue, + domElement + }); + } + } + + return fields; + } + + for (const domElement of document.getElementsByName(name)) { + const { + id, + exportValue + } = domElement; + + if (id === skipId) { + continue; + } + + if (!GetElementsByNameSet.has(domElement)) { + continue; + } + + fields.push({ + id, + exportValue, + domElement + }); + } + + return fields; + } + + static get platform() { + const platform = typeof navigator !== "undefined" ? navigator.platform : ""; + return (0, _util.shadow)(this, "platform", { + isWin: platform.includes("Win"), + isMac: platform.includes("Mac") + }); + } + + } + + class LinkAnnotationElement extends AnnotationElement { + constructor(parameters, options = null) { + super(parameters, { + isRenderable: true, + ignoreBorder: !!options?.ignoreBorder, + createQuadrilaterals: true + }); + this.isTooltipOnly = parameters.data.isTooltipOnly; + } + + render() { + const { + data, + linkService + } = this; + const link = document.createElement("a"); + link.setAttribute("data-element-id", data.id); + let isBound = false; + + if (data.url) { + linkService.addLinkAttributes(link, data.url, data.newWindow); + isBound = true; + } else if (data.action) { + this._bindNamedAction(link, data.action); + + isBound = true; + } else if (data.dest) { + this._bindLink(link, data.dest); + + isBound = true; + } else { + if (data.actions && (data.actions.Action || data.actions["Mouse Up"] || data.actions["Mouse Down"]) && this.enableScripting && this.hasJSActions) { + this._bindJSAction(link, data); + + isBound = true; + } + + if (data.resetForm) { + this._bindResetFormAction(link, data.resetForm); + + isBound = true; + } else if (this.isTooltipOnly && !isBound) { + this._bindLink(link, ""); + + isBound = true; + } + } + + if (this.quadrilaterals) { + return this._renderQuadrilaterals("linkAnnotation").map((quadrilateral, index) => { + const linkElement = index === 0 ? link : link.cloneNode(); + quadrilateral.append(linkElement); + return quadrilateral; + }); + } + + this.container.className = "linkAnnotation"; + + if (isBound) { + this.container.append(link); + } + + return this.container; + } + + _bindLink(link, destination) { + link.href = this.linkService.getDestinationHash(destination); + + link.onclick = () => { + if (destination) { + this.linkService.goToDestination(destination); + } + + return false; + }; + + if (destination || destination === "") { + link.className = "internalLink"; + } + } + + _bindNamedAction(link, action) { + link.href = this.linkService.getAnchorUrl(""); + + link.onclick = () => { + this.linkService.executeNamedAction(action); + return false; + }; + + link.className = "internalLink"; + } + + _bindJSAction(link, data) { + link.href = this.linkService.getAnchorUrl(""); + const map = new Map([["Action", "onclick"], ["Mouse Up", "onmouseup"], ["Mouse Down", "onmousedown"]]); + + for (const name of Object.keys(data.actions)) { + const jsName = map.get(name); + + if (!jsName) { + continue; + } + + link[jsName] = () => { + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id: data.id, + name + } + }); + return false; + }; + } + + if (!link.onclick) { + link.onclick = () => false; + } + + link.className = "internalLink"; + } + + _bindResetFormAction(link, resetForm) { + const otherClickAction = link.onclick; + + if (!otherClickAction) { + link.href = this.linkService.getAnchorUrl(""); + } + + link.className = "internalLink"; + + if (!this._fieldObjects) { + (0, _util.warn)(`_bindResetFormAction - "resetForm" action not supported, ` + "ensure that the `fieldObjects` parameter is provided."); + + if (!otherClickAction) { + link.onclick = () => false; + } + + return; + } + + link.onclick = () => { + if (otherClickAction) { + otherClickAction(); + } + + const { + fields: resetFormFields, + refs: resetFormRefs, + include + } = resetForm; + const allFields = []; + + if (resetFormFields.length !== 0 || resetFormRefs.length !== 0) { + const fieldIds = new Set(resetFormRefs); + + for (const fieldName of resetFormFields) { + const fields = this._fieldObjects[fieldName] || []; + + for (const { + id + } of fields) { + fieldIds.add(id); + } + } + + for (const fields of Object.values(this._fieldObjects)) { + for (const field of fields) { + if (fieldIds.has(field.id) === include) { + allFields.push(field); + } + } + } + } else { + for (const fields of Object.values(this._fieldObjects)) { + allFields.push(...fields); + } + } + + const storage = this.annotationStorage; + const allIds = []; + + for (const field of allFields) { + const { + id + } = field; + allIds.push(id); + + switch (field.type) { + case "text": + { + const value = field.defaultValue || ""; + storage.setValue(id, { + value + }); + break; + } + + case "checkbox": + case "radiobutton": + { + const value = field.defaultValue === field.exportValues; + storage.setValue(id, { + value + }); + break; + } + + case "combobox": + case "listbox": + { + const value = field.defaultValue || ""; + storage.setValue(id, { + value + }); + break; + } + + default: + continue; + } + + const domElement = document.querySelector(`[data-element-id="${id}"]`); + + if (!domElement) { + continue; + } else if (!GetElementsByNameSet.has(domElement)) { + (0, _util.warn)(`_bindResetFormAction - element not allowed: ${id}`); + continue; + } + + domElement.dispatchEvent(new Event("resetform")); + } + + if (this.enableScripting) { + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id: "app", + ids: allIds, + name: "ResetForm" + } + }); + } + + return false; + }; + } + + } + + class TextAnnotationElement extends AnnotationElement { + constructor(parameters) { + const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str); + super(parameters, { + isRenderable + }); + } + + render() { + this.container.className = "textAnnotation"; + const image = document.createElement("img"); + image.src = this.imageResourcesPath + "annotation-" + this.data.name.toLowerCase() + ".svg"; + image.alt = "[{{type}} Annotation]"; + image.dataset.l10nId = "text_annotation_type"; + image.dataset.l10nArgs = JSON.stringify({ + type: this.data.name + }); + + if (!this.data.hasPopup) { + this._createPopup(image, this.data); + } + + this.container.append(image); + return this.container; + } + + } + + class WidgetAnnotationElement extends AnnotationElement { + render() { + if (this.data.alternativeText) { + this.container.title = this.data.alternativeText; + } + + return this.container; + } + + _getKeyModifier(event) { + const { + isWin, + isMac + } = AnnotationElement.platform; + return isWin && event.ctrlKey || isMac && event.metaKey; + } + + _setEventListener(element, baseName, eventName, valueGetter) { + if (baseName.includes("mouse")) { + element.addEventListener(baseName, event => { + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id: this.data.id, + name: eventName, + value: valueGetter(event), + shift: event.shiftKey, + modifier: this._getKeyModifier(event) + } + }); + }); + } else { + element.addEventListener(baseName, event => { + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id: this.data.id, + name: eventName, + value: valueGetter(event) + } + }); + }); + } + } + + _setEventListeners(element, names, getter) { + for (const [baseName, eventName] of names) { + if (eventName === "Action" || this.data.actions?.[eventName]) { + this._setEventListener(element, baseName, eventName, getter); + } + } + } + + _setBackgroundColor(element) { + const color = this.data.backgroundColor || null; + element.style.backgroundColor = color === null ? "transparent" : _util.Util.makeHexColor(color[0], color[1], color[2]); + } + + _setTextStyle(element) { + const TEXT_ALIGNMENT = ["left", "center", "right"]; + const { + fontColor + } = this.data.defaultAppearanceData; + const fontSize = this.data.defaultAppearanceData.fontSize || DEFAULT_FONT_SIZE; + const style = element.style; + let computedFontSize; + + if (this.data.multiLine) { + const height = Math.abs(this.data.rect[3] - this.data.rect[1]); + const numberOfLines = Math.round(height / (_util.LINE_FACTOR * fontSize)) || 1; + const lineHeight = height / numberOfLines; + computedFontSize = Math.min(fontSize, Math.round(lineHeight / _util.LINE_FACTOR)); + } else { + const height = Math.abs(this.data.rect[3] - this.data.rect[1]); + computedFontSize = Math.min(fontSize, Math.round(height / _util.LINE_FACTOR)); + } + + style.fontSize = `calc(${computedFontSize}px * var(--scale-factor))`; + style.color = _util.Util.makeHexColor(fontColor[0], fontColor[1], fontColor[2]); + + if (this.data.textAlignment !== null) { + style.textAlign = TEXT_ALIGNMENT[this.data.textAlignment]; + } + } + + _setRequired(element, isRequired) { + if (isRequired) { + element.setAttribute("required", true); + } else { + element.removeAttribute("required"); + } + + element.setAttribute("aria-required", isRequired); + } + + } + + class TextWidgetAnnotationElement extends WidgetAnnotationElement { + constructor(parameters) { + const isRenderable = parameters.renderForms || !parameters.data.hasAppearance && !!parameters.data.fieldValue; + super(parameters, { + isRenderable + }); + } + + setPropertyOnSiblings(base, key, value, keyInStorage) { + const storage = this.annotationStorage; + + for (const element of this._getElementsByName(base.name, base.id)) { + if (element.domElement) { + element.domElement[key] = value; + } + + storage.setValue(element.id, { + [keyInStorage]: value + }); + } + } + + render() { + const storage = this.annotationStorage; + const id = this.data.id; + this.container.className = "textWidgetAnnotation"; + let element = null; + + if (this.renderForms) { + const storedData = storage.getValue(id, { + value: this.data.fieldValue + }); + let textContent = storedData.formattedValue || storedData.value || ""; + const maxLen = storage.getValue(id, { + charLimit: this.data.maxLen + }).charLimit; + + if (maxLen && textContent.length > maxLen) { + textContent = textContent.slice(0, maxLen); + } + + const elementData = { + userValue: textContent, + formattedValue: null, + valueOnFocus: "" + }; + + if (this.data.multiLine) { + element = document.createElement("textarea"); + element.textContent = textContent; + + if (this.data.doNotScroll) { + element.style.overflowY = "hidden"; + } + } else { + element = document.createElement("input"); + element.type = "text"; + element.setAttribute("value", textContent); + + if (this.data.doNotScroll) { + element.style.overflowX = "hidden"; + } + } + + GetElementsByNameSet.add(element); + element.setAttribute("data-element-id", id); + element.disabled = this.data.readOnly; + element.name = this.data.fieldName; + element.tabIndex = DEFAULT_TAB_INDEX; + + this._setRequired(element, this.data.required); + + if (maxLen) { + element.maxLength = maxLen; + } + + element.addEventListener("input", event => { + storage.setValue(id, { + value: event.target.value + }); + this.setPropertyOnSiblings(element, "value", event.target.value, "value"); + }); + element.addEventListener("resetform", event => { + const defaultValue = this.data.defaultFieldValue ?? ""; + element.value = elementData.userValue = defaultValue; + elementData.formattedValue = null; + }); + + let blurListener = event => { + const { + formattedValue + } = elementData; + + if (formattedValue !== null && formattedValue !== undefined) { + event.target.value = formattedValue; + } + + event.target.scrollLeft = 0; + }; + + if (this.enableScripting && this.hasJSActions) { + element.addEventListener("focus", event => { + if (elementData.userValue) { + event.target.value = elementData.userValue; + } + + elementData.valueOnFocus = event.target.value; + }); + element.addEventListener("updatefromsandbox", jsEvent => { + const actions = { + value(event) { + elementData.userValue = event.detail.value ?? ""; + storage.setValue(id, { + value: elementData.userValue.toString() + }); + event.target.value = elementData.userValue; + }, + + formattedValue(event) { + const { + formattedValue + } = event.detail; + elementData.formattedValue = formattedValue; + + if (formattedValue !== null && formattedValue !== undefined && event.target !== document.activeElement) { + event.target.value = formattedValue; + } + + storage.setValue(id, { + formattedValue + }); + }, + + selRange(event) { + event.target.setSelectionRange(...event.detail.selRange); + }, + + charLimit: event => { + const { + charLimit + } = event.detail; + const { + target + } = event; + + if (charLimit === 0) { + target.removeAttribute("maxLength"); + return; + } + + target.setAttribute("maxLength", charLimit); + let value = elementData.userValue; + + if (!value || value.length <= charLimit) { + return; + } + + value = value.slice(0, charLimit); + target.value = elementData.userValue = value; + storage.setValue(id, { + value + }); + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id, + name: "Keystroke", + value, + willCommit: true, + commitKey: 1, + selStart: target.selectionStart, + selEnd: target.selectionEnd + } + }); + } + }; + + this._dispatchEventFromSandbox(actions, jsEvent); + }); + element.addEventListener("keydown", event => { + let commitKey = -1; + + if (event.key === "Escape") { + commitKey = 0; + } else if (event.key === "Enter") { + commitKey = 2; + } else if (event.key === "Tab") { + commitKey = 3; + } + + if (commitKey === -1) { + return; + } + + const { + value + } = event.target; + + if (elementData.valueOnFocus === value) { + return; + } + + elementData.userValue = value; + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id, + name: "Keystroke", + value, + willCommit: true, + commitKey, + selStart: event.target.selectionStart, + selEnd: event.target.selectionEnd + } + }); + }); + const _blurListener = blurListener; + blurListener = null; + element.addEventListener("blur", event => { + const { + value + } = event.target; + elementData.userValue = value; + + if (this._mouseState.isDown && elementData.valueOnFocus !== value) { + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id, + name: "Keystroke", + value, + willCommit: true, + commitKey: 1, + selStart: event.target.selectionStart, + selEnd: event.target.selectionEnd + } + }); + } + + _blurListener(event); + }); + + if (this.data.actions?.Keystroke) { + element.addEventListener("beforeinput", event => { + const { + data, + target + } = event; + const { + value, + selectionStart, + selectionEnd + } = target; + let selStart = selectionStart, + selEnd = selectionEnd; + + switch (event.inputType) { + case "deleteWordBackward": + { + const match = value.substring(0, selectionStart).match(/\w*[^\w]*$/); + + if (match) { + selStart -= match[0].length; + } + + break; + } + + case "deleteWordForward": + { + const match = value.substring(selectionStart).match(/^[^\w]*\w*/); + + if (match) { + selEnd += match[0].length; + } + + break; + } + + case "deleteContentBackward": + if (selectionStart === selectionEnd) { + selStart -= 1; + } + + break; + + case "deleteContentForward": + if (selectionStart === selectionEnd) { + selEnd += 1; + } + + break; + } + + event.preventDefault(); + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id, + name: "Keystroke", + value, + change: data || "", + willCommit: false, + selStart, + selEnd + } + }); + }); + } + + this._setEventListeners(element, [["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"]], event => event.target.value); + } + + if (blurListener) { + element.addEventListener("blur", blurListener); + } + + if (this.data.comb) { + const fieldWidth = this.data.rect[2] - this.data.rect[0]; + const combWidth = fieldWidth / maxLen; + element.classList.add("comb"); + element.style.letterSpacing = `calc(${combWidth}px * var(--scale-factor) - 1ch)`; + } + } else { + element = document.createElement("div"); + element.textContent = this.data.fieldValue; + element.style.verticalAlign = "middle"; + element.style.display = "table-cell"; + } + + this._setTextStyle(element); + + this._setBackgroundColor(element); + + this._setDefaultPropertiesFromJS(element); + + this.container.append(element); + return this.container; + } + + } + + class CheckboxWidgetAnnotationElement extends WidgetAnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: parameters.renderForms + }); + } + + render() { + const storage = this.annotationStorage; + const data = this.data; + const id = data.id; + let value = storage.getValue(id, { + value: data.exportValue === data.fieldValue + }).value; + + if (typeof value === "string") { + value = value !== "Off"; + storage.setValue(id, { + value + }); + } + + this.container.className = "buttonWidgetAnnotation checkBox"; + const element = document.createElement("input"); + GetElementsByNameSet.add(element); + element.setAttribute("data-element-id", id); + element.disabled = data.readOnly; + + this._setRequired(element, this.data.required); + + element.type = "checkbox"; + element.name = data.fieldName; + + if (value) { + element.setAttribute("checked", true); + } + + element.setAttribute("exportValue", data.exportValue); + element.tabIndex = DEFAULT_TAB_INDEX; + element.addEventListener("change", event => { + const { + name, + checked + } = event.target; + + for (const checkbox of this._getElementsByName(name, id)) { + const curChecked = checked && checkbox.exportValue === data.exportValue; + + if (checkbox.domElement) { + checkbox.domElement.checked = curChecked; + } + + storage.setValue(checkbox.id, { + value: curChecked + }); + } + + storage.setValue(id, { + value: checked + }); + }); + element.addEventListener("resetform", event => { + const defaultValue = data.defaultFieldValue || "Off"; + event.target.checked = defaultValue === data.exportValue; + }); + + if (this.enableScripting && this.hasJSActions) { + element.addEventListener("updatefromsandbox", jsEvent => { + const actions = { + value(event) { + event.target.checked = event.detail.value !== "Off"; + storage.setValue(id, { + value: event.target.checked + }); + } + + }; + + this._dispatchEventFromSandbox(actions, jsEvent); + }); + + this._setEventListeners(element, [["change", "Validate"], ["change", "Action"], ["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"]], event => event.target.checked); + } + + this._setBackgroundColor(element); + + this._setDefaultPropertiesFromJS(element); + + this.container.append(element); + return this.container; + } + + } + + class RadioButtonWidgetAnnotationElement extends WidgetAnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: parameters.renderForms + }); + } + + render() { + this.container.className = "buttonWidgetAnnotation radioButton"; + const storage = this.annotationStorage; + const data = this.data; + const id = data.id; + let value = storage.getValue(id, { + value: data.fieldValue === data.buttonValue + }).value; + + if (typeof value === "string") { + value = value !== data.buttonValue; + storage.setValue(id, { + value + }); + } + + const element = document.createElement("input"); + GetElementsByNameSet.add(element); + element.setAttribute("data-element-id", id); + element.disabled = data.readOnly; + + this._setRequired(element, this.data.required); + + element.type = "radio"; + element.name = data.fieldName; + + if (value) { + element.setAttribute("checked", true); + } + + element.tabIndex = DEFAULT_TAB_INDEX; + element.addEventListener("change", event => { + const { + name, + checked + } = event.target; + + for (const radio of this._getElementsByName(name, id)) { + storage.setValue(radio.id, { + value: false + }); + } + + storage.setValue(id, { + value: checked + }); + }); + element.addEventListener("resetform", event => { + const defaultValue = data.defaultFieldValue; + event.target.checked = defaultValue !== null && defaultValue !== undefined && defaultValue === data.buttonValue; + }); + + if (this.enableScripting && this.hasJSActions) { + const pdfButtonValue = data.buttonValue; + element.addEventListener("updatefromsandbox", jsEvent => { + const actions = { + value: event => { + const checked = pdfButtonValue === event.detail.value; + + for (const radio of this._getElementsByName(event.target.name)) { + const curChecked = checked && radio.id === id; + + if (radio.domElement) { + radio.domElement.checked = curChecked; + } + + storage.setValue(radio.id, { + value: curChecked + }); + } + } + }; + + this._dispatchEventFromSandbox(actions, jsEvent); + }); + + this._setEventListeners(element, [["change", "Validate"], ["change", "Action"], ["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"]], event => event.target.checked); + } + + this._setBackgroundColor(element); + + this._setDefaultPropertiesFromJS(element); + + this.container.append(element); + return this.container; + } + + } + + class PushButtonWidgetAnnotationElement extends LinkAnnotationElement { + constructor(parameters) { + super(parameters, { + ignoreBorder: parameters.data.hasAppearance + }); + } + + render() { + const container = super.render(); + container.className = "buttonWidgetAnnotation pushButton"; + + if (this.data.alternativeText) { + container.title = this.data.alternativeText; + } + + const linkElement = container.lastChild; + + if (this.enableScripting && this.hasJSActions && linkElement) { + this._setDefaultPropertiesFromJS(linkElement); + + linkElement.addEventListener("updatefromsandbox", jsEvent => { + this._dispatchEventFromSandbox({}, jsEvent); + }); + } + + return container; + } + + } + + class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: parameters.renderForms + }); + } + + render() { + this.container.className = "choiceWidgetAnnotation"; + const storage = this.annotationStorage; + const id = this.data.id; + const storedData = storage.getValue(id, { + value: this.data.fieldValue + }); + const selectElement = document.createElement("select"); + GetElementsByNameSet.add(selectElement); + selectElement.setAttribute("data-element-id", id); + selectElement.disabled = this.data.readOnly; + + this._setRequired(selectElement, this.data.required); + + selectElement.name = this.data.fieldName; + selectElement.tabIndex = DEFAULT_TAB_INDEX; + let addAnEmptyEntry = this.data.combo && this.data.options.length > 0; + + if (!this.data.combo) { + selectElement.size = this.data.options.length; + + if (this.data.multiSelect) { + selectElement.multiple = true; + } + } + + selectElement.addEventListener("resetform", event => { + const defaultValue = this.data.defaultFieldValue; + + for (const option of selectElement.options) { + option.selected = option.value === defaultValue; + } + }); + + for (const option of this.data.options) { + const optionElement = document.createElement("option"); + optionElement.textContent = option.displayValue; + optionElement.value = option.exportValue; + + if (storedData.value.includes(option.exportValue)) { + optionElement.setAttribute("selected", true); + addAnEmptyEntry = false; + } + + selectElement.append(optionElement); + } + + let removeEmptyEntry = null; + + if (addAnEmptyEntry) { + const noneOptionElement = document.createElement("option"); + noneOptionElement.value = " "; + noneOptionElement.setAttribute("hidden", true); + noneOptionElement.setAttribute("selected", true); + selectElement.prepend(noneOptionElement); + + removeEmptyEntry = () => { + noneOptionElement.remove(); + selectElement.removeEventListener("input", removeEmptyEntry); + removeEmptyEntry = null; + }; + + selectElement.addEventListener("input", removeEmptyEntry); + } + + const getValue = (event, isExport) => { + const name = isExport ? "value" : "textContent"; + const options = event.target.options; + + if (!event.target.multiple) { + return options.selectedIndex === -1 ? null : options[options.selectedIndex][name]; + } + + return Array.prototype.filter.call(options, option => option.selected).map(option => option[name]); + }; + + const getItems = event => { + const options = event.target.options; + return Array.prototype.map.call(options, option => { + return { + displayValue: option.textContent, + exportValue: option.value + }; + }); + }; + + if (this.enableScripting && this.hasJSActions) { + selectElement.addEventListener("updatefromsandbox", jsEvent => { + const actions = { + value(event) { + removeEmptyEntry?.(); + const value = event.detail.value; + const values = new Set(Array.isArray(value) ? value : [value]); + + for (const option of selectElement.options) { + option.selected = values.has(option.value); + } + + storage.setValue(id, { + value: getValue(event, true) + }); + }, + + multipleSelection(event) { + selectElement.multiple = true; + }, + + remove(event) { + const options = selectElement.options; + const index = event.detail.remove; + options[index].selected = false; + selectElement.remove(index); + + if (options.length > 0) { + const i = Array.prototype.findIndex.call(options, option => option.selected); + + if (i === -1) { + options[0].selected = true; + } + } + + storage.setValue(id, { + value: getValue(event, true), + items: getItems(event) + }); + }, + + clear(event) { + while (selectElement.length !== 0) { + selectElement.remove(0); + } + + storage.setValue(id, { + value: null, + items: [] + }); + }, + + insert(event) { + const { + index, + displayValue, + exportValue + } = event.detail.insert; + const selectChild = selectElement.children[index]; + const optionElement = document.createElement("option"); + optionElement.textContent = displayValue; + optionElement.value = exportValue; + + if (selectChild) { + selectChild.before(optionElement); + } else { + selectElement.append(optionElement); + } + + storage.setValue(id, { + value: getValue(event, true), + items: getItems(event) + }); + }, + + items(event) { + const { + items + } = event.detail; + + while (selectElement.length !== 0) { + selectElement.remove(0); + } + + for (const item of items) { + const { + displayValue, + exportValue + } = item; + const optionElement = document.createElement("option"); + optionElement.textContent = displayValue; + optionElement.value = exportValue; + selectElement.append(optionElement); + } + + if (selectElement.options.length > 0) { + selectElement.options[0].selected = true; + } + + storage.setValue(id, { + value: getValue(event, true), + items: getItems(event) + }); + }, + + indices(event) { + const indices = new Set(event.detail.indices); + + for (const option of event.target.options) { + option.selected = indices.has(option.index); + } + + storage.setValue(id, { + value: getValue(event, true) + }); + }, + + editable(event) { + event.target.disabled = !event.detail.editable; + } + + }; + + this._dispatchEventFromSandbox(actions, jsEvent); + }); + selectElement.addEventListener("input", event => { + const exportValue = getValue(event, true); + const value = getValue(event, false); + storage.setValue(id, { + value: exportValue + }); + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id, + name: "Keystroke", + value, + changeEx: exportValue, + willCommit: true, + commitKey: 1, + keyDown: false + } + }); + }); + + this._setEventListeners(selectElement, [["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"], ["input", "Action"]], event => event.target.checked); + } else { + selectElement.addEventListener("input", function (event) { + storage.setValue(id, { + value: getValue(event, true) + }); + }); + } + + if (this.data.combo) { + this._setTextStyle(selectElement); + } + + this._setBackgroundColor(selectElement); + + this._setDefaultPropertiesFromJS(selectElement); + + this.container.append(selectElement); + return this.container; + } + + } + + class PopupAnnotationElement extends AnnotationElement { + constructor(parameters) { + const isRenderable = !!(parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str); + super(parameters, { + isRenderable + }); + } + + render() { + const IGNORE_TYPES = ["Line", "Square", "Circle", "PolyLine", "Polygon", "Ink"]; + this.container.className = "popupAnnotation"; + + if (IGNORE_TYPES.includes(this.data.parentType)) { + return this.container; + } + + const selector = `[data-annotation-id="${this.data.parentId}"]`; + const parentElements = this.layer.querySelectorAll(selector); + + if (parentElements.length === 0) { + return this.container; + } + + const popup = new PopupElement({ + container: this.container, + trigger: Array.from(parentElements), + color: this.data.color, + titleObj: this.data.titleObj, + modificationDate: this.data.modificationDate, + contentsObj: this.data.contentsObj, + richText: this.data.richText + }); + const page = this.page; + + const rect = _util.Util.normalizeRect([this.data.parentRect[0], page.view[3] - this.data.parentRect[1] + page.view[1], this.data.parentRect[2], page.view[3] - this.data.parentRect[3] + page.view[1]]); + + const popupLeft = rect[0] + this.data.parentRect[2] - this.data.parentRect[0]; + const popupTop = rect[1]; + const [pageLLx, pageLLy, pageURx, pageURy] = this.viewport.viewBox; + const pageWidth = pageURx - pageLLx; + const pageHeight = pageURy - pageLLy; + this.container.style.left = `${100 * (popupLeft - pageLLx) / pageWidth}%`; + this.container.style.top = `${100 * (popupTop - pageLLy) / pageHeight}%`; + this.container.append(popup.render()); + return this.container; + } + + } + + class PopupElement { + constructor(parameters) { + this.container = parameters.container; + this.trigger = parameters.trigger; + this.color = parameters.color; + this.titleObj = parameters.titleObj; + this.modificationDate = parameters.modificationDate; + this.contentsObj = parameters.contentsObj; + this.richText = parameters.richText; + this.hideWrapper = parameters.hideWrapper || false; + this.pinned = false; + } + + render() { + const BACKGROUND_ENLIGHT = 0.7; + const wrapper = document.createElement("div"); + wrapper.className = "popupWrapper"; + this.hideElement = this.hideWrapper ? wrapper : this.container; + this.hideElement.hidden = true; + const popup = document.createElement("div"); + popup.className = "popup"; + const color = this.color; + + if (color) { + const r = BACKGROUND_ENLIGHT * (255 - color[0]) + color[0]; + const g = BACKGROUND_ENLIGHT * (255 - color[1]) + color[1]; + const b = BACKGROUND_ENLIGHT * (255 - color[2]) + color[2]; + popup.style.backgroundColor = _util.Util.makeHexColor(r | 0, g | 0, b | 0); + } + + const title = document.createElement("h1"); + title.dir = this.titleObj.dir; + title.textContent = this.titleObj.str; + popup.append(title); + + const dateObject = _display_utils.PDFDateString.toDateObject(this.modificationDate); + + if (dateObject) { + const modificationDate = document.createElement("span"); + modificationDate.className = "popupDate"; + modificationDate.textContent = "{{date}}, {{time}}"; + modificationDate.dataset.l10nId = "annotation_date_string"; + modificationDate.dataset.l10nArgs = JSON.stringify({ + date: dateObject.toLocaleDateString(), + time: dateObject.toLocaleTimeString() + }); + popup.append(modificationDate); + } + + if (this.richText?.str && (!this.contentsObj?.str || this.contentsObj.str === this.richText.str)) { + _xfa_layer.XfaLayer.render({ + xfaHtml: this.richText.html, + intent: "richText", + div: popup + }); + + popup.lastChild.className = "richText popupContent"; + } else { + const contents = this._formatContents(this.contentsObj); + + popup.append(contents); + } + + if (!Array.isArray(this.trigger)) { + this.trigger = [this.trigger]; + } + + for (const element of this.trigger) { + element.addEventListener("click", this._toggle.bind(this)); + element.addEventListener("mouseover", this._show.bind(this, false)); + element.addEventListener("mouseout", this._hide.bind(this, false)); + } + + popup.addEventListener("click", this._hide.bind(this, true)); + wrapper.append(popup); + return wrapper; + } + + _formatContents({ + str, + dir + }) { + const p = document.createElement("p"); + p.className = "popupContent"; + p.dir = dir; + const lines = str.split(/(?:\r\n?|\n)/); + + for (let i = 0, ii = lines.length; i < ii; ++i) { + const line = lines[i]; + p.append(document.createTextNode(line)); + + if (i < ii - 1) { + p.append(document.createElement("br")); + } + } + + return p; + } + + _toggle() { + if (this.pinned) { + this._hide(true); + } else { + this._show(true); + } + } + + _show(pin = false) { + if (pin) { + this.pinned = true; + } + + if (this.hideElement.hidden) { + this.hideElement.hidden = false; + this.container.style.zIndex = parseInt(this.container.style.zIndex) + 1000; + } + } + + _hide(unpin = true) { + if (unpin) { + this.pinned = false; + } + + if (!this.hideElement.hidden && !this.pinned) { + this.hideElement.hidden = true; + this.container.style.zIndex = parseInt(this.container.style.zIndex) - 1000; + } + } + + } + + class FreeTextAnnotationElement extends AnnotationElement { + constructor(parameters) { + const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str); + super(parameters, { + isRenderable, + ignoreBorder: true + }); + this.textContent = parameters.data.textContent; + } + + render() { + this.container.className = "freeTextAnnotation"; + + if (this.textContent) { + const content = document.createElement("div"); + content.className = "annotationTextContent"; + content.setAttribute("role", "comment"); + + for (const line of this.textContent) { + const lineSpan = document.createElement("span"); + lineSpan.textContent = line; + content.append(lineSpan); + } + + this.container.append(content); + } + + if (!this.data.hasPopup) { + this._createPopup(null, this.data); + } + + return this.container; + } + + } + + class LineAnnotationElement extends AnnotationElement { + constructor(parameters) { + const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str); + super(parameters, { + isRenderable, + ignoreBorder: true + }); + } + + render() { + this.container.className = "lineAnnotation"; + const data = this.data; + const { + width, + height + } = getRectDims(data.rect); + const svg = this.svgFactory.create(width, height, true); + const line = this.svgFactory.createElement("svg:line"); + line.setAttribute("x1", data.rect[2] - data.lineCoordinates[0]); + line.setAttribute("y1", data.rect[3] - data.lineCoordinates[1]); + line.setAttribute("x2", data.rect[2] - data.lineCoordinates[2]); + line.setAttribute("y2", data.rect[3] - data.lineCoordinates[3]); + line.setAttribute("stroke-width", data.borderStyle.width || 1); + line.setAttribute("stroke", "transparent"); + line.setAttribute("fill", "transparent"); + svg.append(line); + this.container.append(svg); + + this._createPopup(line, data); + + return this.container; + } + + } + + class SquareAnnotationElement extends AnnotationElement { + constructor(parameters) { + const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str); + super(parameters, { + isRenderable, + ignoreBorder: true + }); + } + + render() { + this.container.className = "squareAnnotation"; + const data = this.data; + const { + width, + height + } = getRectDims(data.rect); + const svg = this.svgFactory.create(width, height, true); + const borderWidth = data.borderStyle.width; + const square = this.svgFactory.createElement("svg:rect"); + square.setAttribute("x", borderWidth / 2); + square.setAttribute("y", borderWidth / 2); + square.setAttribute("width", width - borderWidth); + square.setAttribute("height", height - borderWidth); + square.setAttribute("stroke-width", borderWidth || 1); + square.setAttribute("stroke", "transparent"); + square.setAttribute("fill", "transparent"); + svg.append(square); + this.container.append(svg); + + this._createPopup(square, data); + + return this.container; + } + + } + + class CircleAnnotationElement extends AnnotationElement { + constructor(parameters) { + const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str); + super(parameters, { + isRenderable, + ignoreBorder: true + }); + } + + render() { + this.container.className = "circleAnnotation"; + const data = this.data; + const { + width, + height + } = getRectDims(data.rect); + const svg = this.svgFactory.create(width, height, true); + const borderWidth = data.borderStyle.width; + const circle = this.svgFactory.createElement("svg:ellipse"); + circle.setAttribute("cx", width / 2); + circle.setAttribute("cy", height / 2); + circle.setAttribute("rx", width / 2 - borderWidth / 2); + circle.setAttribute("ry", height / 2 - borderWidth / 2); + circle.setAttribute("stroke-width", borderWidth || 1); + circle.setAttribute("stroke", "transparent"); + circle.setAttribute("fill", "transparent"); + svg.append(circle); + this.container.append(svg); + + this._createPopup(circle, data); + + return this.container; + } + + } + + class PolylineAnnotationElement extends AnnotationElement { + constructor(parameters) { + const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str); + super(parameters, { + isRenderable, + ignoreBorder: true + }); + this.containerClassName = "polylineAnnotation"; + this.svgElementName = "svg:polyline"; + } + + render() { + this.container.className = this.containerClassName; + const data = this.data; + const { + width, + height + } = getRectDims(data.rect); + const svg = this.svgFactory.create(width, height, true); + let points = []; + + for (const coordinate of data.vertices) { + const x = coordinate.x - data.rect[0]; + const y = data.rect[3] - coordinate.y; + points.push(x + "," + y); + } + + points = points.join(" "); + const polyline = this.svgFactory.createElement(this.svgElementName); + polyline.setAttribute("points", points); + polyline.setAttribute("stroke-width", data.borderStyle.width || 1); + polyline.setAttribute("stroke", "transparent"); + polyline.setAttribute("fill", "transparent"); + svg.append(polyline); + this.container.append(svg); + + this._createPopup(polyline, data); + + return this.container; + } + + } + + class PolygonAnnotationElement extends PolylineAnnotationElement { + constructor(parameters) { + super(parameters); + this.containerClassName = "polygonAnnotation"; + this.svgElementName = "svg:polygon"; + } + + } + + class CaretAnnotationElement extends AnnotationElement { + constructor(parameters) { + const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str); + super(parameters, { + isRenderable, + ignoreBorder: true + }); + } + + render() { + this.container.className = "caretAnnotation"; + + if (!this.data.hasPopup) { + this._createPopup(null, this.data); + } + + return this.container; + } + + } + + class InkAnnotationElement extends AnnotationElement { + constructor(parameters) { + const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str); + super(parameters, { + isRenderable, + ignoreBorder: true + }); + this.containerClassName = "inkAnnotation"; + this.svgElementName = "svg:polyline"; + } + + render() { + this.container.className = this.containerClassName; + const data = this.data; + const { + width, + height + } = getRectDims(data.rect); + const svg = this.svgFactory.create(width, height, true); + + for (const inkList of data.inkLists) { + let points = []; + + for (const coordinate of inkList) { + const x = coordinate.x - data.rect[0]; + const y = data.rect[3] - coordinate.y; + points.push(`${x},${y}`); + } + + points = points.join(" "); + const polyline = this.svgFactory.createElement(this.svgElementName); + polyline.setAttribute("points", points); + polyline.setAttribute("stroke-width", data.borderStyle.width || 1); + polyline.setAttribute("stroke", "transparent"); + polyline.setAttribute("fill", "transparent"); + + this._createPopup(polyline, data); + + svg.append(polyline); + } + + this.container.append(svg); + return this.container; + } + + } + + class HighlightAnnotationElement extends AnnotationElement { + constructor(parameters) { + const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str); + super(parameters, { + isRenderable, + ignoreBorder: true, + createQuadrilaterals: true + }); + } + + render() { + if (!this.data.hasPopup) { + this._createPopup(null, this.data); + } + + if (this.quadrilaterals) { + return this._renderQuadrilaterals("highlightAnnotation"); + } + + this.container.className = "highlightAnnotation"; + return this.container; + } + + } + + class UnderlineAnnotationElement extends AnnotationElement { + constructor(parameters) { + const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str); + super(parameters, { + isRenderable, + ignoreBorder: true, + createQuadrilaterals: true + }); + } + + render() { + if (!this.data.hasPopup) { + this._createPopup(null, this.data); + } + + if (this.quadrilaterals) { + return this._renderQuadrilaterals("underlineAnnotation"); + } + + this.container.className = "underlineAnnotation"; + return this.container; + } + + } + + class SquigglyAnnotationElement extends AnnotationElement { + constructor(parameters) { + const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str); + super(parameters, { + isRenderable, + ignoreBorder: true, + createQuadrilaterals: true + }); + } + + render() { + if (!this.data.hasPopup) { + this._createPopup(null, this.data); + } + + if (this.quadrilaterals) { + return this._renderQuadrilaterals("squigglyAnnotation"); + } + + this.container.className = "squigglyAnnotation"; + return this.container; + } + + } + + class StrikeOutAnnotationElement extends AnnotationElement { + constructor(parameters) { + const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str); + super(parameters, { + isRenderable, + ignoreBorder: true, + createQuadrilaterals: true + }); + } + + render() { + if (!this.data.hasPopup) { + this._createPopup(null, this.data); + } + + if (this.quadrilaterals) { + return this._renderQuadrilaterals("strikeoutAnnotation"); + } + + this.container.className = "strikeoutAnnotation"; + return this.container; + } + + } + + class StampAnnotationElement extends AnnotationElement { + constructor(parameters) { + const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str); + super(parameters, { + isRenderable, + ignoreBorder: true + }); + } + + render() { + this.container.className = "stampAnnotation"; + + if (!this.data.hasPopup) { + this._createPopup(null, this.data); + } + + return this.container; + } + + } + + class FileAttachmentAnnotationElement extends AnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: true + }); + const { + filename, + content + } = this.data.file; + this.filename = (0, _display_utils.getFilenameFromUrl)(filename); + this.content = content; + this.linkService.eventBus?.dispatch("fileattachmentannotation", { + source: this, + filename, + content + }); + } + + render() { + this.container.className = "fileAttachmentAnnotation"; + const trigger = document.createElement("div"); + trigger.className = "popupTriggerArea"; + trigger.addEventListener("dblclick", this._download.bind(this)); + + if (!this.data.hasPopup && (this.data.titleObj?.str || this.data.contentsObj?.str || this.data.richText)) { + this._createPopup(trigger, this.data); + } + + this.container.append(trigger); + return this.container; + } + + _download() { + this.downloadManager?.openOrDownloadData(this.container, this.content, this.filename); + } + + } + + class AnnotationLayer { + static #appendElement(element, id, div, accessibilityManager) { + const contentElement = element.firstChild || element; + contentElement.id = `${_display_utils.AnnotationPrefix}${id}`; + div.append(element); + accessibilityManager?.moveElementInDOM(div, element, contentElement, false); + } + + static render(parameters) { + const { + annotations, + div, + viewport, + accessibilityManager + } = parameters; + this.#setDimensions(div, viewport); + let zIndex = 0; + + for (const data of annotations) { + if (data.annotationType !== _util.AnnotationType.POPUP) { + const { + width, + height + } = getRectDims(data.rect); + + if (width <= 0 || height <= 0) { + continue; + } + } + + const element = AnnotationElementFactory.create({ + data, + layer: div, + page: parameters.page, + viewport, + linkService: parameters.linkService, + downloadManager: parameters.downloadManager, + imageResourcesPath: parameters.imageResourcesPath || "", + renderForms: parameters.renderForms !== false, + svgFactory: new _display_utils.DOMSVGFactory(), + annotationStorage: parameters.annotationStorage || new _annotation_storage.AnnotationStorage(), + enableScripting: parameters.enableScripting, + hasJSActions: parameters.hasJSActions, + fieldObjects: parameters.fieldObjects, + mouseState: parameters.mouseState || { + isDown: false + } + }); + + if (element.isRenderable) { + const rendered = element.render(); + + if (data.hidden) { + rendered.style.visibility = "hidden"; + } + + if (Array.isArray(rendered)) { + for (const renderedElement of rendered) { + renderedElement.style.zIndex = zIndex++; + AnnotationLayer.#appendElement(renderedElement, data.id, div, accessibilityManager); + } + } else { + rendered.style.zIndex = zIndex++; + + if (element instanceof PopupAnnotationElement) { + div.prepend(rendered); + } else { + AnnotationLayer.#appendElement(rendered, data.id, div, accessibilityManager); + } + } + } + } + + this.#setAnnotationCanvasMap(div, parameters.annotationCanvasMap); + } + + static update(parameters) { + const { + annotationCanvasMap, + div, + viewport + } = parameters; + this.#setDimensions(div, viewport); + this.#setAnnotationCanvasMap(div, annotationCanvasMap); + div.hidden = false; + } + + static #setDimensions(div, { + width, + height, + rotation + }) { + const { + style + } = div; + const flipOrientation = rotation % 180 !== 0, + widthStr = Math.floor(width) + "px", + heightStr = Math.floor(height) + "px"; + style.width = flipOrientation ? heightStr : widthStr; + style.height = flipOrientation ? widthStr : heightStr; + div.setAttribute("data-main-rotation", rotation); + } + + static #setAnnotationCanvasMap(div, annotationCanvasMap) { + if (!annotationCanvasMap) { + return; + } + + for (const [id, canvas] of annotationCanvasMap) { + const element = div.querySelector(`[data-annotation-id="${id}"]`); + + if (!element) { + continue; + } + + const { + firstChild + } = element; + + if (!firstChild) { + element.append(canvas); + } else if (firstChild.nodeName === "CANVAS") { + firstChild.replaceWith(canvas); + } else { + firstChild.before(canvas); + } + } + + annotationCanvasMap.clear(); + } + + } + + exports.AnnotationLayer = AnnotationLayer; + + /***/ }), + /* 28 */ + /***/ ((__unused_webpack_module, exports) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.ColorConverters = void 0; + + function makeColorComp(n) { + return Math.floor(Math.max(0, Math.min(1, n)) * 255).toString(16).padStart(2, "0"); + } + + class ColorConverters { + static CMYK_G([c, y, m, k]) { + return ["G", 1 - Math.min(1, 0.3 * c + 0.59 * m + 0.11 * y + k)]; + } + + static G_CMYK([g]) { + return ["CMYK", 0, 0, 0, 1 - g]; + } + + static G_RGB([g]) { + return ["RGB", g, g, g]; + } + + static G_HTML([g]) { + const G = makeColorComp(g); + return `#${G}${G}${G}`; + } + + static RGB_G([r, g, b]) { + return ["G", 0.3 * r + 0.59 * g + 0.11 * b]; + } + + static RGB_HTML([r, g, b]) { + const R = makeColorComp(r); + const G = makeColorComp(g); + const B = makeColorComp(b); + return `#${R}${G}${B}`; + } + + static T_HTML() { + return "#00000000"; + } + + static CMYK_RGB([c, y, m, k]) { + return ["RGB", 1 - Math.min(1, c + k), 1 - Math.min(1, m + k), 1 - Math.min(1, y + k)]; + } + + static CMYK_HTML(components) { + const rgb = this.CMYK_RGB(components).slice(1); + return this.RGB_HTML(rgb); + } + + static RGB_CMYK([r, g, b]) { + const c = 1 - r; + const m = 1 - g; + const y = 1 - b; + const k = Math.min(c, m, y); + return ["CMYK", c, m, y, k]; + } + + } + + exports.ColorConverters = ColorConverters; + + /***/ }), + /* 29 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.XfaLayer = void 0; + + var _xfa_text = __w_pdfjs_require__(20); + + class XfaLayer { + static setupStorage(html, id, element, storage, intent) { + const storedData = storage.getValue(id, { + value: null + }); + + switch (element.name) { + case "textarea": + if (storedData.value !== null) { + html.textContent = storedData.value; + } + + if (intent === "print") { + break; + } + + html.addEventListener("input", event => { + storage.setValue(id, { + value: event.target.value + }); + }); + break; + + case "input": + if (element.attributes.type === "radio" || element.attributes.type === "checkbox") { + if (storedData.value === element.attributes.xfaOn) { + html.setAttribute("checked", true); + } else if (storedData.value === element.attributes.xfaOff) { + html.removeAttribute("checked"); + } + + if (intent === "print") { + break; + } + + html.addEventListener("change", event => { + storage.setValue(id, { + value: event.target.checked ? event.target.getAttribute("xfaOn") : event.target.getAttribute("xfaOff") + }); + }); + } else { + if (storedData.value !== null) { + html.setAttribute("value", storedData.value); + } + + if (intent === "print") { + break; + } + + html.addEventListener("input", event => { + storage.setValue(id, { + value: event.target.value + }); + }); + } + + break; + + case "select": + if (storedData.value !== null) { + for (const option of element.children) { + if (option.attributes.value === storedData.value) { + option.attributes.selected = true; + } + } + } + + html.addEventListener("input", event => { + const options = event.target.options; + const value = options.selectedIndex === -1 ? "" : options[options.selectedIndex].value; + storage.setValue(id, { + value + }); + }); + break; + } + } + + static setAttributes({ + html, + element, + storage = null, + intent, + linkService + }) { + const { + attributes + } = element; + const isHTMLAnchorElement = html instanceof HTMLAnchorElement; + + if (attributes.type === "radio") { + attributes.name = `${attributes.name}-${intent}`; + } + + for (const [key, value] of Object.entries(attributes)) { + if (value === null || value === undefined) { + continue; + } + + switch (key) { + case "class": + if (value.length) { + html.setAttribute(key, value.join(" ")); + } + + break; + + case "dataId": + break; + + case "id": + html.setAttribute("data-element-id", value); + break; + + case "style": + Object.assign(html.style, value); + break; + + case "textContent": + html.textContent = value; + break; + + default: + if (!isHTMLAnchorElement || key !== "href" && key !== "newWindow") { + html.setAttribute(key, value); + } + + } + } + + if (isHTMLAnchorElement) { + linkService.addLinkAttributes(html, attributes.href, attributes.newWindow); + } + + if (storage && attributes.dataId) { + this.setupStorage(html, attributes.dataId, element, storage); + } + } + + static render(parameters) { + const storage = parameters.annotationStorage; + const linkService = parameters.linkService; + const root = parameters.xfaHtml; + const intent = parameters.intent || "display"; + const rootHtml = document.createElement(root.name); + + if (root.attributes) { + this.setAttributes({ + html: rootHtml, + element: root, + intent, + linkService + }); + } + + const stack = [[root, -1, rootHtml]]; + const rootDiv = parameters.div; + rootDiv.append(rootHtml); + + if (parameters.viewport) { + const transform = `matrix(${parameters.viewport.transform.join(",")})`; + rootDiv.style.transform = transform; + } + + if (intent !== "richText") { + rootDiv.setAttribute("class", "xfaLayer xfaFont"); + } + + const textDivs = []; + + while (stack.length > 0) { + const [parent, i, html] = stack.at(-1); + + if (i + 1 === parent.children.length) { + stack.pop(); + continue; + } + + const child = parent.children[++stack.at(-1)[1]]; + + if (child === null) { + continue; + } + + const { + name + } = child; + + if (name === "#text") { + const node = document.createTextNode(child.value); + textDivs.push(node); + html.append(node); + continue; + } + + let childHtml; + + if (child?.attributes?.xmlns) { + childHtml = document.createElementNS(child.attributes.xmlns, name); + } else { + childHtml = document.createElement(name); + } + + html.append(childHtml); + + if (child.attributes) { + this.setAttributes({ + html: childHtml, + element: child, + storage, + intent, + linkService + }); + } + + if (child.children && child.children.length > 0) { + stack.push([child, -1, childHtml]); + } else if (child.value) { + const node = document.createTextNode(child.value); + + if (_xfa_text.XfaText.shouldBuildText(name)) { + textDivs.push(node); + } + + childHtml.append(node); + } + } + + for (const el of rootDiv.querySelectorAll(".xfaNonInteractive input, .xfaNonInteractive textarea")) { + el.setAttribute("readOnly", true); + } + + return { + textDivs + }; + } + + static update(parameters) { + const transform = `matrix(${parameters.viewport.transform.join(",")})`; + parameters.div.style.transform = transform; + parameters.div.hidden = false; + } + + } + + exports.XfaLayer = XfaLayer; + + /***/ }), + /* 30 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.TextLayerRenderTask = void 0; + exports.renderTextLayer = renderTextLayer; + + var _util = __w_pdfjs_require__(1); + + var _display_utils = __w_pdfjs_require__(8); + + const MAX_TEXT_DIVS_TO_RENDER = 100000; + const DEFAULT_FONT_SIZE = 30; + const DEFAULT_FONT_ASCENT = 0.8; + const ascentCache = new Map(); + const AllWhitespaceRegexp = /^\s+$/g; + + function getAscent(fontFamily, ctx) { + const cachedAscent = ascentCache.get(fontFamily); + + if (cachedAscent) { + return cachedAscent; + } + + ctx.save(); + ctx.font = `${DEFAULT_FONT_SIZE}px ${fontFamily}`; + const metrics = ctx.measureText(""); + let ascent = metrics.fontBoundingBoxAscent; + let descent = Math.abs(metrics.fontBoundingBoxDescent); + + if (ascent) { + ctx.restore(); + const ratio = ascent / (ascent + descent); + ascentCache.set(fontFamily, ratio); + return ratio; + } + + ctx.strokeStyle = "red"; + ctx.clearRect(0, 0, DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE); + ctx.strokeText("g", 0, 0); + let pixels = ctx.getImageData(0, 0, DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE).data; + descent = 0; + + for (let i = pixels.length - 1 - 3; i >= 0; i -= 4) { + if (pixels[i] > 0) { + descent = Math.ceil(i / 4 / DEFAULT_FONT_SIZE); + break; + } + } + + ctx.clearRect(0, 0, DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE); + ctx.strokeText("A", 0, DEFAULT_FONT_SIZE); + pixels = ctx.getImageData(0, 0, DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE).data; + ascent = 0; + + for (let i = 0, ii = pixels.length; i < ii; i += 4) { + if (pixels[i] > 0) { + ascent = DEFAULT_FONT_SIZE - Math.floor(i / 4 / DEFAULT_FONT_SIZE); + break; + } + } + + ctx.restore(); + + if (ascent) { + const ratio = ascent / (ascent + descent); + ascentCache.set(fontFamily, ratio); + return ratio; + } + + ascentCache.set(fontFamily, DEFAULT_FONT_ASCENT); + return DEFAULT_FONT_ASCENT; + } + + function appendText(task, geom, styles, ctx) { + const textDiv = document.createElement("span"); + const textDivProperties = task._enhanceTextSelection ? { + angle: 0, + canvasWidth: 0, + hasText: geom.str !== "", + hasEOL: geom.hasEOL, + originalTransform: null, + paddingBottom: 0, + paddingLeft: 0, + paddingRight: 0, + paddingTop: 0, + scale: 1, + fontSize: 0 + } : { + angle: 0, + canvasWidth: 0, + hasText: geom.str !== "", + hasEOL: geom.hasEOL, + fontSize: 0 + }; + + task._textDivs.push(textDiv); + + const tx = _util.Util.transform(task._viewport.transform, geom.transform); + + let angle = Math.atan2(tx[1], tx[0]); + const style = styles[geom.fontName]; + + if (style.vertical) { + angle += Math.PI / 2; + } + + const fontHeight = Math.hypot(tx[2], tx[3]); + const fontAscent = fontHeight * getAscent(style.fontFamily, ctx); + let left, top; + + if (angle === 0) { + left = tx[4]; + top = tx[5] - fontAscent; + } else { + left = tx[4] + fontAscent * Math.sin(angle); + top = tx[5] - fontAscent * Math.cos(angle); + } + + textDiv.style.left = `${left}px`; + textDiv.style.top = `${top}px`; + textDiv.style.fontSize = `${fontHeight}px`; + textDiv.style.fontFamily = style.fontFamily; + textDivProperties.fontSize = fontHeight; + textDiv.setAttribute("role", "presentation"); + textDiv.textContent = geom.str; + textDiv.dir = geom.dir; + + if (task._fontInspectorEnabled) { + textDiv.dataset.fontName = geom.fontName; + } + + if (angle !== 0) { + textDivProperties.angle = angle * (180 / Math.PI); + } + + let shouldScaleText = false; + + if (geom.str.length > 1 || task._enhanceTextSelection && AllWhitespaceRegexp.test(geom.str)) { + shouldScaleText = true; + } else if (geom.str !== " " && geom.transform[0] !== geom.transform[3]) { + const absScaleX = Math.abs(geom.transform[0]), + absScaleY = Math.abs(geom.transform[3]); + + if (absScaleX !== absScaleY && Math.max(absScaleX, absScaleY) / Math.min(absScaleX, absScaleY) > 1.5) { + shouldScaleText = true; + } + } + + if (shouldScaleText) { + if (style.vertical) { + textDivProperties.canvasWidth = geom.height * task._viewport.scale; + } else { + textDivProperties.canvasWidth = geom.width * task._viewport.scale; + } + } + + task._textDivProperties.set(textDiv, textDivProperties); + + if (task._textContentStream) { + task._layoutText(textDiv); + } + + if (task._enhanceTextSelection && textDivProperties.hasText) { + let angleCos = 1, + angleSin = 0; + + if (angle !== 0) { + angleCos = Math.cos(angle); + angleSin = Math.sin(angle); + } + + const divWidth = (style.vertical ? geom.height : geom.width) * task._viewport.scale; + const divHeight = fontHeight; + let m, b; + + if (angle !== 0) { + m = [angleCos, angleSin, -angleSin, angleCos, left, top]; + b = _util.Util.getAxialAlignedBoundingBox([0, 0, divWidth, divHeight], m); + } else { + b = [left, top, left + divWidth, top + divHeight]; + } + + task._bounds.push({ + left: b[0], + top: b[1], + right: b[2], + bottom: b[3], + div: textDiv, + size: [divWidth, divHeight], + m + }); + } + } + + function render(task) { + if (task._canceled) { + return; + } + + const textDivs = task._textDivs; + const capability = task._capability; + const textDivsLength = textDivs.length; + + if (textDivsLength > MAX_TEXT_DIVS_TO_RENDER) { + task._renderingDone = true; + capability.resolve(); + return; + } + + if (!task._textContentStream) { + for (let i = 0; i < textDivsLength; i++) { + task._layoutText(textDivs[i]); + } + } + + task._renderingDone = true; + capability.resolve(); + } + + function findPositiveMin(ts, offset, count) { + let result = 0; + + for (let i = 0; i < count; i++) { + const t = ts[offset++]; + + if (t > 0) { + result = result ? Math.min(t, result) : t; + } + } + + return result; + } + + function expand(task) { + const bounds = task._bounds; + const viewport = task._viewport; + const expanded = expandBounds(viewport.width, viewport.height, bounds); + + for (let i = 0; i < expanded.length; i++) { + const div = bounds[i].div; + + const divProperties = task._textDivProperties.get(div); + + if (divProperties.angle === 0) { + divProperties.paddingLeft = bounds[i].left - expanded[i].left; + divProperties.paddingTop = bounds[i].top - expanded[i].top; + divProperties.paddingRight = expanded[i].right - bounds[i].right; + divProperties.paddingBottom = expanded[i].bottom - bounds[i].bottom; + + task._textDivProperties.set(div, divProperties); + + continue; + } + + const e = expanded[i], + b = bounds[i]; + const m = b.m, + c = m[0], + s = m[1]; + const points = [[0, 0], [0, b.size[1]], [b.size[0], 0], b.size]; + const ts = new Float64Array(64); + + for (let j = 0, jj = points.length; j < jj; j++) { + const t = _util.Util.applyTransform(points[j], m); + + ts[j + 0] = c && (e.left - t[0]) / c; + ts[j + 4] = s && (e.top - t[1]) / s; + ts[j + 8] = c && (e.right - t[0]) / c; + ts[j + 12] = s && (e.bottom - t[1]) / s; + ts[j + 16] = s && (e.left - t[0]) / -s; + ts[j + 20] = c && (e.top - t[1]) / c; + ts[j + 24] = s && (e.right - t[0]) / -s; + ts[j + 28] = c && (e.bottom - t[1]) / c; + ts[j + 32] = c && (e.left - t[0]) / -c; + ts[j + 36] = s && (e.top - t[1]) / -s; + ts[j + 40] = c && (e.right - t[0]) / -c; + ts[j + 44] = s && (e.bottom - t[1]) / -s; + ts[j + 48] = s && (e.left - t[0]) / s; + ts[j + 52] = c && (e.top - t[1]) / -c; + ts[j + 56] = s && (e.right - t[0]) / s; + ts[j + 60] = c && (e.bottom - t[1]) / -c; + } + + const boxScale = 1 + Math.min(Math.abs(c), Math.abs(s)); + divProperties.paddingLeft = findPositiveMin(ts, 32, 16) / boxScale; + divProperties.paddingTop = findPositiveMin(ts, 48, 16) / boxScale; + divProperties.paddingRight = findPositiveMin(ts, 0, 16) / boxScale; + divProperties.paddingBottom = findPositiveMin(ts, 16, 16) / boxScale; + + task._textDivProperties.set(div, divProperties); + } + } + + function expandBounds(width, height, boxes) { + const bounds = boxes.map(function (box, i) { + return { + x1: box.left, + y1: box.top, + x2: box.right, + y2: box.bottom, + index: i, + x1New: undefined, + x2New: undefined + }; + }); + expandBoundsLTR(width, bounds); + const expanded = new Array(boxes.length); + + for (const b of bounds) { + const i = b.index; + expanded[i] = { + left: b.x1New, + top: 0, + right: b.x2New, + bottom: 0 + }; + } + + boxes.map(function (box, i) { + const e = expanded[i], + b = bounds[i]; + b.x1 = box.top; + b.y1 = width - e.right; + b.x2 = box.bottom; + b.y2 = width - e.left; + b.index = i; + b.x1New = undefined; + b.x2New = undefined; + }); + expandBoundsLTR(height, bounds); + + for (const b of bounds) { + const i = b.index; + expanded[i].top = b.x1New; + expanded[i].bottom = b.x2New; + } + + return expanded; + } + + function expandBoundsLTR(width, bounds) { + bounds.sort(function (a, b) { + return a.x1 - b.x1 || a.index - b.index; + }); + const fakeBoundary = { + x1: -Infinity, + y1: -Infinity, + x2: 0, + y2: Infinity, + index: -1, + x1New: 0, + x2New: 0 + }; + const horizon = [{ + start: -Infinity, + end: Infinity, + boundary: fakeBoundary + }]; + + for (const boundary of bounds) { + let i = 0; + + while (i < horizon.length && horizon[i].end <= boundary.y1) { + i++; + } + + let j = horizon.length - 1; + + while (j >= 0 && horizon[j].start >= boundary.y2) { + j--; + } + + let horizonPart, affectedBoundary; + let q, + k, + maxXNew = -Infinity; + + for (q = i; q <= j; q++) { + horizonPart = horizon[q]; + affectedBoundary = horizonPart.boundary; + let xNew; + + if (affectedBoundary.x2 > boundary.x1) { + xNew = affectedBoundary.index > boundary.index ? affectedBoundary.x1New : boundary.x1; + } else if (affectedBoundary.x2New === undefined) { + xNew = (affectedBoundary.x2 + boundary.x1) / 2; + } else { + xNew = affectedBoundary.x2New; + } + + if (xNew > maxXNew) { + maxXNew = xNew; + } + } + + boundary.x1New = maxXNew; + + for (q = i; q <= j; q++) { + horizonPart = horizon[q]; + affectedBoundary = horizonPart.boundary; + + if (affectedBoundary.x2New === undefined) { + if (affectedBoundary.x2 > boundary.x1) { + if (affectedBoundary.index > boundary.index) { + affectedBoundary.x2New = affectedBoundary.x2; + } + } else { + affectedBoundary.x2New = maxXNew; + } + } else if (affectedBoundary.x2New > maxXNew) { + affectedBoundary.x2New = Math.max(maxXNew, affectedBoundary.x2); + } + } + + const changedHorizon = []; + let lastBoundary = null; + + for (q = i; q <= j; q++) { + horizonPart = horizon[q]; + affectedBoundary = horizonPart.boundary; + const useBoundary = affectedBoundary.x2 > boundary.x2 ? affectedBoundary : boundary; + + if (lastBoundary === useBoundary) { + changedHorizon.at(-1).end = horizonPart.end; + } else { + changedHorizon.push({ + start: horizonPart.start, + end: horizonPart.end, + boundary: useBoundary + }); + lastBoundary = useBoundary; + } + } + + if (horizon[i].start < boundary.y1) { + changedHorizon[0].start = boundary.y1; + changedHorizon.unshift({ + start: horizon[i].start, + end: boundary.y1, + boundary: horizon[i].boundary + }); + } + + if (boundary.y2 < horizon[j].end) { + changedHorizon.at(-1).end = boundary.y2; + changedHorizon.push({ + start: boundary.y2, + end: horizon[j].end, + boundary: horizon[j].boundary + }); + } + + for (q = i; q <= j; q++) { + horizonPart = horizon[q]; + affectedBoundary = horizonPart.boundary; + + if (affectedBoundary.x2New !== undefined) { + continue; + } + + let used = false; + + for (k = i - 1; !used && k >= 0 && horizon[k].start >= affectedBoundary.y1; k--) { + used = horizon[k].boundary === affectedBoundary; + } + + for (k = j + 1; !used && k < horizon.length && horizon[k].end <= affectedBoundary.y2; k++) { + used = horizon[k].boundary === affectedBoundary; + } + + for (k = 0; !used && k < changedHorizon.length; k++) { + used = changedHorizon[k].boundary === affectedBoundary; + } + + if (!used) { + affectedBoundary.x2New = maxXNew; + } + } + + Array.prototype.splice.apply(horizon, [i, j - i + 1, ...changedHorizon]); + } + + for (const horizonPart of horizon) { + const affectedBoundary = horizonPart.boundary; + + if (affectedBoundary.x2New === undefined) { + affectedBoundary.x2New = Math.max(width, affectedBoundary.x2); + } + } + } + + class TextLayerRenderTask { + constructor({ + textContent, + textContentStream, + container, + viewport, + textDivs, + textContentItemsStr, + enhanceTextSelection + }) { + if (enhanceTextSelection) { + (0, _display_utils.deprecated)("The `enhanceTextSelection` functionality will be removed in the future."); + } + + this._textContent = textContent; + this._textContentStream = textContentStream; + this._container = container; + this._document = container.ownerDocument; + this._viewport = viewport; + this._textDivs = textDivs || []; + this._textContentItemsStr = textContentItemsStr || []; + this._enhanceTextSelection = !!enhanceTextSelection; + this._fontInspectorEnabled = !!globalThis.FontInspector?.enabled; + this._reader = null; + this._layoutTextLastFontSize = null; + this._layoutTextLastFontFamily = null; + this._layoutTextCtx = null; + this._textDivProperties = new WeakMap(); + this._renderingDone = false; + this._canceled = false; + this._capability = (0, _util.createPromiseCapability)(); + this._renderTimer = null; + this._bounds = []; + this._devicePixelRatio = globalThis.devicePixelRatio || 1; + + this._capability.promise.finally(() => { + if (!this._enhanceTextSelection) { + this._textDivProperties = null; + } + + if (this._layoutTextCtx) { + this._layoutTextCtx.canvas.width = 0; + this._layoutTextCtx.canvas.height = 0; + this._layoutTextCtx = null; + } + }).catch(() => {}); + } + + get promise() { + return this._capability.promise; + } + + cancel() { + this._canceled = true; + + if (this._reader) { + this._reader.cancel(new _util.AbortException("TextLayer task cancelled.")).catch(() => {}); + + this._reader = null; + } + + if (this._renderTimer !== null) { + clearTimeout(this._renderTimer); + this._renderTimer = null; + } + + this._capability.reject(new Error("TextLayer task cancelled.")); + } + + _processItems(items, styleCache) { + for (let i = 0, len = items.length; i < len; i++) { + if (items[i].str === undefined) { + if (items[i].type === "beginMarkedContentProps" || items[i].type === "beginMarkedContent") { + const parent = this._container; + this._container = document.createElement("span"); + + this._container.classList.add("markedContent"); + + if (items[i].id !== null) { + this._container.setAttribute("id", `${items[i].id}`); + } + + parent.append(this._container); + } else if (items[i].type === "endMarkedContent") { + this._container = this._container.parentNode; + } + + continue; + } + + this._textContentItemsStr.push(items[i].str); + + appendText(this, items[i], styleCache, this._layoutTextCtx); + } + } + + _layoutText(textDiv) { + const textDivProperties = this._textDivProperties.get(textDiv); + + let transform = ""; + + if (textDivProperties.canvasWidth !== 0 && textDivProperties.hasText) { + const { + fontFamily + } = textDiv.style; + const { + fontSize + } = textDivProperties; + + if (fontSize !== this._layoutTextLastFontSize || fontFamily !== this._layoutTextLastFontFamily) { + this._layoutTextCtx.font = `${fontSize * this._devicePixelRatio}px ${fontFamily}`; + this._layoutTextLastFontSize = fontSize; + this._layoutTextLastFontFamily = fontFamily; + } + + const { + width + } = this._layoutTextCtx.measureText(textDiv.textContent); + + if (width > 0) { + const scale = this._devicePixelRatio * textDivProperties.canvasWidth / width; + + if (this._enhanceTextSelection) { + textDivProperties.scale = scale; + } + + transform = `scaleX(${scale})`; + } + } + + if (textDivProperties.angle !== 0) { + transform = `rotate(${textDivProperties.angle}deg) ${transform}`; + } + + if (transform.length > 0) { + if (this._enhanceTextSelection) { + textDivProperties.originalTransform = transform; + } + + textDiv.style.transform = transform; + } + + if (textDivProperties.hasText) { + this._container.append(textDiv); + } + + if (textDivProperties.hasEOL) { + const br = document.createElement("br"); + br.setAttribute("role", "presentation"); + + this._container.append(br); + } + } + + _render(timeout = 0) { + const capability = (0, _util.createPromiseCapability)(); + let styleCache = Object.create(null); + + const canvas = this._document.createElement("canvas"); + + canvas.height = canvas.width = DEFAULT_FONT_SIZE; + this._layoutTextCtx = canvas.getContext("2d", { + alpha: false + }); + + if (this._textContent) { + const textItems = this._textContent.items; + const textStyles = this._textContent.styles; + + this._processItems(textItems, textStyles); + + capability.resolve(); + } else if (this._textContentStream) { + const pump = () => { + this._reader.read().then(({ + value, + done + }) => { + if (done) { + capability.resolve(); + return; + } + + Object.assign(styleCache, value.styles); + + this._processItems(value.items, styleCache); + + pump(); + }, capability.reject); + }; + + this._reader = this._textContentStream.getReader(); + pump(); + } else { + throw new Error('Neither "textContent" nor "textContentStream" parameters specified.'); + } + + capability.promise.then(() => { + styleCache = null; + + if (!timeout) { + render(this); + } else { + this._renderTimer = setTimeout(() => { + render(this); + this._renderTimer = null; + }, timeout); + } + }, this._capability.reject); + } + + expandTextDivs(expandDivs = false) { + if (!this._enhanceTextSelection || !this._renderingDone) { + return; + } + + if (this._bounds !== null) { + expand(this); + this._bounds = null; + } + + const transformBuf = [], + paddingBuf = []; + + for (let i = 0, ii = this._textDivs.length; i < ii; i++) { + const div = this._textDivs[i]; + + const divProps = this._textDivProperties.get(div); + + if (!divProps.hasText) { + continue; + } + + if (expandDivs) { + transformBuf.length = 0; + paddingBuf.length = 0; + + if (divProps.originalTransform) { + transformBuf.push(divProps.originalTransform); + } + + if (divProps.paddingTop > 0) { + paddingBuf.push(`${divProps.paddingTop}px`); + transformBuf.push(`translateY(${-divProps.paddingTop}px)`); + } else { + paddingBuf.push(0); + } + + if (divProps.paddingRight > 0) { + paddingBuf.push(`${divProps.paddingRight / divProps.scale}px`); + } else { + paddingBuf.push(0); + } + + if (divProps.paddingBottom > 0) { + paddingBuf.push(`${divProps.paddingBottom}px`); + } else { + paddingBuf.push(0); + } + + if (divProps.paddingLeft > 0) { + paddingBuf.push(`${divProps.paddingLeft / divProps.scale}px`); + transformBuf.push(`translateX(${-divProps.paddingLeft / divProps.scale}px)`); + } else { + paddingBuf.push(0); + } + + div.style.padding = paddingBuf.join(" "); + + if (transformBuf.length) { + div.style.transform = transformBuf.join(" "); + } + } else { + div.style.padding = null; + div.style.transform = divProps.originalTransform; + } + } + } + + } + + exports.TextLayerRenderTask = TextLayerRenderTask; + + function renderTextLayer(renderParameters) { + const task = new TextLayerRenderTask({ + textContent: renderParameters.textContent, + textContentStream: renderParameters.textContentStream, + container: renderParameters.container, + viewport: renderParameters.viewport, + textDivs: renderParameters.textDivs, + textContentItemsStr: renderParameters.textContentItemsStr, + enhanceTextSelection: renderParameters.enhanceTextSelection + }); + + task._render(renderParameters.timeout); + + return task; + } + + /***/ }), + /* 31 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.SVGGraphics = void 0; + + var _display_utils = __w_pdfjs_require__(8); + + var _util = __w_pdfjs_require__(1); + + var _is_node = __w_pdfjs_require__(3); + + let SVGGraphics = class { + constructor() { + (0, _util.unreachable)("Not implemented: SVGGraphics"); + } + + }; + exports.SVGGraphics = SVGGraphics; + { + const SVG_DEFAULTS = { + fontStyle: "normal", + fontWeight: "normal", + fillColor: "#000000" + }; + const XML_NS = "http://www.w3.org/XML/1998/namespace"; + const XLINK_NS = "http://www.w3.org/1999/xlink"; + const LINE_CAP_STYLES = ["butt", "round", "square"]; + const LINE_JOIN_STYLES = ["miter", "round", "bevel"]; + + const createObjectURL = function (data, contentType = "", forceDataSchema = false) { + if (URL.createObjectURL && typeof Blob !== "undefined" && !forceDataSchema) { + return URL.createObjectURL(new Blob([data], { + type: contentType + })); + } + + const digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + let buffer = `data:${contentType};base64,`; + + for (let i = 0, ii = data.length; i < ii; i += 3) { + const b1 = data[i] & 0xff; + const b2 = data[i + 1] & 0xff; + const b3 = data[i + 2] & 0xff; + const d1 = b1 >> 2, + d2 = (b1 & 3) << 4 | b2 >> 4; + const d3 = i + 1 < ii ? (b2 & 0xf) << 2 | b3 >> 6 : 64; + const d4 = i + 2 < ii ? b3 & 0x3f : 64; + buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4]; + } + + return buffer; + }; + + const convertImgDataToPng = function () { + const PNG_HEADER = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]); + const CHUNK_WRAPPER_SIZE = 12; + const crcTable = new Int32Array(256); + + for (let i = 0; i < 256; i++) { + let c = i; + + for (let h = 0; h < 8; h++) { + if (c & 1) { + c = 0xedb88320 ^ c >> 1 & 0x7fffffff; + } else { + c = c >> 1 & 0x7fffffff; + } + } + + crcTable[i] = c; + } + + function crc32(data, start, end) { + let crc = -1; + + for (let i = start; i < end; i++) { + const a = (crc ^ data[i]) & 0xff; + const b = crcTable[a]; + crc = crc >>> 8 ^ b; + } + + return crc ^ -1; + } + + function writePngChunk(type, body, data, offset) { + let p = offset; + const len = body.length; + data[p] = len >> 24 & 0xff; + data[p + 1] = len >> 16 & 0xff; + data[p + 2] = len >> 8 & 0xff; + data[p + 3] = len & 0xff; + p += 4; + data[p] = type.charCodeAt(0) & 0xff; + data[p + 1] = type.charCodeAt(1) & 0xff; + data[p + 2] = type.charCodeAt(2) & 0xff; + data[p + 3] = type.charCodeAt(3) & 0xff; + p += 4; + data.set(body, p); + p += body.length; + const crc = crc32(data, offset + 4, p); + data[p] = crc >> 24 & 0xff; + data[p + 1] = crc >> 16 & 0xff; + data[p + 2] = crc >> 8 & 0xff; + data[p + 3] = crc & 0xff; + } + + function adler32(data, start, end) { + let a = 1; + let b = 0; + + for (let i = start; i < end; ++i) { + a = (a + (data[i] & 0xff)) % 65521; + b = (b + a) % 65521; + } + + return b << 16 | a; + } + + function deflateSync(literals) { + if (!_is_node.isNodeJS) { + return deflateSyncUncompressed(literals); + } + + try { + let input; + + if (parseInt(process.versions.node) >= 8) { + input = literals; + } else { + input = Buffer.from(literals); + } + + const output = require$$5.deflateSync(input, { + level: 9 + }); + + return output instanceof Uint8Array ? output : new Uint8Array(output); + } catch (e) { + (0, _util.warn)("Not compressing PNG because zlib.deflateSync is unavailable: " + e); + } + + return deflateSyncUncompressed(literals); + } + + function deflateSyncUncompressed(literals) { + let len = literals.length; + const maxBlockLength = 0xffff; + const deflateBlocks = Math.ceil(len / maxBlockLength); + const idat = new Uint8Array(2 + len + deflateBlocks * 5 + 4); + let pi = 0; + idat[pi++] = 0x78; + idat[pi++] = 0x9c; + let pos = 0; + + while (len > maxBlockLength) { + idat[pi++] = 0x00; + idat[pi++] = 0xff; + idat[pi++] = 0xff; + idat[pi++] = 0x00; + idat[pi++] = 0x00; + idat.set(literals.subarray(pos, pos + maxBlockLength), pi); + pi += maxBlockLength; + pos += maxBlockLength; + len -= maxBlockLength; + } + + idat[pi++] = 0x01; + idat[pi++] = len & 0xff; + idat[pi++] = len >> 8 & 0xff; + idat[pi++] = ~len & 0xffff & 0xff; + idat[pi++] = (~len & 0xffff) >> 8 & 0xff; + idat.set(literals.subarray(pos), pi); + pi += literals.length - pos; + const adler = adler32(literals, 0, literals.length); + idat[pi++] = adler >> 24 & 0xff; + idat[pi++] = adler >> 16 & 0xff; + idat[pi++] = adler >> 8 & 0xff; + idat[pi++] = adler & 0xff; + return idat; + } + + function encode(imgData, kind, forceDataSchema, isMask) { + const width = imgData.width; + const height = imgData.height; + let bitDepth, colorType, lineSize; + const bytes = imgData.data; + + switch (kind) { + case _util.ImageKind.GRAYSCALE_1BPP: + colorType = 0; + bitDepth = 1; + lineSize = width + 7 >> 3; + break; + + case _util.ImageKind.RGB_24BPP: + colorType = 2; + bitDepth = 8; + lineSize = width * 3; + break; + + case _util.ImageKind.RGBA_32BPP: + colorType = 6; + bitDepth = 8; + lineSize = width * 4; + break; + + default: + throw new Error("invalid format"); + } + + const literals = new Uint8Array((1 + lineSize) * height); + let offsetLiterals = 0, + offsetBytes = 0; + + for (let y = 0; y < height; ++y) { + literals[offsetLiterals++] = 0; + literals.set(bytes.subarray(offsetBytes, offsetBytes + lineSize), offsetLiterals); + offsetBytes += lineSize; + offsetLiterals += lineSize; + } + + if (kind === _util.ImageKind.GRAYSCALE_1BPP && isMask) { + offsetLiterals = 0; + + for (let y = 0; y < height; y++) { + offsetLiterals++; + + for (let i = 0; i < lineSize; i++) { + literals[offsetLiterals++] ^= 0xff; + } + } + } + + const ihdr = new Uint8Array([width >> 24 & 0xff, width >> 16 & 0xff, width >> 8 & 0xff, width & 0xff, height >> 24 & 0xff, height >> 16 & 0xff, height >> 8 & 0xff, height & 0xff, bitDepth, colorType, 0x00, 0x00, 0x00]); + const idat = deflateSync(literals); + const pngLength = PNG_HEADER.length + CHUNK_WRAPPER_SIZE * 3 + ihdr.length + idat.length; + const data = new Uint8Array(pngLength); + let offset = 0; + data.set(PNG_HEADER, offset); + offset += PNG_HEADER.length; + writePngChunk("IHDR", ihdr, data, offset); + offset += CHUNK_WRAPPER_SIZE + ihdr.length; + writePngChunk("IDATA", idat, data, offset); + offset += CHUNK_WRAPPER_SIZE + idat.length; + writePngChunk("IEND", new Uint8Array(0), data, offset); + return createObjectURL(data, "image/png", forceDataSchema); + } + + return function convertImgDataToPng(imgData, forceDataSchema, isMask) { + const kind = imgData.kind === undefined ? _util.ImageKind.GRAYSCALE_1BPP : imgData.kind; + return encode(imgData, kind, forceDataSchema, isMask); + }; + }(); + + class SVGExtraState { + constructor() { + this.fontSizeScale = 1; + this.fontWeight = SVG_DEFAULTS.fontWeight; + this.fontSize = 0; + this.textMatrix = _util.IDENTITY_MATRIX; + this.fontMatrix = _util.FONT_IDENTITY_MATRIX; + this.leading = 0; + this.textRenderingMode = _util.TextRenderingMode.FILL; + this.textMatrixScale = 1; + this.x = 0; + this.y = 0; + this.lineX = 0; + this.lineY = 0; + this.charSpacing = 0; + this.wordSpacing = 0; + this.textHScale = 1; + this.textRise = 0; + this.fillColor = SVG_DEFAULTS.fillColor; + this.strokeColor = "#000000"; + this.fillAlpha = 1; + this.strokeAlpha = 1; + this.lineWidth = 1; + this.lineJoin = ""; + this.lineCap = ""; + this.miterLimit = 0; + this.dashArray = []; + this.dashPhase = 0; + this.dependencies = []; + this.activeClipUrl = null; + this.clipGroup = null; + this.maskId = ""; + } + + clone() { + return Object.create(this); + } + + setCurrentPoint(x, y) { + this.x = x; + this.y = y; + } + + } + + function opListToTree(opList) { + let opTree = []; + const tmp = []; + + for (const opListElement of opList) { + if (opListElement.fn === "save") { + opTree.push({ + fnId: 92, + fn: "group", + items: [] + }); + tmp.push(opTree); + opTree = opTree.at(-1).items; + continue; + } + + if (opListElement.fn === "restore") { + opTree = tmp.pop(); + } else { + opTree.push(opListElement); + } + } + + return opTree; + } + + function pf(value) { + if (Number.isInteger(value)) { + return value.toString(); + } + + const s = value.toFixed(10); + let i = s.length - 1; + + if (s[i] !== "0") { + return s; + } + + do { + i--; + } while (s[i] === "0"); + + return s.substring(0, s[i] === "." ? i : i + 1); + } + + function pm(m) { + if (m[4] === 0 && m[5] === 0) { + if (m[1] === 0 && m[2] === 0) { + if (m[0] === 1 && m[3] === 1) { + return ""; + } + + return `scale(${pf(m[0])} ${pf(m[3])})`; + } + + if (m[0] === m[3] && m[1] === -m[2]) { + const a = Math.acos(m[0]) * 180 / Math.PI; + return `rotate(${pf(a)})`; + } + } else { + if (m[0] === 1 && m[1] === 0 && m[2] === 0 && m[3] === 1) { + return `translate(${pf(m[4])} ${pf(m[5])})`; + } + } + + return `matrix(${pf(m[0])} ${pf(m[1])} ${pf(m[2])} ${pf(m[3])} ${pf(m[4])} ` + `${pf(m[5])})`; + } + + let clipCount = 0; + let maskCount = 0; + let shadingCount = 0; + exports.SVGGraphics = SVGGraphics = class { + constructor(commonObjs, objs, forceDataSchema = false) { + (0, _display_utils.deprecated)("The SVG back-end is no longer maintained and *may* be removed in the future."); + this.svgFactory = new _display_utils.DOMSVGFactory(); + this.current = new SVGExtraState(); + this.transformMatrix = _util.IDENTITY_MATRIX; + this.transformStack = []; + this.extraStack = []; + this.commonObjs = commonObjs; + this.objs = objs; + this.pendingClip = null; + this.pendingEOFill = false; + this.embedFonts = false; + this.embeddedFonts = Object.create(null); + this.cssStyle = null; + this.forceDataSchema = !!forceDataSchema; + this._operatorIdMapping = []; + + for (const op in _util.OPS) { + this._operatorIdMapping[_util.OPS[op]] = op; + } + } + + save() { + this.transformStack.push(this.transformMatrix); + const old = this.current; + this.extraStack.push(old); + this.current = old.clone(); + } + + restore() { + this.transformMatrix = this.transformStack.pop(); + this.current = this.extraStack.pop(); + this.pendingClip = null; + this.tgrp = null; + } + + group(items) { + this.save(); + this.executeOpTree(items); + this.restore(); + } + + loadDependencies(operatorList) { + const fnArray = operatorList.fnArray; + const argsArray = operatorList.argsArray; + + for (let i = 0, ii = fnArray.length; i < ii; i++) { + if (fnArray[i] !== _util.OPS.dependency) { + continue; + } + + for (const obj of argsArray[i]) { + const objsPool = obj.startsWith("g_") ? this.commonObjs : this.objs; + const promise = new Promise(resolve => { + objsPool.get(obj, resolve); + }); + this.current.dependencies.push(promise); + } + } + + return Promise.all(this.current.dependencies); + } + + transform(a, b, c, d, e, f) { + const transformMatrix = [a, b, c, d, e, f]; + this.transformMatrix = _util.Util.transform(this.transformMatrix, transformMatrix); + this.tgrp = null; + } + + getSVG(operatorList, viewport) { + this.viewport = viewport; + + const svgElement = this._initialize(viewport); + + return this.loadDependencies(operatorList).then(() => { + this.transformMatrix = _util.IDENTITY_MATRIX; + this.executeOpTree(this.convertOpList(operatorList)); + return svgElement; + }); + } + + convertOpList(operatorList) { + const operatorIdMapping = this._operatorIdMapping; + const argsArray = operatorList.argsArray; + const fnArray = operatorList.fnArray; + const opList = []; + + for (let i = 0, ii = fnArray.length; i < ii; i++) { + const fnId = fnArray[i]; + opList.push({ + fnId, + fn: operatorIdMapping[fnId], + args: argsArray[i] + }); + } + + return opListToTree(opList); + } + + executeOpTree(opTree) { + for (const opTreeElement of opTree) { + const fn = opTreeElement.fn; + const fnId = opTreeElement.fnId; + const args = opTreeElement.args; + + switch (fnId | 0) { + case _util.OPS.beginText: + this.beginText(); + break; + + case _util.OPS.dependency: + break; + + case _util.OPS.setLeading: + this.setLeading(args); + break; + + case _util.OPS.setLeadingMoveText: + this.setLeadingMoveText(args[0], args[1]); + break; + + case _util.OPS.setFont: + this.setFont(args); + break; + + case _util.OPS.showText: + this.showText(args[0]); + break; + + case _util.OPS.showSpacedText: + this.showText(args[0]); + break; + + case _util.OPS.endText: + this.endText(); + break; + + case _util.OPS.moveText: + this.moveText(args[0], args[1]); + break; + + case _util.OPS.setCharSpacing: + this.setCharSpacing(args[0]); + break; + + case _util.OPS.setWordSpacing: + this.setWordSpacing(args[0]); + break; + + case _util.OPS.setHScale: + this.setHScale(args[0]); + break; + + case _util.OPS.setTextMatrix: + this.setTextMatrix(args[0], args[1], args[2], args[3], args[4], args[5]); + break; + + case _util.OPS.setTextRise: + this.setTextRise(args[0]); + break; + + case _util.OPS.setTextRenderingMode: + this.setTextRenderingMode(args[0]); + break; + + case _util.OPS.setLineWidth: + this.setLineWidth(args[0]); + break; + + case _util.OPS.setLineJoin: + this.setLineJoin(args[0]); + break; + + case _util.OPS.setLineCap: + this.setLineCap(args[0]); + break; + + case _util.OPS.setMiterLimit: + this.setMiterLimit(args[0]); + break; + + case _util.OPS.setFillRGBColor: + this.setFillRGBColor(args[0], args[1], args[2]); + break; + + case _util.OPS.setStrokeRGBColor: + this.setStrokeRGBColor(args[0], args[1], args[2]); + break; + + case _util.OPS.setStrokeColorN: + this.setStrokeColorN(args); + break; + + case _util.OPS.setFillColorN: + this.setFillColorN(args); + break; + + case _util.OPS.shadingFill: + this.shadingFill(args[0]); + break; + + case _util.OPS.setDash: + this.setDash(args[0], args[1]); + break; + + case _util.OPS.setRenderingIntent: + this.setRenderingIntent(args[0]); + break; + + case _util.OPS.setFlatness: + this.setFlatness(args[0]); + break; + + case _util.OPS.setGState: + this.setGState(args[0]); + break; + + case _util.OPS.fill: + this.fill(); + break; + + case _util.OPS.eoFill: + this.eoFill(); + break; + + case _util.OPS.stroke: + this.stroke(); + break; + + case _util.OPS.fillStroke: + this.fillStroke(); + break; + + case _util.OPS.eoFillStroke: + this.eoFillStroke(); + break; + + case _util.OPS.clip: + this.clip("nonzero"); + break; + + case _util.OPS.eoClip: + this.clip("evenodd"); + break; + + case _util.OPS.paintSolidColorImageMask: + this.paintSolidColorImageMask(); + break; + + case _util.OPS.paintImageXObject: + this.paintImageXObject(args[0]); + break; + + case _util.OPS.paintInlineImageXObject: + this.paintInlineImageXObject(args[0]); + break; + + case _util.OPS.paintImageMaskXObject: + this.paintImageMaskXObject(args[0]); + break; + + case _util.OPS.paintFormXObjectBegin: + this.paintFormXObjectBegin(args[0], args[1]); + break; + + case _util.OPS.paintFormXObjectEnd: + this.paintFormXObjectEnd(); + break; + + case _util.OPS.closePath: + this.closePath(); + break; + + case _util.OPS.closeStroke: + this.closeStroke(); + break; + + case _util.OPS.closeFillStroke: + this.closeFillStroke(); + break; + + case _util.OPS.closeEOFillStroke: + this.closeEOFillStroke(); + break; + + case _util.OPS.nextLine: + this.nextLine(); + break; + + case _util.OPS.transform: + this.transform(args[0], args[1], args[2], args[3], args[4], args[5]); + break; + + case _util.OPS.constructPath: + this.constructPath(args[0], args[1]); + break; + + case _util.OPS.endPath: + this.endPath(); + break; + + case 92: + this.group(opTreeElement.items); + break; + + default: + (0, _util.warn)(`Unimplemented operator ${fn}`); + break; + } + } + } + + setWordSpacing(wordSpacing) { + this.current.wordSpacing = wordSpacing; + } + + setCharSpacing(charSpacing) { + this.current.charSpacing = charSpacing; + } + + nextLine() { + this.moveText(0, this.current.leading); + } + + setTextMatrix(a, b, c, d, e, f) { + const current = this.current; + current.textMatrix = current.lineMatrix = [a, b, c, d, e, f]; + current.textMatrixScale = Math.hypot(a, b); + current.x = current.lineX = 0; + current.y = current.lineY = 0; + current.xcoords = []; + current.ycoords = []; + current.tspan = this.svgFactory.createElement("svg:tspan"); + current.tspan.setAttributeNS(null, "font-family", current.fontFamily); + current.tspan.setAttributeNS(null, "font-size", `${pf(current.fontSize)}px`); + current.tspan.setAttributeNS(null, "y", pf(-current.y)); + current.txtElement = this.svgFactory.createElement("svg:text"); + current.txtElement.append(current.tspan); + } + + beginText() { + const current = this.current; + current.x = current.lineX = 0; + current.y = current.lineY = 0; + current.textMatrix = _util.IDENTITY_MATRIX; + current.lineMatrix = _util.IDENTITY_MATRIX; + current.textMatrixScale = 1; + current.tspan = this.svgFactory.createElement("svg:tspan"); + current.txtElement = this.svgFactory.createElement("svg:text"); + current.txtgrp = this.svgFactory.createElement("svg:g"); + current.xcoords = []; + current.ycoords = []; + } + + moveText(x, y) { + const current = this.current; + current.x = current.lineX += x; + current.y = current.lineY += y; + current.xcoords = []; + current.ycoords = []; + current.tspan = this.svgFactory.createElement("svg:tspan"); + current.tspan.setAttributeNS(null, "font-family", current.fontFamily); + current.tspan.setAttributeNS(null, "font-size", `${pf(current.fontSize)}px`); + current.tspan.setAttributeNS(null, "y", pf(-current.y)); + } + + showText(glyphs) { + const current = this.current; + const font = current.font; + const fontSize = current.fontSize; + + if (fontSize === 0) { + return; + } + + const fontSizeScale = current.fontSizeScale; + const charSpacing = current.charSpacing; + const wordSpacing = current.wordSpacing; + const fontDirection = current.fontDirection; + const textHScale = current.textHScale * fontDirection; + const vertical = font.vertical; + const spacingDir = vertical ? 1 : -1; + const defaultVMetrics = font.defaultVMetrics; + const widthAdvanceScale = fontSize * current.fontMatrix[0]; + let x = 0; + + for (const glyph of glyphs) { + if (glyph === null) { + x += fontDirection * wordSpacing; + continue; + } else if (typeof glyph === "number") { + x += spacingDir * glyph * fontSize / 1000; + continue; + } + + const spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing; + const character = glyph.fontChar; + let scaledX, scaledY; + let width = glyph.width; + + if (vertical) { + let vx; + const vmetric = glyph.vmetric || defaultVMetrics; + vx = glyph.vmetric ? vmetric[1] : width * 0.5; + vx = -vx * widthAdvanceScale; + const vy = vmetric[2] * widthAdvanceScale; + width = vmetric ? -vmetric[0] : width; + scaledX = vx / fontSizeScale; + scaledY = (x + vy) / fontSizeScale; + } else { + scaledX = x / fontSizeScale; + scaledY = 0; + } + + if (glyph.isInFont || font.missingFile) { + current.xcoords.push(current.x + scaledX); + + if (vertical) { + current.ycoords.push(-current.y + scaledY); + } + + current.tspan.textContent += character; + } + + let charWidth; + + if (vertical) { + charWidth = width * widthAdvanceScale - spacing * fontDirection; + } else { + charWidth = width * widthAdvanceScale + spacing * fontDirection; + } + + x += charWidth; + } + + current.tspan.setAttributeNS(null, "x", current.xcoords.map(pf).join(" ")); + + if (vertical) { + current.tspan.setAttributeNS(null, "y", current.ycoords.map(pf).join(" ")); + } else { + current.tspan.setAttributeNS(null, "y", pf(-current.y)); + } + + if (vertical) { + current.y -= x; + } else { + current.x += x * textHScale; + } + + current.tspan.setAttributeNS(null, "font-family", current.fontFamily); + current.tspan.setAttributeNS(null, "font-size", `${pf(current.fontSize)}px`); + + if (current.fontStyle !== SVG_DEFAULTS.fontStyle) { + current.tspan.setAttributeNS(null, "font-style", current.fontStyle); + } + + if (current.fontWeight !== SVG_DEFAULTS.fontWeight) { + current.tspan.setAttributeNS(null, "font-weight", current.fontWeight); + } + + const fillStrokeMode = current.textRenderingMode & _util.TextRenderingMode.FILL_STROKE_MASK; + + if (fillStrokeMode === _util.TextRenderingMode.FILL || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) { + if (current.fillColor !== SVG_DEFAULTS.fillColor) { + current.tspan.setAttributeNS(null, "fill", current.fillColor); + } + + if (current.fillAlpha < 1) { + current.tspan.setAttributeNS(null, "fill-opacity", current.fillAlpha); + } + } else if (current.textRenderingMode === _util.TextRenderingMode.ADD_TO_PATH) { + current.tspan.setAttributeNS(null, "fill", "transparent"); + } else { + current.tspan.setAttributeNS(null, "fill", "none"); + } + + if (fillStrokeMode === _util.TextRenderingMode.STROKE || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) { + const lineWidthScale = 1 / (current.textMatrixScale || 1); + + this._setStrokeAttributes(current.tspan, lineWidthScale); + } + + let textMatrix = current.textMatrix; + + if (current.textRise !== 0) { + textMatrix = textMatrix.slice(); + textMatrix[5] += current.textRise; + } + + current.txtElement.setAttributeNS(null, "transform", `${pm(textMatrix)} scale(${pf(textHScale)}, -1)`); + current.txtElement.setAttributeNS(XML_NS, "xml:space", "preserve"); + current.txtElement.append(current.tspan); + current.txtgrp.append(current.txtElement); + + this._ensureTransformGroup().append(current.txtElement); + } + + setLeadingMoveText(x, y) { + this.setLeading(-y); + this.moveText(x, y); + } + + addFontStyle(fontObj) { + if (!fontObj.data) { + throw new Error("addFontStyle: No font data available, " + 'ensure that the "fontExtraProperties" API parameter is set.'); + } + + if (!this.cssStyle) { + this.cssStyle = this.svgFactory.createElement("svg:style"); + this.cssStyle.setAttributeNS(null, "type", "text/css"); + this.defs.append(this.cssStyle); + } + + const url = createObjectURL(fontObj.data, fontObj.mimetype, this.forceDataSchema); + this.cssStyle.textContent += `@font-face { font-family: "${fontObj.loadedName}";` + ` src: url(${url}); }\n`; + } + + setFont(details) { + const current = this.current; + const fontObj = this.commonObjs.get(details[0]); + let size = details[1]; + current.font = fontObj; + + if (this.embedFonts && !fontObj.missingFile && !this.embeddedFonts[fontObj.loadedName]) { + this.addFontStyle(fontObj); + this.embeddedFonts[fontObj.loadedName] = fontObj; + } + + current.fontMatrix = fontObj.fontMatrix || _util.FONT_IDENTITY_MATRIX; + let bold = "normal"; + + if (fontObj.black) { + bold = "900"; + } else if (fontObj.bold) { + bold = "bold"; + } + + const italic = fontObj.italic ? "italic" : "normal"; + + if (size < 0) { + size = -size; + current.fontDirection = -1; + } else { + current.fontDirection = 1; + } + + current.fontSize = size; + current.fontFamily = fontObj.loadedName; + current.fontWeight = bold; + current.fontStyle = italic; + current.tspan = this.svgFactory.createElement("svg:tspan"); + current.tspan.setAttributeNS(null, "y", pf(-current.y)); + current.xcoords = []; + current.ycoords = []; + } + + endText() { + const current = this.current; + + if (current.textRenderingMode & _util.TextRenderingMode.ADD_TO_PATH_FLAG && current.txtElement?.hasChildNodes()) { + current.element = current.txtElement; + this.clip("nonzero"); + this.endPath(); + } + } + + setLineWidth(width) { + if (width > 0) { + this.current.lineWidth = width; + } + } + + setLineCap(style) { + this.current.lineCap = LINE_CAP_STYLES[style]; + } + + setLineJoin(style) { + this.current.lineJoin = LINE_JOIN_STYLES[style]; + } + + setMiterLimit(limit) { + this.current.miterLimit = limit; + } + + setStrokeAlpha(strokeAlpha) { + this.current.strokeAlpha = strokeAlpha; + } + + setStrokeRGBColor(r, g, b) { + this.current.strokeColor = _util.Util.makeHexColor(r, g, b); + } + + setFillAlpha(fillAlpha) { + this.current.fillAlpha = fillAlpha; + } + + setFillRGBColor(r, g, b) { + this.current.fillColor = _util.Util.makeHexColor(r, g, b); + this.current.tspan = this.svgFactory.createElement("svg:tspan"); + this.current.xcoords = []; + this.current.ycoords = []; + } + + setStrokeColorN(args) { + this.current.strokeColor = this._makeColorN_Pattern(args); + } + + setFillColorN(args) { + this.current.fillColor = this._makeColorN_Pattern(args); + } + + shadingFill(args) { + const width = this.viewport.width; + const height = this.viewport.height; + + const inv = _util.Util.inverseTransform(this.transformMatrix); + + const bl = _util.Util.applyTransform([0, 0], inv); + + const br = _util.Util.applyTransform([0, height], inv); + + const ul = _util.Util.applyTransform([width, 0], inv); + + const ur = _util.Util.applyTransform([width, height], inv); + + const x0 = Math.min(bl[0], br[0], ul[0], ur[0]); + const y0 = Math.min(bl[1], br[1], ul[1], ur[1]); + const x1 = Math.max(bl[0], br[0], ul[0], ur[0]); + const y1 = Math.max(bl[1], br[1], ul[1], ur[1]); + const rect = this.svgFactory.createElement("svg:rect"); + rect.setAttributeNS(null, "x", x0); + rect.setAttributeNS(null, "y", y0); + rect.setAttributeNS(null, "width", x1 - x0); + rect.setAttributeNS(null, "height", y1 - y0); + rect.setAttributeNS(null, "fill", this._makeShadingPattern(args)); + + if (this.current.fillAlpha < 1) { + rect.setAttributeNS(null, "fill-opacity", this.current.fillAlpha); + } + + this._ensureTransformGroup().append(rect); + } + + _makeColorN_Pattern(args) { + if (args[0] === "TilingPattern") { + return this._makeTilingPattern(args); + } + + return this._makeShadingPattern(args); + } + + _makeTilingPattern(args) { + const color = args[1]; + const operatorList = args[2]; + const matrix = args[3] || _util.IDENTITY_MATRIX; + const [x0, y0, x1, y1] = args[4]; + const xstep = args[5]; + const ystep = args[6]; + const paintType = args[7]; + const tilingId = `shading${shadingCount++}`; + + const [tx0, ty0, tx1, ty1] = _util.Util.normalizeRect([..._util.Util.applyTransform([x0, y0], matrix), ..._util.Util.applyTransform([x1, y1], matrix)]); + + const [xscale, yscale] = _util.Util.singularValueDecompose2dScale(matrix); + + const txstep = xstep * xscale; + const tystep = ystep * yscale; + const tiling = this.svgFactory.createElement("svg:pattern"); + tiling.setAttributeNS(null, "id", tilingId); + tiling.setAttributeNS(null, "patternUnits", "userSpaceOnUse"); + tiling.setAttributeNS(null, "width", txstep); + tiling.setAttributeNS(null, "height", tystep); + tiling.setAttributeNS(null, "x", `${tx0}`); + tiling.setAttributeNS(null, "y", `${ty0}`); + const svg = this.svg; + const transformMatrix = this.transformMatrix; + const fillColor = this.current.fillColor; + const strokeColor = this.current.strokeColor; + const bbox = this.svgFactory.create(tx1 - tx0, ty1 - ty0); + this.svg = bbox; + this.transformMatrix = matrix; + + if (paintType === 2) { + const cssColor = _util.Util.makeHexColor(...color); + + this.current.fillColor = cssColor; + this.current.strokeColor = cssColor; + } + + this.executeOpTree(this.convertOpList(operatorList)); + this.svg = svg; + this.transformMatrix = transformMatrix; + this.current.fillColor = fillColor; + this.current.strokeColor = strokeColor; + tiling.append(bbox.childNodes[0]); + this.defs.append(tiling); + return `url(#${tilingId})`; + } + + _makeShadingPattern(args) { + if (typeof args === "string") { + args = this.objs.get(args); + } + + switch (args[0]) { + case "RadialAxial": + const shadingId = `shading${shadingCount++}`; + const colorStops = args[3]; + let gradient; + + switch (args[1]) { + case "axial": + const point0 = args[4]; + const point1 = args[5]; + gradient = this.svgFactory.createElement("svg:linearGradient"); + gradient.setAttributeNS(null, "id", shadingId); + gradient.setAttributeNS(null, "gradientUnits", "userSpaceOnUse"); + gradient.setAttributeNS(null, "x1", point0[0]); + gradient.setAttributeNS(null, "y1", point0[1]); + gradient.setAttributeNS(null, "x2", point1[0]); + gradient.setAttributeNS(null, "y2", point1[1]); + break; + + case "radial": + const focalPoint = args[4]; + const circlePoint = args[5]; + const focalRadius = args[6]; + const circleRadius = args[7]; + gradient = this.svgFactory.createElement("svg:radialGradient"); + gradient.setAttributeNS(null, "id", shadingId); + gradient.setAttributeNS(null, "gradientUnits", "userSpaceOnUse"); + gradient.setAttributeNS(null, "cx", circlePoint[0]); + gradient.setAttributeNS(null, "cy", circlePoint[1]); + gradient.setAttributeNS(null, "r", circleRadius); + gradient.setAttributeNS(null, "fx", focalPoint[0]); + gradient.setAttributeNS(null, "fy", focalPoint[1]); + gradient.setAttributeNS(null, "fr", focalRadius); + break; + + default: + throw new Error(`Unknown RadialAxial type: ${args[1]}`); + } + + for (const colorStop of colorStops) { + const stop = this.svgFactory.createElement("svg:stop"); + stop.setAttributeNS(null, "offset", colorStop[0]); + stop.setAttributeNS(null, "stop-color", colorStop[1]); + gradient.append(stop); + } + + this.defs.append(gradient); + return `url(#${shadingId})`; + + case "Mesh": + (0, _util.warn)("Unimplemented pattern Mesh"); + return null; + + case "Dummy": + return "hotpink"; + + default: + throw new Error(`Unknown IR type: ${args[0]}`); + } + } + + setDash(dashArray, dashPhase) { + this.current.dashArray = dashArray; + this.current.dashPhase = dashPhase; + } + + constructPath(ops, args) { + const current = this.current; + let x = current.x, + y = current.y; + let d = []; + let j = 0; + + for (const op of ops) { + switch (op | 0) { + case _util.OPS.rectangle: + x = args[j++]; + y = args[j++]; + const width = args[j++]; + const height = args[j++]; + const xw = x + width; + const yh = y + height; + d.push("M", pf(x), pf(y), "L", pf(xw), pf(y), "L", pf(xw), pf(yh), "L", pf(x), pf(yh), "Z"); + break; + + case _util.OPS.moveTo: + x = args[j++]; + y = args[j++]; + d.push("M", pf(x), pf(y)); + break; + + case _util.OPS.lineTo: + x = args[j++]; + y = args[j++]; + d.push("L", pf(x), pf(y)); + break; + + case _util.OPS.curveTo: + x = args[j + 4]; + y = args[j + 5]; + d.push("C", pf(args[j]), pf(args[j + 1]), pf(args[j + 2]), pf(args[j + 3]), pf(x), pf(y)); + j += 6; + break; + + case _util.OPS.curveTo2: + d.push("C", pf(x), pf(y), pf(args[j]), pf(args[j + 1]), pf(args[j + 2]), pf(args[j + 3])); + x = args[j + 2]; + y = args[j + 3]; + j += 4; + break; + + case _util.OPS.curveTo3: + x = args[j + 2]; + y = args[j + 3]; + d.push("C", pf(args[j]), pf(args[j + 1]), pf(x), pf(y), pf(x), pf(y)); + j += 4; + break; + + case _util.OPS.closePath: + d.push("Z"); + break; + } + } + + d = d.join(" "); + + if (current.path && ops.length > 0 && ops[0] !== _util.OPS.rectangle && ops[0] !== _util.OPS.moveTo) { + d = current.path.getAttributeNS(null, "d") + d; + } else { + current.path = this.svgFactory.createElement("svg:path"); + + this._ensureTransformGroup().append(current.path); + } + + current.path.setAttributeNS(null, "d", d); + current.path.setAttributeNS(null, "fill", "none"); + current.element = current.path; + current.setCurrentPoint(x, y); + } + + endPath() { + const current = this.current; + current.path = null; + + if (!this.pendingClip) { + return; + } + + if (!current.element) { + this.pendingClip = null; + return; + } + + const clipId = `clippath${clipCount++}`; + const clipPath = this.svgFactory.createElement("svg:clipPath"); + clipPath.setAttributeNS(null, "id", clipId); + clipPath.setAttributeNS(null, "transform", pm(this.transformMatrix)); + const clipElement = current.element.cloneNode(true); + + if (this.pendingClip === "evenodd") { + clipElement.setAttributeNS(null, "clip-rule", "evenodd"); + } else { + clipElement.setAttributeNS(null, "clip-rule", "nonzero"); + } + + this.pendingClip = null; + clipPath.append(clipElement); + this.defs.append(clipPath); + + if (current.activeClipUrl) { + current.clipGroup = null; + + for (const prev of this.extraStack) { + prev.clipGroup = null; + } + + clipPath.setAttributeNS(null, "clip-path", current.activeClipUrl); + } + + current.activeClipUrl = `url(#${clipId})`; + this.tgrp = null; + } + + clip(type) { + this.pendingClip = type; + } + + closePath() { + const current = this.current; + + if (current.path) { + const d = `${current.path.getAttributeNS(null, "d")}Z`; + current.path.setAttributeNS(null, "d", d); + } + } + + setLeading(leading) { + this.current.leading = -leading; + } + + setTextRise(textRise) { + this.current.textRise = textRise; + } + + setTextRenderingMode(textRenderingMode) { + this.current.textRenderingMode = textRenderingMode; + } + + setHScale(scale) { + this.current.textHScale = scale / 100; + } + + setRenderingIntent(intent) {} + + setFlatness(flatness) {} + + setGState(states) { + for (const [key, value] of states) { + switch (key) { + case "LW": + this.setLineWidth(value); + break; + + case "LC": + this.setLineCap(value); + break; + + case "LJ": + this.setLineJoin(value); + break; + + case "ML": + this.setMiterLimit(value); + break; + + case "D": + this.setDash(value[0], value[1]); + break; + + case "RI": + this.setRenderingIntent(value); + break; + + case "FL": + this.setFlatness(value); + break; + + case "Font": + this.setFont(value); + break; + + case "CA": + this.setStrokeAlpha(value); + break; + + case "ca": + this.setFillAlpha(value); + break; + + default: + (0, _util.warn)(`Unimplemented graphic state operator ${key}`); + break; + } + } + } + + fill() { + const current = this.current; + + if (current.element) { + current.element.setAttributeNS(null, "fill", current.fillColor); + current.element.setAttributeNS(null, "fill-opacity", current.fillAlpha); + this.endPath(); + } + } + + stroke() { + const current = this.current; + + if (current.element) { + this._setStrokeAttributes(current.element); + + current.element.setAttributeNS(null, "fill", "none"); + this.endPath(); + } + } + + _setStrokeAttributes(element, lineWidthScale = 1) { + const current = this.current; + let dashArray = current.dashArray; + + if (lineWidthScale !== 1 && dashArray.length > 0) { + dashArray = dashArray.map(function (value) { + return lineWidthScale * value; + }); + } + + element.setAttributeNS(null, "stroke", current.strokeColor); + element.setAttributeNS(null, "stroke-opacity", current.strokeAlpha); + element.setAttributeNS(null, "stroke-miterlimit", pf(current.miterLimit)); + element.setAttributeNS(null, "stroke-linecap", current.lineCap); + element.setAttributeNS(null, "stroke-linejoin", current.lineJoin); + element.setAttributeNS(null, "stroke-width", pf(lineWidthScale * current.lineWidth) + "px"); + element.setAttributeNS(null, "stroke-dasharray", dashArray.map(pf).join(" ")); + element.setAttributeNS(null, "stroke-dashoffset", pf(lineWidthScale * current.dashPhase) + "px"); + } + + eoFill() { + if (this.current.element) { + this.current.element.setAttributeNS(null, "fill-rule", "evenodd"); + } + + this.fill(); + } + + fillStroke() { + this.stroke(); + this.fill(); + } + + eoFillStroke() { + if (this.current.element) { + this.current.element.setAttributeNS(null, "fill-rule", "evenodd"); + } + + this.fillStroke(); + } + + closeStroke() { + this.closePath(); + this.stroke(); + } + + closeFillStroke() { + this.closePath(); + this.fillStroke(); + } + + closeEOFillStroke() { + this.closePath(); + this.eoFillStroke(); + } + + paintSolidColorImageMask() { + const rect = this.svgFactory.createElement("svg:rect"); + rect.setAttributeNS(null, "x", "0"); + rect.setAttributeNS(null, "y", "0"); + rect.setAttributeNS(null, "width", "1px"); + rect.setAttributeNS(null, "height", "1px"); + rect.setAttributeNS(null, "fill", this.current.fillColor); + + this._ensureTransformGroup().append(rect); + } + + paintImageXObject(objId) { + const imgData = objId.startsWith("g_") ? this.commonObjs.get(objId) : this.objs.get(objId); + + if (!imgData) { + (0, _util.warn)(`Dependent image with object ID ${objId} is not ready yet`); + return; + } + + this.paintInlineImageXObject(imgData); + } + + paintInlineImageXObject(imgData, mask) { + const width = imgData.width; + const height = imgData.height; + const imgSrc = convertImgDataToPng(imgData, this.forceDataSchema, !!mask); + const cliprect = this.svgFactory.createElement("svg:rect"); + cliprect.setAttributeNS(null, "x", "0"); + cliprect.setAttributeNS(null, "y", "0"); + cliprect.setAttributeNS(null, "width", pf(width)); + cliprect.setAttributeNS(null, "height", pf(height)); + this.current.element = cliprect; + this.clip("nonzero"); + const imgEl = this.svgFactory.createElement("svg:image"); + imgEl.setAttributeNS(XLINK_NS, "xlink:href", imgSrc); + imgEl.setAttributeNS(null, "x", "0"); + imgEl.setAttributeNS(null, "y", pf(-height)); + imgEl.setAttributeNS(null, "width", pf(width) + "px"); + imgEl.setAttributeNS(null, "height", pf(height) + "px"); + imgEl.setAttributeNS(null, "transform", `scale(${pf(1 / width)} ${pf(-1 / height)})`); + + if (mask) { + mask.append(imgEl); + } else { + this._ensureTransformGroup().append(imgEl); + } + } + + paintImageMaskXObject(imgData) { + const current = this.current; + const width = imgData.width; + const height = imgData.height; + const fillColor = current.fillColor; + current.maskId = `mask${maskCount++}`; + const mask = this.svgFactory.createElement("svg:mask"); + mask.setAttributeNS(null, "id", current.maskId); + const rect = this.svgFactory.createElement("svg:rect"); + rect.setAttributeNS(null, "x", "0"); + rect.setAttributeNS(null, "y", "0"); + rect.setAttributeNS(null, "width", pf(width)); + rect.setAttributeNS(null, "height", pf(height)); + rect.setAttributeNS(null, "fill", fillColor); + rect.setAttributeNS(null, "mask", `url(#${current.maskId})`); + this.defs.append(mask); + + this._ensureTransformGroup().append(rect); + + this.paintInlineImageXObject(imgData, mask); + } + + paintFormXObjectBegin(matrix, bbox) { + if (Array.isArray(matrix) && matrix.length === 6) { + this.transform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]); + } + + if (bbox) { + const width = bbox[2] - bbox[0]; + const height = bbox[3] - bbox[1]; + const cliprect = this.svgFactory.createElement("svg:rect"); + cliprect.setAttributeNS(null, "x", bbox[0]); + cliprect.setAttributeNS(null, "y", bbox[1]); + cliprect.setAttributeNS(null, "width", pf(width)); + cliprect.setAttributeNS(null, "height", pf(height)); + this.current.element = cliprect; + this.clip("nonzero"); + this.endPath(); + } + } + + paintFormXObjectEnd() {} + + _initialize(viewport) { + const svg = this.svgFactory.create(viewport.width, viewport.height); + const definitions = this.svgFactory.createElement("svg:defs"); + svg.append(definitions); + this.defs = definitions; + const rootGroup = this.svgFactory.createElement("svg:g"); + rootGroup.setAttributeNS(null, "transform", pm(viewport.transform)); + svg.append(rootGroup); + this.svg = rootGroup; + return svg; + } + + _ensureClipGroup() { + if (!this.current.clipGroup) { + const clipGroup = this.svgFactory.createElement("svg:g"); + clipGroup.setAttributeNS(null, "clip-path", this.current.activeClipUrl); + this.svg.append(clipGroup); + this.current.clipGroup = clipGroup; + } + + return this.current.clipGroup; + } + + _ensureTransformGroup() { + if (!this.tgrp) { + this.tgrp = this.svgFactory.createElement("svg:g"); + this.tgrp.setAttributeNS(null, "transform", pm(this.transformMatrix)); + + if (this.current.activeClipUrl) { + this._ensureClipGroup().append(this.tgrp); + } else { + this.svg.append(this.tgrp); + } + } + + return this.tgrp; + } + + }; + } + + /***/ }), + /* 32 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.PDFNodeStream = void 0; + + var _util = __w_pdfjs_require__(1); + + var _network_utils = __w_pdfjs_require__(33); + + const fs = require$$5; + + const http = require$$5; + + const https = require$$5; + + const url = require$$5; + + const fileUriRegex = /^file:\/\/\/[a-zA-Z]:\//; + + function parseUrl(sourceUrl) { + const parsedUrl = url.parse(sourceUrl); + + if (parsedUrl.protocol === "file:" || parsedUrl.host) { + return parsedUrl; + } + + if (/^[a-z]:[/\\]/i.test(sourceUrl)) { + return url.parse(`file:///${sourceUrl}`); + } + + if (!parsedUrl.host) { + parsedUrl.protocol = "file:"; + } + + return parsedUrl; + } + + class PDFNodeStream { + constructor(source) { + this.source = source; + this.url = parseUrl(source.url); + this.isHttp = this.url.protocol === "http:" || this.url.protocol === "https:"; + this.isFsUrl = this.url.protocol === "file:"; + this.httpHeaders = this.isHttp && source.httpHeaders || {}; + this._fullRequestReader = null; + this._rangeRequestReaders = []; + } + + get _progressiveDataLength() { + return this._fullRequestReader?._loaded ?? 0; + } + + getFullReader() { + (0, _util.assert)(!this._fullRequestReader, "PDFNodeStream.getFullReader can only be called once."); + this._fullRequestReader = this.isFsUrl ? new PDFNodeStreamFsFullReader(this) : new PDFNodeStreamFullReader(this); + return this._fullRequestReader; + } + + getRangeReader(start, end) { + if (end <= this._progressiveDataLength) { + return null; + } + + const rangeReader = this.isFsUrl ? new PDFNodeStreamFsRangeReader(this, start, end) : new PDFNodeStreamRangeReader(this, start, end); + + this._rangeRequestReaders.push(rangeReader); + + return rangeReader; + } + + cancelAllRequests(reason) { + if (this._fullRequestReader) { + this._fullRequestReader.cancel(reason); + } + + for (const reader of this._rangeRequestReaders.slice(0)) { + reader.cancel(reason); + } + } + + } + + exports.PDFNodeStream = PDFNodeStream; + + class BaseFullReader { + constructor(stream) { + this._url = stream.url; + this._done = false; + this._storedError = null; + this.onProgress = null; + const source = stream.source; + this._contentLength = source.length; + this._loaded = 0; + this._filename = null; + this._disableRange = source.disableRange || false; + this._rangeChunkSize = source.rangeChunkSize; + + if (!this._rangeChunkSize && !this._disableRange) { + this._disableRange = true; + } + + this._isStreamingSupported = !source.disableStream; + this._isRangeSupported = !source.disableRange; + this._readableStream = null; + this._readCapability = (0, _util.createPromiseCapability)(); + this._headersCapability = (0, _util.createPromiseCapability)(); + } + + get headersReady() { + return this._headersCapability.promise; + } + + get filename() { + return this._filename; + } + + get contentLength() { + return this._contentLength; + } + + get isRangeSupported() { + return this._isRangeSupported; + } + + get isStreamingSupported() { + return this._isStreamingSupported; + } + + async read() { + await this._readCapability.promise; + + if (this._done) { + return { + value: undefined, + done: true + }; + } + + if (this._storedError) { + throw this._storedError; + } + + const chunk = this._readableStream.read(); + + if (chunk === null) { + this._readCapability = (0, _util.createPromiseCapability)(); + return this.read(); + } + + this._loaded += chunk.length; + + if (this.onProgress) { + this.onProgress({ + loaded: this._loaded, + total: this._contentLength + }); + } + + const buffer = new Uint8Array(chunk).buffer; + return { + value: buffer, + done: false + }; + } + + cancel(reason) { + if (!this._readableStream) { + this._error(reason); + + return; + } + + this._readableStream.destroy(reason); + } + + _error(reason) { + this._storedError = reason; + + this._readCapability.resolve(); + } + + _setReadableStream(readableStream) { + this._readableStream = readableStream; + readableStream.on("readable", () => { + this._readCapability.resolve(); + }); + readableStream.on("end", () => { + readableStream.destroy(); + this._done = true; + + this._readCapability.resolve(); + }); + readableStream.on("error", reason => { + this._error(reason); + }); + + if (!this._isStreamingSupported && this._isRangeSupported) { + this._error(new _util.AbortException("streaming is disabled")); + } + + if (this._storedError) { + this._readableStream.destroy(this._storedError); + } + } + + } + + class BaseRangeReader { + constructor(stream) { + this._url = stream.url; + this._done = false; + this._storedError = null; + this.onProgress = null; + this._loaded = 0; + this._readableStream = null; + this._readCapability = (0, _util.createPromiseCapability)(); + const source = stream.source; + this._isStreamingSupported = !source.disableStream; + } + + get isStreamingSupported() { + return this._isStreamingSupported; + } + + async read() { + await this._readCapability.promise; + + if (this._done) { + return { + value: undefined, + done: true + }; + } + + if (this._storedError) { + throw this._storedError; + } + + const chunk = this._readableStream.read(); + + if (chunk === null) { + this._readCapability = (0, _util.createPromiseCapability)(); + return this.read(); + } + + this._loaded += chunk.length; + + if (this.onProgress) { + this.onProgress({ + loaded: this._loaded + }); + } + + const buffer = new Uint8Array(chunk).buffer; + return { + value: buffer, + done: false + }; + } + + cancel(reason) { + if (!this._readableStream) { + this._error(reason); + + return; + } + + this._readableStream.destroy(reason); + } + + _error(reason) { + this._storedError = reason; + + this._readCapability.resolve(); + } + + _setReadableStream(readableStream) { + this._readableStream = readableStream; + readableStream.on("readable", () => { + this._readCapability.resolve(); + }); + readableStream.on("end", () => { + readableStream.destroy(); + this._done = true; + + this._readCapability.resolve(); + }); + readableStream.on("error", reason => { + this._error(reason); + }); + + if (this._storedError) { + this._readableStream.destroy(this._storedError); + } + } + + } + + function createRequestOptions(parsedUrl, headers) { + return { + protocol: parsedUrl.protocol, + auth: parsedUrl.auth, + host: parsedUrl.hostname, + port: parsedUrl.port, + path: parsedUrl.path, + method: "GET", + headers + }; + } + + class PDFNodeStreamFullReader extends BaseFullReader { + constructor(stream) { + super(stream); + + const handleResponse = response => { + if (response.statusCode === 404) { + const error = new _util.MissingPDFException(`Missing PDF "${this._url}".`); + this._storedError = error; + + this._headersCapability.reject(error); + + return; + } + + this._headersCapability.resolve(); + + this._setReadableStream(response); + + const getResponseHeader = name => { + return this._readableStream.headers[name.toLowerCase()]; + }; + + const { + allowRangeRequests, + suggestedLength + } = (0, _network_utils.validateRangeRequestCapabilities)({ + getResponseHeader, + isHttp: stream.isHttp, + rangeChunkSize: this._rangeChunkSize, + disableRange: this._disableRange + }); + this._isRangeSupported = allowRangeRequests; + this._contentLength = suggestedLength || this._contentLength; + this._filename = (0, _network_utils.extractFilenameFromHeader)(getResponseHeader); + }; + + this._request = null; + + if (this._url.protocol === "http:") { + this._request = http.request(createRequestOptions(this._url, stream.httpHeaders), handleResponse); + } else { + this._request = https.request(createRequestOptions(this._url, stream.httpHeaders), handleResponse); + } + + this._request.on("error", reason => { + this._storedError = reason; + + this._headersCapability.reject(reason); + }); + + this._request.end(); + } + + } + + class PDFNodeStreamRangeReader extends BaseRangeReader { + constructor(stream, start, end) { + super(stream); + this._httpHeaders = {}; + + for (const property in stream.httpHeaders) { + const value = stream.httpHeaders[property]; + + if (typeof value === "undefined") { + continue; + } + + this._httpHeaders[property] = value; + } + + this._httpHeaders.Range = `bytes=${start}-${end - 1}`; + + const handleResponse = response => { + if (response.statusCode === 404) { + const error = new _util.MissingPDFException(`Missing PDF "${this._url}".`); + this._storedError = error; + return; + } + + this._setReadableStream(response); + }; + + this._request = null; + + if (this._url.protocol === "http:") { + this._request = http.request(createRequestOptions(this._url, this._httpHeaders), handleResponse); + } else { + this._request = https.request(createRequestOptions(this._url, this._httpHeaders), handleResponse); + } + + this._request.on("error", reason => { + this._storedError = reason; + }); + + this._request.end(); + } + + } + + class PDFNodeStreamFsFullReader extends BaseFullReader { + constructor(stream) { + super(stream); + let path = decodeURIComponent(this._url.path); + + if (fileUriRegex.test(this._url.href)) { + path = path.replace(/^\//, ""); + } + + fs.lstat(path, (error, stat) => { + if (error) { + if (error.code === "ENOENT") { + error = new _util.MissingPDFException(`Missing PDF "${path}".`); + } + + this._storedError = error; + + this._headersCapability.reject(error); + + return; + } + + this._contentLength = stat.size; + + this._setReadableStream(fs.createReadStream(path)); + + this._headersCapability.resolve(); + }); + } + + } + + class PDFNodeStreamFsRangeReader extends BaseRangeReader { + constructor(stream, start, end) { + super(stream); + let path = decodeURIComponent(this._url.path); + + if (fileUriRegex.test(this._url.href)) { + path = path.replace(/^\//, ""); + } + + this._setReadableStream(fs.createReadStream(path, { + start, + end: end - 1 + })); + } + + } + + /***/ }), + /* 33 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.createResponseStatusError = createResponseStatusError; + exports.extractFilenameFromHeader = extractFilenameFromHeader; + exports.validateRangeRequestCapabilities = validateRangeRequestCapabilities; + exports.validateResponseStatus = validateResponseStatus; + + var _util = __w_pdfjs_require__(1); + + var _content_disposition = __w_pdfjs_require__(34); + + var _display_utils = __w_pdfjs_require__(8); + + function validateRangeRequestCapabilities({ + getResponseHeader, + isHttp, + rangeChunkSize, + disableRange + }) { + const returnValues = { + allowRangeRequests: false, + suggestedLength: undefined + }; + const length = parseInt(getResponseHeader("Content-Length"), 10); + + if (!Number.isInteger(length)) { + return returnValues; + } + + returnValues.suggestedLength = length; + + if (length <= 2 * rangeChunkSize) { + return returnValues; + } + + if (disableRange || !isHttp) { + return returnValues; + } + + if (getResponseHeader("Accept-Ranges") !== "bytes") { + return returnValues; + } + + const contentEncoding = getResponseHeader("Content-Encoding") || "identity"; + + if (contentEncoding !== "identity") { + return returnValues; + } + + returnValues.allowRangeRequests = true; + return returnValues; + } + + function extractFilenameFromHeader(getResponseHeader) { + const contentDisposition = getResponseHeader("Content-Disposition"); + + if (contentDisposition) { + let filename = (0, _content_disposition.getFilenameFromContentDispositionHeader)(contentDisposition); + + if (filename.includes("%")) { + try { + filename = decodeURIComponent(filename); + } catch (ex) {} + } + + if ((0, _display_utils.isPdfFile)(filename)) { + return filename; + } + } + + return null; + } + + function createResponseStatusError(status, url) { + if (status === 404 || status === 0 && url.startsWith("file:")) { + return new _util.MissingPDFException('Missing PDF "' + url + '".'); + } + + return new _util.UnexpectedResponseException(`Unexpected server response (${status}) while retrieving PDF "${url}".`, status); + } + + function validateResponseStatus(status) { + return status === 200 || status === 206; + } + + /***/ }), + /* 34 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.getFilenameFromContentDispositionHeader = getFilenameFromContentDispositionHeader; + + var _util = __w_pdfjs_require__(1); + + function getFilenameFromContentDispositionHeader(contentDisposition) { + let needsEncodingFixup = true; + let tmp = toParamRegExp("filename\\*", "i").exec(contentDisposition); + + if (tmp) { + tmp = tmp[1]; + let filename = rfc2616unquote(tmp); + filename = unescape(filename); + filename = rfc5987decode(filename); + filename = rfc2047decode(filename); + return fixupEncoding(filename); + } + + tmp = rfc2231getparam(contentDisposition); + + if (tmp) { + const filename = rfc2047decode(tmp); + return fixupEncoding(filename); + } + + tmp = toParamRegExp("filename", "i").exec(contentDisposition); + + if (tmp) { + tmp = tmp[1]; + let filename = rfc2616unquote(tmp); + filename = rfc2047decode(filename); + return fixupEncoding(filename); + } + + function toParamRegExp(attributePattern, flags) { + return new RegExp("(?:^|;)\\s*" + attributePattern + "\\s*=\\s*" + "(" + '[^";\\s][^;\\s]*' + "|" + '"(?:[^"\\\\]|\\\\"?)+"?' + ")", flags); + } + + function textdecode(encoding, value) { + if (encoding) { + if (!/^[\x00-\xFF]+$/.test(value)) { + return value; + } + + try { + const decoder = new TextDecoder(encoding, { + fatal: true + }); + const buffer = (0, _util.stringToBytes)(value); + value = decoder.decode(buffer); + needsEncodingFixup = false; + } catch (e) {} + } + + return value; + } + + function fixupEncoding(value) { + if (needsEncodingFixup && /[\x80-\xff]/.test(value)) { + value = textdecode("utf-8", value); + + if (needsEncodingFixup) { + value = textdecode("iso-8859-1", value); + } + } + + return value; + } + + function rfc2231getparam(contentDispositionStr) { + const matches = []; + let match; + const iter = toParamRegExp("filename\\*((?!0\\d)\\d+)(\\*?)", "ig"); + + while ((match = iter.exec(contentDispositionStr)) !== null) { + let [, n, quot, part] = match; + n = parseInt(n, 10); + + if (n in matches) { + if (n === 0) { + break; + } + + continue; + } + + matches[n] = [quot, part]; + } + + const parts = []; + + for (let n = 0; n < matches.length; ++n) { + if (!(n in matches)) { + break; + } + + let [quot, part] = matches[n]; + part = rfc2616unquote(part); + + if (quot) { + part = unescape(part); + + if (n === 0) { + part = rfc5987decode(part); + } + } + + parts.push(part); + } + + return parts.join(""); + } + + function rfc2616unquote(value) { + if (value.startsWith('"')) { + const parts = value.slice(1).split('\\"'); + + for (let i = 0; i < parts.length; ++i) { + const quotindex = parts[i].indexOf('"'); + + if (quotindex !== -1) { + parts[i] = parts[i].slice(0, quotindex); + parts.length = i + 1; + } + + parts[i] = parts[i].replace(/\\(.)/g, "$1"); + } + + value = parts.join('"'); + } + + return value; + } + + function rfc5987decode(extvalue) { + const encodingend = extvalue.indexOf("'"); + + if (encodingend === -1) { + return extvalue; + } + + const encoding = extvalue.slice(0, encodingend); + const langvalue = extvalue.slice(encodingend + 1); + const value = langvalue.replace(/^[^']*'/, ""); + return textdecode(encoding, value); + } + + function rfc2047decode(value) { + if (!value.startsWith("=?") || /[\x00-\x19\x80-\xff]/.test(value)) { + return value; + } + + return value.replace(/=\?([\w-]*)\?([QqBb])\?((?:[^?]|\?(?!=))*)\?=/g, function (matches, charset, encoding, text) { + if (encoding === "q" || encoding === "Q") { + text = text.replace(/_/g, " "); + text = text.replace(/=([0-9a-fA-F]{2})/g, function (match, hex) { + return String.fromCharCode(parseInt(hex, 16)); + }); + return textdecode(charset, text); + } + + try { + text = atob(text); + } catch (e) {} + + return textdecode(charset, text); + }); + } + + return ""; + } + + /***/ }), + /* 35 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.PDFNetworkStream = void 0; + + var _util = __w_pdfjs_require__(1); + + var _network_utils = __w_pdfjs_require__(33); + const OK_RESPONSE = 200; + const PARTIAL_CONTENT_RESPONSE = 206; + + function getArrayBuffer(xhr) { + const data = xhr.response; + + if (typeof data !== "string") { + return data; + } + + const array = (0, _util.stringToBytes)(data); + return array.buffer; + } + + class NetworkManager { + constructor(url, args = {}) { + this.url = url; + this.isHttp = /^https?:/i.test(url); + this.httpHeaders = this.isHttp && args.httpHeaders || Object.create(null); + this.withCredentials = args.withCredentials || false; + + this.getXhr = args.getXhr || function NetworkManager_getXhr() { + return new XMLHttpRequest(); + }; + + this.currXhrId = 0; + this.pendingRequests = Object.create(null); + } + + requestRange(begin, end, listeners) { + const args = { + begin, + end + }; + + for (const prop in listeners) { + args[prop] = listeners[prop]; + } + + return this.request(args); + } + + requestFull(listeners) { + return this.request(listeners); + } + + request(args) { + const xhr = this.getXhr(); + const xhrId = this.currXhrId++; + const pendingRequest = this.pendingRequests[xhrId] = { + xhr + }; + xhr.open("GET", this.url); + xhr.withCredentials = this.withCredentials; + + for (const property in this.httpHeaders) { + const value = this.httpHeaders[property]; + + if (typeof value === "undefined") { + continue; + } + + xhr.setRequestHeader(property, value); + } + + if (this.isHttp && "begin" in args && "end" in args) { + xhr.setRequestHeader("Range", `bytes=${args.begin}-${args.end - 1}`); + pendingRequest.expectedStatus = PARTIAL_CONTENT_RESPONSE; + } else { + pendingRequest.expectedStatus = OK_RESPONSE; + } + + xhr.responseType = "arraybuffer"; + + if (args.onError) { + xhr.onerror = function (evt) { + args.onError(xhr.status); + }; + } + + xhr.onreadystatechange = this.onStateChange.bind(this, xhrId); + xhr.onprogress = this.onProgress.bind(this, xhrId); + pendingRequest.onHeadersReceived = args.onHeadersReceived; + pendingRequest.onDone = args.onDone; + pendingRequest.onError = args.onError; + pendingRequest.onProgress = args.onProgress; + xhr.send(null); + return xhrId; + } + + onProgress(xhrId, evt) { + const pendingRequest = this.pendingRequests[xhrId]; + + if (!pendingRequest) { + return; + } + + pendingRequest.onProgress?.(evt); + } + + onStateChange(xhrId, evt) { + const pendingRequest = this.pendingRequests[xhrId]; + + if (!pendingRequest) { + return; + } + + const xhr = pendingRequest.xhr; + + if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) { + pendingRequest.onHeadersReceived(); + delete pendingRequest.onHeadersReceived; + } + + if (xhr.readyState !== 4) { + return; + } + + if (!(xhrId in this.pendingRequests)) { + return; + } + + delete this.pendingRequests[xhrId]; + + if (xhr.status === 0 && this.isHttp) { + pendingRequest.onError?.(xhr.status); + return; + } + + const xhrStatus = xhr.status || OK_RESPONSE; + const ok_response_on_range_request = xhrStatus === OK_RESPONSE && pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE; + + if (!ok_response_on_range_request && xhrStatus !== pendingRequest.expectedStatus) { + pendingRequest.onError?.(xhr.status); + return; + } + + const chunk = getArrayBuffer(xhr); + + if (xhrStatus === PARTIAL_CONTENT_RESPONSE) { + const rangeHeader = xhr.getResponseHeader("Content-Range"); + const matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader); + pendingRequest.onDone({ + begin: parseInt(matches[1], 10), + chunk + }); + } else if (chunk) { + pendingRequest.onDone({ + begin: 0, + chunk + }); + } else { + pendingRequest.onError?.(xhr.status); + } + } + + getRequestXhr(xhrId) { + return this.pendingRequests[xhrId].xhr; + } + + isPendingRequest(xhrId) { + return xhrId in this.pendingRequests; + } + + abortRequest(xhrId) { + const xhr = this.pendingRequests[xhrId].xhr; + delete this.pendingRequests[xhrId]; + xhr.abort(); + } + + } + + class PDFNetworkStream { + constructor(source) { + this._source = source; + this._manager = new NetworkManager(source.url, { + httpHeaders: source.httpHeaders, + withCredentials: source.withCredentials + }); + this._rangeChunkSize = source.rangeChunkSize; + this._fullRequestReader = null; + this._rangeRequestReaders = []; + } + + _onRangeRequestReaderClosed(reader) { + const i = this._rangeRequestReaders.indexOf(reader); + + if (i >= 0) { + this._rangeRequestReaders.splice(i, 1); + } + } + + getFullReader() { + (0, _util.assert)(!this._fullRequestReader, "PDFNetworkStream.getFullReader can only be called once."); + this._fullRequestReader = new PDFNetworkStreamFullRequestReader(this._manager, this._source); + return this._fullRequestReader; + } + + getRangeReader(begin, end) { + const reader = new PDFNetworkStreamRangeRequestReader(this._manager, begin, end); + reader.onClosed = this._onRangeRequestReaderClosed.bind(this); + + this._rangeRequestReaders.push(reader); + + return reader; + } + + cancelAllRequests(reason) { + this._fullRequestReader?.cancel(reason); + + for (const reader of this._rangeRequestReaders.slice(0)) { + reader.cancel(reason); + } + } + + } + + exports.PDFNetworkStream = PDFNetworkStream; + + class PDFNetworkStreamFullRequestReader { + constructor(manager, source) { + this._manager = manager; + const args = { + onHeadersReceived: this._onHeadersReceived.bind(this), + onDone: this._onDone.bind(this), + onError: this._onError.bind(this), + onProgress: this._onProgress.bind(this) + }; + this._url = source.url; + this._fullRequestId = manager.requestFull(args); + this._headersReceivedCapability = (0, _util.createPromiseCapability)(); + this._disableRange = source.disableRange || false; + this._contentLength = source.length; + this._rangeChunkSize = source.rangeChunkSize; + + if (!this._rangeChunkSize && !this._disableRange) { + this._disableRange = true; + } + + this._isStreamingSupported = false; + this._isRangeSupported = false; + this._cachedChunks = []; + this._requests = []; + this._done = false; + this._storedError = undefined; + this._filename = null; + this.onProgress = null; + } + + _onHeadersReceived() { + const fullRequestXhrId = this._fullRequestId; + + const fullRequestXhr = this._manager.getRequestXhr(fullRequestXhrId); + + const getResponseHeader = name => { + return fullRequestXhr.getResponseHeader(name); + }; + + const { + allowRangeRequests, + suggestedLength + } = (0, _network_utils.validateRangeRequestCapabilities)({ + getResponseHeader, + isHttp: this._manager.isHttp, + rangeChunkSize: this._rangeChunkSize, + disableRange: this._disableRange + }); + + if (allowRangeRequests) { + this._isRangeSupported = true; + } + + this._contentLength = suggestedLength || this._contentLength; + this._filename = (0, _network_utils.extractFilenameFromHeader)(getResponseHeader); + + if (this._isRangeSupported) { + this._manager.abortRequest(fullRequestXhrId); + } + + this._headersReceivedCapability.resolve(); + } + + _onDone(data) { + if (data) { + if (this._requests.length > 0) { + const requestCapability = this._requests.shift(); + + requestCapability.resolve({ + value: data.chunk, + done: false + }); + } else { + this._cachedChunks.push(data.chunk); + } + } + + this._done = true; + + if (this._cachedChunks.length > 0) { + return; + } + + for (const requestCapability of this._requests) { + requestCapability.resolve({ + value: undefined, + done: true + }); + } + + this._requests.length = 0; + } + + _onError(status) { + this._storedError = (0, _network_utils.createResponseStatusError)(status, this._url); + + this._headersReceivedCapability.reject(this._storedError); + + for (const requestCapability of this._requests) { + requestCapability.reject(this._storedError); + } + + this._requests.length = 0; + this._cachedChunks.length = 0; + } + + _onProgress(evt) { + this.onProgress?.({ + loaded: evt.loaded, + total: evt.lengthComputable ? evt.total : this._contentLength + }); + } + + get filename() { + return this._filename; + } + + get isRangeSupported() { + return this._isRangeSupported; + } + + get isStreamingSupported() { + return this._isStreamingSupported; + } + + get contentLength() { + return this._contentLength; + } + + get headersReady() { + return this._headersReceivedCapability.promise; + } + + async read() { + if (this._storedError) { + throw this._storedError; + } + + if (this._cachedChunks.length > 0) { + const chunk = this._cachedChunks.shift(); + + return { + value: chunk, + done: false + }; + } + + if (this._done) { + return { + value: undefined, + done: true + }; + } + + const requestCapability = (0, _util.createPromiseCapability)(); + + this._requests.push(requestCapability); + + return requestCapability.promise; + } + + cancel(reason) { + this._done = true; + + this._headersReceivedCapability.reject(reason); + + for (const requestCapability of this._requests) { + requestCapability.resolve({ + value: undefined, + done: true + }); + } + + this._requests.length = 0; + + if (this._manager.isPendingRequest(this._fullRequestId)) { + this._manager.abortRequest(this._fullRequestId); + } + + this._fullRequestReader = null; + } + + } + + class PDFNetworkStreamRangeRequestReader { + constructor(manager, begin, end) { + this._manager = manager; + const args = { + onDone: this._onDone.bind(this), + onError: this._onError.bind(this), + onProgress: this._onProgress.bind(this) + }; + this._url = manager.url; + this._requestId = manager.requestRange(begin, end, args); + this._requests = []; + this._queuedChunk = null; + this._done = false; + this._storedError = undefined; + this.onProgress = null; + this.onClosed = null; + } + + _close() { + this.onClosed?.(this); + } + + _onDone(data) { + const chunk = data.chunk; + + if (this._requests.length > 0) { + const requestCapability = this._requests.shift(); + + requestCapability.resolve({ + value: chunk, + done: false + }); + } else { + this._queuedChunk = chunk; + } + + this._done = true; + + for (const requestCapability of this._requests) { + requestCapability.resolve({ + value: undefined, + done: true + }); + } + + this._requests.length = 0; + + this._close(); + } + + _onError(status) { + this._storedError = (0, _network_utils.createResponseStatusError)(status, this._url); + + for (const requestCapability of this._requests) { + requestCapability.reject(this._storedError); + } + + this._requests.length = 0; + this._queuedChunk = null; + } + + _onProgress(evt) { + if (!this.isStreamingSupported) { + this.onProgress?.({ + loaded: evt.loaded + }); + } + } + + get isStreamingSupported() { + return false; + } + + async read() { + if (this._storedError) { + throw this._storedError; + } + + if (this._queuedChunk !== null) { + const chunk = this._queuedChunk; + this._queuedChunk = null; + return { + value: chunk, + done: false + }; + } + + if (this._done) { + return { + value: undefined, + done: true + }; + } + + const requestCapability = (0, _util.createPromiseCapability)(); + + this._requests.push(requestCapability); + + return requestCapability.promise; + } + + cancel(reason) { + this._done = true; + + for (const requestCapability of this._requests) { + requestCapability.resolve({ + value: undefined, + done: true + }); + } + + this._requests.length = 0; + + if (this._manager.isPendingRequest(this._requestId)) { + this._manager.abortRequest(this._requestId); + } + + this._close(); + } + + } + + /***/ }), + /* 36 */ + /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { + + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + exports.PDFFetchStream = void 0; + + var _util = __w_pdfjs_require__(1); + + var _network_utils = __w_pdfjs_require__(33); + + function createFetchOptions(headers, withCredentials, abortController) { + return { + method: "GET", + headers, + signal: abortController.signal, + mode: "cors", + credentials: withCredentials ? "include" : "same-origin", + redirect: "follow" + }; + } + + function createHeaders(httpHeaders) { + const headers = new Headers(); + + for (const property in httpHeaders) { + const value = httpHeaders[property]; + + if (typeof value === "undefined") { + continue; + } + + headers.append(property, value); + } + + return headers; + } + + class PDFFetchStream { + constructor(source) { + this.source = source; + this.isHttp = /^https?:/i.test(source.url); + this.httpHeaders = this.isHttp && source.httpHeaders || {}; + this._fullRequestReader = null; + this._rangeRequestReaders = []; + } + + get _progressiveDataLength() { + return this._fullRequestReader?._loaded ?? 0; + } + + getFullReader() { + (0, _util.assert)(!this._fullRequestReader, "PDFFetchStream.getFullReader can only be called once."); + this._fullRequestReader = new PDFFetchStreamReader(this); + return this._fullRequestReader; + } + + getRangeReader(begin, end) { + if (end <= this._progressiveDataLength) { + return null; + } + + const reader = new PDFFetchStreamRangeReader(this, begin, end); + + this._rangeRequestReaders.push(reader); + + return reader; + } + + cancelAllRequests(reason) { + if (this._fullRequestReader) { + this._fullRequestReader.cancel(reason); + } + + for (const reader of this._rangeRequestReaders.slice(0)) { + reader.cancel(reason); + } + } + + } + + exports.PDFFetchStream = PDFFetchStream; + + class PDFFetchStreamReader { + constructor(stream) { + this._stream = stream; + this._reader = null; + this._loaded = 0; + this._filename = null; + const source = stream.source; + this._withCredentials = source.withCredentials || false; + this._contentLength = source.length; + this._headersCapability = (0, _util.createPromiseCapability)(); + this._disableRange = source.disableRange || false; + this._rangeChunkSize = source.rangeChunkSize; + + if (!this._rangeChunkSize && !this._disableRange) { + this._disableRange = true; + } + + this._abortController = new AbortController(); + this._isStreamingSupported = !source.disableStream; + this._isRangeSupported = !source.disableRange; + this._headers = createHeaders(this._stream.httpHeaders); + const url = source.url; + fetch(url, createFetchOptions(this._headers, this._withCredentials, this._abortController)).then(response => { + if (!(0, _network_utils.validateResponseStatus)(response.status)) { + throw (0, _network_utils.createResponseStatusError)(response.status, url); + } + + this._reader = response.body.getReader(); + + this._headersCapability.resolve(); + + const getResponseHeader = name => { + return response.headers.get(name); + }; + + const { + allowRangeRequests, + suggestedLength + } = (0, _network_utils.validateRangeRequestCapabilities)({ + getResponseHeader, + isHttp: this._stream.isHttp, + rangeChunkSize: this._rangeChunkSize, + disableRange: this._disableRange + }); + this._isRangeSupported = allowRangeRequests; + this._contentLength = suggestedLength || this._contentLength; + this._filename = (0, _network_utils.extractFilenameFromHeader)(getResponseHeader); + + if (!this._isStreamingSupported && this._isRangeSupported) { + this.cancel(new _util.AbortException("Streaming is disabled.")); + } + }).catch(this._headersCapability.reject); + this.onProgress = null; + } + + get headersReady() { + return this._headersCapability.promise; + } + + get filename() { + return this._filename; + } + + get contentLength() { + return this._contentLength; + } + + get isRangeSupported() { + return this._isRangeSupported; + } + + get isStreamingSupported() { + return this._isStreamingSupported; + } + + async read() { + await this._headersCapability.promise; + const { + value, + done + } = await this._reader.read(); + + if (done) { + return { + value, + done + }; + } + + this._loaded += value.byteLength; + + if (this.onProgress) { + this.onProgress({ + loaded: this._loaded, + total: this._contentLength + }); + } + + const buffer = new Uint8Array(value).buffer; + return { + value: buffer, + done: false + }; + } + + cancel(reason) { + if (this._reader) { + this._reader.cancel(reason); + } + + this._abortController.abort(); + } + + } + + class PDFFetchStreamRangeReader { + constructor(stream, begin, end) { + this._stream = stream; + this._reader = null; + this._loaded = 0; + const source = stream.source; + this._withCredentials = source.withCredentials || false; + this._readCapability = (0, _util.createPromiseCapability)(); + this._isStreamingSupported = !source.disableStream; + this._abortController = new AbortController(); + this._headers = createHeaders(this._stream.httpHeaders); + + this._headers.append("Range", `bytes=${begin}-${end - 1}`); + + const url = source.url; + fetch(url, createFetchOptions(this._headers, this._withCredentials, this._abortController)).then(response => { + if (!(0, _network_utils.validateResponseStatus)(response.status)) { + throw (0, _network_utils.createResponseStatusError)(response.status, url); + } + + this._readCapability.resolve(); + + this._reader = response.body.getReader(); + }).catch(this._readCapability.reject); + this.onProgress = null; + } + + get isStreamingSupported() { + return this._isStreamingSupported; + } + + async read() { + await this._readCapability.promise; + const { + value, + done + } = await this._reader.read(); + + if (done) { + return { + value, + done + }; + } + + this._loaded += value.byteLength; + + if (this.onProgress) { + this.onProgress({ + loaded: this._loaded + }); + } + + const buffer = new Uint8Array(value).buffer; + return { + value: buffer, + done: false + }; + } + + cancel(reason) { + if (this._reader) { + this._reader.cancel(reason); + } + + this._abortController.abort(); + } + + } + + /***/ }) + /******/ ]); + /************************************************************************/ + /******/ // The module cache + /******/ var __webpack_module_cache__ = {}; + /******/ + /******/ // The require function + /******/ function __w_pdfjs_require__(moduleId) { + /******/ // Check if module is in cache + /******/ var cachedModule = __webpack_module_cache__[moduleId]; + /******/ if (cachedModule !== undefined) { + /******/ return cachedModule.exports; + /******/ } + /******/ // Create a new module (and put it into the cache) + /******/ var module = __webpack_module_cache__[moduleId] = { + /******/ // no module.id needed + /******/ // no module.loaded needed + /******/ exports: {} + /******/ }; + /******/ + /******/ // Execute the module function + /******/ __webpack_modules__[moduleId](module, module.exports, __w_pdfjs_require__); + /******/ + /******/ // Return the exports of the module + /******/ return module.exports; + /******/ } + /******/ + /************************************************************************/ + var __webpack_exports__ = {}; + // This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. + (() => { + var exports = __webpack_exports__; + + + Object.defineProperty(exports, "__esModule", ({ + value: true + })); + Object.defineProperty(exports, "AnnotationEditorLayer", ({ + enumerable: true, + get: function () { + return _annotation_editor_layer.AnnotationEditorLayer; + } + })); + Object.defineProperty(exports, "AnnotationEditorParamsType", ({ + enumerable: true, + get: function () { + return _util.AnnotationEditorParamsType; + } + })); + Object.defineProperty(exports, "AnnotationEditorType", ({ + enumerable: true, + get: function () { + return _util.AnnotationEditorType; + } + })); + Object.defineProperty(exports, "AnnotationEditorUIManager", ({ + enumerable: true, + get: function () { + return _tools.AnnotationEditorUIManager; + } + })); + Object.defineProperty(exports, "AnnotationLayer", ({ + enumerable: true, + get: function () { + return _annotation_layer.AnnotationLayer; + } + })); + Object.defineProperty(exports, "AnnotationMode", ({ + enumerable: true, + get: function () { + return _util.AnnotationMode; + } + })); + Object.defineProperty(exports, "CMapCompressionType", ({ + enumerable: true, + get: function () { + return _util.CMapCompressionType; + } + })); + Object.defineProperty(exports, "GlobalWorkerOptions", ({ + enumerable: true, + get: function () { + return _worker_options.GlobalWorkerOptions; + } + })); + Object.defineProperty(exports, "InvalidPDFException", ({ + enumerable: true, + get: function () { + return _util.InvalidPDFException; + } + })); + Object.defineProperty(exports, "LoopbackPort", ({ + enumerable: true, + get: function () { + return _api.LoopbackPort; + } + })); + Object.defineProperty(exports, "MissingPDFException", ({ + enumerable: true, + get: function () { + return _util.MissingPDFException; + } + })); + Object.defineProperty(exports, "OPS", ({ + enumerable: true, + get: function () { + return _util.OPS; + } + })); + Object.defineProperty(exports, "PDFDataRangeTransport", ({ + enumerable: true, + get: function () { + return _api.PDFDataRangeTransport; + } + })); + Object.defineProperty(exports, "PDFDateString", ({ + enumerable: true, + get: function () { + return _display_utils.PDFDateString; + } + })); + Object.defineProperty(exports, "PDFWorker", ({ + enumerable: true, + get: function () { + return _api.PDFWorker; + } + })); + Object.defineProperty(exports, "PasswordResponses", ({ + enumerable: true, + get: function () { + return _util.PasswordResponses; + } + })); + Object.defineProperty(exports, "PermissionFlag", ({ + enumerable: true, + get: function () { + return _util.PermissionFlag; + } + })); + Object.defineProperty(exports, "PixelsPerInch", ({ + enumerable: true, + get: function () { + return _display_utils.PixelsPerInch; + } + })); + Object.defineProperty(exports, "RenderingCancelledException", ({ + enumerable: true, + get: function () { + return _display_utils.RenderingCancelledException; + } + })); + Object.defineProperty(exports, "SVGGraphics", ({ + enumerable: true, + get: function () { + return _svg.SVGGraphics; + } + })); + Object.defineProperty(exports, "UNSUPPORTED_FEATURES", ({ + enumerable: true, + get: function () { + return _util.UNSUPPORTED_FEATURES; + } + })); + Object.defineProperty(exports, "UnexpectedResponseException", ({ + enumerable: true, + get: function () { + return _util.UnexpectedResponseException; + } + })); + Object.defineProperty(exports, "Util", ({ + enumerable: true, + get: function () { + return _util.Util; + } + })); + Object.defineProperty(exports, "VerbosityLevel", ({ + enumerable: true, + get: function () { + return _util.VerbosityLevel; + } + })); + Object.defineProperty(exports, "XfaLayer", ({ + enumerable: true, + get: function () { + return _xfa_layer.XfaLayer; + } + })); + Object.defineProperty(exports, "build", ({ + enumerable: true, + get: function () { + return _api.build; + } + })); + Object.defineProperty(exports, "createPromiseCapability", ({ + enumerable: true, + get: function () { + return _util.createPromiseCapability; + } + })); + Object.defineProperty(exports, "createValidAbsoluteUrl", ({ + enumerable: true, + get: function () { + return _util.createValidAbsoluteUrl; + } + })); + Object.defineProperty(exports, "getDocument", ({ + enumerable: true, + get: function () { + return _api.getDocument; + } + })); + Object.defineProperty(exports, "getFilenameFromUrl", ({ + enumerable: true, + get: function () { + return _display_utils.getFilenameFromUrl; + } + })); + Object.defineProperty(exports, "getPdfFilenameFromUrl", ({ + enumerable: true, + get: function () { + return _display_utils.getPdfFilenameFromUrl; + } + })); + Object.defineProperty(exports, "getXfaPageViewport", ({ + enumerable: true, + get: function () { + return _display_utils.getXfaPageViewport; + } + })); + Object.defineProperty(exports, "isPdfFile", ({ + enumerable: true, + get: function () { + return _display_utils.isPdfFile; + } + })); + Object.defineProperty(exports, "loadScript", ({ + enumerable: true, + get: function () { + return _display_utils.loadScript; + } + })); + Object.defineProperty(exports, "renderTextLayer", ({ + enumerable: true, + get: function () { + return _text_layer.renderTextLayer; + } + })); + Object.defineProperty(exports, "shadow", ({ + enumerable: true, + get: function () { + return _util.shadow; + } + })); + Object.defineProperty(exports, "version", ({ + enumerable: true, + get: function () { + return _api.version; + } + })); + + var _util = __w_pdfjs_require__(1); + + var _api = __w_pdfjs_require__(4); + + var _display_utils = __w_pdfjs_require__(8); + + var _annotation_editor_layer = __w_pdfjs_require__(22); + + var _tools = __w_pdfjs_require__(7); + + var _annotation_layer = __w_pdfjs_require__(27); + + var _worker_options = __w_pdfjs_require__(15); + + var _is_node = __w_pdfjs_require__(3); + + var _text_layer = __w_pdfjs_require__(30); + + var _svg = __w_pdfjs_require__(31); + + var _xfa_layer = __w_pdfjs_require__(29); + { + if (_is_node.isNodeJS) { + const { + PDFNodeStream + } = __w_pdfjs_require__(32); + + (0, _api.setPDFNetworkStreamFactory)(params => { + return new PDFNodeStream(params); + }); + } else { + const { + PDFNetworkStream + } = __w_pdfjs_require__(35); + + const { + PDFFetchStream + } = __w_pdfjs_require__(36); + + (0, _api.setPDFNetworkStreamFactory)(params => { + if ((0, _display_utils.isValidFetchUrl)(params.url)) { + return new PDFFetchStream(params); + } + + return new PDFNetworkStream(params); + }); + } + } + })(); + + /******/ return __webpack_exports__; + /******/ })() + ; + }); + +} (pdf)); + +var pdfExports = pdf.exports; + +function h(t,i,s,r){const e=s-t,h=r-i;return Math.sqrt(e*e+h*h)}function n$1(t,i,s){return Math.max(i,Math.min(t,s))}class u{constructor(t=0,i=0){this.length=2,this.x=t,this.y=i;}static multiplyByScalar(t,i){return new u(t.x*i,t.y*i)}static addScalar(t,i){return new u(t.x+i,t.y+i)}static normalize(t){return (new u).setFromVec2(t).normalize()}static add(t,i){return new u(t.x+i.x,t.y+i.y)}static subtract(t,i){return new u(t.x-i.x,t.y-i.y)}static dotProduct(t,i){return t.x*i.x+t.y*i.y}static applyMat3(t,i){return t.clone().applyMat3(i)}static lerp(t,i,s){return t.clone().lerp(i,s)}static rotate(t,i,s){return t.clone().rotate(i,s)}static equals(t,i,s=6){return !!t&&t.equals(i)}static getDistance(t,i){const s=i.x-t.x,r=i.y-t.y;return Math.sqrt(s*s+r*r)}static getAngle(t,i){return t.getAngle(i)}static minMax(...t){if(!(t=(t||[]).filter((t=>t))).length)return {min:new u,max:new u};return {min:new u(Math.min(...t.map((t=>t.x))),Math.min(...t.map((t=>t.y)))),max:new u(Math.max(...t.map((t=>t.x))),Math.max(...t.map((t=>t.y))))}}clone(){return new u(this.x,this.y)}set(t,i){return this.x=t,this.y=i,this}setFromVec2(t){return this.x=t.x,this.y=t.y,this}multiplyByScalar(t){return this.x*=t,this.y*=t,this}addScalar(t){return this.x+=t,this.y+=t,this}getMagnitude(){return Math.sqrt(this.x*this.x+this.y*this.y)}getAngle(t){const i=Math.atan2(this.x,this.y);let s=Math.atan2(t.x,t.y)-i;return s>Math.PI?s-=2*Math.PI:s<=-Math.PI&&(s+=2*Math.PI),s}normalize(){const t=this.getMagnitude();return t&&(this.x/=t,this.y/=t),this}add(t){return this.x+=t.x,this.y+=t.y,this}subtract(t){return this.x-=t.x,this.y-=t.y,this}dotProduct(t){return u.dotProduct(this,t)}applyMat3(t){if(9!==t.length)throw new Error("Matrix must contain 9 elements");const{x:i,y:s}=this,[r,e,,h,a,,n,x]=t;return this.x=i*r+s*h+n,this.y=i*e+s*a+x,this}lerp(t,i){return this.x+=i*(t.x-this.x),this.y+=i*(t.y-this.y),this}rotate(t,i){const s=Math.sin(i),r=Math.cos(i),e=this.x-t.x,h=this.y-t.y;return this.x=e*r-h*s+t.x,this.y=e*s+h*r+t.y,this}truncate(t=5){return this.x=+this.x.toFixed(t),this.y=+this.y.toFixed(t),this}equals(t,i=6){return !!t&&(+this.x.toFixed(i)==+t.x.toFixed(i)&&+this.y.toFixed(i)==+t.y.toFixed(i))}toArray(){return [this.x,this.y]}toIntArray(){return new Int32Array(this)}toFloatArray(){return new Float32Array(this)}*[Symbol.iterator](){yield this.x,yield this.y;}}class l{constructor(){this.length=9,this._matrix=new Array(this.length),this._matrix[0]=1,this._matrix[1]=0,this._matrix[2]=0,this._matrix[3]=0,this._matrix[4]=1,this._matrix[5]=0,this._matrix[6]=0,this._matrix[7]=0,this._matrix[8]=1;}get x_x(){return this._matrix[0]}get x_y(){return this._matrix[1]}get x_z(){return this._matrix[2]}get y_x(){return this._matrix[3]}get y_y(){return this._matrix[4]}get y_z(){return this._matrix[5]}get z_x(){return this._matrix[6]}get z_y(){return this._matrix[7]}get z_z(){return this._matrix[8]}static fromMat3(t){return (new l).setFromMat3(t)}static fromMat4(t){return (new l).setFromMat4(t)}static from4Vec2(t,i,s,r,e=!1){const h=new l;h.applyTranslation(-t.x,-t.y);const a=u.subtract(i,t).getMagnitude(),n=u.subtract(r,s).getMagnitude()/a;if(h.applyScaling(n),!e){const e=Math.atan2(i.y-t.y,i.x-t.x)-Math.atan2(r.y-s.y,r.x-s.x);h.applyRotation(e);}return h.applyTranslation(s.x,s.y),h}static multiply(t,i){const[s,r,e,h,a,n,x,o,y]=t._matrix,[_,u,c,z,m,w,d,M,g]=i._matrix,p=new l;return p.set(s*_+r*z+e*d,s*u+r*m+e*M,s*c+r*w+e*g,h*_+a*z+n*d,h*u+a*m+n*M,h*c+a*w+n*g,x*_+o*z+y*d,x*u+o*m+y*M,x*c+o*w+y*g),p}static multiplyScalar(t,i){const s=new l;for(let r=0;rMath.PI/2&&e>0||h 1 && arguments[1] !== undefined ? arguments[1] : 0; + // Note: Be careful editing this code! It's been tuned for performance + // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434 + var uuid = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); // Consistency check for valid UUID. If this throws, it's likely due to one + // of the following: + // - One or more input array values don't map to a hex octet (leading to + // "undefined" in the uuid) + // - Invalid input values for the RFC `version` or `variant` fields + + if (!validate(uuid)) { + throw TypeError('Stringified UUID is invalid'); + } + + return uuid; +} + +function v4(options, buf, offset) { + options = options || {}; + var rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + + rnds[6] = rnds[6] & 0x0f | 0x40; + rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided + + if (buf) { + offset = offset || 0; + + for (var i = 0; i < 16; ++i) { + buf[offset + i] = rnds[i]; + } + + return buf; + } + + return stringify(rnds); +} + +/** + * MIT License + * + * Copyright (c) 2021-present Volodymyr Yermolenko (yermolim@gmail.com) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +var img$J = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZE7SwNBFIW/PCSiERUtRCy2iGKRgCiIpUQwTbRIIhi1SdY8hDyW3QQJtoKNRcBCtPFV+A+0FWwVBEERRGz8A74akfVOIkQkmWX2fpyZc5k5A85wTs9b7jHIF0pmJBTUFuNLmucFNz304kRL6JYxF52N0XJ83uFQ9TagerXe13R0rqYsHRztwpO6YZaEp4XD6yVD8bZwv55NrAofCvtNOaDwldKTdX5WnKnzu2IzFpkBp+qpZf5w8g/rWTMvPCrsy+fK+u951E28qcJCVOqgzCEsIoQIopGkzBo5SgSkFiSz5r6xmm+eonh0+RtUMMWRIStev6hl6ZqSmhY9JV+Oisr9f55WemK83t0bhLYn234bBs8OfFdt++vItr+PwfUIF4WGvyg5TX2IXm1ovgPo3oSzy4aW3IXzLRh4MBJmoia5ZDrTaXg9ha449N1Ax3I9q991Tu4htiFPdA17+zAi+7tXfgDAkGftS3qrhgAAAAlwSFlzAAALEwAACxMBAJqcGAAABNVJREFUeNrlW21T4jAQTkJxPI9BeXFGZ27u//8oP934QUcpMnIngjS3GxomhKRt0qSUmjmuRTD22X32NQklkcft7S3ZbreEU0o4vKdZRjhj4krhiiPj8Al8vv8Mvwc/Y3D/+voa9flojEnH4/EOGIBilu9kAJZJASj3tu9xuM7nc5/H4UVYaUjQQssFYOoOnJvg3NWFwcvw1hbAaDQSD4V/iZFmRpabT/b1RRaLhYsAjjAntW0o1zatojm8R5ZsNsIvLO/uxM8GT0+k1+sR2u/v5kGfoPgIfUiG9ZKkiolzg1BoMAHYUXP4x4W2rFp6eBCXpWWK6+trIRich4Y1q70QggsAZ958fpLlcll7LlVwg8GAXFxciGjh4QCtQkhC2STDMAavdDaLQigpUBlWszxMeoIP5wME1UEAabEzCjZeXl7E9ebmZucr3MBTPSxS0r3BXXIe+p3Bk7LQLTO6cwY/mkwKlWwVwGg6dfW4rdQ8LVGkUQBD8LQcPG1XaI8RY4oKrRoFEiVz64LNY7j8skQMZqR+Bx0eAp1MJsUCwMIGa/Iuenv5S5he2xmAtFccH2Z4+i+cE3hQ6O9MUyjWFkYBiHpepwcIY+GR4Y0NVIsFPv9bRs3P5/M/TItk6BBVpe4FwA3dG1ojDE4D+xIAagQPtUfhQ/b7/Z+6Q2RKGc0OanZN1DOPwkZqHyWN9yHYIMGrc1UBj+P5+fmvXjNQ5X1P0l+vt7GkXa/Xzlo3GejHx0cwzf+4uhKvKuD3YR00fmD7wOzLy0uyWq0smSBIyKeet3VwfVlgoj0OF/A43t/fjxgu8xzxf6bZOufcW2PYD2AG3+EqhFDgrf4sFwjDBgMzNDjqDBsTqjrG0OCNAgEGoOmzrZbz86IeniMTjjpHuWM8Bfg0TYlJrYzr1AhYA9jMwcaE2JrXkYnQz0ncYTIHExOaoP2RIxS9TD3+R+gBlDnGJsDbHCPjGuVx0aIpJjQNXo9uorNMNAZsIzZCDI6xUc3r0Q0ZQEuKjjirxzvqn4T2qu8R6xklFVcsH+lVz8cYjfe9bDYvwUcspclwODx2gm0CH7ufoC+lceEETwzeZvMxhKDXA6wpBpSBty2ohm6qUEPRx9qied/aoXYi1Cbau9YOznmAgQG0QoiiTYCvYv919h7gmgA31AasDZqP1VQpbPLAe9xpxtoGvkLt4CcAnf75e9ZG8GWUdxUCJkDUIpCQAuCmB67dydHmxPf4cnGMib6dDuj/ljMslAC46YFDFTZyTnVuNJEqTLi/v78qMgcWEnzMqs7CrlIhrNbrf/p6J+4wLQpxLmGwNVWd0VeMx78gmXo8qAGA/tggDcGAVoMXDEnTR70A2mgdL9ZV8JZkQKwSHTjI7wIebf/NsMWefRfwPdvO887TPq/7bUv9SdfBlx21oQ5gzw58JXb49hJIRwarCx631olzQ80nObgPuPY8SV3Nex5l8x6Q22N6uz+k0bQAQi+UVEaAJS1WdZ8AXhysDLSMn5zYBHmREOQub16whnfuAthrF3N2mp87EsmLQu+YHjex0JI3hJ3ayllWktmh/W8CLOUnocIcbj8VOzALDjyGKGbk8dxQh7SisEsepw0iDAkaXm8RTpJHT2hURyYEAldc8cGrbFXLe5Zf1c9ih9n/LqFyUTq2iTQAAAAASUVORK5CYII="; + +var img$I = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABcWlDQ1BpY2MAACiRdZG9S8NQFMVPW8Wi1Q46SHHIUMWhhaIgjlLBLtWhrWDVJXlN2kKShpcUKa6Ci0PBQXTxa/A/0FVwVRAERRBx8R/wa5ES72sKLdLe8PJ+nHfP5eUE8Kd1Zth9CcAwHZ5JJaW1/Lo08A4fRhBEHBGZ2dZydimHnvXzSN1UD3Exq3df1xoqqDYDfEHiOWZxh3iBOL3lWIL3iMdYSS4QnxDHOF2Q+Fboisdvgosefwnmucwi4BczpWIHKx3MStwgniaOGnqVte4jviSkmqtZ2iO0JmAjgxSSkKCgijJ0OJRLGSZl1t2XaPpWUCEPo7eFGjg5iiiRN0ZqlaaqtGukq/ToqInc/+dpa7Mz3vRQEuh/dd3PSWBgH2jUXff31HUbZ0DgBbg22/4K5TT/TXq9rUWPgfAOcHnT1pQD4GoXGH+2ZC43pQAtv6YBHxfAcB4YvQcGN7ysWuc4fwJy2/SL7oDDI2CK+sObf/JNaAQfxWcoAAAACXBIWXMAAAsTAAALEwEAmpwYAAAJT0lEQVR42uVbW2wUVRiec7bt0i2l3U7TAgajCFp8AoEIgjzZhCBqUB40qfdYL5V6wRASjAlKYoIgVsQLPGlMMJYEI4IhJfGBApogBB+o1hIvmBSyO7vbUrv3Gb9/ma1nTme7u7O7tV1PsswyOz0z//ffL8OUEi+v13sjDisYY0sMw2jB8SbdMJpxrp5z7qZrdF2P4hDijF3FNb8rnPcxwziPc2cCgcBfpXw+Voo96xsbV4OAjfjcqzB2SyGbGbo+AECOAqXuYDB4mk5NSQDq6uq8vKKiHUS3g+j5peCWCcYBPZHYPzQ0FJoSANTW1qqVlZVbINYdEOkaZRIWVGYE6vJBMpncCSCC/xUAroaGhg5wezvp8wTXJXVFOcsNoxff+6Djv+BzGURcGx4eHqELZs2aNRPg1cI+zMN/Wxjni/A3q7miLKX7TLB3AAS8oWnaR4TLpAGgqmpLUtc/w0Mvz3BJDIp6FOrwOb6fgCEbdnIfADwLh1YA1gZQ1uF7la1EKMr3FYw97vf7+0sOAB7qSYj7PhBfbfOzXzGMPYlE4mNwN1BMsTdV7XlI3MvEAxu1+Btq8QLA/qxUALjg0rrAiQ67m+P8WzOqqvYODg6OllL/m5uba+Lx+EtgwjYwwTPOUCrK+0FNeyVXlcgNgAUL3A2BQDfQv8/mhoch6p2l9tcZ4ou9AP5+G2/xVVBVH1YGBqJZuZoL8fXB4NcwUOskrkfgkjqA9pZwOJy3jjc2Ni6tcrsHqmtqqiPh8Hf5/n0kEhnC5wu3x+MDA+4BcyrGuMpYS3Uksix8ww2HlEAgWYgEkKU/LHMesvUXiF8f8vkuODJuqhqUPUdA0xx7JIB5RyKZPAKVmCtLJxi0cSJ14FnErGsc8br+M9P1VU6JhwdZZuc2vaq6xykAsP7nIPar8Gz9Enc3YN/djlQAnH8K+rVDJj7hdq8Z9vsHnRIPrvTg6wwbUVwxw+Ophzocd7J3NBoNIRr9Eh7oAaiAKu4LNbmEfX/KWQVMP39OdHUk9sR5xON/OhTTpbDcZ00gB7H3nAw+fU9I014tICS/CYw7Le5PXqrC5VoCSfk1FxVwmUFOtWTw1hdI/Imxm2Yg3nygV+pV9V2nACA0/h3Erkc8EhXuV4P7f2pHr8tG9DcBwaetT8U7Qn7/MacGD2LfaYp9yE78BaAHIb61EMuVENs6p+owOjo66PF4yNCKnmse9ryKPc9mVIFUtFVVNSAaKdOSPlio2DtKegpUBzDzCIz4euGUlkwkFoiZpEUkKKsTiaesi4Ich5wPCDofzubu7M6TOmAfx/k/ssVNuLcYmapI2V+ztQGUz1NKaxEPeAEnER5xnjzbdREyoml7ks3XZ/q9IYsrm8geID94W4oSO+He68YBQMUMSz5vGD6K7R2Kfc+/KDJ3PoFOhutedQqCy+V6j7YVDGIt/nlGBoClKjnW1ZVvYkMRmSn23kKivIwgNDTsyhcAn883AmZ2Sda2PW3/UgBQDU8qY8UQUHzkgPgTuYq1IxAY2+wEhFgs9iEOcUG1F0INVowBQAVMKYY+mk8+bxq8HwvlfKlAGBkZ8UP3v5Xs20YRgHstP16v5OTK+VtlwotBfDYQEONvz6vwwdjnUsyRihF4Kq+2lq4TuLgn50qtYbSWivgM+2kmBY/k6RJ7xKwQxrAFzJtDErBCCj5+1DTtWq4b49pPgMLJUhFvs6+K+30D4B/K0yWGoAbnJSm4q4I6NpbA4Hr1Np+VQKywZjKqQAWDyzkxaumY9DK2mFO7SrqsTynXxVifZOwXcerVSTr9S7nSD4IttCG9v5mbjUoRgMtlC0A8bknnDc6buVyeoo5NuQIAT3BNigi9PN2iTq90u6oc18js2desNpG7ufI/X9wcThhb1KgsV2JnXrlSK6l7hJtlKsWSLpbpQmpcK8UFQU5jKVLMPK9sw4DKyhslN3iVp2ZyrKulbAGQgj64wd84DSRJaeKiMrZ5FgAQV/dxcxpLTIZWly35un63JBEXyAiesdgFJAvmZEZZLSr6QrqXSEbxFKeqb2r6SjiPT2vZ+XvOWxWhCAxJv+jz+a5w89ejUj7QVn6JIGuT0v5jyhgiut4tGcJ11CUqmwBo5sxGILBWOn1oDIDUBKZhXBJ+rEoNJJXJqnS7X6SDEAH2Q/V/UASdMAzG9ksy8zINJE134lVVpWZrpyTh+wWjb6KSSOynXqD4tzSNNe1rAIZBE2NewfgNw/0dGAcAFQ1p/NTiNg1jmzmNNV1d382gYasU/HSJg5tcKhjsVKx9NJrD2ztdAYCf/8Ay0GkYPhiA3VLc8++iwWOavZX05f56VZ12BhHBXKcijfYh9n8dBn9IkojxMQMIPg1k7hSQiyY5Xznk958vysPZ9PyL2U+A4VuOG1B5X5wt7sU9qHxvZJSAtOpXMPaYZbCAMTdLJr+hAaQpr/dNTfOTuv61SDzVOROcP6HYvGxhWxKjqWsYxOelUHIu1OE4XGPTVCW+qampmcfjx/Gssy1i7nI9O+zzXbINkTNtRlPXNHgsgXBrNBY7WQxJoNE18zhaLM7DbfeCSQskP7gr6PcfzJgjTLQpTV3T4LEMAm5yiuYBnD4s6Tv2eDNllxjbUaj+0wAmi8dPjSNeUbrByC0T5ghZd6dJ8WCQQFgrIRtFgrFZ07R9U8Dav6PIL1Mg2QHxG/AtVhgAJgjeYPAgzd7ahFpHIMabQqHQH5Md5JCfl13dGOc1rS0b8encPweZDSQj4XD3DI+njkntdDzAbbAV7R6PhyPrOjc6OhorJeEU21dXV2/FfQ9C5G+3YcgucP45fEvklCbn+wCIEdpguT7O8IZYgAaSaCaHxlKKndJSVmcmNl4bozoCa98+kcErCgC0YAAXmrO3KzNcEqeZHBpLockMp+/4pd5F5LwV+zxq5vMVGS7tJT+fydUVHQAhYnwWbuQtxeYlJjHFSE1mcN5L/XlqUVOXlhqV6V4ddWyoaUF1e7N03QKWroGIL87iqfxI47eB6wcUh2+UsiIYI3pjdDNNYE5WVymV0iKro8RGju0nHYD0So2f0gSmrrfTHF5JCNf1fipmUD7v9F3EkgEg7klDiDSHR6NoNI1VILcvmgXMQ+kyVlEfttTiSqNoNI1FA0k0k0NjKTSZYQ4npF+fpxcygtSro3YVdWyoaUF1eypdl/L5/gF8P3SyE6no9QAAAABJRU5ErkJggg=="; + +var img$H = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABcWlDQ1BpY2MAACiRdZG9S8NQFMVPW8Wi1Q46SHHIUMWhhaIgjlLBLtWhrWDVJXlN2kKShpcUKa6Ci0PBQXTxa/A/0FVwVRAERRBx8R/wa5ES72sKLdLe8PJ+nHfP5eUE8Kd1Zth9CcAwHZ5JJaW1/Lo08A4fRhBEHBGZ2dZydimHnvXzSN1UD3Exq3df1xoqqDYDfEHiOWZxh3iBOL3lWIL3iMdYSS4QnxDHOF2Q+Fboisdvgosefwnmucwi4BczpWIHKx3MStwgniaOGnqVte4jviSkmqtZ2iO0JmAjgxSSkKCgijJ0OJRLGSZl1t2XaPpWUCEPo7eFGjg5iiiRN0ZqlaaqtGukq/ToqInc/+dpa7Mz3vRQEuh/dd3PSWBgH2jUXff31HUbZ0DgBbg22/4K5TT/TXq9rUWPgfAOcHnT1pQD4GoXGH+2ZC43pQAtv6YBHxfAcB4YvQcGN7ysWuc4fwJy2/SL7oDDI2CK+sObf/JNaAQfxWcoAAAACXBIWXMAAAsTAAALEwEAmpwYAAAJeElEQVR42uVbbWxb1Rk+5zi2g+Mmvv4Q6QSMQVSWaRuqqNSVtf+oEC1lBdEfSFW3Pw0d0GVQ2FRpExKi0r74KhRE+QFslZhop2pQojKkaWKsq9SVov0hoqWgTqJN5OvrNGkcx/a5e96ba/fek2vHvrbT1LxSm+Te63PP+7zveb/NWZsplUr1l0qlH5qc32oyNsil/JYpxLVMSk0I0U3PSCnzTAgD98Zw7wvO2KfcND/B/WPpdPp8O/fH27FoPB5fjR/3S843CMa+08xaAGcUQIyYUh4yDOM4LplLEgAw3Qspb8dGh7DhFe0AFmufhqbsByqvAYyJJQGApml92NQuiGUY0u5li0DQikkuxF5ZLD4zMTFhXCkAuJZMbsdZ3YPfk7X2C8l9ApA+xO+j0JJRs1A4B7swOdXfP0kPRC9cWBYIBJbxYPAGbOgWZpqD4HItmFyJ24Eaa+uSsV9ndf1Ves+iAdCbSt3cJeUb+HVtlUeKYOKoaZp/grQ+8Culvr6+GIBZj3W2Aoy7cClY5dF/C85/DIN5uu0AQOoPmKXSfpzzqMdtA0dhbyGff2lqairdSrWPRqPJUCj0EON8mEyOx7G4BC3bAW040C4ABAzdb7GBxz1enoMEfsM5f07X9ck2u9Uojs/PpWnuhhAi8wwlY88bur6r3iNRLwCheCJByG6Zb5rNEWzoEaj5F2wRKRaLfRMAvAiBbPIA4bChaQ+wM2fyrQAgBMkfxos2KNdnwfwTmUxmL7uClEgkHoaNeAb7Cyu3jmY0bfNCIAQWAgiSfwuLb1ZU/gJU/g4wf7jJ2GH3NZHIh92RSG4ml/uXnzVyudyJnp6ekZKUm3AElzluDXRPT393ZmbmYK3giS+wwd+rZx4u7YwMBu+cGB8/2xTziQSWktN0jsmA4WdPRtd9u2V4jBvhKd5XgzAyyrAJw1UNWy1r78V8MBhc2yzzlZfbRoyYb3Yt2KAvw6HQOoD5mSLhn0GQ2xoCgPw8XN2rqtqT5MfHx8fYEqWxsbFxCOlO7PUrdyRmvpJMJlfUCwCnIAdScZ6n2YAQ97RK8u0k0gQzELgbBjrv1LSiaf7Ri1/hofrb50V4sPbw7yfYVUIT6fQpZKKPKoyuhsf4aU0jSIkNLOlpnP2U08/D2m9secoMI6hea8YIVknU/grDeI/zFaViccAZmgvFKu1yMk8RHgU57OqlneRpnLgjt/iF5xGw8nmktK6bCG8XO8JrJRmGcQ487FEM4iOUZM0DgIoZSj5vUGzPrnKC236B0maHQYyKrq6h+QBIOaQGEO1ObBbJNV6CHXveZfhMc6hs/0S5hqdEUAVKaVmHUKFQeMXKXSoI8JthIG93asD9its72up8/krS5OSkDg0fUQz+lgoAUsn0kF0dYB1GsGcHlCKG5doF1e2V0rWkMhbrPCKeShVAhBjA0b9OUNNCSXhONVtpXYqEYO6iZOykcnmNoI6Ncjb+yTqUoOkfuYTN+UpB7SrludFOBQDa/aliBwYF9eoUVDoWAFW4MIw3CqtR6QSgUDjXsRpgmv9TwuJrBXVpnRepY9OpAFBLTbkUE+UWdZnK7apOpIsXL0657b0IC/Y1J2ENJziIGpWdymxvb29UORJ5QZMZzovUpe1YabvrnERZcoOuKi+1qDsVALi9612AcD5GbtBV8bH6850LwC2KW/xS0ECS4iwHO9jmDSqAjAqaxlKc5bpGV43FYt9DZvUuVXq9qr2tpPI78D6aOOlqKA7gfK2iAacoDjjmQkWIlc6iYZ2q9Rf8dzeza2/tAsG1LufrEonEg/V+Fs8ug8+/Tbl8XNAcHo2iOW0DjaU0aF7fKr/Hc7OtZv4y8HXXLSDt9S6NMc3Praqx7R5GlIe3NrI5Q9efZNSjr2PTrWKeXgvhfVY3AJxvVf5+z06RrTTxkHIM7qKZnAYLDo+3AwSPzxtwX7dldD3eQAAUh7HfqABwqAIATWBaQ4iXKWgNJDVedWkpCF6fo8EMSP7jRtbp6uqinmDIoeJns+n0RxUA6JI1gek+YMM0kOQLBMaebRaEKpJf1Sjzy5cvpxmEYUX6+5k9NSIc7u81JV2M0zSWH8ll5qa0fINQec7Z4uZ8PZg/2eheZmZndyr9zkuyWKwIuwIAzd7S+KlSMNhNoydNgMAaBaF8nxqzjsEnww/zVPXF0f6VcoT2Ve0OA5k/MHcfLQKX+KJfA0btbsnYc/WC4LyOd19jb3hVIwZPUfW9ykBntlAo/M6V/Dn/yOfzM+FIZNJlMTlfEYlE0jSN5WcTM7nc+1izD2uusSV7XpnmUimLf+UiTVavMeBUi7RkcgjvfEIJBn4J6f9DyX3mhzWQBFnINY4P5oHk7Y0aIFe4nEg8C3V7tM7Hs7a1P+nrXanUraxYPO6sdgH4E1nDIJ5KLma9QmYaPLZmby9rQbhYKh3xaw9sUT7mdRwcGzyvuDpfzGuadgMWO6IwnwsIsU1lft4RKNP09HSmu6fnHNTjPkfYSWq7ASC8fQnk9zh0RyIxrPsDj7CW1s/i3jqovS/mo/39KVEq/R0A3qSo+Q64Z8+wOVBjs/9VN4tNJorF4o/C4fAR2Itsy0GYY/4/fiVvMS/Et13HXsp98HB7qiZyC6U5WiJxCA/dq6jrV12BwKZmbIKHJ8jC2mu+zzypPWPXKUbvXUj+Xi/Vr2UDXLxaU9eMHVVqa98ACMdg2B7yCwC5SCDwtDUuO+fqfDFP1t4yeArzsDd/y8TjW2oxX48GzNHAQFjT9T8jUNo8z9dK+Q5+7KTUcjFLO1aQAz+vamdF8sR8HePygfrElSnR1DXOroYXrlbrbEifH0SsQFnXx7CPhXYyTrF9MBx+DO88CM35vodA6Mz/BHuuax/cB/LbECK/XGXAWaeBJJrJobGUVjJOKS2yuh1sbgI06eFG6VsrD+PMv95QNcvPZmjwuGiabwoPS27TLM3k2GMpH9Bwgk81p7G9O6iYYUenoSoxxAny8/AgDXe2mxlNFTR7C0P2FPP4EpODSjSZQcMJdn9+lLq0lHmWe3XUsaGmBdXt7dL1IBUw8ZlVCxzTLDTuSQC8byFj1w4ALEJgpNH4KU1gVvkmWcvJ+oIFsjpKbJo9ai0bTqZKsjWBKeV2GkBqC+emeZaKGZTPt2qOqR1fnubWECLN4Um5sWkwTPNzKmBSDc8uYy3NL0/X8teUWdJAEs3k0FgKTWawueGEsK3SeTsDHKN2FXVsqGmBa8fbHV/8H2Qog/fmBwhzAAAAAElFTkSuQmCC"; + +var img$G = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZE7SwNBFIW/JIoSE1JoISKYQsUiAVEUS4mgTbSIEYzaZNc8hDyW3Q0SbAUbC8FCtPFV+A+0FWwVBEERRGz8A74akfWOCSRIMsvs/Tgz5zJzBtzRnJ63WoYhX7DN2EwkuJhYCra94qEPL37GkrplzM5Px2k6vu5xqXoXVr2a72s4OlZTlg6uduFx3TBt4Unh6LptKN4W7tKzyVXhI+GQKQcUvla6VuEXxZkKfyg247EpcKuewUwda3WsZ8288JBwfz5X0qvnUTfxpQoL81J7ZPZiEWOGCEE0SqyRwyYstSCZNfYN//nmKIpHl79BGVMcGbLiDYlakq4pqWnRU/LlKKvc/+dppUdHKt19EWh9dpz3AWjbhZ8dx/k+dpyfE/A8wWWh5i9KThOfou/UtP5DCGzC+VVN0/bgYgu6H42kmfyTPDLd6TS8nYE/AZ234F2uZFVd5/QB4hvyRDewfwCDsj+w8gsVKmgU+omlKwAAAAlwSFlzAAALEwAACxMBAJqcGAAACdRJREFUeNrdW3tsW9UdPuf4Ok5wHrav86pYB6zQZA+NDpi6tUzaRCSg7TakIsEUFYTUQGlpV2AVk7ZJCLFNhY62lIHafwarhLZ2KoK2g0XaHzRQ0Cgt/yyllOdQm9SPmzgmTvw4d99xbff45NqxnTi+7pFS3/oe33u/3+P7Pc65lFR5+P3+bs75D01KrzcJ6aWcX20y1kk49zLGXGIOzk8RxgycG8W5Tykhw9Q0P3A4HG8FAoGRaj4frcY1vV7vcsrYWgC7HSB75nIxTsh/mWkexeHBcDj8rm0FANBt0OJ6qHMA4K+thrYg0DO49l5Yxz4II2ILAbS1tXmYpj1qcr4Z2m4hCzBgFRE8+C5IZIdhGOO1EgDz6Pr9jJAncKwXe14I5ySs4xihdBg88KGZSHyRSqUmol1dE2JC88hIC/y9hTqdi6Fd4TI9AHcztL1M3KfglU0zAM74jREM7hP/WzABgNiu5ab5Ig5/UGBKAqD/SSndD6CD4+PjYxValyDKPlynH8K7FV85C0wdSjJ2byQQ+LjqAoDW+6GdF/BgbovTYWhlVzwe/3M0Gg3Op9k3Nzf7nS7XJjzwZkE5FvwwQR2O+2ENL1dLAMyr6zvwg19a3HySUfoHmPFOhK1oNf1f1/UW0zS3wgIfgxKaLNziaRDktlJdojQBLFni8hrGy5h8h8UND8PMH4KZf0YWcMA9robA98A1brc4fSAcCvXjMz53AQC8zzBewdGtCvBp+OYjoVDoOVLD4fP5NkMIT+GwQXm+o7CEO2YTAp3V7L3ef4CNf66Y/HnN4VgdDAbfJzYYcIubUpy/CpfosrCEuy5GTuvhKJrc6PpOaPkeNRkBw/8Y8XeY2GTEYrFzrtbWQzSVWoXn9UmnvtXU1OTG+cGyLQCmtQ6m9aIK3tXQcPPo6OgFYsPR0dHRmUgkhmCxS/K8gdJfFIoOtECcvy6ZSr0vhzqAPwfNr1hosiubHDs6rqGJxFuyO+DZo1zTrrfKE6yyLJZEkpMX50F48Pk1dgcvxviFC584GFsjkx+wNGuc/8VK4Q4LQnkQswbyTJ/SLSCTV0mdDMEJ8P0IXPg26evFjW73uanJyRMFXUCkng5NOysoIKd8sCsI72ekDgd47IiSJwSBZ4lcQOW5ABKLbTJ4keHh46GKS2Rdfxxh9IzH4/lOLQSABG0TMMRkeoM/PGLJAaKsRXq5Ke8kpU9CWl9UKP2nYV6/E70B+ODva8IH4+OfAsMf8yICIVvwbK0zBICafkCQhTQ35HQ6d1UKHqaXlXQIx6tr5QbIC57BhyEBbkVYXK8KgMLe1yup5E7E+6/mCJ7M0iuo+kCqPgGt786DxvlAHgnCT1fAVIekOfFEPL5oYmIiVBZ4VIv4eHhGjRwK0VoKQZTSDS7XeRxqkoKXix4jywTKOxUJHb1cwIuR7k2Y5uvK12svuQDnqxS/2V8meNOu4C8p3PyrktukwyODz16p5M4p/A2W0SH6k9X3dgKfCemDclUIzX+zvb29i6l9Pcw4UWrLWYDHBbbaHXwmJBpw7VNKnrCCISQsUxKDocsN/CVw7E2lSvwug230KgQ4fFmCvzhOK0lRLxIlelWxSRbp7TNZ8KIzVEfghcbzsIl1Sob0t1Nhy/8VAy93hZE5dtcL+DS2RCIvrReLtCIx8ChsOVEk1JFyz9ViFFKIWI1CtSuDFQsvF5eosyMSiUQtNP9EvZTAooJFaP+1ZUKUWYqTLLiRlWQ6nD9cLwIAqCuQyT1Z8nxIbFr+orW1tVmdpDkcP6ojC/gK/viYZU0wMtKizJ0WFjCmSHDGEncwGDwhz5PZ34YW4DZCoe1W58QKtDLZ0BAHR3HYLdUBX8PH5xbEAirQb4R0B7PsX08hMI3N6VyMMCeHwVGGsPeZUggtLVJbvwekfdJXY3aMAgUFQMhSJQyKjhFVE5/eWRoM7+FHN2bAe+waCguUhL2KQIaFBZxUysSVs11HcAKEcIvECbG6EALnedioaZ4SO7oWoxz+PK8cNk1fKRUhABs5KzDNafiPy66cIJq+SILEpo3cWgiUuIilu76mKS8ZiQm3lJhxeTPuQLLg7WoJiAB9MnhY7WlY8nmWKRKOKEVDf6kXzoRIw+7pMVy9XwmXR3MtMQA+qJDDKiREvjJyb1/GEgw7CkE0ReHmtynZ7cGcAMaCwSGI6BPpfIOmaQ+Uc5MMMfbZ0RIaGhoeJNIOM4D/CK7/Tk4AaQuhdG9+0KRbu7u7r6hACDfYyRLa29ubgWWLkgHuJZlNVLliiCeTe0UeLU3zT8XjZa8Lim0zcois9UAJLPoXvrxyn/N9OVlkD0TTEA/+nOInvxVd40qEkGcFpnmsFuA9Hs/XuWnmlcbggt0FV4cTicR2uegRhQVcY3eFTQlBjEtBqJuQU/ykRoXRs+nyWEpkYek7iBLzcyMej8eamppi8sYCAOhtdLvPqxsLShmTk5OhWCz2H1Jkl1a1Bgq3jYLH8hJBQh4dN4xjSsSbmTN4vN7jkNxNkt9MEU1bPhYIfFAPRY/f7/8envltOTnDOA6rXKkqw6ojlHIwtk7eWCBaR5DCYZE22x08Ut6rkqnUazJ4Qe7s4na/GZbIClR8p/GDjcrEKxE33mju6mq3K/jOzs4OkNwbUNgihQweADF/ZJkiF7oYfPdUY2NjO8rl70u9Aj9NJteAJ16bmpoat5vmU5z/G+Cvy4tkhOwcC4WeKtIjKF5DIAweAvI1Cpl8CamutgsntPn9y2gqdVjVPMAfMkKhtcVIeLaucCrs892JX/9LdQeSTL7j9fsHag3eo+sbHJwfn2H2hLxueL13zxaBSt4u7wuHD6iWkJUyNc3NiPVfLiTwDCE/C5//6Yxn4vwVQ9fvImfPTs9aJpeW1YRT4IS/gxN0mROyeQKyrYEmt5t7PZ6T0Wg0UWWic7tcrl9B8H+D1r9toZDdRjh8H545WWKfsLwBTrgPgPcUeFsjgH93JZPJ5yORSHg+gbe0tOhOp3MDrFDk9vrMblf6rZUNsMSXyrluRa0rZFk9YNyX5GRJGXFo4ghcYz8sZlDs1KrkPpn9fH2imQFTF1taGixbfYS8q1G6DqHuTLn3mEvvTkQIkW4+TpQFVmUkxa4TZppi48UwwHwoVqBFVZZdhxSrUWJBJrMm0QOwvfjNSpDtDbO4aVhsxoSAn6803abzZJrb4BYbC7xJNu9DbH+Hue9BqbtdVLFzuda8dW/T7/hp2gDMfgBWcU2VGnsfi8aN6F1U+i5i1QQgX9Pj96+EINbibxWE8Y05Yeb8LJKuI1D7AdTxb5MK3xBdSAFYxevl8O9l8P0esSUnsyvFI70+L+L1mFinTC/VMSZenz+ZruCqnF/8H8NHa92AY3WkAAAAAElFTkSuQmCC"; + +var img$F = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZE7SwNBFIW/JIoSE1JoISKYQsUiAVEUS4mgTbSIEYzaZNc8hDyW3Q0SbAUbC8FCtPFV+A+0FWwVBEERRGz8A74akfWOCSRIMsvs/Tgz5zJzBtzRnJ63WoYhX7DN2EwkuJhYCra94qEPL37GkrplzM5Px2k6vu5xqXoXVr2a72s4OlZTlg6uduFx3TBt4Unh6LptKN4W7tKzyVXhI+GQKQcUvla6VuEXxZkKfyg247EpcKuewUwda3WsZ8288JBwfz5X0qvnUTfxpQoL81J7ZPZiEWOGCEE0SqyRwyYstSCZNfYN//nmKIpHl79BGVMcGbLiDYlakq4pqWnRU/LlKKvc/+dppUdHKt19EWh9dpz3AWjbhZ8dx/k+dpyfE/A8wWWh5i9KThOfou/UtP5DCGzC+VVN0/bgYgu6H42kmfyTPDLd6TS8nYE/AZ234F2uZFVd5/QB4hvyRDewfwCDsj+w8gsVKmgU+omlKwAAAAlwSFlzAAALEwAACxMBAJqcGAAACd1JREFUeNrdW2tsHFcVnrmzT3vt9e7s+gFNCa3TxPCjpEUi5AFCIlKbpFUrEolKaQuImDTNo2kgP3gIiYd4CPJqQ2gi8Wit0qoGShO7LUb9EUxIlRSDVJGkSWkIqI7xzs76va+Zy3fN7nLnena9a2e9417JnvV4duZ+537nO+fce0eWqtzC4fBNOHycyvJKyTQ7ZFlealLagnNNhBAvu8Y0zRQOCSLLQ5TSq7jmIo4DOHdW1/Vr1eyfXI17hkKh1RIhW4Bso0xI+7zuRunbMF4PfroTsVg/O+NIAwSDwSbicnXKlHZKsnxrVYaL0n/AEMfNbPb4yMiI7ggDAHhIUZT9oPVOUDogLUCDy0zAXY5mMpkfjo2NabUyAFFV9RHw8VvM1UtcZ5iS9AaRpH5qmhfwN/PvfwHE2Ojo6Di7oLGxMQDjNcD3l+BnOU51mLK8Ft+5E59dJe6dACu+GY/Hj7LnLJgBIpHIbVlKn0YHP1bkkjTA9gJMFz73oYOjc3kODNwAY60H7beioxtxylOEEecUQh7SNO1i1Q0AVX8IdD+GEauz+beGETkEah6bLzXFBpaEXS7XI/i4BxoTtTHCFNxiJ4z9s2oZgIRU9SC+sNvm4ZN4+HfdbvfhoaGhiWr6f1tbW10ynd4Fhn3dTnNw/ihC555yXaI8A7S3e0Oa9hxC2n02D3wJh13Vjtd2+QVc4wgA3G8TLU7Gw+Et0pUrqfkbAODDuv4iPt0lPCQFodqb0LRjUg1bKBLppIZxGGzwWVgpSb9PhEL3zmYEuQzad4tWBuXfpYqyaSQWG5Ac0Jqi0dvRqVMQ5ZtmMCEev7+UOyglrauqBwD+8wL4t0D7T43o+kXJIS05OTnk9/l+jYhxNyJP5P/DKy/3+XxqMpnsrZgBTaq6FRZ9RgTv9XjWQej+IzmwBVpbo65U6jTcYYXAhC+ACT8v2wCI88uyhjGAG9VbaG+aa5CCXpUc3FCH3EwJ+RPvDixEIk+4wy5PIHZ+jzj/Sx48EzyXotzjdPCsTUcjQjYBdLIAiBC/YZpP27m8YkP97aDFdgtNZPkxWO8laZG0aU0IBIaB4x4Ow/v9fr82NTX1elEXmC5sXK7LLAsVlPTeGuBwIRX+EjreF4vF3pqTO6jqb4QIlsik0+18lmpxAZSz+3jwLMPDz65ajCISnddQaD0Jd7wUVtX4nAodSnezypEnOLLV/bYaAPEIQuQsaS7S2+8lEol/1oTHsrzOmu9E7qj0FmDuv5G9ftsSySh9lDF9JgMI2cZKUv77qPMPOcWv0fE/zMUIPo/nCRxinCDWs4kb0QAy+N4pxM7Dw8PD47UCHNc0MUSHYIQ3YIQ7K7nP4ODgJLAcFFyjM69/JEf/VaDKMu4aaEX6J7UedRsjMCb0VWqEbDb7UzZHwbnXLU2RyNqCAQB+s1DhvTw+Ph5zAvWLMOF8JcI4Ojoah6D2CCzYXDAAlHKDEPe7nBTX7ZiQE8aymQDAXcLfG6ePuEkbLPouP4dnZLMRZH0JpyU4GHWaz0wxSt58bIeBQmWE1UZ8J84nf2D6BwhGf7VA/wEngrcwAeBZfp+P7eUwgc1LmpJ0Xji9ilBZ/oi1EiD9Tk5z80Zg+b0QImc1AqG0X3D1lQSc6hASkAtOz/UFTWBsbWLCiNT5o7N89YI10tMVRDbND1pOStKlxVDwcEZo4vreV8oIAHxJYMBSF2rnFt6cNJO5NqsIObBBEwbhFm3o4Dn001YY2YKMbM0pWgi+abnQMIyxIpXVfqGwcFRj4Pmix04T2GqUWP2T/BJ1vo23to4VmTr6vmWSxOEtaxinbRKiccFoXlL2HSn9GiuPF4sBkN0eKOu6plBonB/ZdCoVLZYGO1kDyskep5fX3G6Nc4kpF3jA1tkLBkAJ3MCXj2WkpLXPDK1R7JCuaXuL6ESDcCrBwuCQhRJu982LYYTz4Jn6lwM+F/aWCBM+QwRh8B2hSFixWMDz6o8092Ap8Lm2QgiLV4ksZEfiRU4GX/BlgE9o2uNlCGOH4BMXCEb8b0Kw/MR7EXzu2rUC2wfkaDTaanB+xK7LlcP6ewm8XTkMH1hChoeHr+NGf7eKJVnvdPDTEl4m+FxbL8wFXGGzxiRXJvYKavmgw8EfqDQkQ/C2Cv7fU5gSQ+sW4sVdgUAg4mDw+yq5T0NDgwoB3CBo3QsFA4AKr7Olb+7fLrfXu9Nx4Cn9caXgWXO73WxzlYenv67rZ3gGsBBxXCh+drNtajUmgWYBH49/udIbtLS01IPRjwn0PyHlttwSLiScgBjy+/lC8Ju9NYNO6Skpv045R/CsZTKZPZJ1vXOcbbUtpP75D1NTUyl/XV0dRv6T3ITBKq/X+2wqlVrwSVI8900cPo3RO6rH41+dyz2mN0tI0vMQdTfH7AOJRKKH+9vyhSBc4Qo+RriR6IX1N0qLsAHP74CHX9qPI8dp53McywaJZDKZ8tXXj/AbCzACy/x+vy5uLHB6a1LVHSh2Hhd07SsQv9PCuZkpMxSYXcSnjWlcuEbTtPOLATxbRYavn+EWT1jWeBaJ05r/feT00E5+soR8jokFd86DdPlksLn5FqeDDwaDS7OGcdIC3jQnXLL8sAi+mAGk0eHht2VF6RQmE1pJJvNqc3Nzi1PBI+Q1w+dfRV/fJ9T9O4ptsym6UTI5OfkmfD8AS67mUuSwYRj3eRsbe1ITE7rTRh4sfQ3gbxNmiI4givygaIk8y30J9OA5HLdYs0jzugJ1hSacc4rPg/anhKlxlvG9CNH7jB31S7oAjxWp51ZJKJaYO8Cy/Sgxd9caPLLVR5ngieDRXtFV9bOlwJfDgIIIggldIhPyeQLcYidi6zsLTXlFUZ6AX26a0SVJ+q0eCj1QznZ5pcznGcgDuqEJ9bwm5PME/O5EEqng5y+4Ll1N4NFoNODz+fbjub+C4H3YBjybGP0iKrxsOfereJo7FIk8QA3jKZspZtZ0JjqZVOrJG73FhpXnHo9nB4Cz3H7GS1rTy3aEbEesr2h3y5zm+Ruj0VtdpvkLIVmy1CBwjVdQTHWhY31znV5j7yKC5uvZZAZG+25W2Ra59M8IdQ8j1F2u9BnzWeiQwYZtsml+x+4lJn5w2K4TjM4fJfbKHHstNpO5xhZh8+uQgevXG9iCDFuTQIeWw3gdGNJ1AL1yFqHWoHDfwKg/NZvYVcMAhQIK4PaB+nvQ08aFEEC2ygvjHEFZ+6P5bue5YUtdbNYVo7sNo90pJiM3bIrANC9LbOLGNE8gvo/ciHtWZa0PxmAvVG42ZXkDWPGheY72RRi0F+C7Afqs5NSXp0uErVb4+xqw43a2H4ltyWG7UtjGjPybXtOvzxOis3VKtlTHVqtkSv+K/5+BsA1Ws3//Bc6zp+jC743WAAAAAElFTkSuQmCC"; + +var img$E = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZE7SwNBFIW/JErEBymMIKKQQsXCgCiIpUTQRi1iBKM22c1LyGPZTZBgK9hYBCxEG1+F/0BbwVZBEBRBxMY/4KuRsN7JBhLEzDJ7P87MucycAfd8Rs9aLWOQzRXM8FwosBJdDXjf8NCDDz8DMd0yFpZmIzQd3w+4VL0Pql7N9/07OuIJSwdXm/CkbpgF4Wnh+c2CoXhX2K+nY3HhY+FRUw4ofKN0zeFXxSmHPxWbkfAMuFXPQKqBtQbW02ZWeER4MJsp6rXzqJt0JnLLS1L7ZPZjEWaOEAE0imyQoUBQak4y+983VvUtkhePLn+DEqY4UqTFOypqUbompCZFT8iXoaRy/5unlZwYd7p3hqD1xbY/hsC7B5Wybf+c2HblFDzPcJWr+/OS09SX6OW6NngEvm24uK5r2j5c7kDvkxEzY1XJI9OdTML7OXRFofsO2tecrGrrnD1CZEue6BYODmFY9vvWfwHle2f+inwUtgAAAAlwSFlzAAALEwAACxMBAJqcGAAACSJJREFUeNrlW1tsFGUUnvl3tyV1e5m90EIAMVSwPkhQE0Tqmz7ILRDhgYSAL1TkkqqoCVFDYiRRIgGL1QiJFyRGAwkqSlDeAJEEBd4od4IJ0trZbbutsN3d+f3Osltn/53ZnZ2d2a5xkma3c/nnnO/cz39Wllw+wuFwSyqVms9leTaXpDZZ0x7gjDXjc6LMWA3do3GekGS5D+d6ce26LEkXZM7PM8ZO9ff3/+kmfbIbiwYCgbn4WK7J8gImSQ8b3aNpmgQG874b3NeDa0e4ph2MRqOncYpXJQBgugFSXgtCO0DwTDeAxdqXgdQeoLIXYAxWBQCKojSCqM0QSydk2CBV4IBWxGA+XVoyuWNwcDA6XgDISii0Fra6Dd9DheiF5M4DpOP43gMt6eGJxE34hdhwS0uMbvDfvl3v8XjqZZ9vGgiaJXHeBi7bweQcXPYUWFvVJOmtAVX9hN5TMQAawuEZXk37HF/bTW5JgomjnPMvIa1jdqXU2NjYBGCewTqrAMazOOUzufVXJstr4DAvuw4ApL6Sp1J7YOd+g8tRmEJXIh7/cHh4uN9Jtff7/aGampr1iBad5HIMzGIEWrYO2rDfLQAYHN17IOBVg5ffgQTelWV5p6qqMZfDqh/m8xJC5xYIoS7PUUrSrqiqbrZqElYBqAkEg4TsinzXzI+AoI1Q8+tSBY+mpqb7AcBuCGSxAQiHooqyUrpyJe4EADWQ/CG8aIFwfhTMvxaJRLpKiWROa2YwGNwAH7ED9NUKl45GFGVpMRCKvUiG5L8RJQ+Vv+1hbDHU/TcHmbZNZygUejSZSh2GRkwW8oZvkS88V8gcWJHkZrvIPBa9wn2++RaY5w5mbQXXgvc/C7rmQzCXclBjbKkSDO60hSx5e8T4r0TmfT5fe19fX28FpF4y3c3NzRPjo6Mn8jJRztfAVPdZXojiPEsmz2Gher3ak+QH+/quuWzjZa2B3GE6JP+L3hxA+99ej2cONOWSFROQKcnRM08ODza/pEzmZd2fE/cZvg/R6Ab3eBZB6mPOj8JlkvN9RvwyA9Vfm5fhwdvD5s/YZN4KM3afNQahv/8cKtGXBUbnImK8WFCNqLBBMnMZISWsj/Own4U2mHej1C7pXeDnO5jDEt2pSCqZbNWn5rkagKpOzzxleJTkVAnzhdY1o2MT2b8+sKG2eN3QBNL1PEranItIbwtkeNxhdXccBOQAN8HDttzSlG+kIisPAGpmCPV8lHJ7qToPyyAjbH9AZbPOIfqZ19uRD4CmdQhwdhUobLhVopBJVhKEPLp6e3tH4Md25TzIeUf2eZbt4QnJQ4JK2nKZd6XfCEB1oFoCIZFIfJyuXcaekmfAQT6p14DlQtg76mQ975QWZNeJqGpJz8ViMRUafkRw+CvGANCESg/V1f5yVBHFiSipskEowLwl7YM/2y80MdKhXU737TVN33vXECtDJm2ssmwfHpkKF9sAFJB8UbooygGFSE6PkfOpjDYthILnXAk9PFP0jYhFCCqqCaLmWGDekhYgmRtCTfy7cHoeox0bwTZOOGX7RDRJ3chEimlNFggLzFvv6UnSyRxhy/IcRttVwn09Tpa4RipvpAlmmlEG83n0QrsvCH6gjdFenYBKj9PJiJkmZJl2iHkr9PQIjnE6o43KHAASiZtuxG8z5+eC5M1VgvM/BE1sZlADRX+SdmzcSmKsMuUG85niLiZoQAAJIJugP5ndrhovENxino6hoaFhQSNqmfQ/PxjUIqdvThuVbufylUibjY6Ghga/YAJJhrifk/TQLu14Me82CEKfk0zgLwqDOS1u2qKuJPNmNu8GCJD4VCE176UweF0IprPsJhp2mTcDwSxjtEsPAJglaMANRgNJQrBsKzfxsSN5u7VDiYlRmwBID6NpLCFYPuW25zWTeKm1Q8l5gCy3CxpAmz/sVA4qjM3RNw2dMgOrcd5q7VAqHcFgsB4x/zHh9GlGc3g0iqb3DTSWMt6ZYKHawWYaTDx5dSeuprvGmfBwRE8gzeSUYFfcSeZt1A6WmjQo8lYJ//841hKjIUT94jSQRDM5lZa8WyESCVAAiCwUADioR0pWFOUiGH9QpyJbI5HI2zZbULycyOF4DhIIvAGX/46Ot2vgrZW+sTGCaQIzN0Z00kCSjTjMpSo6Jk2aRINUnYL092TpZLrwt1coFwM0jVViTsCd6CI5edwdHd0k7HeOaMnkHl2b7N5Bs7c0fiqEny00cOBkYlRh1Z8C//amkP52m+4OA5n3pdx9tDqExN1OtMXG44CqdwkDnQOJRGJ7DiD6f4DMAM3eCr5gEY2i/ddAUEKhDhC2TEgGttIuUTHiGcIMtY/n6R6Mw2tOsJmFVRygpnB4tpRMntZ3u2D7ZwaiUeIpZaoB2Xtp8Dg9e/uvFtQ2KcotJ1Jh1yWvKNPA7Q8C83c8jK0WmTcDQEpPXTO2TmgmTAIIF2kUrVpt3t/SEoZEfgJTUwTHt1FVVcN2v2lPkKauafBYAGEmzeHpIoNcLT6AJO+Nx4+DxodyVFTTumG+n9q1T6YEgwdFZwKVuuX1eBbThGY1MJ+2eVJ7QfLwXYfB/DIj1S+qAVle01PXknRU0ITJAOFUUzC4vhq8fdrhCcwjmv0cCQRWFGLeuoduba1VVPVrmr3N84Ka9j0+NlFpWfEkB3E+L9RlJU/MWxiX91gryyKpu3fvHphQV6fghXPFPhvK5xfq6uqo6jo7MjKScDu399XWvoJ3HoBze8RAIN0QxvOg2RIdsg3kVyNF/ghmcJ/BZZUGkmgmR0w4yj2opPV6veukexOgeaV65lcrG2Dzn5Wyri0PHgqFZiY5/wJ294TJLaM0k5MZSzlGwwk21ZzG9p6mZkamnq8xdFRIcijOm4U6t7I0RrO3CJXUMwgUuC9Fkxk0nJDZn++hXVqqPLN7dbRjQ5sW1LfPtK7bqIGJZx4vYqYDmb5FdzFn51qaipxAofFTmsA0+SWZ4wdlqVTVUWFTrqk5lsRQJzk9galpaxEtWt0p7/g1amZQPV/uL0bdLFTk9BAizeFp2sKyweD8KjUwqYc30N9/UqrWH08XitdUWdJAEs3k0FgKTWbgMwxf4M2E0ji+R2ivjraraMeGNi1w6bTb+cU/7fBoL+/5UFUAAAAASUVORK5CYII="; + +var img$D = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZE7SwNBFIU/N4piFBEtRCxSRLFQCApiKRFMoxYxgq8mu24SIRuX3Q0itoKNRcBCtPFV+A+0FWwVBEERRGz8A74akfVOVohIMsvs/Tgz5zJzBrTJvGG59TGwCp6TTMQjc/MLkcYXQmiE6aQ9bbj21MxEiprj8446VW8HVa/a+6qO8LLpGlDXJDxi2I4nPCY8uebZireFO41celn4UHjAkQMKXyldD/hZcTbgd8VOKjkOmuoZyf5h/Q8bOccS7heOWvmi8XsedZMWszA7I7VbZg8uSRLEiaBTZIU8HoNSC5JZdV+s7JtmVTyG/G3WccSRJSfeAVGL0tWUmhHdlC/Pusr9f55uZngo6N4Sh4Yn33/rhcYd+C75/teR738fQ+gRLgoV/6rkNPoheqmiRQ+gbRPOLiuavgvnW9D1YKeddFkKydQyGXg9hdZ56LiB5sUgq991Tu4htSFPdA17+9An+9uWfgCZXmfbLPy9EwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAtBJREFUeNrlWwtuwjAMra2cALj/CWFHWLYiQKGLEzu282GRqiFo3bznT23PhY1Yl8vl/vd6vW6VFTf5AitZp/P5JQsByPMoHEABr12oAE/d21IWG0+gTuywYrLx2OumR8sOSnmg3LwaONcFiqZT0j4jBngAhoZYVDX/HLbQCfgRWJT6MkVGycefn0tEQO5HS7YJWWwCanI5+y8REKxUu99UEEhzsQO0hFOKK5GFrdrfhT2PQU+RJiVVCdA8WkYA0O4DPTdrHUg5AKUk4AhNzURy0DIqDH4uJB/3sH+mAt+fVPg7Ri+Nx5bonpFtIscrFeZkfFGxeSs5pLLQGfww2Vy3xIXAu9wDO2xMY7bgTQJODF5EQi4Q59zg+B1ODt7FElIS4HQ+v/34dbv1Ah8NrqleW+t14OSad7cEXAi8Cwm4GHgVCRbl8Azgm0igiqagBf/rR+BZCVaKGaor/ZY2l/aEC2reNCaE9LGXtrgy1diM4KuW8Lt/YPcDMqayAniVO+CiZm/mDvhB4JtIwA8DLyYBt3++Qmsw6bUa8wq2FeOoRoTjErkw9io6ZgR/dwGLVHMl8Mf+BzIaCCtYQvOTC5m9tJlJUD22JdVg1h0etQKsCP7lAtyO6mSWYJKwoaQWn4gEs2wVGxOOkSSYpuqaVHgECeZ1ingqy3BTUXl+E/gU3z4aYFEM9bAEc/B38wdonxLrSIJreW5ZDnuQYAaecm3UChjQNDG7B/m/QcoNJiDBXDZ22CiMluM6K1wQDoqgaqb12mMdS/6hcINlFqZDz9z3hVYnIcUVtg9dZmNyveZ+e4En3xpLL+aAfp43G0Fdp8UVsSCOKKWzEyKcbtAKbpAL4hwMotfmDF6vE78252mJr1RYo+G9KfpojHIOiYuwjlalNI3LCwYopFle1ChAky2GI7iOSc4xz+/SVK0+BrlEPH6HwgyR1MebSOBOqVHf/wB4polu0KoYHQAAAABJRU5ErkJggg=="; + +var img$C = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZE7SwNBFIW/JIpioim0ELHYIgaLCKIglhJBG7WIEYzabDabRNjEZTdBgq1gYyFYiDa+Cv+BtoKtgiAogoiNf8BXI2G9Y4SImFlm78eZOZeZM+CfsoyC2zQIhWLJSUzGtfnUgtbyTIAQHQSJ6oZrT89OJGk4Pm7xqXozoHo13vfvCGZM1wBfq/CIYTsl4THhqdWSrXhTuMvI6xnhA+GYIwcUvlR6usZPinM1flPsJBPj4Fc9tdwvTv9iI+8UhPuFIwWrbPycR90kZBbnZqX2yOzFJcEkcTTSlFnGosSA1KJk9r9v8Ns3w4p4DPnbVHDEkSMv3pioZelqSs2KbspnUVG5/83TzQ4P1bqH4tD86HmvfdCyDdUtz/s89LzqEQQe4LxY969ITqPvom/Vtcg+hNfh9KKupXfgbAO6723d0b+lgEx/NgsvJ9Cegs5raFusZfWzzvEdJNfkia5gdw+isj+89AXPlWf0rTeiAwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAZdJREFUeNrtW1GywiAMZDOeQHv/E9Z3hBenf05ttZAACSQz/lQHdjcJCRVSCgsLm9nQcC62iA3GSDfHCcOkm2CGI+JVsKMDeTQcq/oA7H0OVASmvb5UmQ8VwPSsLGghABvoKdRwwCl5NTxwTF4FF5yTF+MjJ/uIrmWQjZMXYSXnnhdjo8Lc8mRcqhg7834RdkqTGw2S+8VYaeDcv8SJBvR+tRTwZphdgEtpQJPkvygCMHIaRB8QAoQAIUAIEAKEAOUvFDxugCICfgiAgfmiNAKG3R/cpAPcH4/093wePte0szmOnuc4jTQ2QHuy2uSV5oA0AvibMDVIC+a4nLLTV4GS8zrWq0QW5tsMTl6W5fCLdV1/pgCclcQsbJswqBFWxsjjnfDHIvj+8CxUHETCpQMSW8hLvDjEEZm9kzX+G2Qv5LUaGD759CAvwrFxj4OSFUuOi6OyJOjhkRGiGqGuTl6SApKFcKjj8j2rgakLEy2FMHtlpqYYri5NaYlh59rcvn38Z7sbQgK+9v4fv0+TG+V635N5xt7MXlrTY+62KCOPAAAAAElFTkSuQmCC"; + +var img$B = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZE7SwNBFIU/4yOikYAKilikULFIICiIpUTQRi1iBF/NZpNNhDyW3QQJtoKNRcBCtPFV+A+0FWwVBEERRGz8A74aCeudJJAgcZbZ+3FmzmXmDLjmUnrabglCOpOzwrMh3/LKqs/9RgttdOOmT9Ntc35xJsK/4/uBJlXvA6rX//sajs5Y3NahqV14QjetnPCU8NxmzlS8K9yrJ7WY8LGw35IDCt8oPVrhV8WJCn8qtiLhaXCpnr5EHUfrWE9aaeFR4aF0Kq9Xz6Nu4olnlhalDsgcxCbMLCF8RMmzQYocAakZyayxL1j2LZAVjy5/kwKWOBIkxesXNS9d41IN0ePypSio3P/maRvjY5XunhC0vjjOxzC496BUdJyfE8cpnULzM1xlav6s5DT5JXqxpg0dgXcbLq5rWnQfLneg/8nULK0sNct0GQa8n0PXCvTcQcdaJavqOmePENmSJ7qFg0MYkf3e9V+kTWfgP9nSuwAAAAlwSFlzAAALEwAACxMBAJqcGAAACLpJREFUeNrlW1tsU2Uc/76vl5HZjZ1e2Ea4GRZwvhD0AYHxJg9cAxEeSAj6sokCoqAmPBATo4kSCTgkBEi88kCUBBUlQ964yBIUeGOBcQkmk+HabmwTurbn8/dv2nL6tT29nq7ML+nanXN6zve//3///7+cWbx8Pl9TNBpdLDmfJxlr5br+rBSikem6JoSYRNfouh5iQgRxrh/n7nDGrnMpr+H87wMDA39buT9uxU3dbvcCvK3TOV8uGHu+lHuBOT1gxGmp6yeCwWA3DsmqZACIroeU27HRDmx4jhWMxb1vQlOOgCtHwYyhqmCApmmTsamdEMt2SLveCsIDfj9zezxGrRjmQnTqkchnQ0NDg+PFAK55ve2w248Y5z4zLYbkroJJ5/G5B1rSI8Phe/ALwyNNTcN0gev+/TqbzVbHHY4Z2NBcJmUrqFwCIufjtDC5t19nbPeg33+YnlMxBtT7fLPtuv41PrZluSQMIrqklMcgrbOQUrCY50yePLkBjFmK+2wEM5bhkCPLpZcE56/CYd60nAGQ+gYZjR6GnddlOB2EKXSGQ6EvRkZGBsppBi6Xy+t0Ot+Etm0nl5PBWY5CyzZDG45ZxQAOR7cHG3g3w8MfQQKfcM73+f3+YYvDqgvm87Yu5S4IoTbNUTK2P+j378zXJPJlgBNOiDi7Pt01y9PY0Fao+R1WwQXzmAXzOACBrMzAhJNBTdvAentD5WCAE5I/iQctV46Pgfj3AoFAJxvH5fF4tsBH7MX+apRTXQFNW5OLCbkYICD546rkofL3bUKshrpfLjSUW+WbGjStDybRrOQNPyJfeMXMHESO5OZTlXjctFc6HIsLIF4aXqyI7+T1vcFgcCoEcyOFi0Ks0TyefaYSNvP2qsMj4h0OR9vQgwe3LSA6n/uZrhqnc0kaExh7C4LcVJCqUZwXkQiBEZdR7UnyeRJv9eJmzhGSv4i9TzWGSLvN9gLyhBv5aACnJMdIPDk82PyqHMTnK3Ge41WSL0E0ugtiV8FBJ50faHkmIuU3megVGVS/PS3Dg7eHzf9RgtQLITDfa2U2AUDSV4BEdyiEvoSI8YapKhGwgfr04qPXGOcR6lYUSTwvow8we4bM9EzQ8xPoWW3EVdFIpMWYmqdqAFCdkXjK8CjJKWJjnJW31mB2P2ny/zbQ8K8xsCF5ej+jCcTwPCBtykmktyYZnqxkkaWYeyMHuAcaPk6FpnIrgaw0BlAxQ8HzQcrtCyCeW0x8UUxA2P6cYLPBIbqE3d6RzgBd71Ao7LQa2FjgD9JWf3//KPzYfgW9tScYyZM1PM67DZdExkKh5iyQVlZY7UtOpevq6jwOp7OPcI1B4G0wkYsJDVinhL2uKiS+6DU8POwHwacVh78+aQK6gvSArr6rUlqK9jPwZ8cUM4iFdh6r2+u6sfauI1Z6M5SxnkrpG6McuBDAR5tB0tMFNS0UwHOt2BpeNS8kcw+Bif9UDi8U1LFRbOOcVZh9vBfs/UKKsDmfL6hdpVzXM04Iz/oQouvXFT/QKqhXp3Clh03c1aM4xlki1qg0MiAcvldB9ZeV1C5Et7+UtLiRNGAKAEPyIHVsxiGpqQgTqKWmaIBPAC46kR8nDybaVeOQ0VnOhIcPH44oGmEX7H++BOwgbDQBalSOE6KzPKzW19e7FBMICfx9YDQB6tJWMK2taE6h9jNhAgFygv0pu3I4ZjwNuX2ReGC6UvDppzB4R9nR3HJj8qpBUpzPVTTgrqCBJCVYtk6EtDfLalUY0iNoGksJlm0T1eMD9rcpGnCVe73eZkSCPsPxaBwOD050OAxsMFPQHB6NohmutdFYygRUgJeVWsCtWNU4Hh5OK6qxMU9pPzXOECBvo/L/r3GIHFOFEymUCrGMZnImiuiRALkhvRUKA04kGUATmLEhxCfLERtImiBaYLfbNzNDRRgqfntwYOBCkgExImgCMzVGbKeBpBLATVWs5ubmWtDyjiL9I4k9C0P4O6rARTdNYxXg+auSCY/Hxrax1H7nqB6JJIWdZADN3tL4qVIw2NXQ0DDzaWUCQt80mPZuJf09mLU7DM7sZal9tFq8DhRYFaoaJkDVO2k4wnBoMBwO70lhiPEf4gzN3iq+YBWNohXBhHIyouD7aV5vBza3VknzP6AuUS4CaDSOPORCwxdD4OQimrwoUuq8BMILvk+DzzePRSLdiR9kxG3/8mAwSDRFs2pA4loaPI7N3j7RgppINHqKBpCKJLCQqbGSJsw0TZsBan9RiH9kE2KTSnw2BrDY1LUQm5ViwlQ4yTONjY1TSsT2Mser6OVqavLhBmdA1DTF8W3x+/0Zy/1Za4I0dU2DxwoT5oTGxs6baMK4ASSSvD0UOoc9PpfCbV0/GAgEvip2s0LzeE6ozgQq1SdttpVDAwNXK5Qk8Zw2T2qvSB6+6xSIX5tJ9XNqQILW2NQ1Y12qOdh0/VJDhrEzE9PgBRKc1/fI28ccnkI8otlvAbd7vRnx+atrS0uN5vcfp9nbNPHq+s9420bQsuJJDuJ8WqhLSJ6Iz2Nc3pbX0wKB6OPHj3+YVFur4YEL1Dob4PPrtbW1hLqujI6Ohq3O7R01NTvwzO+F2tmO2zyE8Rr2HC7ZtrJwfhNS5EOZfq0RyyKl3I9s65CacJQD0gLVkcltz/QjrfivVrbC5r8sm3PJtrxe75yIlN8KRRsMa4xmcuJjKWdpOKGY5yADrYOkl1IxI47nnRkdFZIcivPZQp0VGVrMF9LsLVz8hyzDj5gMK0qTGTScEO/P91CXlpBnoldHHRtqWlDdPl66bqUCJr7zIsF5k3sPUnoLBh/M5ewsi9nICTQaP6UJTGXC3LJFWSqhOgI2pZpa2ZIWGj+lCUwuZQdsdLY18E7epmIG4flyzTFZkbVxZGWLYnN4ur4CobOlRKJvUQGTanjxMlZ1/njaLF4TsqSBJJrJobEUmszAuxu+oCYeSuFT5T/Uq6N2FXVsqGmBU91W5xf/AaUAHXpt/nz4AAAAAElFTkSuQmCC"; + +var img$A = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZG9S0JRGMZ/aqGVIVRDVIODRYGBFERjGORSDWaQ1aI3PwI/LvcqIa1BS4PQELX0NfQf1Bq0FgRBEUS09A/0tUTc3qOCEnku574/nnOel3OeA/bZjJY1WwKQzRWMcCjoXYoue52vtNGPiy5GYpqpzy3MRGg6vu6xqXo3qno13/fv6FhLmBrYXMITmm4UhKeEZzcKuuId4R4tHVsTPhL2G3JA4Wulx6v8ojhV5Q/FRiQ8DXbV05tq4HgDa2kjKzws7MtmilrtPOom7kRucUFqn8wBTMKECOIlTpF1MhQYlZqTzP73BSq+efLi0eSvU8IQR4q0eP2iFqVrQmpS9IR8GUoq9795msnxsWp3dxBany3rfRCcu/BTtqzvY8v6OQHHE1zm6v685DT5KXq5rvkOwbMF51d1Lb4HF9vQ+6jHjFhFcsi0J5PwdgadUei+hfaVala1dU4fILIpT3QD+wcwJPs9q78GJWgN6zGReAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAlxJREFUeNrtW1uOgzAMxCgn2HL/E9IeYb30AymkYbETv6BEQuoDiD2xJ+MQYNhp0zRh7fdfxEGrjQCb7/M8w6DcgOq4BwAWQADVcU8ANIEYhy9vcDT6FnnISUNpe1Ikx8u+qWnZFQG1Tjydp0SDpH1fzwFj5NHP7CmPexZQJ8FK4xASXA0A7HG8V1aX5/08HmKyOmmiazGNcW0pgUjEUQBCFEBEx4+ASFfMay0SdJOxZc6/ns9ue96/v+1JFihHltWj9uhHEVY1O9723lLYKfSRKazU7JHmAEq4Y/HZNUVSgCg8BKHC+ig1IB4cAJ11hui5aUWXoq+V89YkHUrlOzLEBVJunh+NIEgqUmBxAEdhOTeXJTE4k2NaswAI5nuIYstjFgjjvBcAocrs5OQwdjp/aiG0GqbtPOncUSCfwy5/aXMAGilEOyHUG1pMWR2GOLE4uOdXrzEAoaktdm1sry13g1MxZDUlYisHoLVxJiSYh2rgsNUVQsQOwCsFNFeEWoohby3PFUL/2paOtqYRQXBf3LQWQp7OhhBCR0UNSgI1TdPmu+TTpqQwGnjqFOh8ti/ufDn6V1wQ8Y2AvaemEYyrjf5ir7wQ2ukcpQknSthXSYwz6vlDj0WlQV5p5SVx/p8QV3DvB7VqMFeW4muCBFndS7LAuB/ugPAJgOUObVfSK5RvqpBMMxBEWQ3CKQCcFCCToDL5QZT73TrgBkB3Pg9FqDV77rfGLFCOsFlyz65k2Xm0V/BUIqBHVpetZcvOqvKob6GG5YDW/Urc61RSILKs/nhjxKKzCEDs8c8fwBklUiRq2yMAAAAASUVORK5CYII="; + +var img$z = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZE7SwNBFIU/4yOikYAKilikULFIICiIpUTQRi1iBF/NZpNNhDyW3QQJtoKNRcBCtPFV+A+0FWwVBEERRGz8A74aCeudJJAgcZbZ+3FmzmXmDLjmUnrabglCOpOzwrMh3/LKqs/9RgttdOOmT9Ntc35xJsK/4/uBJlXvA6rX//sajs5Y3NahqV14QjetnPCU8NxmzlS8K9yrJ7WY8LGw35IDCt8oPVrhV8WJCn8qtiLhaXCpnr5EHUfrWE9aaeFR4aF0Kq9Xz6Nu4olnlhalDsgcxCbMLCF8RMmzQYocAakZyayxL1j2LZAVjy5/kwKWOBIkxesXNS9d41IN0ePypSio3P/maRvjY5XunhC0vjjOxzC496BUdJyfE8cpnULzM1xlav6s5DT5JXqxpg0dgXcbLq5rWnQfLneg/8nULK0sNct0GQa8n0PXCvTcQcdaJavqOmePENmSJ7qFg0MYkf3e9V+kTWfgP9nSuwAAAAlwSFlzAAALEwAACxMBAJqcGAAACQFJREFUeNrlW2tsHMUdn5nbuwv4dXd7ju2IUh4BbAmpBAQyjfnWSJQQSqREAslKK6QY0jwoBSIqFRBCFS1tRBKSUiUfWmgkRBMEgiRA+QaBgNoS+FKHEN6oiXOPtc8Hie8xw2+ud2Z2vPf07tk+Rjrfend2d37/x+///8/MUeJxi0ajfZzzHwtKrxKEDFDOLxaM9RDOw4yxoOyD6+cIYxaujeHap5SQUSrEBz6f761YLHbay/FRL54ZDocHKWNrAOwmgOyfzcM4If9lQhzG4YFkMvnuvBUAQHdBi+uhzhGAv8wLbUGgJ/DsPbCOvRBGal4IoKurK8QM4z7B+RZou6N0PplIkIhpemK2sIoUBr4DEtlmWdbEXAmAhUzzTkbIoziuhJRDOMdgHW8SSkfBAx+KbPaLfD4/me7tnZQd2k+f7oC/d1C//0JoV7pMP8DdAG0vk+8p+2QhYuCM31rx+F75X9MEAGK7jAvxNA6vL9MlC9CvUEr3AejrExMT4w1alyTKFXjOMIR3I075y3Q9kmPsF6lY7GPPBQCtD0M7f8HA2hwuJ6GVHZlM5s/pdDruptm3t7dH/cHgJgx4i6QcB36YpD7fnbCGZ70SAAub5jbc8CuHl3/DKH0MZrwdYSvtZdgyTbNDCHEPLPABKOE8B7f4Ewhya60uUZsAli4Nhi3rWXRe7fDCgzDzzTDzz0gTG9zjYgh8F1zjJofL+0HCw/jOzF4AAB+xrBdxdKMGfAq+eW8ikdhN5rBFIpEtEMIfcRjQxncYlrC6mhBoVbMPh58HG9+qmfypccta0sB4hRfcBLe4Ns/5S3CJXgdLuO3/kbMMwIrJjWk+4QD+RB3ghfYhDdxXtcEK/yX8/uWIPCe1S2thIX+oqOEKprWuyLg28MFA4IY6ALjRahLGxJkzn/j9/qEZQqD0vnA0entdpoY4f3kun39PDXUA/z88fHkVshNNcPuK7tG1ePElNJt9S3UHjD3NDeMqpzzByQJYDkmOLc6D8Ayfb5VL4GmVz6ysS1qCj7FVKvkBS7vB+d+cns8cCGUDTg7aTJ/SX8fj8fcqDEDUAZq41FdU4IR/Q2n3a6eH4ArrK5qTTD19hiF9KDL9FrArCo6flXkxrQKeusgDdb8DPHZIyxPiwLNULaBsFoDEYqsKXmZ4+NpcYSCiihbd9Htar3CQoG0ChrMqvcEf7nV0AVnWIr3cZLtI6e8grS/mwSRLtWc7CgGc9Skw/F7reDcso3OGAFDTj0iyUF0JYWXHPAJfzRochYBs9Ql8WQrgTkHpel0AFPa+Xkslt4+NjX3tUabXtAZCnMSgdtoGyfmITWNId5cj4zui9MlkM5klk5OTiWaksi6TI3UqpQPB4CkcGoqCB+UcIysGyrWahA47gJ+PrSZXKMxNCPGqdnrNdy7A+UrNb/Z5wNZz2oQQf9dym0J4pGDEC4D4SzV6oHfErVnX+eIKxRwnrhI/MsY+ps/roW78zwIDX1NDSLTg2u9recJyhpCwTEsMjixAfLW5HWNv2MyG0h8x+P+ARoCjLaJ0J7c4rnUYQKJEL6rUqZUaNG7DJtcpGdLfHo0tv2yylkSz3EAuyNj+Z6xHWkC3NuszOQcm2pQMUq5GKTilBSxm0LihdkqlUuk58k/PhVBaiitOkhBkvwFGvudNusCUeqKzs7N9jsKW5xmkXIRVXQD8l5UukLSHyu+WuJsohKakz3IFWnUBZMBnGExgTKsDftDkBKZptYNcftfC4Ji0gM80AVzRQomPLu0rtDAoZ4yonvgMtAi/UYeScEDrMCot4JhWJg61LOVzbsNGhXhf7ui6EPHw8+9BORwqlsM+JQQuYYVZXyHUJSPZ4SetpnxEgBUqeITB4/F4/BQrFgmHtKJhuJW0X6xxhrVwf5iUZkcA+IB290okRJFW0b6cFIWb/1Qr+w9MC2A8Hj8CEX2iXA8YhnFXq2g/EAj8kig7zAD+I7j+O9MCKFgIpXvsj6H39PX1nb+Q475s3d3d7cBytzYztKd0/3QxxHO5PSAGdSEkei6T2bzAwFOHEljuaovYyn3O907LonQgJw0RFnZrfvJgYdZ4gYIPhUI/RMHzG1snxnaWXR3OZrOPS0pQmLINrrFzIYIvjv9JfFQ3TsDSt9n6qP8UVoOEeFh78upwNDrSwECFy8DrAm+a5kb4/ipbIkjIg9LSq93sC4XDRyG5axW/OUcMY3A8FvugQU1Rj4iu3B6nqzHmtyGAoHL6aDKRGCLaljmnGaG8j7F16sYCCGMRpHBQps2z1KBwsa8jeKS8F+Xy+ZdV8JLcwW8/Jw77BR2nxBKJxHHcsFHreAFG9Fp7b2+3S+Zc7tPwHEJPT89ikNxrUNgSjQzuQtr7kSNPlHsLiqG/Igrs1kil35iaemMWluB+iatofiqTeRNjvFyT9vbxRGJf3Q8s8QHC4AsOZPIVpHFzDZwgvAQ9DT4aXUbz+YO65vHyF6xEYg1pdKus5INkJLIWd/9TdweSy71TQ3Sodw+g030VW8g0N/g4PzrD7Al51QqHb68EvnZ2ljvGk8n9uiWUpEyF2AKX+aqZvlB0wyfh87fMGBPnL1qmeRs5eXKqaplc09uSyfzZs2f/sWjRIpNSep0mwQFkWyPntbXxcCh0LJ1OZ70EDqJrCwaD90Pwz0HrVzooZKeVTN6BMedc8S+9gRPuAOBdZX6tEcPfHblc7qlUKpV0E3hHR4fp9/s3wAplbm/OnO0q/GplAyzxGVcJpkyW1Z/n/Bk1WdJaBpo4BNfYB4t5Xe7UauQ9xf18K+RkBkxdbmkJOE71EfKuQek6hLoTrjNslQgh081HJBdV6JeTu06YEHLjxSjAfChXoGVVVlqHlKtRckGmuCbRD7ADuGcIZHtNFTdNAsBDEPBT1cjOCwGoprkVbrGxzC/JXG9y+zvMfRdK3cf13L7pAlASkbDcbQqzH4FVXOJNLSg+lhM3cu6i0d8ieiYA9ZmhaHQIgliDz0oI49JZYZa/AGHsENS+H3X82y5Xmd6vyxXj9SD8exl8v19uyZG7UuTGjNLeBLlCLRdp5TplYamOMfnz+WOFCs7j/OJb5EAGggqAwaMAAAAASUVORK5CYII="; + +var img$y = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZE7SwNBFIU/EyXigxSxELFIEcXCoCiIWEkEbaJFEsFXk6x5CHksuxsk2Ao2FoKFaOOr8B9oK9gqCIIiiNj4B3w1EtY72UCCJLPM3o8zcy4zZ8AVzmo5s3UUcnnLiMyF/EvLK37POy58eBhhKq6Z+nx0NkbT8fNIi6oPQdWr+b6Go3M9aWrQ0i48oemGJTwtHN60dMW7wj1aJr4ufCI8bMgBhW+VnnD4TXHa4S/FRiwyAy7V05+u40QdaxkjJzwkHMhli1r1POomXcn8YlRqn8x+TCLMEcJPgiIbZLEISs1LZo19oxXfAgXxaPLXKWGII01GvMOiFqVrUmpK9KR8WUoq9/95mqnxMad7VwjaXm37cwA8+1Des+3fU9sun4H7Ba7zNX9Bcpr8Fn2vpgWOwbsNlzc1LXEAVzvQ+6zHjXhFcst0pVLwcQHdy+C7h45VJ6vqOudPENuSJ7qDwyMYlP3etT9GwWgrP+9tUQAAAAlwSFlzAAALEwAACxMBAJqcGAAACRlJREFUeNrlW1toHFUYnjm7my3rJs3s7DaJ1FoxtMYHS0Wo1fgg6IO9eEH7IJTqS2LVlnoHQRGEgrdijVYxffBWRLFYL7VEBR+s1kLViCAGW6tUsE3c2c092ezsHL9/uklmzs7sJdnZWfFAyXZm9sz5v/9+WVnyeCUSidZcLnctl+U1XJI6ZMO4hDPWgr/LZMYa6BmD86wky0O4Noh7f8iS9KvM+U+MsWPJZPKsl+eTvdg0Foutw587DFnewCTpcqdnDMOQQGDBZ4fnBnDvCDeMg+l0+jgu8boEAEQ3gctdOGg3DrzKC2Cx90kg1QtU9gOMkboAQFGUpTjUw2DLLvCwSarBglSMQX16DF3fMzIykvYLAFmJx7ugq7vxOV7svODcTwDpa3wegJQM8Gz2DOzC2Hhr6xg9ED13rjEQCDTKodAKHGi1xHkHqOwEkWtxO1Bkb82QpCeHNe11ek/NAGhKJC4NGsab+Njp8ogOIvo45++AW18ulEtLly5tBjA3Yp+tAOMmXAq5PPodk+W7YDBPeg4AuH4nz+V6oedRh9tpqEJPNpN5ZXx8PFlNsY9Go/GGhob74C12kclxUIsJSNl2SMMBrwBgMHTP4gCPOLx8Chx4RpblFzVNG/PYrUahPg/AdT4OJkQKDKUk7U1r2sPlqkS5ADTEVJWQ3VJomvkRHGgHxPwPqYarubn5YgDwMhiy2QGEQ2lFuVM6dSpTDQAawPlDeNEG4foMiH80lUr1SD4uVVXvh43Yg/OFhVt9KUW5tRQIpQCQwfn3Rc5D5M8FGNsMcf9eqoMVj8ev1HO5TyERFwpxw0eIF24vpg6BEsHN80C2S9j0FA+Frk8nk79IdbImJyfPhsPhD/FxA+yQOsc9Wb5sSSSiTE9N9VUsAWTt4ePfFYkPhUKdQ0NDg1IdrpaWlmWZmZmjBZEo53dBVd8uGwDy80zX+7FRo1XswflrR4aGTkt1vBA7rETM8K1VHXD2yWAgsBZxwm8Frs0JFApyrMSTwYPO31zvxNOCN/qTBwKbwPU540fuUuf8bSd6mYPodxVEeLD2MHgnitoLVeW1JLTY+0aSyX5kog8KhK6Dx7i3qApQYgPDcRLWI2H189CfjeUeJqVpco2Jl/FOt0TtY6jDzZZLqZyut1tDc7sEIKuzEk8RHgU5lXDCa0lw2L/Y+3aS/lu/jtziMUcVMPN5pLS2mwhvFxLheQVCpfsiBjgDGnbbU1O+g5KsAgComCHk82mK7Uu9xE3kEZzwWhBfSuXgtl+itNliEKMsGOwuBMAwugW56ik3sXE6BJA2D41/vhFPa3BwcAJ2bK/N8HHePWv/2GwNTwgespTSVnJIOgzEzbGS5Rfx88RkXzNzl/kQ8VIYyGusEnCH4Pb6FpLPI9CQq2kTqkE8rbGxMQ0SfkQw+FvmADCETA/Z1YGFcsxNEioFoVrEW/KCA0IRw3Ttslm3Nwxr7d2Ar4wvttjoRAAB4yYlXhI/6+WAQsqWAHJ+EaOmhZDw9C+W+FKGsdbEm99PpUaRE/8gXF7PqGMj6MbRarkuN3Vwc5FeEW9xed/YmC3Laxm1q4TnBqrpv51E3kkSvCY+L92/Cnagg1GvTkClqgCUYxhrQbwTc2EYVzJqVNoAyGbPeBHGVuoivUiq4N3+EiSxhUEMFOtF6th4lciUS5RXGSW11AQJiCEAZEusF2fbVX6B4GU6PTo6Oi5IRJhJ//PFIBa2ujk1Kv2q5HhdT2hqaooKKqAz+H1b0ENdWr+I9xoEoc5JKvAPuUFbiZta1LUk3k3nvQABHL9ICM0HyQ3aKj5mf77GxNeqqAIAVgsS8CejgSTBWXb4wfmF5g4Vrg4BkAFG01iCs7zOL7GvNHeoOA6Q5U5BAvplbN4GpP8W0mEVGeGwX5UcL6JDVVUbsSmlw0FLbnAxozk8GkWz2gYaS/GzjFWtoorA7RutxOPC72bVOO8ejggPb/WLeK/Ka0jytgr//2yuJEZDiDbjwNhNNJPjF/HVdpEIgGLYaKMAwME5AGgC0xxCnF8hcyDJR+JLfb8SwxgMBqkn2GAR8dPDyeQ3cwDQJXMC0+4jdtFAkp/EV8NFtrW10SDVLoH7vVK+XM8s7m+/kC7GaBrLb+IXaxinZ2Z2Cv3OCUPXey1lsvOLZm9p/FRA+XEaOHDb3E0MvUppy6ko28CJxZZDtZ8Qwt99rt1hIPOCZO+jReASXy52IJErXrfHy4kgLaLeIwx0Dmez2edsgFj/Q8EPzd4KtmATjaKVw5VazAaUk0PQUuLxbty8TQgGnqIukZD7FGaN0CuykOstX8wAyWtA7I//hSJHcyKxRtL149ZqF3T/xHA6TTTlXCVg9lkaPDZnb+elIKzncoeL2YN6WYqirAC1hwXipwKMbROJdwNAMqeuGdsuFBPaYCQ/p1G0eiU+2tqagFX+HEQtFwzfDk3THMv9roOS01NTPy+JRJqhI1db0kdV1/VbwuHw4UwmM1xvnGe53Fdg1GU2tTeMffBwu11rBKWqSIqqHhSNCUTq72AgsLlebIKp8yT2Audhuz5NpVK3OYl+URWw0mpOXUtSn6AOFwKEY82qep/vnIe1Nw2eQDy82RepWGxLMeLLkYDzq709rGjae7ABtxb4WsP4BH92UmpZS8LNIAd+vsDVzXKeiC9jXD5QnuNN5aanpz+gwWO8cJ1YZ0P6fE8kEqGs68eJiYmsl4RTbB8Khx/COz+AcbvCgSGk83fjzGWdQ14A8tsQIr8KNbjA4bZGA0k0kyMGHItdlNIiq9sunZ8ALUjV879auR86/0Yl+y4ockMOsErn/C1m8RDCmqGZnPxYypc0nLBAMaexvRuomJHP5xscDRWCHPLzbq6u6gDM2kKavYXffVpy+BGTZeVoMoOGE/L9+QHq0lLmOduro44NNS2obp8vXXdQARPfuaqEmg5TeAuA95Uydl4AYC5EhwqNn9IEpssvyaq+KEqlrI4Sm8WqWtWSFxo/NScwDaML3qLdE8o5P03FDMrnqzHHVFUArHuaQ4g0h2cYGxcNBue/UwGTanj5MlZ9/ni6mL+mzJIGkmgmh8ZSaDIDfxOwBcG8K83gc4p6ddSuoo4NNS1w67jX8cW/7UTXYK9/2wQAAAAASUVORK5CYII="; + +var img$x = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZG9S0JRGMZ/adGX4VBDRIODRYOCGERjGNRiDWrQ16LXezVQu9yrRLQGLQ1BQ9TS19B/UGvQWhAERRDR0j/Q1xJye48KSui5nPv+eM55Xs55DriiOS1vt4cgXyhasdmIb3Fp2df5jpsh+gnTndRscy4+k6Dl+HmkTdWHoOrVel/T0ZvWbQ3auoQnNNMqCk8JRzeKpuJd4QEtm0wLnwgHLDmg8K3SU1V+U5yp8pdiKxGbBpfq6cs0cKqBtayVFx4T9udzJa12HnUTj15YiEsdkjmMTYxZIvhIUWKNHEWCUguSWXNfqOKbZ108mvxNNrHEkSEr3oCoJemqSzVE1+XLsaly/5+nbYyHq909Eeh4dZzPEejch/Ke4/yeOk75DNwvcF2o+9clp8lv0ffqmv8YvNtweVPXUgdwtQODz2bSSlYkt0yXYcDHBfQtQf899KxUs6qtc/4EiS15ojs4PIJR2e9d/QMO/2gR3i+r3wAAAAlwSFlzAAALEwAACxMBAJqcGAAABZ9JREFUeNrlW2tv2zYUJWkpH7YsieUYaICi2P7/XyqwYeiHBvEjTryiqWNx99JixlyREimSsrYRcGVHNqtzeHhfJDnL3JbLJTsej0xyziR85nXNpBDqyuGKrZZwB+6/3cPvwd8EvF+tVlmfj+fotKqqEzAAJRzfqQGs0AQY713fk3DdbrejESBDyUHQapQ7wMQ27Jth3wnJ4A7w3gqZz+fqofBHgo3T6mb61K+vbLfbefNnw1R0gPdSgp7H3Gfk8D2q5HBQdmH/4YP62+XXr2w2mzFelqd+0CYYNoI2rbBZUYSCb2EqPH8cbisAhIQXjpZzlD5/Vpe9o4vr62tFDPbDh08r2XWzsEwJGUMCfvHw8sL2+3201E3iLi8v2cXFhfIWqcC7FBBMgrLU6MbgtVmvs8x7Tah2q3XjJgeA530EhJGAUgcCNv7GKKo9PDyo683NzclWRID3sfLeHU2oBT0zT93hvwk863PdTUTHhxqYKYCfLxadA+UkYH57a1rcqZPgHHluhObeBFyBpZVgaQPC5knLHj3GLQ6oLwGFO56fGglecx6xvDo8hrBKf3gCNVmDh0AXi0U3AZjYYE4emUVO0trrH2F47VYAyt4INTHCgx/8NjESvMHDgH6qyYBibmElQOXzVB5ABsTjv4cqoVos5Fjgq5Osrc+x3W7/FCR3QINoquCNAGmp3kBs/8vQ6QBWNykJNlIRPOQenbIvy/JnahCFkUaLdzk7oXq9Xj+HFlaaEVFM40NXFsMzFLzZlw94bPf393/RnIEbn4WWP3V7mNKGVpccvlamHHkE7gv+Dcvh0AqPVCXLGQkCQ0Py+dVqldQmuH4XAh7b8/NzS+G6QqX+rTnNcIcPGj6csBQtQklIBd6wZ7SIcSIACwzCUuCIaS4l+BrG1OCthIAC1NQ/kphfdtXwApXQqhw1hvEc4DebDbMNq5BUGglr+q7p4FJC7pGnyJTrzx222aaDTQljyL5lCFUtk/p/nr7Q02cYxwDvMoxCEslL6jMzKmFs8NS7qcoyIwo4tgshSZWQ8nuhjXo3pQAaAerlqnORkFP2T09PLUWMtZ452SaoLHChMmcbGgekaFdXV+0pQP0+LRiMCT43CXS6qylA3SAuUY8J3jXnc5BA8wFhc4P8DOBdJKQuqnBL0ie4JRU+x8gPzR2iAyFOAUdmgjGyD80dguMAmwKoYcA0kZaOxyxm+OYOoQ3XBGw+X+A+vL7S8diVnFRFlc4iD3zGnWbC5R7OBX5o7tBLAJV/81nY0kScBrgn51zgU7tIDIC4gxBFAEqBkqA2JAWSbNsfFF3JaXsL9QoxjAXdTgcKf2y24ApnJQgYWi6XvjKQ5gOmTmyMeMGcIl5KuLu7+6lrOgjT/dXt1HgfAj5nVmfrDwnpI+H7jx/f6Hon7jC1Bn5zcBWc5M8wNX7d7XZ/hIBnefcPef+fVVV9BBf65Z2RB/ljgbStAARsMKO9w8TAd/Xfeh4A+qW14kUqXu/uYjm8TjwK5yaBGj9cJXISgO2xf6fnVLbNBZGA09mUvpMAnSY6VoemtmfQiwTEMnPtPHdEYbYFkqlumOwlAQd0PWQP8/yf9XjpeE2pWZ9RL4OziNH7T2+V/d9vlhaxHaHE+mSWo+HS9ty+/SbIOxSxLKrDS2Bl8YHKssQ9OVmBQ2yP4e3bIY2O5/Q671CkkL2Otg4QSSIRGG3RgCO2YUqLWd0LgOeM+Zwh8iKhSD7nYVRKSKXVrtNmhGwBiK/MdfY20OhwFnhoKpnBM0fopqnH6ZqDPk2m1+pwdFFFvDl3pIIXQ96RFreThOiDk/pom8chpmRNz//AqWY9OJns6CwSoXZgdhx4jHdwUk2HwBOj6eXdG0E2x2mTkNGAxtdjhpPk2QMa05ApQnAE8SQogmqqz/q9aK7mvRwnxs32N2D2E/TuYxaGAAAAAElFTkSuQmCC"; + +var img$w = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZE7SwNBFIU/YyTBBykUEbHYwoiFAVEQS4mgjVrECEZtkk02EbKbZTdBgq1gYyFYiDa+Cv+BtoKtgiAogoiNf8BXI2G9YwIJorPM3o8zcy4zZ8A3k9dN1z8MplV0YtNRbTGxpAVe8NNNB0HCSd21Z+en4vw7Pu9oUvU2onr9v+/P0ZbOuDo0BYXHdNspCk8Iz6wVbcVbwl16LpkWPhQecuSAwldKT1X5WXG2yu+KnXhsEnyqp5Zt4FQD6znHFB4U7jfzJb12HnWT9oy1MC+1V2YfLjGmiaKRosQqeYpEpFqS2d++4R/fHAXx6PK3KeOII0tOvEOilqRrRqoheka+PGWV++88XWN0pNq9PQotT573FobADlS2Pe/ryPMqx9D8CBdW3V+QnMY/RN+ua/0HENqAs8u6ltqF803oebCTTvJHapbpMwx4PYWOBHTeQOtyNavaOif3EF+XJ7qGvX0YkP2hlW/cxWf6XLNyeQAAAAlwSFlzAAALEwAACxMBAJqcGAAAAJpJREFUeNrt1TESxCAIBdCw97+z2+1slQmgNHmv9guS0VwXAAAAAADAS8TDdauYq2Qna6WbyeSz2claWza92yObnaz1aACrcZXW4LVd3SsfGw7/v9fpw++oFZUBRGNIcfhtyGajFUg2ls1O1fqt/TRe3mhkd/+uy31+DjeWycVwD1sGMPH1T+55O4AoNlbJTdYCAAAAAAAAXugLTOAcJH5aTj8AAAAASUVORK5CYII="; + +var img$v = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABbmlDQ1BpY2MAACiRdZE7SwNBFIW/JEp8IqiFiEWKKAoKoiCWEkEbtYgRfDW76yYRsuuyu0GCrWBjIViINr4K/4G2gq2CICiCiI1/wFcjYb1jhATRWWbvx5k5l5kzEJ7IGZZX1Q+W7bvJ8URsdm4+Fn0mQjO19BDVDM+ZnB5L8e/4uCWk6k2f6vX/vj9H/ZLpGRCqER4yHNcXHhGeWPUdxZvCrUZWWxI+EO515YDCl0rXS/ykOFPiN8VuKjkKYdUzlqlgvYKNrGsJdwvHrVze+DmPukmDac9MS22X2YFHknESxNDJs0wOnz6ptmT2t6//2zfFingM+TsUcMWRISveXlHz0tWUmhbdlC9HQeX+O08vPThQ6t6QgOrHIHjthOg2FLeC4PMwCIpHEHmAc7vsX5Gcht9F3ypr8X1oWofTi7Km78DZBrTdO5qrfUsRmeF0Gl5OoHEOWq6hbqGU1c86x3eQWpMnuoLdPeiS/U2LX8/hZ/QGsUVrAAAACXBIWXMAAAsTAAALEwEAmpwYAAABDklEQVR42u2aQRKDIAxFSacnqNz/hNgjNF221qkIKAJ5f+eMjPwHiZmAc8i2pPL3tLV5SYPmq87tRgiUr1TXnsWY+ZVvQsB6CCCESILUAdQBhmUewP2gokEzxtUasxnahAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYUqwt7rz3i+eXLjvMz3m+1MBjmj6rKesueQiBHQAAAPxX7HR41KMxTocBAAAAAOBIAJKRmWuNKSuFC36pLY3J3gEj3BrTFAAWLhJLag7QUVd/a8X17Ni7yLyUJEHtBIRmx8OACTDqVQaO/10+5Yxt1YPx3MSmoxhPejHWGG2qtv9qjMYaorvqgF/zPannuVfTG32vK+uRIdIIAAAAAElFTkSuQmCC"; + +var img$u = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABbmlDQ1BpY2MAACiRdZG9S0JRGMZ/amGY4VBDRIODhYRCFERjGORiDWqQ1aLXr8CPy71KSGvQ0iA0RC19Df0HtQatBUFQBBEt/QN9LSG392RghJ7Lue+P55zn5ZzngD1S0Ipm1zgUSxUjGg55lxLLXucLDly4GcOf1Ex9PjYXp+P4vMOm6m1Q9eq8r+3oTWdMDWw9wlOablSEZ4Qj6xVd8bbwgJZPpoUPhQOGHFD4SumpJj8rzjX5XbERj86CXfX05v5w6g9reaMo7Bf2FQtV7fc86ibuTGkxJnVI5jAmUcKE8JKiyhoFKgSlliSz9r7xH98CZfFo8tepYYgjR168AVGr0jUjNSt6Rr4CNZX7/zzN7OREs7s7BN1PlvU2As4daNQt6+vIshrH4HiEi1LLX5acpj9Er7c03wF4NuHssqWlduF8CwYf9KSR/JEcMu3ZLLyeQl8C+m/AtdLM6nedk3uIb8gTXcPePozKfs/qNw5zaBHJcPVKAAAACXBIWXMAAAsTAAALEwEAmpwYAAADIUlEQVR42u1bPY7UMBS2PZYQotmdTMMhqFhKGsR23IN6F1pEg7bj5xZUnICSluEAXIBmnEkFQsomPId45bGcxEnsTJ4nT7I0cX7s73u/diaUNMhms7H2F2VJ+kgqhK3b9hBqu3CdJM5jMUobz+12O2s/dwWOXRQukwgeO/AuIhg5caFd2m/ynZHiHAN8aLsNG58Y+KSiMLQRwWwnYwDvaiEnEQOkQp3T4Ny0PyY75be3JNvvD7CZz+MhJ+CDUFvhVRQFYYw1Fj7qHnlNl3DMpt23KrUGQUyAlcZdNOsqR7EAWd/rawTz2GEtMWitYLMa7sOMhpIwh2egcQEzGPsAj4oAPZv4Ao9yMdQGXsULmSajJMAFfN8swWIDH6ULhAKPgoCQ4FEGQZ/gnSrBOe4N+AKP0gJ8gkdHgG/wzouhMXsCvlwoBHg0FhAKPAoCQoJHnQYXAhwspnRYFPEYtdrHbRYXWAhYCFgIWAhYCDhhGV0H5Hn+iDF2Qyh9UedgGmqy6yT5/xanLL+lafpMDu/DAkqjmYNWr5NUU+/aVaOUfqnBi4NJhgIvhdKnSZK8HPioA7zjXYCxz/WvxDpZ3+DvOKBfZxED9kK8BZN87zJpX+DlsGB9PychQNbV8rW0anJzRG/VNWn6OgQJlvv3MIfHMKf17LKAbxJs9wH456D5H7NNgxUJhHwYS0KD5i98gw9SB4B5vhpDgpbq/mqavwTwWzSFUE0C6UuCOl8UxR8I8/e0gBcEfNBKUBZEBSEfXUnQ+6Gwul9r/sJnwAtSCXZsmV/nUDwBy1e1Zn8BuIct12fQztTvkJqfbC2QCXGtLKEDPKnBZ7Xmz6NZDOkk2ERahpHqtmQimWw1KEkAJ/9kr6Yry8hgFfUkNHi9qKua2RFSoGy+aiIBRr4UQnyPfj9AkmA3kOnBH21DRKZIsIR34Pu/pwx4gwg4O/c/N5k6V5S+4avVAzjcHvODLdtncyUEortgoP/fHrtIbLNwgTkJ07XdxlSM2pfYedcNNoKwAzfSb3+tH+sv9q6FjosoxS5fjg7xf8wWYLo0HeI7GAloimX/ANBjieJDfrkhAAAAAElFTkSuQmCC"; + +var img$t = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABcWlDQ1BpY2MAACiRdZG9S8NQFMVPW8Wi1Q46SHHIUMWhhaIgjlLBLtWhrWDVJXlN2kKShpcUKa6Ci0PBQXTxa/A/0FVwVRAERRBx8R/wa5ES72sKLdLe8PJ+nHfP5eUE8Kd1Zth9CcAwHZ5JJaW1/Lo08A4fRhBEHBGZ2dZydimHnvXzSN1UD3Exq3df1xoqqDYDfEHiOWZxh3iBOL3lWIL3iMdYSS4QnxDHOF2Q+Fboisdvgosefwnmucwi4BczpWIHKx3MStwgniaOGnqVte4jviSkmqtZ2iO0JmAjgxSSkKCgijJ0OJRLGSZl1t2XaPpWUCEPo7eFGjg5iiiRN0ZqlaaqtGukq/ToqInc/+dpa7Mz3vRQEuh/dd3PSWBgH2jUXff31HUbZ0DgBbg22/4K5TT/TXq9rUWPgfAOcHnT1pQD4GoXGH+2ZC43pQAtv6YBHxfAcB4YvQcGN7ysWuc4fwJy2/SL7oDDI2CK+sObf/JNaAQfxWcoAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB30lEQVR42u2bzXKDIBCAw+ql6cnqpQ/Q93+f9gF60aan9GKwmkqHsXZA5Wd3YWcyySFO+D4WCLKKU+R4qush5u/DKfHIAlIXIFIDXs45eQhkAYlHiaUhTdMMcvgZniDcTE397Xb9vFweKQgoFfwU+ue1kFJ+AcDDf6J+RQKcqWRAv+cikyhqc4Ax71WPT73Pbg746Lpd/0uO7iVIrwIuNlJkBIyrhJddJBkBbdt62UIDp7Qf5xExL5PvLAXYwM+rxDM7AbbwLIeAL3gSAnzCoxfgGx61gBDwaAWEgkcpICQ8OgGh4VEJiAGPRkAseBQCPMF3JAQo+LV7e3vh9esGKd9M3xeppT2Kk6GYY/5PBiwb47sBmOCDZwA2eCsBVVW9Tg0fX63TsadNfLHgrQQIgBebHtza8+pQIyb81iFQc0n7YHMAdnivAijAexNABd6LAErwzgVQg3cqgCK8MwFU4Z0IoAx/WAB1+EMCOMBvEqAfOXOB3yRAHTlzgne6DOrwy3IW9gKWPa+Xs7AXQDHt9ThcJ7h2p8eiglPMdYF85oCpfvf+ble+OpDMAFNx8o7f7tELGHv2WhbF2SQGisJYv7soh+9JZICp3p565EdmsoDEQ8R+dpfSwUgeAlkAw/gGgdL3j4c6UpkAAAAASUVORK5CYII="; + +var img$s = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABcWlDQ1BpY2MAACiRdZG9S8NQFMVPW8Wi1Q46SHHIUMWhhaIgjlLBLtWhrWDVJXlN2kKShpcUKa6Ci0PBQXTxa/A/0FVwVRAERRBx8R/wa5ES72sKLdLe8PJ+nHfP5eUE8Kd1Zth9CcAwHZ5JJaW1/Lo08A4fRhBEHBGZ2dZydimHnvXzSN1UD3Exq3df1xoqqDYDfEHiOWZxh3iBOL3lWIL3iMdYSS4QnxDHOF2Q+Fboisdvgosefwnmucwi4BczpWIHKx3MStwgniaOGnqVte4jviSkmqtZ2iO0JmAjgxSSkKCgijJ0OJRLGSZl1t2XaPpWUCEPo7eFGjg5iiiRN0ZqlaaqtGukq/ToqInc/+dpa7Mz3vRQEuh/dd3PSWBgH2jUXff31HUbZ0DgBbg22/4K5TT/TXq9rUWPgfAOcHnT1pQD4GoXGH+2ZC43pQAtv6YBHxfAcB4YvQcGN7ysWuc4fwJy2/SL7oDDI2CK+sObf/JNaAQfxWcoAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB+0lEQVR42u2bMW/EIAyFA7qla5Ol///HdUm6dguFKlQuBwnh7ADKs5TlTsrxPp6NAZ16H0czCMTXsijO90mNUw83DwC4OwAV5hZ37rYWoV6kAAAAAAAAAAAAAAAAAAAAAADcMh6CO63F7iwnkR2cUmqe57YcEIq3zyg4cWaapnYARM7rRjtLYupXY9ggaAHxzqKDtSgbAXdIkwBqqgK4QryP8J3OBe6xLjBVAFwpnjoh9rmDUJoOuhfxqXTwTiitCbon8WE6ROrCaQi6N/GxdFjX9XtzwWkIukS8/cHPmuKfnKD1W6kTdMnM2x/8qC0+VhNIPciGoEts7+nb75ro53cm4nCJ3L0ZkrqRvWSXRwokBZR9M9SzeJoOR82SziHYe5C6kA/A2cZB8E/PsXfh+zgqLt4+DgIl2cotsivEdizJlD0aZ84ymOy/G5nd5FhyJukQwHby8td60jW3hULpxP8Wu605O+vQrEaIQqDtZ20nePG+OStJz+xW+MkJpP2s4QQqvmTmizZDUSdsg7jSCVzii7bDHkK4PF5VEzjFFx+IOAip/lsSArf4YgCxZkl6iZQQ/zKAVJ/AnQ5S4lkA0Jog3Msv3OK5HBBdHZjj300TZxvOdjcoCYHrjlHMAT0HAAAAAAAAAAAAAAAAAAAAANwzFP47jBQAgFvHDyRnPtj60cBDAAAAAElFTkSuQmCC"; + +var img$r = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZE7SwNBFIW/JIpioim0ELHYIgaLCKIglhJBG7WIEYzabDabRNjEZTdBgq1gYyFYiDa+Cv+BtoKtgiAogoiNf8BXI2G9Y4SImFlm78eZOZeZM+CfsoyC2zQIhWLJSUzGtfnUgtbyTIAQHQSJ6oZrT89OJGk4Pm7xqXozoHo13vfvCGZM1wBfq/CIYTsl4THhqdWSrXhTuMvI6xnhA+GYIwcUvlR6usZPinM1flPsJBPj4Fc9tdwvTv9iI+8UhPuFIwWrbPycR90kZBbnZqX2yOzFJcEkcTTSlFnGosSA1KJk9r9v8Ns3w4p4DPnbVHDEkSMv3pioZelqSs2KbspnUVG5/83TzQ4P1bqH4tD86HmvfdCyDdUtz/s89LzqEQQe4LxY969ITqPvom/Vtcg+hNfh9KKupXfgbAO6723d0b+lgEx/NgsvJ9Cegs5raFusZfWzzvEdJNfkia5gdw+isj+89AXPlWf0rTeiAwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAeNJREFUeNrlm2uOwjAMhDsWJ4De/4bsEfD+WGm3QqTNw54460hIBbWNP2ec2G3Alq/p4RhIDP/jgczwmRyghd9NQ0AbzkUEeAtD1MBAzIIf6VwdjAUbvqdTJUgWLPjWztQAQAlO0JZ7wgAeTnMIvOFrOlFSzFr0oz3Xw/qGrNi1shWB4Hv7HrJVAiYvICjm9EQNkjJf2WGiUgSFv7LHLERlW6+Zzk8IPPotyVO3nRKkYhuBG7JTiDl+yLpBssV8rQMQHN5UQp6TX/TQgqw8ehY2SmD5U5psydst0JJVM9urgVo1ogKmld+SGT6CA6bCz3bAdPiSAzQL/CwFWD/4HHYAFpU9VlPACLyyQ4CVx09Pu+XEEA0MD28FRBp5ZSiAqYJReDDmgH+zzrc6wEIFVvCUx/S1D0SUHK+0dxRiMLIMeHoq3PoqWo3A6XPHaP6NzX/vkOvuMa809JNj0OFc9xXq1jByq+wSc00pV9knWM0g+77/fjkeTzAOMxKlCApgQzfPAbUZngaGLucB98fDKr3F26ck8VD1AIzga64L+cpdnOCXaZIZ/swBKeBLDkgD/8kBqeDfHZAO/uiAlPBX9TxKNcJL/y75ej5nFk5uq0CajVKXD0UrKsTlQ+AoV9afF8PwfwNGBXNgWGrhCQAAAABJRU5ErkJggg=="; + +var img$q = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABcWlDQ1BpY2MAACiRdZE9S8NQFIbfpkpFqx3qIMUhQxWHFoqCOEoFu1SHtoJVl+Q2aYQkDUmKFFfBxaHgILr4NfgPdBVcFQRBEURc/AN+LVLiuU2hRdoTbs7De897uPdcQMjqzHD6UoBhunYukxZXi2ti6B0BxDACAVGJOdZSfrGAnvHzSNUUD0neq3dd1xgqKQ4DAgPEs8yyXeJ54uyWa3HeIx5lmlQiPiFO2HRA4luuyz6/cS77/MXZLuQWAIH3FMsdLHcw02yDeIo4buhV1joPv0lYMVfylGO0xuEghwzSECGjik3ocJGkbNLMuvtSTd8yKuRh9LdQg02OMjTyJkitUleFskq6Qp+OGp/7/3k66sy03z2cBvpfPe9zAgjtA4265/2eel7jDAi+ANdm21+hOc19k15va/FjILIDXN60NfkAuNoFxp4tyZaaUpCWoKrAxwUwXASi98Dguj+r1j7On4DCNj3RHXB4BExSfWTjD603Z+Sp2ztrAAAACXBIWXMAAAsTAAALEwEAmpwYAAADGklEQVR42uVbC47jIAytESeY6f1P2NkjLCOqInmoP5g4BChSpLZJAT8/G9sQuDHtfr+Tv/9P6WZp/35+tP6lDsEyXgBg7z0eD3qAVsE9AWgU/s8cOQG+vr+bAOCAiK2Cn9CS4TnwGrTIWYAItw9voGmfo56DJlI1DnD38jx75qGxOvcZRwuuCV++V888zaCmLyUkvlc+S0BE6uZBtBMDKHjYbvnMzVG6Rz0bvbSaByWo+0frR0GQWCSZicSE0Kv93Fm5mAl10V/4PSkrSGpRkgrAUXoatWbq8yVA8ujfFQBOg56UbxXQCoIXACytvUHwBjkepffL+Q0PYGqQseaxw5WWyScDcmyPr6uEYOzdnT3YcTcxwMsBtsTlXv1aVoJwpv0bNH16tDl8FThTmwygXeYSBtn61YAmLn6YlgFW0Bg/UgueatMYWQ+AWRiFQZjSBOql6kwneWlF6MyaA8E+6EqHtUleEQUeMD2ofcJH1QRPS4cno7tp/NjoMGbSIljpL4EfPo3ybwzAOzd5aRC0DSOTllEgBEPykBSAlmzBkjkhILyWJLb2Vy7qP54heW89oGu/rgiEKskiRdGETyurBUr7L08L0sA9FdhpTYBaZopmpMKjBwjO+5KiuVD9xVYPSuzXTRdAtdQRc90TnyMIBxBetuHib+jQxjYgPNnQ68m3igOsjm0nEALl4Q2BzvIgRC3Qwaewciu5A9pzr4sM65nAQRYszYioxPzqQUXsDzJbOMZMDwAX6GQB6vM522WDStKzdYt1HlCzQNrBXZEROAxuDYS2YUGtrAwGmw1+SmsNhdMm2n87Wxha1/PdvH/xa8GQg69eEL3ufMBszg+zPBjD2jRwgmfavv7CxC7rvqbcgA89E4cKYQNfkCTlDt0XmGDZezNt1QmuGBgJwvNvjeE/t5Siy3ncq/f9LcJTrA1Wp7GAQ2SFJ0+ItGx5C0XQNJPmhYIuiG+Otm5P9QzQypwjpmSlPR4TNDoTr6iRA40+ak/l95QD1+RaemdIE96UDqMDCUuBYBW+lhM0O1VC4nQl/SkW1MJrcvwCJhH28gf87HUAAAAASUVORK5CYII="; + +var img$p = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZE7SwNBFIU/o6JoJIIWIhZbqFhEEAWxlAimUYsYwahNsskmwm6y7CZIsBVsLAIWoo2vwn+grWCrIAiKIGLjH/DVSFjvGCFBkllm78eZOZeZM+CbM3XLbRkDK5t3IuGQthxb0dpeaaEbP5ME4rprzy/ORmk4vu5pUvVuVPVqvK/u6EymXB2a2oUnddvJC08Lz23kbcU7wr16Jp4UPhIOOnJA4WulJyr8ojhd4Q/FTjQyAz7VU0vXcKKG9YxjCY8ID1pmQf87j7qJP5VdWpTaL3MAlwhhQmgkKLCOSZ5RqVnJrL5v7Ne3QE48uvxtijjiSJMRb1DUgnRNSTVET8lnUlS5/8/TNSbGK939IWh99rz3IWjbhXLJ876PPa98As1PcJmt+nOS09Sn6KWqNngIgS04v6pqiT242Ia+RzvuxH+lZpk+w4C3M+iKQc8tdKxWsvpb5/QBopvyRDewfwDDsj+w9gMBwWgLeGpB4gAAAAlwSFlzAAALEwAACxMBAJqcGAAABX1JREFUeNrlW21P4zgQtt0EcRwC2lJpkU6n+/+/aT+cTvthEdBS6B3Q0vhmjF2ZiZ3YiZ3SrrXdpKR188w88+qYs8xjNpux7XbLJOdMwnteVUwKoY4cjjgqCVfg+u4afg7+JuD8/v4+6/3xHJNOJpMPYABKeD5TAVhhBGCd+z4n4bhYLLrcjmzCylOCVlpuANN34NwM5w4XhmzD21sA4/FY3RT+kmDDjEqbT/X+zpbLZYwAapiL3jaktc1DNIfnyJLNRvmF1bdv6m/nP3+y0WjEeFl+zIM+wfIRdBiGjYoixMSlQyg8mQD8qCX8k0pbXi19/64OK88Ul5eXSjA4D09rVjshJBcAzrx5e2Or1ar3XLbgzs/P2cnJiYoWHRygVwhFKpsUGMbgNX94yEIoI1ATVisdJjuCT+cDFNVBAPNmZ5Rs3N3dqePV1dWHr4gDz2lY5Oz4hozJefivDJ61hW6T0R0y+PF02qhkrwDG19exHvdLap63KNIpgAvwtBI87bHQHiPGNSo0NAoUVuZ2DDaP4fLdEzGEk/pH6PAQ6HQ6bRYAFjZYkx+jtzdfwvTazwCkveX4MMOjXzgk8KDQPyuiUKwtnAJQ9TylBwhj2SHDmziolgu8/i2n5heLxT+CRDJ0iLZSdwKQju4N7xEGrxP7EgDqBA+1R+NNlmX5O3WIwiqjxaeanYj6oUNhY7SPksbzFGww4O25QsDjuL29/ZfWDNx6PzL0p/U2lrTr9Tpa6y4DfXl5Sab5387O1CsE/C6sg8Y/2T4w+/T0lL2+vnoyQZBQl3re18HtygIX7XHEgMfx/PxcY7jJc9T/FbF1KWVnjWE/QDh8R6wQUoH3+jMtEIENBuFocPQZPiaEOsbU4J0CAQag6YstyfllUw8vkgm1zpF2jPsAP5/PmUutQlJqJKwBfObgY0JuzVNkKvRLlne4zMHFhCFoX3OEqpdJ43+GHkCbYxwCvM8xCkkoj4sWQzFhaPA0uqnOMiMM2GZshDgc46Cap9FNMYD21s1y1QBCGJz2T09PNUbsq+3TqZ7PMQSlBS5U5hw+mzfgM5bS7OLiom4CNO7ThsGQ4HP3E6i5KxOgYRCXqIcE77P5HEKg9YBwhUG+B/C+BdXUTRXuKPoEd5TC+9B819qhdyLEKeCEXeFY2sfWDtF5gIsB1DFgmZiiE9w1wwutHWIHrgm4Yr7AH2xrHQ/dyUnVVGls8sB7fNJM+MLDvsAH1A7dBEDpr98LV5mIZoDP5OwLfJNj7CIETIC4RyBKAEgFKgT1QFKkkF033LuTQ+bE9/iKcYwFfZwOGP6oGSa8nSCQ0Gw2C6WBdN1wqsLGzGnPjSYSwoSbm5uzJnMQdvir6qXxKgZ8zqrOw65WIbyu1//R9U58wtSZ+I1hMk7qZzCNv5bL5d9fvapz+orJ5A8IoT8+OXmgPzZI6wxAwJZkTHQ4VPCKIfP5DxrhNqTj9ekqtsOrSJv/quA9yYBaJfIKAMdj+4LoQYJHc7ap7xWAKRM9q0MHC37ke/Lcm4XVv3CYtNcK7bLUr6KCBd71+vJDbehoKomP1uGF9gQ8YPmvAJ76AEnOg8AjxdpolinJsU208yhaNN2qebV5Cbws3lBZlvhMTlbgkNtjervbpJFKADxACP5HznXE2EAmiYLAbIsmHH0HlrRY1b0BeM5Ysj1EBQHY3+ZBKyWU0uqpU60hVwISSnNTveVyOoUDaJLwZmvoSvfjTM/B7CYza3WoXWQR1/uOVPJi0Tunx+URoc/5WbO1LWATU9LMDu0/hanxiPjfqAgUhHoCs2HDY4piBs0hYMdoEgG48oLw7Evv8e0tDA0aX48ZdpJnT2hsR6YEghrEnaAISnefzbnQR/taxx3jweN/nwXieSq4/nsAAAAASUVORK5CYII="; + +var img$o = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZG9S0JRGMZ/adGX4VBDRIODRYOCGERjGNRiDWrQ16LXezVQu9yrRLQGLQ1BQ9TS19B/UGvQWhAERRDR0j/Q1xJye48KSui5nPv+eM55Xs55DriiOS1vt4cgXyhasdmIb3Fp2df5jpsh+gnTndRscy4+k6Dl+HmkTdWHoOrVel/T0ZvWbQ3auoQnNNMqCk8JRzeKpuJd4QEtm0wLnwgHLDmg8K3SU1V+U5yp8pdiKxGbBpfq6cs0cKqBtayVFx4T9udzJa12HnUTj15YiEsdkjmMTYxZIvhIUWKNHEWCUguSWXNfqOKbZ108mvxNNrHEkSEr3oCoJemqSzVE1+XLsaly/5+nbYyHq909Eeh4dZzPEejch/Ke4/yeOk75DNwvcF2o+9clp8lv0ffqmv8YvNtweVPXUgdwtQODz2bSSlYkt0yXYcDHBfQtQf899KxUs6qtc/4EiS15ojs4PIJR2e9d/QMO/2gR3i+r3wAAAAlwSFlzAAALEwAACxMBAJqcGAAAAvVJREFUeNrtW01y0zAYtRQPadzpkEQ5AwcoXcCGHSdgxTFaTtA9tGy5BxumnemCbXoD9mwsJ6sYZlqLT0EeUiNZ/pHj2P40o3HGcWS99733SXJk4hnKYrHQnk+E2B4jzr1DKXPGtkdKiPGaMAy150c64EEQGBsS6hjHca1Ow31ePhuPf0yOjye/4viuTlsT1V+SQ4DEJOtms3lyntgi3oQCIGIrOEx3z0F7pEkFmBRB9y1XxthZFrwsM8au27APsUXf5J2q4EE/NzoClL0+rzg/d3U/m6oltlHqD92XWb/U9TwAXMLHoyRJfoJfTzTReDUOgueQE765uKfsv6ymnCa/G+lYchn1FDzkjlsJXiWrkxxJvnZJginA6fnGc4BMeAB+qWS/zk2woAyVmM6njF256oMMqCmoJKsAl9FXkV9W/X3ieddrzi+qev3h8dFbr1a519IijetqgchHKXiIbGwb7nTnpRKgHVGaOBiqZaXULvBGLCAjL0e2v6ld/IaOTIqM9abvgYRPRQCntUyhTYCHTtz8MxkZl5noGK67sJFQtVDH4E+V7Gd1ZnlGEubzj3X7mFULrSMfDfjborKuRAIhH1yQ4FwBKuHd1418GyRQB7J/kQXuAryNBFg7XB4EAUKIt02BN7TH1azpvea6dEK1PwI451+Ahe9Ngde0y+B+X4H4dzrwW1C0OCzfQd8eoih6s4+la84k6jCGwS4WJGDoBFhzgOtnA6gAJKBjFjA9cOiLNdACSAAS0K+yOy0WBRZFfh+jWmZtgBZAApAAJAAJQAKQgGGvBrN/Bz158Cg3IO3+Y3RI2+MqFoEKQAJKECAlL/ffpbXoBoku5YDWFyzpRsfBWCCbSNtMrJgDkAAkAAlAAoa+FhhWxDMvVfhl3rJACyABAyRgOpv1mgD5vsB/+2PDMOxlYtBh9VvqiKchvR0L6KKtY6qP0ZfYfdsPum4HWzBJlajX2Va/74mOqaSBHfwwWMn/XVZA1tKkine6SIApl/0BVV9uhgTVncEAAAAASUVORK5CYII="; + +var img$n = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABcWlDQ1BpY2MAACiRdZG9S8NQFMVPW8Wi1Q46SHHIUMWhhaIgjlLBLtWhrWDVJXlN2kKShpcUKa6Ci0PBQXTxa/A/0FVwVRAERRBx8R/wa5ES72sKLdLe8PJ+nHfP5eUE8Kd1Zth9CcAwHZ5JJaW1/Lo08A4fRhBEHBGZ2dZydimHnvXzSN1UD3Exq3df1xoqqDYDfEHiOWZxh3iBOL3lWIL3iMdYSS4QnxDHOF2Q+Fboisdvgosefwnmucwi4BczpWIHKx3MStwgniaOGnqVte4jviSkmqtZ2iO0JmAjgxSSkKCgijJ0OJRLGSZl1t2XaPpWUCEPo7eFGjg5iiiRN0ZqlaaqtGukq/ToqInc/+dpa7Mz3vRQEuh/dd3PSWBgH2jUXff31HUbZ0DgBbg22/4K5TT/TXq9rUWPgfAOcHnT1pQD4GoXGH+2ZC43pQAtv6YBHxfAcB4YvQcGN7ysWuc4fwJy2/SL7oDDI2CK+sObf/JNaAQfxWcoAAAACXBIWXMAAAsTAAALEwEAmpwYAAAIkklEQVR42uVbWYwTZRz/vm96YOku207r7hK8IgHXBw3GBI/VxEQfBFGM8mBCxBdWEAheaHwwJiYknhFX0YgPXsR4EFFBsmpijAKSeGBMDBtBNJggu3baLnt0u53O5+8/duvM19lDaJd2/L+0OzM7M//79z/KWY0pmUy2FYvFqyXnl0rGOrhlXSCFaMXn2VyIEF1jSVlgnPfjWB/O/cYZO8Sl/FEIsT+VSv1Zy/fjtbhpPB5fjI/bLc6XCMYu9rrGsiwGBiu+e1zXi3N7pGXtyGQyB3BI1qUAwHQztLwaL9qFF15QC8Hi3ochqW2QyqsQxkBdCCAWi83BSz0AtWyEDpvZDBCsYhDu022Z5rMDAwOZMyUAHkskVsNXN+N7YrL3heZ+hJC+wvdeWEmvLBSOIS4MDrW1DdIF0RMnmjRNa+LB4Ll4oYVMyg5w2QkmF+G0Nsm9DYuxR7OG8Qo9Z8YE0JxMXhiwrNfxtXOCS0ww0SOlfAva+vxUtTRnzpwWCOYG3GclhHEjDgUnuPQbwfkqBMzDNRcAtH6HLBa3wc+jHqczcIXuQj7/4tDQUKqaZh+NRhOhUOgeZIuNFHI83GIYVrYG1rC9VgIQCHRP4gUe9Hh4Dhp4gnP+nGEYgzVOq1G4z71InY9ACZGKQMnYloxhPDBdl5iuAEJxXSfJrqgMzXIPXmg9zPw3NoPU0tJyHgTwAhSyzEMIOzOx2B3syJF8NQQQguZ34kFLlONjYH5TOp3uZmeQdF1fhxjxLN4vrJzqScdiy6cSwlQC4ND8u6rmYfInNCGWwdy/Y3VAiUTiMrNY3AWLmKvghg+BF26bzB20KcDN05DsauWmR2QweF0mlfqZ1QmNjIz8GQ6HP8DXJYhDell7nF80KxKJjeZyPf/ZAijaI8e/rTIfDAY7+/v7+1gdUmtr69n5sbGvK5ColKvgqm9OWwCU54VpHsSNmpxmD81fPdDff5TVMQE7nA/MsM/pDnj3kYCmLQJO+KUitXkJhUCOk3kKePD5m+udeSJko9+lpt0ErZeDH6VLU8o3vfjVPEy/C2axTjGh+2FCO1mDUH5k5EQ4EjHAx1KHqc+LRCJ/5XK5byd0ASpsEDgOI3oknXkezC9lDUjg5yO4w82OQ+miac53QnO3SaCqczJPCI9ADmtc2kD+70xsqC0e8owBdj2PktZ1EvB2phFeNQkY4Bh42OwuTeV6KrIqBEDNDKWezxC2Zw1OSNvPU9nsCIhREQh0VQrAsroUPN1d68JmJqivr28YcWyLK/BJ2TUe/3i5h8f5Acc1hbF8fm61S9ozRU1NTXowFDpOdY1D4Z1wkX3jFnC7kvZ6/MI80eDgoAGG9ygBf0XZBSyl0kN1tZ35jBDPtitNDDu1c7tvb1nO3ruFXJk43WZjvRFlOUgh7QJ/Up4jaGihFDwH/ca8jYDS6ZOoib9XDl8paGKj+MbXzKcEf9/rUjbniwSNq5Trev0qAFj3ISUOdAia1SlS8a0AVOUiMJ4vaFDpEkChcMy3FiDlHwosbg3ADGLMMZikiY1nFNV12UjMpg2jotlDIzWhaU4LiAMai1nOi8bHVX6kkydPDikWERbsf04CZuHqm9Og0q/MNjc3R5UgaAbg/wR6yiMmmtLiIzUdn2o4bbv7nOQCf1EadLW4aUTtVwuAxs9RGj59lAZdHR97Pu9fASxULOB3QQtJSrLs8HHM61AE0itoG0tJltf4lXuU/Z2KBRzkiUSiHYjouFIO66gIs35iXtf1JiA5KocDjtrgPEF7eLSK5owNtJbiQxh8g5N5HPjV7hqX0sMe5eKVvhMA5yuVvz8plci2KexwBQchbqSdHB8BoLhzTFYSwI6yAGgD015C/JeC9kKSTygQCKxljo4wTPxoNpXaWxYAHbI3MN05YiMtJDU68+3t7YRyNyra38ZKK7fCkf5epXLRWQHTNlajC2B0bGyDMu8ctkyzrOxycTw6Opo/a/bs2fCVax0NgyvC4fDb+Xy+IVNiPB6fh4D+HgBPyIF0t2Sz2V3llOcCCqb5DHPP0SJIiS80cOTvVhY6s4VC4SnnNa4FCWh6NByJDLoiJucLIpFISl0sqHcqLXpsUsDAwwB4Xyq1T2XVGNd1ipBXOv4xD0leBdD0QyMw35JMXspM84Cz2wXf/zabyRBPRRezXpCZFo/t3dt/rSBsFou7aQGp7jUfi50LbncrzOc0Ie5UmZ9IAMzeuhZijdJMaAdA+pRW0eqV+WhbWxK57VMwNU+p+9cbhuHZ7p9wUXI0l/tpViTSAh+5wlE+6qZp3oLMsLveMgNpXhSLX0BRF7nc3rK2AuhtnrBHMFUXKabrO3DRre6K2Toe0LRl9RITbJ8ns1c0j9i1K51O3+pl+pO6gJNXe+uasR7FHeZCCPtbdP2Mw2WK9nbAU5i3GPssHY+vmIz56VjAPzR/fjhmGO8gBiyvyLWW9TE+NlBpOeMgB3letc6y5on5aazLa9N6WjpdBFJ8nxaP8cDFSltpIdDW3cAKVHX9MDw8XKg1tg+Gw/fjme8juF3ioRDy+bvwztN6D34Kkr8TEPkluMFsj9MGLSQBbb1MaynVLmlR1a2BxO9jHj/SKv1qZR18/rX/ct9T6vUnEokFppRvCEeGUGiMdnJKaymf03LCKZo5re1dT82MEjoNeQYqgBzK8xOluqoLYDwW6rq+Fnn3cebxIyYHFWkzg5YTSvP5XprSUuU5PqujiQ0NLahvX2pdd1ADE/9z+RRumoXFPQYBb50q2NVCADYBHcZo/ZQ2MCf4JVnViVAqzH0rFTan62pVG3fR+qm9gWlZq5Et5temvJNHqZlB9Xy19phqMe/jQGVX2Xt4lrX0tIUh5a/UwKQeXqmNVZ8/np4sX1NlSQtJtJNDaym0mYHPJGJBoJRK8/ieplkdjatoYkNDC5w6UGt88TeBNfhPMH+OaQAAAABJRU5ErkJggg=="; + +var img$m = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZE7SwNBFIU/EyXigxSxELFIEcXCoCiIWEkEbaJFEsFXk6x5CHksuxsk2Ao2FoKFaOOr8B9oK9gqCIIiiNj4B3w1EtY72UCCJLPM3o8zcy4zZ8AVzmo5s3UUcnnLiMyF/EvLK37POy58eBhhKq6Z+nx0NkbT8fNIi6oPQdWr+b6Go3M9aWrQ0i48oemGJTwtHN60dMW7wj1aJr4ufCI8bMgBhW+VnnD4TXHa4S/FRiwyAy7V05+u40QdaxkjJzwkHMhli1r1POomXcn8YlRqn8x+TCLMEcJPgiIbZLEISs1LZo19oxXfAgXxaPLXKWGII01GvMOiFqVrUmpK9KR8WUoq9/95mqnxMad7VwjaXm37cwA8+1Des+3fU9sun4H7Ba7zNX9Bcpr8Fn2vpgWOwbsNlzc1LXEAVzvQ+6zHjXhFcst0pVLwcQHdy+C7h45VJ6vqOudPENuSJ7qDwyMYlP3etT9GwWgrP+9tUQAAAAlwSFlzAAALEwAACxMBAJqcGAAACZpJREFUeNrNW11sHNUVvnN31xtt145nZxfbiL+KQHAfioIqpYT0oVJ5ICEUVPKAFEFf7AZIlLa0lZBaVaoUqX+o1DStGh7a0qhqRVRKoZEpUh8KhUi0BFWqsEhIUCqR2N3ZtWM79npn5/Y7w665e3d2/nbG3itZO56Znbnnu+fnO+ee1VjCo1QqjTYajbuEpt0uGBvXbPuTgvMRfF6jcT5A99hC1JmmzeHcLK5d0Bh7VxPiHc75G+Vy+VKS89OSeGihUNiJjwdtTdvDGfuU2z22bTMI2HHsct8Mrp0Stn2yWq2exinRlwBA6CGs8gQmOokJ35oEsHj2WSB1HKg8CzAW+gIAXde3YlJPYFmOYA2H2AYMaMUizGfKtqynFhYWqpsFgKYXixOw1aM4LnrNFyv3DkD6O45noCUzol6/CL+wuDQ6ukg35C9fHkylUoNaJnMDJrSdCTEOKXdDyB24nPJ4tmkz9p150/wlvWfDABgqlW5O2/avcbi7yy0WhJgWQvwWq/Vq1FXaunXrMIC5G885ADDuwalMl1vf5Jr2CBzm2cQBwKo/JBqN47DzvMvlKkxhql6r/Wxpaakcp9rn8/niwMDAY4gWR8jluJjFMrTsILThRFIAcDi6H2AC33B5+QpW4Puapv3ENM3FhMNqHubzVYTOJ7EIuQ5HydjTVdN8IqhJBAVgoGAYhOz+TtcsTmFCh6DmF9gGjuHh4RsBwDNYkH0uILxQ1fWH2LlztTgAGMDKv4AX7VHOr0H4b1YqlSm2icMwjMfhI57C/LLKpemKrt/vB4IfABpW/g/qykPlL6c43wd1/yfrg1EsFu+wGo2XoBHXKrzhT+ALX/Iyh5QPufkRkJ1QHnpOZDKfr5bL/2F9Mq5evXopm83+EYd74IeM9dXTtNu25HL66srKdGgNIG+PGP87VfhMJrN7bm5ulvXhGBkZuaa2tvZaBxMV4hGY6nOBAaA4zy3rDB40KKs9Vv6uhbm586yPB7jDTeAM/5DNAXO/mk6ldoAnvNcR2txAIZIjC08ODzZ/X78LTwPR6AORSt2LVV93fhQuLSGec5OXu6j+RAfDg7eHw3vL018YxoYK6vW+hXL5DDLRrymC7kTEeNTTBCixgeM4C+9RkuM87Gdv0MlUTHPDhe/2TsjzIszhPvnWhmVtk6l5uwYgq5OFJ4ZHJCfMZJLWhJDPP0z2L38ducW3XE3AyeeR0rZdBL2NwvCSBIFWG/OiP9H6Aw9wvRcc4CKuH21PTcUhSrI6AKBihpLPV4nbB5lQF3KSFOlhLlWhrlUihO2fUtosOcQ8T6cnOwGw7UnliVNBExs3EIC0owkb7RzVMTs7uww/9nSb4xNisuX/eKuGp5CHOqW0UVQzYcrLotQE6/X6L5zc5WOKeDMc5C5ZAx5Uwt50lHweRCNWnyB/L6rwNBYXF01o+CnF4e9fB8BWMj1kVyd6dVK9ghBSeF/Vgz87oRQxnNCuOXV725Zr7zZiZbHXYqObwARMNy3x4hVeAOB5geyOohxQqLQlgEJcz2nTQkl4zvQqvJ9jDANcL6rfNp9K5Qpy4n8pp+/ktGOj2MZrccfsoCGyCzg9qb5Cel5ve7Cm7eC0XaXcNxOn53ZT+W6aQIDJfz5RRQtiTop2v6v4gXFOe3UKKrECENUx+ql+WOHdFheO8SZOG5VtANTrF5OI4WEmHIfXd9UAIf6raOIIhxro8knasUmSx8chfMTVd7bUFA0ogADyLfLJ1nbVZoIQlyap48qVK0uKRmR5P1VzklJ9z8gAtWirm9NG5Wbk80mqfmsMDQ3lFROw0oj7RHrWt5hol5Y0LcJK+U6wh8ywZ+GbqfCgYgL/ozDYVuKmLeogDtXtnFcNYBNCnls+cL1CzWcpDF5QjGx7D+9wBaGb8H48PwzXDwjAdkUDPuDUkKQEy/Ee39MGgpfwQeYcc0FlXAFkhlM3lhIsPxdkYlE0oYvwws/u4yqvIe3frWjAGQ0PHwMj+lBJhw1khPMxVGe6Oq+gqh9Xyd0wjEG8jNLhtJQb3MipD49a0WTfQG0pQQhJAPsUEa9pMUcRWu27ZeFx4n2natwMD6eUmw+E8S0+mhI2l/cMeVFBQJJ3QPn/L+slMWpCbJsB5/dQT04IahoKBC9QwlaMAhKgAia4VwHg5DoA1IHpNCF+PDJOQ1I4fh4IBB+N0IJGizCOMZ1O057ggKTi5+fL5dfXAXDskTow22PEEWpISgKEsKoftbxGY2xsjFjuEWX1j7d8EJfC37NKuligbqwImVoU4uJLdaNWm1fX1g4r+53LtmUdl8pkHw3qvaX2UwXlJ6nhwCcU9gxCUKoblhIXCoXrYNrfVujvsa67w0Dmx6x9Hy2HkPhM2AmFASEs1VXNwYsbQNWnlIbO+Xq9/sM2QOR/iPxQ763iC+6lVjQ/r6yqYosneAkYlee3hPYSXi8WJ/HwBxQy8F3aJfKL4RzCkIe8U/piDUjuwoTf7qHYIZJKctQxXCrdzizrtFztgu2/NV+tkkwNXxKDyd5iNRrUJPUJ6QGXYE+7qAeH9fHQdf0GQU1SjF0nzX0lxfkdpml2VLx5F9WkHyYcVIoJY3CSr1ArWr8Knx8dLUHNXpGFbzq+Q27COwWgruFjZeXfW3K5YajIZ6X00bAs64vZbPblWq02328rzxuNv2Ghbmsze9s+hgh3NGpay3XDOKk6E6jUh+lUal8vPiF2m7ftl9WVh+96qVKpPKDava8JyLI6XdeMTSvmcC1AeGPYMB7b9JWHt3ccniI8otlfK4XCfi/hgxOWbduyumn+Hj7g/o5Ya9t/xsdhSi03UnCH5CDOd4S61sqT8AHa5VPBAm+lsbq6+jw1HuOFO9U6G9Lnr+RyOcq63l5eXq4nKThx+0w2+3W883k4t0+7LAjZ/Jcx50Dz0CIg/zAo8s/lECkNkxqSqCdHJRy9DkppkdUdZB91gHZw8OavVh6Hzf8qVBISkdTcagnxGy5FCGWsUU9Osy3lVWpOiKjm1Lb3BSpmNPP5AVdHBZKDOP9wt1AXOwAtX0i9t4i732MuP2KSRoM6M6g5obk/P0O7tJR5tvbqaMeGNi2obt8sXY9TARPf+YyPmc4TvQXAx/ycXRIAOAPZok7tp9SB2eWXZLEPSmkpq6PEpldTi42PU/up04Fp2xOIFtsSkVyI81TMoHw+jj6mWAGQn+k0IVIfnm3v7RkMId6nAibV8JplrP788bRXvKbMkhqSqCeH2lKoMwOfJfiCdDOU1nBcob062q6iHRvatMCl00nzi/8Dx0Tcgl7ehnwAAAAASUVORK5CYII="; + +var img$l = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZE7SwNBFIW/JIpioim0ELHYIgaLCKIglhJBG7WIEYzabDabRNjEZTdBgq1gYyFYiDa+Cv+BtoKtgiAogoiNf8BXI2G9Y4SImFlm78eZOZeZM+CfsoyC2zQIhWLJSUzGtfnUgtbyTIAQHQSJ6oZrT89OJGk4Pm7xqXozoHo13vfvCGZM1wBfq/CIYTsl4THhqdWSrXhTuMvI6xnhA+GYIwcUvlR6usZPinM1flPsJBPj4Fc9tdwvTv9iI+8UhPuFIwWrbPycR90kZBbnZqX2yOzFJcEkcTTSlFnGosSA1KJk9r9v8Ns3w4p4DPnbVHDEkSMv3pioZelqSs2KbspnUVG5/83TzQ4P1bqH4tD86HmvfdCyDdUtz/s89LzqEQQe4LxY969ITqPvom/Vtcg+hNfh9KKupXfgbAO6723d0b+lgEx/NgsvJ9Cegs5raFusZfWzzvEdJNfkia5gdw+isj+89AXPlWf0rTeiAwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAaNJREFUeNrlm0sOgzAMRHHEEbj/CbmDq7Ko2opWxBk79pBNuwCTN/4lCshSc+jbfxkxJMXhhzmEAH6IRUjgzTxCBG9iaoXhBSBW+gi4Aq8jbELiebMIQhL2ZhGEBN58rxDBm2wIGXy3LSGE77LZSOEv399I4S8viORm8GlqQDR8qjaYBn5GDZie8zMjIEXOzxIgJXyUAGnhIwRIDe8tQHp4TwFKwHsJUAbeQ4BS8GgBysEjBSgJf2pk27bjd993evjnWL/B7+J5xGaoPPxLAIP3KeCtEUADfxg+8/6fAkgF3xsBdPCnAvzwPiX8Rxsk8Tz8bDAzPOStkdUw8dnwipxf73l7NnjxqgG6+AwFpSKsQDYQQEl49EqwHPw/g8iXEhHwbmsCj91gGfgeAQSYDqneS2oArym4jWqkWM2hZmgV+F8PUcM1iLDXGWnSgMKhcj60RvTsBTwLni6ThjhOxgIf3iHWIFFTwp89VIPAU8BbIqDiV2bDAngfoU8VVYInqdkiKmpTolnTCXEuUBbeskTtTZ30RTRqpZa2eyA/R6FvmZTjAXQIhaMv+ge0AAAAAElFTkSuQmCC"; + +var img$k = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABcWlDQ1BpY2MAACiRdZG9S8NQFMVPW8Wi1Q46SHHIUMWhhaIgjlLBLtWhrWDVJXlN2kKShpcUKa6Ci0PBQXTxa/A/0FVwVRAERRBx8R/wa5ES72sKLdLe8PJ+nHfP5eUE8Kd1Zth9CcAwHZ5JJaW1/Lo08A4fRhBEHBGZ2dZydimHnvXzSN1UD3Exq3df1xoqqDYDfEHiOWZxh3iBOL3lWIL3iMdYSS4QnxDHOF2Q+Fboisdvgosefwnmucwi4BczpWIHKx3MStwgniaOGnqVte4jviSkmqtZ2iO0JmAjgxSSkKCgijJ0OJRLGSZl1t2XaPpWUCEPo7eFGjg5iiiRN0ZqlaaqtGukq/ToqInc/+dpa7Mz3vRQEuh/dd3PSWBgH2jUXff31HUbZ0DgBbg22/4K5TT/TXq9rUWPgfAOcHnT1pQD4GoXGH+2ZC43pQAtv6YBHxfAcB4YvQcGN7ysWuc4fwJy2/SL7oDDI2CK+sObf/JNaAQfxWcoAAAACXBIWXMAAAsTAAALEwEAmpwYAAAIPUlEQVR42uVbW2wUVRg+c/ZSUrelsxfaGkQNDVgfJKgJAuVNg1yDER5ICPrSigJWQU1INCYmJEokQLEQIPHKgwYSULABeQPEJijwRiPXYKK07uz2Kt3uzhy/f90uM2dnt6XdbXfH87LbmdOZ83///bIKK/AKhUI1uq4vFIoyRzBWrxjG44LzanxOUzj30h5DiDhTlC5c68S9WwpjVxUhrnDOL4TD4b8KeT6lEA/1+/3z8LHaUJSlnLEn7fYYhsFAYMZ3m30duNcmDONoNBptxyVRlACA6EpwuREHbcKBZxUCWDz7GpA6CFQOAYyeogBAVdWpONRWsKUZPKxkE7AgFX1QnxYjkdjZ09MTnSwAFDUYbISubsf3YK7zgnNXANJZfO+AlHSIePwO7EJff01NH23w3b1b4XK5KhSPZwYONJsJUQ8qG0DkXNx25Xi2ZjD2QbemHaD3TBgAlaHQTLdhfImvDVm2JEDEKSHEN+DWmbFyaerUqVUA5gU8Zx3AWIJLnixbf+GK8goM5rWCAwCurxW6fhB67rO5HYUqtMRjsc/6+/vD+RR7n88X9Hq9b8BbNJPJsVGLAUjZBkjD4UIBwGHoPsEB3rF5+T1w4GNFUXZpmtZXYLfqg/q8Bde5DUwozzCUjO2OatrW0arEaAHw+gMBQnZNpmkWbTjQJoj5LTaBq6qq6lEAsBcMWWEDwrGoqq5l16/H8gGAF5w/hhctla4Pgfh3I5FIC5vEFQgENsJG7MT5yqRbpyKqumokEEYCQAHnv5M5D5G/6+J8BcT91zHHDYGAJaCJaNqYPVIwGHw6oesnIBEPS3HDccQLL+dSBz5CcLNDJh4PvS48noXjIT7fC9b/Es61EIz53cI9zlepgcCunIYtl7WXDR4R7/F4Gnq6um6yIluwQbfLvN5FGSAw9iYYuf6BACA/D1d3QBZ7w+NZ3NXV1cmKdHV2dnaBSYtx1j+tkZjYDzWZNVoAFApyoE8VZoMHnV9ZjJy3kwThci2HgU4bP3KXCSG+tqOX24h+Y0aEB2sPnb/ISmT1hMOXkYm+LRE6Dx7j9ZxegBIbBDPXoPshs5+Hq1uW95Q5j14gR6L2PQzhSvNr9ESizhyaWyUAWZ2ZeIrwKMhhpbs2g4Z/zLgjt3jPVgWS+TxSWstNhLcTHeHlcyEGuAMatksGcRMlWRkAUDFDyuejFNuzEl9w23sobTYZRB93u5syATCMJimebil0YjNBrnEAdmy3xfAJ0TRs//hwDU8qY8UppWUOWfF4fH8yd0kjoMyEgVxgloDVkts7le98fjJXX1+fBglvkwz+mjQAhpTpIbs6zBy2YM8OS0WMpGvnVLeXStcGlbGY8xbRpJsSpTqo/nROTQsp4bk83kprMS4Ec73IiX+TLs/n1LGRdOMcc+iCpJ+3MFtR5nJqV0n7OpwKAKT7qmQH6jn16iRUHAuAzFwYxsc4NSotAMTjdxwrAUL8IYXF1W6IgcpMjUnq2Iwmeyt0djhuo2eTXVJLjbtcZgnwIwDkU8ybhttVTly9vb39kkSUcfY/XxxiYambU6PSqcRWVlb6JCOYcEP/KehJt5ioS4uP8Gh0qtgrQhncttY5SQX+JjdoqfJSi9qpEgCOPyIVfDrJDVoqPsn+vHMBmC1JwG1OA0mSs6x3sM2rlwDp4DSNJTnLRU6lHml/gyQBlykOuGBBhfO55qKhU1YgEKiAz39GutzOaQ6PRtHMtoHGUhwYBhNNbtOFG8mqcco9tEmb1zkOAEVZJ/39YypFTqaJRyU1WEIzOQ4KgPww9sskAI6mAaAJzOQQ4v3lSQ4kOWS53W7qCXpNIn6zOxw+nwaALiUnMK0+opkGkkqd+NraWopymyXuH2SpkVtucn+HKF00R6s0jVXqAAwODW2W+p0DRiKRZnYaAJq9pfFTqWCwDS7xsVIlnqq+UO33pfC3NWt3GMh8yqx9tHK4xL0lbPlbpIHO7ng8vsMCiPkPINNNs7eSLVhOo2ilRrwaDDbB8r8kBQMfUpdIyn0ys0akqmQh55v+MQYkF9A0Vimkw1Wh0ByWSLSbq13Q/Yvd0SjRpGeVgOG9NHicnL29LwVlCV0/WQr2QFXVGaD2pET8PRfn62XiswHAklPXnG+Qigm1MJKnq6urpxUr8b6amhDE6jSImi4Zvk2aptmW+7PWBGnqmgaPJRBmxYaGzhWjJBDn3bHYWZzxCYvaG0ZrJBL5PGuVKNdDaeqaBo9lECAJP9N4arEQTzovcCaZeNiuE3DvzTmLJCM+va6uzB+NHse3F6WHx5Bfb4Gk7Jtsay90fY9c3oc3+6lbVVeOd1g6DYKqad/S7G2GrzWMH/CxmVLLCQ9y4OczXF2K8xG/f81oxuVdo3pbJKIPDg4emVJeruKF86Sy0mykz6+Vl5dT1nVpYGAgXujY3lNWtgXvPALj9pQNQ1rBjFdx5lGdQxkD8usRIu+DyD1kc1ujgSSayZEDjnyktMjqNrD/JkAzUvXUr1Y2wuB98SDPHVPwQYPHCSG+ggV9LsuWIZrJSY2lnKHhhDGKOY3tPU/FjFQ+77XbR0EO+flsri7vAAw7BJq9hZf4iNn8iMm0dJrMoOGEVH++g7q0lHkO9+qoY0NNC6rbp0rX9VTAxP88O4KadlN4C4Bb7YKcQgOQXIgJVBo/pQnMLL8ky/uiKJWyOkpsxqtqeYu/qZKcnMA0jEYaQCpMeiduUjGD8vl8zTEVoh+nJIcQaQ7PMJaNGwwhblABk2p4qTJWcf54Ope/psySBpJoJofGUmgyA58h2AJ3ypXG8D1CvTpqV1HHhpoWuNVe6PjiX7rk5GR8PE/UAAAAAElFTkSuQmCC"; + +var img$j = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZE7SwNBFIW/JIpioim0ELHYIgaLCKIglhJBG7WIEYzabDabRNjEZTdBgq1gYyFYiDa+Cv+BtoKtgiAogoiNf8BXI2G9Y4SImFlm78eZOZeZM+CfsoyC2zQIhWLJSUzGtfnUgtbyTIAQHQSJ6oZrT89OJGk4Pm7xqXozoHo13vfvCGZM1wBfq/CIYTsl4THhqdWSrXhTuMvI6xnhA+GYIwcUvlR6usZPinM1flPsJBPj4Fc9tdwvTv9iI+8UhPuFIwWrbPycR90kZBbnZqX2yOzFJcEkcTTSlFnGosSA1KJk9r9v8Ns3w4p4DPnbVHDEkSMv3pioZelqSs2KbspnUVG5/83TzQ4P1bqH4tD86HmvfdCyDdUtz/s89LzqEQQe4LxY969ITqPvom/Vtcg+hNfh9KKupXfgbAO6723d0b+lgEx/NgsvJ9Cegs5raFusZfWzzvEdJNfkia5gdw+isj+89AXPlWf0rTeiAwAAAAlwSFlzAAALEwAACxMBAJqcGAAAA0dJREFUeNrlWwmO5CAMjBEv2On/v7BnnjDeZhUkixgfQELIIkXqzgG4XD64YKuU1+vF3v9F3Dzl5/vbVX9PewGg+uz9frP3wduxskMVAdHSlgeImgB/vr5MANTqid6OGAoK92GbXLKcGYgwuH7sfH55iZr2a9TrBAmkdjxsrPkYrZ70LLUZBwpes3vUQCjbSv+5zpf05YSkz/JvCYjAPRykdZCcX6vtWjTrqTOeZPtgZMIQQDTFSUwIrdpPlY2IHFqnRxauzrDNKzhKwz2hPFxA/22UL7AI6AVhJgOGULrXVOJoRK8UvhY2c4zXwuQ/BqTcnl53FHB09KCgTDeBGsPOYl5pNuHJmr7ECVobKqnXo+GRoIWRdmUNU/m9VhBGmkeYaecjtcy9Lw2oLgWgFq8/93BPpNjrrDR5ehRwJDBIQDqFlXGG8C3ffDqMwrfQCkLs7fBVmaLSD2wF4w5jAahcbpB306qaDAfi5SZAhfl0SJoqB6pdmt9bTWYTpt1cANxlQLSDAJY5hV1g1TSWHg5z5qL4iQNgkU4rJ9oI2gZrsjEJiEx70VSSj/i8BwcG5I8lBBWAblO0PlJHGYzCl0B0aarQWjVR2jUJLSGucKTDw2BTZrYLBVR4ia4EHI+tm/xEdpKB0z7pJAidw22tYosCOcxkzaT/QrzGM+21IW3WzAVcY4Fi4hFmaN0DAuMzDiXtJ6D7CMIIGq1W6ORvaNDGY0BIV2ik5CNAYBlgsfMngRA4D+9IdJYHIQqJDmSvSUseO5Clp+Fr/5ebQCcLlmZEVHJ+0NYLqT9IbKkx5vYA1BKdJMCoFZ0losCIQc+yJsCxgNuadsMJEbvGSRpsTYQew4LDstgHjOpo8H8p1lQYH6L9w4auYI3nT/P+2a8FxxgcFwcBe0zgUc6Psjw401q8sINn2r5+YOIpcV9TbqD7e5hNhfAAX4CScmNHpbCA3auHt1QnuGJiJAhfPzVGP7ZMRe9bVuCsjY5nCM+xNnidxgIOsSo8e2DCsuQtTILinTQvTOiCeHLUujzV0oCVOT2m5KU9bRM0OjNH1NiGZm21V84LgybX0itDmvCu4bB19+YKiyKS8KWcoNmpkhLjTPpzLCiF1+T4C+eX+V1keq0EAAAAAElFTkSuQmCC"; + +var img$i = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZE7SwNBFIW/JIpioim0ELHYIgaLCKIglhJBG7WIEYzabDabRNjEZTdBgq1gYyFYiDa+Cv+BtoKtgiAogoiNf8BXI2G9Y4SImFlm78eZOZeZM+CfsoyC2zQIhWLJSUzGtfnUgtbyTIAQHQSJ6oZrT89OJGk4Pm7xqXozoHo13vfvCGZM1wBfq/CIYTsl4THhqdWSrXhTuMvI6xnhA+GYIwcUvlR6usZPinM1flPsJBPj4Fc9tdwvTv9iI+8UhPuFIwWrbPycR90kZBbnZqX2yOzFJcEkcTTSlFnGosSA1KJk9r9v8Ns3w4p4DPnbVHDEkSMv3pioZelqSs2KbspnUVG5/83TzQ4P1bqH4tD86HmvfdCyDdUtz/s89LzqEQQe4LxY969ITqPvom/Vtcg+hNfh9KKupXfgbAO6723d0b+lgEx/NgsvJ9Cegs5raFusZfWzzvEdJNfkia5gdw+isj+89AXPlWf0rTeiAwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAbhJREFUeNrtWgFqwzAM9Jm+YM3/X5juCdPooFA8Z7MdSZbkCEohtFi6O8lSUEqXXba0waBPpOkfDAev4uPNcOBLpADN9hOOWEcUAKjRJ5V6AEPBY0ZRhDHWW/8HTwDQSR9EQYAxyauDAKOsq4EAw6yrgAAngYuBAKNyV5sZ4IR1MSXAafBsIMBx8CwgZOaucsZscerMbMEJofNJCgBKNm0IhByA/VMg5CDsD4OQA7E/BEIOxr7qLYCVAAjJPncj5LE4NgFADuVPlwKYAPDIflfBjqgA4lJAFPaXrwHgAgAR0ckr5/8KKYCrBvxjt055/UL0435Pn49Hqj3ntKMz3p5X5b9t28/3vu/dCmguemWw3MEPnoESiBcYowroclDCOM4oFRGlBgyP673LCXACAErGa/ZUQfhb4Kj4RboG6Uw9GNnPcbteW0uH/P6w8oNQs38tHTCAMDyyf0Ty8q1wS3NBDZ+ZChj24xk7BmUmMplx3v/cTmmxDMn8r/YBjf01Jkm6J90glQJW1CFCkoVl6fAAaIBkYlV2Fkgh31bbKhxl+/hFdtcFMtA8Cl+tcAsAf71RsW6efVezb/4DdiZjsxv1AAAAAElFTkSuQmCC"; + +var img$h = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZE7SwNBFIW/JIpioim0ELHYIgaLCKIglhJBG7WIEYzabDabRNjEZTdBgq1gYyFYiDa+Cv+BtoKtgiAogoiNf8BXI2G9Y4SImFlm78eZOZeZM+CfsoyC2zQIhWLJSUzGtfnUgtbyTIAQHQSJ6oZrT89OJGk4Pm7xqXozoHo13vfvCGZM1wBfq/CIYTsl4THhqdWSrXhTuMvI6xnhA+GYIwcUvlR6usZPinM1flPsJBPj4Fc9tdwvTv9iI+8UhPuFIwWrbPycR90kZBbnZqX2yOzFJcEkcTTSlFnGosSA1KJk9r9v8Ns3w4p4DPnbVHDEkSMv3pioZelqSs2KbspnUVG5/83TzQ4P1bqH4tD86HmvfdCyDdUtz/s89LzqEQQe4LxY969ITqPvom/Vtcg+hNfh9KKupXfgbAO6723d0b+lgEx/NgsvJ9Cegs5raFusZfWzzvEdJNfkia5gdw+isj+89AXPlWf0rTeiAwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAa1JREFUeNrtmoFqAyEMhv2lT7De+z/hdY+wjA4GxXkjphqTaKAUpOWSL380eqa0bdvSBoM+kaZ/MBy8io83w4EvUQI02084yjqiACCmTyrzAQwFjxmTIoxlnfs/eAJAb/owFAKMSV4dAoxmXQ0CDGddBQKcBD4MAozKXW3PACdZH6YEOA2+G4TsvL2GsCyHAMCkvcXUZZCMbKvFE6PFIzFVCNEANEOICKAJQlQAbAg5LW4bwAawjmElALQVsAHwlvu8svw5AChNfHE5uwRIStWL/PckGBAArQ6gebO3fAncGuX1h+jH/Z4+H49UG+9pV894Ga/K/ziOn+/zPJsVwD4rKIPtHbzwGShB/MKQKqDJwRHW4xmlIqLMAeI+pfVyApwAQJnxmj1VEH4VuJr8Ii2D9M58ILmf4/Z6ba0c8utg5Qcej83RUg4QEIbH7F8leflWmNNcEOMzUwFiP56xQyizITuznut/b6e0soyR9V/tA5j9NSZJuqXcMKoErKhjSJIsXJYOD0ADkomrsrMgRb7kYaRuyvbxi+y+J8kAeyu8W2EOgP9OVKybZ9/V7BsoanMeq391+AAAAABJRU5ErkJggg=="; + +var img$g = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZHNK0RRGMZ/M4gYUSwk6S6GKFOiZKlRZoPFGGWwuffOnRk1M273zqTJVtlYTFmIja+F/4CtsqWUIiXZ+Ad8bTRd7zFqJHNu576/nnOet3OeA/7pjJl164chm8s70UhYW4gvao3P1NNDO4P06qZrz8xNxag5Pm7xqXoTUr1q7/t3tCQs1wRfk/CYaTt54Qnh6bW8rXhLuNNM6wnhA+EhRw4ofKl0o8JPilMVflPsxKKT4Fc9tdQvNn6xmXaywgPCwWymYP6cR90kYOXm56R2y+zBJUqEMBoGBVbIkCckNSeZ/e8b/vbNsioeU/42RRxxpEiLd0jUgnS1pCZFt+TLUFS5/83TTY6OVLoHwtDw6HmvfdC4DeWS530eel75COoe4DxX9a9KTuPvopeqWnAf2jbg9KKqGTtwtgld97bu6N9SnUx/MgkvJ9Aah45raF6qZPWzzvEdxNblia5gdw/6ZX/b8hco4WgdZKtgqgAAAAlwSFlzAAALEwAACxMBAJqcGAAAAhtJREFUeNrtW21uwyAMjREnWHv/E6brDrDGC1MzZQiCCWAMwVL+NCH2e/iLQGHyyP1+R9fvC+IkVRSA9948z86bQAXeOgE+IoAKvBcCbCLUdHGB0Oz7YidFVn22jiLg3noOsWlO4NzyJhaOiFCu2e8BPDXhXyIHGE/whZmWPvt2voiR79dr+no+/2GzPV6XNCBHgnOV3WVZJqWUt+xtY8wzIdEtu3aOnkSnzmCqh8Q2OgY0ZWazEVBbPh+Pw/sft1uS18D6ArQUUpKg1H44aLuN94wvoWCHibbt8msBVcLNJIdAdBL0ZHmyIlcVObsYOkp4W7K0nwkl0WZCgAKeKwS6Ad8EASXBN10FcoAfjZDxAMNkJJtdNULboN/LZif0vNCL4gF/FzgGdR0Ctu26oKJuW+HLrwUGAYOAjuRsEuSqAiDRAzhLII4QEEgAZw8AUnPAaIQGAb0QsP/iErvL0qLYGPVVgPtI0JdzeWtLXcccLRtJcBAwCOifAOqR2RbFhW0clfUx09thSR9GHRrQOhGhkIYzsX90PG23T5+VuPW9SOlaqX1NkePy+y22zeCc4G0dWb8HbIzkrALG8FRPyEmkK6S9Z4VzEZFCQk7w5P8MZRAM5Rvm94TLoEASkMvekiXuLAjktLV0jY8Fg9x2cjQ5VFBYw0auLi8EDmvZx9nmokTbuPt8lGZXjYUOSrKp5koPBdlSlYSqX6B+AGDuGPLVCsLeAAAAAElFTkSuQmCC"; + +var img$f = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZHNK0RRGMZ/M4gYUSwk6S6GKFOiZKlRZoPFGGWwuffOnRk1M273zqTJVtlYTFmIja+F/4CtsqWUIiXZ+Ad8bTRd7zFqJHNu576/nnOet3OeA/7pjJl164chm8s70UhYW4gvao3P1NNDO4P06qZrz8xNxag5Pm7xqXoTUr1q7/t3tCQs1wRfk/CYaTt54Qnh6bW8rXhLuNNM6wnhA+EhRw4ofKl0o8JPilMVflPsxKKT4Fc9tdQvNn6xmXaywgPCwWymYP6cR90kYOXm56R2y+zBJUqEMBoGBVbIkCckNSeZ/e8b/vbNsioeU/42RRxxpEiLd0jUgnS1pCZFt+TLUFS5/83TTY6OVLoHwtDw6HmvfdC4DeWS530eel75COoe4DxX9a9KTuPvopeqWnAf2jbg9KKqGTtwtgld97bu6N9SnUx/MgkvJ9Aah45raF6qZPWzzvEdxNblia5gdw/6ZX/b8hco4WgdZKtgqgAAAAlwSFlzAAALEwAACxMBAJqcGAAAAhRJREFUeNrtW1tywyAMtBhO0OT+J3SaHqAxMZ2446qINwQBmvFPbAy7rB4YAgth1+tVmX7flFpaNQFA3lvX1XgTfIFzJ4AiAnyB90IAJkIsgxu4Zp/ynRTb+8N9FAH36seKTdYEXttexIKNCGGa/R7A+wb8IWKAVgLlZrL12cfxIsS+H4/l637/gw0rXpYcQI4AZ0q727YtQggy7R1t9DMuk5ylnaMmkakzmKqQ0EJHg/aZ2WwEvNs+bzfr/Y/LJUk1sL9AoQ59gmCr9bBz7BhvjJZUw4IJHtvwawFRQmYtu0BwECSivHdHpiwSuxiyBbwjWOJnXEGUjQv4gK/lAt2AZ0FASfCss0AO8LMQ0grQTAay2VUhdDT6uTA7rucbvXwU8HuBoVHXLoDHLgt21G0pPPxaYBIwCejIYoNgrSwALSqgZgpU0wUaJKBmDQCtxoBZCE0CeiHg/MUldJeFo2GMchTgFAlyOMmjLXUZcrRsBsFJwCSgfwJ8j8xyNBO2eVSWYqa3w5IURulqwJ0Il0tDjO+fDhr9Iwfv0xt2nZJijKtq9a1rko7Ln7bTlAk8ATwZvOW9+T44uJSAT3PsMwKeg8uWXWwqcCkAuzR5VpgIGjHjbSKtev9nKAIMJIB/e4CFDDMKHIGXLITYgM/9PYAV8JwuUKofdgpgBbzGYohFCS1HBV5KAewWTnJU4KkDVz2A1/YE9TAKPpdsqQcAAAAASUVORK5CYII="; + +var img$e = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABcmlDQ1BpY2MAACiRdZE9S8NQFIbftkpFWwrqIOKQoYpCC0VBHKWCXapDW8GqS3KbtEKShpsUKa6Ci0PBQXTxa/Af6Cq4KgiCIoi4+Af8WqTEc5tCi7Qn3JyH9573cO+5gD+tM8PuSQCG6fBMKimt5tek4Dt8GEQYQ5iSmW0tZRdz6Bo/j1RN8RAXvbrXdYyBgmozwNdHPMss7hDPE6e3HEvwHvEwK8kF4hPiGKcDEt8KXfH4TXDR4y/BPJdZAPyip1RsY6WNWYkbxJPEUUOvsOZ5xE1CqrmSpTxKaww2MkghCQkKKtiEDgdxyibNrLMv0fAto0weRn8LVXByFFEib4zUCnVVKWukq/TpqIq5/5+nrc1Me91DSaD31XU/x4HgPlCvue7vqevWz4DAC3BttvxlmtPcN+m1lhY9BiI7wOVNS1MOgKtdYOTZkrnckAK0/JoGfFwA4TwwdA/0r3uzau7j/AnIbdMT3QGHR8AE1Uc2/gDt82gCvNGYhAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAcpJREFUeNrtWwFuwyAMjBEPWNf8/4XpugesoWMKUppBYidQ5cAnVZWaRtGdDxscoC6Bvu9d7PfRue6sMETJa8MwRC8Slzi6ACkhiEu8FgGWQpiucdBW9FNj5wiWzyvxjOk5/muVm30n8Xfjl8NfkNeEMLHo10Cem/CbyAHeCZMb/sGePfqTfXfh5/Hovu/3F25Lx9ujiURad6WIld1xHDtjTLLshXv8f7Zgka2dY04ClQNCxDmR5eL0Dvi63Vavf16vh1xjzzy13YKUPPQQWFaDHOShBJjX8VzkIRdDa+RDvvBlskoBOOSlVcLURr7KIVCKPIQAJclDJsGc5FkzwdBUqJE8pANykocTIDd59mKI2zIv0Q8oSR7GAaXIQwhQkjx0GVQBGI5xjEWRrTGqkmGjQ0AFUAFUABVABVAB2sXmRMi3pEbnSDLJyNm3h3MAEvnsAqCRZw0Bb/l5Q2THjg1qaghoFVABVAAVQAVQAVQAFUCCI9thxYSJXj5WcspCHaACNNgP+LhcTr+gySqAX/nNX2nP99ujI/aaX3NAbAPDkQ0RSNFfPTUWbkA/QLUVTNoT9RpOj+rJ0aUDJE5AdkDy8LRECEQBUrnsCeUexwK5uUFRAAAAAElFTkSuQmCC"; + +var img$d = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZE7SwNBFIW/JIpioim0ELHYIgaLCKIglhJBG7WIEYzabDabRNjEZTdBgq1gYyFYiDa+Cv+BtoKtgiAogoiNf8BXI2G9Y4SImFlm78eZOZeZM+CfsoyC2zQIhWLJSUzGtfnUgtbyTIAQHQSJ6oZrT89OJGk4Pm7xqXozoHo13vfvCGZM1wBfq/CIYTsl4THhqdWSrXhTuMvI6xnhA+GYIwcUvlR6usZPinM1flPsJBPj4Fc9tdwvTv9iI+8UhPuFIwWrbPycR90kZBbnZqX2yOzFJcEkcTTSlFnGosSA1KJk9r9v8Ns3w4p4DPnbVHDEkSMv3pioZelqSs2KbspnUVG5/83TzQ4P1bqH4tD86HmvfdCyDdUtz/s89LzqEQQe4LxY969ITqPvom/Vtcg+hNfh9KKupXfgbAO6723d0b+lgEx/NgsvJ9Cegs5raFusZfWzzvEdJNfkia5gdw+isj+89AXPlWf0rTeiAwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAMtJREFUeNrt2kEKgzAQBVAjnqDm/ifUHqHpsigKgkYa5/2dWRjnOQkE0nUiEjlpZ7xEqTcFKn6z5j76EggPMJzYJ1pJ0QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACB4hrMveI1j957nzfErszfH1vjtHbAu9uria84x1PrAGqkxR/g94Mg1uafdEXJNDgAAAAAAAAAAAACAY6fBogMAxDoOP7nt01GARXLOi+dP+V+fPv1KmqbJEjgNsP77LaXlb78tX1rgGEFVOtioAAAAAElFTkSuQmCC"; + +var img$c = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZE7SwNBFIW/JIpioim0ELHYIgaLCKIglhJBG7WIEYzabDabRNjEZTdBgq1gYyFYiDa+Cv+BtoKtgiAogoiNf8BXI2G9Y4SImFlm78eZOZeZM+CfsoyC2zQIhWLJSUzGtfnUgtbyTIAQHQSJ6oZrT89OJGk4Pm7xqXozoHo13vfvCGZM1wBfq/CIYTsl4THhqdWSrXhTuMvI6xnhA+GYIwcUvlR6usZPinM1flPsJBPj4Fc9tdwvTv9iI+8UhPuFIwWrbPycR90kZBbnZqX2yOzFJcEkcTTSlFnGosSA1KJk9r9v8Ns3w4p4DPnbVHDEkSMv3pioZelqSs2KbspnUVG5/83TzQ4P1bqH4tD86HmvfdCyDdUtz/s89LzqEQQe4LxY969ITqPvom/Vtcg+hNfh9KKupXfgbAO6723d0b+lgEx/NgsvJ9Cegs5raFusZfWzzvEdJNfkia5gdw+isj+89AXPlWf0rTeiAwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAZBJREFUeNrtmlGOwyAMRDOoJ9jm/idM9wjrzVZaKWpDoBI2YzBSf6oqeB5jjGmWZfKBDnMKU0wgEd0tPpAKN4sTDsSrxgqyPDffH2AoHp2eYwqgddDqEEAs3gQCyMWrPz85KbHUZVA6VxewOsDFSOTWV392UrAkW3Nl6gCL5grMKSDsK94aAAhSIKpAACADIF7yvxUAeM3/SAFFAOIltRKLFXvNqZkCwr76sQc0BgBv9rdwgDDbP1Ig2uFwQAAIAI46QZU5wgEOdmzEHuAEgOV/BMJk0VxAFu8eQA3Auq6nlH/k/evvx+Ptu6/7van6mjkS8jy2bUMVgJzwKwCvAbYWXzvHFYAcCNQKLwGg2NBQnxH/IKavAiitfi53vIySttuowo86dgjZ0okzQqOIP7ggW0qn2AP2BX1+sifB4w9GW/2Ss3FiC4zshteUjzK4n6jk7Jg5w/g7TWLheNNr2AsRfgBajYunFOh1qdG9BYgUCAABIADcPuymnsPLrVCuAQoHXABAafWd3gNM0+x9PH4BvDJ3ZJJMpIIAAAAASUVORK5CYII="; + +var img$b = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZE7SwNBFIU/YyTBBykUEbHYwoiFAVEQS4mgjVrECEZtkk02EbKbZTdBgq1gYyFYiDa+Cv+BtoKtgiAogoiNf8BXI2G9YwIJorPM3o8zcy4zZ8A3k9dN1z8MplV0YtNRbTGxpAVe8NNNB0HCSd21Z+en4vw7Pu9oUvU2onr9v+/P0ZbOuDo0BYXHdNspCk8Iz6wVbcVbwl16LpkWPhQecuSAwldKT1X5WXG2yu+KnXhsEnyqp5Zt4FQD6znHFB4U7jfzJb12HnWT9oy1MC+1V2YfLjGmiaKRosQqeYpEpFqS2d++4R/fHAXx6PK3KeOII0tOvEOilqRrRqoheka+PGWV++88XWN0pNq9PQotT573FobADlS2Pe/ryPMqx9D8CBdW3V+QnMY/RN+ua/0HENqAs8u6ltqF803oebCTTvJHapbpMwx4PYWOBHTeQOtyNavaOif3EF+XJ7qGvX0YkP2hlW/cxWf6XLNyeQAAAAlwSFlzAAALEwAACxMBAJqcGAAAADdJREFUeNrt1LERAAAEA0DsvzO9EfjvUsrlRAAAAAAAAABwX67c3+6u7wtQgC8AAAAAAAAAwH0DNkcBCEXoxRkAAAAASUVORK5CYII="; + +var img$a = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZHNK0RRGMZ/xmiESWEhLO5iyAKJkqVGscFiZpTBZu51Z0bNx+3eO2myVTYWykJsfC38B2yVLaUUKcnGP+BrI13vMVMzyZzbue+v55zn7ZzngG8mY2Qd/zBkc64dmQ5rC/FFLfCCn27aGCKYMBxrNjoVo+b4vKNO1dtB1av2vn9H84rpGFDXKDxmWLYrPCE8s+ZaireEO4x0YkX4UHjAlgMKXyldL/Gz4lSJ3xXbscgk+FRPLVXFehUbaTsr3C8cymYKRvk86iYtZm4+KrVLZg8OEaYJo6FTYJUMLoNSc5LZ/77hX98cefEY8rcoYosjRVq8A6IWpKspNSm6KV+Gosr9b55OcnSk1L0lDA1PnvfWC4Ed+N72vK8jz/s+hvpHuMhV/HnJafxD9O2KFjqA1g04u6xo+i6cb0Lng5WwE79SvUxfMgmvpxCMQ/sNNC2Vsiqvc3IPsXV5omvY24c+2d+6/AMRKmgSy8M37AAAAAlwSFlzAAALEwAACxMBAJqcGAAAAV1JREFUeNrtmgEKgzAMRRvJCab3P6HuCOtU5nBdY61iqcn/UJBN0f9qkxTjHARBkGGR9EfXdT72+8v7as00JNpxfd/TLgCS8bsDkEDQXuNaAIQgGsSAxOxLa+cuSnljrcbXPkYI02EUBMUIaTG/eguWwz+vJmLAOKHziAZO7bOf8mY+CwCAdQBszXBYyfLB0rbWephKLAFf8QR7xIACAGquE7KfjUvdCGkQAAAAADRVgnoKoecwuGlYLYSWi+bxaFufc36lY1Mfj99BkYtI+RLwKISQBQAAAADgZBAslQmo1jegVBr0WAKVAihVB1DNMYAsvwFIg2oAjLuj9U5JveHQI1sxLkEw920w7CTjnNYyBEEAAAD9APa2zN5RMW9olZXIKGyWjHrk1AWae4V/dnQ5a3+rryjzK9PpUjZV6Ei6pF3+avNX3INDIpqzQGxJs3SCNhCae6AhCIKgo3oDRfKqQh1Aqh4AAAAASUVORK5CYII="; + +var img$9 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABbmlDQ1BpY2MAACiRdZE7SwNBFIW/JEpEE1JoIZIihYqFgiiIpUTQRi1iBF/N7uYlZDfLboKIrWBjIViINr4K/4G2gq2CICiCiI1/wFcjst5JAgmSzDJ7P87MucycAf9M3jDdlmEwraKTmI7HFpeWY8E3WogSIoxPM1x7dn4qSdPx/YBP1fsh1av5voajI5V2DfC1CY8ZtlMUnhCeWS/aineEu4yclhI+Fh505IDCN0rXK/yqOFvhT8VOMjEJftUzlq1jvY6NnGMKDwj3mvmSUT2PukkobS3MS+2RGcUlwTRxYuiUWCNPkSGplmTW2Ddc9s1REI8hf5sNHHFkyYl3UNSSdE1LzYieli/Phsr9f55uZnSk0j0Uh9YXz/vog+Ae/O563s+J5/2eQuAZrqyavyA5jX+JvlvTeo8gsgUX1zVN34fLbeh+sjVHK0sBmf5MBt7PIbwEnXfQvlLJqrrO2SMkN+WJbuHgEPplf2T1D6TFZ+Dpj8jzAAAACXBIWXMAAAsTAAALEwEAmpwYAAABJUlEQVR42u2b6wrCMAyFF9kTuL3/q0YUlDIQrGnatPkOFPZDluY0l7NQty05pHjWCfbo9nKd6KCa4pY9BSAgOwF7w7zTRrmrRIAjzvN8rSsB0rP1VFZ86RUBUqwIbc91L+8ooAtkdv4ZBUQABEAAn8Ot8KsS1Ei+946ASJ/dSgoMIECipf8+ed2pxv04hhdB2iAEQEAcjCiCLbWAGGwsIYTUYAMhtIIQEoMN8Qjv6woHhBBtEAIgYCUhZO4gTISoAXMLIfNe0k2E6AIQAAFT6ADLoGMJHaDOzqMDousAy6Cjai/p5gHlFTlSAAJsbVD/+E24lBBH52ts6ijfI6SAjrTLJanOJyeBokBSnvi36/IAUATD/3fQxXdJ6vyHBHRA9hQA2fEADxYsjjbR70EAAAAASUVORK5CYII="; + +var img$8 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZHNK0RRGMZ/M4gYUSwk6S6GKFOiZKlRZoPFGGWwuffOnRk1M273zqTJVtlYTFmIja+F/4CtsqWUIiXZ+Ad8bTRd7zFqJHNu576/nnOet3OeA/7pjJl164chm8s70UhYW4gvao3P1NNDO4P06qZrz8xNxag5Pm7xqXoTUr1q7/t3tCQs1wRfk/CYaTt54Qnh6bW8rXhLuNNM6wnhA+EhRw4ofKl0o8JPilMVflPsxKKT4Fc9tdQvNn6xmXaywgPCwWymYP6cR90kYOXm56R2y+zBJUqEMBoGBVbIkCckNSeZ/e8b/vbNsioeU/42RRxxpEiLd0jUgnS1pCZFt+TLUFS5/83TTY6OVLoHwtDw6HmvfdC4DeWS530eel75COoe4DxX9a9KTuPvopeqWnAf2jbg9KKqGTtwtgld97bu6N9SnUx/MgkvJ9Aah45raF6qZPWzzvEdxNblia5gdw/6ZX/b8hco4WgdZKtgqgAAAAlwSFlzAAALEwAACxMBAJqcGAAAAZ1JREFUeNrtmw1uwyAMhTHiBGvuf8K03QHWMDE1UkehgEMSDO+TKlX5IXnG2E4gpCJM0xTcvlirWkUTRffN8xzcTrnCpRsgZgjKFd6LAVIeAQAYCzrjon7APTMgmdZ7KDc7hfh5PNT3/f7W3mpw99/seQM1ejeUdpdlUVrraNpbz3HHpDQZyeO3Rk1ifJfweyzVg1s9pLTQcaJjPcuOAUeKKOV2vX7c/3W5bPIa8htIXfBJq/VwMqv5ejm+ZBsOC8X3ptXg6D3cTFJhx60Dsi8UyiLcSvBTwFtjV2lMEzMEcsQfNQS6ES/CAHuKF50FaohHIeQ8wAkutGZXhRCnrraN/4o00imWbqgQAgCAoRk+C1BH4lmaNIYACiEAhub16ah0lkW6XocZRXjMCNzZ4aOyQPWo/jalzpgYbeoFxxacdgmVILXYuO1BPHcIdMPfEAgZoNdlpCGteBiKWaY3L4hpNKkTpBsiFeOKl8s7Xhca1Zqjq1Xa5i6ZXzuWFQMY02lyXoi0tI53Dw/w9ZjYAb3VB/hCBAAAAAAAgH/8Ah3f3c5J52vwAAAAAElFTkSuQmCC"; + +var img$7 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZHNK0RRGMZ/M4gYUSwk6S6GKFOiZKlRZoPFGGWwuffOnRk1M273zqTJVtlYTFmIja+F/4CtsqWUIiXZ+Ad8bTRd7zFqJHNu576/nnOet3OeA/7pjJl164chm8s70UhYW4gvao3P1NNDO4P06qZrz8xNxag5Pm7xqXoTUr1q7/t3tCQs1wRfk/CYaTt54Qnh6bW8rXhLuNNM6wnhA+EhRw4ofKl0o8JPilMVflPsxKKT4Fc9tdQvNn6xmXaywgPCwWymYP6cR90kYOXm56R2y+zBJUqEMBoGBVbIkCckNSeZ/e8b/vbNsioeU/42RRxxpEiLd0jUgnS1pCZFt+TLUFS5/83TTY6OVLoHwtDw6HmvfdC4DeWS530eel75COoe4DxX9a9KTuPvopeqWnAf2jbg9KKqGTtwtgld97bu6N9SnUx/MgkvJ9Aah45raF6qZPWzzvEdxNblia5gdw/6ZX/b8hco4WgdZKtgqgAAAAlwSFlzAAALEwAACxMBAJqcGAAAAgVJREFUeNrtWwtuwyAMxREnWLn/Cdt1B1hDSzemyoNiKFADthSpSiDhPX/5FFREjDHB+7u1iqtsANFnx+MxeB+owEcnIEYEUIHPQgAmwvfgi6qt3ClbFfyP1ajFZXkCNCUz1BYccGMpqpHYFAGshJqdQvJ9uaiv8/nf+zzh7rduOYAa2g2l3X3f1bZt0bTn+7g2KUx6ZP+tUZNobBJYYykNvmohuYWOAx3TbHEQ7AkiVz5Pp6fPPw6Hl6wGbi+w6IOULMC1eEqOHeMtsSXOlWP22KQSbGFmnF2AUglSojz5Q6EsUloJPgt4PljiNqkgOowLUMBPOxlqBX4IAlqCHzoL1AAvhZCzAMdkJptTFUK+0/3C7KTaM70oFvB3hRZFp3YBVWlFiHM1KHMBIUAIEALqzQbfnAmAqwX0SoNWXIApAb3qAOAcA2BlC5A0OA0BjysuubssIwrGqFcBHiNBL2fyaEsdjDG28wkNNuL2J+SU2PJZ4GYGsCp4hx1Ce38MY0LJumXQ58UFMAGU3dtMTVmm5h60dJ3qkOEOFv0GrsCDvpSj9ceDRr+7SrbxbDEaA3AVSz0y7xVbFAPQdlpr8H0XHDJPb/QCX80CMB4da0BwiaE0T/7PUKFG3m65PUvhqeYOyxdCI7oAcHnZ0Omv1oCHJ6HGYOcqhFYjYWNG5PDCdjosEpEraP7o1MFLlvgAAAAASUVORK5CYII="; + +var img$6 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZHNK0RRGMZ/M4gYUSwk6S6GKFOiZKlRZoPFGGWwuffOnRk1M273zqTJVtlYTFmIja+F/4CtsqWUIiXZ+Ad8bTRd7zFqJHNu576/nnOet3OeA/7pjJl164chm8s70UhYW4gvao3P1NNDO4P06qZrz8xNxag5Pm7xqXoTUr1q7/t3tCQs1wRfk/CYaTt54Qnh6bW8rXhLuNNM6wnhA+EhRw4ofKl0o8JPilMVflPsxKKT4Fc9tdQvNn6xmXaywgPCwWymYP6cR90kYOXm56R2y+zBJUqEMBoGBVbIkCckNSeZ/e8b/vbNsioeU/42RRxxpEiLd0jUgnS1pCZFt+TLUFS5/83TTY6OVLoHwtDw6HmvfdC4DeWS530eel75COoe4DxX9a9KTuPvopeqWnAf2jbg9KKqGTtwtgld97bu6N9SnUx/MgkvJ9Aah45raF6qZPWzzvEdxNblia5gdw/6ZX/b8hco4WgdZKtgqgAAAAlwSFlzAAALEwAACxMBAJqcGAAAALNJREFUeNrt2zEOgCAMAEAw/v/L1Qc4FSWNvSaORLjS6gBjiN4x7yc6Axzdd0B7gDMzKCJmyXqeMz7fAVUXn52bHgBAE9zffJ5qNdPA3uhHSiCZ7VjJ3FefvcxczuSLR5Vf6NUEKAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPDj2HJlJnOkddcBzKPi4lfGKQEAxQCytbyrB7g3qAQACNE5LgqdKICszpBUAAAAAElFTkSuQmCC"; + +var img$5 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZE7SwNBFIW/JMaIRlJoISKaQsVCQRTEUiKYRi1iBF9Ndt0kwiYuuwkitoKNhWAh2vgq/AfaCrYKgqAIIjb+AV+NhPVOVkiQOMvs/Tgz5zJzBvyTpp5z6gYhly/YiXgsOje/EA29EqSeEJ10pXTHmpqZSPLv+LrHp+rdgOr1/76ao2nZcHTwNQiP6JZdEB4TnlwrWIq3hVv1bGpZ+Ei435YDCl8rXfP4RXHG4w/FdjIxDn7VM5qpYq2K9aydE+4T7s6ZRf33POomYSM/OyO1XWYHDgnixIiiUWQFkwIDUvOSWW3fYNk3zap4dPlbrGOLI0NWvP2iFqWrITUtuiGfybrK/W+eTnp4yOsejkHw2XXfeyC0C6Ud1/0+dt3SCQSe4DJf8a9KTqOfou9UtO5DiGzC+VVF0/bgYgvaHq2UnSpLAZn+dBrezqB5HlpuoXHRy+p3ndMHSG7IE93A/gH0yv7I0g/RtGf1H+H7WwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAPxJREFUeNrtmm0OgyAQRB3TE1Tvf1WaNmlCE4NCW77mkfDHRbP7nF1AXBbzpsL7wizxaKLgi2Ja3VMAAO4Abo2KT+ilHtkpYN/3V/8GgH40lf5DeaqlAEW9h2kv25e3CpgFnIN/qgAFAAAAbIdbtNCLL6QAANgNerX7tlEESQEAAAAAAAAAADwBsBAiBQAAAAAAAAAAAAAAAAAAAAAAAACwOxmKf5FDAQColwKhYEyVT2TqJPhm/lED3AGooxrQyje/dUC8FtDFt6YJ7UnD2cnN6PbL5I7Gj25PXggGZUA5spkeggyD/4h9zZHLhPYkAJ08ZHR7sgbMOO8f2h90sy2pSZTVdgAAAABJRU5ErkJggg=="; + +var img$4 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZHNK0RRGMZ/M4gYUSwk6S6GKFOiZKlRZoPFGGWwuffOnRk1M273zqTJVtlYTFmIja+F/4CtsqWUIiXZ+Ad8bTRd7zFqJHNu576/nnOet3OeA/7pjJl164chm8s70UhYW4gvao3P1NNDO4P06qZrz8xNxag5Pm7xqXoTUr1q7/t3tCQs1wRfk/CYaTt54Qnh6bW8rXhLuNNM6wnhA+EhRw4ofKl0o8JPilMVflPsxKKT4Fc9tdQvNn6xmXaywgPCwWymYP6cR90kYOXm56R2y+zBJUqEMBoGBVbIkCckNSeZ/e8b/vbNsioeU/42RRxxpEiLd0jUgnS1pCZFt+TLUFS5/83TTY6OVLoHwtDw6HmvfdC4DeWS530eel75COoe4DxX9a9KTuPvopeqWnAf2jbg9KKqGTtwtgld97bu6N9SnUx/MgkvJ9Aah45raF6qZPWzzvEdxNblia5gdw/6ZX/b8hco4WgdZKtgqgAAAAlwSFlzAAALEwAACxMBAJqcGAAAAMpJREFUeNrtmksKgDAMBY30BNr7n7B3iCgo4kbwl+CbAZdCM77E+uk6AABh7OJ5/pd67EfFX6qpV4t8rXU5ZAXIJ2CfhJkSNHw8yzySboE5Bf0DV9sCa7i9lvJR5DPuZWgBBARG2bOshRZAgDhFreBhHBmCtAACEIAABABocrYRciEXdhTggoEwboPqAuRnAAAzIAReiHAbRAACEIAABMQj92Vo/4scCUAAAngWoAVogbjIp1ibJS3+tfWt+4DWGi0gmQBmAAAAwMYEsvUT/L18rywAAAAASUVORK5CYII="; + +var img$3 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABb2lDQ1BpY2MAACiRdZHNK0RRGMZ/M4gYUSwk6S6GKFOiZKlRZoPFGGWwuffOnRk1M273zqTJVtlYTFmIja+F/4CtsqWUIiXZ+Ad8bTRd7zFqJHNu576/nnOet3OeA/7pjJl164chm8s70UhYW4gvao3P1NNDO4P06qZrz8xNxag5Pm7xqXoTUr1q7/t3tCQs1wRfk/CYaTt54Qnh6bW8rXhLuNNM6wnhA+EhRw4ofKl0o8JPilMVflPsxKKT4Fc9tdQvNn6xmXaywgPCwWymYP6cR90kYOXm56R2y+zBJUqEMBoGBVbIkCckNSeZ/e8b/vbNsioeU/42RRxxpEiLd0jUgnS1pCZFt+TLUFS5/83TTY6OVLoHwtDw6HmvfdC4DeWS530eel75COoe4DxX9a9KTuPvopeqWnAf2jbg9KKqGTtwtgld97bu6N9SnUx/MgkvJ9Aah45raF6qZPWzzvEdxNblia5gdw/6ZX/b8hco4WgdZKtgqgAAAAlwSFlzAAALEwAACxMBAJqcGAAAANNJREFUeNrt2tEKwyAMhWEz9gSr7/+qjg0GvZ3dVMwX8K6F5OfkRFtLSR7R+V7bpZ7YqPiumm7ZWwCA7ADuk8ynreJH6RRQa32vKwDiR6P0H8qLUQqI01ph7H2dy0cFpkDm4l8qoAAAAHAcnhFtlVy0AABOg7nicRxMUAsAAAAAAAAAQE4ANkJaAAAAAAAAAAAAAAAAAAAAAAAA0v0ZOl+RowAAxrVA63hmyCeyWKT4afnxgOwAYiEPmJVbvn3A1evyQmxogi1r/ZG4eCYIAA+w2SpPUykQkfN9GyAAAAAASUVORK5CYII="; + +class Icons { +} +Icons.icon_arrow = img$J; +Icons.icon_arrow_up = img$I; +Icons.icon_arrow_down = img$H; +Icons.icon_arrow_left = img$G; +Icons.icon_arrow_right = img$F; +Icons.icon_back = img$E; +Icons.icon_caret = img$D; +Icons.icon_circle = img$C; +Icons.icon_clockwise = img$B; +Icons.icon_counter_clockwise = img$z; +Icons.icon_compare = img$A; +Icons.icon_close = img$y; +Icons.icon_close2 = img$x; +Icons.icon_cloudy = img$w; +Icons.icon_delete = img$v; +Icons.icon_download = img$u; +Icons.icon_fit_page = img$t; +Icons.icon_fit_viewer = img$s; +Icons.icon_geometric = img$r; +Icons.icon_hand = img$q; +Icons.icon_line = img$p; +Icons.icon_load = img$o; +Icons.icon_minus = img$n; +Icons.icon_ok = img$m; +Icons.icon_pen = img$l; +Icons.icon_plus = img$k; +Icons.icon_pointer = img$j; +Icons.icon_polygon = img$i; +Icons.icon_polyline = img$h; +Icons.icon_popup = img$g; +Icons.icon_popup2 = img$f; +Icons.icon_sidebar = img$e; +Icons.icon_square = img$d; +Icons.icon_stamp = img$c; +Icons.icon_straight = img$b; +Icons.icon_text = img$a; +Icons.icon_text2 = img$9; +Icons.icon_text_free = img$8; +Icons.icon_text_callout = img$7; +Icons.icon_text_highlight = img$6; +Icons.icon_text_squiggly = img$5; +Icons.icon_text_strikeout = img$4; +Icons.icon_text_underline = img$3; +Icons.geometricIcons = { + square: ``, + circle: ``, + line: ``, + arrow: ``, + polyline: ``, + polygon: ``, +}; +Icons.textIcons = { + note: ``, + freeText: ``, + freeTextCallout: ``, + strikeout: ``, + squiggly: ``, + underline: ``, + highlight: ``, +}; +Icons.lineTypeIcons = { + straight: ``, + cloudy: ``, +}; +Icons.editIcons = { + close: ``, + ok: ``, + back: ``, + delete: ``, +}; + +function getCommonStyles(appName) { + return ` + :host { + --${appName}-color-primary-final: var(--${appName}-color-primary, rgba(40,40,40,1)); + --${appName}-color-primary-tr-final: var(--${appName}-color-primary-tr, rgba(40,40,40,0.9)); + --${appName}-color-secondary-final: var(--${appName}-color-secondary, rgba(60,60,60,1)); + --${appName}-color-secondary-tr-final: var(--${appName}-color-secondary-tr, rgba(60,60,60,0.9)); + --${appName}-color-accent-final: var(--${appName}-color-accent, rgba(96,96,96,1)); + --${appName}-color-shadow-final: var(--${appName}-color-shadow, rgba(0,0,0,0.75)); + --${appName}-color-bg-final: var(--${appName}-color-bg, rgba(128,128,128,1)); + --${appName}-color-fg-primary-final: var(--${appName}-color-fg-primary, rgba(255,255,255,1)); + --${appName}-color-fg-secondary-final: var(--${appName}-color-fg-secondary, rgba(187,187,187,1)); + --${appName}-color-fg-accent-final: var(--${appName}-color-fg-accent, rgba(255,204,0,1)); + --${appName}-color-text-selection-final: var(--${appName}-color-text-selection, rgba(104,104,128,0.3)); + } + + .disabled { + pointer-events: none !important; + } + + .relative { + position: relative; + } + .absolute { + position: absolute; + } + .abs-hidden { + position: absolute; + opacity: 0; + z-index: -10; + } + .abs-stretch { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + } + .abs-topleft { + position: absolute; + left: 0; + top: 0; + } + .stretch { + width: 100%; + height: 100%; + } + + .no-margin { + margin: 0; + } + .no-padding { + padding: 0; + } + .margin-s-5 { + margin: 0 5px; + } + + .line-clamp { + display: -webkit-box; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + overflow: hidden; + } + + #main-container { + box-sizing: border-box; + position: relative; + display: flex; + flex-direction: column; + justify-content: stretch; + align-items: stretch; + width: 100%; + height: 100%; + background: var(--${appName}-color-bg-final); + } + + #top-panel { + position: relative; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + flex-shrink: 0; + width: 100%; + height: 50px; + background: var(--${appName}-color-primary-final); + box-shadow: 0 0 10px var(--${appName}-color-shadow-final); + z-index: 4; + transition: height 0.25s ease-out 0.1s; + } + .hide-panels #top-panel { + height: 0; + transition: height 0.25s ease-in 0.2s; + } + + #bottom-panel { + position: absolute; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + flex-grow: 0; + flex-shrink: 0; + bottom: 20px; + height: 50px; + background: var(--${appName}-color-primary-tr-final); + box-shadow: 0 0 10px var(--${appName}-color-shadow-final); + z-index: 4; + transition: height 0.25s ease-out, bottom 0.1s linear 0.25s; + } + .hide-panels #bottom-panel { + bottom: 0; + height: 0; + transition: bottom 0.1s linear 0.1s, height 0.25s ease-in 0.2s; + } + .compact #zoom-fit-viewer, + .compact #zoom-fit-page { + width: 0; + transform: scale(0); + } + + #focused-annotation-panel { + box-sizing: border-box; + position: absolute; + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: stretch; + flex-grow: 0; + flex-shrink: 0; + left: calc(50% - 120px); + top: 80px; + width: 240px; + height: 84px; + padding: 18px; + border-radius: 18px; + background: var(--${appName}-color-secondary-tr-final); + box-shadow: 0 0 10px var(--${appName}-color-shadow-final); + opacity: 0; + transform: scale(0); + transition: opacity 0.1s ease-in, transform 0s linear 0.1s; + z-index: 4; + pointer-events: none; + } + .mobile #focused-annotation-panel { + left: 20px; + width: 150px; + } + .annotation-focused #focused-annotation-panel { + opacity: 100; + transform: scale(1); + transition: opacity 0.1s ease-out 0.35s, transform 0s linear 0.35s; + } + #focused-annotation-panel p { + margin: 0; + padding: 0; + line-height: 16px; + font-size: 12px; + font-family: sans-serif; + color: var(--${appName}-color-fg-primary-final); + } + + #annotation-panel, + #command-panel { + position: absolute; + display: flex; + flex-direction: column; + justify-content: center; + align-items: flex-end; + flex-grow: 1; + flex-shrink: 1; + right: 20px; + pointer-events: none; + } + #annotation-panel { + top: 125px; + z-index: -5; + transition: z-index 0s linear 0.25s; + } + #command-panel { + top: 80px; + z-index: 5; + } + .mode-annotation #annotation-panel { + z-index: 5; + } + + .annotation-panel-row, + .command-panel-row { + display: flex; + flex-direction: row; + justify-content: flex-end; + align-items: center; + flex-grow: 1; + flex-shrink: 1; + } + + .annotation-panel-item { + margin: 3px; + cursor: default; + opacity: 0; + background: var(--${appName}-color-primary-tr-final); + box-shadow: 0 0 10px var(--${appName}-color-shadow-final); + transform: scale(0); + transition: opacity 0.1s ease-in, transform 0s linear 0.1s; + pointer-events: all; + } + .mode-annotation .annotation-panel-item { + cursor: pointer; + opacity: 100; + transform: scale(1); + transition: opacity 0.1s ease-out 0.35s, transform 0s linear 0.35s; + } + + .annotation-panel-subitem, + .command-panel-subitem { + margin: 3px; + background: var(--${appName}-color-secondary-tr-final); + box-shadow: 0 0 10px var(--${appName}-color-shadow-final); + pointer-events: all; + } + .command-panel-subitem.accent:hover, + .command-panel-subitem.accent.on { + box-shadow: 0 0 10px var(--${appName}-color-fg-accent-final); + } + :not(.mode-annotation):not(.undoable-commands) #button-command-undo, + :not(.annotation-selected) #button-annotation-edit-text, + :not(.annotation-selected) #button-annotation-delete, + :not(.stamp-annotator-data-undoable) #button-annotation-stamp-undo, + :not(.stamp-annotator-data-clearable) #button-annotation-stamp-clear, + :not(.stamp-annotator-data-saveable) #button-annotation-stamp-save, + :not(.pen-annotator-data-undoable) #button-annotation-pen-undo, + :not(.pen-annotator-data-clearable) #button-annotation-pen-clear, + :not(.pen-annotator-data-saveable) #button-annotation-pen-save, + :not(.text-annotator-data-undoable) #button-annotation-text-undo, + :not(.text-annotator-data-clearable) #button-annotation-text-clear, + :not(.text-annotator-data-saveable) #button-annotation-text-save, + :not(.geom-annotator-data-undoable) #button-annotation-geometric-undo, + :not(.geom-annotator-data-clearable) #button-annotation-geometric-clear, + :not(.geom-annotator-data-saveable) #button-annotation-geometric-save { + cursor: default; + opacity: 0; + transform: scale(0); + transition: opacity 0.1s ease-in, transform 0s linear 0.1s; + } + .mode-annotation.undoable-commands #button-command-undo, + .annotation-selected #button-annotation-edit-text, + .annotation-selected #button-annotation-delete, + .stamp-annotator-data-undoable #button-annotation-stamp-undo, + .stamp-annotator-data-clearable #button-annotation-stamp-clear, + .stamp-annotator-data-saveable #button-annotation-stamp-save, + .pen-annotator-data-undoable #button-annotation-pen-undo, + .pen-annotator-data-clearable #button-annotation-pen-clear, + .pen-annotator-data-saveable #button-annotation-pen-save, + .text-annotator-data-undoable #button-annotation-text-undo, + .text-annotator-data-clearable #button-annotation-text-clear, + .text-annotator-data-saveable #button-annotation-text-save, + .geom-annotator-data-undoable #button-annotation-geometric-undo, + .geom-annotator-data-clearable #button-annotation-geometric-clear, + .geom-annotator-data-saveable #button-annotation-geometric-save { + cursor: pointer; + opacity: 100; + transform: scale(1); + transition: opacity 0.1s ease-out 0.35s, transform 0s linear 0.35s; + } + + .panel-v-separator { + width: 1px; + height: 30px; + background-color: var(--${appName}-color-fg-secondary-final); + } + + .panel-button { + cursor: pointer; + user-select: none; + display: flex; + flex-direction: column; + flex-shrink: 0; + flex-grow: 0; + justify-content: center; + align-items: center; + width: 36px; + height: 36px; + border-radius: 50%; + } + .panel-button:hover, + .panel-button.on { + background-color: var(--${appName}-color-accent-final); + } + .panel-button.accent, + .panel-button.accent:hover, + .panel-button.accent.on { + background-color: var(--${appName}-color-fg-accent-final); + } + .panel-button img { + width: 20px; + height: 20px; + filter: invert() opacity(0.7) drop-shadow(0 0 0 var(--${appName}-color-fg-primary-final)) saturate(1000%); + } + .panel-button:hover img, + .panel-button.on img { + filter: invert() opacity(0.7) drop-shadow(0 0 0 var(--${appName}-color-fg-accent-final)) saturate(1000%); + } + .panel-button.accent img, + .panel-button.accent:hover img, + .panel-button.accent.on img { + filter: opacity(0.7) drop-shadow(0 0 0 var(--${appName}-color-primary-final)) saturate(1000%); + } + .disabled .panel-button img, + .panel-button.disabled img { + filter: invert() opacity(0.2) drop-shadow(0 0 0 var(--${appName}-color-fg-primary-final)) saturate(1000%); + } + .context-menu-content .panel-button { + margin: 1px; + } + + .subpanel { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + margin: 0 4px; + } + + .panel-item { + transform: scale(1); + transition: opacity 0.1s ease-out 0.35s, transform 0s linear 0.35s; + } + .hide-panels .panel-item { + cursor: default; + opacity: 0; + transform: scale(0); + transition: opacity 0.1s ease-in, transform 0s linear 0.1s; + } + + #paginator { + user-select: none; + font-family: sans-serif; + font-size: 16px; + color: var(--${appName}-color-fg-primary-final); + } + + #toggle-previewer { + margin: 4px; + } + + #previewer { + box-sizing: border-box; + position: absolute; + display: flex; + flex-direction: column; + justify-content: flex-start; + overflow-x: hidden; + overflow-y: auto; + left: 0; + top: 50px; + bottom: 0; + width: 160px; + padding-top: 0px; + background: var(--${appName}-color-secondary-final); + box-shadow: 0 0 10px var(--${appName}-color-shadow-final); + z-index: 3; + transition: padding-top 0.25s ease-out 0.1s, top 0.25s ease-out 0.1s, width 0.25s ease-out; + } + .hide-panels #previewer { + top: 0; + padding-top: 50px; + transition: padding-top 0.25s ease-in 0.2s, top 0.25s ease-in 0.2s; + } + .mobile #previewer { + background: var(--${appName}-color-secondary-tr-final); + } + .hide-previewer #previewer { + width: 0; + transition: width 0.25s ease-in 0.1s; + } + #previewer .page-preview { + transform: scaleX(1); + transition: opacity 0.1s ease-out 0.35s, transform 0s linear 0.35s; + } + .hide-previewer #previewer .page-preview { + opacity: 0; + transform: scaleX(0); + transition: opacity 0.1s ease-in, transform 0s linear 0.1s; + } + + #viewer { + box-sizing: border-box; + position: absolute; + display: flex; + flex-direction: column; + overflow: auto; + left: 160px; + right: 0; + top: 50px; + bottom: 0; + padding-top: 0; + transition: padding-top 0.25s ease-out 0.1s, top 0.25s ease-out 0.1s, left 0.25s ease-out; + } + #viewer.dialog-shown { + overflow: hidden; + } + .mode-hand #viewer { + cursor: grab !important; + user-select: none !important; + } + .hide-panels #viewer { + top: 0; + padding-top: 50px; + transition: padding-top 0.25s ease-in 0.2s, top 0.25s ease-in 0.2s; + } + .hide-panels.mobile #viewer, + .hide-panels.hide-previewer #viewer { + top: 0; + padding-top: 50px; + left: 0; + transition: padding-top 0.25s ease-in 0.2s, top 0.25s ease-in 0.2s, left 0.25s ease-in; + } + .mobile #viewer, + .hide-previewer #viewer { + top: 50px; + padding-top: 0px; + left: 0; + transition: padding-top 0.25s ease-out 0.1s, top 0.25s ease-out 0.1s, left 0.25s ease-in; + } + + #annotation-overlay-container { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + margin-top: 0; + transition: margin-top 0.25s ease-out 0.1s; + z-index: 3; + } + .hide-panels #annotation-overlay-container { + margin-top: 50px; + transition: margin-top 0.25s ease-in 0.2s; + } + .mode-text-markup #annotation-overlay-container { + pointer-events: none; + } + + #annotation-overlay { + position: absolute; + margin: 0; + padding: 0; + width: 100%; + height: 100%; + touch-action: none; + } + + .page-container { + position: relative; + display: flex; + flex-grow: 0; + flex-shrink: 0; + background-color: white; + box-shadow: 0 0 10px var(--${appName}-color-shadow-final); + } + .page { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + transform-origin: left top; + } + .page-preview { + cursor: pointer; + position: relative; + display: flex; + flex-grow: 0; + flex-shrink: 0; + margin: 0 auto; + background-color: white; + background-clip: content-box; + border-style: solid; + border-width: 10px 10px 20px 10px; + border-color: transparent; + } + .page-preview:hover, + .page-preview.current { + border-color: var(--${appName}-color-accent-final); + } + .page-preview::after { + display: inline-block; + position: absolute; + top: calc(100% + 3px); + width: 100%; + text-align: center; + font-family: sans-serif; + font-size: 14px; + line-height: 1; + color: var(--${appName}-color-fg-primary-final); + content: attr(data-page-number) " "; + } + + .page-canvas { + background-color: white; + } + + .page-annotations { + width: 0; + height: 0; + } + .mode-text-markup .page-annotations, + .mode-text .page-annotations, + .mode-hand .page-annotations { + pointer-events: none; + } + .page-annotations-controls, + .annotation-content, + .annotation-content-element { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + } + .page-annotations-controls { + z-index: 2; + } + .annotation-content { + pointer-events: none; + } + + .abs-full-size-overlay { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + background: var(--${appName}-color-secondary-tr-final); + touch-action: none; + } + + .fixed-full-size-overlay { + position: fixed; + left: 0; + top: 0; + width: 100%; + height: 100%; + background: var(--${appName}-color-secondary-tr-final); + } + + .text-dialog { + z-index: 9; + } + .text-dialog .form { + box-sizing: border-box; + position: absolute; + display: flex; + flex-direction: column; + justify-content: stretch; + align-items: stretch; + flex-grow: 0; + flex-shrink: 0; + left: calc(50% - 160px); + top: calc(50% - 120px); + width: 320px; + height: 240px; + padding: 5px; + background: var(--${appName}-color-primary-tr-final); + box-shadow: 0 0 10px var(--${appName}-color-shadow-final); + } + .text-dialog textarea { + height: 100%; + margin: 0 0 5px 0; + padding: 5px; + font-size: 14px; + resize: none; + outline: none; + border: none; + color: var(--${appName}-color-fg-primary-final); + background-color: var(--${appName}-color-primary-final); + } + .text-dialog textarea::placeholder { + font-size: 14px; + font-style: italic; + color: var(--${appName}-color-fg-primary-final); + } + .text-dialog .buttons { + display: flex; + flex-direction: row; + justify-content: flex-end; + align-items: center; + flex-grow: 1; + flex-shrink: 1; + } + + .stamp-dialog { + z-index: 9; + } + .stamp-dialog .form { + position: absolute; + display: flex; + flex-direction: column; + justify-content: stretch; + align-items: stretch; + flex-grow: 0; + flex-shrink: 0; + left: 50%; + top: 50%; + width: 100%; + height: 100%; + max-width: 720px; + max-height: 720px; + background: var(--${appName}-color-primary-tr-final); + box-shadow: 0 0 10px var(--${appName}-color-shadow-final); + transform-origin: center; + transform: translate(-50%, -50%) + } + .stamp-dialog .buttons { + display: flex; + flex-direction: row; + justify-content: flex-end; + align-items: center; + height: 40px; + } + .stamp-dialog .form-canvas-wrapper { + position: relative; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + margin: 20px; + flex-grow: 1; + flex-shrink: 1; + } + .stamp-dialog input { + width: 100%; + margin: 10px; + padding: 5px; + font-size: 16px; + outline: none; + border: none; + color: var(--${appName}-color-fg-primary-final); + background-color: var(--${appName}-color-primary-final); + } + .stamp-dialog input::placeholder { + font-size: 14px; + font-style: italic; + color: var(--${appName}-color-fg-primary-final); + } + .stamp-input-row { + display: flex; + flex-direction: row; + justify-content: stretch; + align-items: center; + height: 30px; + margin: 10px; + } + .stamp-input-row p { + user-select: none; + margin: 0; + padding: 0 10px; + font-family: sans-serif; + font-size: 16px; + white-space: nowrap; + color: var(--${appName}-color-fg-secondary-final); + } + + .abs-ratio-canvas { + outline: 0; + position: absolute; + width: 100%; + height: auto; + max-height: 100%; + border: 2px solid var(--${appName}-color-fg-secondary-final); + } + + .annotation-temp-copy { + opacity: 0.2; + } + .annotation-controls { + cursor: pointer; + } + .annotation-out-of-page { + cursor: not-allowed; + } + .annotation-rect, + .annotation-bbox { + fill: none; + } + .mode-annotation .annotation-controls.selected { + cursor: grab; + } + .mode-annotation .annotation-controls.selected .annotation-rect { + vector-effect: non-scaling-stroke; + stroke: rgba(80, 80, 80, 0.5); + stroke-dasharray: 3 3; + } + .mode-annotation .annotation-controls.selected .annotation-bbox { + vector-effect: non-scaling-stroke; + stroke: rgba(80, 80, 80, 1); + stroke-dasharray: 3 3; + } + .mode-annotation .annotation-controls.focused .annotation-bbox { + vector-effect: non-scaling-stroke; + stroke: rgba(255, 165, 0, 1); + stroke-dasharray: 3 0; + } + .mode-annotation .annotation-controls.selected .annotation-handle { + stroke-width: 16; + stroke-linecap: round; + vector-effect: non-scaling-stroke; + cursor: pointer; + } + .mode-annotation .annotation-controls.selected .annotation-handle.helper { + stroke-width: 12; + stroke: rgba(200, 200, 50, 0.75); + } + .mode-annotation .annotation-controls.selected .annotation-handle.scale { + stroke: rgba(0, 0, 0, 0.75); + } + .mode-annotation .annotation-controls.selected .annotation-handle.rotation { + stroke: rgba(50, 100, 50, 0.75); + } + .mode-annotation .annotation-controls.selected .annotation-handle.translation { + stroke: rgba(100, 100, 200, 0.75); + } + .mode-annotation .annotation-controls.selected .annotation-rotator { + fill: none; + cursor: pointer; + vector-effect: non-scaling-stroke; + } + .mode-annotation .annotation-controls.selected .annotation-rotator .circle { + r: 25; + } + .mode-annotation .annotation-controls.selected .annotation-rotator .dashed { + stroke: rgba(80, 80, 80, 1); + stroke-dasharray: 3 3; + } + + #context-menu { + box-sizing: border-box; + position: absolute; + z-index: 5; + min-width: 50px; + min-height: 50px; + max-height: 300px; + padding: 5px; + background: var(--${appName}-color-secondary-tr-final); + box-shadow: 0 0 10px var(--${appName}-color-shadow-final); + display: flex; + flex-direction: column; + justify-content: stretch; + align-items: stretch; + overflow-y: auto; + } + .context-menu-content { + display: flex; + justify-content: center; + align-items: center; + flex-grow: 1; + flex-shrink: 0; + } + .context-menu-content.row { + flex-direction: row; + } + .context-menu-content.column { + flex-direction: column; + } + .context-menu-color-icon { + width: 20px; + height: 20px; + border-radius: 12px; + border-width: 2px; + border-style: solid; + border-color: var(--${appName}-color-fg-secondary-final); + } + .context-menu-stamp-select-button { + box-sizing: border-box; + cursor: pointer; + user-select: none; + display: flex; + flex-direction: column; + justify-content: center; + align-items: flex-start; + width: 100%; + height: 36px; + padding: 0 5px; + border-radius: 5px; + font-family: sans-serif; + font-size: 16px; + color: var(--${appName}-color-fg-primary-final); + } + .context-menu-stamp-select-button:hover, + .context-menu-stamp-select-button.on { + background-color: var(--${appName}-color-accent-final); + } + .context-menu-slider { + -webkit-appearance: none; + appearance: none; + outline: none; + margin: 10px; + height: 5px; + border-radius: 5px; + cursor: pointer; + background-color: var(--${appName}-color-fg-secondary-final); + } + .context-menu-slider::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + outline: none; + width: 20px; + height: 20px; + border-radius: 10px; + cursor: pointer; + background-color: var(--${appName}-color-accent-final); + } + .context-menu-slider::-moz-range-thumb { + outline: none; + width: 20px; + height: 20px; + border-radius: 10px; + cursor: pointer; + background-color: var(--${appName}-color-accent-final); + } + + #button-open-file { + pointer-events: auto !important; + } + .disabled #button-open-file img { + filter: invert() opacity(0.7) drop-shadow(0 0 0 var(--${appName}-color-fg-primary-final)) saturate(1000%); + } + + .spinner { + position: absolute; + left: calc(50% - 30px); + top: calc(50% - 30px); + width: 60px; + height: 60px; + } + .spinner div { + position: absolute; + width: 20px; + height: 20px; + margin: 5px; + border-radius: 5px; + animation-duration: 3s; + animation-timing-function: linear; + animation-iteration-count: infinite; + } + .spinner div:nth-child(1) { + animation-name: spinnerone; + background-color: var(--${appName}-color-accent-final); + } + .spinner div:nth-child(2) { + animation-name: spinnertwo; + background-color: var(--${appName}-color-fg-primary-final); + } + .spinner div:nth-child(3) { + animation-name: spinnerthree; + background-color: var(--${appName}-color-fg-secondary-final); + } + + @keyframes spinnerone { + from { + left: 0; + top: 0; + } + 8.3% { + left: 0; + top: 0; + } + 16.7% { + left: 0; + top: 0; + } + 25% { + left: 30px; + top: 0px; + } + 33.3% { + left: 30px; + top: 0px; + } + 41.7% { + left: 30px; + top: 0px; + } + 50% { + left: 30px; + top: 30px; + } + 58.3% { + left: 30px; + top: 30px; + } + 66.7% { + left: 30px; + top: 30px; + } + 75% { + left: 0; + top: 30px; + } + 83.3% { + left: 0; + top: 30px; + } + 91.7% { + left: 0; + top: 30px; + } + to { + left: 0; + top: 0; + } + } + @keyframes spinnertwo { + from { + left: 30px; + top: 0px; + } + 8.3% { + left: 30px; + top: 0px; + } + 16.7% { + left: 30px; + top: 30px; + } + 25% { + left: 30px; + top: 30px; + } + 33.3% { + left: 30px; + top: 30px; + } + 41.7% { + left: 0; + top: 30px; + } + 50% { + left: 0; + top: 30px; + } + 58.3% { + left: 0; + top: 30px; + } + 66.7% { + left: 0; + top: 0; + } + 75% { + left: 0; + top: 0; + } + 83.3% { + left: 0; + top: 0; + } + 91.7% { + left: 30px; + top: 0px; + } + to { + left: 30px; + top: 0px; + } + } + @keyframes spinnerthree { + from { + left: 30px; + top: 30px; + } + 8.3% { + left: 0; + top: 30px; + } + 16.7% { + left: 0; + top: 30px; + } + 25% { + left: 0; + top: 30px; + } + 33.3% { + left: 0; + top: 0; + } + 41.7% { + left: 0; + top: 0; + } + 50% { + left: 0; + top: 0; + } + 58.3% { + left: 30px; + top: 0; + } + 66.7% { + left: 30px; + top: 0; + } + 75% { + left: 30px; + top: 0; + } + 83.3% { + left: 30px; + top: 30px; + } + 91.7% { + left: 30px; + top: 30px; + } + to { + left: 30px; + top: 30px; + } + } + `; +} + +class ByteUtils { + static parseIntFromBytes(bytes) { + if (!(bytes === null || bytes === void 0 ? void 0 : bytes.length)) { + return 0; + } + if (bytes.length === 1) { + return bytes[0]; + } + const hex = Array.from(bytes, (byte) => ("0" + (byte & 0xFF).toString(16)).slice(-2)).join(""); + return parseInt(hex, 16); + } + static int8ToBytes(int) { + const buffer = new ArrayBuffer(1); + const view = new DataView(buffer); + view.setInt8(0, int); + return new Uint8Array(buffer); + } + static int16ToBytes(int, le = false) { + const buffer = new ArrayBuffer(2); + const view = new DataView(buffer); + view.setInt16(0, int, le); + return new Uint8Array(buffer); + } + static int32ToBytes(int, le = false) { + const buffer = new ArrayBuffer(4); + const view = new DataView(buffer); + view.setInt32(0, int, le); + return new Uint8Array(buffer); + } + static int32ArrayToBytes(ints, le = false) { + const buffer = new ArrayBuffer(ints.length * 4); + const view = new DataView(buffer); + for (let i = 0; i < ints.length; i++) { + view.setInt32(i * 4, ints[i], le); + } + return new Uint8Array(buffer); + } + static bytesToInt32Array(bytes, le = false) { + if (!(bytes === null || bytes === void 0 ? void 0 : bytes.length)) { + return null; + } + const buffer = new ArrayBuffer(Math.ceil(bytes.length / 4) * 4); + const view = new DataView(buffer); + for (let i = 0; i < bytes.length; i++) { + view.setUint8(i, bytes[i]); + } + const result = new Int32Array(buffer.byteLength / 4); + for (let j = 0; j < result.length; j++) { + result[j] = view.getInt32(j * 4, le); + } + return result; + } + static xorBytes(bytes, n) { + const result = new Uint8Array(bytes.length); + for (let i = 0; i < bytes.length; i++) { + result[i] = bytes[i] ^ n; + } + return result; + } + static arraysEqual(a, b) { + if (a.length !== b.length) { + return false; + } + for (let i = 0; i < a.length; i++) { + if (a[i] !== b[i]) { + return false; + } + } + return true; + } + static findSubarrayIndex(arr, sub) { + if ((arr === null || arr === void 0 ? void 0 : arr.length) && (sub === null || sub === void 0 ? void 0 : sub.length)) { + let j; + outer_loop: for (let i = 0; i <= arr.length; i++) { + let overlap = false; + for (j = 0; j < sub.length; j++) { + if (i + j < arr.length) { + if (arr[i + j] !== sub[j]) { + continue outer_loop; + } + overlap = true; + } + else if (overlap) { + return i; + } + else { + break outer_loop; + } + } + } + } + return -1; + } + static hexStringToBytes(hexString) { + const bytes = new Uint8Array(hexString.length / 2); + for (let i = 0, j = 0; i < hexString.length; i += 2, j++) { + bytes[j] = parseInt(hexString.substr(i, 2), 16); + } + return bytes; + } + static getBit(n, bitPosition) { + return (n & (1 << bitPosition)) === 0 ? 0 : 1; + } + static setBit(n, bitPosition) { + return n | (1 << bitPosition); + } + static clearBit(n, bitPosition) { + const mask = ~(1 << bitPosition); + return n & mask; + } + static updateBit(n, bitPosition, bitValue) { + const bitValueNormalized = bitValue ? 1 : 0; + const clearMask = ~(1 << bitPosition); + return (n & clearMask) | (bitValueNormalized << bitPosition); + } +} + +class ContextMenu { + constructor() { + this.onPointerDownOutside = (e) => { + if (!this._shown) { + return; + } + const target = e.composedPath()[0]; + if (!target.closest("#context-menu")) { + this.hide(); + } + }; + this._container = document.createElement("div"); + this._container.id = "context-menu"; + this.hide(); + document.addEventListener("pointerdown", this.onPointerDownOutside); + } + set content(value) { + var _a; + (_a = this._content) === null || _a === void 0 ? void 0 : _a.forEach(x => x.remove()); + if (value === null || value === void 0 ? void 0 : value.length) { + value.forEach(x => this._container.append(x)); + this._content = value; + } + else { + this._content = null; + } + } + get enabled() { + return this._enabled; + } + set enabled(value) { + this._enabled = !!value; + } + destroy() { + this.clear(); + document.removeEventListener("pointerdown", this.onPointerDownOutside); + } + show(pointerPosition, parent) { + parent.append(this._container); + this._shown = true; + setTimeout(() => { + this.setContextMenuPosition(pointerPosition, parent); + this._container.style.opacity = "1"; + }, 0); + } + hide() { + this._container.style.opacity = "0"; + this._container.remove(); + this._shown = false; + } + clear() { + this.hide(); + this.content = null; + } + setContextMenuPosition(pointerPosition, parent) { + const menuDimension = new u(this._container.offsetWidth, this._container.offsetHeight); + const menuPosition = new u(); + const parentRect = parent.getBoundingClientRect(); + const relPointerPosition = new u(pointerPosition.x - parentRect.x, pointerPosition.y - parentRect.y); + if (relPointerPosition.x + menuDimension.x > parentRect.width + parentRect.x) { + menuPosition.x = relPointerPosition.x - menuDimension.x; + } + else { + menuPosition.x = relPointerPosition.x; + } + if (relPointerPosition.y + menuDimension.y > parentRect.height + parentRect.y) { + menuPosition.y = relPointerPosition.y - menuDimension.y; + } + else { + menuPosition.y = relPointerPosition.y; + } + this._container.style.left = menuPosition.x + parent.scrollLeft + "px"; + this._container.style.top = menuPosition.y + parent.scrollTop + "px"; + } +} + +class SmoothPath { + constructor(options) { + this._paths = []; + this._positionBuffer = []; + this._bufferSize = (options === null || options === void 0 ? void 0 : options.bufferSize) || SmoothPath._defaultBufferSize; + this._id = options === null || options === void 0 ? void 0 : options.id; + this._uuid = options === null || options === void 0 ? void 0 : options.uuid; + } + get id() { + return this._id; + } + get uuid() { + return this._uuid; + } + get bufferSize() { + return this._bufferSize; + } + get paths() { + return this._paths.slice(); + } + get pathCount() { + return this._paths.length; + } + endPath() { + if (this._currentPath && this._currentPath.positions.length > 1) { + this._paths.push(this._currentPath); + } + this._positionBuffer = null; + this._currentPath = null; + this._currentPathString = null; + } + addPosition(pos) { + this.appendPositionToBuffer(pos); + this.updateCurrentPath(); + } + appendPositionToBuffer(pos) { + const buffer = this._positionBuffer; + buffer.push(pos); + this._positionBuffer = buffer + .slice(Math.max(0, buffer.length - this._bufferSize), buffer.length); + } + getAverageBufferPosition(offset) { + const len = this._positionBuffer.length; + if (len >= this._bufferSize) { + let totalX = 0; + let totalY = 0; + let pos; + let i; + let count = 0; + for (i = offset; i < len; i++) { + count++; + pos = this._positionBuffer[i]; + totalX += pos.x; + totalY += pos.y; + } + return new u(totalX / count, totalY / count); + } + return null; + } + updateCurrentPath() { + let pos = this.getAverageBufferPosition(0); + if (!pos) { + return null; + } + this._currentPathString += " L" + pos.x + " " + pos.y; + this._currentPath.positions.push(pos); + let tmpPath = ""; + for (let offset = 2; offset < this._positionBuffer.length; offset += 2) { + pos = this.getAverageBufferPosition(offset); + tmpPath += " L" + pos.x + " " + pos.y; + } + return tmpPath; + } +} +SmoothPath._defaultBufferSize = 8; + +class CanvasSmoothPathEditor extends SmoothPath { + constructor(container, options) { + super(options); + this._strokeWidth = CanvasSmoothPathEditor._defaultStrokeWidth; + this._color = CanvasSmoothPathEditor._colors[0]; + this._paths = []; + this.onContextMenu = (event) => { + if (this._contextMenu.enabled) { + event.preventDefault(); + this._contextMenu.show(new u(event.clientX, event.clientY), this._container); + } + }; + this.onPointerDown = (e) => { + if (!e.isPrimary || e.button === 2) { + return; + } + const { clientX: clX, clientY: clY } = e; + const [caX, caY] = this.convertClientCoordsToCanvas(clX, clY); + this.newPath(new u(caX, caY)); + const target = e.target; + target.addEventListener("pointermove", this.onPointerMove); + target.addEventListener("pointerup", this.onPointerUp); + target.addEventListener("pointerout", this.onPointerUp); + target.setPointerCapture(e.pointerId); + }; + this.onPointerMove = (e) => { + if (!e.isPrimary) { + return; + } + const { clientX: clX, clientY: clY } = e; + const [caX, caY] = this.convertClientCoordsToCanvas(clX, clY); + this.addPosition(new u(caX, caY)); + this.refreshEditor(); + }; + this.onPointerUp = (e) => { + if (!e.isPrimary) { + return; + } + const target = e.target; + target.removeEventListener("pointermove", this.onPointerMove); + target.removeEventListener("pointerup", this.onPointerUp); + target.removeEventListener("pointerout", this.onPointerUp); + target.releasePointerCapture(e.pointerId); + this.endPath(); + this.refreshEditor(); + }; + if (!container) { + throw new Error("Container is not defined"); + } + if (!(options === null || options === void 0 ? void 0 : options.canvasWidth) || !options.canvasHeight) { + throw new Error("Canvas dimensions is not defined"); + } + this._container = container; + this._canvas = document.createElement("canvas"); + this._canvas.classList.add("abs-ratio-canvas"); + this._canvas.width = options.canvasWidth; + this._canvas.height = options.canvasHeight; + this._canvas.addEventListener("pointerdown", this.onPointerDown); + this._contextMenu = new ContextMenu(); + this.fillContextMenu(); + this._container.append(this._canvas); + this._container.addEventListener("contextmenu", this.onContextMenu); + } + get canvas() { + return this._canvas; + } + get ctx() { + return this._canvas.getContext("2d"); + } + get canvasSize() { + return [this._canvas.width, this._canvas.height]; + } + set canvasSize(value) { + if (!value) { + return; + } + const [w, h] = value; + if (!w || !h) { + return; + } + if (w === this._canvas.width + && h === this._canvas.height) { + return; + } + this._canvas.width = w; + this._canvas.height = h; + this.refreshEditor(); + } + get paths() { + return this._paths.slice(); + } + destroy() { + this._canvas.remove(); + this._container.removeEventListener("contextmenu", this.onContextMenu); + this._contextMenu.destroy(); + } + getImageData() { + this.refreshEditor(); + const imgData = this.ctx.getImageData(0, 0, this._canvas.width, this._canvas.height).data; + return imgData; + } + newPath(startPosition) { + const pathString = "M" + startPosition.x + " " + startPosition.y; + const path2d = new Path2D(pathString); + this._positionBuffer = [startPosition]; + this._currentPath = { + strokeWidth: this._strokeWidth, + color: this._color, + path: path2d, + positions: [new u(startPosition.x, startPosition.y)], + }; + this._currentPathString = pathString; + } + removePath(path) { + if (!path) { + return; + } + this._paths = this._paths.filter(x => x.path !== path); + this.refreshEditor(); + } + removeLastPath() { + this._paths.pop(); + this.refreshEditor(); + } + removeAllPaths() { + this._paths.length = 0; + this.refreshEditor(); + } + updateCurrentPath() { + const tmpPath = super.updateCurrentPath(); + if (tmpPath) { + this._currentPath.path = new Path2D(this._currentPathString + tmpPath); + } + return tmpPath; + } + refreshEditor() { + this.drawPaths(); + this.fillContextMenu(); + } + drawPaths() { + this.ctx.clearRect(0, 0, this._canvas.width, this._canvas.height); + (this._currentPath + ? [...this._paths, this._currentPath] + : this._paths).forEach(x => { + const [r, g, b, a] = x.color; + this.ctx.strokeStyle = `rgba(${r * 255},${g * 255},${b * 255},${a})`; + this.ctx.lineWidth = x.strokeWidth; + this.ctx.lineCap = "round"; + this.ctx.lineJoin = "round"; + this.ctx.stroke(x.path); + }); + } + convertClientCoordsToCanvas(clX, clY) { + const { top, left, width, height } = this._canvas.getBoundingClientRect(); + const caHorRatio = width / this._canvas.width; + const caVertRatio = height / this._canvas.height; + const caX = (clX - left) / caHorRatio; + const caY = (clY - top) / caVertRatio; + return [caX, caY]; + } + fillContextMenu() { + const cmContent = [ + this.buildColorPicker(), + this.buildWidthSliderWithButtons(), + ]; + this._contextMenu.content = cmContent; + this._contextMenu.enabled = true; + } + buildColorPicker() { + const colorPickerDiv = document.createElement("div"); + colorPickerDiv.classList.add("context-menu-content", "row"); + CanvasSmoothPathEditor._colors.forEach(x => { + const item = document.createElement("div"); + item.classList.add("panel-button"); + if (x === this._color) { + item.classList.add("on"); + } + item.addEventListener("click", () => { + this._color = x; + this.fillContextMenu(); + }); + const colorIcon = document.createElement("div"); + colorIcon.classList.add("context-menu-color-icon"); + colorIcon.style.backgroundColor = `rgb(${x[0] * 255},${x[1] * 255},${x[2] * 255})`; + item.append(colorIcon); + colorPickerDiv.append(item); + }); + return colorPickerDiv; + } + buildWidthSliderWithButtons() { + const div = document.createElement("div"); + div.classList.add("context-menu-content", "row"); + const undoButton = document.createElement("div"); + undoButton.classList.add("panel-button"); + if (!this.pathCount) { + undoButton.classList.add("disabled"); + } + else { + undoButton.addEventListener("click", () => { + this.removeLastPath(); + }); + } + undoButton.innerHTML = ``; + div.append(undoButton); + const clearButton = document.createElement("div"); + clearButton.classList.add("panel-button"); + if (!this.pathCount) { + clearButton.classList.add("disabled"); + } + else { + clearButton.addEventListener("click", () => { + this.removeAllPaths(); + }); + } + clearButton.innerHTML = ``; + div.append(clearButton); + const slider = document.createElement("input"); + slider.setAttribute("type", "range"); + slider.setAttribute("min", "1"); + slider.setAttribute("max", "32"); + slider.setAttribute("step", "1"); + slider.setAttribute("value", this._strokeWidth + ""); + slider.classList.add("context-menu-slider"); + slider.addEventListener("change", () => { + this._strokeWidth = slider.valueAsNumber; + }); + div.append(slider); + return div; + } +} +CanvasSmoothPathEditor._defaultStrokeWidth = 3; +CanvasSmoothPathEditor._colors = [ + [0, 0, 0, 1], + [0.804, 0, 0, 1], + [0, 0.804, 0, 1], + [0, 0, 0.804, 1], + [1, 0.5, 0, 1], + [1, 0.2, 1, 1], +]; + +var __awaiter$1$1 = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class DomUtils { + static htmlToElements(html) { + const template = document.createElement("template"); + template.innerHTML = html; + const nodes = []; + template.content.childNodes.forEach(x => { + if (x instanceof HTMLElement) { + nodes.push(x); + } + }); + return nodes; + } + static promisify(callback) { + return __awaiter$1$1(this, void 0, void 0, function* () { + return new Promise(resolve => { + setTimeout(() => { + const result = callback(); + resolve(result); + }, 0); + }); + }); + } + static runEmptyTimeout() { + return __awaiter$1$1(this, void 0, void 0, function* () { + yield this.promisify(() => undefined); + }); + } + static downloadFile(blob, name) { + const url = URL.createObjectURL(blob); + const link = document.createElement("a"); + link.setAttribute("download", name); + link.href = url; + document.body.appendChild(link); + link.click(); + link.remove(); + setTimeout(() => URL.revokeObjectURL(url), 10000); + } + static loadImageAsync(url, revoke = false) { + return __awaiter$1$1(this, void 0, void 0, function* () { + const loadedImage = yield new Promise((resolve, reject) => { + const image = new Image(); + image.onerror = (e, error) => { + if (revoke) { + URL.revokeObjectURL(url); + } + console.log(`Error while loading image: ${(error === null || error === void 0 ? void 0 : error.message) || e.toString()}`); + resolve(null); + }; + image.onload = () => { + if (revoke) { + URL.revokeObjectURL(url); + } + resolve(image); + }; + image.src = url; + }); + return loadedImage; + }); + } + static loadFileDataAsync(src) { + return __awaiter$1$1(this, void 0, void 0, function* () { + let data; + if (src instanceof Uint8Array) { + data = src; + } + else { + let blob; + if (typeof src === "string") { + const res = yield fetch(src); + if (!res.ok) { + throw new Error(`${res.status}: ${res.statusText}`); + } + blob = yield res.blob(); + } + else { + blob = src; + } + const buffer = yield blob.arrayBuffer(); + data = new Uint8Array(buffer); + } + return data; + }); + } +} + +class Spinner { + constructor() { + this._spinnerElement = DomUtils.htmlToElements(Spinner.spinnerHtml)[0]; + } + show(parent, zIndex = 8) { + if (this._isShown || !parent) { + return; + } + this._spinnerElement.style.zIndex = zIndex + ""; + this._spinnerElement.style.top = parent.scrollTop + "px"; + this._spinnerElement.style.left = parent.scrollLeft + "px"; + parent.append(this._spinnerElement); + this._isShown = true; + } + hide() { + this._spinnerElement.remove(); + this._isShown = false; + } +} +Spinner.spinnerHtml = ` +
+
+
+
+
+
+
+ `; + +class CloudCurveData { + static buildFromPolyline(polylinePoints, maxArcSize) { + if (!polylinePoints || polylinePoints.length < 2) { + return null; + } + if (isNaN(maxArcSize) || maxArcSize <= 0) { + throw new Error(`Invalid maximal arc size ${maxArcSize}`); + } + const start = polylinePoints[0].clone().truncate(2); + const curves = []; + const zeroVec = new u(); + const lengthVec = new u(); + let i; + let j; + let lineStart; + let lineEnd; + let lineLength; + let arcCount; + let arcSize; + let halfArcSize; + let arcStart; + let arcEnd; + for (i = 0; i < polylinePoints.length - 1; i++) { + lineStart = polylinePoints[i]; + lineEnd = polylinePoints[i + 1]; + lineLength = u.subtract(lineEnd, lineStart).getMagnitude(); + if (!lineLength) { + continue; + } + lengthVec.set(lineLength, 0); + const matrix = l.from4Vec2(zeroVec, lengthVec, lineStart, lineEnd); + arcCount = Math.ceil(lineLength / maxArcSize); + arcSize = lineLength / arcCount; + halfArcSize = arcSize / 2; + for (j = 0; j < arcCount; j++) { + arcStart = j * arcSize; + arcEnd = (j + 1) * arcSize; + const curve = [ + new u(arcStart, -halfArcSize).applyMat3(matrix).truncate(2), + new u(arcEnd, -halfArcSize).applyMat3(matrix).truncate(2), + new u(arcEnd, 0).applyMat3(matrix).truncate(2), + ]; + curves.push(curve); + } + } + return { + start, + curves, + }; + } + static buildFromEllipse(rx, ry, maxArcSize, matrix) { + matrix || (matrix = new l()); + const center = new u(); + const ellipseCircumferenceApprox = Math.PI * (3 * (rx + ry) - Math.sqrt((3 * rx + ry) * (rx + 3 * ry))); + const segmentsNumber = Math.ceil(ellipseCircumferenceApprox / maxArcSize / 4) * 4; + const maxSegmentLength = Math.ceil(ellipseCircumferenceApprox / segmentsNumber); + const points = []; + const current = new u(center.x + rx, center.y); + const next = new u(); + let angle = 0; + let distance; + points.push(current.clone().applyMat3(matrix).truncate(2)); + for (let i = 0; i < segmentsNumber; i++) { + distance = 0; + while (distance < maxSegmentLength) { + angle += 0.25 / 180 * Math.PI; + next.set(rx * Math.cos(angle) + center.x, ry * Math.sin(angle) + center.y); + distance += h(current.x, current.y, next.x, next.y); + current.setFromVec2(next); + } + points.push(current.clone().applyMat3(matrix).truncate(2)); + } + const curveData = this.buildFromPolyline(points, maxArcSize); + return curveData; + } +} + +class SvgSmoothPath extends SmoothPath { + constructor(options) { + super(options); + this._paths = []; + this._strokeWidth = (options === null || options === void 0 ? void 0 : options.strokeWidth) || SvgSmoothPath._defaultStrokeWidth; + this._color = (options === null || options === void 0 ? void 0 : options.color) || SvgSmoothPath._defaultColor; + this._group = document.createElementNS("http://www.w3.org/2000/svg", "g"); + } + get strokeWidth() { + return this._strokeWidth; + } + get color() { + return this._color; + } + get group() { + return this._group; + } + get paths() { + return this._paths.slice(); + } + newPath(startPosition) { + const [r, g, b, a] = this._color || [0, 0, 0, 1]; + const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); + path.setAttribute("fill", "none"); + path.setAttribute("stroke", `rgba(${r * 255},${g * 255},${b * 255},${a})`); + path.setAttribute("stroke-width", this._strokeWidth + ""); + path.setAttribute("stroke-linecap", "round"); + path.setAttribute("stroke-linejoin", "round"); + const pathString = "M" + startPosition.x + " " + startPosition.y; + path.setAttribute("d", pathString); + this._positionBuffer = [startPosition]; + this._currentPath = { path, positions: [new u(startPosition.x, startPosition.y)] }; + this._currentPathString = pathString; + this._group.append(path); + } + removePath(path) { + if (!path) { + return; + } + path.remove(); + this._paths = this._paths.filter(x => x.path !== path); + } + removeLastPath() { + const pathData = this._paths.pop(); + pathData === null || pathData === void 0 ? void 0 : pathData.path.remove(); + } + updateCurrentPath() { + const tmpPath = super.updateCurrentPath(); + if (tmpPath) { + this._currentPath.path.setAttribute("d", this._currentPathString + tmpPath); + } + return tmpPath; + } +} +SvgSmoothPath._defaultStrokeWidth = 3; +SvgSmoothPath._defaultColor = [0, 0, 0, 0.8]; + +class SvgTempPath { + constructor() { + this._path = document.createElementNS("http://www.w3.org/2000/svg", "path"); + } + get path() { + return this._path; + } + set(fill, stroke, w, points, close = false) { + let d = ""; + if ((points === null || points === void 0 ? void 0 : points.length) > 1) { + d += `M${points[0].x},${points[0].y} `; + for (let i = 1; i < points.length; i++) { + d += `L${points[i].x},${points[i].y} `; + } + if (close) { + d += "Z"; + } + } + this._path.classList.add("annotation-temp-copy"); + this._path.setAttribute("d", d); + this._path.style.fill = fill; + this._path.style.stroke = stroke; + this._path.style.strokeWidth = w + ""; + } + insertAfter(element) { + element.after(this._path); + } + remove() { + this._path.setAttribute("d", ""); + this._path.remove(); + } +} + +class EventService { + constructor(container) { + this._eventMap = new Map(); + if (!container) { + throw new Error("Container is not defined"); + } + const element = document.createElement("div"); + element.style.position = "absolute"; + element.style.width = "0"; + element.style.height = "0"; + element.style.zIndex = "-1000"; + container.append(element); + this._element = element; + } + get element() { + return this._element; + } + destroy() { + this.removeAllListeners(); + this._element.remove(); + this._element = null; + } + addListener(key, listener, options) { + if (!this._element) { + return; + } + this._element.addEventListener(key, listener, options); + if (this._eventMap.has(key)) { + this._eventMap.get(key).add(listener); + } + else { + this._eventMap.set(key, new Set().add(listener)); + } + } + removeListener(key, listener) { + if (!this._element) { + return; + } + this._element.removeEventListener(key, listener); + if (this._eventMap.has(key)) { + this._eventMap.get(key).delete(listener); + } + } + removeAllListenersForKey(key) { + if (!this._element) { + return; + } + if (this._eventMap.has(key)) { + const listeners = this._eventMap.get(key); + listeners.forEach(x => this._element.removeEventListener(key, x)); + this._eventMap.delete(key); + } + } + removeAllListeners() { + if (!this._element) { + return; + } + this._eventMap.forEach((v, k) => { + v.forEach(x => this._element.removeEventListener(k, x)); + }); + this._eventMap.clear(); + } + getListenersByKey(key) { + const listenerSet = this._eventMap.get(key); + return listenerSet + ? [...listenerSet] + : []; + } + hasListenersForKey(key) { + const listenerSet = this._eventMap.get(key); + return !!(listenerSet === null || listenerSet === void 0 ? void 0 : listenerSet.size); + } + dispatchEvent(e) { + if (!this._element) { + return; + } + if (!this.hasListenersForKey(e.type)) { + return; + } + this._element.dispatchEvent(e); + } +} + +class LinkedListNode { + constructor(data) { + this.data = data; + } +} +class LinkedList { + constructor(head) { + this._length = 0; + if (head) { + this.push(head); + } + } + get head() { + return this._head.data; + } + get length() { + return this._length; + } + get tail() { + return this.get(this._length - 1); + } + push(value) { + const node = new LinkedListNode(value); + let current; + if (!this._head) { + this._head = node; + } + else { + current = this._head; + while (current.next) { + current = current.next; + } + current.next = node; + } + this._length++; + } + insert(value, n) { + if (n < 0 || n > this._length - 1) { + return null; + } + const node = new LinkedListNode(value); + let previous; + let current = this._head; + let i = 0; + if (!n) { + this._head = node; + } + else { + while (i++ < n) { + previous = current; + current = current.next; + } + previous.next = node; + } + node.next = current; + this._length++; + return node.data; + } + replace(value, n) { + if (n < 0 || n > this._length - 1) { + return null; + } + const node = new LinkedListNode(value); + let previous; + let current = this._head; + let i = 0; + if (!n) { + this._head = node; + } + else { + while (i++ < n) { + previous = current; + current = current.next; + } + previous.next = node; + } + node.next = current.next; + return current.data; + } + remove(n) { + if (n < 0 || n > this._length - 1) { + return null; + } + let previous; + let current = this._head; + let i = 0; + if (!n) { + this._head = current.next; + } + else { + while (i++ < n) { + previous = current; + current = current.next; + } + previous.next = current.next; + } + this._length--; + return current.data; + } + clear() { + this._head = null; + this._length = 0; + } + get(n) { + if (n < 0 || n > this._length - 1) { + return null; + } + let current = this._head; + let i = 0; + while (i++ < n) { + current = current.next; + } + return current.data; + } + pop() { + return this.remove(this._length - 1); + } + has(value, comparator) { + if (!this._length) { + return false; + } + comparator || (comparator = (a, b) => a === b); + let current = this._head; + let i = 0; + while (i < this._length) { + if (comparator(value, current.data)) { + return true; + } + current = current.next; + i++; + } + return false; + } + findIndex(value, comparator) { + if (!this._length) { + return -1; + } + comparator || (comparator = (a, b) => a === b); + let current = this._head; + let i = 0; + while (i < this._length) { + if (comparator(value, current.data)) { + return i; + } + current = current.next; + i++; + } + return -1; + } + *[Symbol.iterator]() { + let current = this._head; + while (current) { + yield current.data; + current = current.next; + } + } +} + +class UUID { + static getRandomUuid() { + return v4(); + } +} + +var __awaiter$1n = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +const stampImageLoaderHtml = ` +
+
+
+ +
+
+

Stamp name:

+ +
+
+

Stamp description:

+ +
+
+

Width:

+ +

Height:

+ +
+
+
+ +
+
+ +
+
+
+
+`; +const stampDesignerHtml = ` +
+
+
+
+
+

Stamp name:

+ +
+
+

Stamp description:

+ +
+
+

Width:

+ +

Height:

+ +
+
+
+ +
+
+ +
+
+
+
+`; +const customStampEvent = "tsviewer-customstampchange"; +class CustomStampEvent extends CustomEvent { + constructor(detail) { + super(customStampEvent, { detail }); + } +} +class CustomStampService { + constructor(container, eventService) { + this._customStampsByType = new Map(); + this._spinner = new Spinner(); + this.onFileInput = () => { + const files = this._fileInput.files; + if (files.length === 0) { + return; + } + this.openImageLoaderOverlayAsync(files[0]); + this._fileInput.value = null; + }; + if (!container) { + throw new Error("Container is not defined"); + } + if (!eventService) { + throw new Error("Event service is not defined"); + } + this._container = container; + this._eventService = eventService; + const fileInput = document.createElement("input"); + fileInput.type = "file"; + fileInput.accept = "image/*"; + fileInput.classList.add("abs-hidden"); + this._fileInput = fileInput; + this._fileInput.addEventListener("change", this.onFileInput); + this._container.append(this._fileInput); + } + destroy() { + var _a; + this._fileInput.remove(); + this._spinner.hide(); + (_a = this._overlay) === null || _a === void 0 ? void 0 : _a.remove(); + } + importCustomStamps(stamps) { + if (stamps === null || stamps === void 0 ? void 0 : stamps.length) { + stamps.forEach(x => { + this._customStampsByType.set(x.type, x); + }); + } + } + getCustomStamps() { + return [...this._customStampsByType.values()]; + } + addCustomStamp(stamp) { + this._customStampsByType.set(stamp.type, stamp); + this._eventService.dispatchEvent(new CustomStampEvent({ + type: "add", + stamp: stamp, + })); + } + removeCustomStamp(type) { + const stamp = this._customStampsByType.get(type); + if (!stamp) { + return; + } + this._customStampsByType.delete(type); + this._eventService.dispatchEvent(new CustomStampEvent({ + type: "delete", + stamp: stamp, + })); + } + startLoadingImage() { + this._fileInput.click(); + } + startDrawing() { + this.openDesignerOverlayAsync(); + } + openImageLoaderOverlayAsync(file) { + return __awaiter$1n(this, void 0, void 0, function* () { + this._spinner.show(this._container, 10); + const imagePromise = new Promise((resolve, reject) => { + const url = URL.createObjectURL(file); + const img = new Image(); + img.onload = () => { + URL.revokeObjectURL(url); + resolve(img); + }; + img.onerror = (e) => { + console.log(e); + reject(); + }; + img.src = url; + }); + let image; + try { + image = yield imagePromise; + } + catch (_a) { + this._spinner.hide(); + return; + } + const imageWidth = image.width; + const imageHeight = image.height; + const imageRatio = image.width / image.height; + const overlay = DomUtils.htmlToElements(stampImageLoaderHtml)[0]; + const canvas = overlay.querySelector("canvas"); + const cancelButton = overlay.querySelector(".stamp-cancel"); + const okButton = overlay.querySelector(".stamp-ok"); + const nameInput = overlay.querySelector(".stamp-name-input"); + const subjectInput = overlay.querySelector(".stamp-subject-input"); + const widthInput = overlay.querySelector(".stamp-width-input"); + const heightInput = overlay.querySelector(".stamp-height-input"); + let stampName = "Custom stamp"; + let stampSubject = "image stamp"; + let stampWidth = 64; + let stampHeight = +(64 / imageRatio).toFixed(); + nameInput.value = stampName; + widthInput.value = stampWidth + ""; + heightInput.value = stampHeight + ""; + this._overlay = overlay; + this._container.append(overlay); + canvas.width = imageWidth; + canvas.height = imageHeight; + const ctx = canvas.getContext("2d"); + ctx.drawImage(image, 0, 0); + const imgData = ctx.getImageData(0, 0, image.width, image.height).data; + const validate = () => { + if (!stampName + || (!stampHeight || isNaN(stampHeight)) + || (!stampWidth || isNaN(stampWidth))) { + okButton.classList.add("disabled"); + } + else { + okButton.classList.remove("disabled"); + } + }; + nameInput.addEventListener("input", () => { + stampName = nameInput.value; + validate(); + }); + subjectInput.addEventListener("input", () => { + stampSubject = subjectInput.value; + validate(); + }); + widthInput.addEventListener("input", () => { + var _a; + stampWidth = +((_a = (+widthInput.value)) === null || _a === void 0 ? void 0 : _a.toFixed()); + validate(); + }); + heightInput.addEventListener("input", () => { + var _a; + stampHeight = +((_a = (+heightInput.value)) === null || _a === void 0 ? void 0 : _a.toFixed()); + validate(); + }); + const hide = () => { + overlay.remove(); + this._overlay = null; + }; + cancelButton.addEventListener("click", hide); + okButton.addEventListener("click", () => { + const imageDataArray = new Array(imgData.length); + for (let i = 0; i < imgData.length; i++) { + imageDataArray[i] = imgData[i]; + } + const stamp = { + type: "/" + UUID.getRandomUuid(), + name: stampName, + subject: stampSubject, + rect: [0, 0, stampWidth, stampHeight], + bbox: [0, 0, imageWidth, imageHeight], + imageData: imageDataArray, + }; + this.addCustomStamp(stamp); + hide(); + }); + this._spinner.hide(); + }); + } + openDesignerOverlayAsync() { + return __awaiter$1n(this, void 0, void 0, function* () { + this._spinner.show(this._container, 10); + const overlay = DomUtils.htmlToElements(stampDesignerHtml)[0]; + const canvasContainer = overlay.querySelector(".form-canvas-wrapper"); + const cancelButton = overlay.querySelector(".stamp-cancel"); + const okButton = overlay.querySelector(".stamp-ok"); + const nameInput = overlay.querySelector(".stamp-name-input"); + const subjectInput = overlay.querySelector(".stamp-subject-input"); + const widthInput = overlay.querySelector(".stamp-width-input"); + const heightInput = overlay.querySelector(".stamp-height-input"); + let stampName = "Custom stamp"; + let stampSubject = "drawing stamp"; + let stampWidth = 64; + let stampHeight = 64; + nameInput.value = stampName; + widthInput.value = stampWidth + ""; + heightInput.value = stampHeight + ""; + const editor = new CanvasSmoothPathEditor(canvasContainer, { + canvasWidth: stampWidth, + canvasHeight: stampHeight, + }); + this._overlay = overlay; + this._container.append(overlay); + const updateCanvasSize = () => { + editor.canvasSize = [stampWidth, stampHeight]; + }; + const validate = () => { + if (!stampName + || (!stampHeight || isNaN(stampHeight)) + || (!stampWidth || isNaN(stampWidth))) { + okButton.classList.add("disabled"); + } + else { + updateCanvasSize(); + okButton.classList.remove("disabled"); + } + }; + nameInput.addEventListener("input", () => { + stampName = nameInput.value; + validate(); + }); + subjectInput.addEventListener("input", () => { + stampSubject = subjectInput.value; + validate(); + }); + widthInput.addEventListener("input", () => { + var _a; + stampWidth = +((_a = (+widthInput.value)) === null || _a === void 0 ? void 0 : _a.toFixed()); + validate(); + }); + heightInput.addEventListener("input", () => { + var _a; + stampHeight = +((_a = (+heightInput.value)) === null || _a === void 0 ? void 0 : _a.toFixed()); + validate(); + }); + const hide = () => { + overlay.remove(); + this._overlay = null; + }; + cancelButton.addEventListener("click", hide); + okButton.addEventListener("click", () => { + const imgData = editor.getImageData(); + const imageDataArray = new Array(imgData.length); + for (let i = 0; i < imgData.length; i++) { + imageDataArray[i] = imgData[i]; + } + const stamp = { + type: "/" + UUID.getRandomUuid(), + name: stampName, + subject: stampSubject, + rect: [0, 0, stampWidth, stampHeight], + bbox: [0, 0, stampWidth, stampHeight], + imageData: imageDataArray, + }; + this.addCustomStamp(stamp); + hide(); + }); + this._spinner.hide(); + }); + } +} + +class HtmlTemplates { +} +HtmlTemplates.textDialogHtml = ` +
+
+ +
+
+ +
+
+ +
+
+
+
+ `; +HtmlTemplates.stampContextButtonsHtml = ` +
+
+ +
+
+ +
+
+ +
+
+ `; + +/*! pako 2.1.0 https://github.com/nodeca/pako @license (MIT AND Zlib) */ +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +/* eslint-disable space-unary-ops */ + +/* Public constants ==========================================================*/ +/* ===========================================================================*/ + + +//const Z_FILTERED = 1; +//const Z_HUFFMAN_ONLY = 2; +//const Z_RLE = 3; +const Z_FIXED$1 = 4; +//const Z_DEFAULT_STRATEGY = 0; + +/* Possible values of the data_type field (though see inflate()) */ +const Z_BINARY = 0; +const Z_TEXT = 1; +//const Z_ASCII = 1; // = Z_TEXT +const Z_UNKNOWN$1 = 2; + +/*============================================================================*/ + + +function zero$1(buf) { let len = buf.length; while (--len >= 0) { buf[len] = 0; } } + +// From zutil.h + +const STORED_BLOCK = 0; +const STATIC_TREES = 1; +const DYN_TREES = 2; +/* The three kinds of block type */ + +const MIN_MATCH$1 = 3; +const MAX_MATCH$1 = 258; +/* The minimum and maximum match lengths */ + +// From deflate.h +/* =========================================================================== + * Internal compression state. + */ + +const LENGTH_CODES$1 = 29; +/* number of length codes, not counting the special END_BLOCK code */ + +const LITERALS$1 = 256; +/* number of literal bytes 0..255 */ + +const L_CODES$1 = LITERALS$1 + 1 + LENGTH_CODES$1; +/* number of Literal or Length codes, including the END_BLOCK code */ + +const D_CODES$1 = 30; +/* number of distance codes */ + +const BL_CODES$1 = 19; +/* number of codes used to transfer the bit lengths */ + +const HEAP_SIZE$1 = 2 * L_CODES$1 + 1; +/* maximum heap size */ + +const MAX_BITS$1 = 15; +/* All codes must not exceed MAX_BITS bits */ + +const Buf_size = 16; +/* size of bit buffer in bi_buf */ + + +/* =========================================================================== + * Constants + */ + +const MAX_BL_BITS = 7; +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +const END_BLOCK = 256; +/* end of block literal code */ + +const REP_3_6 = 16; +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +const REPZ_3_10 = 17; +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +const REPZ_11_138 = 18; +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +/* eslint-disable comma-spacing,array-bracket-spacing */ +const extra_lbits = /* extra bits for each length code */ + new Uint8Array([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0]); + +const extra_dbits = /* extra bits for each distance code */ + new Uint8Array([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13]); + +const extra_blbits = /* extra bits for each bit length code */ + new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7]); + +const bl_order = + new Uint8Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]); +/* eslint-enable comma-spacing,array-bracket-spacing */ + +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +// We pre-fill arrays with 0 to avoid uninitialized gaps + +const DIST_CODE_LEN = 512; /* see definition of array dist_code below */ + +// !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1 +const static_ltree = new Array((L_CODES$1 + 2) * 2); +zero$1(static_ltree); +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +const static_dtree = new Array(D_CODES$1 * 2); +zero$1(static_dtree); +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +const _dist_code = new Array(DIST_CODE_LEN); +zero$1(_dist_code); +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +const _length_code = new Array(MAX_MATCH$1 - MIN_MATCH$1 + 1); +zero$1(_length_code); +/* length code for each normalized match length (0 == MIN_MATCH) */ + +const base_length = new Array(LENGTH_CODES$1); +zero$1(base_length); +/* First normalized length for each code (0 = MIN_MATCH) */ + +const base_dist = new Array(D_CODES$1); +zero$1(base_dist); +/* First normalized distance for each code (0 = distance of 1) */ + + +function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) { + + this.static_tree = static_tree; /* static tree or NULL */ + this.extra_bits = extra_bits; /* extra bits for each code or NULL */ + this.extra_base = extra_base; /* base index for extra_bits */ + this.elems = elems; /* max number of elements in the tree */ + this.max_length = max_length; /* max bit length for the codes */ + + // show if `static_tree` has data or dummy - needed for monomorphic objects + this.has_stree = static_tree && static_tree.length; +} + + +let static_l_desc; +let static_d_desc; +let static_bl_desc; + + +function TreeDesc(dyn_tree, stat_desc) { + this.dyn_tree = dyn_tree; /* the dynamic tree */ + this.max_code = 0; /* largest code with non zero frequency */ + this.stat_desc = stat_desc; /* the corresponding static tree */ +} + + + +const d_code = (dist) => { + + return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)]; +}; + + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +const put_short = (s, w) => { +// put_byte(s, (uch)((w) & 0xff)); +// put_byte(s, (uch)((ush)(w) >> 8)); + s.pending_buf[s.pending++] = (w) & 0xff; + s.pending_buf[s.pending++] = (w >>> 8) & 0xff; +}; + + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +const send_bits = (s, value, length) => { + + if (s.bi_valid > (Buf_size - length)) { + s.bi_buf |= (value << s.bi_valid) & 0xffff; + put_short(s, s.bi_buf); + s.bi_buf = value >> (Buf_size - s.bi_valid); + s.bi_valid += length - Buf_size; + } else { + s.bi_buf |= (value << s.bi_valid) & 0xffff; + s.bi_valid += length; + } +}; + + +const send_code = (s, c, tree) => { + + send_bits(s, tree[c * 2]/*.Code*/, tree[c * 2 + 1]/*.Len*/); +}; + + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +const bi_reverse = (code, len) => { + + let res = 0; + do { + res |= code & 1; + code >>>= 1; + res <<= 1; + } while (--len > 0); + return res >>> 1; +}; + + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +const bi_flush = (s) => { + + if (s.bi_valid === 16) { + put_short(s, s.bi_buf); + s.bi_buf = 0; + s.bi_valid = 0; + + } else if (s.bi_valid >= 8) { + s.pending_buf[s.pending++] = s.bi_buf & 0xff; + s.bi_buf >>= 8; + s.bi_valid -= 8; + } +}; + + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +const gen_bitlen = (s, desc) => { +// deflate_state *s; +// tree_desc *desc; /* the tree descriptor */ + + const tree = desc.dyn_tree; + const max_code = desc.max_code; + const stree = desc.stat_desc.static_tree; + const has_stree = desc.stat_desc.has_stree; + const extra = desc.stat_desc.extra_bits; + const base = desc.stat_desc.extra_base; + const max_length = desc.stat_desc.max_length; + let h; /* heap index */ + let n, m; /* iterate over the tree elements */ + let bits; /* bit length */ + let xbits; /* extra bits */ + let f; /* frequency */ + let overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS$1; bits++) { + s.bl_count[bits] = 0; + } + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s.heap[s.heap_max] * 2 + 1]/*.Len*/ = 0; /* root of the heap */ + + for (h = s.heap_max + 1; h < HEAP_SIZE$1; h++) { + n = s.heap[h]; + bits = tree[tree[n * 2 + 1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1; + if (bits > max_length) { + bits = max_length; + overflow++; + } + tree[n * 2 + 1]/*.Len*/ = bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) { continue; } /* not a leaf node */ + + s.bl_count[bits]++; + xbits = 0; + if (n >= base) { + xbits = extra[n - base]; + } + f = tree[n * 2]/*.Freq*/; + s.opt_len += f * (bits + xbits); + if (has_stree) { + s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits); + } + } + if (overflow === 0) { return; } + + // Tracev((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length - 1; + while (s.bl_count[bits] === 0) { bits--; } + s.bl_count[bits]--; /* move one leaf down the tree */ + s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */ + s.bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits !== 0; bits--) { + n = s.bl_count[bits]; + while (n !== 0) { + m = s.heap[--h]; + if (m > max_code) { continue; } + if (tree[m * 2 + 1]/*.Len*/ !== bits) { + // Tracev((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/; + tree[m * 2 + 1]/*.Len*/ = bits; + } + n--; + } + } +}; + + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +const gen_codes = (tree, max_code, bl_count) => { +// ct_data *tree; /* the tree to decorate */ +// int max_code; /* largest code with non zero frequency */ +// ushf *bl_count; /* number of codes at each bit length */ + + const next_code = new Array(MAX_BITS$1 + 1); /* next code value for each bit length */ + let code = 0; /* running code value */ + let bits; /* bit index */ + let n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS$1; bits++) { + code = (code + bl_count[bits - 1]) << 1; + next_code[bits] = code; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + //Assert (code + bl_count[MAX_BITS]-1 == (1< { + + let n; /* iterates over tree elements */ + let bits; /* bit counter */ + let length; /* length value */ + let code; /* code value */ + let dist; /* distance index */ + const bl_count = new Array(MAX_BITS$1 + 1); + /* number of codes at each bit length for an optimal tree */ + + // do check in _tr_init() + //if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ +/*#ifdef NO_INIT_GLOBAL_POINTERS + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; +#endif*/ + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES$1 - 1; code++) { + base_length[code] = length; + for (n = 0; n < (1 << extra_lbits[code]); n++) { + _length_code[length++] = code; + } + } + //Assert (length == 256, "tr_static_init: length != 256"); + /* Note that the length 255 (match length 258) can be represented + * in two different ways: code 284 + 5 bits or code 285, so we + * overwrite length_code[255] to use the best encoding: + */ + _length_code[length - 1] = code; + + /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ + dist = 0; + for (code = 0; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1 << extra_dbits[code]); n++) { + _dist_code[dist++] = code; + } + } + //Assert (dist == 256, "tr_static_init: dist != 256"); + dist >>= 7; /* from now on, all distances are divided by 128 */ + for (; code < D_CODES$1; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) { + _dist_code[256 + dist++] = code; + } + } + //Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS$1; bits++) { + bl_count[bits] = 0; + } + + n = 0; + while (n <= 143) { + static_ltree[n * 2 + 1]/*.Len*/ = 8; + n++; + bl_count[8]++; + } + while (n <= 255) { + static_ltree[n * 2 + 1]/*.Len*/ = 9; + n++; + bl_count[9]++; + } + while (n <= 279) { + static_ltree[n * 2 + 1]/*.Len*/ = 7; + n++; + bl_count[7]++; + } + while (n <= 287) { + static_ltree[n * 2 + 1]/*.Len*/ = 8; + n++; + bl_count[8]++; + } + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes(static_ltree, L_CODES$1 + 1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES$1; n++) { + static_dtree[n * 2 + 1]/*.Len*/ = 5; + static_dtree[n * 2]/*.Code*/ = bi_reverse(n, 5); + } + + // Now data ready and we can init static trees + static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS$1 + 1, L_CODES$1, MAX_BITS$1); + static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES$1, MAX_BITS$1); + static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES$1, MAX_BL_BITS); + + //static_init_done = true; +}; + + +/* =========================================================================== + * Initialize a new block. + */ +const init_block = (s) => { + + let n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES$1; n++) { s.dyn_ltree[n * 2]/*.Freq*/ = 0; } + for (n = 0; n < D_CODES$1; n++) { s.dyn_dtree[n * 2]/*.Freq*/ = 0; } + for (n = 0; n < BL_CODES$1; n++) { s.bl_tree[n * 2]/*.Freq*/ = 0; } + + s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1; + s.opt_len = s.static_len = 0; + s.sym_next = s.matches = 0; +}; + + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +const bi_windup = (s) => +{ + if (s.bi_valid > 8) { + put_short(s, s.bi_buf); + } else if (s.bi_valid > 0) { + //put_byte(s, (Byte)s->bi_buf); + s.pending_buf[s.pending++] = s.bi_buf; + } + s.bi_buf = 0; + s.bi_valid = 0; +}; + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +const smaller = (tree, n, m, depth) => { + + const _n2 = n * 2; + const _m2 = m * 2; + return (tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ || + (tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m])); +}; + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +const pqdownheap = (s, tree, k) => { +// deflate_state *s; +// ct_data *tree; /* the tree to restore */ +// int k; /* node to move down */ + + const v = s.heap[k]; + let j = k << 1; /* left son of k */ + while (j <= s.heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s.heap_len && + smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s.heap[j], s.depth)) { break; } + + /* Exchange v with the smallest son */ + s.heap[k] = s.heap[j]; + k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s.heap[k] = v; +}; + + +// inlined manually +// const SMALLEST = 1; + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +const compress_block = (s, ltree, dtree) => { +// deflate_state *s; +// const ct_data *ltree; /* literal tree */ +// const ct_data *dtree; /* distance tree */ + + let dist; /* distance of matched string */ + let lc; /* match length or unmatched char (if dist == 0) */ + let sx = 0; /* running index in sym_buf */ + let code; /* the code to send */ + let extra; /* number of extra bits to send */ + + if (s.sym_next !== 0) { + do { + dist = s.pending_buf[s.sym_buf + sx++] & 0xff; + dist += (s.pending_buf[s.sym_buf + sx++] & 0xff) << 8; + lc = s.pending_buf[s.sym_buf + sx++]; + if (dist === 0) { + send_code(s, lc, ltree); /* send a literal byte */ + //Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code + LITERALS$1 + 1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra !== 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + //Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra !== 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and sym_buf is ok: */ + //Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow"); + + } while (sx < s.sym_next); + } + + send_code(s, END_BLOCK, ltree); +}; + + +/* =========================================================================== + * Construct one Huffman tree and assigns the code bit strings and lengths. + * Update the total bit length for the current block. + * IN assertion: the field freq is set for all tree elements. + * OUT assertions: the fields len and code are set to the optimal bit length + * and corresponding code. The length opt_len is updated; static_len is + * also updated if stree is not null. The field max_code is set. + */ +const build_tree = (s, desc) => { +// deflate_state *s; +// tree_desc *desc; /* the tree descriptor */ + + const tree = desc.dyn_tree; + const stree = desc.stat_desc.static_tree; + const has_stree = desc.stat_desc.has_stree; + const elems = desc.stat_desc.elems; + let n, m; /* iterate over heap elements */ + let max_code = -1; /* largest code with non zero frequency */ + let node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s.heap_len = 0; + s.heap_max = HEAP_SIZE$1; + + for (n = 0; n < elems; n++) { + if (tree[n * 2]/*.Freq*/ !== 0) { + s.heap[++s.heap_len] = max_code = n; + s.depth[n] = 0; + + } else { + tree[n * 2 + 1]/*.Len*/ = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s.heap_len < 2) { + node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0); + tree[node * 2]/*.Freq*/ = 1; + s.depth[node] = 0; + s.opt_len--; + + if (has_stree) { + s.static_len -= stree[node * 2 + 1]/*.Len*/; + } + /* node is 0 or 1 so it does not have extra bits */ + } + desc.max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = (s.heap_len >> 1/*int /2*/); n >= 1; n--) { pqdownheap(s, tree, n); } + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + //pqremove(s, tree, n); /* n = node of least frequency */ + /*** pqremove ***/ + n = s.heap[1/*SMALLEST*/]; + s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--]; + pqdownheap(s, tree, 1/*SMALLEST*/); + /***/ + + m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */ + + s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */ + s.heap[--s.heap_max] = m; + + /* Create a new node father of n and m */ + tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/; + s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1; + tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node; + + /* and insert the new node in the heap */ + s.heap[1/*SMALLEST*/] = node++; + pqdownheap(s, tree, 1/*SMALLEST*/); + + } while (s.heap_len >= 2); + + s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes(tree, max_code, s.bl_count); +}; + + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +const scan_tree = (s, tree, max_code) => { +// deflate_state *s; +// ct_data *tree; /* the tree to be scanned */ +// int max_code; /* and its largest code of non zero frequency */ + + let n; /* iterates over all tree elements */ + let prevlen = -1; /* last emitted length */ + let curlen; /* length of current code */ + + let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ + + let count = 0; /* repeat count of the current code */ + let max_count = 7; /* max repeat count */ + let min_count = 4; /* min repeat count */ + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; + + if (++count < max_count && curlen === nextlen) { + continue; + + } else if (count < min_count) { + s.bl_tree[curlen * 2]/*.Freq*/ += count; + + } else if (curlen !== 0) { + + if (curlen !== prevlen) { s.bl_tree[curlen * 2]/*.Freq*/++; } + s.bl_tree[REP_3_6 * 2]/*.Freq*/++; + + } else if (count <= 10) { + s.bl_tree[REPZ_3_10 * 2]/*.Freq*/++; + + } else { + s.bl_tree[REPZ_11_138 * 2]/*.Freq*/++; + } + + count = 0; + prevlen = curlen; + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + + } else if (curlen === nextlen) { + max_count = 6; + min_count = 3; + + } else { + max_count = 7; + min_count = 4; + } + } +}; + + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +const send_tree = (s, tree, max_code) => { +// deflate_state *s; +// ct_data *tree; /* the tree to be scanned */ +// int max_code; /* and its largest code of non zero frequency */ + + let n; /* iterates over all tree elements */ + let prevlen = -1; /* last emitted length */ + let curlen; /* length of current code */ + + let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ + + let count = 0; /* repeat count of the current code */ + let max_count = 7; /* max repeat count */ + let min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; + + if (++count < max_count && curlen === nextlen) { + continue; + + } else if (count < min_count) { + do { send_code(s, curlen, s.bl_tree); } while (--count !== 0); + + } else if (curlen !== 0) { + if (curlen !== prevlen) { + send_code(s, curlen, s.bl_tree); + count--; + } + //Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s.bl_tree); + send_bits(s, count - 3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s.bl_tree); + send_bits(s, count - 3, 3); + + } else { + send_code(s, REPZ_11_138, s.bl_tree); + send_bits(s, count - 11, 7); + } + + count = 0; + prevlen = curlen; + if (nextlen === 0) { + max_count = 138; + min_count = 3; + + } else if (curlen === nextlen) { + max_count = 6; + min_count = 3; + + } else { + max_count = 7; + min_count = 4; + } + } +}; + + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +const build_bl_tree = (s) => { + + let max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, s.dyn_ltree, s.l_desc.max_code); + scan_tree(s, s.dyn_dtree, s.d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, s.bl_desc); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES$1 - 1; max_blindex >= 3; max_blindex--) { + if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) { + break; + } + } + /* Update opt_len to include the bit length tree and counts */ + s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; + //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + // s->opt_len, s->static_len)); + + return max_blindex; +}; + + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +const send_all_trees = (s, lcodes, dcodes, blcodes) => { +// deflate_state *s; +// int lcodes, dcodes, blcodes; /* number of codes for each tree */ + + let rank; /* index in bl_order */ + + //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + // "too many codes"); + //Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes - 1, 5); + send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + //Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1]/*.Len*/, 3); + } + //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */ + //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */ + //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +}; + + +/* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "block list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "allow list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ +const detect_data_type = (s) => { + /* block_mask is the bit mask of block-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + let block_mask = 0xf3ffc07f; + let n; + + /* Check for non-textual ("block-listed") bytes. */ + for (n = 0; n <= 31; n++, block_mask >>>= 1) { + if ((block_mask & 1) && (s.dyn_ltree[n * 2]/*.Freq*/ !== 0)) { + return Z_BINARY; + } + } + + /* Check for textual ("allow-listed") bytes. */ + if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 || + s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) { + return Z_TEXT; + } + for (n = 32; n < LITERALS$1; n++) { + if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { + return Z_TEXT; + } + } + + /* There are no "block-listed" or "allow-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. + */ + return Z_BINARY; +}; + + +let static_init_done = false; + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +const _tr_init$1 = (s) => +{ + + if (!static_init_done) { + tr_static_init(); + static_init_done = true; + } + + s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc); + s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc); + s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc); + + s.bi_buf = 0; + s.bi_valid = 0; + + /* Initialize the first block of the first file: */ + init_block(s); +}; + + +/* =========================================================================== + * Send a stored block + */ +const _tr_stored_block$1 = (s, buf, stored_len, last) => { +//DeflateState *s; +//charf *buf; /* input block */ +//ulg stored_len; /* length of input block */ +//int last; /* one if this is the last block for a file */ + + send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3); /* send block type */ + bi_windup(s); /* align on byte boundary */ + put_short(s, stored_len); + put_short(s, ~stored_len); + if (stored_len) { + s.pending_buf.set(s.window.subarray(buf, buf + stored_len), s.pending); + } + s.pending += stored_len; +}; + + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + */ +const _tr_align$1 = (s) => { + send_bits(s, STATIC_TREES << 1, 3); + send_code(s, END_BLOCK, static_ltree); + bi_flush(s); +}; + + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and write out the encoded block. + */ +const _tr_flush_block$1 = (s, buf, stored_len, last) => { +//DeflateState *s; +//charf *buf; /* input block, or NULL if too old */ +//ulg stored_len; /* length of input block */ +//int last; /* one if this is the last block for a file */ + + let opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + let max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s.level > 0) { + + /* Check if the file is binary or text */ + if (s.strm.data_type === Z_UNKNOWN$1) { + s.strm.data_type = detect_data_type(s); + } + + /* Construct the literal and distance trees */ + build_tree(s, s.l_desc); + // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + // s->static_len)); + + build_tree(s, s.d_desc); + // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + // s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s.opt_len + 3 + 7) >>> 3; + static_lenb = (s.static_len + 3 + 7) >>> 3; + + // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + // opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + // s->sym_next / 3)); + + if (static_lenb <= opt_lenb) { opt_lenb = static_lenb; } + + } else { + // Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + + if ((stored_len + 4 <= opt_lenb) && (buf !== -1)) { + /* 4: two words for the lengths */ + + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block$1(s, buf, stored_len, last); + + } else if (s.strategy === Z_FIXED$1 || static_lenb === opt_lenb) { + + send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3); + compress_block(s, static_ltree, static_dtree); + + } else { + send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3); + send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1); + compress_block(s, s.dyn_ltree, s.dyn_dtree); + } + // Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (last) { + bi_windup(s); + } + // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + // s->compressed_len-7*last)); +}; + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +const _tr_tally$1 = (s, dist, lc) => { +// deflate_state *s; +// unsigned dist; /* distance of matched string */ +// unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ + + s.pending_buf[s.sym_buf + s.sym_next++] = dist; + s.pending_buf[s.sym_buf + s.sym_next++] = dist >> 8; + s.pending_buf[s.sym_buf + s.sym_next++] = lc; + if (dist === 0) { + /* lc is the unmatched char */ + s.dyn_ltree[lc * 2]/*.Freq*/++; + } else { + s.matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + //Assert((ush)dist < (ush)MAX_DIST(s) && + // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + // (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s.dyn_ltree[(_length_code[lc] + LITERALS$1 + 1) * 2]/*.Freq*/++; + s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++; + } + + return (s.sym_next === s.sym_end); +}; + +var _tr_init_1 = _tr_init$1; +var _tr_stored_block_1 = _tr_stored_block$1; +var _tr_flush_block_1 = _tr_flush_block$1; +var _tr_tally_1 = _tr_tally$1; +var _tr_align_1 = _tr_align$1; + +var trees = { + _tr_init: _tr_init_1, + _tr_stored_block: _tr_stored_block_1, + _tr_flush_block: _tr_flush_block_1, + _tr_tally: _tr_tally_1, + _tr_align: _tr_align_1 +}; + +// Note: adler32 takes 12% for level 0 and 2% for level 6. +// It isn't worth it to make additional optimizations as in original. +// Small size is preferable. + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +const adler32 = (adler, buf, len, pos) => { + let s1 = (adler & 0xffff) |0, + s2 = ((adler >>> 16) & 0xffff) |0, + n = 0; + + while (len !== 0) { + // Set limit ~ twice less than 5552, to keep + // s2 in 31-bits, because we force signed ints. + // in other case %= will fail. + n = len > 2000 ? 2000 : len; + len -= n; + + do { + s1 = (s1 + buf[pos++]) |0; + s2 = (s2 + s1) |0; + } while (--n); + + s1 %= 65521; + s2 %= 65521; + } + + return (s1 | (s2 << 16)) |0; +}; + + +var adler32_1 = adler32; + +// Note: we can't get significant speed boost here. +// So write code to minimize size - no pregenerated tables +// and array tools dependencies. + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +// Use ordinary array, since untyped makes no boost here +const makeTable = () => { + let c, table = []; + + for (var n = 0; n < 256; n++) { + c = n; + for (var k = 0; k < 8; k++) { + c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); + } + table[n] = c; + } + + return table; +}; + +// Create table on load. Just 255 signed longs. Not a problem. +const crcTable = new Uint32Array(makeTable()); + + +const crc32 = (crc, buf, len, pos) => { + const t = crcTable; + const end = pos + len; + + crc ^= -1; + + for (let i = pos; i < end; i++) { + crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; + } + + return (crc ^ (-1)); // >>> 0; +}; + + +var crc32_1 = crc32; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +var messages = { + 2: 'need dictionary', /* Z_NEED_DICT 2 */ + 1: 'stream end', /* Z_STREAM_END 1 */ + 0: '', /* Z_OK 0 */ + '-1': 'file error', /* Z_ERRNO (-1) */ + '-2': 'stream error', /* Z_STREAM_ERROR (-2) */ + '-3': 'data error', /* Z_DATA_ERROR (-3) */ + '-4': 'insufficient memory', /* Z_MEM_ERROR (-4) */ + '-5': 'buffer error', /* Z_BUF_ERROR (-5) */ + '-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */ +}; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +var constants$2 = { + + /* Allowed flush values; see deflate() and inflate() below for details */ + Z_NO_FLUSH: 0, + Z_PARTIAL_FLUSH: 1, + Z_SYNC_FLUSH: 2, + Z_FULL_FLUSH: 3, + Z_FINISH: 4, + Z_BLOCK: 5, + Z_TREES: 6, + + /* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + Z_OK: 0, + Z_STREAM_END: 1, + Z_NEED_DICT: 2, + Z_ERRNO: -1, + Z_STREAM_ERROR: -2, + Z_DATA_ERROR: -3, + Z_MEM_ERROR: -4, + Z_BUF_ERROR: -5, + //Z_VERSION_ERROR: -6, + + /* compression levels */ + Z_NO_COMPRESSION: 0, + Z_BEST_SPEED: 1, + Z_BEST_COMPRESSION: 9, + Z_DEFAULT_COMPRESSION: -1, + + + Z_FILTERED: 1, + Z_HUFFMAN_ONLY: 2, + Z_RLE: 3, + Z_FIXED: 4, + Z_DEFAULT_STRATEGY: 0, + + /* Possible values of the data_type field (though see inflate()) */ + Z_BINARY: 0, + Z_TEXT: 1, + //Z_ASCII: 1, // = Z_TEXT (deprecated) + Z_UNKNOWN: 2, + + /* The deflate compression method */ + Z_DEFLATED: 8 + //Z_NULL: null // Use -1 or null inline, depending on var type +}; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +const { _tr_init, _tr_stored_block, _tr_flush_block, _tr_tally, _tr_align } = trees; + + + + +/* Public constants ==========================================================*/ +/* ===========================================================================*/ + +const { + Z_NO_FLUSH: Z_NO_FLUSH$2, Z_PARTIAL_FLUSH, Z_FULL_FLUSH: Z_FULL_FLUSH$1, Z_FINISH: Z_FINISH$3, Z_BLOCK: Z_BLOCK$1, + Z_OK: Z_OK$3, Z_STREAM_END: Z_STREAM_END$3, Z_STREAM_ERROR: Z_STREAM_ERROR$2, Z_DATA_ERROR: Z_DATA_ERROR$2, Z_BUF_ERROR: Z_BUF_ERROR$1, + Z_DEFAULT_COMPRESSION: Z_DEFAULT_COMPRESSION$1, + Z_FILTERED, Z_HUFFMAN_ONLY, Z_RLE, Z_FIXED, Z_DEFAULT_STRATEGY: Z_DEFAULT_STRATEGY$1, + Z_UNKNOWN, + Z_DEFLATED: Z_DEFLATED$2 +} = constants$2; + +/*============================================================================*/ + + +const MAX_MEM_LEVEL = 9; +/* Maximum value for memLevel in deflateInit2 */ +const MAX_WBITS$1 = 15; +/* 32K LZ77 window */ +const DEF_MEM_LEVEL = 8; + + +const LENGTH_CODES = 29; +/* number of length codes, not counting the special END_BLOCK code */ +const LITERALS = 256; +/* number of literal bytes 0..255 */ +const L_CODES = LITERALS + 1 + LENGTH_CODES; +/* number of Literal or Length codes, including the END_BLOCK code */ +const D_CODES = 30; +/* number of distance codes */ +const BL_CODES = 19; +/* number of codes used to transfer the bit lengths */ +const HEAP_SIZE = 2 * L_CODES + 1; +/* maximum heap size */ +const MAX_BITS = 15; +/* All codes must not exceed MAX_BITS bits */ + +const MIN_MATCH = 3; +const MAX_MATCH = 258; +const MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1); + +const PRESET_DICT = 0x20; + +const INIT_STATE = 42; /* zlib header -> BUSY_STATE */ +//#ifdef GZIP +const GZIP_STATE = 57; /* gzip header -> BUSY_STATE | EXTRA_STATE */ +//#endif +const EXTRA_STATE = 69; /* gzip extra block -> NAME_STATE */ +const NAME_STATE = 73; /* gzip file name -> COMMENT_STATE */ +const COMMENT_STATE = 91; /* gzip comment -> HCRC_STATE */ +const HCRC_STATE = 103; /* gzip header CRC -> BUSY_STATE */ +const BUSY_STATE = 113; /* deflate -> FINISH_STATE */ +const FINISH_STATE = 666; /* stream complete */ + +const BS_NEED_MORE = 1; /* block not completed, need more input or more output */ +const BS_BLOCK_DONE = 2; /* block flush performed */ +const BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */ +const BS_FINISH_DONE = 4; /* finish done, accept no more input or output */ + +const OS_CODE = 0x03; // Unix :) . Don't detect, use this default. + +const err = (strm, errorCode) => { + strm.msg = messages[errorCode]; + return errorCode; +}; + +const rank = (f) => { + return ((f) * 2) - ((f) > 4 ? 9 : 0); +}; + +const zero = (buf) => { + let len = buf.length; while (--len >= 0) { buf[len] = 0; } +}; + +/* =========================================================================== + * Slide the hash table when sliding the window down (could be avoided with 32 + * bit values at the expense of memory usage). We slide even when level == 0 to + * keep the hash table consistent if we switch back to level > 0 later. + */ +const slide_hash = (s) => { + let n, m; + let p; + let wsize = s.w_size; + + n = s.hash_size; + p = n; + do { + m = s.head[--p]; + s.head[p] = (m >= wsize ? m - wsize : 0); + } while (--n); + n = wsize; +//#ifndef FASTEST + p = n; + do { + m = s.prev[--p]; + s.prev[p] = (m >= wsize ? m - wsize : 0); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +//#endif +}; + +/* eslint-disable new-cap */ +let HASH_ZLIB = (s, prev, data) => ((prev << s.hash_shift) ^ data) & s.hash_mask; +// This hash causes less collisions, https://github.com/nodeca/pako/issues/135 +// But breaks binary compatibility +//let HASH_FAST = (s, prev, data) => ((prev << 8) + (prev >> 8) + (data << 4)) & s.hash_mask; +let HASH = HASH_ZLIB; + + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output, except for + * some deflate_stored() output, goes through this function so some + * applications may wish to modify it to avoid allocating a large + * strm->next_out buffer and copying into it. (See also read_buf()). + */ +const flush_pending = (strm) => { + const s = strm.state; + + //_tr_flush_bits(s); + let len = s.pending; + if (len > strm.avail_out) { + len = strm.avail_out; + } + if (len === 0) { return; } + + strm.output.set(s.pending_buf.subarray(s.pending_out, s.pending_out + len), strm.next_out); + strm.next_out += len; + s.pending_out += len; + strm.total_out += len; + strm.avail_out -= len; + s.pending -= len; + if (s.pending === 0) { + s.pending_out = 0; + } +}; + + +const flush_block_only = (s, last) => { + _tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last); + s.block_start = s.strstart; + flush_pending(s.strm); +}; + + +const put_byte = (s, b) => { + s.pending_buf[s.pending++] = b; +}; + + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +const putShortMSB = (s, b) => { + + // put_byte(s, (Byte)(b >> 8)); +// put_byte(s, (Byte)(b & 0xff)); + s.pending_buf[s.pending++] = (b >>> 8) & 0xff; + s.pending_buf[s.pending++] = b & 0xff; +}; + + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->input buffer and copying from it. + * (See also flush_pending()). + */ +const read_buf = (strm, buf, start, size) => { + + let len = strm.avail_in; + + if (len > size) { len = size; } + if (len === 0) { return 0; } + + strm.avail_in -= len; + + // zmemcpy(buf, strm->next_in, len); + buf.set(strm.input.subarray(strm.next_in, strm.next_in + len), start); + if (strm.state.wrap === 1) { + strm.adler = adler32_1(strm.adler, buf, len, start); + } + + else if (strm.state.wrap === 2) { + strm.adler = crc32_1(strm.adler, buf, len, start); + } + + strm.next_in += len; + strm.total_in += len; + + return len; +}; + + +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +const longest_match = (s, cur_match) => { + + let chain_length = s.max_chain_length; /* max hash chain length */ + let scan = s.strstart; /* current string */ + let match; /* matched string */ + let len; /* length of current match */ + let best_len = s.prev_length; /* best match length so far */ + let nice_match = s.nice_match; /* stop if match long enough */ + const limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ? + s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/; + + const _win = s.window; // shortcut + + const wmask = s.w_mask; + const prev = s.prev; + + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + + const strend = s.strstart + MAX_MATCH; + let scan_end1 = _win[scan + best_len - 1]; + let scan_end = _win[scan + best_len]; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s.prev_length >= s.good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if (nice_match > s.lookahead) { nice_match = s.lookahead; } + + // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + // Assert(cur_match < s->strstart, "no future"); + match = cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ + + if (_win[match + best_len] !== scan_end || + _win[match + best_len - 1] !== scan_end1 || + _win[match] !== _win[scan] || + _win[++match] !== _win[scan + 1]) { + continue; + } + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2; + match++; + // Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + /*jshint noempty:false*/ + } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + scan < strend); + + // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (strend - scan); + scan = strend - MAX_MATCH; + + if (len > best_len) { + s.match_start = cur_match; + best_len = len; + if (len >= nice_match) { + break; + } + scan_end1 = _win[scan + best_len - 1]; + scan_end = _win[scan + best_len]; + } + } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0); + + if (best_len <= s.lookahead) { + return best_len; + } + return s.lookahead; +}; + + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +const fill_window = (s) => { + + const _w_size = s.w_size; + let n, more, str; + + //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); + + do { + more = s.window_size - s.lookahead - s.strstart; + + // JS ints have 32 bit, block below not needed + /* Deal with !@#$% 64K limit: */ + //if (sizeof(int) <= 2) { + // if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + // more = wsize; + // + // } else if (more == (unsigned)(-1)) { + // /* Very unlikely, but possible on 16 bit machine if + // * strstart == 0 && lookahead == 1 (input done a byte at time) + // */ + // more--; + // } + //} + + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) { + + s.window.set(s.window.subarray(_w_size, _w_size + _w_size - more), 0); + s.match_start -= _w_size; + s.strstart -= _w_size; + /* we now have strstart >= MAX_DIST */ + s.block_start -= _w_size; + if (s.insert > s.strstart) { + s.insert = s.strstart; + } + slide_hash(s); + more += _w_size; + } + if (s.strm.avail_in === 0) { + break; + } + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + //Assert(more >= 2, "more < 2"); + n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more); + s.lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s.lookahead + s.insert >= MIN_MATCH) { + str = s.strstart - s.insert; + s.ins_h = s.window[str]; + + /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */ + s.ins_h = HASH(s, s.ins_h, s.window[str + 1]); +//#if MIN_MATCH != 3 +// Call update_hash() MIN_MATCH-3 more times +//#endif + while (s.insert) { + /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ + s.ins_h = HASH(s, s.ins_h, s.window[str + MIN_MATCH - 1]); + + s.prev[str & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = str; + str++; + s.insert--; + if (s.lookahead + s.insert < MIN_MATCH) { + break; + } + } + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0); + + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + */ +// if (s.high_water < s.window_size) { +// const curr = s.strstart + s.lookahead; +// let init = 0; +// +// if (s.high_water < curr) { +// /* Previous high water mark below current data -- zero WIN_INIT +// * bytes or up to end of window, whichever is less. +// */ +// init = s.window_size - curr; +// if (init > WIN_INIT) +// init = WIN_INIT; +// zmemzero(s->window + curr, (unsigned)init); +// s->high_water = curr + init; +// } +// else if (s->high_water < (ulg)curr + WIN_INIT) { +// /* High water mark at or above current data, but below current data +// * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up +// * to end of window, whichever is less. +// */ +// init = (ulg)curr + WIN_INIT - s->high_water; +// if (init > s->window_size - s->high_water) +// init = s->window_size - s->high_water; +// zmemzero(s->window + s->high_water, (unsigned)init); +// s->high_water += init; +// } +// } +// +// Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, +// "not enough room for search"); +}; + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * + * In case deflateParams() is used to later switch to a non-zero compression + * level, s->matches (otherwise unused when storing) keeps track of the number + * of hash table slides to perform. If s->matches is 1, then one hash table + * slide will be done when switching. If s->matches is 2, the maximum value + * allowed here, then the hash table will be cleared, since two or more slides + * is the same as a clear. + * + * deflate_stored() is written to minimize the number of times an input byte is + * copied. It is most efficient with large input and output buffers, which + * maximizes the opportunites to have a single copy from next_in to next_out. + */ +const deflate_stored = (s, flush) => { + + /* Smallest worthy block size when not flushing or finishing. By default + * this is 32K. This can be as small as 507 bytes for memLevel == 1. For + * large input and output buffers, the stored block size will be larger. + */ + let min_block = s.pending_buf_size - 5 > s.w_size ? s.w_size : s.pending_buf_size - 5; + + /* Copy as many min_block or larger stored blocks directly to next_out as + * possible. If flushing, copy the remaining available input to next_out as + * stored blocks, if there is enough space. + */ + let len, left, have, last = 0; + let used = s.strm.avail_in; + do { + /* Set len to the maximum size block that we can copy directly with the + * available input data and output space. Set left to how much of that + * would be copied from what's left in the window. + */ + len = 65535/* MAX_STORED */; /* maximum deflate stored block length */ + have = (s.bi_valid + 42) >> 3; /* number of header bytes */ + if (s.strm.avail_out < have) { /* need room for header */ + break; + } + /* maximum stored block length that will fit in avail_out: */ + have = s.strm.avail_out - have; + left = s.strstart - s.block_start; /* bytes left in window */ + if (len > left + s.strm.avail_in) { + len = left + s.strm.avail_in; /* limit len to the input */ + } + if (len > have) { + len = have; /* limit len to the output */ + } + + /* If the stored block would be less than min_block in length, or if + * unable to copy all of the available input when flushing, then try + * copying to the window and the pending buffer instead. Also don't + * write an empty block when flushing -- deflate() does that. + */ + if (len < min_block && ((len === 0 && flush !== Z_FINISH$3) || + flush === Z_NO_FLUSH$2 || + len !== left + s.strm.avail_in)) { + break; + } + + /* Make a dummy stored block in pending to get the header bytes, + * including any pending bits. This also updates the debugging counts. + */ + last = flush === Z_FINISH$3 && len === left + s.strm.avail_in ? 1 : 0; + _tr_stored_block(s, 0, 0, last); + + /* Replace the lengths in the dummy stored block with len. */ + s.pending_buf[s.pending - 4] = len; + s.pending_buf[s.pending - 3] = len >> 8; + s.pending_buf[s.pending - 2] = ~len; + s.pending_buf[s.pending - 1] = ~len >> 8; + + /* Write the stored block header bytes. */ + flush_pending(s.strm); + +//#ifdef ZLIB_DEBUG +// /* Update debugging counts for the data about to be copied. */ +// s->compressed_len += len << 3; +// s->bits_sent += len << 3; +//#endif + + /* Copy uncompressed bytes from the window to next_out. */ + if (left) { + if (left > len) { + left = len; + } + //zmemcpy(s->strm->next_out, s->window + s->block_start, left); + s.strm.output.set(s.window.subarray(s.block_start, s.block_start + left), s.strm.next_out); + s.strm.next_out += left; + s.strm.avail_out -= left; + s.strm.total_out += left; + s.block_start += left; + len -= left; + } + + /* Copy uncompressed bytes directly from next_in to next_out, updating + * the check value. + */ + if (len) { + read_buf(s.strm, s.strm.output, s.strm.next_out, len); + s.strm.next_out += len; + s.strm.avail_out -= len; + s.strm.total_out += len; + } + } while (last === 0); + + /* Update the sliding window with the last s->w_size bytes of the copied + * data, or append all of the copied data to the existing window if less + * than s->w_size bytes were copied. Also update the number of bytes to + * insert in the hash tables, in the event that deflateParams() switches to + * a non-zero compression level. + */ + used -= s.strm.avail_in; /* number of input bytes directly copied */ + if (used) { + /* If any input was used, then no unused input remains in the window, + * therefore s->block_start == s->strstart. + */ + if (used >= s.w_size) { /* supplant the previous history */ + s.matches = 2; /* clear hash */ + //zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size); + s.window.set(s.strm.input.subarray(s.strm.next_in - s.w_size, s.strm.next_in), 0); + s.strstart = s.w_size; + s.insert = s.strstart; + } + else { + if (s.window_size - s.strstart <= used) { + /* Slide the window down. */ + s.strstart -= s.w_size; + //zmemcpy(s->window, s->window + s->w_size, s->strstart); + s.window.set(s.window.subarray(s.w_size, s.w_size + s.strstart), 0); + if (s.matches < 2) { + s.matches++; /* add a pending slide_hash() */ + } + if (s.insert > s.strstart) { + s.insert = s.strstart; + } + } + //zmemcpy(s->window + s->strstart, s->strm->next_in - used, used); + s.window.set(s.strm.input.subarray(s.strm.next_in - used, s.strm.next_in), s.strstart); + s.strstart += used; + s.insert += used > s.w_size - s.insert ? s.w_size - s.insert : used; + } + s.block_start = s.strstart; + } + if (s.high_water < s.strstart) { + s.high_water = s.strstart; + } + + /* If the last block was written to next_out, then done. */ + if (last) { + return BS_FINISH_DONE; + } + + /* If flushing and all input has been consumed, then done. */ + if (flush !== Z_NO_FLUSH$2 && flush !== Z_FINISH$3 && + s.strm.avail_in === 0 && s.strstart === s.block_start) { + return BS_BLOCK_DONE; + } + + /* Fill the window with any remaining input. */ + have = s.window_size - s.strstart; + if (s.strm.avail_in > have && s.block_start >= s.w_size) { + /* Slide the window down. */ + s.block_start -= s.w_size; + s.strstart -= s.w_size; + //zmemcpy(s->window, s->window + s->w_size, s->strstart); + s.window.set(s.window.subarray(s.w_size, s.w_size + s.strstart), 0); + if (s.matches < 2) { + s.matches++; /* add a pending slide_hash() */ + } + have += s.w_size; /* more space now */ + if (s.insert > s.strstart) { + s.insert = s.strstart; + } + } + if (have > s.strm.avail_in) { + have = s.strm.avail_in; + } + if (have) { + read_buf(s.strm, s.window, s.strstart, have); + s.strstart += have; + s.insert += have > s.w_size - s.insert ? s.w_size - s.insert : have; + } + if (s.high_water < s.strstart) { + s.high_water = s.strstart; + } + + /* There was not enough avail_out to write a complete worthy or flushed + * stored block to next_out. Write a stored block to pending instead, if we + * have enough input for a worthy block, or if flushing and there is enough + * room for the remaining input as a stored block in the pending buffer. + */ + have = (s.bi_valid + 42) >> 3; /* number of header bytes */ + /* maximum stored block length that will fit in pending: */ + have = s.pending_buf_size - have > 65535/* MAX_STORED */ ? 65535/* MAX_STORED */ : s.pending_buf_size - have; + min_block = have > s.w_size ? s.w_size : have; + left = s.strstart - s.block_start; + if (left >= min_block || + ((left || flush === Z_FINISH$3) && flush !== Z_NO_FLUSH$2 && + s.strm.avail_in === 0 && left <= have)) { + len = left > have ? have : left; + last = flush === Z_FINISH$3 && s.strm.avail_in === 0 && + len === left ? 1 : 0; + _tr_stored_block(s, s.block_start, len, last); + s.block_start += len; + flush_pending(s.strm); + } + + /* We've done all we can with the available input and output. */ + return last ? BS_FINISH_STARTED : BS_NEED_MORE; +}; + + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +const deflate_fast = (s, flush) => { + + let hash_head; /* head of the hash chain */ + let bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s.lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH$2) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { + break; /* flush the current block */ + } + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = 0/*NIL*/; + if (s.lookahead >= MIN_MATCH) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]); + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s.match_length = longest_match(s, hash_head); + /* longest_match() sets match_start */ + } + if (s.match_length >= MIN_MATCH) { + // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only + + /*** _tr_tally_dist(s, s.strstart - s.match_start, + s.match_length - MIN_MATCH, bflush); ***/ + bflush = _tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH); + + s.lookahead -= s.match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ + if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH) { + s.match_length--; /* string at strstart already in table */ + do { + s.strstart++; + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]); + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s.match_length !== 0); + s.strstart++; + } else + { + s.strstart += s.match_length; + s.match_length = 0; + s.ins_h = s.window[s.strstart]; + /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */ + s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + 1]); + +//#if MIN_MATCH != 3 +// Call UPDATE_HASH() MIN_MATCH-3 more times +//#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + //Tracevv((stderr,"%c", s.window[s.strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart]); + + s.lookahead--; + s.strstart++; + } + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = ((s.strstart < (MIN_MATCH - 1)) ? s.strstart : MIN_MATCH - 1); + if (flush === Z_FINISH$3) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.sym_next) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; +}; + +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +const deflate_slow = (s, flush) => { + + let hash_head; /* head of hash chain */ + let bflush; /* set if current block must be flushed */ + + let max_insert; + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s.lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH$2) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { break; } /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = 0/*NIL*/; + if (s.lookahead >= MIN_MATCH) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]); + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + + /* Find the longest match, discarding those <= prev_length. + */ + s.prev_length = s.match_length; + s.prev_match = s.match_start; + s.match_length = MIN_MATCH - 1; + + if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match && + s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s.match_length = longest_match(s, hash_head); + /* longest_match() sets match_start */ + + if (s.match_length <= 5 && + (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH && s.strstart - s.match_start > 4096/*TOO_FAR*/))) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s.match_length = MIN_MATCH - 1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s.prev_length >= MIN_MATCH && s.match_length <= s.prev_length) { + max_insert = s.strstart + s.lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + //check_match(s, s.strstart-1, s.prev_match, s.prev_length); + + /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match, + s.prev_length - MIN_MATCH, bflush);***/ + bflush = _tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH); + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s.lookahead -= s.prev_length - 1; + s.prev_length -= 2; + do { + if (++s.strstart <= max_insert) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]); + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + } while (--s.prev_length !== 0); + s.match_available = 0; + s.match_length = MIN_MATCH - 1; + s.strstart++; + + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + + } else if (s.match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + //Tracevv((stderr,"%c", s->window[s->strstart-1])); + /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart - 1]); + + if (bflush) { + /*** FLUSH_BLOCK_ONLY(s, 0) ***/ + flush_block_only(s, false); + /***/ + } + s.strstart++; + s.lookahead--; + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s.match_available = 1; + s.strstart++; + s.lookahead--; + } + } + //Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s.match_available) { + //Tracevv((stderr,"%c", s->window[s->strstart-1])); + /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart - 1]); + + s.match_available = 0; + } + s.insert = s.strstart < MIN_MATCH - 1 ? s.strstart : MIN_MATCH - 1; + if (flush === Z_FINISH$3) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.sym_next) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + + return BS_BLOCK_DONE; +}; + + +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +const deflate_rle = (s, flush) => { + + let bflush; /* set if current block must be flushed */ + let prev; /* byte at distance one to match */ + let scan, strend; /* scan goes up to strend for length of run */ + + const _win = s.window; + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest run, plus one for the unrolled loop. + */ + if (s.lookahead <= MAX_MATCH) { + fill_window(s); + if (s.lookahead <= MAX_MATCH && flush === Z_NO_FLUSH$2) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { break; } /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + s.match_length = 0; + if (s.lookahead >= MIN_MATCH && s.strstart > 0) { + scan = s.strstart - 1; + prev = _win[scan]; + if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) { + strend = s.strstart + MAX_MATCH; + do { + /*jshint noempty:false*/ + } while (prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + scan < strend); + s.match_length = MAX_MATCH - (strend - scan); + if (s.match_length > s.lookahead) { + s.match_length = s.lookahead; + } + } + //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (s.match_length >= MIN_MATCH) { + //check_match(s, s.strstart, s.strstart - 1, s.match_length); + + /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/ + bflush = _tr_tally(s, 1, s.match_length - MIN_MATCH); + + s.lookahead -= s.match_length; + s.strstart += s.match_length; + s.match_length = 0; + } else { + /* No match, output a literal byte */ + //Tracevv((stderr,"%c", s->window[s->strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart]); + + s.lookahead--; + s.strstart++; + } + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = 0; + if (flush === Z_FINISH$3) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.sym_next) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; +}; + +/* =========================================================================== + * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. + * (It will be regenerated if this run of deflate switches away from Huffman.) + */ +const deflate_huff = (s, flush) => { + + let bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we have a literal to write. */ + if (s.lookahead === 0) { + fill_window(s); + if (s.lookahead === 0) { + if (flush === Z_NO_FLUSH$2) { + return BS_NEED_MORE; + } + break; /* flush the current block */ + } + } + + /* Output a literal byte */ + s.match_length = 0; + //Tracevv((stderr,"%c", s->window[s->strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart]); + s.lookahead--; + s.strstart++; + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = 0; + if (flush === Z_FINISH$3) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.sym_next) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; +}; + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +function Config(good_length, max_lazy, nice_length, max_chain, func) { + + this.good_length = good_length; + this.max_lazy = max_lazy; + this.nice_length = nice_length; + this.max_chain = max_chain; + this.func = func; +} + +const configuration_table = [ + /* good lazy nice chain */ + new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */ + new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */ + new Config(4, 5, 16, 8, deflate_fast), /* 2 */ + new Config(4, 6, 32, 32, deflate_fast), /* 3 */ + + new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */ + new Config(8, 16, 32, 32, deflate_slow), /* 5 */ + new Config(8, 16, 128, 128, deflate_slow), /* 6 */ + new Config(8, 32, 128, 256, deflate_slow), /* 7 */ + new Config(32, 128, 258, 1024, deflate_slow), /* 8 */ + new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */ +]; + + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +const lm_init = (s) => { + + s.window_size = 2 * s.w_size; + + /*** CLEAR_HASH(s); ***/ + zero(s.head); // Fill with NIL (= 0); + + /* Set the default configuration parameters: + */ + s.max_lazy_match = configuration_table[s.level].max_lazy; + s.good_match = configuration_table[s.level].good_length; + s.nice_match = configuration_table[s.level].nice_length; + s.max_chain_length = configuration_table[s.level].max_chain; + + s.strstart = 0; + s.block_start = 0; + s.lookahead = 0; + s.insert = 0; + s.match_length = s.prev_length = MIN_MATCH - 1; + s.match_available = 0; + s.ins_h = 0; +}; + + +function DeflateState() { + this.strm = null; /* pointer back to this zlib stream */ + this.status = 0; /* as the name implies */ + this.pending_buf = null; /* output still pending */ + this.pending_buf_size = 0; /* size of pending_buf */ + this.pending_out = 0; /* next pending byte to output to the stream */ + this.pending = 0; /* nb of bytes in the pending buffer */ + this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ + this.gzhead = null; /* gzip header information to write */ + this.gzindex = 0; /* where in extra, name, or comment */ + this.method = Z_DEFLATED$2; /* can only be DEFLATED */ + this.last_flush = -1; /* value of flush param for previous deflate call */ + + this.w_size = 0; /* LZ77 window size (32K by default) */ + this.w_bits = 0; /* log2(w_size) (8..16) */ + this.w_mask = 0; /* w_size - 1 */ + + this.window = null; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. + */ + + this.window_size = 0; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + this.prev = null; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + this.head = null; /* Heads of the hash chains or NIL. */ + + this.ins_h = 0; /* hash index of string to be inserted */ + this.hash_size = 0; /* number of elements in hash table */ + this.hash_bits = 0; /* log2(hash_size) */ + this.hash_mask = 0; /* hash_size-1 */ + + this.hash_shift = 0; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + this.block_start = 0; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + this.match_length = 0; /* length of best match */ + this.prev_match = 0; /* previous match */ + this.match_available = 0; /* set if previous match exists */ + this.strstart = 0; /* start of string to insert */ + this.match_start = 0; /* start of matching string */ + this.lookahead = 0; /* number of valid bytes ahead in window */ + + this.prev_length = 0; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + this.max_chain_length = 0; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + this.max_lazy_match = 0; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ + // That's alias to max_lazy_match, don't use directly + //this.max_insert_length = 0; + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + this.level = 0; /* compression level (1..9) */ + this.strategy = 0; /* favor or force Huffman coding*/ + + this.good_match = 0; + /* Use a faster search when the previous match is longer than this */ + + this.nice_match = 0; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + + /* Didn't use ct_data typedef below to suppress compiler warning */ + + // struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + // struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + // Use flat array of DOUBLE size, with interleaved fata, + // because JS does not support effective + this.dyn_ltree = new Uint16Array(HEAP_SIZE * 2); + this.dyn_dtree = new Uint16Array((2 * D_CODES + 1) * 2); + this.bl_tree = new Uint16Array((2 * BL_CODES + 1) * 2); + zero(this.dyn_ltree); + zero(this.dyn_dtree); + zero(this.bl_tree); + + this.l_desc = null; /* desc. for literal tree */ + this.d_desc = null; /* desc. for distance tree */ + this.bl_desc = null; /* desc. for bit length tree */ + + //ush bl_count[MAX_BITS+1]; + this.bl_count = new Uint16Array(MAX_BITS + 1); + /* number of codes at each bit length for an optimal tree */ + + //int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + this.heap = new Uint16Array(2 * L_CODES + 1); /* heap used to build the Huffman trees */ + zero(this.heap); + + this.heap_len = 0; /* number of elements in the heap */ + this.heap_max = 0; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + this.depth = new Uint16Array(2 * L_CODES + 1); //uch depth[2*L_CODES+1]; + zero(this.depth); + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + this.sym_buf = 0; /* buffer for distances and literals/lengths */ + + this.lit_bufsize = 0; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + this.sym_next = 0; /* running index in sym_buf */ + this.sym_end = 0; /* symbol table full when sym_next reaches this */ + + this.opt_len = 0; /* bit length of current block with optimal trees */ + this.static_len = 0; /* bit length of current block with static trees */ + this.matches = 0; /* number of string matches in current block */ + this.insert = 0; /* bytes at end of window left to insert */ + + + this.bi_buf = 0; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + this.bi_valid = 0; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + + // Used for window memory init. We safely ignore it for JS. That makes + // sense only for pointers and memory check tools. + //this.high_water = 0; + /* High water mark offset in window for initialized bytes -- bytes above + * this are set to zero in order to avoid memory check warnings when + * longest match routines access bytes past the input. This is then + * updated to the new high water mark. + */ +} + + +/* ========================================================================= + * Check for a valid deflate stream state. Return 0 if ok, 1 if not. + */ +const deflateStateCheck = (strm) => { + + if (!strm) { + return 1; + } + const s = strm.state; + if (!s || s.strm !== strm || (s.status !== INIT_STATE && +//#ifdef GZIP + s.status !== GZIP_STATE && +//#endif + s.status !== EXTRA_STATE && + s.status !== NAME_STATE && + s.status !== COMMENT_STATE && + s.status !== HCRC_STATE && + s.status !== BUSY_STATE && + s.status !== FINISH_STATE)) { + return 1; + } + return 0; +}; + + +const deflateResetKeep = (strm) => { + + if (deflateStateCheck(strm)) { + return err(strm, Z_STREAM_ERROR$2); + } + + strm.total_in = strm.total_out = 0; + strm.data_type = Z_UNKNOWN; + + const s = strm.state; + s.pending = 0; + s.pending_out = 0; + + if (s.wrap < 0) { + s.wrap = -s.wrap; + /* was made negative by deflate(..., Z_FINISH); */ + } + s.status = +//#ifdef GZIP + s.wrap === 2 ? GZIP_STATE : +//#endif + s.wrap ? INIT_STATE : BUSY_STATE; + strm.adler = (s.wrap === 2) ? + 0 // crc32(0, Z_NULL, 0) + : + 1; // adler32(0, Z_NULL, 0) + s.last_flush = -2; + _tr_init(s); + return Z_OK$3; +}; + + +const deflateReset = (strm) => { + + const ret = deflateResetKeep(strm); + if (ret === Z_OK$3) { + lm_init(strm.state); + } + return ret; +}; + + +const deflateSetHeader = (strm, head) => { + + if (deflateStateCheck(strm) || strm.state.wrap !== 2) { + return Z_STREAM_ERROR$2; + } + strm.state.gzhead = head; + return Z_OK$3; +}; + + +const deflateInit2 = (strm, level, method, windowBits, memLevel, strategy) => { + + if (!strm) { // === Z_NULL + return Z_STREAM_ERROR$2; + } + let wrap = 1; + + if (level === Z_DEFAULT_COMPRESSION$1) { + level = 6; + } + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } + + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } + + + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED$2 || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED || (windowBits === 8 && wrap !== 1)) { + return err(strm, Z_STREAM_ERROR$2); + } + + + if (windowBits === 8) { + windowBits = 9; + } + /* until 256-byte window bug fixed */ + + const s = new DeflateState(); + + strm.state = s; + s.strm = strm; + s.status = INIT_STATE; /* to pass state test in deflateReset() */ + + s.wrap = wrap; + s.gzhead = null; + s.w_bits = windowBits; + s.w_size = 1 << s.w_bits; + s.w_mask = s.w_size - 1; + + s.hash_bits = memLevel + 7; + s.hash_size = 1 << s.hash_bits; + s.hash_mask = s.hash_size - 1; + s.hash_shift = ~~((s.hash_bits + MIN_MATCH - 1) / MIN_MATCH); + + s.window = new Uint8Array(s.w_size * 2); + s.head = new Uint16Array(s.hash_size); + s.prev = new Uint16Array(s.w_size); + + // Don't need mem init magic for JS. + //s.high_water = 0; /* nothing written to s->window yet */ + + s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + /* We overlay pending_buf and sym_buf. This works since the average size + * for length/distance pairs over any compressed block is assured to be 31 + * bits or less. + * + * Analysis: The longest fixed codes are a length code of 8 bits plus 5 + * extra bits, for lengths 131 to 257. The longest fixed distance codes are + * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest + * possible fixed-codes length/distance pair is then 31 bits total. + * + * sym_buf starts one-fourth of the way into pending_buf. So there are + * three bytes in sym_buf for every four bytes in pending_buf. Each symbol + * in sym_buf is three bytes -- two for the distance and one for the + * literal/length. As each symbol is consumed, the pointer to the next + * sym_buf value to read moves forward three bytes. From that symbol, up to + * 31 bits are written to pending_buf. The closest the written pending_buf + * bits gets to the next sym_buf symbol to read is just before the last + * code is written. At that time, 31*(n-2) bits have been written, just + * after 24*(n-2) bits have been consumed from sym_buf. sym_buf starts at + * 8*n bits into pending_buf. (Note that the symbol buffer fills when n-1 + * symbols are written.) The closest the writing gets to what is unread is + * then n+14 bits. Here n is lit_bufsize, which is 16384 by default, and + * can range from 128 to 32768. + * + * Therefore, at a minimum, there are 142 bits of space between what is + * written and what is read in the overlain buffers, so the symbols cannot + * be overwritten by the compressed data. That space is actually 139 bits, + * due to the three-bit fixed-code block header. + * + * That covers the case where either Z_FIXED is specified, forcing fixed + * codes, or when the use of fixed codes is chosen, because that choice + * results in a smaller compressed block than dynamic codes. That latter + * condition then assures that the above analysis also covers all dynamic + * blocks. A dynamic-code block will only be chosen to be emitted if it has + * fewer bits than a fixed-code block would for the same set of symbols. + * Therefore its average symbol length is assured to be less than 31. So + * the compressed data for a dynamic block also cannot overwrite the + * symbols from which it is being constructed. + */ + + s.pending_buf_size = s.lit_bufsize * 4; + s.pending_buf = new Uint8Array(s.pending_buf_size); + + // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`) + //s->sym_buf = s->pending_buf + s->lit_bufsize; + s.sym_buf = s.lit_bufsize; + + //s->sym_end = (s->lit_bufsize - 1) * 3; + s.sym_end = (s.lit_bufsize - 1) * 3; + /* We avoid equality with lit_bufsize*3 because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ + + s.level = level; + s.strategy = strategy; + s.method = method; + + return deflateReset(strm); +}; + +const deflateInit = (strm, level) => { + + return deflateInit2(strm, level, Z_DEFLATED$2, MAX_WBITS$1, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY$1); +}; + + +/* ========================================================================= */ +const deflate$2 = (strm, flush) => { + + if (deflateStateCheck(strm) || flush > Z_BLOCK$1 || flush < 0) { + return strm ? err(strm, Z_STREAM_ERROR$2) : Z_STREAM_ERROR$2; + } + + const s = strm.state; + + if (!strm.output || + (strm.avail_in !== 0 && !strm.input) || + (s.status === FINISH_STATE && flush !== Z_FINISH$3)) { + return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR$1 : Z_STREAM_ERROR$2); + } + + const old_flush = s.last_flush; + s.last_flush = flush; + + /* Flush as much pending output as possible */ + if (s.pending !== 0) { + flush_pending(strm); + if (strm.avail_out === 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s.last_flush = -1; + return Z_OK$3; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) && + flush !== Z_FINISH$3) { + return err(strm, Z_BUF_ERROR$1); + } + + /* User must not provide more input after the first FINISH: */ + if (s.status === FINISH_STATE && strm.avail_in !== 0) { + return err(strm, Z_BUF_ERROR$1); + } + + /* Write the header */ + if (s.status === INIT_STATE && s.wrap === 0) { + s.status = BUSY_STATE; + } + if (s.status === INIT_STATE) { + /* zlib header */ + let header = (Z_DEFLATED$2 + ((s.w_bits - 8) << 4)) << 8; + let level_flags = -1; + + if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) { + level_flags = 0; + } else if (s.level < 6) { + level_flags = 1; + } else if (s.level === 6) { + level_flags = 2; + } else { + level_flags = 3; + } + header |= (level_flags << 6); + if (s.strstart !== 0) { header |= PRESET_DICT; } + header += 31 - (header % 31); + + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s.strstart !== 0) { + putShortMSB(s, strm.adler >>> 16); + putShortMSB(s, strm.adler & 0xffff); + } + strm.adler = 1; // adler32(0L, Z_NULL, 0); + s.status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s.pending !== 0) { + s.last_flush = -1; + return Z_OK$3; + } + } +//#ifdef GZIP + if (s.status === GZIP_STATE) { + /* gzip header */ + strm.adler = 0; //crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (!s.gzhead) { // s->gzhead == Z_NULL + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s.level === 9 ? 2 : + (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s.status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s.pending !== 0) { + s.last_flush = -1; + return Z_OK$3; + } + } + else { + put_byte(s, (s.gzhead.text ? 1 : 0) + + (s.gzhead.hcrc ? 2 : 0) + + (!s.gzhead.extra ? 0 : 4) + + (!s.gzhead.name ? 0 : 8) + + (!s.gzhead.comment ? 0 : 16) + ); + put_byte(s, s.gzhead.time & 0xff); + put_byte(s, (s.gzhead.time >> 8) & 0xff); + put_byte(s, (s.gzhead.time >> 16) & 0xff); + put_byte(s, (s.gzhead.time >> 24) & 0xff); + put_byte(s, s.level === 9 ? 2 : + (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? + 4 : 0)); + put_byte(s, s.gzhead.os & 0xff); + if (s.gzhead.extra && s.gzhead.extra.length) { + put_byte(s, s.gzhead.extra.length & 0xff); + put_byte(s, (s.gzhead.extra.length >> 8) & 0xff); + } + if (s.gzhead.hcrc) { + strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending, 0); + } + s.gzindex = 0; + s.status = EXTRA_STATE; + } + } + if (s.status === EXTRA_STATE) { + if (s.gzhead.extra/* != Z_NULL*/) { + let beg = s.pending; /* start of bytes to update crc */ + let left = (s.gzhead.extra.length & 0xffff) - s.gzindex; + while (s.pending + left > s.pending_buf_size) { + let copy = s.pending_buf_size - s.pending; + // zmemcpy(s.pending_buf + s.pending, + // s.gzhead.extra + s.gzindex, copy); + s.pending_buf.set(s.gzhead.extra.subarray(s.gzindex, s.gzindex + copy), s.pending); + s.pending = s.pending_buf_size; + //--- HCRC_UPDATE(beg) ---// + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg); + } + //---// + s.gzindex += copy; + flush_pending(strm); + if (s.pending !== 0) { + s.last_flush = -1; + return Z_OK$3; + } + beg = 0; + left -= copy; + } + // JS specific: s.gzhead.extra may be TypedArray or Array for backward compatibility + // TypedArray.slice and TypedArray.from don't exist in IE10-IE11 + let gzhead_extra = new Uint8Array(s.gzhead.extra); + // zmemcpy(s->pending_buf + s->pending, + // s->gzhead->extra + s->gzindex, left); + s.pending_buf.set(gzhead_extra.subarray(s.gzindex, s.gzindex + left), s.pending); + s.pending += left; + //--- HCRC_UPDATE(beg) ---// + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg); + } + //---// + s.gzindex = 0; + } + s.status = NAME_STATE; + } + if (s.status === NAME_STATE) { + if (s.gzhead.name/* != Z_NULL*/) { + let beg = s.pending; /* start of bytes to update crc */ + let val; + do { + if (s.pending === s.pending_buf_size) { + //--- HCRC_UPDATE(beg) ---// + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg); + } + //---// + flush_pending(strm); + if (s.pending !== 0) { + s.last_flush = -1; + return Z_OK$3; + } + beg = 0; + } + // JS specific: little magic to add zero terminator to end of string + if (s.gzindex < s.gzhead.name.length) { + val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff; + } else { + val = 0; + } + put_byte(s, val); + } while (val !== 0); + //--- HCRC_UPDATE(beg) ---// + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg); + } + //---// + s.gzindex = 0; + } + s.status = COMMENT_STATE; + } + if (s.status === COMMENT_STATE) { + if (s.gzhead.comment/* != Z_NULL*/) { + let beg = s.pending; /* start of bytes to update crc */ + let val; + do { + if (s.pending === s.pending_buf_size) { + //--- HCRC_UPDATE(beg) ---// + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg); + } + //---// + flush_pending(strm); + if (s.pending !== 0) { + s.last_flush = -1; + return Z_OK$3; + } + beg = 0; + } + // JS specific: little magic to add zero terminator to end of string + if (s.gzindex < s.gzhead.comment.length) { + val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff; + } else { + val = 0; + } + put_byte(s, val); + } while (val !== 0); + //--- HCRC_UPDATE(beg) ---// + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg); + } + //---// + } + s.status = HCRC_STATE; + } + if (s.status === HCRC_STATE) { + if (s.gzhead.hcrc) { + if (s.pending + 2 > s.pending_buf_size) { + flush_pending(strm); + if (s.pending !== 0) { + s.last_flush = -1; + return Z_OK$3; + } + } + put_byte(s, strm.adler & 0xff); + put_byte(s, (strm.adler >> 8) & 0xff); + strm.adler = 0; //crc32(0L, Z_NULL, 0); + } + s.status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s.pending !== 0) { + s.last_flush = -1; + return Z_OK$3; + } + } +//#endif + + /* Start a new block or continue the current one. + */ + if (strm.avail_in !== 0 || s.lookahead !== 0 || + (flush !== Z_NO_FLUSH$2 && s.status !== FINISH_STATE)) { + let bstate = s.level === 0 ? deflate_stored(s, flush) : + s.strategy === Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : + s.strategy === Z_RLE ? deflate_rle(s, flush) : + configuration_table[s.level].func(s, flush); + + if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) { + s.status = FINISH_STATE; + } + if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) { + if (strm.avail_out === 0) { + s.last_flush = -1; + /* avoid BUF_ERROR next call, see above */ + } + return Z_OK$3; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate === BS_BLOCK_DONE) { + if (flush === Z_PARTIAL_FLUSH) { + _tr_align(s); + } + else if (flush !== Z_BLOCK$1) { /* FULL_FLUSH or SYNC_FLUSH */ + + _tr_stored_block(s, 0, 0, false); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush === Z_FULL_FLUSH$1) { + /*** CLEAR_HASH(s); ***/ /* forget history */ + zero(s.head); // Fill with NIL (= 0); + + if (s.lookahead === 0) { + s.strstart = 0; + s.block_start = 0; + s.insert = 0; + } + } + } + flush_pending(strm); + if (strm.avail_out === 0) { + s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK$3; + } + } + } + + if (flush !== Z_FINISH$3) { return Z_OK$3; } + if (s.wrap <= 0) { return Z_STREAM_END$3; } + + /* Write the trailer */ + if (s.wrap === 2) { + put_byte(s, strm.adler & 0xff); + put_byte(s, (strm.adler >> 8) & 0xff); + put_byte(s, (strm.adler >> 16) & 0xff); + put_byte(s, (strm.adler >> 24) & 0xff); + put_byte(s, strm.total_in & 0xff); + put_byte(s, (strm.total_in >> 8) & 0xff); + put_byte(s, (strm.total_in >> 16) & 0xff); + put_byte(s, (strm.total_in >> 24) & 0xff); + } + else + { + putShortMSB(s, strm.adler >>> 16); + putShortMSB(s, strm.adler & 0xffff); + } + + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s.wrap > 0) { s.wrap = -s.wrap; } + /* write the trailer only once! */ + return s.pending !== 0 ? Z_OK$3 : Z_STREAM_END$3; +}; + + +const deflateEnd = (strm) => { + + if (deflateStateCheck(strm)) { + return Z_STREAM_ERROR$2; + } + + const status = strm.state.status; + + strm.state = null; + + return status === BUSY_STATE ? err(strm, Z_DATA_ERROR$2) : Z_OK$3; +}; + + +/* ========================================================================= + * Initializes the compression dictionary from the given byte + * sequence without producing any compressed output. + */ +const deflateSetDictionary = (strm, dictionary) => { + + let dictLength = dictionary.length; + + if (deflateStateCheck(strm)) { + return Z_STREAM_ERROR$2; + } + + const s = strm.state; + const wrap = s.wrap; + + if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) { + return Z_STREAM_ERROR$2; + } + + /* when using zlib wrappers, compute Adler-32 for provided dictionary */ + if (wrap === 1) { + /* adler32(strm->adler, dictionary, dictLength); */ + strm.adler = adler32_1(strm.adler, dictionary, dictLength, 0); + } + + s.wrap = 0; /* avoid computing Adler-32 in read_buf */ + + /* if dictionary would fill window, just replace the history */ + if (dictLength >= s.w_size) { + if (wrap === 0) { /* already empty otherwise */ + /*** CLEAR_HASH(s); ***/ + zero(s.head); // Fill with NIL (= 0); + s.strstart = 0; + s.block_start = 0; + s.insert = 0; + } + /* use the tail */ + // dictionary = dictionary.slice(dictLength - s.w_size); + let tmpDict = new Uint8Array(s.w_size); + tmpDict.set(dictionary.subarray(dictLength - s.w_size, dictLength), 0); + dictionary = tmpDict; + dictLength = s.w_size; + } + /* insert dictionary into window and hash */ + const avail = strm.avail_in; + const next = strm.next_in; + const input = strm.input; + strm.avail_in = dictLength; + strm.next_in = 0; + strm.input = dictionary; + fill_window(s); + while (s.lookahead >= MIN_MATCH) { + let str = s.strstart; + let n = s.lookahead - (MIN_MATCH - 1); + do { + /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ + s.ins_h = HASH(s, s.ins_h, s.window[str + MIN_MATCH - 1]); + + s.prev[str & s.w_mask] = s.head[s.ins_h]; + + s.head[s.ins_h] = str; + str++; + } while (--n); + s.strstart = str; + s.lookahead = MIN_MATCH - 1; + fill_window(s); + } + s.strstart += s.lookahead; + s.block_start = s.strstart; + s.insert = s.lookahead; + s.lookahead = 0; + s.match_length = s.prev_length = MIN_MATCH - 1; + s.match_available = 0; + strm.next_in = next; + strm.input = input; + strm.avail_in = avail; + s.wrap = wrap; + return Z_OK$3; +}; + + +var deflateInit_1 = deflateInit; +var deflateInit2_1 = deflateInit2; +var deflateReset_1 = deflateReset; +var deflateResetKeep_1 = deflateResetKeep; +var deflateSetHeader_1 = deflateSetHeader; +var deflate_2$1 = deflate$2; +var deflateEnd_1 = deflateEnd; +var deflateSetDictionary_1 = deflateSetDictionary; +var deflateInfo = 'pako deflate (from Nodeca project)'; + +/* Not implemented +module.exports.deflateBound = deflateBound; +module.exports.deflateCopy = deflateCopy; +module.exports.deflateGetDictionary = deflateGetDictionary; +module.exports.deflateParams = deflateParams; +module.exports.deflatePending = deflatePending; +module.exports.deflatePrime = deflatePrime; +module.exports.deflateTune = deflateTune; +*/ + +var deflate_1$2 = { + deflateInit: deflateInit_1, + deflateInit2: deflateInit2_1, + deflateReset: deflateReset_1, + deflateResetKeep: deflateResetKeep_1, + deflateSetHeader: deflateSetHeader_1, + deflate: deflate_2$1, + deflateEnd: deflateEnd_1, + deflateSetDictionary: deflateSetDictionary_1, + deflateInfo: deflateInfo +}; + +const _has = (obj, key) => { + return Object.prototype.hasOwnProperty.call(obj, key); +}; + +var assign = function (obj /*from1, from2, from3, ...*/) { + const sources = Array.prototype.slice.call(arguments, 1); + while (sources.length) { + const source = sources.shift(); + if (!source) { continue; } + + if (typeof source !== 'object') { + throw new TypeError(source + 'must be non-object'); + } + + for (const p in source) { + if (_has(source, p)) { + obj[p] = source[p]; + } + } + } + + return obj; +}; + + +// Join array of chunks to single array. +var flattenChunks = (chunks) => { + // calculate data length + let len = 0; + + for (let i = 0, l = chunks.length; i < l; i++) { + len += chunks[i].length; + } + + // join chunks + const result = new Uint8Array(len); + + for (let i = 0, pos = 0, l = chunks.length; i < l; i++) { + let chunk = chunks[i]; + result.set(chunk, pos); + pos += chunk.length; + } + + return result; +}; + +var common = { + assign: assign, + flattenChunks: flattenChunks +}; + +// String encode/decode helpers + + +// Quick check if we can use fast array to bin string conversion +// +// - apply(Array) can fail on Android 2.2 +// - apply(Uint8Array) can fail on iOS 5.1 Safari +// +let STR_APPLY_UIA_OK = true; + +try { String.fromCharCode.apply(null, new Uint8Array(1)); } catch (__) { STR_APPLY_UIA_OK = false; } + + +// Table with utf8 lengths (calculated by first byte of sequence) +// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, +// because max possible codepoint is 0x10ffff +const _utf8len = new Uint8Array(256); +for (let q = 0; q < 256; q++) { + _utf8len[q] = (q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1); +} +_utf8len[254] = _utf8len[254] = 1; // Invalid sequence start + + +// convert string to array (typed, when possible) +var string2buf = (str) => { + if (typeof TextEncoder === 'function' && TextEncoder.prototype.encode) { + return new TextEncoder().encode(str); + } + + let buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0; + + // count binary size + for (m_pos = 0; m_pos < str_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) { + c2 = str.charCodeAt(m_pos + 1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; + } + + // allocate buffer + buf = new Uint8Array(buf_len); + + // convert + for (i = 0, m_pos = 0; i < buf_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) { + c2 = str.charCodeAt(m_pos + 1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + if (c < 0x80) { + /* one byte */ + buf[i++] = c; + } else if (c < 0x800) { + /* two bytes */ + buf[i++] = 0xC0 | (c >>> 6); + buf[i++] = 0x80 | (c & 0x3f); + } else if (c < 0x10000) { + /* three bytes */ + buf[i++] = 0xE0 | (c >>> 12); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } else { + /* four bytes */ + buf[i++] = 0xf0 | (c >>> 18); + buf[i++] = 0x80 | (c >>> 12 & 0x3f); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } + } + + return buf; +}; + +// Helper +const buf2binstring = (buf, len) => { + // On Chrome, the arguments in a function call that are allowed is `65534`. + // If the length of the buffer is smaller than that, we can use this optimization, + // otherwise we will take a slower path. + if (len < 65534) { + if (buf.subarray && STR_APPLY_UIA_OK) { + return String.fromCharCode.apply(null, buf.length === len ? buf : buf.subarray(0, len)); + } + } + + let result = ''; + for (let i = 0; i < len; i++) { + result += String.fromCharCode(buf[i]); + } + return result; +}; + + +// convert array to string +var buf2string = (buf, max) => { + const len = max || buf.length; + + if (typeof TextDecoder === 'function' && TextDecoder.prototype.decode) { + return new TextDecoder().decode(buf.subarray(0, max)); + } + + let i, out; + + // Reserve max possible length (2 words per char) + // NB: by unknown reasons, Array is significantly faster for + // String.fromCharCode.apply than Uint16Array. + const utf16buf = new Array(len * 2); + + for (out = 0, i = 0; i < len;) { + let c = buf[i++]; + // quick process ascii + if (c < 0x80) { utf16buf[out++] = c; continue; } + + let c_len = _utf8len[c]; + // skip 5 & 6 byte codes + if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len - 1; continue; } + + // apply mask on first byte + c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07; + // join the rest + while (c_len > 1 && i < len) { + c = (c << 6) | (buf[i++] & 0x3f); + c_len--; + } + + // terminated by end of string? + if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; } + + if (c < 0x10000) { + utf16buf[out++] = c; + } else { + c -= 0x10000; + utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff); + utf16buf[out++] = 0xdc00 | (c & 0x3ff); + } + } + + return buf2binstring(utf16buf, out); +}; + + +// Calculate max possible position in utf8 buffer, +// that will not break sequence. If that's not possible +// - (very small limits) return max size as is. +// +// buf[] - utf8 bytes array +// max - length limit (mandatory); +var utf8border = (buf, max) => { + + max = max || buf.length; + if (max > buf.length) { max = buf.length; } + + // go back from last position, until start of sequence found + let pos = max - 1; + while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; } + + // Very small and broken sequence, + // return max, because we should return something anyway. + if (pos < 0) { return max; } + + // If we came to start of buffer - that means buffer is too small, + // return max too. + if (pos === 0) { return max; } + + return (pos + _utf8len[buf[pos]] > max) ? pos : max; +}; + +var strings = { + string2buf: string2buf, + buf2string: buf2string, + utf8border: utf8border +}; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +function ZStream() { + /* next input byte */ + this.input = null; // JS specific, because we have no pointers + this.next_in = 0; + /* number of bytes available at input */ + this.avail_in = 0; + /* total number of input bytes read so far */ + this.total_in = 0; + /* next output byte should be put there */ + this.output = null; // JS specific, because we have no pointers + this.next_out = 0; + /* remaining free space at output */ + this.avail_out = 0; + /* total number of bytes output so far */ + this.total_out = 0; + /* last error message, NULL if no error */ + this.msg = ''/*Z_NULL*/; + /* not visible by applications */ + this.state = null; + /* best guess about the data type: binary or text */ + this.data_type = 2/*Z_UNKNOWN*/; + /* adler32 value of the uncompressed data */ + this.adler = 0; +} + +var zstream = ZStream; + +const toString$1 = Object.prototype.toString; + +/* Public constants ==========================================================*/ +/* ===========================================================================*/ + +const { + Z_NO_FLUSH: Z_NO_FLUSH$1, Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH: Z_FINISH$2, + Z_OK: Z_OK$2, Z_STREAM_END: Z_STREAM_END$2, + Z_DEFAULT_COMPRESSION, + Z_DEFAULT_STRATEGY, + Z_DEFLATED: Z_DEFLATED$1 +} = constants$2; + +/* ===========================================================================*/ + + +/** + * class Deflate + * + * Generic JS-style wrapper for zlib calls. If you don't need + * streaming behaviour - use more simple functions: [[deflate]], + * [[deflateRaw]] and [[gzip]]. + **/ + +/* internal + * Deflate.chunks -> Array + * + * Chunks of output data, if [[Deflate#onData]] not overridden. + **/ + +/** + * Deflate.result -> Uint8Array + * + * Compressed result, generated by default [[Deflate#onData]] + * and [[Deflate#onEnd]] handlers. Filled after you push last chunk + * (call [[Deflate#push]] with `Z_FINISH` / `true` param). + **/ + +/** + * Deflate.err -> Number + * + * Error code after deflate finished. 0 (Z_OK) on success. + * You will not need it in real life, because deflate errors + * are possible only on wrong options or bad `onData` / `onEnd` + * custom handlers. + **/ + +/** + * Deflate.msg -> String + * + * Error message, if [[Deflate.err]] != 0 + **/ + + +/** + * new Deflate(options) + * - options (Object): zlib deflate options. + * + * Creates new deflator instance with specified params. Throws exception + * on bad params. Supported options: + * + * - `level` + * - `windowBits` + * - `memLevel` + * - `strategy` + * - `dictionary` + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information on these. + * + * Additional options, for internal needs: + * + * - `chunkSize` - size of generated data chunks (16K by default) + * - `raw` (Boolean) - do raw deflate + * - `gzip` (Boolean) - create gzip wrapper + * - `header` (Object) - custom header for gzip + * - `text` (Boolean) - true if compressed data believed to be text + * - `time` (Number) - modification time, unix timestamp + * - `os` (Number) - operation system code + * - `extra` (Array) - array of bytes with extra data (max 65536) + * - `name` (String) - file name (binary string) + * - `comment` (String) - comment (binary string) + * - `hcrc` (Boolean) - true if header crc should be added + * + * ##### Example: + * + * ```javascript + * const pako = require('pako') + * , chunk1 = new Uint8Array([1,2,3,4,5,6,7,8,9]) + * , chunk2 = new Uint8Array([10,11,12,13,14,15,16,17,18,19]); + * + * const deflate = new pako.Deflate({ level: 3}); + * + * deflate.push(chunk1, false); + * deflate.push(chunk2, true); // true -> last chunk + * + * if (deflate.err) { throw new Error(deflate.err); } + * + * console.log(deflate.result); + * ``` + **/ +function Deflate$1(options) { + this.options = common.assign({ + level: Z_DEFAULT_COMPRESSION, + method: Z_DEFLATED$1, + chunkSize: 16384, + windowBits: 15, + memLevel: 8, + strategy: Z_DEFAULT_STRATEGY + }, options || {}); + + let opt = this.options; + + if (opt.raw && (opt.windowBits > 0)) { + opt.windowBits = -opt.windowBits; + } + + else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) { + opt.windowBits += 16; + } + + this.err = 0; // error code, if happens (0 = Z_OK) + this.msg = ''; // error message + this.ended = false; // used to avoid multiple onEnd() calls + this.chunks = []; // chunks of compressed data + + this.strm = new zstream(); + this.strm.avail_out = 0; + + let status = deflate_1$2.deflateInit2( + this.strm, + opt.level, + opt.method, + opt.windowBits, + opt.memLevel, + opt.strategy + ); + + if (status !== Z_OK$2) { + throw new Error(messages[status]); + } + + if (opt.header) { + deflate_1$2.deflateSetHeader(this.strm, opt.header); + } + + if (opt.dictionary) { + let dict; + // Convert data if needed + if (typeof opt.dictionary === 'string') { + // If we need to compress text, change encoding to utf8. + dict = strings.string2buf(opt.dictionary); + } else if (toString$1.call(opt.dictionary) === '[object ArrayBuffer]') { + dict = new Uint8Array(opt.dictionary); + } else { + dict = opt.dictionary; + } + + status = deflate_1$2.deflateSetDictionary(this.strm, dict); + + if (status !== Z_OK$2) { + throw new Error(messages[status]); + } + + this._dict_set = true; + } +} + +/** + * Deflate#push(data[, flush_mode]) -> Boolean + * - data (Uint8Array|ArrayBuffer|String): input data. Strings will be + * converted to utf8 byte sequence. + * - flush_mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. + * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. + * + * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with + * new compressed chunks. Returns `true` on success. The last data block must + * have `flush_mode` Z_FINISH (or `true`). That will flush internal pending + * buffers and call [[Deflate#onEnd]]. + * + * On fail call [[Deflate#onEnd]] with error code and return false. + * + * ##### Example + * + * ```javascript + * push(chunk, false); // push one of data chunks + * ... + * push(chunk, true); // push last chunk + * ``` + **/ +Deflate$1.prototype.push = function (data, flush_mode) { + const strm = this.strm; + const chunkSize = this.options.chunkSize; + let status, _flush_mode; + + if (this.ended) { return false; } + + if (flush_mode === ~~flush_mode) _flush_mode = flush_mode; + else _flush_mode = flush_mode === true ? Z_FINISH$2 : Z_NO_FLUSH$1; + + // Convert data if needed + if (typeof data === 'string') { + // If we need to compress text, change encoding to utf8. + strm.input = strings.string2buf(data); + } else if (toString$1.call(data) === '[object ArrayBuffer]') { + strm.input = new Uint8Array(data); + } else { + strm.input = data; + } + + strm.next_in = 0; + strm.avail_in = strm.input.length; + + for (;;) { + if (strm.avail_out === 0) { + strm.output = new Uint8Array(chunkSize); + strm.next_out = 0; + strm.avail_out = chunkSize; + } + + // Make sure avail_out > 6 to avoid repeating markers + if ((_flush_mode === Z_SYNC_FLUSH || _flush_mode === Z_FULL_FLUSH) && strm.avail_out <= 6) { + this.onData(strm.output.subarray(0, strm.next_out)); + strm.avail_out = 0; + continue; + } + + status = deflate_1$2.deflate(strm, _flush_mode); + + // Ended => flush and finish + if (status === Z_STREAM_END$2) { + if (strm.next_out > 0) { + this.onData(strm.output.subarray(0, strm.next_out)); + } + status = deflate_1$2.deflateEnd(this.strm); + this.onEnd(status); + this.ended = true; + return status === Z_OK$2; + } + + // Flush if out buffer full + if (strm.avail_out === 0) { + this.onData(strm.output); + continue; + } + + // Flush if requested and has data + if (_flush_mode > 0 && strm.next_out > 0) { + this.onData(strm.output.subarray(0, strm.next_out)); + strm.avail_out = 0; + continue; + } + + if (strm.avail_in === 0) break; + } + + return true; +}; + + +/** + * Deflate#onData(chunk) -> Void + * - chunk (Uint8Array): output data. + * + * By default, stores data blocks in `chunks[]` property and glue + * those in `onEnd`. Override this handler, if you need another behaviour. + **/ +Deflate$1.prototype.onData = function (chunk) { + this.chunks.push(chunk); +}; + + +/** + * Deflate#onEnd(status) -> Void + * - status (Number): deflate status. 0 (Z_OK) on success, + * other if not. + * + * Called once after you tell deflate that the input stream is + * complete (Z_FINISH). By default - join collected chunks, + * free memory and fill `results` / `err` properties. + **/ +Deflate$1.prototype.onEnd = function (status) { + // On success - join + if (status === Z_OK$2) { + this.result = common.flattenChunks(this.chunks); + } + this.chunks = []; + this.err = status; + this.msg = this.strm.msg; +}; + + +/** + * deflate(data[, options]) -> Uint8Array + * - data (Uint8Array|ArrayBuffer|String): input data to compress. + * - options (Object): zlib deflate options. + * + * Compress `data` with deflate algorithm and `options`. + * + * Supported options are: + * + * - level + * - windowBits + * - memLevel + * - strategy + * - dictionary + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information on these. + * + * Sugar (options): + * + * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify + * negative windowBits implicitly. + * + * ##### Example: + * + * ```javascript + * const pako = require('pako') + * const data = new Uint8Array([1,2,3,4,5,6,7,8,9]); + * + * console.log(pako.deflate(data)); + * ``` + **/ +function deflate$1(input, options) { + const deflator = new Deflate$1(options); + + deflator.push(input, true); + + // That will never happens, if you don't cheat with options :) + if (deflator.err) { throw deflator.msg || messages[deflator.err]; } + + return deflator.result; +} + + +/** + * deflateRaw(data[, options]) -> Uint8Array + * - data (Uint8Array|ArrayBuffer|String): input data to compress. + * - options (Object): zlib deflate options. + * + * The same as [[deflate]], but creates raw data, without wrapper + * (header and adler32 crc). + **/ +function deflateRaw$1(input, options) { + options = options || {}; + options.raw = true; + return deflate$1(input, options); +} + + +/** + * gzip(data[, options]) -> Uint8Array + * - data (Uint8Array|ArrayBuffer|String): input data to compress. + * - options (Object): zlib deflate options. + * + * The same as [[deflate]], but create gzip wrapper instead of + * deflate one. + **/ +function gzip$1(input, options) { + options = options || {}; + options.gzip = true; + return deflate$1(input, options); +} + + +var Deflate_1$1 = Deflate$1; +var deflate_2 = deflate$1; +var deflateRaw_1$1 = deflateRaw$1; +var gzip_1$1 = gzip$1; +var constants$1 = constants$2; + +var deflate_1$1 = { + Deflate: Deflate_1$1, + deflate: deflate_2, + deflateRaw: deflateRaw_1$1, + gzip: gzip_1$1, + constants: constants$1 +}; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +// See state defs from inflate.js +const BAD$1 = 16209; /* got a data error -- remain here until reset */ +const TYPE$1 = 16191; /* i: waiting for type bits, including last-flag bit */ + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state.mode === LEN + strm.avail_in >= 6 + strm.avail_out >= 258 + start >= strm.avail_out + state.bits < 8 + + On return, state.mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm.avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm.avail_out >= 258 for each loop to avoid checking for + output space. + */ +var inffast = function inflate_fast(strm, start) { + let _in; /* local strm.input */ + let last; /* have enough input while in < last */ + let _out; /* local strm.output */ + let beg; /* inflate()'s initial strm.output */ + let end; /* while out < end, enough space available */ +//#ifdef INFLATE_STRICT + let dmax; /* maximum distance from zlib header */ +//#endif + let wsize; /* window size or zero if not using window */ + let whave; /* valid bytes in the window */ + let wnext; /* window write index */ + // Use `s_window` instead `window`, avoid conflict with instrumentation tools + let s_window; /* allocated sliding window, if wsize != 0 */ + let hold; /* local strm.hold */ + let bits; /* local strm.bits */ + let lcode; /* local strm.lencode */ + let dcode; /* local strm.distcode */ + let lmask; /* mask for first level of length codes */ + let dmask; /* mask for first level of distance codes */ + let here; /* retrieved table entry */ + let op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + let len; /* match length, unused bytes */ + let dist; /* match distance */ + let from; /* where to copy match from */ + let from_source; + + + let input, output; // JS specific, because we have no pointers + + /* copy state to local variables */ + const state = strm.state; + //here = state.here; + _in = strm.next_in; + input = strm.input; + last = _in + (strm.avail_in - 5); + _out = strm.next_out; + output = strm.output; + beg = _out - (start - strm.avail_out); + end = _out + (strm.avail_out - 257); +//#ifdef INFLATE_STRICT + dmax = state.dmax; +//#endif + wsize = state.wsize; + whave = state.whave; + wnext = state.wnext; + s_window = state.window; + hold = state.hold; + bits = state.bits; + lcode = state.lencode; + dcode = state.distcode; + lmask = (1 << state.lenbits) - 1; + dmask = (1 << state.distbits) - 1; + + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + + top: + do { + if (bits < 15) { + hold += input[_in++] << bits; + bits += 8; + hold += input[_in++] << bits; + bits += 8; + } + + here = lcode[hold & lmask]; + + dolen: + for (;;) { // Goto emulation + op = here >>> 24/*here.bits*/; + hold >>>= op; + bits -= op; + op = (here >>> 16) & 0xff/*here.op*/; + if (op === 0) { /* literal */ + //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + // "inflate: literal '%c'\n" : + // "inflate: literal 0x%02x\n", here.val)); + output[_out++] = here & 0xffff/*here.val*/; + } + else if (op & 16) { /* length base */ + len = here & 0xffff/*here.val*/; + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + } + len += hold & ((1 << op) - 1); + hold >>>= op; + bits -= op; + } + //Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += input[_in++] << bits; + bits += 8; + hold += input[_in++] << bits; + bits += 8; + } + here = dcode[hold & dmask]; + + dodist: + for (;;) { // goto emulation + op = here >>> 24/*here.bits*/; + hold >>>= op; + bits -= op; + op = (here >>> 16) & 0xff/*here.op*/; + + if (op & 16) { /* distance base */ + dist = here & 0xffff/*here.val*/; + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + } + } + dist += hold & ((1 << op) - 1); +//#ifdef INFLATE_STRICT + if (dist > dmax) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD$1; + break top; + } +//#endif + hold >>>= op; + bits -= op; + //Tracevv((stderr, "inflate: distance %u\n", dist)); + op = _out - beg; /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state.sane) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD$1; + break top; + } + +// (!) This block is disabled in zlib defaults, +// don't enable it for binary compatibility +//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR +// if (len <= op - whave) { +// do { +// output[_out++] = 0; +// } while (--len); +// continue top; +// } +// len -= op - whave; +// do { +// output[_out++] = 0; +// } while (--op > whave); +// if (op === 0) { +// from = _out - dist; +// do { +// output[_out++] = output[from++]; +// } while (--len); +// continue top; +// } +//#endif + } + from = 0; // window index + from_source = s_window; + if (wnext === 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = 0; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + } + else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + while (len > 2) { + output[_out++] = from_source[from++]; + output[_out++] = from_source[from++]; + output[_out++] = from_source[from++]; + len -= 3; + } + if (len) { + output[_out++] = from_source[from++]; + if (len > 1) { + output[_out++] = from_source[from++]; + } + } + } + else { + from = _out - dist; /* copy direct from output */ + do { /* minimum length is three */ + output[_out++] = output[from++]; + output[_out++] = output[from++]; + output[_out++] = output[from++]; + len -= 3; + } while (len > 2); + if (len) { + output[_out++] = output[from++]; + if (len > 1) { + output[_out++] = output[from++]; + } + } + } + } + else if ((op & 64) === 0) { /* 2nd level distance code */ + here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; + continue dodist; + } + else { + strm.msg = 'invalid distance code'; + state.mode = BAD$1; + break top; + } + + break; // need to emulate goto via "continue" + } + } + else if ((op & 64) === 0) { /* 2nd level length code */ + here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; + continue dolen; + } + else if (op & 32) { /* end-of-block */ + //Tracevv((stderr, "inflate: end of block\n")); + state.mode = TYPE$1; + break top; + } + else { + strm.msg = 'invalid literal/length code'; + state.mode = BAD$1; + break top; + } + + break; // need to emulate goto via "continue" + } + } while (_in < last && _out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + _in -= len; + bits -= len << 3; + hold &= (1 << bits) - 1; + + /* update state and return */ + strm.next_in = _in; + strm.next_out = _out; + strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last)); + strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end)); + state.hold = hold; + state.bits = bits; + return; +}; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +const MAXBITS = 15; +const ENOUGH_LENS$1 = 852; +const ENOUGH_DISTS$1 = 592; +//const ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); + +const CODES$1 = 0; +const LENS$1 = 1; +const DISTS$1 = 2; + +const lbase = new Uint16Array([ /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 +]); + +const lext = new Uint8Array([ /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78 +]); + +const dbase = new Uint16Array([ /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0 +]); + +const dext = new Uint8Array([ /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64 +]); + +const inflate_table = (type, lens, lens_index, codes, table, table_index, work, opts) => +{ + const bits = opts.bits; + //here = opts.here; /* table entry for duplication */ + + let len = 0; /* a code's length in bits */ + let sym = 0; /* index of code symbols */ + let min = 0, max = 0; /* minimum and maximum code lengths */ + let root = 0; /* number of index bits for root table */ + let curr = 0; /* number of index bits for current table */ + let drop = 0; /* code bits to drop for sub-table */ + let left = 0; /* number of prefix codes available */ + let used = 0; /* code entries in table used */ + let huff = 0; /* Huffman code */ + let incr; /* for incrementing code, index */ + let fill; /* index for replicating entries */ + let low; /* low bits for current root entry */ + let mask; /* mask for low root bits */ + let next; /* next available space in table */ + let base = null; /* base value table to use */ +// let shoextra; /* extra bits table to use */ + let match; /* use base and extra for symbol >= match */ + const count = new Uint16Array(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */ + const offs = new Uint16Array(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */ + let extra = null; + + let here_bits, here_op, here_val; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) { + count[len] = 0; + } + for (sym = 0; sym < codes; sym++) { + count[lens[lens_index + sym]]++; + } + + /* bound code lengths, force root to be within code lengths */ + root = bits; + for (max = MAXBITS; max >= 1; max--) { + if (count[max] !== 0) { break; } + } + if (root > max) { + root = max; + } + if (max === 0) { /* no symbols to code at all */ + //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */ + //table.bits[opts.table_index] = 1; //here.bits = (var char)1; + //table.val[opts.table_index++] = 0; //here.val = (var short)0; + table[table_index++] = (1 << 24) | (64 << 16) | 0; + + + //table.op[opts.table_index] = 64; + //table.bits[opts.table_index] = 1; + //table.val[opts.table_index++] = 0; + table[table_index++] = (1 << 24) | (64 << 16) | 0; + + opts.bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) { + if (count[min] !== 0) { break; } + } + if (root < min) { + root = min; + } + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) { + return -1; + } /* over-subscribed */ + } + if (left > 0 && (type === CODES$1 || max !== 1)) { + return -1; /* incomplete set */ + } + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) { + offs[len + 1] = offs[len] + count[len]; + } + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) { + if (lens[lens_index + sym] !== 0) { + work[offs[lens[lens_index + sym]]++] = sym; + } + } + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + // poor man optimization - use if-else instead of switch, + // to avoid deopts in old v8 + if (type === CODES$1) { + base = extra = work; /* dummy value--not used */ + match = 20; + + } else if (type === LENS$1) { + base = lbase; + extra = lext; + match = 257; + + } else { /* DISTS */ + base = dbase; + extra = dext; + match = 0; + } + + /* initialize opts for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = table_index; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = -1; /* trigger new sub-table when len > root */ + used = 1 << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type === LENS$1 && used > ENOUGH_LENS$1) || + (type === DISTS$1 && used > ENOUGH_DISTS$1)) { + return 1; + } + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here_bits = len - drop; + if (work[sym] + 1 < match) { + here_op = 0; + here_val = work[sym]; + } + else if (work[sym] >= match) { + here_op = extra[work[sym] - match]; + here_val = base[work[sym] - match]; + } + else { + here_op = 32 + 64; /* end of block */ + here_val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1 << (len - drop); + fill = 1 << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0; + } while (fill !== 0); + + /* backwards increment the len-bit code huff */ + incr = 1 << (len - 1); + while (huff & incr) { + incr >>= 1; + } + if (incr !== 0) { + huff &= incr - 1; + huff += incr; + } else { + huff = 0; + } + + /* go to next symbol, update count, len */ + sym++; + if (--count[len] === 0) { + if (len === max) { break; } + len = lens[lens_index + work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) !== low) { + /* if first time, transition to sub-tables */ + if (drop === 0) { + drop = root; + } + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = 1 << curr; + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) { break; } + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1 << curr; + if ((type === LENS$1 && used > ENOUGH_LENS$1) || + (type === DISTS$1 && used > ENOUGH_DISTS$1)) { + return 1; + } + + /* point entry in root table to sub-table */ + low = huff & mask; + /*table.op[low] = curr; + table.bits[low] = root; + table.val[low] = next - opts.table_index;*/ + table[low] = (root << 24) | (curr << 16) | (next - table_index) |0; + } + } + + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (huff !== 0) { + //table.op[next + huff] = 64; /* invalid code marker */ + //table.bits[next + huff] = len - drop; + //table.val[next + huff] = 0; + table[next + huff] = ((len - drop) << 24) | (64 << 16) |0; + } + + /* set return parameters */ + //opts.table_index += used; + opts.bits = root; + return 0; +}; + + +var inftrees = inflate_table; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + + + + + + +const CODES = 0; +const LENS = 1; +const DISTS = 2; + +/* Public constants ==========================================================*/ +/* ===========================================================================*/ + +const { + Z_FINISH: Z_FINISH$1, Z_BLOCK, Z_TREES, + Z_OK: Z_OK$1, Z_STREAM_END: Z_STREAM_END$1, Z_NEED_DICT: Z_NEED_DICT$1, Z_STREAM_ERROR: Z_STREAM_ERROR$1, Z_DATA_ERROR: Z_DATA_ERROR$1, Z_MEM_ERROR: Z_MEM_ERROR$1, Z_BUF_ERROR, + Z_DEFLATED +} = constants$2; + + +/* STATES ====================================================================*/ +/* ===========================================================================*/ + + +const HEAD = 16180; /* i: waiting for magic header */ +const FLAGS = 16181; /* i: waiting for method and flags (gzip) */ +const TIME = 16182; /* i: waiting for modification time (gzip) */ +const OS = 16183; /* i: waiting for extra flags and operating system (gzip) */ +const EXLEN = 16184; /* i: waiting for extra length (gzip) */ +const EXTRA = 16185; /* i: waiting for extra bytes (gzip) */ +const NAME = 16186; /* i: waiting for end of file name (gzip) */ +const COMMENT = 16187; /* i: waiting for end of comment (gzip) */ +const HCRC = 16188; /* i: waiting for header crc (gzip) */ +const DICTID = 16189; /* i: waiting for dictionary check value */ +const DICT = 16190; /* waiting for inflateSetDictionary() call */ +const TYPE = 16191; /* i: waiting for type bits, including last-flag bit */ +const TYPEDO = 16192; /* i: same, but skip check to exit inflate on new block */ +const STORED = 16193; /* i: waiting for stored size (length and complement) */ +const COPY_ = 16194; /* i/o: same as COPY below, but only first time in */ +const COPY = 16195; /* i/o: waiting for input or output to copy stored block */ +const TABLE = 16196; /* i: waiting for dynamic block table lengths */ +const LENLENS = 16197; /* i: waiting for code length code lengths */ +const CODELENS = 16198; /* i: waiting for length/lit and distance code lengths */ +const LEN_ = 16199; /* i: same as LEN below, but only first time in */ +const LEN = 16200; /* i: waiting for length/lit/eob code */ +const LENEXT = 16201; /* i: waiting for length extra bits */ +const DIST = 16202; /* i: waiting for distance code */ +const DISTEXT = 16203; /* i: waiting for distance extra bits */ +const MATCH = 16204; /* o: waiting for output space to copy string */ +const LIT = 16205; /* o: waiting for output space to write literal */ +const CHECK = 16206; /* i: waiting for 32-bit check value */ +const LENGTH = 16207; /* i: waiting for 32-bit length (gzip) */ +const DONE = 16208; /* finished check, done -- remain here until reset */ +const BAD = 16209; /* got a data error -- remain here until reset */ +const MEM = 16210; /* got an inflate() memory error -- remain here until reset */ +const SYNC = 16211; /* looking for synchronization bytes to restart inflate() */ + +/* ===========================================================================*/ + + + +const ENOUGH_LENS = 852; +const ENOUGH_DISTS = 592; +//const ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); + +const MAX_WBITS = 15; +/* 32K LZ77 window */ +const DEF_WBITS = MAX_WBITS; + + +const zswap32 = (q) => { + + return (((q >>> 24) & 0xff) + + ((q >>> 8) & 0xff00) + + ((q & 0xff00) << 8) + + ((q & 0xff) << 24)); +}; + + +function InflateState() { + this.strm = null; /* pointer back to this zlib stream */ + this.mode = 0; /* current inflate mode */ + this.last = false; /* true if processing last block */ + this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip, + bit 2 true to validate check value */ + this.havedict = false; /* true if dictionary provided */ + this.flags = 0; /* gzip header method and flags (0 if zlib), or + -1 if raw or no header yet */ + this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */ + this.check = 0; /* protected copy of check value */ + this.total = 0; /* protected copy of output count */ + // TODO: may be {} + this.head = null; /* where to save gzip header information */ + + /* sliding window */ + this.wbits = 0; /* log base 2 of requested window size */ + this.wsize = 0; /* window size or zero if not using window */ + this.whave = 0; /* valid bytes in the window */ + this.wnext = 0; /* window write index */ + this.window = null; /* allocated sliding window, if needed */ + + /* bit accumulator */ + this.hold = 0; /* input bit accumulator */ + this.bits = 0; /* number of bits in "in" */ + + /* for string and stored block copying */ + this.length = 0; /* literal or length of data to copy */ + this.offset = 0; /* distance back to copy string from */ + + /* for table and code decoding */ + this.extra = 0; /* extra bits needed */ + + /* fixed and dynamic code tables */ + this.lencode = null; /* starting table for length/literal codes */ + this.distcode = null; /* starting table for distance codes */ + this.lenbits = 0; /* index bits for lencode */ + this.distbits = 0; /* index bits for distcode */ + + /* dynamic table building */ + this.ncode = 0; /* number of code length code lengths */ + this.nlen = 0; /* number of length code lengths */ + this.ndist = 0; /* number of distance code lengths */ + this.have = 0; /* number of code lengths in lens[] */ + this.next = null; /* next available space in codes[] */ + + this.lens = new Uint16Array(320); /* temporary storage for code lengths */ + this.work = new Uint16Array(288); /* work area for code table building */ + + /* + because we don't have pointers in js, we use lencode and distcode directly + as buffers so we don't need codes + */ + //this.codes = new Int32Array(ENOUGH); /* space for code tables */ + this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */ + this.distdyn = null; /* dynamic table for distance codes (JS specific) */ + this.sane = 0; /* if false, allow invalid distance too far */ + this.back = 0; /* bits back of last unprocessed length/lit */ + this.was = 0; /* initial length of match */ +} + + +const inflateStateCheck = (strm) => { + + if (!strm) { + return 1; + } + const state = strm.state; + if (!state || state.strm !== strm || + state.mode < HEAD || state.mode > SYNC) { + return 1; + } + return 0; +}; + + +const inflateResetKeep = (strm) => { + + if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; } + const state = strm.state; + strm.total_in = strm.total_out = state.total = 0; + strm.msg = ''; /*Z_NULL*/ + if (state.wrap) { /* to support ill-conceived Java test suite */ + strm.adler = state.wrap & 1; + } + state.mode = HEAD; + state.last = 0; + state.havedict = 0; + state.flags = -1; + state.dmax = 32768; + state.head = null/*Z_NULL*/; + state.hold = 0; + state.bits = 0; + //state.lencode = state.distcode = state.next = state.codes; + state.lencode = state.lendyn = new Int32Array(ENOUGH_LENS); + state.distcode = state.distdyn = new Int32Array(ENOUGH_DISTS); + + state.sane = 1; + state.back = -1; + //Tracev((stderr, "inflate: reset\n")); + return Z_OK$1; +}; + + +const inflateReset = (strm) => { + + if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; } + const state = strm.state; + state.wsize = 0; + state.whave = 0; + state.wnext = 0; + return inflateResetKeep(strm); + +}; + + +const inflateReset2 = (strm, windowBits) => { + let wrap; + + /* get the state */ + if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; } + const state = strm.state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 5; + if (windowBits < 48) { + windowBits &= 15; + } + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) { + return Z_STREAM_ERROR$1; + } + if (state.window !== null && state.wbits !== windowBits) { + state.window = null; + } + + /* update state and reset the rest of it */ + state.wrap = wrap; + state.wbits = windowBits; + return inflateReset(strm); +}; + + +const inflateInit2 = (strm, windowBits) => { + + if (!strm) { return Z_STREAM_ERROR$1; } + //strm.msg = Z_NULL; /* in case we return an error */ + + const state = new InflateState(); + + //if (state === Z_NULL) return Z_MEM_ERROR; + //Tracev((stderr, "inflate: allocated\n")); + strm.state = state; + state.strm = strm; + state.window = null/*Z_NULL*/; + state.mode = HEAD; /* to pass state test in inflateReset2() */ + const ret = inflateReset2(strm, windowBits); + if (ret !== Z_OK$1) { + strm.state = null/*Z_NULL*/; + } + return ret; +}; + + +const inflateInit = (strm) => { + + return inflateInit2(strm, DEF_WBITS); +}; + + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +let virgin = true; + +let lenfix, distfix; // We have no pointers in JS, so keep tables separate + + +const fixedtables = (state) => { + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + lenfix = new Int32Array(512); + distfix = new Int32Array(32); + + /* literal/length table */ + let sym = 0; + while (sym < 144) { state.lens[sym++] = 8; } + while (sym < 256) { state.lens[sym++] = 9; } + while (sym < 280) { state.lens[sym++] = 7; } + while (sym < 288) { state.lens[sym++] = 8; } + + inftrees(LENS, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 }); + + /* distance table */ + sym = 0; + while (sym < 32) { state.lens[sym++] = 5; } + + inftrees(DISTS, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 }); + + /* do this just once */ + virgin = false; + } + + state.lencode = lenfix; + state.lenbits = 9; + state.distcode = distfix; + state.distbits = 5; +}; + + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +const updatewindow = (strm, src, end, copy) => { + + let dist; + const state = strm.state; + + /* if it hasn't been done already, allocate space for the window */ + if (state.window === null) { + state.wsize = 1 << state.wbits; + state.wnext = 0; + state.whave = 0; + + state.window = new Uint8Array(state.wsize); + } + + /* copy state->wsize or less output bytes into the circular window */ + if (copy >= state.wsize) { + state.window.set(src.subarray(end - state.wsize, end), 0); + state.wnext = 0; + state.whave = state.wsize; + } + else { + dist = state.wsize - state.wnext; + if (dist > copy) { + dist = copy; + } + //zmemcpy(state->window + state->wnext, end - copy, dist); + state.window.set(src.subarray(end - copy, end - copy + dist), state.wnext); + copy -= dist; + if (copy) { + //zmemcpy(state->window, end - copy, copy); + state.window.set(src.subarray(end - copy, end), 0); + state.wnext = copy; + state.whave = state.wsize; + } + else { + state.wnext += dist; + if (state.wnext === state.wsize) { state.wnext = 0; } + if (state.whave < state.wsize) { state.whave += dist; } + } + } + return 0; +}; + + +const inflate$2 = (strm, flush) => { + + let state; + let input, output; // input/output buffers + let next; /* next input INDEX */ + let put; /* next output INDEX */ + let have, left; /* available input and output */ + let hold; /* bit buffer */ + let bits; /* bits in bit buffer */ + let _in, _out; /* save starting available input and output */ + let copy; /* number of stored or match bytes to copy */ + let from; /* where to copy match bytes from */ + let from_source; + let here = 0; /* current decoding table entry */ + let here_bits, here_op, here_val; // paked "here" denormalized (JS specific) + //let last; /* parent table entry */ + let last_bits, last_op, last_val; // paked "last" denormalized (JS specific) + let len; /* length to copy for repeats, bits to drop */ + let ret; /* return code */ + const hbuf = new Uint8Array(4); /* buffer for gzip header crc calculation */ + let opts; + + let n; // temporary variable for NEED_BITS + + const order = /* permutation of code lengths */ + new Uint8Array([ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]); + + + if (inflateStateCheck(strm) || !strm.output || + (!strm.input && strm.avail_in !== 0)) { + return Z_STREAM_ERROR$1; + } + + state = strm.state; + if (state.mode === TYPE) { state.mode = TYPEDO; } /* skip check */ + + + //--- LOAD() --- + put = strm.next_out; + output = strm.output; + left = strm.avail_out; + next = strm.next_in; + input = strm.input; + have = strm.avail_in; + hold = state.hold; + bits = state.bits; + //--- + + _in = have; + _out = left; + ret = Z_OK$1; + + inf_leave: // goto emulation + for (;;) { + switch (state.mode) { + case HEAD: + if (state.wrap === 0) { + state.mode = TYPEDO; + break; + } + //=== NEEDBITS(16); + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */ + if (state.wbits === 0) { + state.wbits = 15; + } + state.check = 0/*crc32(0L, Z_NULL, 0)*/; + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32_1(state.check, hbuf, 2, 0); + //===// + + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = FLAGS; + break; + } + if (state.head) { + state.head.done = false; + } + if (!(state.wrap & 1) || /* check if zlib header allowed */ + (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) { + strm.msg = 'incorrect header check'; + state.mode = BAD; + break; + } + if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) { + strm.msg = 'unknown compression method'; + state.mode = BAD; + break; + } + //--- DROPBITS(4) ---// + hold >>>= 4; + bits -= 4; + //---// + len = (hold & 0x0f)/*BITS(4)*/ + 8; + if (state.wbits === 0) { + state.wbits = len; + } + if (len > 15 || len > state.wbits) { + strm.msg = 'invalid window size'; + state.mode = BAD; + break; + } + + // !!! pako patch. Force use `options.windowBits` if passed. + // Required to always use max window size by default. + state.dmax = 1 << state.wbits; + //state.dmax = 1 << len; + + state.flags = 0; /* indicate zlib header */ + //Tracev((stderr, "inflate: zlib header ok\n")); + strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; + state.mode = hold & 0x200 ? DICTID : TYPE; + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + break; + case FLAGS: + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.flags = hold; + if ((state.flags & 0xff) !== Z_DEFLATED) { + strm.msg = 'unknown compression method'; + state.mode = BAD; + break; + } + if (state.flags & 0xe000) { + strm.msg = 'unknown header flags set'; + state.mode = BAD; + break; + } + if (state.head) { + state.head.text = ((hold >> 8) & 1); + } + if ((state.flags & 0x0200) && (state.wrap & 4)) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32_1(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = TIME; + /* falls through */ + case TIME: + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (state.head) { + state.head.time = hold; + } + if ((state.flags & 0x0200) && (state.wrap & 4)) { + //=== CRC4(state.check, hold) + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + hbuf[2] = (hold >>> 16) & 0xff; + hbuf[3] = (hold >>> 24) & 0xff; + state.check = crc32_1(state.check, hbuf, 4, 0); + //=== + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = OS; + /* falls through */ + case OS: + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (state.head) { + state.head.xflags = (hold & 0xff); + state.head.os = (hold >> 8); + } + if ((state.flags & 0x0200) && (state.wrap & 4)) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32_1(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = EXLEN; + /* falls through */ + case EXLEN: + if (state.flags & 0x0400) { + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.length = hold; + if (state.head) { + state.head.extra_len = hold; + } + if ((state.flags & 0x0200) && (state.wrap & 4)) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32_1(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + } + else if (state.head) { + state.head.extra = null/*Z_NULL*/; + } + state.mode = EXTRA; + /* falls through */ + case EXTRA: + if (state.flags & 0x0400) { + copy = state.length; + if (copy > have) { copy = have; } + if (copy) { + if (state.head) { + len = state.head.extra_len - state.length; + if (!state.head.extra) { + // Use untyped array for more convenient processing later + state.head.extra = new Uint8Array(state.head.extra_len); + } + state.head.extra.set( + input.subarray( + next, + // extra field is limited to 65536 bytes + // - no need for additional size check + next + copy + ), + /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/ + len + ); + //zmemcpy(state.head.extra + len, next, + // len + copy > state.head.extra_max ? + // state.head.extra_max - len : copy); + } + if ((state.flags & 0x0200) && (state.wrap & 4)) { + state.check = crc32_1(state.check, input, copy, next); + } + have -= copy; + next += copy; + state.length -= copy; + } + if (state.length) { break inf_leave; } + } + state.length = 0; + state.mode = NAME; + /* falls through */ + case NAME: + if (state.flags & 0x0800) { + if (have === 0) { break inf_leave; } + copy = 0; + do { + // TODO: 2 or 1 bytes? + len = input[next + copy++]; + /* use constant limit because in js we should not preallocate memory */ + if (state.head && len && + (state.length < 65536 /*state.head.name_max*/)) { + state.head.name += String.fromCharCode(len); + } + } while (len && copy < have); + + if ((state.flags & 0x0200) && (state.wrap & 4)) { + state.check = crc32_1(state.check, input, copy, next); + } + have -= copy; + next += copy; + if (len) { break inf_leave; } + } + else if (state.head) { + state.head.name = null; + } + state.length = 0; + state.mode = COMMENT; + /* falls through */ + case COMMENT: + if (state.flags & 0x1000) { + if (have === 0) { break inf_leave; } + copy = 0; + do { + len = input[next + copy++]; + /* use constant limit because in js we should not preallocate memory */ + if (state.head && len && + (state.length < 65536 /*state.head.comm_max*/)) { + state.head.comment += String.fromCharCode(len); + } + } while (len && copy < have); + if ((state.flags & 0x0200) && (state.wrap & 4)) { + state.check = crc32_1(state.check, input, copy, next); + } + have -= copy; + next += copy; + if (len) { break inf_leave; } + } + else if (state.head) { + state.head.comment = null; + } + state.mode = HCRC; + /* falls through */ + case HCRC: + if (state.flags & 0x0200) { + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((state.wrap & 4) && hold !== (state.check & 0xffff)) { + strm.msg = 'header crc mismatch'; + state.mode = BAD; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + } + if (state.head) { + state.head.hcrc = ((state.flags >> 9) & 1); + state.head.done = true; + } + strm.adler = state.check = 0; + state.mode = TYPE; + break; + case DICTID: + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + strm.adler = state.check = zswap32(hold); + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = DICT; + /* falls through */ + case DICT: + if (state.havedict === 0) { + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + return Z_NEED_DICT$1; + } + strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; + state.mode = TYPE; + /* falls through */ + case TYPE: + if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; } + /* falls through */ + case TYPEDO: + if (state.last) { + //--- BYTEBITS() ---// + hold >>>= bits & 7; + bits -= bits & 7; + //---// + state.mode = CHECK; + break; + } + //=== NEEDBITS(3); */ + while (bits < 3) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.last = (hold & 0x01)/*BITS(1)*/; + //--- DROPBITS(1) ---// + hold >>>= 1; + bits -= 1; + //---// + + switch ((hold & 0x03)/*BITS(2)*/) { + case 0: /* stored block */ + //Tracev((stderr, "inflate: stored block%s\n", + // state.last ? " (last)" : "")); + state.mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + //Tracev((stderr, "inflate: fixed codes block%s\n", + // state.last ? " (last)" : "")); + state.mode = LEN_; /* decode codes */ + if (flush === Z_TREES) { + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + break inf_leave; + } + break; + case 2: /* dynamic block */ + //Tracev((stderr, "inflate: dynamic codes block%s\n", + // state.last ? " (last)" : "")); + state.mode = TABLE; + break; + case 3: + strm.msg = 'invalid block type'; + state.mode = BAD; + } + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + break; + case STORED: + //--- BYTEBITS() ---// /* go to byte boundary */ + hold >>>= bits & 7; + bits -= bits & 7; + //---// + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) { + strm.msg = 'invalid stored block lengths'; + state.mode = BAD; + break; + } + state.length = hold & 0xffff; + //Tracev((stderr, "inflate: stored length %u\n", + // state.length)); + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = COPY_; + if (flush === Z_TREES) { break inf_leave; } + /* falls through */ + case COPY_: + state.mode = COPY; + /* falls through */ + case COPY: + copy = state.length; + if (copy) { + if (copy > have) { copy = have; } + if (copy > left) { copy = left; } + if (copy === 0) { break inf_leave; } + //--- zmemcpy(put, next, copy); --- + output.set(input.subarray(next, next + copy), put); + //---// + have -= copy; + next += copy; + left -= copy; + put += copy; + state.length -= copy; + break; + } + //Tracev((stderr, "inflate: stored end\n")); + state.mode = TYPE; + break; + case TABLE: + //=== NEEDBITS(14); */ + while (bits < 14) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257; + //--- DROPBITS(5) ---// + hold >>>= 5; + bits -= 5; + //---// + state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1; + //--- DROPBITS(5) ---// + hold >>>= 5; + bits -= 5; + //---// + state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4; + //--- DROPBITS(4) ---// + hold >>>= 4; + bits -= 4; + //---// +//#ifndef PKZIP_BUG_WORKAROUND + if (state.nlen > 286 || state.ndist > 30) { + strm.msg = 'too many length or distance symbols'; + state.mode = BAD; + break; + } +//#endif + //Tracev((stderr, "inflate: table sizes ok\n")); + state.have = 0; + state.mode = LENLENS; + /* falls through */ + case LENLENS: + while (state.have < state.ncode) { + //=== NEEDBITS(3); + while (bits < 3) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.lens[order[state.have++]] = (hold & 0x07);//BITS(3); + //--- DROPBITS(3) ---// + hold >>>= 3; + bits -= 3; + //---// + } + while (state.have < 19) { + state.lens[order[state.have++]] = 0; + } + // We have separate tables & no pointers. 2 commented lines below not needed. + //state.next = state.codes; + //state.lencode = state.next; + // Switch to use dynamic table + state.lencode = state.lendyn; + state.lenbits = 7; + + opts = { bits: state.lenbits }; + ret = inftrees(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts); + state.lenbits = opts.bits; + + if (ret) { + strm.msg = 'invalid code lengths set'; + state.mode = BAD; + break; + } + //Tracev((stderr, "inflate: code lengths ok\n")); + state.have = 0; + state.mode = CODELENS; + /* falls through */ + case CODELENS: + while (state.have < state.nlen + state.ndist) { + for (;;) { + here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if (here_val < 16) { + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.lens[state.have++] = here_val; + } + else { + if (here_val === 16) { + //=== NEEDBITS(here.bits + 2); + n = here_bits + 2; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + if (state.have === 0) { + strm.msg = 'invalid bit length repeat'; + state.mode = BAD; + break; + } + len = state.lens[state.have - 1]; + copy = 3 + (hold & 0x03);//BITS(2); + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + } + else if (here_val === 17) { + //=== NEEDBITS(here.bits + 3); + n = here_bits + 3; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + len = 0; + copy = 3 + (hold & 0x07);//BITS(3); + //--- DROPBITS(3) ---// + hold >>>= 3; + bits -= 3; + //---// + } + else { + //=== NEEDBITS(here.bits + 7); + n = here_bits + 7; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + len = 0; + copy = 11 + (hold & 0x7f);//BITS(7); + //--- DROPBITS(7) ---// + hold >>>= 7; + bits -= 7; + //---// + } + if (state.have + copy > state.nlen + state.ndist) { + strm.msg = 'invalid bit length repeat'; + state.mode = BAD; + break; + } + while (copy--) { + state.lens[state.have++] = len; + } + } + } + + /* handle error breaks in while */ + if (state.mode === BAD) { break; } + + /* check for end-of-block code (better have one) */ + if (state.lens[256] === 0) { + strm.msg = 'invalid code -- missing end-of-block'; + state.mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state.lenbits = 9; + + opts = { bits: state.lenbits }; + ret = inftrees(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts); + // We have separate tables & no pointers. 2 commented lines below not needed. + // state.next_index = opts.table_index; + state.lenbits = opts.bits; + // state.lencode = state.next; + + if (ret) { + strm.msg = 'invalid literal/lengths set'; + state.mode = BAD; + break; + } + + state.distbits = 6; + //state.distcode.copy(state.codes); + // Switch to use dynamic table + state.distcode = state.distdyn; + opts = { bits: state.distbits }; + ret = inftrees(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts); + // We have separate tables & no pointers. 2 commented lines below not needed. + // state.next_index = opts.table_index; + state.distbits = opts.bits; + // state.distcode = state.next; + + if (ret) { + strm.msg = 'invalid distances set'; + state.mode = BAD; + break; + } + //Tracev((stderr, 'inflate: codes ok\n')); + state.mode = LEN_; + if (flush === Z_TREES) { break inf_leave; } + /* falls through */ + case LEN_: + state.mode = LEN; + /* falls through */ + case LEN: + if (have >= 6 && left >= 258) { + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + inffast(strm, _out); + //--- LOAD() --- + put = strm.next_out; + output = strm.output; + left = strm.avail_out; + next = strm.next_in; + input = strm.input; + have = strm.avail_in; + hold = state.hold; + bits = state.bits; + //--- + + if (state.mode === TYPE) { + state.back = -1; + } + break; + } + state.back = 0; + for (;;) { + here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if (here_bits <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if (here_op && (here_op & 0xf0) === 0) { + last_bits = here_bits; + last_op = here_op; + last_val = here_val; + for (;;) { + here = state.lencode[last_val + + ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((last_bits + here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + //--- DROPBITS(last.bits) ---// + hold >>>= last_bits; + bits -= last_bits; + //---// + state.back += last_bits; + } + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.back += here_bits; + state.length = here_val; + if (here_op === 0) { + //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + // "inflate: literal '%c'\n" : + // "inflate: literal 0x%02x\n", here.val)); + state.mode = LIT; + break; + } + if (here_op & 32) { + //Tracevv((stderr, "inflate: end of block\n")); + state.back = -1; + state.mode = TYPE; + break; + } + if (here_op & 64) { + strm.msg = 'invalid literal/length code'; + state.mode = BAD; + break; + } + state.extra = here_op & 15; + state.mode = LENEXT; + /* falls through */ + case LENEXT: + if (state.extra) { + //=== NEEDBITS(state.extra); + n = state.extra; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; + //--- DROPBITS(state.extra) ---// + hold >>>= state.extra; + bits -= state.extra; + //---// + state.back += state.extra; + } + //Tracevv((stderr, "inflate: length %u\n", state.length)); + state.was = state.length; + state.mode = DIST; + /* falls through */ + case DIST: + for (;;) { + here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if ((here_op & 0xf0) === 0) { + last_bits = here_bits; + last_op = here_op; + last_val = here_val; + for (;;) { + here = state.distcode[last_val + + ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((last_bits + here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + //--- DROPBITS(last.bits) ---// + hold >>>= last_bits; + bits -= last_bits; + //---// + state.back += last_bits; + } + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.back += here_bits; + if (here_op & 64) { + strm.msg = 'invalid distance code'; + state.mode = BAD; + break; + } + state.offset = here_val; + state.extra = (here_op) & 15; + state.mode = DISTEXT; + /* falls through */ + case DISTEXT: + if (state.extra) { + //=== NEEDBITS(state.extra); + n = state.extra; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; + //--- DROPBITS(state.extra) ---// + hold >>>= state.extra; + bits -= state.extra; + //---// + state.back += state.extra; + } +//#ifdef INFLATE_STRICT + if (state.offset > state.dmax) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break; + } +//#endif + //Tracevv((stderr, "inflate: distance %u\n", state.offset)); + state.mode = MATCH; + /* falls through */ + case MATCH: + if (left === 0) { break inf_leave; } + copy = _out - left; + if (state.offset > copy) { /* copy from window */ + copy = state.offset - copy; + if (copy > state.whave) { + if (state.sane) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break; + } +// (!) This block is disabled in zlib defaults, +// don't enable it for binary compatibility +//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR +// Trace((stderr, "inflate.c too far\n")); +// copy -= state.whave; +// if (copy > state.length) { copy = state.length; } +// if (copy > left) { copy = left; } +// left -= copy; +// state.length -= copy; +// do { +// output[put++] = 0; +// } while (--copy); +// if (state.length === 0) { state.mode = LEN; } +// break; +//#endif + } + if (copy > state.wnext) { + copy -= state.wnext; + from = state.wsize - copy; + } + else { + from = state.wnext - copy; + } + if (copy > state.length) { copy = state.length; } + from_source = state.window; + } + else { /* copy from output */ + from_source = output; + from = put - state.offset; + copy = state.length; + } + if (copy > left) { copy = left; } + left -= copy; + state.length -= copy; + do { + output[put++] = from_source[from++]; + } while (--copy); + if (state.length === 0) { state.mode = LEN; } + break; + case LIT: + if (left === 0) { break inf_leave; } + output[put++] = state.length; + left--; + state.mode = LEN; + break; + case CHECK: + if (state.wrap) { + //=== NEEDBITS(32); + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + // Use '|' instead of '+' to make sure that result is signed + hold |= input[next++] << bits; + bits += 8; + } + //===// + _out -= left; + strm.total_out += _out; + state.total += _out; + if ((state.wrap & 4) && _out) { + strm.adler = state.check = + /*UPDATE_CHECK(state.check, put - _out, _out);*/ + (state.flags ? crc32_1(state.check, output, _out, put - _out) : adler32_1(state.check, output, _out, put - _out)); + + } + _out = left; + // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too + if ((state.wrap & 4) && (state.flags ? hold : zswap32(hold)) !== state.check) { + strm.msg = 'incorrect data check'; + state.mode = BAD; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + //Tracev((stderr, "inflate: check matches trailer\n")); + } + state.mode = LENGTH; + /* falls through */ + case LENGTH: + if (state.wrap && state.flags) { + //=== NEEDBITS(32); + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((state.wrap & 4) && hold !== (state.total & 0xffffffff)) { + strm.msg = 'incorrect length check'; + state.mode = BAD; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + //Tracev((stderr, "inflate: length matches trailer\n")); + } + state.mode = DONE; + /* falls through */ + case DONE: + ret = Z_STREAM_END$1; + break inf_leave; + case BAD: + ret = Z_DATA_ERROR$1; + break inf_leave; + case MEM: + return Z_MEM_ERROR$1; + case SYNC: + /* falls through */ + default: + return Z_STREAM_ERROR$1; + } + } + + // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave" + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + + if (state.wsize || (_out !== strm.avail_out && state.mode < BAD && + (state.mode < CHECK || flush !== Z_FINISH$1))) { + if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) ; + } + _in -= strm.avail_in; + _out -= strm.avail_out; + strm.total_in += _in; + strm.total_out += _out; + state.total += _out; + if ((state.wrap & 4) && _out) { + strm.adler = state.check = /*UPDATE_CHECK(state.check, strm.next_out - _out, _out);*/ + (state.flags ? crc32_1(state.check, output, _out, strm.next_out - _out) : adler32_1(state.check, output, _out, strm.next_out - _out)); + } + strm.data_type = state.bits + (state.last ? 64 : 0) + + (state.mode === TYPE ? 128 : 0) + + (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0); + if (((_in === 0 && _out === 0) || flush === Z_FINISH$1) && ret === Z_OK$1) { + ret = Z_BUF_ERROR; + } + return ret; +}; + + +const inflateEnd = (strm) => { + + if (inflateStateCheck(strm)) { + return Z_STREAM_ERROR$1; + } + + let state = strm.state; + if (state.window) { + state.window = null; + } + strm.state = null; + return Z_OK$1; +}; + + +const inflateGetHeader = (strm, head) => { + + /* check state */ + if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; } + const state = strm.state; + if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR$1; } + + /* save header structure */ + state.head = head; + head.done = false; + return Z_OK$1; +}; + + +const inflateSetDictionary = (strm, dictionary) => { + const dictLength = dictionary.length; + + let state; + let dictid; + let ret; + + /* check state */ + if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; } + state = strm.state; + + if (state.wrap !== 0 && state.mode !== DICT) { + return Z_STREAM_ERROR$1; + } + + /* check for correct dictionary identifier */ + if (state.mode === DICT) { + dictid = 1; /* adler32(0, null, 0)*/ + /* dictid = adler32(dictid, dictionary, dictLength); */ + dictid = adler32_1(dictid, dictionary, dictLength, 0); + if (dictid !== state.check) { + return Z_DATA_ERROR$1; + } + } + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + ret = updatewindow(strm, dictionary, dictLength, dictLength); + if (ret) { + state.mode = MEM; + return Z_MEM_ERROR$1; + } + state.havedict = 1; + // Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK$1; +}; + + +var inflateReset_1 = inflateReset; +var inflateReset2_1 = inflateReset2; +var inflateResetKeep_1 = inflateResetKeep; +var inflateInit_1 = inflateInit; +var inflateInit2_1 = inflateInit2; +var inflate_2$1 = inflate$2; +var inflateEnd_1 = inflateEnd; +var inflateGetHeader_1 = inflateGetHeader; +var inflateSetDictionary_1 = inflateSetDictionary; +var inflateInfo = 'pako inflate (from Nodeca project)'; + +/* Not implemented +module.exports.inflateCodesUsed = inflateCodesUsed; +module.exports.inflateCopy = inflateCopy; +module.exports.inflateGetDictionary = inflateGetDictionary; +module.exports.inflateMark = inflateMark; +module.exports.inflatePrime = inflatePrime; +module.exports.inflateSync = inflateSync; +module.exports.inflateSyncPoint = inflateSyncPoint; +module.exports.inflateUndermine = inflateUndermine; +module.exports.inflateValidate = inflateValidate; +*/ + +var inflate_1$2 = { + inflateReset: inflateReset_1, + inflateReset2: inflateReset2_1, + inflateResetKeep: inflateResetKeep_1, + inflateInit: inflateInit_1, + inflateInit2: inflateInit2_1, + inflate: inflate_2$1, + inflateEnd: inflateEnd_1, + inflateGetHeader: inflateGetHeader_1, + inflateSetDictionary: inflateSetDictionary_1, + inflateInfo: inflateInfo +}; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +function GZheader() { + /* true if compressed data believed to be text */ + this.text = 0; + /* modification time */ + this.time = 0; + /* extra flags (not used when writing a gzip file) */ + this.xflags = 0; + /* operating system */ + this.os = 0; + /* pointer to extra field or Z_NULL if none */ + this.extra = null; + /* extra field length (valid if extra != Z_NULL) */ + this.extra_len = 0; // Actually, we don't need it in JS, + // but leave for few code modifications + + // + // Setup limits is not necessary because in js we should not preallocate memory + // for inflate use constant limit in 65536 bytes + // + + /* space at extra (only when reading header) */ + // this.extra_max = 0; + /* pointer to zero-terminated file name or Z_NULL */ + this.name = ''; + /* space at name (only when reading header) */ + // this.name_max = 0; + /* pointer to zero-terminated comment or Z_NULL */ + this.comment = ''; + /* space at comment (only when reading header) */ + // this.comm_max = 0; + /* true if there was or will be a header crc */ + this.hcrc = 0; + /* true when done reading gzip header (not used when writing a gzip file) */ + this.done = false; +} + +var gzheader = GZheader; + +const toString = Object.prototype.toString; + +/* Public constants ==========================================================*/ +/* ===========================================================================*/ + +const { + Z_NO_FLUSH, Z_FINISH, + Z_OK, Z_STREAM_END, Z_NEED_DICT, Z_STREAM_ERROR, Z_DATA_ERROR, Z_MEM_ERROR +} = constants$2; + +/* ===========================================================================*/ + + +/** + * class Inflate + * + * Generic JS-style wrapper for zlib calls. If you don't need + * streaming behaviour - use more simple functions: [[inflate]] + * and [[inflateRaw]]. + **/ + +/* internal + * inflate.chunks -> Array + * + * Chunks of output data, if [[Inflate#onData]] not overridden. + **/ + +/** + * Inflate.result -> Uint8Array|String + * + * Uncompressed result, generated by default [[Inflate#onData]] + * and [[Inflate#onEnd]] handlers. Filled after you push last chunk + * (call [[Inflate#push]] with `Z_FINISH` / `true` param). + **/ + +/** + * Inflate.err -> Number + * + * Error code after inflate finished. 0 (Z_OK) on success. + * Should be checked if broken data possible. + **/ + +/** + * Inflate.msg -> String + * + * Error message, if [[Inflate.err]] != 0 + **/ + + +/** + * new Inflate(options) + * - options (Object): zlib inflate options. + * + * Creates new inflator instance with specified params. Throws exception + * on bad params. Supported options: + * + * - `windowBits` + * - `dictionary` + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information on these. + * + * Additional options, for internal needs: + * + * - `chunkSize` - size of generated data chunks (16K by default) + * - `raw` (Boolean) - do raw inflate + * - `to` (String) - if equal to 'string', then result will be converted + * from utf8 to utf16 (javascript) string. When string output requested, + * chunk length can differ from `chunkSize`, depending on content. + * + * By default, when no options set, autodetect deflate/gzip data format via + * wrapper header. + * + * ##### Example: + * + * ```javascript + * const pako = require('pako') + * const chunk1 = new Uint8Array([1,2,3,4,5,6,7,8,9]) + * const chunk2 = new Uint8Array([10,11,12,13,14,15,16,17,18,19]); + * + * const inflate = new pako.Inflate({ level: 3}); + * + * inflate.push(chunk1, false); + * inflate.push(chunk2, true); // true -> last chunk + * + * if (inflate.err) { throw new Error(inflate.err); } + * + * console.log(inflate.result); + * ``` + **/ +function Inflate$1(options) { + this.options = common.assign({ + chunkSize: 1024 * 64, + windowBits: 15, + to: '' + }, options || {}); + + const opt = this.options; + + // Force window size for `raw` data, if not set directly, + // because we have no header for autodetect. + if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) { + opt.windowBits = -opt.windowBits; + if (opt.windowBits === 0) { opt.windowBits = -15; } + } + + // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate + if ((opt.windowBits >= 0) && (opt.windowBits < 16) && + !(options && options.windowBits)) { + opt.windowBits += 32; + } + + // Gzip header has no info about windows size, we can do autodetect only + // for deflate. So, if window size not set, force it to max when gzip possible + if ((opt.windowBits > 15) && (opt.windowBits < 48)) { + // bit 3 (16) -> gzipped data + // bit 4 (32) -> autodetect gzip/deflate + if ((opt.windowBits & 15) === 0) { + opt.windowBits |= 15; + } + } + + this.err = 0; // error code, if happens (0 = Z_OK) + this.msg = ''; // error message + this.ended = false; // used to avoid multiple onEnd() calls + this.chunks = []; // chunks of compressed data + + this.strm = new zstream(); + this.strm.avail_out = 0; + + let status = inflate_1$2.inflateInit2( + this.strm, + opt.windowBits + ); + + if (status !== Z_OK) { + throw new Error(messages[status]); + } + + this.header = new gzheader(); + + inflate_1$2.inflateGetHeader(this.strm, this.header); + + // Setup dictionary + if (opt.dictionary) { + // Convert data if needed + if (typeof opt.dictionary === 'string') { + opt.dictionary = strings.string2buf(opt.dictionary); + } else if (toString.call(opt.dictionary) === '[object ArrayBuffer]') { + opt.dictionary = new Uint8Array(opt.dictionary); + } + if (opt.raw) { //In raw mode we need to set the dictionary early + status = inflate_1$2.inflateSetDictionary(this.strm, opt.dictionary); + if (status !== Z_OK) { + throw new Error(messages[status]); + } + } + } +} + +/** + * Inflate#push(data[, flush_mode]) -> Boolean + * - data (Uint8Array|ArrayBuffer): input data + * - flush_mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE + * flush modes. See constants. Skipped or `false` means Z_NO_FLUSH, + * `true` means Z_FINISH. + * + * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with + * new output chunks. Returns `true` on success. If end of stream detected, + * [[Inflate#onEnd]] will be called. + * + * `flush_mode` is not needed for normal operation, because end of stream + * detected automatically. You may try to use it for advanced things, but + * this functionality was not tested. + * + * On fail call [[Inflate#onEnd]] with error code and return false. + * + * ##### Example + * + * ```javascript + * push(chunk, false); // push one of data chunks + * ... + * push(chunk, true); // push last chunk + * ``` + **/ +Inflate$1.prototype.push = function (data, flush_mode) { + const strm = this.strm; + const chunkSize = this.options.chunkSize; + const dictionary = this.options.dictionary; + let status, _flush_mode, last_avail_out; + + if (this.ended) return false; + + if (flush_mode === ~~flush_mode) _flush_mode = flush_mode; + else _flush_mode = flush_mode === true ? Z_FINISH : Z_NO_FLUSH; + + // Convert data if needed + if (toString.call(data) === '[object ArrayBuffer]') { + strm.input = new Uint8Array(data); + } else { + strm.input = data; + } + + strm.next_in = 0; + strm.avail_in = strm.input.length; + + for (;;) { + if (strm.avail_out === 0) { + strm.output = new Uint8Array(chunkSize); + strm.next_out = 0; + strm.avail_out = chunkSize; + } + + status = inflate_1$2.inflate(strm, _flush_mode); + + if (status === Z_NEED_DICT && dictionary) { + status = inflate_1$2.inflateSetDictionary(strm, dictionary); + + if (status === Z_OK) { + status = inflate_1$2.inflate(strm, _flush_mode); + } else if (status === Z_DATA_ERROR) { + // Replace code with more verbose + status = Z_NEED_DICT; + } + } + + // Skip snyc markers if more data follows and not raw mode + while (strm.avail_in > 0 && + status === Z_STREAM_END && + strm.state.wrap > 0 && + data[strm.next_in] !== 0) + { + inflate_1$2.inflateReset(strm); + status = inflate_1$2.inflate(strm, _flush_mode); + } + + switch (status) { + case Z_STREAM_ERROR: + case Z_DATA_ERROR: + case Z_NEED_DICT: + case Z_MEM_ERROR: + this.onEnd(status); + this.ended = true; + return false; + } + + // Remember real `avail_out` value, because we may patch out buffer content + // to align utf8 strings boundaries. + last_avail_out = strm.avail_out; + + if (strm.next_out) { + if (strm.avail_out === 0 || status === Z_STREAM_END) { + + if (this.options.to === 'string') { + + let next_out_utf8 = strings.utf8border(strm.output, strm.next_out); + + let tail = strm.next_out - next_out_utf8; + let utf8str = strings.buf2string(strm.output, next_out_utf8); + + // move tail & realign counters + strm.next_out = tail; + strm.avail_out = chunkSize - tail; + if (tail) strm.output.set(strm.output.subarray(next_out_utf8, next_out_utf8 + tail), 0); + + this.onData(utf8str); + + } else { + this.onData(strm.output.length === strm.next_out ? strm.output : strm.output.subarray(0, strm.next_out)); + } + } + } + + // Must repeat iteration if out buffer is full + if (status === Z_OK && last_avail_out === 0) continue; + + // Finalize if end of stream reached. + if (status === Z_STREAM_END) { + status = inflate_1$2.inflateEnd(this.strm); + this.onEnd(status); + this.ended = true; + return true; + } + + if (strm.avail_in === 0) break; + } + + return true; +}; + + +/** + * Inflate#onData(chunk) -> Void + * - chunk (Uint8Array|String): output data. When string output requested, + * each chunk will be string. + * + * By default, stores data blocks in `chunks[]` property and glue + * those in `onEnd`. Override this handler, if you need another behaviour. + **/ +Inflate$1.prototype.onData = function (chunk) { + this.chunks.push(chunk); +}; + + +/** + * Inflate#onEnd(status) -> Void + * - status (Number): inflate status. 0 (Z_OK) on success, + * other if not. + * + * Called either after you tell inflate that the input stream is + * complete (Z_FINISH). By default - join collected chunks, + * free memory and fill `results` / `err` properties. + **/ +Inflate$1.prototype.onEnd = function (status) { + // On success - join + if (status === Z_OK) { + if (this.options.to === 'string') { + this.result = this.chunks.join(''); + } else { + this.result = common.flattenChunks(this.chunks); + } + } + this.chunks = []; + this.err = status; + this.msg = this.strm.msg; +}; + +const { Deflate, deflate, deflateRaw, gzip } = deflate_1$1; +var deflate_1 = deflate; + +/* eslint-disable no-use-before-define */ + +const crypto$1 = + (typeof globalThis != 'undefined' ? globalThis : void 0)?.crypto || + (typeof global != 'undefined' ? global : void 0)?.crypto || + (typeof window != 'undefined' ? window : void 0)?.crypto || + (typeof self != 'undefined' ? self : void 0)?.crypto || + (typeof frames != 'undefined' ? frames : void 0)?.[0]?.crypto; + +let randomWordArray; + +if (crypto$1) { + randomWordArray = (nBytes) => { + const words = []; + + for (let i = 0, rcache; i < nBytes; i += 4) { + words.push(crypto$1.getRandomValues(new Uint32Array(1))[0]); + } + + return new WordArray(words, nBytes); + }; +} else { + // Because there is no global crypto property in this context, cryptographically unsafe Math.random() is used. + + randomWordArray = (nBytes) => { + const words = []; + + const r = (m_w) => { + let _m_w = m_w; + let _m_z = 0x3ade68b1; + const mask = 0xffffffff; + + return () => { + _m_z = (0x9069 * (_m_z & 0xFFFF) + (_m_z >> 0x10)) & mask; + _m_w = (0x4650 * (_m_w & 0xFFFF) + (_m_w >> 0x10)) & mask; + let result = ((_m_z << 0x10) + _m_w) & mask; + result /= 0x100000000; + result += 0.5; + return result * (Math.random() > 0.5 ? 1 : -1); + }; + }; + + for (let i = 0, rcache; i < nBytes; i += 4) { + const _r = r((rcache || Math.random()) * 0x100000000); + + rcache = _r() * 0x3ade67b7; + words.push((_r() * 0x100000000) | 0); + } + + return new WordArray(words, nBytes); + }; +} + +/** + * Base class for inheritance. + */ +class Base { + /** + * Extends this object and runs the init method. + * Arguments to create() will be passed to init(). + * + * @return {Object} The new object. + * + * @static + * + * @example + * + * var instance = MyType.create(); + */ + static create(...args) { + return new this(...args); + } + + /** + * Copies properties into this object. + * + * @param {Object} properties The properties to mix in. + * + * @example + * + * MyType.mixIn({ + * field: 'value' + * }); + */ + mixIn(properties) { + return Object.assign(this, properties); + } + + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = instance.clone(); + */ + clone() { + const clone = new this.constructor(); + Object.assign(clone, this); + return clone; + } +} + +/** + * An array of 32-bit words. + * + * @property {Array} words The array of 32-bit words. + * @property {number} sigBytes The number of significant bytes in this word array. + */ +class WordArray extends Base { + /** + * Initializes a newly created word array. + * + * @param {Array} words (Optional) An array of 32-bit words. + * @param {number} sigBytes (Optional) The number of significant bytes in the words. + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.create(); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6); + */ + constructor(words = [], sigBytes = words.length * 4) { + super(); + + let typedArray = words; + // Convert buffers to uint8 + if (typedArray instanceof ArrayBuffer) { + typedArray = new Uint8Array(typedArray); + } + + // Convert other array views to uint8 + if ( + typedArray instanceof Int8Array + || typedArray instanceof Uint8ClampedArray + || typedArray instanceof Int16Array + || typedArray instanceof Uint16Array + || typedArray instanceof Int32Array + || typedArray instanceof Uint32Array + || typedArray instanceof Float32Array + || typedArray instanceof Float64Array + ) { + typedArray = new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength); + } + + // Handle Uint8Array + if (typedArray instanceof Uint8Array) { + // Shortcut + const typedArrayByteLength = typedArray.byteLength; + + // Extract bytes + const _words = []; + for (let i = 0; i < typedArrayByteLength; i += 1) { + _words[i >>> 2] |= typedArray[i] << (24 - (i % 4) * 8); + } + + // Initialize this word array + this.words = _words; + this.sigBytes = typedArrayByteLength; + } else { + // Else call normal init + this.words = words; + this.sigBytes = sigBytes; + } + } + + /** + * Creates a word array filled with random bytes. + * + * @param {number} nBytes The number of random bytes to generate. + * + * @return {WordArray} The random word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.random(16); + */ + static random = randomWordArray; + + /** + * Converts this word array to a string. + * + * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex + * + * @return {string} The stringified word array. + * + * @example + * + * var string = wordArray + ''; + * var string = wordArray.toString(); + * var string = wordArray.toString(CryptoJS.enc.Utf8); + */ + toString(encoder = Hex) { + return encoder.stringify(this); + } + + /** + * Concatenates a word array to this word array. + * + * @param {WordArray} wordArray The word array to append. + * + * @return {WordArray} This word array. + * + * @example + * + * wordArray1.concat(wordArray2); + */ + concat(wordArray) { + // Shortcuts + const thisWords = this.words; + const thatWords = wordArray.words; + const thisSigBytes = this.sigBytes; + const thatSigBytes = wordArray.sigBytes; + + // Clamp excess bits + this.clamp(); + + // Concat + if (thisSigBytes % 4) { + // Copy one byte at a time + for (let i = 0; i < thatSigBytes; i += 1) { + const thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8); + } + } else { + // Copy one word at a time + for (let i = 0; i < thatSigBytes; i += 4) { + thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2]; + } + } + this.sigBytes += thatSigBytes; + + // Chainable + return this; + } + + /** + * Removes insignificant bits. + * + * @example + * + * wordArray.clamp(); + */ + clamp() { + // Shortcuts + const { words, sigBytes } = this; + + // Clamp + words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8); + words.length = Math.ceil(sigBytes / 4); + } + + /** + * Creates a copy of this word array. + * + * @return {WordArray} The clone. + * + * @example + * + * var clone = wordArray.clone(); + */ + clone() { + const clone = super.clone.call(this); + clone.words = this.words.slice(0); + + return clone; + } +} + +/** + * Hex encoding strategy. + */ +const Hex = { + /** + * Converts a word array to a hex string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The hex string. + * + * @static + * + * @example + * + * var hexString = CryptoJS.enc.Hex.stringify(wordArray); + */ + stringify(wordArray) { + // Shortcuts + const { words, sigBytes } = wordArray; + + // Convert + const hexChars = []; + for (let i = 0; i < sigBytes; i += 1) { + const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + hexChars.push((bite >>> 4).toString(16)); + hexChars.push((bite & 0x0f).toString(16)); + } + + return hexChars.join(''); + }, + + /** + * Converts a hex string to a word array. + * + * @param {string} hexStr The hex string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Hex.parse(hexString); + */ + parse(hexStr) { + // Shortcut + const hexStrLength = hexStr.length; + + // Convert + const words = []; + for (let i = 0; i < hexStrLength; i += 2) { + words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4); + } + + return new WordArray(words, hexStrLength / 2); + }, +}; + +/** + * Latin1 encoding strategy. + */ +const Latin1 = { + /** + * Converts a word array to a Latin1 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The Latin1 string. + * + * @static + * + * @example + * + * var latin1String = CryptoJS.enc.Latin1.stringify(wordArray); + */ + stringify(wordArray) { + // Shortcuts + const { words, sigBytes } = wordArray; + + // Convert + const latin1Chars = []; + for (let i = 0; i < sigBytes; i += 1) { + const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + latin1Chars.push(String.fromCharCode(bite)); + } + + return latin1Chars.join(''); + }, + + /** + * Converts a Latin1 string to a word array. + * + * @param {string} latin1Str The Latin1 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Latin1.parse(latin1String); + */ + parse(latin1Str) { + // Shortcut + const latin1StrLength = latin1Str.length; + + // Convert + const words = []; + for (let i = 0; i < latin1StrLength; i += 1) { + words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8); + } + + return new WordArray(words, latin1StrLength); + }, +}; + +/** + * UTF-8 encoding strategy. + */ +const Utf8 = { + /** + * Converts a word array to a UTF-8 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-8 string. + * + * @static + * + * @example + * + * var utf8String = CryptoJS.enc.Utf8.stringify(wordArray); + */ + stringify(wordArray) { + try { + return decodeURIComponent(escape(Latin1.stringify(wordArray))); + } catch (e) { + throw new Error('Malformed UTF-8 data'); + } + }, + + /** + * Converts a UTF-8 string to a word array. + * + * @param {string} utf8Str The UTF-8 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Utf8.parse(utf8String); + */ + parse(utf8Str) { + return Latin1.parse(unescape(encodeURIComponent(utf8Str))); + }, +}; + +/** + * Abstract buffered block algorithm template. + * + * The property blockSize must be implemented in a concrete subtype. + * + * @property {number} _minBufferSize + * + * The number of blocks that should be kept unprocessed in the buffer. Default: 0 + */ +class BufferedBlockAlgorithm extends Base { + constructor() { + super(); + this._minBufferSize = 0; + } + + /** + * Resets this block algorithm's data buffer to its initial state. + * + * @example + * + * bufferedBlockAlgorithm.reset(); + */ + reset() { + // Initial values + this._data = new WordArray(); + this._nDataBytes = 0; + } + + /** + * Adds new data to this block algorithm's buffer. + * + * @param {WordArray|string} data + * + * The data to append. Strings are converted to a WordArray using UTF-8. + * + * @example + * + * bufferedBlockAlgorithm._append('data'); + * bufferedBlockAlgorithm._append(wordArray); + */ + _append(data) { + let m_data = data; + + // Convert string to WordArray, else assume WordArray already + if (typeof m_data === 'string') { + m_data = Utf8.parse(m_data); + } + + // Append + this._data.concat(m_data); + this._nDataBytes += m_data.sigBytes; + } + + /** + * Processes available data blocks. + * + * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype. + * + * @param {boolean} doFlush Whether all blocks and partial blocks should be processed. + * + * @return {WordArray} The processed data. + * + * @example + * + * var processedData = bufferedBlockAlgorithm._process(); + * var processedData = bufferedBlockAlgorithm._process(!!'flush'); + */ + _process(doFlush) { + let processedWords; + + // Shortcuts + const { _data: data, blockSize } = this; + const dataWords = data.words; + const dataSigBytes = data.sigBytes; + const blockSizeBytes = blockSize * 4; + + // Count blocks ready + let nBlocksReady = dataSigBytes / blockSizeBytes; + if (doFlush) { + // Round up to include partial blocks + nBlocksReady = Math.ceil(nBlocksReady); + } else { + // Round down to include only full blocks, + // less the number of blocks that must remain in the buffer + nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0); + } + + // Count words ready + const nWordsReady = nBlocksReady * blockSize; + + // Count bytes ready + const nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); + + // Process blocks + if (nWordsReady) { + for (let offset = 0; offset < nWordsReady; offset += blockSize) { + // Perform concrete-algorithm logic + this._doProcessBlock(dataWords, offset); + } + + // Remove processed words + processedWords = dataWords.splice(0, nWordsReady); + data.sigBytes -= nBytesReady; + } + + // Return processed words + return new WordArray(processedWords, nBytesReady); + } + + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = bufferedBlockAlgorithm.clone(); + */ + clone() { + const clone = super.clone.call(this); + clone._data = this._data.clone(); + + return clone; + } +} + +/** + * Abstract hasher template. + * + * @property {number} blockSize + * + * The number of 32-bit words this hasher operates on. Default: 16 (512 bits) + */ +class Hasher extends BufferedBlockAlgorithm { + constructor(cfg) { + super(); + + this.blockSize = 512 / 32; + + /** + * Configuration options. + */ + this.cfg = Object.assign(new Base(), cfg); + + // Set initial values + this.reset(); + } + + /** + * Creates a shortcut function to a hasher's object interface. + * + * @param {Hasher} SubHasher The hasher to create a helper for. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256); + */ + static _createHelper(SubHasher) { + return (message, cfg) => new SubHasher(cfg).finalize(message); + } + + /** + * Creates a shortcut function to the HMAC's object interface. + * + * @param {Hasher} SubHasher The hasher to use in this HMAC helper. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256); + */ + static _createHmacHelper(SubHasher) { + return (message, key) => new HMAC(SubHasher, key).finalize(message); + } + + /** + * Resets this hasher to its initial state. + * + * @example + * + * hasher.reset(); + */ + reset() { + // Reset data buffer + super.reset.call(this); + + // Perform concrete-hasher logic + this._doReset(); + } + + /** + * Updates this hasher with a message. + * + * @param {WordArray|string} messageUpdate The message to append. + * + * @return {Hasher} This hasher. + * + * @example + * + * hasher.update('message'); + * hasher.update(wordArray); + */ + update(messageUpdate) { + // Append + this._append(messageUpdate); + + // Update the hash + this._process(); + + // Chainable + return this; + } + + /** + * Finalizes the hash computation. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} messageUpdate (Optional) A final message update. + * + * @return {WordArray} The hash. + * + * @example + * + * var hash = hasher.finalize(); + * var hash = hasher.finalize('message'); + * var hash = hasher.finalize(wordArray); + */ + finalize(messageUpdate) { + // Final message update + if (messageUpdate) { + this._append(messageUpdate); + } + + // Perform concrete-hasher logic + const hash = this._doFinalize(); + + return hash; + } +} + +/** + * HMAC algorithm. + */ +class HMAC extends Base { + /** + * Initializes a newly created HMAC. + * + * @param {Hasher} SubHasher The hash algorithm to use. + * @param {WordArray|string} key The secret key. + * + * @example + * + * var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key); + */ + constructor(SubHasher, key) { + super(); + + const hasher = new SubHasher(); + this._hasher = hasher; + + // Convert string to WordArray, else assume WordArray already + let _key = key; + if (typeof _key === 'string') { + _key = Utf8.parse(_key); + } + + // Shortcuts + const hasherBlockSize = hasher.blockSize; + const hasherBlockSizeBytes = hasherBlockSize * 4; + + // Allow arbitrary length keys + if (_key.sigBytes > hasherBlockSizeBytes) { + _key = hasher.finalize(key); + } + + // Clamp excess bits + _key.clamp(); + + // Clone key for inner and outer pads + const oKey = _key.clone(); + this._oKey = oKey; + const iKey = _key.clone(); + this._iKey = iKey; + + // Shortcuts + const oKeyWords = oKey.words; + const iKeyWords = iKey.words; + + // XOR keys with pad constants + for (let i = 0; i < hasherBlockSize; i += 1) { + oKeyWords[i] ^= 0x5c5c5c5c; + iKeyWords[i] ^= 0x36363636; + } + oKey.sigBytes = hasherBlockSizeBytes; + iKey.sigBytes = hasherBlockSizeBytes; + + // Set initial values + this.reset(); + } + + /** + * Resets this HMAC to its initial state. + * + * @example + * + * hmacHasher.reset(); + */ + reset() { + // Shortcut + const hasher = this._hasher; + + // Reset + hasher.reset(); + hasher.update(this._iKey); + } + + /** + * Updates this HMAC with a message. + * + * @param {WordArray|string} messageUpdate The message to append. + * + * @return {HMAC} This HMAC instance. + * + * @example + * + * hmacHasher.update('message'); + * hmacHasher.update(wordArray); + */ + update(messageUpdate) { + this._hasher.update(messageUpdate); + + // Chainable + return this; + } + + /** + * Finalizes the HMAC computation. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} messageUpdate (Optional) A final message update. + * + * @return {WordArray} The HMAC. + * + * @example + * + * var hmac = hmacHasher.finalize(); + * var hmac = hmacHasher.finalize('message'); + * var hmac = hmacHasher.finalize(wordArray); + */ + finalize(messageUpdate) { + // Shortcut + const hasher = this._hasher; + + // Compute HMAC + const innerHash = hasher.finalize(messageUpdate); + hasher.reset(); + const hmac = hasher.finalize(this._oKey.clone().concat(innerHash)); + + return hmac; + } +} + +const X32WordArray = WordArray; + +/** + * A 64-bit word. + */ +class X64Word extends Base { + /** + * Initializes a newly created 64-bit word. + * + * @param {number} high The high 32 bits. + * @param {number} low The low 32 bits. + * + * @example + * + * var x64Word = CryptoJS.x64.Word.create(0x00010203, 0x04050607); + */ + constructor(high, low) { + super(); + + this.high = high; + this.low = low; + } +} + +/** + * An array of 64-bit words. + * + * @property {Array} words The array of CryptoJS.x64.Word objects. + * @property {number} sigBytes The number of significant bytes in this word array. + */ +class X64WordArray extends Base { + /** + * Initializes a newly created word array. + * + * @param {Array} words (Optional) An array of CryptoJS.x64.Word objects. + * @param {number} sigBytes (Optional) The number of significant bytes in the words. + * + * @example + * + * var wordArray = CryptoJS.x64.WordArray.create(); + * + * var wordArray = CryptoJS.x64.WordArray.create([ + * CryptoJS.x64.Word.create(0x00010203, 0x04050607), + * CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f) + * ]); + * + * var wordArray = CryptoJS.x64.WordArray.create([ + * CryptoJS.x64.Word.create(0x00010203, 0x04050607), + * CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f) + * ], 10); + */ + constructor(words = [], sigBytes = words.length * 8) { + super(); + + this.words = words; + this.sigBytes = sigBytes; + } + + /** + * Converts this 64-bit word array to a 32-bit word array. + * + * @return {CryptoJS.lib.WordArray} This word array's data as a 32-bit word array. + * + * @example + * + * var x32WordArray = x64WordArray.toX32(); + */ + toX32() { + // Shortcuts + const x64Words = this.words; + const x64WordsLength = x64Words.length; + + // Convert + const x32Words = []; + for (let i = 0; i < x64WordsLength; i += 1) { + const x64Word = x64Words[i]; + x32Words.push(x64Word.high); + x32Words.push(x64Word.low); + } + + return X32WordArray.create(x32Words, this.sigBytes); + } + + /** + * Creates a copy of this word array. + * + * @return {X64WordArray} The clone. + * + * @example + * + * var clone = x64WordArray.clone(); + */ + clone() { + const clone = super.clone.call(this); + + // Clone "words" array + clone.words = this.words.slice(0); + const { words } = clone; + + // Clone each X64Word object + const wordsLength = words.length; + for (let i = 0; i < wordsLength; i += 1) { + words[i] = words[i].clone(); + } + + return clone; + } +} + +const parseLoop = (base64Str, base64StrLength, reverseMap) => { + const words = []; + let nBytes = 0; + for (let i = 0; i < base64StrLength; i += 1) { + if (i % 4) { + const bits1 = reverseMap[base64Str.charCodeAt(i - 1)] << ((i % 4) * 2); + const bits2 = reverseMap[base64Str.charCodeAt(i)] >>> (6 - (i % 4) * 2); + const bitsCombined = bits1 | bits2; + words[nBytes >>> 2] |= bitsCombined << (24 - (nBytes % 4) * 8); + nBytes += 1; + } + } + return WordArray.create(words, nBytes); +}; + +/** + * Base64 encoding strategy. + */ +const Base64 = { + /** + * Converts a word array to a Base64 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The Base64 string. + * + * @static + * + * @example + * + * const base64String = CryptoJS.enc.Base64.stringify(wordArray); + */ + stringify(wordArray) { + // Shortcuts + const { words, sigBytes } = wordArray; + const map = this._map; + + // Clamp excess bits + wordArray.clamp(); + + // Convert + const base64Chars = []; + for (let i = 0; i < sigBytes; i += 3) { + const byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + const byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff; + const byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff; + + const triplet = (byte1 << 16) | (byte2 << 8) | byte3; + + for (let j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j += 1) { + base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f)); + } + } + + // Add padding + const paddingChar = map.charAt(64); + if (paddingChar) { + while (base64Chars.length % 4) { + base64Chars.push(paddingChar); + } + } + + return base64Chars.join(''); + }, + + /** + * Converts a Base64 string to a word array. + * + * @param {string} base64Str The Base64 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * const wordArray = CryptoJS.enc.Base64.parse(base64String); + */ + parse(base64Str) { + // Shortcuts + let base64StrLength = base64Str.length; + const map = this._map; + let reverseMap = this._reverseMap; + + if (!reverseMap) { + this._reverseMap = []; + reverseMap = this._reverseMap; + for (let j = 0; j < map.length; j += 1) { + reverseMap[map.charCodeAt(j)] = j; + } + } + + // Ignore padding + const paddingChar = map.charAt(64); + if (paddingChar) { + const paddingIndex = base64Str.indexOf(paddingChar); + if (paddingIndex !== -1) { + base64StrLength = paddingIndex; + } + } + + // Convert + return parseLoop(base64Str, base64StrLength, reverseMap); + }, + + _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', +}; + +// Constants table +const T$1 = []; + +// Compute constants +for (let i = 0; i < 64; i += 1) { + T$1[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0; +} + +const FF = (a, b, c, d, x, s, t) => { + const n = a + ((b & c) | (~b & d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; +}; + +const GG = (a, b, c, d, x, s, t) => { + const n = a + ((b & d) | (c & ~d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; +}; + +const HH = (a, b, c, d, x, s, t) => { + const n = a + (b ^ c ^ d) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; +}; + +const II = (a, b, c, d, x, s, t) => { + const n = a + (c ^ (b | ~d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; +}; + +/** + * MD5 hash algorithm. + */ +class MD5Algo extends Hasher { + _doReset() { + this._hash = new WordArray([ + 0x67452301, + 0xefcdab89, + 0x98badcfe, + 0x10325476, + ]); + } + + _doProcessBlock(M, offset) { + const _M = M; + + // Swap endian + for (let i = 0; i < 16; i += 1) { + // Shortcuts + const offset_i = offset + i; + const M_offset_i = M[offset_i]; + + _M[offset_i] = ( + (((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) + | (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00) + ); + } + + // Shortcuts + const H = this._hash.words; + + const M_offset_0 = _M[offset + 0]; + const M_offset_1 = _M[offset + 1]; + const M_offset_2 = _M[offset + 2]; + const M_offset_3 = _M[offset + 3]; + const M_offset_4 = _M[offset + 4]; + const M_offset_5 = _M[offset + 5]; + const M_offset_6 = _M[offset + 6]; + const M_offset_7 = _M[offset + 7]; + const M_offset_8 = _M[offset + 8]; + const M_offset_9 = _M[offset + 9]; + const M_offset_10 = _M[offset + 10]; + const M_offset_11 = _M[offset + 11]; + const M_offset_12 = _M[offset + 12]; + const M_offset_13 = _M[offset + 13]; + const M_offset_14 = _M[offset + 14]; + const M_offset_15 = _M[offset + 15]; + + // Working varialbes + let a = H[0]; + let b = H[1]; + let c = H[2]; + let d = H[3]; + + // Computation + a = FF(a, b, c, d, M_offset_0, 7, T$1[0]); + d = FF(d, a, b, c, M_offset_1, 12, T$1[1]); + c = FF(c, d, a, b, M_offset_2, 17, T$1[2]); + b = FF(b, c, d, a, M_offset_3, 22, T$1[3]); + a = FF(a, b, c, d, M_offset_4, 7, T$1[4]); + d = FF(d, a, b, c, M_offset_5, 12, T$1[5]); + c = FF(c, d, a, b, M_offset_6, 17, T$1[6]); + b = FF(b, c, d, a, M_offset_7, 22, T$1[7]); + a = FF(a, b, c, d, M_offset_8, 7, T$1[8]); + d = FF(d, a, b, c, M_offset_9, 12, T$1[9]); + c = FF(c, d, a, b, M_offset_10, 17, T$1[10]); + b = FF(b, c, d, a, M_offset_11, 22, T$1[11]); + a = FF(a, b, c, d, M_offset_12, 7, T$1[12]); + d = FF(d, a, b, c, M_offset_13, 12, T$1[13]); + c = FF(c, d, a, b, M_offset_14, 17, T$1[14]); + b = FF(b, c, d, a, M_offset_15, 22, T$1[15]); + + a = GG(a, b, c, d, M_offset_1, 5, T$1[16]); + d = GG(d, a, b, c, M_offset_6, 9, T$1[17]); + c = GG(c, d, a, b, M_offset_11, 14, T$1[18]); + b = GG(b, c, d, a, M_offset_0, 20, T$1[19]); + a = GG(a, b, c, d, M_offset_5, 5, T$1[20]); + d = GG(d, a, b, c, M_offset_10, 9, T$1[21]); + c = GG(c, d, a, b, M_offset_15, 14, T$1[22]); + b = GG(b, c, d, a, M_offset_4, 20, T$1[23]); + a = GG(a, b, c, d, M_offset_9, 5, T$1[24]); + d = GG(d, a, b, c, M_offset_14, 9, T$1[25]); + c = GG(c, d, a, b, M_offset_3, 14, T$1[26]); + b = GG(b, c, d, a, M_offset_8, 20, T$1[27]); + a = GG(a, b, c, d, M_offset_13, 5, T$1[28]); + d = GG(d, a, b, c, M_offset_2, 9, T$1[29]); + c = GG(c, d, a, b, M_offset_7, 14, T$1[30]); + b = GG(b, c, d, a, M_offset_12, 20, T$1[31]); + + a = HH(a, b, c, d, M_offset_5, 4, T$1[32]); + d = HH(d, a, b, c, M_offset_8, 11, T$1[33]); + c = HH(c, d, a, b, M_offset_11, 16, T$1[34]); + b = HH(b, c, d, a, M_offset_14, 23, T$1[35]); + a = HH(a, b, c, d, M_offset_1, 4, T$1[36]); + d = HH(d, a, b, c, M_offset_4, 11, T$1[37]); + c = HH(c, d, a, b, M_offset_7, 16, T$1[38]); + b = HH(b, c, d, a, M_offset_10, 23, T$1[39]); + a = HH(a, b, c, d, M_offset_13, 4, T$1[40]); + d = HH(d, a, b, c, M_offset_0, 11, T$1[41]); + c = HH(c, d, a, b, M_offset_3, 16, T$1[42]); + b = HH(b, c, d, a, M_offset_6, 23, T$1[43]); + a = HH(a, b, c, d, M_offset_9, 4, T$1[44]); + d = HH(d, a, b, c, M_offset_12, 11, T$1[45]); + c = HH(c, d, a, b, M_offset_15, 16, T$1[46]); + b = HH(b, c, d, a, M_offset_2, 23, T$1[47]); + + a = II(a, b, c, d, M_offset_0, 6, T$1[48]); + d = II(d, a, b, c, M_offset_7, 10, T$1[49]); + c = II(c, d, a, b, M_offset_14, 15, T$1[50]); + b = II(b, c, d, a, M_offset_5, 21, T$1[51]); + a = II(a, b, c, d, M_offset_12, 6, T$1[52]); + d = II(d, a, b, c, M_offset_3, 10, T$1[53]); + c = II(c, d, a, b, M_offset_10, 15, T$1[54]); + b = II(b, c, d, a, M_offset_1, 21, T$1[55]); + a = II(a, b, c, d, M_offset_8, 6, T$1[56]); + d = II(d, a, b, c, M_offset_15, 10, T$1[57]); + c = II(c, d, a, b, M_offset_6, 15, T$1[58]); + b = II(b, c, d, a, M_offset_13, 21, T$1[59]); + a = II(a, b, c, d, M_offset_4, 6, T$1[60]); + d = II(d, a, b, c, M_offset_11, 10, T$1[61]); + c = II(c, d, a, b, M_offset_2, 15, T$1[62]); + b = II(b, c, d, a, M_offset_9, 21, T$1[63]); + + // Intermediate hash value + H[0] = (H[0] + a) | 0; + H[1] = (H[1] + b) | 0; + H[2] = (H[2] + c) | 0; + H[3] = (H[3] + d) | 0; + } + /* eslint-ensable no-param-reassign */ + + _doFinalize() { + // Shortcuts + const data = this._data; + const dataWords = data.words; + + const nBitsTotal = this._nDataBytes * 8; + const nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - (nBitsLeft % 32)); + + const nBitsTotalH = Math.floor(nBitsTotal / 0x100000000); + const nBitsTotalL = nBitsTotal; + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = ( + (((nBitsTotalH << 8) | (nBitsTotalH >>> 24)) & 0x00ff00ff) + | (((nBitsTotalH << 24) | (nBitsTotalH >>> 8)) & 0xff00ff00) + ); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = ( + (((nBitsTotalL << 8) | (nBitsTotalL >>> 24)) & 0x00ff00ff) + | (((nBitsTotalL << 24) | (nBitsTotalL >>> 8)) & 0xff00ff00) + ); + + data.sigBytes = (dataWords.length + 1) * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + const hash = this._hash; + const H = hash.words; + + // Swap endian + for (let i = 0; i < 4; i += 1) { + // Shortcut + const H_i = H[i]; + + H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) + | (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00); + } + + // Return final computed hash + return hash; + } + + clone() { + const clone = super.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } +} + +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.MD5('message'); + * var hash = CryptoJS.MD5(wordArray); + */ +const MD5 = Hasher._createHelper(MD5Algo); + +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacMD5(message, key); + */ +const HmacMD5 = Hasher._createHmacHelper(MD5Algo); + +/** + * This key derivation function is meant to conform with EVP_BytesToKey. + * www.openssl.org/docs/crypto/EVP_BytesToKey.html + */ +class EvpKDFAlgo extends Base { + /** + * Initializes a newly created key derivation function. + * + * @param {Object} cfg (Optional) The configuration options to use for the derivation. + * + * @example + * + * const kdf = CryptoJS.algo.EvpKDF.create(); + * const kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8 }); + * const kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8, iterations: 1000 }); + */ + constructor(cfg) { + super(); + + /** + * Configuration options. + * + * @property {number} keySize The key size in words to generate. Default: 4 (128 bits) + * @property {Hasher} hasher The hash algorithm to use. Default: MD5 + * @property {number} iterations The number of iterations to perform. Default: 1 + */ + this.cfg = Object.assign( + new Base(), + { + keySize: 128 / 32, + hasher: MD5Algo, + iterations: 1, + }, + cfg, + ); + } + + /** + * Derives a key from a password. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * + * @return {WordArray} The derived key. + * + * @example + * + * const key = kdf.compute(password, salt); + */ + compute(password, salt) { + let block; + + // Shortcut + const { cfg } = this; + + // Init hasher + const hasher = cfg.hasher.create(); + + // Initial values + const derivedKey = WordArray.create(); + + // Shortcuts + const derivedKeyWords = derivedKey.words; + const { keySize, iterations } = cfg; + + // Generate key + while (derivedKeyWords.length < keySize) { + if (block) { + hasher.update(block); + } + block = hasher.update(password).finalize(salt); + hasher.reset(); + + // Iterations + for (let i = 1; i < iterations; i += 1) { + block = hasher.finalize(block); + hasher.reset(); + } + + derivedKey.concat(block); + } + derivedKey.sigBytes = keySize * 4; + + return derivedKey; + } +} + +/** + * Derives a key from a password. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * @param {Object} cfg (Optional) The configuration options to use for this computation. + * + * @return {WordArray} The derived key. + * + * @static + * + * @example + * + * var key = CryptoJS.EvpKDF(password, salt); + * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8 }); + * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8, iterations: 1000 }); + */ +const EvpKDF = (password, salt, cfg) => EvpKDFAlgo.create(cfg).compute(password, salt); + +/* eslint-disable no-use-before-define */ + + +/** + * Abstract base cipher template. + * + * @property {number} keySize This cipher's key size. Default: 4 (128 bits) + * @property {number} ivSize This cipher's IV size. Default: 4 (128 bits) + * @property {number} _ENC_XFORM_MODE A constant representing encryption mode. + * @property {number} _DEC_XFORM_MODE A constant representing decryption mode. + */ +class Cipher extends BufferedBlockAlgorithm { + /** + * Initializes a newly created cipher. + * + * @param {number} xformMode Either the encryption or decryption transormation mode constant. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @example + * + * const cipher = CryptoJS.algo.AES.create( + * CryptoJS.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray } + * ); + */ + constructor(xformMode, key, cfg) { + super(); + + /** + * Configuration options. + * + * @property {WordArray} iv The IV to use for this operation. + */ + this.cfg = Object.assign(new Base(), cfg); + + // Store transform mode and key + this._xformMode = xformMode; + this._key = key; + + // Set initial values + this.reset(); + } + + /** + * Creates this cipher in encryption mode. + * + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {Cipher} A cipher instance. + * + * @static + * + * @example + * + * const cipher = CryptoJS.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray }); + */ + static createEncryptor(key, cfg) { + return this.create(this._ENC_XFORM_MODE, key, cfg); + } + + /** + * Creates this cipher in decryption mode. + * + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {Cipher} A cipher instance. + * + * @static + * + * @example + * + * const cipher = CryptoJS.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray }); + */ + static createDecryptor(key, cfg) { + return this.create(this._DEC_XFORM_MODE, key, cfg); + } + + /** + * Creates shortcut functions to a cipher's object interface. + * + * @param {Cipher} cipher The cipher to create a helper for. + * + * @return {Object} An object with encrypt and decrypt shortcut functions. + * + * @static + * + * @example + * + * const AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES); + */ + static _createHelper(SubCipher) { + const selectCipherStrategy = (key) => { + if (typeof key === 'string') { + return PasswordBasedCipher; + } + return SerializableCipher; + }; + + return { + encrypt(message, key, cfg) { + return selectCipherStrategy(key).encrypt(SubCipher, message, key, cfg); + }, + + decrypt(ciphertext, key, cfg) { + return selectCipherStrategy(key).decrypt(SubCipher, ciphertext, key, cfg); + }, + }; + } + + /** + * Resets this cipher to its initial state. + * + * @example + * + * cipher.reset(); + */ + reset() { + // Reset data buffer + super.reset.call(this); + + // Perform concrete-cipher logic + this._doReset(); + } + + /** + * Adds data to be encrypted or decrypted. + * + * @param {WordArray|string} dataUpdate The data to encrypt or decrypt. + * + * @return {WordArray} The data after processing. + * + * @example + * + * const encrypted = cipher.process('data'); + * const encrypted = cipher.process(wordArray); + */ + process(dataUpdate) { + // Append + this._append(dataUpdate); + + // Process available blocks + return this._process(); + } + + /** + * Finalizes the encryption or decryption process. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} dataUpdate The final data to encrypt or decrypt. + * + * @return {WordArray} The data after final processing. + * + * @example + * + * const encrypted = cipher.finalize(); + * const encrypted = cipher.finalize('data'); + * const encrypted = cipher.finalize(wordArray); + */ + finalize(dataUpdate) { + // Final data update + if (dataUpdate) { + this._append(dataUpdate); + } + + // Perform concrete-cipher logic + const finalProcessedData = this._doFinalize(); + + return finalProcessedData; + } +} +Cipher._ENC_XFORM_MODE = 1; +Cipher._DEC_XFORM_MODE = 2; +Cipher.keySize = 128 / 32; +Cipher.ivSize = 128 / 32; + +/** + * Abstract base stream cipher template. + * + * @property {number} blockSize + * + * The number of 32-bit words this cipher operates on. Default: 1 (32 bits) + */ +class StreamCipher extends Cipher { + constructor(...args) { + super(...args); + + this.blockSize = 1; + } + + _doFinalize() { + // Process partial blocks + const finalProcessedBlocks = this._process(!!'flush'); + + return finalProcessedBlocks; + } +} + +/** + * Abstract base block cipher mode template. + */ +class BlockCipherMode extends Base { + /** + * Initializes a newly created mode. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @example + * + * const mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words); + */ + constructor(cipher, iv) { + super(); + + this._cipher = cipher; + this._iv = iv; + } + + /** + * Creates this mode for encryption. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @static + * + * @example + * + * const mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words); + */ + static createEncryptor(cipher, iv) { + return this.Encryptor.create(cipher, iv); + } + + /** + * Creates this mode for decryption. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @static + * + * @example + * + * const mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words); + */ + static createDecryptor(cipher, iv) { + return this.Decryptor.create(cipher, iv); + } +} + +function xorBlock(words, offset, blockSize) { + const _words = words; + let block; + + // Shortcut + const iv = this._iv; + + // Choose mixing block + if (iv) { + block = iv; + + // Remove IV for subsequent blocks + this._iv = undefined; + } else { + block = this._prevBlock; + } + + // XOR blocks + for (let i = 0; i < blockSize; i += 1) { + _words[offset + i] ^= block[i]; + } +} + +/** + * Cipher Block Chaining mode. + */ + +/** + * Abstract base CBC mode. + */ +class CBC extends BlockCipherMode { +} +/** + * CBC encryptor. + */ +CBC.Encryptor = class extends CBC { + /** + * Processes the data block at offset. + * + * @param {Array} words The data words to operate on. + * @param {number} offset The offset where the block starts. + * + * @example + * + * mode.processBlock(data.words, offset); + */ + processBlock(words, offset) { + // Shortcuts + const cipher = this._cipher; + const { blockSize } = cipher; + + // XOR and encrypt + xorBlock.call(this, words, offset, blockSize); + cipher.encryptBlock(words, offset); + + // Remember this block to use with next block + this._prevBlock = words.slice(offset, offset + blockSize); + } +}; +/** + * CBC decryptor. + */ +CBC.Decryptor = class extends CBC { + /** + * Processes the data block at offset. + * + * @param {Array} words The data words to operate on. + * @param {number} offset The offset where the block starts. + * + * @example + * + * mode.processBlock(data.words, offset); + */ + processBlock(words, offset) { + // Shortcuts + const cipher = this._cipher; + const { blockSize } = cipher; + + // Remember this block to use with next block + const thisBlock = words.slice(offset, offset + blockSize); + + // Decrypt and XOR + cipher.decryptBlock(words, offset); + xorBlock.call(this, words, offset, blockSize); + + // This block becomes the previous block + this._prevBlock = thisBlock; + } +}; + +/** + * PKCS #5/7 padding strategy. + */ +const Pkcs7 = { + /** + * Pads data using the algorithm defined in PKCS #5/7. + * + * @param {WordArray} data The data to pad. + * @param {number} blockSize The multiple that the data should be padded to. + * + * @static + * + * @example + * + * CryptoJS.pad.Pkcs7.pad(wordArray, 4); + */ + pad(data, blockSize) { + // Shortcut + const blockSizeBytes = blockSize * 4; + + // Count padding bytes + const nPaddingBytes = blockSizeBytes - (data.sigBytes % blockSizeBytes); + + // Create padding word + const paddingWord = (nPaddingBytes << 24) + | (nPaddingBytes << 16) + | (nPaddingBytes << 8) + | nPaddingBytes; + + // Create padding + const paddingWords = []; + for (let i = 0; i < nPaddingBytes; i += 4) { + paddingWords.push(paddingWord); + } + const padding = WordArray.create(paddingWords, nPaddingBytes); + + // Add padding + data.concat(padding); + }, + + /** + * Unpads data that had been padded using the algorithm defined in PKCS #5/7. + * + * @param {WordArray} data The data to unpad. + * + * @static + * + * @example + * + * CryptoJS.pad.Pkcs7.unpad(wordArray); + */ + unpad(data) { + const _data = data; + + // Get number of padding bytes from last byte + const nPaddingBytes = _data.words[(_data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + _data.sigBytes -= nPaddingBytes; + }, +}; + +/** + * Abstract base block cipher template. + * + * @property {number} blockSize + * + * The number of 32-bit words this cipher operates on. Default: 4 (128 bits) + */ +class BlockCipher extends Cipher { + constructor(xformMode, key, cfg) { + /** + * Configuration options. + * + * @property {Mode} mode The block mode to use. Default: CBC + * @property {Padding} padding The padding strategy to use. Default: Pkcs7 + */ + super(xformMode, key, Object.assign( + { + mode: CBC, + padding: Pkcs7, + }, + cfg, + )); + + this.blockSize = 128 / 32; + } + + reset() { + let modeCreator; + + // Reset cipher + super.reset.call(this); + + // Shortcuts + const { cfg } = this; + const { iv, mode } = cfg; + + // Reset block mode + if (this._xformMode === this.constructor._ENC_XFORM_MODE) { + modeCreator = mode.createEncryptor; + } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ { + modeCreator = mode.createDecryptor; + // Keep at least one block in the buffer for unpadding + this._minBufferSize = 1; + } + + this._mode = modeCreator.call(mode, this, iv && iv.words); + this._mode.__creator = modeCreator; + } + + _doProcessBlock(words, offset) { + this._mode.processBlock(words, offset); + } + + _doFinalize() { + let finalProcessedBlocks; + + // Shortcut + const { padding } = this.cfg; + + // Finalize + if (this._xformMode === this.constructor._ENC_XFORM_MODE) { + // Pad data + padding.pad(this._data, this.blockSize); + + // Process final blocks + finalProcessedBlocks = this._process(!!'flush'); + } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ { + // Process final blocks + finalProcessedBlocks = this._process(!!'flush'); + + // Unpad data + padding.unpad(finalProcessedBlocks); + } + + return finalProcessedBlocks; + } +} + +/** + * A collection of cipher parameters. + * + * @property {WordArray} ciphertext The raw ciphertext. + * @property {WordArray} key The key to this ciphertext. + * @property {WordArray} iv The IV used in the ciphering operation. + * @property {WordArray} salt The salt used with a key derivation function. + * @property {Cipher} algorithm The cipher algorithm. + * @property {Mode} mode The block mode used in the ciphering operation. + * @property {Padding} padding The padding scheme used in the ciphering operation. + * @property {number} blockSize The block size of the cipher. + * @property {Format} formatter + * The default formatting strategy to convert this cipher params object to a string. + */ +class CipherParams extends Base { + /** + * Initializes a newly created cipher params object. + * + * @param {Object} cipherParams An object with any of the possible cipher parameters. + * + * @example + * + * var cipherParams = CryptoJS.lib.CipherParams.create({ + * ciphertext: ciphertextWordArray, + * key: keyWordArray, + * iv: ivWordArray, + * salt: saltWordArray, + * algorithm: CryptoJS.algo.AES, + * mode: CryptoJS.mode.CBC, + * padding: CryptoJS.pad.PKCS7, + * blockSize: 4, + * formatter: CryptoJS.format.OpenSSL + * }); + */ + constructor(cipherParams) { + super(); + + this.mixIn(cipherParams); + } + + /** + * Converts this cipher params object to a string. + * + * @param {Format} formatter (Optional) The formatting strategy to use. + * + * @return {string} The stringified cipher params. + * + * @throws Error If neither the formatter nor the default formatter is set. + * + * @example + * + * var string = cipherParams + ''; + * var string = cipherParams.toString(); + * var string = cipherParams.toString(CryptoJS.format.OpenSSL); + */ + toString(formatter) { + return (formatter || this.formatter).stringify(this); + } +} + +/** + * OpenSSL formatting strategy. + */ +const OpenSSLFormatter = { + /** + * Converts a cipher params object to an OpenSSL-compatible string. + * + * @param {CipherParams} cipherParams The cipher params object. + * + * @return {string} The OpenSSL-compatible string. + * + * @static + * + * @example + * + * var openSSLString = CryptoJS.format.OpenSSL.stringify(cipherParams); + */ + stringify(cipherParams) { + let wordArray; + + // Shortcuts + const { ciphertext, salt } = cipherParams; + + // Format + if (salt) { + wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext); + } else { + wordArray = ciphertext; + } + + return wordArray.toString(Base64); + }, + + /** + * Converts an OpenSSL-compatible string to a cipher params object. + * + * @param {string} openSSLStr The OpenSSL-compatible string. + * + * @return {CipherParams} The cipher params object. + * + * @static + * + * @example + * + * var cipherParams = CryptoJS.format.OpenSSL.parse(openSSLString); + */ + parse(openSSLStr) { + let salt; + + // Parse base64 + const ciphertext = Base64.parse(openSSLStr); + + // Shortcut + const ciphertextWords = ciphertext.words; + + // Test for salt + if (ciphertextWords[0] === 0x53616c74 && ciphertextWords[1] === 0x65645f5f) { + // Extract salt + salt = WordArray.create(ciphertextWords.slice(2, 4)); + + // Remove salt from ciphertext + ciphertextWords.splice(0, 4); + ciphertext.sigBytes -= 16; + } + + return CipherParams.create({ ciphertext, salt }); + }, +}; + +/** + * A cipher wrapper that returns ciphertext as a serializable cipher params object. + */ +class SerializableCipher extends Base { + /** + * Encrypts a message. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {WordArray|string} message The message to encrypt. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {CipherParams} A cipher params object. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.SerializableCipher + * .encrypt(CryptoJS.algo.AES, message, key); + * var ciphertextParams = CryptoJS.lib.SerializableCipher + * .encrypt(CryptoJS.algo.AES, message, key, { iv: iv }); + * var ciphertextParams = CryptoJS.lib.SerializableCipher + * .encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL }); + */ + static encrypt(cipher, message, key, cfg) { + // Apply config defaults + const _cfg = Object.assign(new Base(), this.cfg, cfg); + + // Encrypt + const encryptor = cipher.createEncryptor(key, _cfg); + const ciphertext = encryptor.finalize(message); + + // Shortcut + const cipherCfg = encryptor.cfg; + + // Create and return serializable cipher params + return CipherParams.create({ + ciphertext, + key, + iv: cipherCfg.iv, + algorithm: cipher, + mode: cipherCfg.mode, + padding: cipherCfg.padding, + blockSize: encryptor.blockSize, + formatter: _cfg.format, + }); + } + + /** + * Decrypts serialized ciphertext. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {CipherParams|string} ciphertext The ciphertext to decrypt. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {WordArray} The plaintext. + * + * @static + * + * @example + * + * var plaintext = CryptoJS.lib.SerializableCipher + * .decrypt(CryptoJS.algo.AES, formattedCiphertext, key, + * { iv: iv, format: CryptoJS.format.OpenSSL }); + * var plaintext = CryptoJS.lib.SerializableCipher + * .decrypt(CryptoJS.algo.AES, ciphertextParams, key, + * { iv: iv, format: CryptoJS.format.OpenSSL }); + */ + static decrypt(cipher, ciphertext, key, cfg) { + let _ciphertext = ciphertext; + + // Apply config defaults + const _cfg = Object.assign(new Base(), this.cfg, cfg); + + // Convert string to CipherParams + _ciphertext = this._parse(_ciphertext, _cfg.format); + + // Decrypt + const plaintext = cipher.createDecryptor(key, _cfg).finalize(_ciphertext.ciphertext); + + return plaintext; + } + + /** + * Converts serialized ciphertext to CipherParams, + * else assumed CipherParams already and returns ciphertext unchanged. + * + * @param {CipherParams|string} ciphertext The ciphertext. + * @param {Formatter} format The formatting strategy to use to parse serialized ciphertext. + * + * @return {CipherParams} The unserialized ciphertext. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.SerializableCipher + * ._parse(ciphertextStringOrParams, format); + */ + static _parse(ciphertext, format) { + if (typeof ciphertext === 'string') { + return format.parse(ciphertext, this); + } + return ciphertext; + } +} +/** + * Configuration options. + * + * @property {Formatter} format + * + * The formatting strategy to convert cipher param objects to and from a string. + * Default: OpenSSL + */ +SerializableCipher.cfg = Object.assign( + new Base(), + { format: OpenSSLFormatter }, +); + +/** + * OpenSSL key derivation function. + */ +const OpenSSLKdf = { + /** + * Derives a key and IV from a password. + * + * @param {string} password The password to derive from. + * @param {number} keySize The size in words of the key to generate. + * @param {number} ivSize The size in words of the IV to generate. + * @param {WordArray|string} salt + * (Optional) A 64-bit salt to use. If omitted, a salt will be generated randomly. + * + * @return {CipherParams} A cipher params object with the key, IV, and salt. + * + * @static + * + * @example + * + * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32); + * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt'); + */ + execute(password, keySize, ivSize, salt, hasher) { + let _salt = salt; + + // Generate random salt + if (!_salt) { + _salt = WordArray.random(64 / 8); + } + + // Derive key and IV + let key; + if (!hasher) { + key = EvpKDFAlgo.create({ keySize: keySize + ivSize }).compute(password, _salt); + } else { + key = EvpKDFAlgo.create({ keySize: keySize + ivSize, hasher }).compute(password, _salt); + } + + // Separate key and IV + const iv = WordArray.create(key.words.slice(keySize), ivSize * 4); + key.sigBytes = keySize * 4; + + // Return params + return CipherParams.create({ key, iv, salt: _salt }); + }, +}; + +/** + * A serializable cipher wrapper that derives the key from a password, + * and returns ciphertext as a serializable cipher params object. + */ +class PasswordBasedCipher extends SerializableCipher { + /** + * Encrypts a message using a password. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {WordArray|string} message The message to encrypt. + * @param {string} password The password. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {CipherParams} A cipher params object. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher + * .encrypt(CryptoJS.algo.AES, message, 'password'); + * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher + * .encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL }); + */ + static encrypt(cipher, message, password, cfg) { + // Apply config defaults + const _cfg = Object.assign(new Base(), this.cfg, cfg); + + // Derive key and other params + const derivedParams = _cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, _cfg.salt, _cfg.hasher); + + // Add IV to config + _cfg.iv = derivedParams.iv; + + // Encrypt + const ciphertext = SerializableCipher.encrypt + .call(this, cipher, message, derivedParams.key, _cfg); + + // Mix in derived params + ciphertext.mixIn(derivedParams); + + return ciphertext; + } + + /** + * Decrypts serialized ciphertext using a password. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {CipherParams|string} ciphertext The ciphertext to decrypt. + * @param {string} password The password. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {WordArray} The plaintext. + * + * @static + * + * @example + * + * var plaintext = CryptoJS.lib.PasswordBasedCipher + * .decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password', + * { format: CryptoJS.format.OpenSSL }); + * var plaintext = CryptoJS.lib.PasswordBasedCipher + * .decrypt(CryptoJS.algo.AES, ciphertextParams, 'password', + * { format: CryptoJS.format.OpenSSL }); + */ + static decrypt(cipher, ciphertext, password, cfg) { + let _ciphertext = ciphertext; + + // Apply config defaults + const _cfg = Object.assign(new Base(), this.cfg, cfg); + + // Convert string to CipherParams + _ciphertext = this._parse(_ciphertext, _cfg.format); + + // Derive key and other params + const derivedParams = _cfg.kdf + .execute(password, cipher.keySize, cipher.ivSize, _ciphertext.salt, _cfg.hasher); + + // Add IV to config + _cfg.iv = derivedParams.iv; + + // Decrypt + const plaintext = SerializableCipher.decrypt + .call(this, cipher, _ciphertext, derivedParams.key, _cfg); + + return plaintext; + } +} +/** + * Configuration options. + * + * @property {KDF} kdf + * The key derivation function to use to generate a key and IV from a password. + * Default: OpenSSL + */ +PasswordBasedCipher.cfg = Object.assign(SerializableCipher.cfg, { kdf: OpenSSLKdf }); + +const swapEndian = word => ((word << 8) & 0xff00ff00) | ((word >>> 8) & 0x00ff00ff); + +/** + * UTF-16 BE encoding strategy. + */ +const Utf16BE = { + /** + * Converts a word array to a UTF-16 BE string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-16 BE string. + * + * @static + * + * @example + * + * const utf16String = CryptoJS.enc.Utf16.stringify(wordArray); + */ + stringify(wordArray) { + // Shortcuts + const { words, sigBytes } = wordArray; + + // Convert + const utf16Chars = []; + for (let i = 0; i < sigBytes; i += 2) { + const codePoint = (words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff; + utf16Chars.push(String.fromCharCode(codePoint)); + } + + return utf16Chars.join(''); + }, + + /** + * Converts a UTF-16 BE string to a word array. + * + * @param {string} utf16Str The UTF-16 BE string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * const wordArray = CryptoJS.enc.Utf16.parse(utf16String); + */ + parse(utf16Str) { + // Shortcut + const utf16StrLength = utf16Str.length; + + // Convert + const words = []; + for (let i = 0; i < utf16StrLength; i += 1) { + words[i >>> 1] |= utf16Str.charCodeAt(i) << (16 - (i % 2) * 16); + } + + return WordArray.create(words, utf16StrLength * 2); + }, +}; +const Utf16 = Utf16BE; + +/** + * UTF-16 LE encoding strategy. + */ +const Utf16LE = { + /** + * Converts a word array to a UTF-16 LE string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-16 LE string. + * + * @static + * + * @example + * + * const utf16Str = CryptoJS.enc.Utf16LE.stringify(wordArray); + */ + stringify(wordArray) { + // Shortcuts + const { words, sigBytes } = wordArray; + + // Convert + const utf16Chars = []; + for (let i = 0; i < sigBytes; i += 2) { + const codePoint = swapEndian((words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff); + utf16Chars.push(String.fromCharCode(codePoint)); + } + + return utf16Chars.join(''); + }, + + /** + * Converts a UTF-16 LE string to a word array. + * + * @param {string} utf16Str The UTF-16 LE string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * const wordArray = CryptoJS.enc.Utf16LE.parse(utf16Str); + */ + parse(utf16Str) { + // Shortcut + const utf16StrLength = utf16Str.length; + + // Convert + const words = []; + for (let i = 0; i < utf16StrLength; i += 1) { + words[i >>> 1] |= swapEndian(utf16Str.charCodeAt(i) << (16 - (i % 2) * 16)); + } + + return WordArray.create(words, utf16StrLength * 2); + }, +}; + +/** + * Base64url encoding strategy. + */ +const Base64url = { + /** + * Converts a word array to a Base64url string. + * + * @param {WordArray} wordArray The word array. + * + * @param {boolean} urlSafe Whether to use url safe. + * + * @return {string} The Base64url string. + * + * @static + * + * @example + * + * const base64String = CryptoJS.enc.Base64.stringify(wordArray); + */ + stringify(wordArray, urlSafe = true) { + // Shortcuts + const { words, sigBytes } = wordArray; + const map = urlSafe ? this._safeMap : this._map; + + // Clamp excess bits + wordArray.clamp(); + + // Convert + const base64Chars = []; + for (let i = 0; i < sigBytes; i += 3) { + const byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + const byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff; + const byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff; + + const triplet = (byte1 << 16) | (byte2 << 8) | byte3; + + for (let j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j += 1) { + base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f)); + } + } + + // Add padding + const paddingChar = map.charAt(64); + if (paddingChar) { + while (base64Chars.length % 4) { + base64Chars.push(paddingChar); + } + } + + return base64Chars.join(''); + }, + + /** + * Converts a Base64url string to a word array. + * + * @param {string} base64Str The Base64url string. + * + * @param {boolean} urlSafe Whether to use url safe. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * const wordArray = CryptoJS.enc.Base64.parse(base64String); + */ + parse(base64Str, urlSafe = true) { + // Shortcuts + let base64StrLength = base64Str.length; + const map = urlSafe ? this._safeMap : this._map; + let reverseMap = this._reverseMap; + + if (!reverseMap) { + this._reverseMap = []; + reverseMap = this._reverseMap; + for (let j = 0; j < map.length; j += 1) { + reverseMap[map.charCodeAt(j)] = j; + } + } + + // Ignore padding + const paddingChar = map.charAt(64); + if (paddingChar) { + const paddingIndex = base64Str.indexOf(paddingChar); + if (paddingIndex !== -1) { + base64StrLength = paddingIndex; + } + } + + // Convert + return parseLoop(base64Str, base64StrLength, reverseMap); + }, + + _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', + + _safeMap: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_', +}; + +// Reusable object +const W$2 = []; + +/** + * SHA-1 hash algorithm. + */ +class SHA1Algo extends Hasher { + _doReset() { + this._hash = new WordArray([ + 0x67452301, + 0xefcdab89, + 0x98badcfe, + 0x10325476, + 0xc3d2e1f0, + ]); + } + + _doProcessBlock(M, offset) { + // Shortcut + const H = this._hash.words; + + // Working variables + let a = H[0]; + let b = H[1]; + let c = H[2]; + let d = H[3]; + let e = H[4]; + + // Computation + for (let i = 0; i < 80; i += 1) { + if (i < 16) { + W$2[i] = M[offset + i] | 0; + } else { + const n = W$2[i - 3] ^ W$2[i - 8] ^ W$2[i - 14] ^ W$2[i - 16]; + W$2[i] = (n << 1) | (n >>> 31); + } + + let t = ((a << 5) | (a >>> 27)) + e + W$2[i]; + if (i < 20) { + t += ((b & c) | (~b & d)) + 0x5a827999; + } else if (i < 40) { + t += (b ^ c ^ d) + 0x6ed9eba1; + } else if (i < 60) { + t += ((b & c) | (b & d) | (c & d)) - 0x70e44324; + } else /* if (i < 80) */ { + t += (b ^ c ^ d) - 0x359d3e2a; + } + + e = d; + d = c; + c = (b << 30) | (b >>> 2); + b = a; + a = t; + } + + // Intermediate hash value + H[0] = (H[0] + a) | 0; + H[1] = (H[1] + b) | 0; + H[2] = (H[2] + c) | 0; + H[3] = (H[3] + d) | 0; + H[4] = (H[4] + e) | 0; + } + + _doFinalize() { + // Shortcuts + const data = this._data; + const dataWords = data.words; + + const nBitsTotal = this._nDataBytes * 8; + const nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - (nBitsLeft % 32)); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Return final computed hash + return this._hash; + } + + clone() { + const clone = super.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } +} + +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA1('message'); + * var hash = CryptoJS.SHA1(wordArray); + */ +const SHA1 = Hasher._createHelper(SHA1Algo); + +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA1(message, key); + */ +const HmacSHA1 = Hasher._createHmacHelper(SHA1Algo); + +// Initialization and round constants tables +const H = []; +const K$1 = []; + +// Compute constants +const isPrime = (n) => { + const sqrtN = Math.sqrt(n); + for (let factor = 2; factor <= sqrtN; factor += 1) { + if (!(n % factor)) { + return false; + } + } + + return true; +}; + +const getFractionalBits = n => ((n - (n | 0)) * 0x100000000) | 0; + +let n = 2; +let nPrime = 0; +while (nPrime < 64) { + if (isPrime(n)) { + if (nPrime < 8) { + H[nPrime] = getFractionalBits(n ** (1 / 2)); + } + K$1[nPrime] = getFractionalBits(n ** (1 / 3)); + + nPrime += 1; + } + + n += 1; +} + +// Reusable object +const W$1 = []; + +/** + * SHA-256 hash algorithm. + */ +class SHA256Algo extends Hasher { + _doReset() { + this._hash = new WordArray(H.slice(0)); + } + + _doProcessBlock(M, offset) { + // Shortcut + const _H = this._hash.words; + + // Working variables + let a = _H[0]; + let b = _H[1]; + let c = _H[2]; + let d = _H[3]; + let e = _H[4]; + let f = _H[5]; + let g = _H[6]; + let h = _H[7]; + + // Computation + for (let i = 0; i < 64; i += 1) { + if (i < 16) { + W$1[i] = M[offset + i] | 0; + } else { + const gamma0x = W$1[i - 15]; + const gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) + ^ ((gamma0x << 14) | (gamma0x >>> 18)) + ^ (gamma0x >>> 3); + + const gamma1x = W$1[i - 2]; + const gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) + ^ ((gamma1x << 13) | (gamma1x >>> 19)) + ^ (gamma1x >>> 10); + + W$1[i] = gamma0 + W$1[i - 7] + gamma1 + W$1[i - 16]; + } + + const ch = (e & f) ^ (~e & g); + const maj = (a & b) ^ (a & c) ^ (b & c); + + const sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22)); + const sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7) | (e >>> 25)); + + const t1 = h + sigma1 + ch + K$1[i] + W$1[i]; + const t2 = sigma0 + maj; + + h = g; + g = f; + f = e; + e = (d + t1) | 0; + d = c; + c = b; + b = a; + a = (t1 + t2) | 0; + } + + // Intermediate hash value + _H[0] = (_H[0] + a) | 0; + _H[1] = (_H[1] + b) | 0; + _H[2] = (_H[2] + c) | 0; + _H[3] = (_H[3] + d) | 0; + _H[4] = (_H[4] + e) | 0; + _H[5] = (_H[5] + f) | 0; + _H[6] = (_H[6] + g) | 0; + _H[7] = (_H[7] + h) | 0; + } + + _doFinalize() { + // Shortcuts + const data = this._data; + const dataWords = data.words; + + const nBitsTotal = this._nDataBytes * 8; + const nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - (nBitsLeft % 32)); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Return final computed hash + return this._hash; + } + + clone() { + const clone = super.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } +} + +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA256('message'); + * var hash = CryptoJS.SHA256(wordArray); + */ +const SHA256 = Hasher._createHelper(SHA256Algo); + +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA256(message, key); + */ +const HmacSHA256 = Hasher._createHmacHelper(SHA256Algo); + +/** + * SHA-224 hash algorithm. + */ +class SHA224Algo extends SHA256Algo { + _doReset() { + this._hash = new WordArray([ + 0xc1059ed8, + 0x367cd507, + 0x3070dd17, + 0xf70e5939, + 0xffc00b31, + 0x68581511, + 0x64f98fa7, + 0xbefa4fa4, + ]); + } + + _doFinalize() { + const hash = super._doFinalize.call(this); + + hash.sigBytes -= 4; + + return hash; + } +} + +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA224('message'); + * var hash = CryptoJS.SHA224(wordArray); + */ +const SHA224 = SHA256Algo._createHelper(SHA224Algo); + +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA224(message, key); + */ +const HmacSHA224 = SHA256Algo._createHmacHelper(SHA224Algo); + +// Constants +const K = [ + new X64Word(0x428a2f98, 0xd728ae22), + new X64Word(0x71374491, 0x23ef65cd), + new X64Word(0xb5c0fbcf, 0xec4d3b2f), + new X64Word(0xe9b5dba5, 0x8189dbbc), + new X64Word(0x3956c25b, 0xf348b538), + new X64Word(0x59f111f1, 0xb605d019), + new X64Word(0x923f82a4, 0xaf194f9b), + new X64Word(0xab1c5ed5, 0xda6d8118), + new X64Word(0xd807aa98, 0xa3030242), + new X64Word(0x12835b01, 0x45706fbe), + new X64Word(0x243185be, 0x4ee4b28c), + new X64Word(0x550c7dc3, 0xd5ffb4e2), + new X64Word(0x72be5d74, 0xf27b896f), + new X64Word(0x80deb1fe, 0x3b1696b1), + new X64Word(0x9bdc06a7, 0x25c71235), + new X64Word(0xc19bf174, 0xcf692694), + new X64Word(0xe49b69c1, 0x9ef14ad2), + new X64Word(0xefbe4786, 0x384f25e3), + new X64Word(0x0fc19dc6, 0x8b8cd5b5), + new X64Word(0x240ca1cc, 0x77ac9c65), + new X64Word(0x2de92c6f, 0x592b0275), + new X64Word(0x4a7484aa, 0x6ea6e483), + new X64Word(0x5cb0a9dc, 0xbd41fbd4), + new X64Word(0x76f988da, 0x831153b5), + new X64Word(0x983e5152, 0xee66dfab), + new X64Word(0xa831c66d, 0x2db43210), + new X64Word(0xb00327c8, 0x98fb213f), + new X64Word(0xbf597fc7, 0xbeef0ee4), + new X64Word(0xc6e00bf3, 0x3da88fc2), + new X64Word(0xd5a79147, 0x930aa725), + new X64Word(0x06ca6351, 0xe003826f), + new X64Word(0x14292967, 0x0a0e6e70), + new X64Word(0x27b70a85, 0x46d22ffc), + new X64Word(0x2e1b2138, 0x5c26c926), + new X64Word(0x4d2c6dfc, 0x5ac42aed), + new X64Word(0x53380d13, 0x9d95b3df), + new X64Word(0x650a7354, 0x8baf63de), + new X64Word(0x766a0abb, 0x3c77b2a8), + new X64Word(0x81c2c92e, 0x47edaee6), + new X64Word(0x92722c85, 0x1482353b), + new X64Word(0xa2bfe8a1, 0x4cf10364), + new X64Word(0xa81a664b, 0xbc423001), + new X64Word(0xc24b8b70, 0xd0f89791), + new X64Word(0xc76c51a3, 0x0654be30), + new X64Word(0xd192e819, 0xd6ef5218), + new X64Word(0xd6990624, 0x5565a910), + new X64Word(0xf40e3585, 0x5771202a), + new X64Word(0x106aa070, 0x32bbd1b8), + new X64Word(0x19a4c116, 0xb8d2d0c8), + new X64Word(0x1e376c08, 0x5141ab53), + new X64Word(0x2748774c, 0xdf8eeb99), + new X64Word(0x34b0bcb5, 0xe19b48a8), + new X64Word(0x391c0cb3, 0xc5c95a63), + new X64Word(0x4ed8aa4a, 0xe3418acb), + new X64Word(0x5b9cca4f, 0x7763e373), + new X64Word(0x682e6ff3, 0xd6b2b8a3), + new X64Word(0x748f82ee, 0x5defb2fc), + new X64Word(0x78a5636f, 0x43172f60), + new X64Word(0x84c87814, 0xa1f0ab72), + new X64Word(0x8cc70208, 0x1a6439ec), + new X64Word(0x90befffa, 0x23631e28), + new X64Word(0xa4506ceb, 0xde82bde9), + new X64Word(0xbef9a3f7, 0xb2c67915), + new X64Word(0xc67178f2, 0xe372532b), + new X64Word(0xca273ece, 0xea26619c), + new X64Word(0xd186b8c7, 0x21c0c207), + new X64Word(0xeada7dd6, 0xcde0eb1e), + new X64Word(0xf57d4f7f, 0xee6ed178), + new X64Word(0x06f067aa, 0x72176fba), + new X64Word(0x0a637dc5, 0xa2c898a6), + new X64Word(0x113f9804, 0xbef90dae), + new X64Word(0x1b710b35, 0x131c471b), + new X64Word(0x28db77f5, 0x23047d84), + new X64Word(0x32caab7b, 0x40c72493), + new X64Word(0x3c9ebe0a, 0x15c9bebc), + new X64Word(0x431d67c4, 0x9c100d4c), + new X64Word(0x4cc5d4be, 0xcb3e42b6), + new X64Word(0x597f299c, 0xfc657e2a), + new X64Word(0x5fcb6fab, 0x3ad6faec), + new X64Word(0x6c44198c, 0x4a475817), +]; + +// Reusable objects +const W = []; +for (let i = 0; i < 80; i += 1) { + W[i] = new X64Word(); +} + +/** + * SHA-512 hash algorithm. + */ +class SHA512Algo extends Hasher { + constructor() { + super(); + + this.blockSize = 1024 / 32; + } + + _doReset() { + this._hash = new X64WordArray([ + new X64Word(0x6a09e667, 0xf3bcc908), + new X64Word(0xbb67ae85, 0x84caa73b), + new X64Word(0x3c6ef372, 0xfe94f82b), + new X64Word(0xa54ff53a, 0x5f1d36f1), + new X64Word(0x510e527f, 0xade682d1), + new X64Word(0x9b05688c, 0x2b3e6c1f), + new X64Word(0x1f83d9ab, 0xfb41bd6b), + new X64Word(0x5be0cd19, 0x137e2179), + ]); + } + + _doProcessBlock(M, offset) { + // Shortcuts + const H = this._hash.words; + + const H0 = H[0]; + const H1 = H[1]; + const H2 = H[2]; + const H3 = H[3]; + const H4 = H[4]; + const H5 = H[5]; + const H6 = H[6]; + const H7 = H[7]; + + const H0h = H0.high; + let H0l = H0.low; + const H1h = H1.high; + let H1l = H1.low; + const H2h = H2.high; + let H2l = H2.low; + const H3h = H3.high; + let H3l = H3.low; + const H4h = H4.high; + let H4l = H4.low; + const H5h = H5.high; + let H5l = H5.low; + const H6h = H6.high; + let H6l = H6.low; + const H7h = H7.high; + let H7l = H7.low; + + // Working variables + let ah = H0h; + let al = H0l; + let bh = H1h; + let bl = H1l; + let ch = H2h; + let cl = H2l; + let dh = H3h; + let dl = H3l; + let eh = H4h; + let el = H4l; + let fh = H5h; + let fl = H5l; + let gh = H6h; + let gl = H6l; + let hh = H7h; + let hl = H7l; + + // Rounds + for (let i = 0; i < 80; i += 1) { + let Wil; + let Wih; + + // Shortcut + const Wi = W[i]; + + // Extend message + if (i < 16) { + Wi.high = M[offset + i * 2] | 0; + Wih = Wi.high; + Wi.low = M[offset + i * 2 + 1] | 0; + Wil = Wi.low; + } else { + // Gamma0 + const gamma0x = W[i - 15]; + const gamma0xh = gamma0x.high; + const gamma0xl = gamma0x.low; + const gamma0h = ((gamma0xh >>> 1) | (gamma0xl << 31)) + ^ ((gamma0xh >>> 8) | (gamma0xl << 24)) + ^ (gamma0xh >>> 7); + const gamma0l = ((gamma0xl >>> 1) | (gamma0xh << 31)) + ^ ((gamma0xl >>> 8) | (gamma0xh << 24)) + ^ ((gamma0xl >>> 7) | (gamma0xh << 25)); + + // Gamma1 + const gamma1x = W[i - 2]; + const gamma1xh = gamma1x.high; + const gamma1xl = gamma1x.low; + const gamma1h = ((gamma1xh >>> 19) | (gamma1xl << 13)) + ^ ((gamma1xh << 3) | (gamma1xl >>> 29)) + ^ (gamma1xh >>> 6); + const gamma1l = ((gamma1xl >>> 19) | (gamma1xh << 13)) + ^ ((gamma1xl << 3) | (gamma1xh >>> 29)) + ^ ((gamma1xl >>> 6) | (gamma1xh << 26)); + + // W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16] + const Wi7 = W[i - 7]; + const Wi7h = Wi7.high; + const Wi7l = Wi7.low; + + const Wi16 = W[i - 16]; + const Wi16h = Wi16.high; + const Wi16l = Wi16.low; + + Wil = gamma0l + Wi7l; + Wih = gamma0h + Wi7h + ((Wil >>> 0) < (gamma0l >>> 0) ? 1 : 0); + Wil += gamma1l; + Wih = Wih + gamma1h + ((Wil >>> 0) < (gamma1l >>> 0) ? 1 : 0); + Wil += Wi16l; + Wih = Wih + Wi16h + ((Wil >>> 0) < (Wi16l >>> 0) ? 1 : 0); + + Wi.high = Wih; + Wi.low = Wil; + } + + const chh = (eh & fh) ^ (~eh & gh); + const chl = (el & fl) ^ (~el & gl); + const majh = (ah & bh) ^ (ah & ch) ^ (bh & ch); + const majl = (al & bl) ^ (al & cl) ^ (bl & cl); + + const sigma0h = ((ah >>> 28) | (al << 4)) + ^ ((ah << 30) | (al >>> 2)) + ^ ((ah << 25) | (al >>> 7)); + const sigma0l = ((al >>> 28) | (ah << 4)) + ^ ((al << 30) | (ah >>> 2)) + ^ ((al << 25) | (ah >>> 7)); + const sigma1h = ((eh >>> 14) | (el << 18)) + ^ ((eh >>> 18) | (el << 14)) + ^ ((eh << 23) | (el >>> 9)); + const sigma1l = ((el >>> 14) | (eh << 18)) + ^ ((el >>> 18) | (eh << 14)) + ^ ((el << 23) | (eh >>> 9)); + + // t1 = h + sigma1 + ch + K[i] + W[i] + const Ki = K[i]; + const Kih = Ki.high; + const Kil = Ki.low; + + let t1l = hl + sigma1l; + let t1h = hh + sigma1h + ((t1l >>> 0) < (hl >>> 0) ? 1 : 0); + t1l += chl; + t1h = t1h + chh + ((t1l >>> 0) < (chl >>> 0) ? 1 : 0); + t1l += Kil; + t1h = t1h + Kih + ((t1l >>> 0) < (Kil >>> 0) ? 1 : 0); + t1l += Wil; + t1h = t1h + Wih + ((t1l >>> 0) < (Wil >>> 0) ? 1 : 0); + + // t2 = sigma0 + maj + const t2l = sigma0l + majl; + const t2h = sigma0h + majh + ((t2l >>> 0) < (sigma0l >>> 0) ? 1 : 0); + + // Update working variables + hh = gh; + hl = gl; + gh = fh; + gl = fl; + fh = eh; + fl = el; + el = (dl + t1l) | 0; + eh = (dh + t1h + ((el >>> 0) < (dl >>> 0) ? 1 : 0)) | 0; + dh = ch; + dl = cl; + ch = bh; + cl = bl; + bh = ah; + bl = al; + al = (t1l + t2l) | 0; + ah = (t1h + t2h + ((al >>> 0) < (t1l >>> 0) ? 1 : 0)) | 0; + } + + // Intermediate hash value + H0.low = (H0l + al); + H0l = H0.low; + H0.high = (H0h + ah + ((H0l >>> 0) < (al >>> 0) ? 1 : 0)); + H1.low = (H1l + bl); + H1l = H1.low; + H1.high = (H1h + bh + ((H1l >>> 0) < (bl >>> 0) ? 1 : 0)); + H2.low = (H2l + cl); + H2l = H2.low; + H2.high = (H2h + ch + ((H2l >>> 0) < (cl >>> 0) ? 1 : 0)); + H3.low = (H3l + dl); + H3l = H3.low; + H3.high = (H3h + dh + ((H3l >>> 0) < (dl >>> 0) ? 1 : 0)); + H4.low = (H4l + el); + H4l = H4.low; + H4.high = (H4h + eh + ((H4l >>> 0) < (el >>> 0) ? 1 : 0)); + H5.low = (H5l + fl); + H5l = H5.low; + H5.high = (H5h + fh + ((H5l >>> 0) < (fl >>> 0) ? 1 : 0)); + H6.low = (H6l + gl); + H6l = H6.low; + H6.high = (H6h + gh + ((H6l >>> 0) < (gl >>> 0) ? 1 : 0)); + H7.low = (H7l + hl); + H7l = H7.low; + H7.high = (H7h + hh + ((H7l >>> 0) < (hl >>> 0) ? 1 : 0)); + } + + _doFinalize() { + // Shortcuts + const data = this._data; + const dataWords = data.words; + + const nBitsTotal = this._nDataBytes * 8; + const nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - (nBitsLeft % 32)); + dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 30] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 31] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Convert hash to 32-bit word array before returning + const hash = this._hash.toX32(); + + // Return final computed hash + return hash; + } + + clone() { + const clone = super.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } +} + +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA512('message'); + * var hash = CryptoJS.SHA512(wordArray); + */ +const SHA512 = Hasher._createHelper(SHA512Algo); + +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA512(message, key); + */ +const HmacSHA512 = Hasher._createHmacHelper(SHA512Algo); + +/** + * SHA-384 hash algorithm. + */ +class SHA384Algo extends SHA512Algo { + _doReset() { + this._hash = new X64WordArray([ + new X64Word(0xcbbb9d5d, 0xc1059ed8), + new X64Word(0x629a292a, 0x367cd507), + new X64Word(0x9159015a, 0x3070dd17), + new X64Word(0x152fecd8, 0xf70e5939), + new X64Word(0x67332667, 0xffc00b31), + new X64Word(0x8eb44a87, 0x68581511), + new X64Word(0xdb0c2e0d, 0x64f98fa7), + new X64Word(0x47b5481d, 0xbefa4fa4), + ]); + } + + _doFinalize() { + const hash = super._doFinalize.call(this); + + hash.sigBytes -= 16; + + return hash; + } +} + +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA384('message'); + * var hash = CryptoJS.SHA384(wordArray); + */ +const SHA384 = SHA512Algo._createHelper(SHA384Algo); + +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA384(message, key); + */ +const HmacSHA384 = SHA512Algo._createHmacHelper(SHA384Algo); + +// Constants tables +const RHO_OFFSETS = []; +const PI_INDEXES = []; +const ROUND_CONSTANTS = []; + +// Compute Constants +// Compute rho offset constants +let _x = 1; +let _y = 0; +for (let t = 0; t < 24; t += 1) { + RHO_OFFSETS[_x + 5 * _y] = ((t + 1) * (t + 2) / 2) % 64; + + const newX = _y % 5; + const newY = (2 * _x + 3 * _y) % 5; + _x = newX; + _y = newY; +} + +// Compute pi index constants +for (let x = 0; x < 5; x += 1) { + for (let y = 0; y < 5; y += 1) { + PI_INDEXES[x + 5 * y] = y + ((2 * x + 3 * y) % 5) * 5; + } +} + +// Compute round constants +let LFSR = 0x01; +for (let i = 0; i < 24; i += 1) { + let roundConstantMsw = 0; + let roundConstantLsw = 0; + + for (let j = 0; j < 7; j += 1) { + if (LFSR & 0x01) { + const bitPosition = (1 << j) - 1; + if (bitPosition < 32) { + roundConstantLsw ^= 1 << bitPosition; + } else /* if (bitPosition >= 32) */ { + roundConstantMsw ^= 1 << (bitPosition - 32); + } + } + + // Compute next LFSR + if (LFSR & 0x80) { + // Primitive polynomial over GF(2): x^8 + x^6 + x^5 + x^4 + 1 + LFSR = (LFSR << 1) ^ 0x71; + } else { + LFSR <<= 1; + } + } + + ROUND_CONSTANTS[i] = X64Word.create(roundConstantMsw, roundConstantLsw); +} + +// Reusable objects for temporary values +const T = []; +for (let i = 0; i < 25; i += 1) { + T[i] = X64Word.create(); +} + +/** + * SHA-3 hash algorithm. + */ +class SHA3Algo extends Hasher { + constructor(cfg) { + /** + * Configuration options. + * + * @property {number} outputLength + * The desired number of bits in the output hash. + * Only values permitted are: 224, 256, 384, 512. + * Default: 512 + */ + super(Object.assign( + { outputLength: 512 }, + cfg, + )); + } + + _doReset() { + this._state = []; + const state = this._state; + for (let i = 0; i < 25; i += 1) { + state[i] = new X64Word(); + } + + this.blockSize = (1600 - 2 * this.cfg.outputLength) / 32; + } + + _doProcessBlock(M, offset) { + // Shortcuts + const state = this._state; + const nBlockSizeLanes = this.blockSize / 2; + + // Absorb + for (let i = 0; i < nBlockSizeLanes; i += 1) { + // Shortcuts + let M2i = M[offset + 2 * i]; + let M2i1 = M[offset + 2 * i + 1]; + + // Swap endian + M2i = (((M2i << 8) | (M2i >>> 24)) & 0x00ff00ff) + | (((M2i << 24) | (M2i >>> 8)) & 0xff00ff00); + M2i1 = (((M2i1 << 8) | (M2i1 >>> 24)) & 0x00ff00ff) + | (((M2i1 << 24) | (M2i1 >>> 8)) & 0xff00ff00); + + // Absorb message into state + const lane = state[i]; + lane.high ^= M2i1; + lane.low ^= M2i; + } + + // Rounds + for (let round = 0; round < 24; round += 1) { + // Theta + for (let x = 0; x < 5; x += 1) { + // Mix column lanes + let tMsw = 0; + let tLsw = 0; + for (let y = 0; y < 5; y += 1) { + const lane = state[x + 5 * y]; + tMsw ^= lane.high; + tLsw ^= lane.low; + } + + // Temporary values + const Tx = T[x]; + Tx.high = tMsw; + Tx.low = tLsw; + } + for (let x = 0; x < 5; x += 1) { + // Shortcuts + const Tx4 = T[(x + 4) % 5]; + const Tx1 = T[(x + 1) % 5]; + const Tx1Msw = Tx1.high; + const Tx1Lsw = Tx1.low; + + // Mix surrounding columns + const tMsw = Tx4.high ^ ((Tx1Msw << 1) | (Tx1Lsw >>> 31)); + const tLsw = Tx4.low ^ ((Tx1Lsw << 1) | (Tx1Msw >>> 31)); + for (let y = 0; y < 5; y += 1) { + const lane = state[x + 5 * y]; + lane.high ^= tMsw; + lane.low ^= tLsw; + } + } + + // Rho Pi + for (let laneIndex = 1; laneIndex < 25; laneIndex += 1) { + let tMsw; + let tLsw; + + // Shortcuts + const lane = state[laneIndex]; + const laneMsw = lane.high; + const laneLsw = lane.low; + const rhoOffset = RHO_OFFSETS[laneIndex]; + + // Rotate lanes + if (rhoOffset < 32) { + tMsw = (laneMsw << rhoOffset) | (laneLsw >>> (32 - rhoOffset)); + tLsw = (laneLsw << rhoOffset) | (laneMsw >>> (32 - rhoOffset)); + } else /* if (rhoOffset >= 32) */ { + tMsw = (laneLsw << (rhoOffset - 32)) | (laneMsw >>> (64 - rhoOffset)); + tLsw = (laneMsw << (rhoOffset - 32)) | (laneLsw >>> (64 - rhoOffset)); + } + + // Transpose lanes + const TPiLane = T[PI_INDEXES[laneIndex]]; + TPiLane.high = tMsw; + TPiLane.low = tLsw; + } + + // Rho pi at x = y = 0 + const T0 = T[0]; + const state0 = state[0]; + T0.high = state0.high; + T0.low = state0.low; + + // Chi + for (let x = 0; x < 5; x += 1) { + for (let y = 0; y < 5; y += 1) { + // Shortcuts + const laneIndex = x + 5 * y; + const lane = state[laneIndex]; + const TLane = T[laneIndex]; + const Tx1Lane = T[((x + 1) % 5) + 5 * y]; + const Tx2Lane = T[((x + 2) % 5) + 5 * y]; + + // Mix rows + lane.high = TLane.high ^ (~Tx1Lane.high & Tx2Lane.high); + lane.low = TLane.low ^ (~Tx1Lane.low & Tx2Lane.low); + } + } + + // Iota + const lane = state[0]; + const roundConstant = ROUND_CONSTANTS[round]; + lane.high ^= roundConstant.high; + lane.low ^= roundConstant.low; + } + } + + _doFinalize() { + // Shortcuts + const data = this._data; + const dataWords = data.words; + const nBitsLeft = data.sigBytes * 8; + const blockSizeBits = this.blockSize * 32; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x1 << (24 - (nBitsLeft % 32)); + dataWords[((Math.ceil((nBitsLeft + 1) / blockSizeBits) * blockSizeBits) >>> 5) - 1] |= 0x80; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + const state = this._state; + const outputLengthBytes = this.cfg.outputLength / 8; + const outputLengthLanes = outputLengthBytes / 8; + + // Squeeze + const hashWords = []; + for (let i = 0; i < outputLengthLanes; i += 1) { + // Shortcuts + const lane = state[i]; + let laneMsw = lane.high; + let laneLsw = lane.low; + + // Swap endian + laneMsw = (((laneMsw << 8) | (laneMsw >>> 24)) & 0x00ff00ff) + | (((laneMsw << 24) | (laneMsw >>> 8)) & 0xff00ff00); + laneLsw = (((laneLsw << 8) | (laneLsw >>> 24)) & 0x00ff00ff) + | (((laneLsw << 24) | (laneLsw >>> 8)) & 0xff00ff00); + + // Squeeze state to retrieve hash + hashWords.push(laneLsw); + hashWords.push(laneMsw); + } + + // Return final computed hash + return new WordArray(hashWords, outputLengthBytes); + } + + clone() { + const clone = super.clone.call(this); + + clone._state = this._state.slice(0); + const state = clone._state; + for (let i = 0; i < 25; i += 1) { + state[i] = state[i].clone(); + } + + return clone; + } +} + +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA3('message'); + * var hash = CryptoJS.SHA3(wordArray); + */ +const SHA3 = Hasher._createHelper(SHA3Algo); + +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA3(message, key); + */ +const HmacSHA3 = Hasher._createHmacHelper(SHA3Algo); + +/** @preserve +(c) 2012 by Cédric Mesnil. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted +provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY +WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +// Constants table +const _zl = WordArray.create([ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13]); +const _zr = WordArray.create([ + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11]); +const _sl = WordArray.create([ + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6]); +const _sr = WordArray.create([ + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11]); + +const _hl = WordArray.create([0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E]); +const _hr = WordArray.create([0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000]); + +const f1 = (x, y, z) => (x) ^ (y) ^ (z); + +const f2 = (x, y, z) => ((x) & (y)) | ((~x) & (z)); + +const f3 = (x, y, z) => ((x) | (~(y))) ^ (z); + +const f4 = (x, y, z) => ((x) & (z)) | ((y) & (~(z))); + +const f5 = (x, y, z) => (x) ^ ((y) | (~(z))); + +const rotl = (x, n) => (x << n) | (x >>> (32 - n)); + +/** + * RIPEMD160 hash algorithm. + */ +class RIPEMD160Algo extends Hasher { + _doReset() { + this._hash = WordArray.create([0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]); + } + + _doProcessBlock(M, offset) { + const _M = M; + + // Swap endian + for (let i = 0; i < 16; i += 1) { + // Shortcuts + const offset_i = offset + i; + const M_offset_i = _M[offset_i]; + + // Swap + _M[offset_i] = ( + (((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) + | (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00) + ); + } + // Shortcut + const H = this._hash.words; + const hl = _hl.words; + const hr = _hr.words; + const zl = _zl.words; + const zr = _zr.words; + const sl = _sl.words; + const sr = _sr.words; + + // Working variables + let al = H[0]; + let bl = H[1]; + let cl = H[2]; + let dl = H[3]; + let el = H[4]; + let ar = H[0]; + let br = H[1]; + let cr = H[2]; + let dr = H[3]; + let er = H[4]; + + // Computation + let t; + for (let i = 0; i < 80; i += 1) { + t = (al + _M[offset + zl[i]]) | 0; + if (i < 16) { + t += f1(bl, cl, dl) + hl[0]; + } else if (i < 32) { + t += f2(bl, cl, dl) + hl[1]; + } else if (i < 48) { + t += f3(bl, cl, dl) + hl[2]; + } else if (i < 64) { + t += f4(bl, cl, dl) + hl[3]; + } else { // if (i<80) { + t += f5(bl, cl, dl) + hl[4]; + } + t |= 0; + t = rotl(t, sl[i]); + t = (t + el) | 0; + al = el; + el = dl; + dl = rotl(cl, 10); + cl = bl; + bl = t; + + t = (ar + _M[offset + zr[i]]) | 0; + if (i < 16) { + t += f5(br, cr, dr) + hr[0]; + } else if (i < 32) { + t += f4(br, cr, dr) + hr[1]; + } else if (i < 48) { + t += f3(br, cr, dr) + hr[2]; + } else if (i < 64) { + t += f2(br, cr, dr) + hr[3]; + } else { // if (i<80) { + t += f1(br, cr, dr) + hr[4]; + } + t |= 0; + t = rotl(t, sr[i]); + t = (t + er) | 0; + ar = er; + er = dr; + dr = rotl(cr, 10); + cr = br; + br = t; + } + // Intermediate hash value + t = (H[1] + cl + dr) | 0; + H[1] = (H[2] + dl + er) | 0; + H[2] = (H[3] + el + ar) | 0; + H[3] = (H[4] + al + br) | 0; + H[4] = (H[0] + bl + cr) | 0; + H[0] = t; + } + + _doFinalize() { + // Shortcuts + const data = this._data; + const dataWords = data.words; + + const nBitsTotal = this._nDataBytes * 8; + const nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - (nBitsLeft % 32)); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = ( + (((nBitsTotal << 8) | (nBitsTotal >>> 24)) & 0x00ff00ff) + | (((nBitsTotal << 24) | (nBitsTotal >>> 8)) & 0xff00ff00) + ); + data.sigBytes = (dataWords.length + 1) * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + const hash = this._hash; + const H = hash.words; + + // Swap endian + for (let i = 0; i < 5; i += 1) { + // Shortcut + const H_i = H[i]; + + // Swap + H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) + | (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00); + } + + // Return final computed hash + return hash; + } + + clone() { + const clone = super.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } +} + +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.RIPEMD160('message'); + * var hash = CryptoJS.RIPEMD160(wordArray); + */ +const RIPEMD160 = Hasher._createHelper(RIPEMD160Algo); + +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacRIPEMD160(message, key); + */ +const HmacRIPEMD160 = Hasher._createHmacHelper(RIPEMD160Algo); + +/** + * Password-Based Key Derivation Function 2 algorithm. + */ +class PBKDF2Algo extends Base { + /** + * Initializes a newly created key derivation function. + * + * @param {Object} cfg (Optional) The configuration options to use for the derivation. + * + * @example + * + * const kdf = CryptoJS.algo.PBKDF2.create(); + * const kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8 }); + * const kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8, iterations: 1000 }); + */ + constructor(cfg) { + super(); + + /** + * Configuration options. + * + * The default `hasher` and `interations` is different from CryptoJs to enhance security: + * https://github.com/entronad/crypto-es/security/advisories/GHSA-mpj8-q39x-wq5h + * + * @property {number} keySize The key size in words to generate. Default: 4 (128 bits) + * @property {Hasher} hasher The hasher to use. Default: SHA256 + * @property {number} iterations The number of iterations to perform. Default: 250000 + */ + this.cfg = Object.assign( + new Base(), + { + keySize: 128 / 32, + hasher: SHA256Algo, + iterations: 250000, + }, + cfg, + ); + } + + /** + * Computes the Password-Based Key Derivation Function 2. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * + * @return {WordArray} The derived key. + * + * @example + * + * const key = kdf.compute(password, salt); + */ + compute(password, salt) { + // Shortcut + const { cfg } = this; + + // Init HMAC + const hmac = HMAC.create(cfg.hasher, password); + + // Initial values + const derivedKey = WordArray.create(); + const blockIndex = WordArray.create([0x00000001]); + + // Shortcuts + const derivedKeyWords = derivedKey.words; + const blockIndexWords = blockIndex.words; + const { keySize, iterations } = cfg; + + // Generate key + while (derivedKeyWords.length < keySize) { + const block = hmac.update(salt).finalize(blockIndex); + hmac.reset(); + + // Shortcuts + const blockWords = block.words; + const blockWordsLength = blockWords.length; + + // Iterations + let intermediate = block; + for (let i = 1; i < iterations; i += 1) { + intermediate = hmac.finalize(intermediate); + hmac.reset(); + + // Shortcut + const intermediateWords = intermediate.words; + + // XOR intermediate with block + for (let j = 0; j < blockWordsLength; j += 1) { + blockWords[j] ^= intermediateWords[j]; + } + } + + derivedKey.concat(block); + blockIndexWords[0] += 1; + } + derivedKey.sigBytes = keySize * 4; + + return derivedKey; + } +} + +/** + * Computes the Password-Based Key Derivation Function 2. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * @param {Object} cfg (Optional) The configuration options to use for this computation. + * + * @return {WordArray} The derived key. + * + * @static + * + * @example + * + * var key = CryptoJS.PBKDF2(password, salt); + * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8 }); + * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8, iterations: 1000 }); + */ +const PBKDF2 = (password, salt, cfg) => PBKDF2Algo.create(cfg).compute(password, salt); + +// Lookup tables +const _SBOX = []; +const INV_SBOX = []; +const _SUB_MIX_0 = []; +const _SUB_MIX_1 = []; +const _SUB_MIX_2 = []; +const _SUB_MIX_3 = []; +const INV_SUB_MIX_0 = []; +const INV_SUB_MIX_1 = []; +const INV_SUB_MIX_2 = []; +const INV_SUB_MIX_3 = []; + +// Compute lookup tables + +// Compute double table +const d = []; +for (let i = 0; i < 256; i += 1) { + if (i < 128) { + d[i] = i << 1; + } else { + d[i] = (i << 1) ^ 0x11b; + } +} + +// Walk GF(2^8) +let x = 0; +let xi = 0; +for (let i = 0; i < 256; i += 1) { + // Compute sbox + let sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4); + sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63; + _SBOX[x] = sx; + INV_SBOX[sx] = x; + + // Compute multiplication + const x2 = d[x]; + const x4 = d[x2]; + const x8 = d[x4]; + + // Compute sub bytes, mix columns tables + let t = (d[sx] * 0x101) ^ (sx * 0x1010100); + _SUB_MIX_0[x] = (t << 24) | (t >>> 8); + _SUB_MIX_1[x] = (t << 16) | (t >>> 16); + _SUB_MIX_2[x] = (t << 8) | (t >>> 24); + _SUB_MIX_3[x] = t; + + // Compute inv sub bytes, inv mix columns tables + t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100); + INV_SUB_MIX_0[sx] = (t << 24) | (t >>> 8); + INV_SUB_MIX_1[sx] = (t << 16) | (t >>> 16); + INV_SUB_MIX_2[sx] = (t << 8) | (t >>> 24); + INV_SUB_MIX_3[sx] = t; + + // Compute next counter + if (!x) { + xi = 1; + x = xi; + } else { + x = x2 ^ d[d[d[x8 ^ x2]]]; + xi ^= d[d[xi]]; + } +} + +// Precomputed Rcon lookup +const RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36]; + +/** + * AES block cipher algorithm. + */ +class AESAlgo extends BlockCipher { + _doReset() { + let t; + + // Skip reset of nRounds has been set before and key did not change + if (this._nRounds && this._keyPriorReset === this._key) { + return; + } + + // Shortcuts + this._keyPriorReset = this._key; + const key = this._keyPriorReset; + const keyWords = key.words; + const keySize = key.sigBytes / 4; + + // Compute number of rounds + this._nRounds = keySize + 6; + const nRounds = this._nRounds; + + // Compute number of key schedule rows + const ksRows = (nRounds + 1) * 4; + + // Compute key schedule + this._keySchedule = []; + const keySchedule = this._keySchedule; + for (let ksRow = 0; ksRow < ksRows; ksRow += 1) { + if (ksRow < keySize) { + keySchedule[ksRow] = keyWords[ksRow]; + } else { + t = keySchedule[ksRow - 1]; + + if (!(ksRow % keySize)) { + // Rot word + t = (t << 8) | (t >>> 24); + + // Sub word + t = (_SBOX[t >>> 24] << 24) + | (_SBOX[(t >>> 16) & 0xff] << 16) + | (_SBOX[(t >>> 8) & 0xff] << 8) + | _SBOX[t & 0xff]; + + // Mix Rcon + t ^= RCON[(ksRow / keySize) | 0] << 24; + } else if (keySize > 6 && ksRow % keySize === 4) { + // Sub word + t = (_SBOX[t >>> 24] << 24) + | (_SBOX[(t >>> 16) & 0xff] << 16) + | (_SBOX[(t >>> 8) & 0xff] << 8) + | _SBOX[t & 0xff]; + } + + keySchedule[ksRow] = keySchedule[ksRow - keySize] ^ t; + } + } + + // Compute inv key schedule + this._invKeySchedule = []; + const invKeySchedule = this._invKeySchedule; + for (let invKsRow = 0; invKsRow < ksRows; invKsRow += 1) { + const ksRow = ksRows - invKsRow; + + if (invKsRow % 4) { + t = keySchedule[ksRow]; + } else { + t = keySchedule[ksRow - 4]; + } + + if (invKsRow < 4 || ksRow <= 4) { + invKeySchedule[invKsRow] = t; + } else { + invKeySchedule[invKsRow] = INV_SUB_MIX_0[_SBOX[t >>> 24]] + ^ INV_SUB_MIX_1[_SBOX[(t >>> 16) & 0xff]] + ^ INV_SUB_MIX_2[_SBOX[(t >>> 8) & 0xff]] + ^ INV_SUB_MIX_3[_SBOX[t & 0xff]]; + } + } + } + + encryptBlock(M, offset) { + this._doCryptBlock( + M, offset, this._keySchedule, _SUB_MIX_0, _SUB_MIX_1, _SUB_MIX_2, _SUB_MIX_3, _SBOX, + ); + } + + decryptBlock(M, offset) { + const _M = M; + + // Swap 2nd and 4th rows + let t = _M[offset + 1]; + _M[offset + 1] = _M[offset + 3]; + _M[offset + 3] = t; + + this._doCryptBlock( + _M, + offset, + this._invKeySchedule, + INV_SUB_MIX_0, + INV_SUB_MIX_1, + INV_SUB_MIX_2, + INV_SUB_MIX_3, + INV_SBOX, + ); + + // Inv swap 2nd and 4th rows + t = _M[offset + 1]; + _M[offset + 1] = _M[offset + 3]; + _M[offset + 3] = t; + } + + _doCryptBlock(M, offset, keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) { + const _M = M; + + // Shortcut + const nRounds = this._nRounds; + + // Get input, add round key + let s0 = _M[offset] ^ keySchedule[0]; + let s1 = _M[offset + 1] ^ keySchedule[1]; + let s2 = _M[offset + 2] ^ keySchedule[2]; + let s3 = _M[offset + 3] ^ keySchedule[3]; + + // Key schedule row counter + let ksRow = 4; + + // Rounds + for (let round = 1; round < nRounds; round += 1) { + // Shift rows, sub bytes, mix columns, add round key + const t0 = SUB_MIX_0[s0 >>> 24] + ^ SUB_MIX_1[(s1 >>> 16) & 0xff] + ^ SUB_MIX_2[(s2 >>> 8) & 0xff] + ^ SUB_MIX_3[s3 & 0xff] + ^ keySchedule[ksRow]; + ksRow += 1; + const t1 = SUB_MIX_0[s1 >>> 24] + ^ SUB_MIX_1[(s2 >>> 16) & 0xff] + ^ SUB_MIX_2[(s3 >>> 8) & 0xff] + ^ SUB_MIX_3[s0 & 0xff] + ^ keySchedule[ksRow]; + ksRow += 1; + const t2 = SUB_MIX_0[s2 >>> 24] + ^ SUB_MIX_1[(s3 >>> 16) & 0xff] + ^ SUB_MIX_2[(s0 >>> 8) & 0xff] + ^ SUB_MIX_3[s1 & 0xff] + ^ keySchedule[ksRow]; + ksRow += 1; + const t3 = SUB_MIX_0[s3 >>> 24] + ^ SUB_MIX_1[(s0 >>> 16) & 0xff] + ^ SUB_MIX_2[(s1 >>> 8) & 0xff] + ^ SUB_MIX_3[s2 & 0xff] + ^ keySchedule[ksRow]; + ksRow += 1; + + // Update state + s0 = t0; + s1 = t1; + s2 = t2; + s3 = t3; + } + + // Shift rows, sub bytes, add round key + const t0 = ( + (SBOX[s0 >>> 24] << 24) + | (SBOX[(s1 >>> 16) & 0xff] << 16) + | (SBOX[(s2 >>> 8) & 0xff] << 8) + | SBOX[s3 & 0xff] + ) ^ keySchedule[ksRow]; + ksRow += 1; + const t1 = ( + (SBOX[s1 >>> 24] << 24) + | (SBOX[(s2 >>> 16) & 0xff] << 16) + | (SBOX[(s3 >>> 8) & 0xff] << 8) + | SBOX[s0 & 0xff] + ) ^ keySchedule[ksRow]; + ksRow += 1; + const t2 = ( + (SBOX[s2 >>> 24] << 24) + | (SBOX[(s3 >>> 16) & 0xff] << 16) + | (SBOX[(s0 >>> 8) & 0xff] << 8) + | SBOX[s1 & 0xff] + ) ^ keySchedule[ksRow]; + ksRow += 1; + const t3 = ( + (SBOX[s3 >>> 24] << 24) + | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff] + ) ^ keySchedule[ksRow]; + ksRow += 1; + + // Set output + _M[offset] = t0; + _M[offset + 1] = t1; + _M[offset + 2] = t2; + _M[offset + 3] = t3; + } +} +AESAlgo.keySize = 256 / 32; + +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.AES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.AES.decrypt(ciphertext, key, cfg); + */ +const AES = BlockCipher._createHelper(AESAlgo); + +// Permuted Choice 1 constants +const PC1 = [ + 57, 49, 41, 33, 25, 17, 9, 1, + 58, 50, 42, 34, 26, 18, 10, 2, + 59, 51, 43, 35, 27, 19, 11, 3, + 60, 52, 44, 36, 63, 55, 47, 39, + 31, 23, 15, 7, 62, 54, 46, 38, + 30, 22, 14, 6, 61, 53, 45, 37, + 29, 21, 13, 5, 28, 20, 12, 4, +]; + +// Permuted Choice 2 constants +const PC2 = [ + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32, +]; + +// Cumulative bit shift constants +const BIT_SHIFTS = [1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28]; + +// SBOXes and round permutation constants +const SBOX_P = [ + { + 0x0: 0x808200, + 0x10000000: 0x8000, + 0x20000000: 0x808002, + 0x30000000: 0x2, + 0x40000000: 0x200, + 0x50000000: 0x808202, + 0x60000000: 0x800202, + 0x70000000: 0x800000, + 0x80000000: 0x202, + 0x90000000: 0x800200, + 0xa0000000: 0x8200, + 0xb0000000: 0x808000, + 0xc0000000: 0x8002, + 0xd0000000: 0x800002, + 0xe0000000: 0x0, + 0xf0000000: 0x8202, + 0x8000000: 0x0, + 0x18000000: 0x808202, + 0x28000000: 0x8202, + 0x38000000: 0x8000, + 0x48000000: 0x808200, + 0x58000000: 0x200, + 0x68000000: 0x808002, + 0x78000000: 0x2, + 0x88000000: 0x800200, + 0x98000000: 0x8200, + 0xa8000000: 0x808000, + 0xb8000000: 0x800202, + 0xc8000000: 0x800002, + 0xd8000000: 0x8002, + 0xe8000000: 0x202, + 0xf8000000: 0x800000, + 0x1: 0x8000, + 0x10000001: 0x2, + 0x20000001: 0x808200, + 0x30000001: 0x800000, + 0x40000001: 0x808002, + 0x50000001: 0x8200, + 0x60000001: 0x200, + 0x70000001: 0x800202, + 0x80000001: 0x808202, + 0x90000001: 0x808000, + 0xa0000001: 0x800002, + 0xb0000001: 0x8202, + 0xc0000001: 0x202, + 0xd0000001: 0x800200, + 0xe0000001: 0x8002, + 0xf0000001: 0x0, + 0x8000001: 0x808202, + 0x18000001: 0x808000, + 0x28000001: 0x800000, + 0x38000001: 0x200, + 0x48000001: 0x8000, + 0x58000001: 0x800002, + 0x68000001: 0x2, + 0x78000001: 0x8202, + 0x88000001: 0x8002, + 0x98000001: 0x800202, + 0xa8000001: 0x202, + 0xb8000001: 0x808200, + 0xc8000001: 0x800200, + 0xd8000001: 0x0, + 0xe8000001: 0x8200, + 0xf8000001: 0x808002, + }, + { + 0x0: 0x40084010, + 0x1000000: 0x4000, + 0x2000000: 0x80000, + 0x3000000: 0x40080010, + 0x4000000: 0x40000010, + 0x5000000: 0x40084000, + 0x6000000: 0x40004000, + 0x7000000: 0x10, + 0x8000000: 0x84000, + 0x9000000: 0x40004010, + 0xa000000: 0x40000000, + 0xb000000: 0x84010, + 0xc000000: 0x80010, + 0xd000000: 0x0, + 0xe000000: 0x4010, + 0xf000000: 0x40080000, + 0x800000: 0x40004000, + 0x1800000: 0x84010, + 0x2800000: 0x10, + 0x3800000: 0x40004010, + 0x4800000: 0x40084010, + 0x5800000: 0x40000000, + 0x6800000: 0x80000, + 0x7800000: 0x40080010, + 0x8800000: 0x80010, + 0x9800000: 0x0, + 0xa800000: 0x4000, + 0xb800000: 0x40080000, + 0xc800000: 0x40000010, + 0xd800000: 0x84000, + 0xe800000: 0x40084000, + 0xf800000: 0x4010, + 0x10000000: 0x0, + 0x11000000: 0x40080010, + 0x12000000: 0x40004010, + 0x13000000: 0x40084000, + 0x14000000: 0x40080000, + 0x15000000: 0x10, + 0x16000000: 0x84010, + 0x17000000: 0x4000, + 0x18000000: 0x4010, + 0x19000000: 0x80000, + 0x1a000000: 0x80010, + 0x1b000000: 0x40000010, + 0x1c000000: 0x84000, + 0x1d000000: 0x40004000, + 0x1e000000: 0x40000000, + 0x1f000000: 0x40084010, + 0x10800000: 0x84010, + 0x11800000: 0x80000, + 0x12800000: 0x40080000, + 0x13800000: 0x4000, + 0x14800000: 0x40004000, + 0x15800000: 0x40084010, + 0x16800000: 0x10, + 0x17800000: 0x40000000, + 0x18800000: 0x40084000, + 0x19800000: 0x40000010, + 0x1a800000: 0x40004010, + 0x1b800000: 0x80010, + 0x1c800000: 0x0, + 0x1d800000: 0x4010, + 0x1e800000: 0x40080010, + 0x1f800000: 0x84000, + }, + { + 0x0: 0x104, + 0x100000: 0x0, + 0x200000: 0x4000100, + 0x300000: 0x10104, + 0x400000: 0x10004, + 0x500000: 0x4000004, + 0x600000: 0x4010104, + 0x700000: 0x4010000, + 0x800000: 0x4000000, + 0x900000: 0x4010100, + 0xa00000: 0x10100, + 0xb00000: 0x4010004, + 0xc00000: 0x4000104, + 0xd00000: 0x10000, + 0xe00000: 0x4, + 0xf00000: 0x100, + 0x80000: 0x4010100, + 0x180000: 0x4010004, + 0x280000: 0x0, + 0x380000: 0x4000100, + 0x480000: 0x4000004, + 0x580000: 0x10000, + 0x680000: 0x10004, + 0x780000: 0x104, + 0x880000: 0x4, + 0x980000: 0x100, + 0xa80000: 0x4010000, + 0xb80000: 0x10104, + 0xc80000: 0x10100, + 0xd80000: 0x4000104, + 0xe80000: 0x4010104, + 0xf80000: 0x4000000, + 0x1000000: 0x4010100, + 0x1100000: 0x10004, + 0x1200000: 0x10000, + 0x1300000: 0x4000100, + 0x1400000: 0x100, + 0x1500000: 0x4010104, + 0x1600000: 0x4000004, + 0x1700000: 0x0, + 0x1800000: 0x4000104, + 0x1900000: 0x4000000, + 0x1a00000: 0x4, + 0x1b00000: 0x10100, + 0x1c00000: 0x4010000, + 0x1d00000: 0x104, + 0x1e00000: 0x10104, + 0x1f00000: 0x4010004, + 0x1080000: 0x4000000, + 0x1180000: 0x104, + 0x1280000: 0x4010100, + 0x1380000: 0x0, + 0x1480000: 0x10004, + 0x1580000: 0x4000100, + 0x1680000: 0x100, + 0x1780000: 0x4010004, + 0x1880000: 0x10000, + 0x1980000: 0x4010104, + 0x1a80000: 0x10104, + 0x1b80000: 0x4000004, + 0x1c80000: 0x4000104, + 0x1d80000: 0x4010000, + 0x1e80000: 0x4, + 0x1f80000: 0x10100, + }, + { + 0x0: 0x80401000, + 0x10000: 0x80001040, + 0x20000: 0x401040, + 0x30000: 0x80400000, + 0x40000: 0x0, + 0x50000: 0x401000, + 0x60000: 0x80000040, + 0x70000: 0x400040, + 0x80000: 0x80000000, + 0x90000: 0x400000, + 0xa0000: 0x40, + 0xb0000: 0x80001000, + 0xc0000: 0x80400040, + 0xd0000: 0x1040, + 0xe0000: 0x1000, + 0xf0000: 0x80401040, + 0x8000: 0x80001040, + 0x18000: 0x40, + 0x28000: 0x80400040, + 0x38000: 0x80001000, + 0x48000: 0x401000, + 0x58000: 0x80401040, + 0x68000: 0x0, + 0x78000: 0x80400000, + 0x88000: 0x1000, + 0x98000: 0x80401000, + 0xa8000: 0x400000, + 0xb8000: 0x1040, + 0xc8000: 0x80000000, + 0xd8000: 0x400040, + 0xe8000: 0x401040, + 0xf8000: 0x80000040, + 0x100000: 0x400040, + 0x110000: 0x401000, + 0x120000: 0x80000040, + 0x130000: 0x0, + 0x140000: 0x1040, + 0x150000: 0x80400040, + 0x160000: 0x80401000, + 0x170000: 0x80001040, + 0x180000: 0x80401040, + 0x190000: 0x80000000, + 0x1a0000: 0x80400000, + 0x1b0000: 0x401040, + 0x1c0000: 0x80001000, + 0x1d0000: 0x400000, + 0x1e0000: 0x40, + 0x1f0000: 0x1000, + 0x108000: 0x80400000, + 0x118000: 0x80401040, + 0x128000: 0x0, + 0x138000: 0x401000, + 0x148000: 0x400040, + 0x158000: 0x80000000, + 0x168000: 0x80001040, + 0x178000: 0x40, + 0x188000: 0x80000040, + 0x198000: 0x1000, + 0x1a8000: 0x80001000, + 0x1b8000: 0x80400040, + 0x1c8000: 0x1040, + 0x1d8000: 0x80401000, + 0x1e8000: 0x400000, + 0x1f8000: 0x401040, + }, + { + 0x0: 0x80, + 0x1000: 0x1040000, + 0x2000: 0x40000, + 0x3000: 0x20000000, + 0x4000: 0x20040080, + 0x5000: 0x1000080, + 0x6000: 0x21000080, + 0x7000: 0x40080, + 0x8000: 0x1000000, + 0x9000: 0x20040000, + 0xa000: 0x20000080, + 0xb000: 0x21040080, + 0xc000: 0x21040000, + 0xd000: 0x0, + 0xe000: 0x1040080, + 0xf000: 0x21000000, + 0x800: 0x1040080, + 0x1800: 0x21000080, + 0x2800: 0x80, + 0x3800: 0x1040000, + 0x4800: 0x40000, + 0x5800: 0x20040080, + 0x6800: 0x21040000, + 0x7800: 0x20000000, + 0x8800: 0x20040000, + 0x9800: 0x0, + 0xa800: 0x21040080, + 0xb800: 0x1000080, + 0xc800: 0x20000080, + 0xd800: 0x21000000, + 0xe800: 0x1000000, + 0xf800: 0x40080, + 0x10000: 0x40000, + 0x11000: 0x80, + 0x12000: 0x20000000, + 0x13000: 0x21000080, + 0x14000: 0x1000080, + 0x15000: 0x21040000, + 0x16000: 0x20040080, + 0x17000: 0x1000000, + 0x18000: 0x21040080, + 0x19000: 0x21000000, + 0x1a000: 0x1040000, + 0x1b000: 0x20040000, + 0x1c000: 0x40080, + 0x1d000: 0x20000080, + 0x1e000: 0x0, + 0x1f000: 0x1040080, + 0x10800: 0x21000080, + 0x11800: 0x1000000, + 0x12800: 0x1040000, + 0x13800: 0x20040080, + 0x14800: 0x20000000, + 0x15800: 0x1040080, + 0x16800: 0x80, + 0x17800: 0x21040000, + 0x18800: 0x40080, + 0x19800: 0x21040080, + 0x1a800: 0x0, + 0x1b800: 0x21000000, + 0x1c800: 0x1000080, + 0x1d800: 0x40000, + 0x1e800: 0x20040000, + 0x1f800: 0x20000080, + }, + { + 0x0: 0x10000008, + 0x100: 0x2000, + 0x200: 0x10200000, + 0x300: 0x10202008, + 0x400: 0x10002000, + 0x500: 0x200000, + 0x600: 0x200008, + 0x700: 0x10000000, + 0x800: 0x0, + 0x900: 0x10002008, + 0xa00: 0x202000, + 0xb00: 0x8, + 0xc00: 0x10200008, + 0xd00: 0x202008, + 0xe00: 0x2008, + 0xf00: 0x10202000, + 0x80: 0x10200000, + 0x180: 0x10202008, + 0x280: 0x8, + 0x380: 0x200000, + 0x480: 0x202008, + 0x580: 0x10000008, + 0x680: 0x10002000, + 0x780: 0x2008, + 0x880: 0x200008, + 0x980: 0x2000, + 0xa80: 0x10002008, + 0xb80: 0x10200008, + 0xc80: 0x0, + 0xd80: 0x10202000, + 0xe80: 0x202000, + 0xf80: 0x10000000, + 0x1000: 0x10002000, + 0x1100: 0x10200008, + 0x1200: 0x10202008, + 0x1300: 0x2008, + 0x1400: 0x200000, + 0x1500: 0x10000000, + 0x1600: 0x10000008, + 0x1700: 0x202000, + 0x1800: 0x202008, + 0x1900: 0x0, + 0x1a00: 0x8, + 0x1b00: 0x10200000, + 0x1c00: 0x2000, + 0x1d00: 0x10002008, + 0x1e00: 0x10202000, + 0x1f00: 0x200008, + 0x1080: 0x8, + 0x1180: 0x202000, + 0x1280: 0x200000, + 0x1380: 0x10000008, + 0x1480: 0x10002000, + 0x1580: 0x2008, + 0x1680: 0x10202008, + 0x1780: 0x10200000, + 0x1880: 0x10202000, + 0x1980: 0x10200008, + 0x1a80: 0x2000, + 0x1b80: 0x202008, + 0x1c80: 0x200008, + 0x1d80: 0x0, + 0x1e80: 0x10000000, + 0x1f80: 0x10002008, + }, + { + 0x0: 0x100000, + 0x10: 0x2000401, + 0x20: 0x400, + 0x30: 0x100401, + 0x40: 0x2100401, + 0x50: 0x0, + 0x60: 0x1, + 0x70: 0x2100001, + 0x80: 0x2000400, + 0x90: 0x100001, + 0xa0: 0x2000001, + 0xb0: 0x2100400, + 0xc0: 0x2100000, + 0xd0: 0x401, + 0xe0: 0x100400, + 0xf0: 0x2000000, + 0x8: 0x2100001, + 0x18: 0x0, + 0x28: 0x2000401, + 0x38: 0x2100400, + 0x48: 0x100000, + 0x58: 0x2000001, + 0x68: 0x2000000, + 0x78: 0x401, + 0x88: 0x100401, + 0x98: 0x2000400, + 0xa8: 0x2100000, + 0xb8: 0x100001, + 0xc8: 0x400, + 0xd8: 0x2100401, + 0xe8: 0x1, + 0xf8: 0x100400, + 0x100: 0x2000000, + 0x110: 0x100000, + 0x120: 0x2000401, + 0x130: 0x2100001, + 0x140: 0x100001, + 0x150: 0x2000400, + 0x160: 0x2100400, + 0x170: 0x100401, + 0x180: 0x401, + 0x190: 0x2100401, + 0x1a0: 0x100400, + 0x1b0: 0x1, + 0x1c0: 0x0, + 0x1d0: 0x2100000, + 0x1e0: 0x2000001, + 0x1f0: 0x400, + 0x108: 0x100400, + 0x118: 0x2000401, + 0x128: 0x2100001, + 0x138: 0x1, + 0x148: 0x2000000, + 0x158: 0x100000, + 0x168: 0x401, + 0x178: 0x2100400, + 0x188: 0x2000001, + 0x198: 0x2100000, + 0x1a8: 0x0, + 0x1b8: 0x2100401, + 0x1c8: 0x100401, + 0x1d8: 0x400, + 0x1e8: 0x2000400, + 0x1f8: 0x100001, + }, + { + 0x0: 0x8000820, + 0x1: 0x20000, + 0x2: 0x8000000, + 0x3: 0x20, + 0x4: 0x20020, + 0x5: 0x8020820, + 0x6: 0x8020800, + 0x7: 0x800, + 0x8: 0x8020000, + 0x9: 0x8000800, + 0xa: 0x20800, + 0xb: 0x8020020, + 0xc: 0x820, + 0xd: 0x0, + 0xe: 0x8000020, + 0xf: 0x20820, + 0x80000000: 0x800, + 0x80000001: 0x8020820, + 0x80000002: 0x8000820, + 0x80000003: 0x8000000, + 0x80000004: 0x8020000, + 0x80000005: 0x20800, + 0x80000006: 0x20820, + 0x80000007: 0x20, + 0x80000008: 0x8000020, + 0x80000009: 0x820, + 0x8000000a: 0x20020, + 0x8000000b: 0x8020800, + 0x8000000c: 0x0, + 0x8000000d: 0x8020020, + 0x8000000e: 0x8000800, + 0x8000000f: 0x20000, + 0x10: 0x20820, + 0x11: 0x8020800, + 0x12: 0x20, + 0x13: 0x800, + 0x14: 0x8000800, + 0x15: 0x8000020, + 0x16: 0x8020020, + 0x17: 0x20000, + 0x18: 0x0, + 0x19: 0x20020, + 0x1a: 0x8020000, + 0x1b: 0x8000820, + 0x1c: 0x8020820, + 0x1d: 0x20800, + 0x1e: 0x820, + 0x1f: 0x8000000, + 0x80000010: 0x20000, + 0x80000011: 0x800, + 0x80000012: 0x8020020, + 0x80000013: 0x20820, + 0x80000014: 0x20, + 0x80000015: 0x8020000, + 0x80000016: 0x8000000, + 0x80000017: 0x8000820, + 0x80000018: 0x8020820, + 0x80000019: 0x8000020, + 0x8000001a: 0x8000800, + 0x8000001b: 0x0, + 0x8000001c: 0x20800, + 0x8000001d: 0x820, + 0x8000001e: 0x20020, + 0x8000001f: 0x8020800, + }, +]; + +// Masks that select the SBOX input +const SBOX_MASK = [ + 0xf8000001, 0x1f800000, 0x01f80000, 0x001f8000, + 0x0001f800, 0x00001f80, 0x000001f8, 0x8000001f, +]; + +// Swap bits across the left and right words +function exchangeLR(offset, mask) { + const t = ((this._lBlock >>> offset) ^ this._rBlock) & mask; + this._rBlock ^= t; + this._lBlock ^= t << offset; +} + +function exchangeRL(offset, mask) { + const t = ((this._rBlock >>> offset) ^ this._lBlock) & mask; + this._lBlock ^= t; + this._rBlock ^= t << offset; +} + +/** + * DES block cipher algorithm. + */ +class DESAlgo extends BlockCipher { + constructor(xformMode, key, cfg) { + super(xformMode, key, cfg); + + // blickSize is an instance field and should set in constructor. + // Both DESAlgo and TripleDESAlgo. + this.blockSize = 64 / 32; + } + + _doReset() { + // Shortcuts + const key = this._key; + const keyWords = key.words; + + // Select 56 bits according to PC1 + const keyBits = []; + for (let i = 0; i < 56; i += 1) { + const keyBitPos = PC1[i] - 1; + keyBits[i] = (keyWords[keyBitPos >>> 5] >>> (31 - (keyBitPos % 32))) & 1; + } + + // Assemble 16 subkeys + this._subKeys = []; + const subKeys = this._subKeys; + for (let nSubKey = 0; nSubKey < 16; nSubKey += 1) { + // Create subkey + subKeys[nSubKey] = []; + const subKey = subKeys[nSubKey]; + + // Shortcut + const bitShift = BIT_SHIFTS[nSubKey]; + + // Select 48 bits according to PC2 + for (let i = 0; i < 24; i += 1) { + // Select from the left 28 key bits + subKey[(i / 6) | 0] |= keyBits[((PC2[i] - 1) + bitShift) % 28] << (31 - (i % 6)); + + // Select from the right 28 key bits + subKey[4 + ((i / 6) | 0)] + |= keyBits[28 + (((PC2[i + 24] - 1) + bitShift) % 28)] + << (31 - (i % 6)); + } + + // Since each subkey is applied to an expanded 32-bit input, + // the subkey can be broken into 8 values scaled to 32-bits, + // which allows the key to be used without expansion + subKey[0] = (subKey[0] << 1) | (subKey[0] >>> 31); + for (let i = 1; i < 7; i += 1) { + subKey[i] >>>= ((i - 1) * 4 + 3); + } + subKey[7] = (subKey[7] << 5) | (subKey[7] >>> 27); + } + + // Compute inverse subkeys + this._invSubKeys = []; + const invSubKeys = this._invSubKeys; + for (let i = 0; i < 16; i += 1) { + invSubKeys[i] = subKeys[15 - i]; + } + } + + encryptBlock(M, offset) { + this._doCryptBlock(M, offset, this._subKeys); + } + + decryptBlock(M, offset) { + this._doCryptBlock(M, offset, this._invSubKeys); + } + + _doCryptBlock(M, offset, subKeys) { + const _M = M; + + // Get input + this._lBlock = M[offset]; + this._rBlock = M[offset + 1]; + + // Initial permutation + exchangeLR.call(this, 4, 0x0f0f0f0f); + exchangeLR.call(this, 16, 0x0000ffff); + exchangeRL.call(this, 2, 0x33333333); + exchangeRL.call(this, 8, 0x00ff00ff); + exchangeLR.call(this, 1, 0x55555555); + + // Rounds + for (let round = 0; round < 16; round += 1) { + // Shortcuts + const subKey = subKeys[round]; + const lBlock = this._lBlock; + const rBlock = this._rBlock; + + // Feistel function + let f = 0; + for (let i = 0; i < 8; i += 1) { + f |= SBOX_P[i][((rBlock ^ subKey[i]) & SBOX_MASK[i]) >>> 0]; + } + this._lBlock = rBlock; + this._rBlock = lBlock ^ f; + } + + // Undo swap from last round + const t = this._lBlock; + this._lBlock = this._rBlock; + this._rBlock = t; + + // Final permutation + exchangeLR.call(this, 1, 0x55555555); + exchangeRL.call(this, 8, 0x00ff00ff); + exchangeRL.call(this, 2, 0x33333333); + exchangeLR.call(this, 16, 0x0000ffff); + exchangeLR.call(this, 4, 0x0f0f0f0f); + + // Set output + _M[offset] = this._lBlock; + _M[offset + 1] = this._rBlock; + } +} +DESAlgo.keySize = 64 / 32; +DESAlgo.ivSize = 64 / 32; +// blickSize is an instance field and should set in constructor. + +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.DES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.DES.decrypt(ciphertext, key, cfg); + */ +const DES = BlockCipher._createHelper(DESAlgo); + +/** + * Triple-DES block cipher algorithm. + */ +class TripleDESAlgo extends BlockCipher { + _doReset() { + // Shortcuts + const key = this._key; + const keyWords = key.words; + // Make sure the key length is valid (64, 128 or >= 192 bit) + if (keyWords.length !== 2 && keyWords.length !== 4 && keyWords.length < 6) { + throw new Error('Invalid key length - 3DES requires the key length to be 64, 128, 192 or >192.'); + } + + // Extend the key according to the keying options defined in 3DES standard + const key1 = keyWords.slice(0, 2); + const key2 = keyWords.length < 4 ? keyWords.slice(0, 2) : keyWords.slice(2, 4); + const key3 = keyWords.length < 6 ? keyWords.slice(0, 2) : keyWords.slice(4, 6); + + // Create DES instances + this._des1 = DESAlgo.createEncryptor(WordArray.create(key1)); + this._des2 = DESAlgo.createEncryptor(WordArray.create(key2)); + this._des3 = DESAlgo.createEncryptor(WordArray.create(key3)); + } + + encryptBlock(M, offset) { + this._des1.encryptBlock(M, offset); + this._des2.decryptBlock(M, offset); + this._des3.encryptBlock(M, offset); + } + + decryptBlock(M, offset) { + this._des3.decryptBlock(M, offset); + this._des2.encryptBlock(M, offset); + this._des1.decryptBlock(M, offset); + } +} +TripleDESAlgo.keySize = 192 / 32; +TripleDESAlgo.ivSize = 64 / 32; +// blickSize is an instance field and should set in constructor. + +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.TripleDES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.TripleDES.decrypt(ciphertext, key, cfg); + */ +const TripleDES = BlockCipher._createHelper(TripleDESAlgo); + +// Reusable objects +const S$1 = []; +const C_$1 = []; +const G$1 = []; + +function nextState$1() { + // Shortcuts + const X = this._X; + const C = this._C; + + // Save old counter values + for (let i = 0; i < 8; i += 1) { + C_$1[i] = C[i]; + } + + // Calculate new counter values + C[0] = (C[0] + 0x4d34d34d + this._b) | 0; + C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_$1[0] >>> 0) ? 1 : 0)) | 0; + C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_$1[1] >>> 0) ? 1 : 0)) | 0; + C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_$1[2] >>> 0) ? 1 : 0)) | 0; + C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_$1[3] >>> 0) ? 1 : 0)) | 0; + C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_$1[4] >>> 0) ? 1 : 0)) | 0; + C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_$1[5] >>> 0) ? 1 : 0)) | 0; + C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_$1[6] >>> 0) ? 1 : 0)) | 0; + this._b = (C[7] >>> 0) < (C_$1[7] >>> 0) ? 1 : 0; + + // Calculate the g-values + for (let i = 0; i < 8; i += 1) { + const gx = X[i] + C[i]; + + // Construct high and low argument for squaring + const ga = gx & 0xffff; + const gb = gx >>> 16; + + // Calculate high and low result of squaring + const gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb; + const gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0); + + // High XOR low + G$1[i] = gh ^ gl; + } + + // Calculate new state values + X[0] = (G$1[0] + ((G$1[7] << 16) | (G$1[7] >>> 16)) + ((G$1[6] << 16) | (G$1[6] >>> 16))) | 0; + X[1] = (G$1[1] + ((G$1[0] << 8) | (G$1[0] >>> 24)) + G$1[7]) | 0; + X[2] = (G$1[2] + ((G$1[1] << 16) | (G$1[1] >>> 16)) + ((G$1[0] << 16) | (G$1[0] >>> 16))) | 0; + X[3] = (G$1[3] + ((G$1[2] << 8) | (G$1[2] >>> 24)) + G$1[1]) | 0; + X[4] = (G$1[4] + ((G$1[3] << 16) | (G$1[3] >>> 16)) + ((G$1[2] << 16) | (G$1[2] >>> 16))) | 0; + X[5] = (G$1[5] + ((G$1[4] << 8) | (G$1[4] >>> 24)) + G$1[3]) | 0; + X[6] = (G$1[6] + ((G$1[5] << 16) | (G$1[5] >>> 16)) + ((G$1[4] << 16) | (G$1[4] >>> 16))) | 0; + X[7] = (G$1[7] + ((G$1[6] << 8) | (G$1[6] >>> 24)) + G$1[5]) | 0; +} + +/** + * Rabbit stream cipher algorithm + */ +class RabbitAlgo extends StreamCipher { + constructor(...args) { + super(...args); + + this.blockSize = 128 / 32; + this.ivSize = 64 / 32; + } + + _doReset() { + // Shortcuts + const K = this._key.words; + const { iv } = this.cfg; + + // Swap endian + for (let i = 0; i < 4; i += 1) { + K[i] = (((K[i] << 8) | (K[i] >>> 24)) & 0x00ff00ff) + | (((K[i] << 24) | (K[i] >>> 8)) & 0xff00ff00); + } + + // Generate initial state values + this._X = [ + K[0], (K[3] << 16) | (K[2] >>> 16), + K[1], (K[0] << 16) | (K[3] >>> 16), + K[2], (K[1] << 16) | (K[0] >>> 16), + K[3], (K[2] << 16) | (K[1] >>> 16), + ]; + const X = this._X; + + // Generate initial counter values + this._C = [ + (K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff), + (K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff), + (K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff), + (K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff), + ]; + const C = this._C; + + // Carry bit + this._b = 0; + + // Iterate the system four times + for (let i = 0; i < 4; i += 1) { + nextState$1.call(this); + } + + // Modify the counters + for (let i = 0; i < 8; i += 1) { + C[i] ^= X[(i + 4) & 7]; + } + + // IV setup + if (iv) { + // Shortcuts + const IV = iv.words; + const IV_0 = IV[0]; + const IV_1 = IV[1]; + + // Generate four subvectors + const i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff) + | (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00); + const i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff) + | (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00); + const i1 = (i0 >>> 16) | (i2 & 0xffff0000); + const i3 = (i2 << 16) | (i0 & 0x0000ffff); + + // Modify counter values + C[0] ^= i0; + C[1] ^= i1; + C[2] ^= i2; + C[3] ^= i3; + C[4] ^= i0; + C[5] ^= i1; + C[6] ^= i2; + C[7] ^= i3; + + // Iterate the system four times + for (let i = 0; i < 4; i += 1) { + nextState$1.call(this); + } + } + } + + _doProcessBlock(M, offset) { + const _M = M; + + // Shortcut + const X = this._X; + + // Iterate the system + nextState$1.call(this); + + // Generate four keystream words + S$1[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16); + S$1[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16); + S$1[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16); + S$1[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16); + + for (let i = 0; i < 4; i += 1) { + // Swap endian + S$1[i] = (((S$1[i] << 8) | (S$1[i] >>> 24)) & 0x00ff00ff) + | (((S$1[i] << 24) | (S$1[i] >>> 8)) & 0xff00ff00); + + // Encrypt + _M[offset + i] ^= S$1[i]; + } + } +} + +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.Rabbit.encrypt(message, key, cfg); + * var plaintext = CryptoJS.Rabbit.decrypt(ciphertext, key, cfg); + */ +const Rabbit = StreamCipher._createHelper(RabbitAlgo); + +// Reusable objects +const S = []; +const C_ = []; +const G = []; + +function nextState() { + // Shortcuts + const X = this._X; + const C = this._C; + + // Save old counter values + for (let i = 0; i < 8; i += 1) { + C_[i] = C[i]; + } + + // Calculate new counter values + C[0] = (C[0] + 0x4d34d34d + this._b) | 0; + C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0; + C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0; + C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0; + C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0; + C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0; + C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0; + C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0; + this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0; + + // Calculate the g-values + for (let i = 0; i < 8; i += 1) { + const gx = X[i] + C[i]; + + // Construct high and low argument for squaring + const ga = gx & 0xffff; + const gb = gx >>> 16; + + // Calculate high and low result of squaring + const gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb; + const gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0); + + // High XOR low + G[i] = gh ^ gl; + } + + // Calculate new state values + X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0; + X[1] = (G[1] + ((G[0] << 8) | (G[0] >>> 24)) + G[7]) | 0; + X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0; + X[3] = (G[3] + ((G[2] << 8) | (G[2] >>> 24)) + G[1]) | 0; + X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0; + X[5] = (G[5] + ((G[4] << 8) | (G[4] >>> 24)) + G[3]) | 0; + X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0; + X[7] = (G[7] + ((G[6] << 8) | (G[6] >>> 24)) + G[5]) | 0; +} + +/** + * Rabbit stream cipher algorithm. + * + * This is a legacy version that neglected to convert the key to little-endian. + * This error doesn't affect the cipher's security, + * but it does affect its compatibility with other implementations. + */ +class RabbitLegacyAlgo extends StreamCipher { + constructor(...args) { + super(...args); + + this.blockSize = 128 / 32; + this.ivSize = 64 / 32; + } + + _doReset() { + // Shortcuts + const K = this._key.words; + const { iv } = this.cfg; + + // Generate initial state values + this._X = [ + K[0], (K[3] << 16) | (K[2] >>> 16), + K[1], (K[0] << 16) | (K[3] >>> 16), + K[2], (K[1] << 16) | (K[0] >>> 16), + K[3], (K[2] << 16) | (K[1] >>> 16), + ]; + const X = this._X; + + // Generate initial counter values + this._C = [ + (K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff), + (K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff), + (K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff), + (K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff), + ]; + const C = this._C; + + // Carry bit + this._b = 0; + + // Iterate the system four times + for (let i = 0; i < 4; i += 1) { + nextState.call(this); + } + + // Modify the counters + for (let i = 0; i < 8; i += 1) { + C[i] ^= X[(i + 4) & 7]; + } + + // IV setup + if (iv) { + // Shortcuts + const IV = iv.words; + const IV_0 = IV[0]; + const IV_1 = IV[1]; + + // Generate four subvectors + const i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff) + | (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00); + const i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff) + | (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00); + const i1 = (i0 >>> 16) | (i2 & 0xffff0000); + const i3 = (i2 << 16) | (i0 & 0x0000ffff); + + // Modify counter values + C[0] ^= i0; + C[1] ^= i1; + C[2] ^= i2; + C[3] ^= i3; + C[4] ^= i0; + C[5] ^= i1; + C[6] ^= i2; + C[7] ^= i3; + + // Iterate the system four times + for (let i = 0; i < 4; i += 1) { + nextState.call(this); + } + } + } + + _doProcessBlock(M, offset) { + const _M = M; + + // Shortcut + const X = this._X; + + // Iterate the system + nextState.call(this); + + // Generate four keystream words + S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16); + S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16); + S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16); + S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16); + + for (let i = 0; i < 4; i += 1) { + // Swap endian + S[i] = (((S[i] << 8) | (S[i] >>> 24)) & 0x00ff00ff) + | (((S[i] << 24) | (S[i] >>> 8)) & 0xff00ff00); + + // Encrypt + _M[offset + i] ^= S[i]; + } + } +} + +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RabbitLegacy.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RabbitLegacy.decrypt(ciphertext, key, cfg); + */ +const RabbitLegacy = StreamCipher._createHelper(RabbitLegacyAlgo); + +function generateKeystreamWord() { + // Shortcuts + const S = this._S; + let i = this._i; + let j = this._j; + + // Generate keystream word + let keystreamWord = 0; + for (let n = 0; n < 4; n += 1) { + i = (i + 1) % 256; + j = (j + S[i]) % 256; + + // Swap + const t = S[i]; + S[i] = S[j]; + S[j] = t; + + keystreamWord |= S[(S[i] + S[j]) % 256] << (24 - n * 8); + } + + // Update counters + this._i = i; + this._j = j; + + return keystreamWord; +} + +/** + * RC4 stream cipher algorithm. + */ +class RC4Algo extends StreamCipher { + _doReset() { + // Shortcuts + const key = this._key; + const keyWords = key.words; + const keySigBytes = key.sigBytes; + + // Init sbox + this._S = []; + const S = this._S; + for (let i = 0; i < 256; i += 1) { + S[i] = i; + } + + // Key setup + for (let i = 0, j = 0; i < 256; i += 1) { + const keyByteIndex = i % keySigBytes; + const keyByte = (keyWords[keyByteIndex >>> 2] >>> (24 - (keyByteIndex % 4) * 8)) & 0xff; + + j = (j + S[i] + keyByte) % 256; + + // Swap + const t = S[i]; + S[i] = S[j]; + S[j] = t; + } + + // Counters + this._j = 0; + this._i = this._j; + } + + _doProcessBlock(M, offset) { + const _M = M; + + _M[offset] ^= generateKeystreamWord.call(this); + } +} +RC4Algo.keySize = 256 / 32; +RC4Algo.ivSize = 0; + +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RC4.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RC4.decrypt(ciphertext, key, cfg); + */ +const RC4 = StreamCipher._createHelper(RC4Algo); + +/** + * Modified RC4 stream cipher algorithm. + */ +class RC4DropAlgo extends RC4Algo { + constructor(...args) { + super(...args); + + /** + * Configuration options. + * + * @property {number} drop The number of keystream words to drop. Default 192 + */ + Object.assign(this.cfg, { drop: 192 }); + } + + _doReset() { + super._doReset.call(this); + + // Drop + for (let i = this.cfg.drop; i > 0; i -= 1) { + generateKeystreamWord.call(this); + } + } +} + +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RC4Drop.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RC4Drop.decrypt(ciphertext, key, cfg); + */ +const RC4Drop = StreamCipher._createHelper(RC4DropAlgo); + +const N = 16; + +//Origin pbox and sbox, derived from PI +const ORIG_P = [ + 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, + 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89, + 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, + 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917, + 0x9216D5D9, 0x8979FB1B, +]; + +const ORIG_S = [ + [0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, + 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99, + 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16, + 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E, + 0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE, + 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013, + 0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF, + 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E, + 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60, + 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440, + 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE, + 0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A, + 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E, + 0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677, + 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193, + 0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032, + 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88, + 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239, + 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, + 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0, + 0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3, + 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98, + 0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88, + 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE, + 0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6, + 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D, + 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B, + 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7, + 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA, + 0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463, + 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F, + 0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09, + 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3, + 0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB, + 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279, + 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8, + 0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB, + 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82, + 0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB, + 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573, + 0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0, + 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B, + 0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790, + 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8, + 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4, + 0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0, + 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7, + 0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C, + 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD, + 0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1, + 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299, + 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9, + 0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477, + 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF, + 0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49, + 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF, + 0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA, + 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5, + 0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41, + 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915, + 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400, + 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915, + 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664, + 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A,], + [0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, + 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266, + 0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1, + 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E, + 0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6, + 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1, + 0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E, + 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1, + 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737, + 0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8, + 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF, + 0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD, + 0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701, + 0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7, + 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41, + 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331, + 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF, + 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF, + 0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E, + 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87, + 0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C, + 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2, + 0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16, + 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD, + 0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B, + 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509, + 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E, + 0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3, + 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F, + 0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A, + 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4, + 0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960, + 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66, + 0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28, + 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802, + 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84, + 0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510, + 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF, + 0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14, + 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E, + 0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50, + 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7, + 0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8, + 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281, + 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99, + 0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696, + 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128, + 0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73, + 0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0, + 0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0, + 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105, + 0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250, + 0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3, + 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285, + 0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00, + 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061, + 0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB, + 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E, + 0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735, + 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC, + 0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9, + 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340, + 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20, + 0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7,], + [0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934, + 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068, + 0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF, + 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840, + 0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45, + 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504, + 0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A, + 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB, + 0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE, + 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6, + 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42, + 0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B, + 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2, + 0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB, + 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527, + 0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B, + 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33, + 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C, + 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3, + 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC, + 0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17, + 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564, + 0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B, + 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115, + 0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922, + 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728, + 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0, + 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E, + 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37, + 0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D, + 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804, + 0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B, + 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3, + 0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB, + 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D, + 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C, + 0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350, + 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9, + 0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A, + 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE, + 0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D, + 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC, + 0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F, + 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61, + 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2, + 0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9, + 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2, + 0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C, + 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E, + 0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633, + 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10, + 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169, + 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52, + 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027, + 0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5, + 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62, + 0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634, + 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76, + 0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24, + 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC, + 0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4, + 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C, + 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837, + 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0,], + [0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B, + 0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE, + 0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B, + 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4, + 0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8, + 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6, + 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304, + 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22, + 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4, + 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6, + 0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9, + 0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59, + 0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593, + 0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51, + 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28, + 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C, + 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B, + 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28, + 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C, + 0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD, + 0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A, + 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319, + 0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB, + 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F, + 0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991, + 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32, + 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680, + 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166, + 0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE, + 0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB, + 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5, + 0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47, + 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370, + 0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D, + 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84, + 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048, + 0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8, + 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD, + 0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9, + 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7, + 0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38, + 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F, + 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C, + 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525, + 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1, + 0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442, + 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964, + 0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E, + 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8, + 0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D, + 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F, + 0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299, + 0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02, + 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC, + 0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614, + 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A, + 0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6, + 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B, + 0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0, + 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060, + 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E, + 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9, + 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F, + 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6,], +]; + +const blowfishCtx = { + pbox: [], + sbox: [], +}; + +function f(ctx, x) { + const a = (x >> 24) & 0xFF; + const b = (x >> 16) & 0xFF; + const c = (x >> 8) & 0xFF; + const d = x & 0xFF; + + let y = ctx.sbox[0][a] + ctx.sbox[1][b]; + y = y ^ ctx.sbox[2][c]; + y = y + ctx.sbox[3][d]; + + return y; +} + +function blowfishEncrypt(ctx, left, right) { + let Xl = left; + let Xr = right; + let temp; + + for(let i = 0; i < N; ++i){ + Xl = Xl ^ ctx.pbox[i]; + Xr = f(ctx, Xl) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx.pbox[N]; + Xl = Xl ^ ctx.pbox[N + 1]; + + return {left: Xl, right: Xr}; +} + +function blowfishDecrypt(ctx, left, right) { + let Xl = left; + let Xr = right; + let temp; + + for(let i = N + 1; i > 1; --i){ + Xl = Xl ^ ctx.pbox[i]; + Xr = f(ctx, Xl) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx.pbox[1]; + Xl = Xl ^ ctx.pbox[0]; + + return {left: Xl, right: Xr}; +} + +/** +* Initialization ctx's pbox and sbox. +* +* @param {Object} ctx The object has pbox and sbox. +* @param {Array} key An array of 32-bit words. +* @param {int} keysize The length of the key. +* +* @example +* +* blowfishInit(BLOWFISH_CTX, key, 128/32); +*/ +function blowfishInit(ctx, key, keysize) { + for (let Row = 0; Row < 4; Row++) { + ctx.sbox[Row] = []; + for (let Col = 0; Col < 256; Col++) { + ctx.sbox[Row][Col] = ORIG_S[Row][Col]; + } + } + + let keyIndex = 0; + for (let index = 0; index < N + 2; index++) { + ctx.pbox[index] = ORIG_P[index] ^ key[keyIndex]; + keyIndex++; + if (keyIndex >= keysize) { + keyIndex = 0; + } + } + + let data1 = 0; + let data2 = 0; + let res = 0; + for (let i = 0; i < N + 2; i += 2) { + res = blowfishEncrypt(ctx, data1, data2); + data1 = res.left; + data2 = res.right; + ctx.pbox[i] = data1; + ctx.pbox[i + 1] = data2; + } + + for (let i = 0; i < 4; i++) { + for (let j = 0; j < 256; j += 2) { + res = blowfishEncrypt(ctx, data1, data2); + data1 = res.left; + data2 = res.right; + ctx.sbox[i][j] = data1; + ctx.sbox[i][j + 1] = data2; + } + } + + return true; +} + +/** + * Blowfish block cipher algorithm. + */ +class BlowfishAlgo extends BlockCipher { + constructor(xformMode, key, cfg) { + super(xformMode, key, cfg); + + // blickSize is an instance field and should set in constructor. + this.blockSize = 64 / 32; + } + + _doReset() { + // Skip reset of nRounds has been set before and key did not change + if (this._keyPriorReset === this._key) { + return; + } + + // Shortcuts + const key = this._keyPriorReset = this._key; + const keyWords = key.words; + const keySize = key.sigBytes / 4; + + //Initialization pbox and sbox + blowfishInit(blowfishCtx, keyWords, keySize); + } + + encryptBlock(M, offset) { + const res = blowfishEncrypt(blowfishCtx, M[offset], M[offset + 1]); + M[offset] = res.left; + M[offset + 1] = res.right; + } + + decryptBlock(M, offset) { + const res = blowfishDecrypt(blowfishCtx, M[offset], M[offset + 1]); + M[offset] = res.left; + M[offset + 1] = res.right; + } +} +BlowfishAlgo.keySize = 128 / 32; +BlowfishAlgo.ivSize = 64 / 32; +// blickSize is an instance field and should set in constructor. + +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.Blowfish.encrypt(message, key, cfg); + * var plaintext = CryptoJS.Blowfish.decrypt(ciphertext, key, cfg); + */ +const Blowfish = BlockCipher._createHelper(BlowfishAlgo); + +function generateKeystreamAndEncrypt(words, offset, blockSize, cipher) { + const _words = words; + let keystream; + + // Shortcut + const iv = this._iv; + + // Generate keystream + if (iv) { + keystream = iv.slice(0); + + // Remove IV for subsequent blocks + this._iv = undefined; + } else { + keystream = this._prevBlock; + } + cipher.encryptBlock(keystream, 0); + + // Encrypt + for (let i = 0; i < blockSize; i += 1) { + _words[offset + i] ^= keystream[i]; + } +} + +/** + * Cipher Feedback block mode. + */ +class CFB extends BlockCipherMode { +} +CFB.Encryptor = class extends CFB { + processBlock(words, offset) { + // Shortcuts + const cipher = this._cipher; + const { blockSize } = cipher; + + generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher); + + // Remember this block to use with next block + this._prevBlock = words.slice(offset, offset + blockSize); + } +}; +CFB.Decryptor = class extends CFB { + processBlock(words, offset) { + // Shortcuts + const cipher = this._cipher; + const { blockSize } = cipher; + + // Remember this block to use with next block + const thisBlock = words.slice(offset, offset + blockSize); + + generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher); + + // This block becomes the previous block + this._prevBlock = thisBlock; + } +}; + +/** + * Counter block mode. + */ +class CTR extends BlockCipherMode { +} +CTR.Encryptor = class extends CTR { + processBlock(words, offset) { + const _words = words; + + // Shortcuts + const cipher = this._cipher; + const { blockSize } = cipher; + const iv = this._iv; + let counter = this._counter; + + // Generate keystream + if (iv) { + this._counter = iv.slice(0); + counter = this._counter; + + // Remove IV for subsequent blocks + this._iv = undefined; + } + const keystream = counter.slice(0); + cipher.encryptBlock(keystream, 0); + + // Increment counter + counter[blockSize - 1] = (counter[blockSize - 1] + 1) | 0; + + // Encrypt + for (let i = 0; i < blockSize; i += 1) { + _words[offset + i] ^= keystream[i]; + } + } +}; +CTR.Decryptor = CTR.Encryptor; + +const incWord = (word) => { + let _word = word; + + if (((word >> 24) & 0xff) === 0xff) { // overflow + let b1 = (word >> 16) & 0xff; + let b2 = (word >> 8) & 0xff; + let b3 = word & 0xff; + + if (b1 === 0xff) { // overflow b1 + b1 = 0; + if (b2 === 0xff) { + b2 = 0; + if (b3 === 0xff) { + b3 = 0; + } else { + b3 += 1; + } + } else { + b2 += 1; + } + } else { + b1 += 1; + } + + _word = 0; + _word += (b1 << 16); + _word += (b2 << 8); + _word += b3; + } else { + _word += (0x01 << 24); + } + return _word; +}; + +const incCounter = (counter) => { + const _counter = counter; + _counter[0] = incWord(_counter[0]); + + if (_counter[0] === 0) { + // encr_data in fileenc.c from Dr Brian Gladman's counts only with DWORD j < 8 + _counter[1] = incWord(_counter[1]); + } + return _counter; +}; + +/** @preserve + * Counter block mode compatible with Dr Brian Gladman fileenc.c + * derived from CryptoJS.mode.CTR + * Jan Hruby jhruby.web@gmail.com + */ +class CTRGladman extends BlockCipherMode { +} +CTRGladman.Encryptor = class extends CTRGladman { + processBlock(words, offset) { + const _words = words; + + // Shortcuts + const cipher = this._cipher; + const { blockSize } = cipher; + const iv = this._iv; + let counter = this._counter; + + // Generate keystream + if (iv) { + this._counter = iv.slice(0); + counter = this._counter; + + // Remove IV for subsequent blocks + this._iv = undefined; + } + + incCounter(counter); + + const keystream = counter.slice(0); + cipher.encryptBlock(keystream, 0); + + // Encrypt + for (let i = 0; i < blockSize; i += 1) { + _words[offset + i] ^= keystream[i]; + } + } +}; +CTRGladman.Decryptor = CTRGladman.Encryptor; + +/** + * Electronic Codebook block mode. + */ +class ECB extends BlockCipherMode { +} +ECB.Encryptor = class extends ECB { + processBlock(words, offset) { + this._cipher.encryptBlock(words, offset); + } +}; +ECB.Decryptor = class extends ECB { + processBlock(words, offset) { + this._cipher.decryptBlock(words, offset); + } +}; + +/** + * Output Feedback block mode. + */ +class OFB extends BlockCipherMode { +} +OFB.Encryptor = class extends OFB { + processBlock(words, offset) { + const _words = words; + + // Shortcuts + const cipher = this._cipher; + const { blockSize } = cipher; + const iv = this._iv; + let keystream = this._keystream; + + // Generate keystream + if (iv) { + this._keystream = iv.slice(0); + keystream = this._keystream; + + // Remove IV for subsequent blocks + this._iv = undefined; + } + cipher.encryptBlock(keystream, 0); + + // Encrypt + for (let i = 0; i < blockSize; i += 1) { + _words[offset + i] ^= keystream[i]; + } + } +}; +OFB.Decryptor = OFB.Encryptor; + +/** + * ANSI X.923 padding strategy. + */ +const AnsiX923 = { + pad(data, blockSize) { + const _data = data; + + // Shortcuts + const dataSigBytes = _data.sigBytes; + const blockSizeBytes = blockSize * 4; + + // Count padding bytes + const nPaddingBytes = blockSizeBytes - (dataSigBytes % blockSizeBytes); + + // Compute last byte position + const lastBytePos = dataSigBytes + nPaddingBytes - 1; + + // Pad + _data.clamp(); + _data.words[lastBytePos >>> 2] |= nPaddingBytes << (24 - (lastBytePos % 4) * 8); + _data.sigBytes += nPaddingBytes; + }, + + unpad(data) { + const _data = data; + + // Get number of padding bytes from last byte + const nPaddingBytes = _data.words[(_data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + _data.sigBytes -= nPaddingBytes; + }, +}; + +/** + * ISO 10126 padding strategy. + */ +const Iso10126 = { + pad(data, blockSize) { + // Shortcut + const blockSizeBytes = blockSize * 4; + + // Count padding bytes + const nPaddingBytes = blockSizeBytes - (data.sigBytes % blockSizeBytes); + + // Pad + data + .concat(WordArray.random(nPaddingBytes - 1)) + .concat(WordArray.create([nPaddingBytes << 24], 1)); + }, + + unpad(data) { + const _data = data; + // Get number of padding bytes from last byte + const nPaddingBytes = _data.words[(_data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + _data.sigBytes -= nPaddingBytes; + }, +}; + +/** + * Zero padding strategy. + */ +const ZeroPadding = { + pad(data, blockSize) { + const _data = data; + + // Shortcut + const blockSizeBytes = blockSize * 4; + + // Pad + _data.clamp(); + _data.sigBytes += blockSizeBytes - ((data.sigBytes % blockSizeBytes) || blockSizeBytes); + }, + + unpad(data) { + const _data = data; + + // Shortcut + const dataWords = _data.words; + + // Unpad + for (let i = _data.sigBytes - 1; i >= 0; i -= 1) { + if (((dataWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff)) { + _data.sigBytes = i + 1; + break; + } + } + }, +}; + +/** + * ISO/IEC 9797-1 Padding Method 2. + */ +const Iso97971 = { + pad(data, blockSize) { + // Add 0x80 byte + data.concat(WordArray.create([0x80000000], 1)); + + // Zero pad the rest + ZeroPadding.pad(data, blockSize); + }, + + unpad(data) { + const _data = data; + + // Remove zero padding + ZeroPadding.unpad(_data); + + // Remove one more byte -- the 0x80 byte + _data.sigBytes -= 1; + }, +}; + +/** + * A noop padding strategy. + */ +const NoPadding = { + pad() { + }, + + unpad() { + }, +}; + +const HexFormatter = { + /** + * Converts the ciphertext of a cipher params object to a hexadecimally encoded string. + * + * @param {CipherParams} cipherParams The cipher params object. + * + * @return {string} The hexadecimally encoded string. + * + * @static + * + * @example + * + * var hexString = CryptoJS.format.Hex.stringify(cipherParams); + */ + stringify(cipherParams) { + return cipherParams.ciphertext.toString(Hex); + }, + + /** + * Converts a hexadecimally encoded ciphertext string to a cipher params object. + * + * @param {string} input The hexadecimally encoded string. + * + * @return {CipherParams} The cipher params object. + * + * @static + * + * @example + * + * var cipherParams = CryptoJS.format.Hex.parse(hexString); + */ + parse(input) { + const ciphertext = Hex.parse(input); + return CipherParams.create({ ciphertext }); + }, +}; + +var CryptoES = { + lib: { + Base, + WordArray, + BufferedBlockAlgorithm, + Hasher, + Cipher, + StreamCipher, + BlockCipherMode, + BlockCipher, + CipherParams, + SerializableCipher, + PasswordBasedCipher, + }, + + x64: { + Word: X64Word, + WordArray: X64WordArray, + }, + + enc: { + Hex, + Latin1, + Utf8, + Utf16, + Utf16BE, + Utf16LE, + Base64, + Base64url, + }, + + algo: { + HMAC, + MD5: MD5Algo, + SHA1: SHA1Algo, + SHA224: SHA224Algo, + SHA256: SHA256Algo, + SHA384: SHA384Algo, + SHA512: SHA512Algo, + SHA3: SHA3Algo, + RIPEMD160: RIPEMD160Algo, + + PBKDF2: PBKDF2Algo, + EvpKDF: EvpKDFAlgo, + + AES: AESAlgo, + DES: DESAlgo, + TripleDES: TripleDESAlgo, + Rabbit: RabbitAlgo, + RabbitLegacy: RabbitLegacyAlgo, + RC4: RC4Algo, + RC4Drop: RC4DropAlgo, + Blowfish: BlowfishAlgo, + }, + + mode: { + CBC, + CFB, + CTR, + CTRGladman, + ECB, + OFB, + }, + + pad: { + Pkcs7, + AnsiX923, + Iso10126, + Iso97971, + NoPadding, + ZeroPadding, + }, + + format: { + OpenSSL: OpenSSLFormatter, + Hex: HexFormatter, + }, + + kdf: { + OpenSSL: OpenSSLKdf, + }, + + MD5, + HmacMD5, + SHA1, + HmacSHA1, + SHA224, + HmacSHA224, + SHA256, + HmacSHA256, + SHA384, + HmacSHA384, + SHA512, + HmacSHA512, + SHA3, + HmacSHA3, + RIPEMD160, + HmacRIPEMD160, + + PBKDF2, + EvpKDF, + + AES, + DES, + TripleDES, + Rabbit, + RabbitLegacy, + RC4, + RC4Drop, + Blowfish, +}; + +/** + * ts-pdf (a PDF.js-based PDF viewer written in TypeScript) + * Copyright (C) 2021-present Volodymyr Yermolenko (yermolim@gmail.com), Chemproject PJSC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial activities involving this program without + * disclosing the source code of your own applications. + * + * -//-//-//-//-//-//-//-//-//-//-//-//-//-//- + * + * FlateStream class is based on the corresponding one from PDF.js, + * so the code of that class is also subject to the next license notice: + * + * Copyright 2012 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright 1996-2003 Glyph & Cog, LLC + * + * The flate stream implementation contained in this file is a JavaScript port + * of XPDF's implementation, made available under the Apache 2.0 open source + * license. + * + * -//-//-//-//-//-//-//-//-//-//-//-//-//-//- + */ + + +const mainHtml = ` +
+
+
+
+
+
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+ +
+ +  /  + 0 +
+
+
+
+ +
+
+ +
+
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ +
+

+

+

+
+ + + +
+`; +const passwordDialogHtml = ` +
+
+ +
+
+ +
+
+ +
+
+
+
+`; + +const appName = "tspdf"; +const styles = ` + +`; + +function getNextNode(node) { + if (node.hasChildNodes()) { + return node.firstChild; + } + else { + while (node && !node.nextSibling) { + node = node.parentNode; + } + if (!node) { + return null; + } + return node.nextSibling; + } +} +function getRangeNodes(range) { + let node = range.startContainer; + const endNode = range.endContainer; + if (node === endNode) { + return [node]; + } + const rangeNodes = []; + while (node && node !== endNode) { + rangeNodes.push(node = getNextNode(node)); + } + node = range.startContainer; + while (node && node !== range.commonAncestorContainer) { + rangeNodes.unshift(node); + node = node.parentNode; + } + return rangeNodes; +} +function getSelectionInfosFromRangeSpans(range) { + var _a; + const textNodes = getRangeNodes(range).filter(x => (x === null || x === void 0 ? void 0 : x.nodeType) === 3); + const selectionInfos = []; + for (let i = 0; i < textNodes.length; i++) { + const node = textNodes[i]; + const textContent = node.textContent; + if (!textContent) { + continue; + } + const textLength = ((_a = node.textContent) === null || _a === void 0 ? void 0 : _a.length) || 0; + let startOffset = 0; + let endOffset = textLength; + if (i === 0) { + startOffset = range.startOffset; + } + if (i === textNodes.length - 1) { + endOffset = range.endOffset; + } + const text = textContent.slice(startOffset, endOffset); + if (!text) { + continue; + } + const parent = node.parentElement; + if (!parent || parent.tagName.toLowerCase() !== "span") { + continue; + } + const dummies = parent.querySelectorAll(".dummy-corner"); + if (dummies.length !== 4) { + continue; + } + const spanBlVec = new u(); + const spanBrVec = new u(); + const spanTrVec = new u(); + const spanTlVec = new u(); + dummies.forEach(dummy => { + const { x, y } = dummy.getBoundingClientRect(); + if (dummy.classList.contains("bl")) { + spanBlVec.set(x, y); + } + else if (dummy.classList.contains("br")) { + spanBrVec.set(x, y); + } + else if (dummy.classList.contains("tr")) { + spanTrVec.set(x, y); + } + else if (dummy.classList.contains("tl")) { + spanTlVec.set(x, y); + } + }); + const startOffsetRelative = startOffset / textLength; + const endOffsetRelative = endOffset / textLength; + const spanBottomVec = u.subtract(spanBrVec, spanBlVec); + const spanTopVec = u.subtract(spanTrVec, spanTlVec); + const selectionBlVec = u.add(spanBlVec, u.multiplyByScalar(spanBottomVec, startOffsetRelative)); + const selectionBrVec = u.add(spanBlVec, u.multiplyByScalar(spanBottomVec, endOffsetRelative)); + const selectionTrVec = u.add(spanTlVec, u.multiplyByScalar(spanTopVec, endOffsetRelative)); + const selectionTlVec = u.add(spanTlVec, u.multiplyByScalar(spanTopVec, startOffsetRelative)); + selectionInfos.push({ + text, + bottomLeft: selectionBlVec, + bottomRight: selectionBrVec, + topRight: selectionTrVec, + topLeft: selectionTlVec, + }); + } + return selectionInfos; +} +function getSelectionInfosFromSelection(selection) { + const selectionRange = selection.getRangeAt(0); + return getSelectionInfosFromRangeSpans(selectionRange); +} + +var __awaiter$1m = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class PageTextView { + constructor(pageProxy) { + this.onPointerDown = (e) => { + var _a; + if (this._divModeTimer) { + clearTimeout(this._divModeTimer); + this._divModeTimer = null; + } + (_a = this._renderTask) === null || _a === void 0 ? void 0 : _a.expandTextDivs(true); + }; + this.onPointerUp = (e) => { + this._divModeTimer = setTimeout(() => { + var _a; + (_a = this._renderTask) === null || _a === void 0 ? void 0 : _a.expandTextDivs(false); + this._divModeTimer = null; + }, 300); + }; + if (!pageProxy) { + throw new Error("Page proxy is not defined"); + } + this._pageProxy = pageProxy; + this._container = document.createElement("div"); + this._container.classList.add("page-text"); + this._container.addEventListener("pointerdown", this.onPointerDown); + this._container.addEventListener("pointerup", this.onPointerUp); + } + static appendPageTextAsync(pageProxy, parent, scale) { + return __awaiter$1m(this, void 0, void 0, function* () { + const textObj = new PageTextView(pageProxy); + try { + const result = yield textObj.renderTextLayerAsync(scale); + if (!result || textObj._destroyed) { + return null; + } + } + catch (e) { + console.error(e); + return null; + } + parent.append(textObj._container); + return textObj; + }); + } + destroy() { + this.remove(); + this._container = null; + this._destroyed = true; + } + remove() { + this.destroyRenderTask(); + if (this._container) { + this._container.remove(); + } + } + renderTextLayerAsync(scale) { + return __awaiter$1m(this, void 0, void 0, function* () { + this.destroyRenderTask(); + this.clear(); + const viewport = this._pageProxy.getViewport({ scale }); + const textContentStream = this._pageProxy.streamTextContent(); + this._renderTask = pdfExports.renderTextLayer({ + container: this._container, + textContentStream, + viewport, + enhanceTextSelection: false, + }); + try { + yield this._renderTask.promise; + } + catch (error) { + if (error.message === "TextLayer task cancelled.") { + return false; + } + else { + throw error; + } + } + const spans = this._container.querySelectorAll("span"); + spans.forEach(x => { + const blCornerSpan = document.createElement("span"); + blCornerSpan.classList.add("dummy-corner", "bl"); + const brCornerSpan = document.createElement("span"); + brCornerSpan.classList.add("dummy-corner", "br"); + const trCornerSpan = document.createElement("span"); + trCornerSpan.classList.add("dummy-corner", "tr"); + const tlCornerSpan = document.createElement("span"); + tlCornerSpan.classList.add("dummy-corner", "tl"); + x.append(blCornerSpan, brCornerSpan, trCornerSpan, tlCornerSpan); + }); + return true; + }); + } + clear() { + this._container.innerHTML = ""; + } + destroyRenderTask() { + if (this._renderTask) { + this._renderTask.cancel(); + this._renderTask = null; + } + } +} + +function applyFlipYToElement(element) { + setTransformationToElement(element, getVerticalMirrorCssTransformation()); +} +function applyMatrixToElement(element, matrix) { + const matrixString = `matrix(${matrix.toFloatShortArray().join(", ")})`; + setTransformationToElement(element, matrixString); +} +function applyTranslateRotateToElement(element, x, y, r) { + element.setAttribute("transform", `translate(${x} ${y}) rotate(${-r})`); +} +function setTransformationToElement(element, transformation) { + element.style["transform"] = transformation; + element.style["-webkit-transform"] = transformation; +} +function getVerticalMirrorCssTransformation() { + return "matrix(1, 0, 0, -1, 0, 0)"; +} + +const maxGeneration = 65535; +const objectTypes = { + UNKNOWN: 0, + NULL: 1, + BOOLEAN: 2, + NUMBER: 3, + STRING_LITERAL: 4, + STRING_HEX: 5, + NAME: 6, + ARRAY: 7, + DICTIONARY: 8, + STREAM: 9, +}; +const valueTypes = { + UNKNOWN: 0, + NULL: 1, + BOOLEAN: 2, + NUMBER: 3, + STRING_LITERAL: 4, + STRING_HEX: 5, + NAME: 6, + ARRAY: 7, + DICTIONARY: 8, + STREAM: 9, + REF: 10, + COMMENT: 11, +}; +const dictTypes = { + XREF: "/XRef", + XOBJECT: "/XObject", + CATALOG: "/Catalog", + PAGE_TREE: "/Pages", + PAGE: "/Page", + ANNOTATION: "/Annot", + BORDER_STYLE: "/Border", + OPTIONAL_CONTENT_GROUP: "/OCG", + OPTIONAL_CONTENT_MD: "/OCMD", + EXTERNAL_DATA: "/ExDATA", + ACTION: "/Action", + MEASURE: "/Measure", + DEV_EXTENSIONS: "/DeveloperExtensions", + GRAPHICS_STATE: "/ExtGState", + CRYPT_FILTER: "/CryptFilter", + SOFT_MASK: "/Mask", + GROUP: "/Group", + FONT: "/Font", + FONT_DESCRIPTOR: "/FontDescriptor", + ENCODING: "/Encoding", + EMPTY: "", +}; +const xRefTypes = { + TABLE: 0, + STREAM: 1, + HYBRID: 2, +}; +const xRefEntryTypes = { + FREE: 0, + NORMAL: 1, + COMPRESSED: 2, +}; +const streamFilters = { + ASCII85: "/ASCII85Decode", + ASCIIHEX: "/ASCIIHexDecode", + CCF: "/CCITTFaxDecode", + CRYPT: "/Crypt", + DCT: "/DCTDecode", + FLATE: "/FlateDecode", + JBIG2: "/JBIG2Decode", + JPX: "/JPXDecode", + LZW: "/LZWDecode", + RLX: "/RunLengthDecode", +}; +const flatePredictors = { + NONE: 1, + TIFF: 2, + PNG_NONE: 10, + PNG_SUB: 11, + PNG_UP: 12, + PNG_AVERAGE: 13, + PNG_PAETH: 14, + PNG_OPTIMUM: 15, +}; +const streamTypes = { + XREF: "/XRef", + OBJECT_STREAM: "/ObjStm", + FORM_XOBJECT: "/XObject", + METADATA_STREAM: "/Metadata", +}; +const supportedFilters = new Set([ + streamFilters.FLATE, + streamFilters.DCT, + streamFilters.JBIG2, + streamFilters.JPX, +]); +const cryptVersions = { + RC4_40: 1, + RC4_128: 2, + AES_128: 4, + AES_256: 5, +}; +const cryptRevisions = { + RC4_40: 2, + RC4_128: 3, + AES_128: 4, + AES_256: 5, + AES_256_V2: 6, +}; +const cryptMethods = { + NONE: "/None", + RC4: "/V2", + AES_128: "/AESV2", + AES_256: "/AESV3", +}; +const authEvents = { + DOC_OPEN: "/DocOpen", + EMBEDDED_OPEN: "/EFOpen", +}; +const annotationTypes = { + TEXT: "/Text", + LINK: "/Link", + FREE_TEXT: "/FreeText", + LINE: "/Line", + SQUARE: "/Square", + CIRCLE: "/Circle", + POLYGON: "/Polygon", + POLYLINE: "/PolyLine", + HIGHLIGHT: "/Highlight", + UNDERLINE: "/Underline", + SQUIGGLY: "/Squiggly", + STRIKEOUT: "/StrikeOut", + STAMP: "/Stamp", + CARET: "/Caret", + INK: "/Ink", + POPUP: "/Popup", + FILE_ATTACHMENT: "/FileAttachment", + SOUND: "/Sound", + MOVIE: "/Movie", + WIDGET: "/Widget", + SCREEN: "/Screen", + PRINTER_MARK: "/PrinterMark", + TRAPNET: "/TrapNet", + WATERMARK: "/Watermark", + THREED: "/3D", + REDACT: "/Redact", + PROJECTION: "/Projection", + RICH_MEDIA: "/RichMedia", +}; +const annotationStateModelTypes = { + MARKED: "/Marked", + REVIEW: "/Review", +}; +const annotationMarkedStates = { + MARKED: "/Marked", + UNMARKED: "/Unmarked", +}; +const annotationReviewStates = { + ACCEPTED: "/Accepted", + REJECTED: "/Rejected", + CANCELLED: "/Cancelled", + COMPLETED: "/Completed", + NONE: "/None", +}; +const annotationIconTypes = { + COMMENT: "/Comment", + KEY: "/Key", + NOTE: "/Note", + HELP: "/Help", + NEW_PARAGRAPH: "/NewParagraph", + PARAGRAPH: "/Paragraph", + INSERT: "/Insert", +}; +const freeTextIntents = { + PLAIN_TEXT: "/FreeText", + WITH_CALLOUT: "/FreeTextCallout", + CLICK_TO_TYPE: "/FreeTextTypeWriter", +}; +const markupAnnotationReplyTypes = { + REPLY: "/R", + GROUP: "/Group", +}; +const stampTypes = { + DRAFT: "/Draft", + NOT_APPROVED: "/NotApproved", + APPROVED: "/Approved", + AS_IS: "/AsIs", + FOR_COMMENT: "/ForComment", + EXPERIMENTAL: "/Experimental", + FINAL: "/Final", + SOLD: "/Sold", + EXPIRED: "/Expired", + PUBLIC: "/ForPublicRelease", + NOT_PUBLIC: "/NotForPublicRelease", + DEPARTMENTAL: "/Departmental", + CONFIDENTIAL: "/Confidential", + SECRET: "/TopSecret", +}; +const polyIntents = { + CLOUD: "/PolygonCloud", + POLYGON_DIMENSION: "/PolygonDimension", + POLYLINE_DIMENSION: "/PolyLineDimension", +}; +const lineIntents = { + ARROW: "/LineArrow", + DIMENSION: "/LineDimension", +}; +const lineCaptionPositions = { + INLINE: "/Inline", + TOP: "/Top", +}; +const lineEndingTypes = { + SQUARE: "/Square", + CIRCLE: "/Circle", + DIAMOND: "/Diamond", + ARROW_OPEN: "/OpenArrow", + ARROW_CLOSED: "/ClosedArrow", + NONE: "/None", + BUTT: "/Butt", + ARROW_OPEN_R: "/ROpenArrow", + ARROW_CLOSED_R: "/RClosedArrow", + SLASH: "/Slash", +}; +const lineCapStyles = { + BUTT: 0, + ROUND: 1, + SQUARE: 2, +}; +const lineJoinStyles = { + MITER: 0, + ROUND: 1, + BEVEL: 2, +}; +const justificationTypes = { + LEFT: 0, + CENTER: 1, + RIGHT: 2, +}; +const renderingIntents = { + ABSOLUTE: "/AbsoluteColorimetric", + RELATIVE: "/RelativeColorimetric", + SATURATION: "/Saturation", + PERCEPTUAL: "/Perceptual", +}; +const blendModes = { + NORMAL: "/Normal", + COMPATIBLE: "/Compatible", + MULTIPLY: "/Multiply", + SCREEN: "/Screen", + OVERLAY: "/Overlay", + DARKEN: "/Darken", + LIGHTEN: "/Lighten", + COLOR_DODGE: "/ColorDodge", + COLOR_BURN: "/ColorBurn", + HARD_LIGHT: "/HardLight", + SOFT_LIGHT: "/SoftLight", + DIFFERENCE: "/Difference", + EXCLUSION: "/Exclusion", +}; +const textRenderModes = { + FILL: 0, + STROKE: 1, + FILL_STROKE: 2, + INVISIBLE: 3, + FILL_USE_AS_CLIP: 4, + STROKE_USE_AS_CLIP: 5, + FILL_STROKE_USE_AS_CLIP: 6, + USE_AS_CLIP: 7, +}; +const colorSpaces = { + GRAYSCALE: "/DeviceGray", + RGB: "/DeviceRGB", + CMYK: "/DeviceCMYK", + SPECIAL: "/DeviceN", + SPECIAL_INDEXED: "/Indexed", + SPECIAL_PATTERN: "/Pattern", + SPECIAL_SEPARATION: "/Separation", +}; +const softMaskTypes = { + ALPHA: "/Alpha", + LUMINOSITY: "/Luminosity", +}; +const borderEffects = { + NONE: "/S", + CLOUDY: "/C", +}; +const borderStyles = { + SOLID: "/S", + DASHED: "/D", + BEVELED: "/B", + INSET: "/I", + UNDERLINE: "/U", + NONE: "/N", +}; +const groupDictTypes = { + TRANSPARENCY: "/Transparency", +}; + +const workerSrc = ` +/**the most used char codes from the ASCII set */ +const codes = { + NULL: 0, + BACKSPACE: 8, + HORIZONTAL_TAB: 9, + LINE_FEED: 10, + VERTICAL_TAB: 11, + FORM_FEED: 12, + CARRIAGE_RETURN: 13, + WHITESPACE: 32, + EXCLAMATION_MARK: 33, + DOUBLE_QUOTE: 34, + HASH: 35, + DOLLAR: 36, + PERCENT: 37, + AMPERSAND: 38, + QUOTE: 39, + L_PARENTHESE: 40, + R_PARENTHESE: 41, + ASTERISK: 42, + PLUS: 43, + COMMA: 44, + MINUS: 45, + DOT: 46, + SLASH: 47, + D_0: 48, + D_1: 49, + D_2: 50, + D_3: 51, + D_4: 52, + D_5: 53, + D_6: 54, + D_7: 55, + D_8: 56, + D_9: 57, + COLON: 58, + SEMICOLON: 59, + LESS: 60, + EQUAL: 61, + GREATER: 62, + QUESTION_MARK: 63, + AT: 64, + A: 65, + B: 66, + C: 67, + D: 68, + E: 69, + F: 70, + G: 71, + H: 72, + I: 73, + J: 74, + K: 75, + L: 76, + M: 77, + N: 78, + O: 79, + P: 80, + Q: 81, + R: 82, + S: 83, + T: 84, + U: 85, + V: 86, + W: 87, + X: 88, + Y: 89, + Z: 90, + L_BRACKET: 91, + BACKSLASH: 92, + R_BRACKET: 93, + CARET: 94, + UNDERSCORE: 95, + BACKTICK: 96, + a: 97, + b: 98, + c: 99, + d: 100, + e: 101, + f: 102, + g: 103, + h: 104, + i: 105, + j: 106, + k: 107, + l: 108, + m: 109, + n: 110, + o: 111, + p: 112, + q: 113, + r: 114, + s: 115, + t: 116, + u: 117, + v: 118, + w: 119, + x: 120, + y: 121, + z: 122, + L_BRACE: 123, + VERTICAL_LINE: 124, + R_BRACE: 125, + TILDE: 126, +}; + +/**char code sequences commonly used in PDF data */ +const keywordCodes = { + NULL: [codes.n, codes.u, codes.l, codes.l], + + OBJ: [codes.o, codes.b, codes.j], + OBJ_END: [codes.e, codes.n, codes.d, codes.o, codes.b, codes.j], + + STREAM_START: [codes.s, codes.t, codes.r, codes.e, codes.a, codes.m], + STREAM_END: [codes.e, codes.n, codes.d, + codes.s, codes.t, codes.r, codes.e, codes.a, codes.m], + + DICT_START: [codes.LESS, codes.LESS], + DICT_END: [codes.GREATER, codes.GREATER], + + ARRAY_START: [codes.L_BRACKET], + ARRAY_END: [codes.R_BRACKET], + + STR_LITERAL_START: [codes.L_PARENTHESE], + STR_LITERAL_END: [codes.R_PARENTHESE], + + STR_HEX_START: [codes.LESS], + STR_HEX_END: [codes.GREATER], + + VERSION: [codes.PERCENT, codes.P, codes.D, codes.F, codes.MINUS], + + PREV: [codes.SLASH, codes.P, codes.r, codes.e, codes.v], + TYPE: [codes.SLASH, codes.T, codes.y, codes.p, codes.e], + SUBTYPE: [codes.SLASH, codes.S, codes.u, codes.b, codes.t, codes.y, codes.p, codes.e], + FORM: [codes.SLASH, codes.F, codes.o, codes.r, codes.m], + + XREF_TABLE: [codes.x, codes.r, codes.e, codes.f], + XREF_STREAM: [codes.SLASH, codes.X, codes.R, codes.e, codes.f], + XREF_HYBRID: [codes.X, codes.R, codes.e, codes.f, codes.S, codes.t, codes.m], + + XREF_START: [codes.s, codes.t, codes.a, codes.r, codes.t, + codes.x, codes.r, codes.e, codes.f], + TRAILER: [codes.t, codes.r, codes.a, codes.i, codes.l, codes.e, codes.r], + END_OF_FILE: [codes.PERCENT, codes.PERCENT, codes.E, codes.O, codes.F], + + END_OF_LINE: [codes.CARRIAGE_RETURN, codes.LINE_FEED], + + TRUE: [codes.t, codes.r, codes.u, codes.e], + FALSE: [codes.f, codes.a, codes.l, codes.s, codes.e], + + CMAP_BEGIN: [codes.b, codes.e, codes.g, codes.i, codes.n, + codes.c, codes.m, codes.a, codes.p], + CMAP_END: [codes.e, codes.n, codes.d, + codes.c, codes.m, codes.a, codes.p], + CMAP_BEGIN_CODE_RANGE: [codes.b, codes.e, codes.g, codes.i, codes.n, + codes.c, codes.o, codes.d, codes.e, codes.s, codes.p, codes.a, codes.c, codes.e, + codes.r, codes.a, codes.n, codes.g, codes.e], + CMAP_END_CODE_RANGE: [codes.e, codes.n, codes.d, + codes.c, codes.o, codes.d, codes.e, codes.s, codes.p, codes.a, codes.c, codes.e, + codes.r, codes.a, codes.n, codes.g, codes.e], + CMAP_BEGIN_CHAR: [codes.b, codes.e, codes.g, codes.i, codes.n, + codes.b, codes.f, codes.c, codes.h, codes.a, codes.r], + CMAP_END_CHAR: [codes.e, codes.n, codes.d, + codes.b, codes.f, codes.c, codes.h, codes.a, codes.r], + CMAP_BEGIN_RANGE: [codes.b, codes.e, codes.g, codes.i, codes.n, + codes.b, codes.f, codes.r, codes.a, codes.n, codes.g, codes.e], + CMAP_END_RANGE: [codes.e, codes.n, codes.d, + codes.b, codes.f, codes.r, codes.a, codes.n, codes.g, codes.e], + + AP_STREAM_TEXT_END: [codes.E, codes.T], +}; + +/**value types that can be found in PDF file data */ +const valueTypes = { + UNKNOWN: 0, + NULL: 1, + BOOLEAN: 2, + NUMBER: 3, + STRING_LITERAL: 4, + STRING_HEX: 5, + NAME: 6, + ARRAY: 7, + DICTIONARY: 8, + STREAM: 9, + REF: 10, + COMMENT: 11, +}; + +//#region static collections +/** + * Each line is terminated by an end-of-line (EOL) marker + */ +// const EOL = [ +// codes.CARRIAGE_RETURN, +// codes.LINE_FEED, +// ]; + +/** + * The delimiter characters (, ), <, >, [, ], {, }, /, and % are special. + * They delimit syntactic entities such as strings, arrays, names, and comments. + * Any of these characters terminates the entity preceding it and is not included in the entity. + */ +const delimiterChars = new Set([ + codes.PERCENT, + codes.L_PARENTHESE, + codes.R_PARENTHESE, + codes.SLASH, + codes.LESS, + codes.GREATER, + codes.L_BRACKET, + codes.R_BRACKET, + codes.L_BRACE, + codes.R_BRACE, +]); + +/** + * White-space characters separate syntactic constructs such as names and numbers from each other. + * All white-space characters are equivalent, except in comments, strings, and streams. + * In all other contexts, PDF treats any sequence of consecutive white-space characters as one character. + */ +const spaceChars = new Set([ + codes.NULL, + codes.HORIZONTAL_TAB, + codes.LINE_FEED, + codes.FORM_FEED, + codes.CARRIAGE_RETURN, + codes.WHITESPACE, +]); + +const digitChars = new Set([ + codes.D_0, + codes.D_1, + codes.D_2, + codes.D_3, + codes.D_4, + codes.D_5, + codes.D_6, + codes.D_7, + codes.D_8, + codes.D_9, +]); + +const newLineChars = new Set([ + codes.CARRIAGE_RETURN, + codes.LINE_FEED, +]); +//#endregion + +//#region static check functions +/** + * check if the char is not a space char or a delimiter char + * @param code char code + * @returns + */ +function isRegularChar(code) { + if (isNaN(code)) { + return false; + } + return !delimiterChars.has(code) && !spaceChars.has(code); +} + +/** + * check if the char is a space char or a delimiter char + * @param code char code + * @returns + */ +function isNotRegularChar(code) { + if (isNaN(code)) { + return true; + } + return delimiterChars.has(code) || spaceChars.has(code); +} + +function isDigit(code) { + return digitChars.has(code); +} + +function isNewLineChar(code) { + return newLineChars.has(code); +} + +function isSpaceChar(code) { + return spaceChars.has(code); +} + +function isNotSpaceChar(code) { + return !spaceChars.has(code); +} + +function isDelimiterChar(code) { + return delimiterChars.has(code); +} + +function isNotDelimiterChar(code) { + return !delimiterChars.has(code); +} +//#endregion + +let _data = new Uint8Array(); +let _maxIndex = 0; + +const _messageQueue = []; +let _busy = false; + +self.onmessage = (event) => { + if (_busy) { + _messageQueue.push(event); + } else { + _busy = true; + processData(event.data); + } +}; + +function sendResponse(response) { + self.postMessage(response); + if (_messageQueue.length) { + processData(_messageQueue.shift().data); + } else { + _busy = false; + } +} + +function processData(data) { + const id = data.id; + const name = data.name; + + if (name === "data-set") { + if (data.bytes) { + const dataBytesArray = new Uint8Array(data.bytes); + if (dataBytesArray?.length) { + _data = dataBytesArray; + _maxIndex = dataBytesArray.length - 1; + sendResponse({id, name, type: "success"}); + return; + } + } + sendResponse({id, name, type: "error", + message: "data-set: byte array is null or empty"}); + return; + } + + if (name === "data-reset") { + const buffer = _data.buffer; + _data = new Uint8Array(); + _maxIndex = 0; + sendResponse({id, name, type: "success", bytes: buffer}, [buffer]); + return; + } + + // console.log(JSON.stringify(data)); + try { + let result; + switch (name) { + // common cases + case "is-outside": + result = isOutside(...data.args); + break; + case "is-code-at": + result = isCodeAt(...data.args); + break; + case "get-value-type-at": + result = getValueTypeAt(...data.args); + break; + // search cases + case "find-subarray-index": + result = findSubarrayIndex(...data.args); + break; + case "find-char-index": + result = findCharIndex(...data.args); + break; + case "find-new-line-index": + result = findNewLineIndex(...data.args); + break; + case "find-space-index":result = findSpaceIndex(...data.args); + break; + case "find-non-space-index": + result = findNonSpaceIndex(...data.args); + break; + case "find-delimiter-index": + result = findDelimiterIndex(...data.args); + break; + case "find-non-delimiter-index": + result = findNonDelimiterIndex(...data.args); + break; + case "find-regular-index": + result = findRegularIndex(...data.args); + break; + case "find-irregular-index": + result = findIrregularIndex(...data.args); + break; + // getting bounds cases + case "get-indirect-object-bounds": + result = getIndirectObjectBoundsAt(...data.args); + break; + case "get-xref-table-bounds": + result = getXrefTableBoundsAt(...data.args); + break; + case "get-dict-bounds": + result = getDictBoundsAt(...data.args); + break; + case "get-array-bounds": + result = getArrayBoundsAt(...data.args); + break; + case "get-hex-bounds": + result = getHexBoundsAt(...data.args); + break; + case "get-literal-bounds": + result = getLiteralBoundsAt(...data.args); + break; + // parsing cases + case "parse-number": + result = parseNumberAt(...data.args); + break; + case "parse-name": + result = parseNameAt(...data.args); + break; + case "parse-string": + result = parseStringAt(...data.args); + break; + case "parse-bool": + result = parseBoolAt(...data.args); + break; + case "parse-number-array": + result = parseNumberArrayAt(...data.args); + break; + case "parse-name-array": + result = parseNameArrayAt(...data.args); + break; + case "parse-dict-type": + result = parseDictType(...data.args); + break; + case "parse-dict-subtype": + result = parseDictSubtype(...data.args); + break; + case "parse-dict-property-by-name": + result = parseDictPropertyByName(...data.args); + break; + // skip cases + case "skip-empty": + result = skipEmptyChars(...data.args); + break; + case "skip-to-next-name": + result = skipToNextName(...data.args); + break; + // getting char/codes cases + case "slice-char-codes": + result = sliceCharCodes(...data.args); + break; + case "slice-chars": + result = sliceChars(...data.args); + break; + case "get-char-code": + result = getCharCode(...data.args); + break; + default: + throw new Error("Unknown command name: " + name); + } + // console.log(JSON.stringify(result)); + sendResponse({id, name, type: "success", result}); + } catch (e) { + // console.log(JSON.stringify(e)); + sendResponse({id, name, type: "error", message: e.message}); + } +} + +//#region common functions +function isOutside(index) { + return (index < 0 || index > _maxIndex); +} + +function isCodeAt(index, code) { + return getCharCode(index) === code; +} + +function getValueTypeAt(start, skipEmpty = true) { + if (skipEmpty) { + start = skipEmptyChars(start); + } + if (isOutside(start)) { + return null; + } + + const arr = _data; + const i = start; + const charCode = arr[i]; + + let tempIndex; + switch (charCode) { + case codes.SLASH: + if (isRegularChar(arr[i + 1])) { + return valueTypes.NAME; + } + return valueTypes.UNKNOWN; + case codes.L_BRACKET: + return valueTypes.ARRAY; + case codes.L_PARENTHESE: + return valueTypes.STRING_LITERAL; + case codes.LESS: + if (codes.LESS === arr[i + 1]) { + return valueTypes.DICTIONARY; + } + return valueTypes.STRING_HEX; + case codes.PERCENT: + return valueTypes.COMMENT; + case codes.D_0: + case codes.D_1: + case codes.D_2: + case codes.D_3: + case codes.D_4: + case codes.D_5: + case codes.D_6: + case codes.D_7: + case codes.D_8: + case codes.D_9: + tempIndex = findDelimiterIndex(true, i + 1); + if (tempIndex !== -1) { + const refEndIndex = findCharIndex(codes.R, false, tempIndex - 1); + if (refEndIndex !== -1 && refEndIndex > i && !isRegularChar(arr[refEndIndex + 1])) { + return valueTypes.REF; + } + } + return valueTypes.NUMBER; + case codes.DOT: + case codes.MINUS: + if (isDigit(arr[i + 1])) { + return valueTypes.NUMBER; + } + return valueTypes.UNKNOWN; + case codes.s: + if (arr[i + 1] === codes.t + && arr[i + 2] === codes.r + && arr[i + 3] === codes.e + && arr[i + 4] === codes.a + && arr[i + 5] === codes.m) { + return valueTypes.STREAM; + } + return valueTypes.UNKNOWN; + case codes.t: + if (arr[i + 1] === codes.r + && arr[i + 2] === codes.u + && arr[i + 3] === codes.e) { + return valueTypes.BOOLEAN; + } + return valueTypes.UNKNOWN; + case codes.f: + if (arr[i + 1] === codes.a + && arr[i + 2] === codes.l + && arr[i + 3] === codes.s + && arr[i + 4] === codes.e) { + return valueTypes.BOOLEAN; + } + return valueTypes.UNKNOWN; + default: + return valueTypes.UNKNOWN; + } +} +//#endregion + +//#region search functions +function findSubarrayIndex(sub, options) { + const arr = _data; + if (!sub?.length) { + return null; + } + + const direction = options?.direction ?? true; + const minIndex = Math.max(Math.min(options?.minIndex ?? 0, _maxIndex), 0); + const maxIndex = Math.max(Math.min(options?.maxIndex ?? _maxIndex, _maxIndex), 0); + const allowOpened = !options?.closedOnly; + + let i = direction + ? minIndex + : maxIndex; + + let j; + if (direction) { + outer_loop: + for (i; i <= maxIndex; i++) { + for (j = 0; j < sub.length; j++) { + if (arr[i + j] !== sub[j]) { + continue outer_loop; + } + } + if (allowOpened || !isRegularChar(arr[i + j])) { + return {start: i, end: i + j - 1}; + } + } + } else { + const subMaxIndex = sub.length - 1; + outer_loop: + for (i; i >= minIndex; i--) { + for (j = 0; j < sub.length; j++) { + if (arr[i - j] !== sub[subMaxIndex - j]) { + continue outer_loop; + } + } + if (allowOpened || !isRegularChar(arr[i - j])) { + return {start: i - j + 1, end: i}; + } + } + } + + return null; +} + +function findCharIndex(charCode, direction = true, start = undefined) { + + const arr = _data; + let i = isNaN(start) + ? direction + ? 0 + : _maxIndex + : start; + + if (direction) { + for (i; i <= _maxIndex; i++) { + if (arr[i] === charCode) { + return i; + } + } + } else { + for (i; i >= 0; i--) { + if (arr[i] === charCode) { + return i; + } + } + } + + return -1; +} + +function findNewLineIndex(direction = true, start = undefined) { + let lineBreakIndex; + + const arr = _data; + let i = isNaN(start) + ? direction + ? 0 + : _maxIndex + : start; + + if (direction) { + for (i; i <= _maxIndex; i++) { + if (isNewLineChar(arr[i])) { + lineBreakIndex = i; + break; + } + } + } else { + for (i; i >= 0; i--) { + if (isNewLineChar(arr[i])) { + lineBreakIndex = i; + break; + } + } + } + + if (lineBreakIndex === undefined) { + return -1; + } + + if (direction) { + if (_data[lineBreakIndex] === codes.CARRIAGE_RETURN + && _data[lineBreakIndex + 1] === codes.LINE_FEED) { + lineBreakIndex++; + } + return Math.min(lineBreakIndex + 1, _maxIndex); + } else { + if (_data[lineBreakIndex] === codes.LINE_FEED + && _data[lineBreakIndex - 1] === codes.CARRIAGE_RETURN) { + lineBreakIndex--; + } + return Math.max(lineBreakIndex - 1, 0); + } +} + +function findSpaceIndex(direction = true, start = undefined) { + const arr = _data; + let i = isNaN(start) + ? direction + ? 0 + : _maxIndex + : start; + + if (direction) { + for (i; i <= _maxIndex; i++) { + if (isSpaceChar(arr[i])) { + return i; + } + } + } else { + for (i; i >= 0; i--) { + if (isSpaceChar(arr[i])) { + return i; + } + } + } + + return -1; +} + +function findNonSpaceIndex(direction = true, start = undefined) { + const arr = _data; + let i = isNaN(start) + ? direction + ? 0 + : _maxIndex + : start; + + if (direction) { + for (i; i <= _maxIndex; i++) { + if (isNotSpaceChar(arr[i])) { + return i; + } + } + } else { + for (i; i >= 0; i--) { + if (isNotSpaceChar(arr[i])) { + return i; + } + } + } + + return -1; +} + +function findDelimiterIndex(direction = true, start = undefined) { + const arr = _data; + let i = isNaN(start) + ? direction + ? 0 + : _maxIndex + : start; + + if (direction) { + for (i; i <= _maxIndex; i++) { + if (isDelimiterChar(arr[i])) { + return i; + } + } + } else { + for (i; i >= 0; i--) { + if (isDelimiterChar(arr[i])) { + return i; + } + } + } + + return -1; +} + +function findNonDelimiterIndex(direction = true, start = undefined) { + const arr = _data; + let i = isNaN(start) + ? direction + ? 0 + : _maxIndex + : start; + + if (direction) { + for (i; i <= _maxIndex; i++) { + if (isNotDelimiterChar(arr[i])) { + return i; + } + } + } else { + for (i; i >= 0; i--) { + if (isNotDelimiterChar(arr[i])) { + return i; + } + } + } + + return -1; +} + +function findRegularIndex(direction = true, start = undefined) { + const arr = _data; + let i = isNaN(start) + ? direction + ? 0 + : _maxIndex + : start; + + if (direction) { + for (i; i <= _maxIndex; i++) { + if (isRegularChar(arr[i])) { + return i; + } + } + } else { + for (i; i >= 0; i--) { + if (isRegularChar(arr[i])) { + return i; + } + } + } + + return -1; +} + +function findIrregularIndex(direction = true, start = undefined) { + const arr = _data; + let i = isNaN(start) + ? direction + ? 0 + : _maxIndex + : start; + + if (direction) { + for (i; i <= _maxIndex; i++) { + if (isNotRegularChar(arr[i])) { + return i; + } + } + } else { + for (i; i >= 0; i--) { + if (isNotRegularChar(arr[i])) { + return i; + } + } + } + + return -1; +} +//#endregion + +//#region get bounds functions +function getIndirectObjectBoundsAt(start, skipEmpty = true) { + if (skipEmpty) { + start = skipEmptyChars(start); + } + if (isOutside(start)) { + return null; + } + + const objStartIndex = findSubarrayIndex(keywordCodes.OBJ, + {minIndex: start, closedOnly: true}); + if (!objStartIndex) { + return null; + } + + let contentStart = findNonSpaceIndex(true, objStartIndex.end + 1); + if (contentStart === -1){ + return null; + } + const objEndIndex = findSubarrayIndex(keywordCodes.OBJ_END, + {minIndex: contentStart, closedOnly: true}); + if (!objEndIndex) { + return null; + } + let contentEnd = findNonSpaceIndex(false, objEndIndex.start - 1); + + if (getCharCode(contentStart) === codes.LESS + && getCharCode(contentStart + 1) === codes.LESS + && getCharCode(contentEnd - 1) === codes.GREATER + && getCharCode(contentEnd) === codes.GREATER) { + // object is dict. exclude bounds from content + contentStart += 2; + contentEnd -=2; + } + + return { + start: objStartIndex.start, + end: objEndIndex.end, + contentStart, + contentEnd, + }; +} + +function getXrefTableBoundsAt(start, skipEmpty = true) { + if (skipEmpty) { + start = skipEmptyChars(start); + } + if (isOutside(start) || _data[start] !== codes.x) { + return null; + } + + const xrefStart = findSubarrayIndex(keywordCodes.XREF_TABLE, + {minIndex: start}); + if (!xrefStart) { + return null; + } + const contentStart = findNonSpaceIndex(true, xrefStart.end + 1); + if (contentStart === -1){ + return null; + } + const xrefEnd = findSubarrayIndex(keywordCodes.TRAILER, + {minIndex: xrefStart.end + 1}); + if (!xrefEnd) { + return null; + } + const contentEnd = findNonSpaceIndex(false, xrefEnd.start - 1); + + if (contentEnd < contentStart) { + // should be only possible in an empty xref, which is not allowed + return null; + } + + return { + start: xrefStart.start, + end: xrefEnd.end, + contentStart, + contentEnd, + }; +} + +function getDictBoundsAt(start, skipEmpty = true) { + if (skipEmpty) { + start = skipEmptyChars(start); + } + if (isOutside(start) + || _data[start] !== codes.LESS + || _data[start + 1] !== codes.LESS) { + return null; + } + + const contentStart = findNonSpaceIndex(true, start + 2); + if (contentStart === -1){ + return null; + } + + let dictOpened = 1; + let dictBound = true; + let literalOpened = 0; + let i = contentStart; + let code; + let prevCode; + while (dictOpened) { + prevCode = code; + code = _data[i++]; + + if (code === codes.L_PARENTHESE + && (!literalOpened || prevCode !== codes.BACKSLASH)) { + // increase string literal nesting + literalOpened++; + } + + if (code === codes.R_PARENTHESE + && (literalOpened && prevCode !== codes.BACKSLASH)) { + // decrease string literal nesting + literalOpened--; + } + + if (literalOpened) { + // ignore 'less' and 'greater' signs while being inside a literal + continue; + } + + if (!dictBound) { + if (code === codes.LESS && code === prevCode) { + dictOpened++; + dictBound = true; + } else if (code === codes.GREATER && code === prevCode) { + dictOpened--; + dictBound = true; + } + } else { + dictBound = false; + } + } + const end = i - 1; + + const contentEnd = findNonSpaceIndex(false, end - 2); + if (contentEnd < contentStart) { + // should be possible only in an empty dict + return { + start, + end, + }; + } + + return { + start, + end, + contentStart, + contentEnd, + }; +} + +function getArrayBoundsAt(start, skipEmpty = true) { + if (skipEmpty) { + start = skipEmptyChars(start); + } + if (isOutside(start) || _data[start] !== codes.L_BRACKET) { + return null; + } + + let arraysOpened = 1; + let i = start + 1; + let code; + while (arraysOpened) { + code = _data[i++]; + if (code === codes.L_BRACKET) { + arraysOpened++; + } else if (code === codes.R_BRACKET) { + arraysOpened--; + } + } + const arrayEnd = i - 1; + if (arrayEnd - start < 1) { + return null; + } + + return {start, end: arrayEnd}; +} + +function getHexBoundsAt(start, skipEmpty = true) { + if (skipEmpty) { + start = skipEmptyChars(start); + } + if (isOutside(start) || getCharCode(start) !== codes.LESS) { + return null; + } + + const end = findCharIndex(codes.GREATER, true, start + 1); + if (end === -1) { + return null; + } + + return {start, end}; +} + +function getLiteralBoundsAt(start, skipEmpty = true) { + if (skipEmpty) { + start = skipEmptyChars(start); + } + if (isOutside(start) || getCharCode(start) !== codes.L_PARENTHESE) { + return null; + } + + let i = start; + let code; + let escaped = false; + let opened = 0; + + while (opened || code !== codes.R_PARENTHESE || escaped) { + if (i > _maxIndex) { + return null; + } + + code = getCharCode(i++); + + if (!escaped) { + if (code === codes.L_PARENTHESE) { + opened += 1; + } else if (opened && code === codes.R_PARENTHESE) { + opened -= 1; + } + } + + if (!escaped && code === codes.BACKSLASH) { + escaped = true; + } else { + escaped = false; + } + } + + return {start, end: i - 1}; +} +//#endregion + +//#region parse functions +function parseNumberAt(start, float = false, skipEmpty = true) { + if (skipEmpty) { + start = skipEmptyChars(start); + } + if (isOutside(start) || !isRegularChar(_data[start])) { + return null; + } + + let i = start; + let numberStr = ""; + let value = _data[i]; + if (value === codes.MINUS) { + numberStr += "-"; + value = _data[++i]; + } else if (value === codes.DOT) { + numberStr += "0."; + value = _data[++i]; + } + while (isDigit(value) + || (float && value === codes.DOT)) { + numberStr += String.fromCharCode(value); + value = _data[++i]; + } + + return numberStr + ? {value: +numberStr, start, end: i - 1} + : null; +} + +function parseNameAt(start, includeSlash = true, skipEmpty = true) { + if (skipEmpty) { + start = skipEmptyChars(start); + } + if (isOutside(start) || _data[start] !== codes.SLASH) { + return null; + } + + let i = start + 1; + let result = includeSlash + ? "/" + : ""; + let value = _data[i]; + while (isRegularChar(value)) { + result += String.fromCharCode(value); + value = _data[++i]; + } + + return result.length > 1 + ? {value: result, start, end: i - 1} + : null; +} + +function parseStringAt(start, skipEmpty = true) { + if (skipEmpty) { + start = skipEmptyChars(start); + } + if (isOutside(start)) { + return null; + } + + let i = start; + let result = ""; + let value = _data[i]; + while (isRegularChar(value)) { + result += String.fromCharCode(value); + value = _data[++i]; + } + + return result.length !== 0 + ? {value: result, start, end: i - 1} + : null; +} + +function parseBoolAt(start, skipEmpty = true) { + if (skipEmpty) { + start = skipEmptyChars(start); + } + + if (isOutside(start)) { + return null; + } + + const nearestDelimiter = findDelimiterIndex(true, start); + + const isTrue = findSubarrayIndex(keywordCodes.TRUE, { + minIndex: start, + maxIndex: nearestDelimiter === -1 ? _maxIndex : nearestDelimiter, + }); + if (isTrue) { + return {value: true, start, end: isTrue.end}; + } + + const isFalse = findSubarrayIndex(keywordCodes.FALSE, { + minIndex: start, + maxIndex: nearestDelimiter === -1 ? _maxIndex : nearestDelimiter, + }); + if (isFalse) { + return {value: false, start, end: isFalse.end}; + } + + return null; +} + +function parseNumberArrayAt(start, float = true, skipEmpty = true) { + const arrayBounds = getArrayBoundsAt(start, skipEmpty); + if (!arrayBounds) { + return null; + } + + const numbers = []; + let current; + let i = arrayBounds.start + 1; + while(i < arrayBounds.end) { + current = parseNumberAt(i, float, true); + if (!current) { + break; + } + numbers.push(current.value); + i = current.end + 1; + } + + return {value: numbers, start: arrayBounds.start, end: arrayBounds.end}; +} + +function parseNameArrayAt(start, includeSlash = true, + skipEmpty = true) { + const arrayBounds = getArrayBoundsAt(start, skipEmpty); + if (!arrayBounds) { + return null; + } + + const names = []; + let current; + let i = arrayBounds.start + 1; + while(i < arrayBounds.end) { + current = parseNameAt(i, includeSlash, true); + if (!current) { + break; + } + names.push(current.value); + i = current.end + 1; + } + + return {value: names, start: arrayBounds.start, end: arrayBounds.end}; +} + +function parseDictType(bounds) { + return parseDictPropertyByName(keywordCodes.TYPE, bounds); +} + +function parseDictSubtype(bounds) { + return parseDictPropertyByName(keywordCodes.SUBTYPE, bounds); +} + +function parseDictPropertyByName(propName, bounds) { + const arr = _data; + if (!propName?.length) { + return null; + } + + const minIndex = Math.max(Math.min(bounds.start ?? 0, _maxIndex), 0); + const maxIndex = Math.max(Math.min(bounds.end ?? _maxIndex, _maxIndex), 0); + + let propNameBounds; + let i = minIndex; + let j; + let code; + let prevCode; + let dictOpened = 0; + let dictBound = true; + let literalOpened = 0; + outer_loop: + for (i; i <= maxIndex; i++) { + prevCode = code; + code = arr[i]; + + // check if literal opens + if (code === codes.L_PARENTHESE + && (!literalOpened || prevCode !== codes.BACKSLASH)) { + // increase string literal nesting + literalOpened++; + } + + // check if literal closes + if (code === codes.R_PARENTHESE + && (literalOpened && prevCode !== codes.BACKSLASH)) { + // decrease string literal nesting + literalOpened--; + } + + if (literalOpened) { + // ignore all bytes while being inside a literal + continue; + } + + // check if dict opens or closes + if (!dictBound) { + if (code === codes.LESS && code === prevCode) { + dictOpened++; + dictBound = true; + } else if (code === codes.GREATER && code === prevCode) { + dictOpened--; + dictBound = true; + } + } else { + dictBound = false; + } + + // compare next j values to the corresponding values of the sought name + for (j = 0; j < propName.length; j++) { + if (arr[i + j] !== propName[j]) { + continue outer_loop; + } + } + + if (dictOpened !== 1) { + // the found property name is not inside the topmost dict + continue; + } + + // check if name is closed + if (!isRegularChar(arr[i + j])) { + propNameBounds = {start: i, end: i + j - 1}; + break; + } + } + + if (!propNameBounds) { + // the property name is not found + return null; + } + + // parse the property value + const type = parseNameAt(propNameBounds.end + 1); + if (!type) { + return null; + } + + return type.value; +} +//#endregion + +//#region skip functions +function skipEmptyChars(start) { + let index = findNonSpaceIndex(true, start); + if (index === -1) { + return -1; + } + if (_data[index] === codes.PERCENT) { + // it's a comment. skip it + const afterComment = findNewLineIndex(true, index + 1); + if (afterComment === -1) { + return -1; + } + index = findNonSpaceIndex(true, afterComment); + } + return index; +} + +function skipToNextName(start, max) { + start ||= 0; + max = max + ? Math.min(max, _maxIndex) + : 0; + if (max < start) { + return -1; + } + + let i = start; + while (i <= max) { + const value = getValueTypeAt(i, true); + if (value) { + let skipValueBounds; + let parseResult; + switch (value) { + case valueTypes.DICTIONARY: + skipValueBounds = getDictBoundsAt(i, false); + break; + case valueTypes.ARRAY: + skipValueBounds = getArrayBoundsAt(i, false); + break; + case valueTypes.STRING_LITERAL: + skipValueBounds = getLiteralBoundsAt(i, false); + break; + case valueTypes.STRING_HEX: + skipValueBounds = getHexBoundsAt(i, false); + break; + case valueTypes.NUMBER: + parseResult = parseNumberAt(i, true, false); + if (parseResult) { + skipValueBounds = parseResult; + } + break; + case valueTypes.BOOLEAN: + parseResult = parseBoolAt(i, false); + if (parseResult) { + skipValueBounds = parseResult; + } + break; + case valueTypes.COMMENT: + // TODO: Add skip comment + break; + case valueTypes.NAME: + return i; + default: + i++; + continue; + } + if (skipValueBounds) { + i = skipValueBounds.end + 1; + skipValueBounds = null; + continue; + } + } + i++; + } + return -1; +} +//#endregion + +//#region get chars/codes functions +function sliceCharCodes(start, end = undefined) { + return _data.slice(start, (end || start) + 1); +} + +function sliceChars(start, end = undefined) { + return String.fromCharCode(..._data.slice(start, (end || start) + 1)); +} + +function getCharCode(index) { + return _data[index]; +} +//#endregion +`; + +var __awaiter$1l = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class BgDataParser { + get maxIndex() { + return this._maxIndex; + } + constructor(data) { + this._workerOnMessageHandlers = new Set(); + this._commandsInProgress = 0; + this.onWorkerMessage = (e) => { + for (const handler of this._workerOnMessageHandlers) { + handler(e); + } + }; + this.onWorkerError = (e) => { + throw new Error(`Background worker error: ${e.message}`); + }; + if (!(data === null || data === void 0 ? void 0 : data.length)) { + throw new Error("Data is empty"); + } + if (!BgDataParser._workerSrc) { + throw new Error("Worker source is not initialized"); + } + this._data = data.buffer; + this._maxIndex = data.length - 1; + } + static tryGetParser(data) { + try { + const parser = new BgDataParser(data); + return parser; + } + catch (e) { + console.error(e); + return null; + } + } + static destroy() { + this._freeWorkers.clear(); + this._workerPool.forEach(x => x.terminate()); + this._workerPool.length = 0; + } + static getFreeWorkerFromPoolAsync() { + return __awaiter$1l(this, void 0, void 0, function* () { + if (this._freeWorkers.size) { + const worker = this._freeWorkers.values().next().value; + this._freeWorkers.delete(worker); + return worker; + } + if (this._workerPool.length < this._maxWorkersCount) { + const worker = new Worker(this._workerSrc); + this._workerPool.push(worker); + return worker; + } + const freeWorkerPromise = new Promise((resolve, reject) => { + const start = performance.now(); + const interval = setInterval(() => { + if (this._freeWorkers.size) { + const worker = this._freeWorkers.values().next().value; + this._freeWorkers.delete(worker); + clearInterval(interval); + resolve(worker); + } + if (performance.now() - start > this._workerTimeout) { + clearInterval(interval); + reject("Free worker waiting timeout exceeded"); + } + }, 20); + }); + return yield freeWorkerPromise; + }); + } + static returnWorkerToPool(worker) { + this._freeWorkers.add(worker); + } + static transferDataToWorker(worker, buffer) { + return __awaiter$1l(this, void 0, void 0, function* () { + const workerPromise = new Promise((resolve, reject) => { + worker.onmessage = (e) => { + if (e.data.type === "success") { + resolve(); + } + else { + console.log(e); + console.log(e.data); + reject(e); + } + }; + worker.onerror = (e) => { + console.log(e); + console.log(e.message); + reject(e); + }; + worker.postMessage({ name: "data-set", bytes: buffer }, [buffer]); + }); + try { + yield workerPromise; + } + catch (e) { + console.error(e); + throw new Error("Error while transfering parser data to worker"); + } + }); + } + static transferDataFromWorker(worker) { + return __awaiter$1l(this, void 0, void 0, function* () { + const workerPromise = new Promise((resolve, reject) => { + worker.onmessage = (e) => { + if (e.data.type === "success") { + const buffer = e.data.bytes; + resolve(buffer); + } + else { + reject(e); + } + }; + worker.onerror = (e) => reject(e); + worker.postMessage({ name: "data-reset" }); + }); + try { + const buffer = yield workerPromise; + return buffer; + } + catch (_a) { + throw new Error("Error while transfering parser data from worker"); + } + }); + } + destroy() { + } + getSubParserAsync(start, end) { + return __awaiter$1l(this, void 0, void 0, function* () { + const data = yield this.execCommandAsync("slice-char-codes", [start, end]); + const parser = BgDataParser.tryGetParser(data); + return parser; + }); + } + isOutside(index) { + return (index < 0 || index > this._maxIndex); + } + isCodeAtAsync(index, code) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("is-code-at", [index, code]); + return result; + }); + } + getValueTypeAtAsync(start, skipEmpty = true) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("get-value-type-at", [start, skipEmpty]); + return result; + }); + } + findSubarrayIndexAsync(sub, options) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("find-subarray-index", [sub, options]); + return result; + }); + } + findCharIndexAsync(charCode, direction = true, start) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("find-char-index", [charCode, direction, start]); + return result; + }); + } + findNewLineIndexAsync(direction = true, start) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("find-new-line-index", [direction, start]); + return result; + }); + } + findSpaceIndexAsync(direction = true, start) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("find-space-index", [direction, start]); + return result; + }); + } + findNonSpaceIndexAsync(direction = true, start) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("find-non-space-index", [direction, start]); + return result; + }); + } + findDelimiterIndexAsync(direction = true, start) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("find-delimiter-index", [direction, start]); + return result; + }); + } + findNonDelimiterIndexAsync(direction = true, start) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("find-non-delimiter-index", [direction, start]); + return result; + }); + } + findRegularIndexAsync(direction = true, start) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("find-regular-index", [direction, start]); + return result; + }); + } + findIrregularIndexAsync(direction = true, start) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("find-irregular-index", [direction, start]); + return result; + }); + } + getIndirectObjectBoundsAtAsync(start, skipEmpty = true) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("get-indirect-object-bounds", [start, skipEmpty]); + return result; + }); + } + getXrefTableBoundsAtAsync(start, skipEmpty = true) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("get-xref-table-bounds", [start, skipEmpty]); + return result; + }); + } + getDictBoundsAtAsync(start, skipEmpty = true) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("get-dict-bounds", [start, skipEmpty]); + return result; + }); + } + getArrayBoundsAtAsync(start, skipEmpty = true) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("get-array-bounds", [start, skipEmpty]); + return result; + }); + } + getHexBoundsAtAsync(start, skipEmpty = true) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("get-hex-bounds", [start, skipEmpty]); + return result; + }); + } + getLiteralBoundsAtAsync(start, skipEmpty = true) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("get-literal-bounds", [start, skipEmpty]); + return result; + }); + } + parseNumberAtAsync(start, float = false, skipEmpty = true) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("parse-number", [start, float, skipEmpty]); + return result; + }); + } + parseNameAtAsync(start, includeSlash = true, skipEmpty = true) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("parse-name", [start, includeSlash, skipEmpty]); + return result; + }); + } + parseStringAtAsync(start, skipEmpty = true) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("parse-string", [start, skipEmpty]); + return result; + }); + } + parseBoolAtAsync(start, skipEmpty = true) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("parse-bool", [start, skipEmpty]); + return result; + }); + } + parseNumberArrayAtAsync(start, float = true, skipEmpty = true) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("parse-number-array", [start, float, skipEmpty]); + return result; + }); + } + parseNameArrayAtAsync(start, includeSlash = true, skipEmpty = true) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("parse-name-array", [start, includeSlash, skipEmpty]); + return result; + }); + } + parseDictTypeAsync(bounds) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("parse-dict-type", [bounds]); + return result; + }); + } + parseDictSubtypeAsync(bounds) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("parse-dict-subtype", [bounds]); + return result; + }); + } + parseDictPropertyByNameAsync(propName, bounds) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("parse-dict-property-by-name", [propName, bounds]); + return result; + }); + } + skipEmptyAsync(start) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("skip-empty", [start]); + return result; + }); + } + skipToNextNameAsync(start, max) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("skip-to-next-name", [start, max]); + return result; + }); + } + sliceCharCodesAsync(start, end) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("slice-char-codes", [start, end]); + return result; + }); + } + sliceCharsAsync(start, end) { + return __awaiter$1l(this, void 0, void 0, function* () { + const result = yield this.execCommandAsync("slice-chars", [start, end]); + return result; + }); + } + releaseWorkerAsync(worker) { + return __awaiter$1l(this, void 0, void 0, function* () { + this._workerPromise = null; + const returnedBuffer = yield BgDataParser.transferDataFromWorker(worker); + this._data = returnedBuffer; + worker.onmessage = null; + worker.onerror = null; + BgDataParser.returnWorkerToPool(worker); + this._prevWorkerReleasePromise = null; + }); + } + getWorkerAsync() { + return __awaiter$1l(this, void 0, void 0, function* () { + if (this._prevWorkerReleasePromise) { + yield this._prevWorkerReleasePromise; + } + if (!this._workerPromise) { + this._workerPromise = new Promise((resolve, reject) => __awaiter$1l(this, void 0, void 0, function* () { + const dataBuffer = this._data; + const freeWorker = yield BgDataParser.getFreeWorkerFromPoolAsync(); + yield BgDataParser.transferDataToWorker(freeWorker, dataBuffer); + freeWorker.onmessage = this.onWorkerMessage; + freeWorker.onerror = this.onWorkerError; + const workerReleaseInterval = setInterval(() => __awaiter$1l(this, void 0, void 0, function* () { + if (this._commandsInProgress > 0 || this._workerOnMessageHandlers.size) { + return; + } + clearInterval(workerReleaseInterval); + this._prevWorkerReleasePromise = this.releaseWorkerAsync(freeWorker); + }), 50); + resolve(freeWorker); + })); + } + const worker = yield this._workerPromise; + return worker; + }); + } + execCommandAsync(commandName, commandArgs = []) { + return __awaiter$1l(this, void 0, void 0, function* () { + this._commandsInProgress++; + const worker = yield this.getWorkerAsync(); + const commandId = UUID.getRandomUuid(); + const commandResultPromise = new Promise((resolve, reject) => { + const onMessage = (e) => { + if (e.data.id !== commandId) { + return; + } + this._workerOnMessageHandlers.delete(onMessage); + if (e.data.type === "error") { + reject(`Background worker error: ${e.data.message}`); + } + else { + resolve(e.data.result); + } + }; + this._workerOnMessageHandlers.add(onMessage); + }); + worker.postMessage({ id: commandId, name: commandName, args: commandArgs }); + const result = yield commandResultPromise; + this._commandsInProgress--; + return result; + }); + } +} +BgDataParser._maxWorkersCount = navigator.hardwareConcurrency || 4; +BgDataParser._workerTimeout = 60 * 1000; +BgDataParser._workerSrc = (() => { + const srcBlob = new Blob([workerSrc], { type: "text/plain;charset=utf-8;" }); + const srcUri = URL.createObjectURL(srcBlob); + return srcUri; +})(); +BgDataParser._workerPool = []; +BgDataParser._freeWorkers = new Set(); + +const codes = { + NULL: 0, + BACKSPACE: 8, + HORIZONTAL_TAB: 9, + LINE_FEED: 10, + VERTICAL_TAB: 11, + FORM_FEED: 12, + CARRIAGE_RETURN: 13, + WHITESPACE: 32, + EXCLAMATION_MARK: 33, + DOUBLE_QUOTE: 34, + HASH: 35, + DOLLAR: 36, + PERCENT: 37, + AMPERSAND: 38, + QUOTE: 39, + L_PARENTHESE: 40, + R_PARENTHESE: 41, + ASTERISK: 42, + PLUS: 43, + COMMA: 44, + MINUS: 45, + DOT: 46, + SLASH: 47, + D_0: 48, + D_1: 49, + D_2: 50, + D_3: 51, + D_4: 52, + D_5: 53, + D_6: 54, + D_7: 55, + D_8: 56, + D_9: 57, + COLON: 58, + SEMICOLON: 59, + LESS: 60, + EQUAL: 61, + GREATER: 62, + QUESTION_MARK: 63, + AT: 64, + A: 65, + B: 66, + C: 67, + D: 68, + E: 69, + F: 70, + G: 71, + H: 72, + I: 73, + J: 74, + K: 75, + L: 76, + M: 77, + N: 78, + O: 79, + P: 80, + Q: 81, + R: 82, + S: 83, + T: 84, + U: 85, + V: 86, + W: 87, + X: 88, + Y: 89, + Z: 90, + L_BRACKET: 91, + BACKSLASH: 92, + R_BRACKET: 93, + CARET: 94, + UNDERSCORE: 95, + BACKTICK: 96, + a: 97, + b: 98, + c: 99, + d: 100, + e: 101, + f: 102, + g: 103, + h: 104, + i: 105, + j: 106, + k: 107, + l: 108, + m: 109, + n: 110, + o: 111, + p: 112, + q: 113, + r: 114, + s: 115, + t: 116, + u: 117, + v: 118, + w: 119, + x: 120, + y: 121, + z: 122, + L_BRACE: 123, + VERTICAL_LINE: 124, + R_BRACE: 125, + TILDE: 126, +}; +const keywordCodes = { + NULL: [codes.n, codes.u, codes.l, codes.l], + OBJ: [codes.o, codes.b, codes.j], + OBJ_END: [codes.e, codes.n, codes.d, codes.o, codes.b, codes.j], + STREAM_START: [codes.s, codes.t, codes.r, codes.e, codes.a, codes.m], + STREAM_END: [codes.e, codes.n, codes.d, + codes.s, codes.t, codes.r, codes.e, codes.a, codes.m], + DICT_START: [codes.LESS, codes.LESS], + DICT_END: [codes.GREATER, codes.GREATER], + ARRAY_START: [codes.L_BRACKET], + ARRAY_END: [codes.R_BRACKET], + STR_LITERAL_START: [codes.L_PARENTHESE], + STR_LITERAL_END: [codes.R_PARENTHESE], + STR_HEX_START: [codes.LESS], + STR_HEX_END: [codes.GREATER], + VERSION: [codes.PERCENT, codes.P, codes.D, codes.F, codes.MINUS], + PREV: [codes.SLASH, codes.P, codes.r, codes.e, codes.v], + TYPE: [codes.SLASH, codes.T, codes.y, codes.p, codes.e], + SUBTYPE: [codes.SLASH, codes.S, codes.u, codes.b, codes.t, codes.y, codes.p, codes.e], + FORM: [codes.SLASH, codes.F, codes.o, codes.r, codes.m], + XREF_TABLE: [codes.x, codes.r, codes.e, codes.f], + XREF_STREAM: [codes.SLASH, codes.X, codes.R, codes.e, codes.f], + XREF_HYBRID: [codes.X, codes.R, codes.e, codes.f, codes.S, codes.t, codes.m], + XREF_START: [codes.s, codes.t, codes.a, codes.r, codes.t, + codes.x, codes.r, codes.e, codes.f], + TRAILER: [codes.t, codes.r, codes.a, codes.i, codes.l, codes.e, codes.r], + END_OF_FILE: [codes.PERCENT, codes.PERCENT, codes.E, codes.O, codes.F], + END_OF_LINE: [codes.CARRIAGE_RETURN, codes.LINE_FEED], + TRUE: [codes.t, codes.r, codes.u, codes.e], + FALSE: [codes.f, codes.a, codes.l, codes.s, codes.e], + CMAP_BEGIN: [codes.b, codes.e, codes.g, codes.i, codes.n, + codes.c, codes.m, codes.a, codes.p], + CMAP_END: [codes.e, codes.n, codes.d, + codes.c, codes.m, codes.a, codes.p], + CMAP_BEGIN_CODE_RANGE: [codes.b, codes.e, codes.g, codes.i, codes.n, + codes.c, codes.o, codes.d, codes.e, codes.s, codes.p, codes.a, codes.c, codes.e, + codes.r, codes.a, codes.n, codes.g, codes.e], + CMAP_END_CODE_RANGE: [codes.e, codes.n, codes.d, + codes.c, codes.o, codes.d, codes.e, codes.s, codes.p, codes.a, codes.c, codes.e, + codes.r, codes.a, codes.n, codes.g, codes.e], + CMAP_BEGIN_CHAR: [codes.b, codes.e, codes.g, codes.i, codes.n, + codes.b, codes.f, codes.c, codes.h, codes.a, codes.r], + CMAP_END_CHAR: [codes.e, codes.n, codes.d, + codes.b, codes.f, codes.c, codes.h, codes.a, codes.r], + CMAP_BEGIN_RANGE: [codes.b, codes.e, codes.g, codes.i, codes.n, + codes.b, codes.f, codes.r, codes.a, codes.n, codes.g, codes.e], + CMAP_END_RANGE: [codes.e, codes.n, codes.d, + codes.b, codes.f, codes.r, codes.a, codes.n, codes.g, codes.e], + AP_STREAM_TEXT_END: [codes.E, codes.T], +}; + +var __awaiter$1k = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class NaiveBytePatternSearch { + constructor(pattern) { + if (!(pattern === null || pattern === void 0 ? void 0 : pattern.length)) { + throw new Error("Pattern is empty"); + } + this._pattern = pattern; + } + *run(arr) { + const pattern = this._pattern; + if (!(arr === null || arr === void 0 ? void 0 : arr.length) || arr.length < pattern.length) { + return -1; + } + let found = false; + let i = 0; + let j = 0; + outer_loop: for (i; i < arr.length; i++) { + for (j = 0; j < pattern.length; j++) { + if (arr[i + j] !== pattern[j]) { + continue outer_loop; + } + } + found = true; + yield i; + } + if (!found) { + return -1; + } + } + *runBackwards(arr) { + const pattern = this._pattern; + if (!(arr === null || arr === void 0 ? void 0 : arr.length) || arr.length < pattern.length) { + return -1; + } + let found = false; + let i = arr.length - 1; + let j = 0; + const subMaxIndex = pattern.length - 1; + outer_loop: for (i; i >= 0; i--) { + for (j = 0; j < pattern.length; j++) { + if (arr[i - j] !== pattern[subMaxIndex - j]) { + continue outer_loop; + } + } + found = true; + yield i - j + 1; + } + if (!found) { + return -1; + } + } +} +class SyncDataParser { + get maxIndex() { + return this._maxIndex; + } + constructor(data) { + if (!(data === null || data === void 0 ? void 0 : data.length)) { + throw new Error("Data is empty"); + } + this._data = data; + this._maxIndex = data.length - 1; + } + static tryGetParser(data) { + try { + const parser = new SyncDataParser(data); + return parser; + } + catch (e) { + console.error(e); + return null; + } + } + static isRegularChar(code) { + if (isNaN(code)) { + return false; + } + return !this.delimiterChars.has(code) && !this.spaceChars.has(code); + } + static isNotRegularChar(code) { + if (isNaN(code)) { + return true; + } + return this.delimiterChars.has(code) || this.spaceChars.has(code); + } + static isDigit(code) { + return this.digitChars.has(code); + } + static isNewLineChar(code) { + return this.newLineChars.has(code); + } + static isSpaceChar(code) { + return this.spaceChars.has(code); + } + static isNotSpaceChar(code) { + return !this.spaceChars.has(code); + } + static isDelimiterChar(code) { + return this.delimiterChars.has(code); + } + static isNotDelimiterChar(code) { + return !this.delimiterChars.has(code); + } + destroy() { + } + getSubParserAsync(start, end) { + return __awaiter$1k(this, void 0, void 0, function* () { + return new SyncDataParser(yield this.sliceCharCodesAsync(start, end)); + }); + } + isOutside(index) { + return (index < 0 || index > this._maxIndex); + } + isCodeAtAsync(index, code) { + return __awaiter$1k(this, void 0, void 0, function* () { + return this.getCharCode(index) === code; + }); + } + getValueTypeAtAsync(start, skipEmpty = true) { + return __awaiter$1k(this, void 0, void 0, function* () { + if (skipEmpty) { + start = yield this.skipEmptyAsync(start); + } + if (this.isOutside(start)) { + return null; + } + const arr = this._data; + const i = start; + const charCode = arr[i]; + switch (charCode) { + case codes.SLASH: + if (SyncDataParser.isRegularChar(arr[i + 1])) { + return valueTypes.NAME; + } + return valueTypes.UNKNOWN; + case codes.L_BRACKET: + return valueTypes.ARRAY; + case codes.L_PARENTHESE: + return valueTypes.STRING_LITERAL; + case codes.LESS: + if (codes.LESS === arr[i + 1]) { + return valueTypes.DICTIONARY; + } + return valueTypes.STRING_HEX; + case codes.PERCENT: + return valueTypes.COMMENT; + case codes.D_0: + case codes.D_1: + case codes.D_2: + case codes.D_3: + case codes.D_4: + case codes.D_5: + case codes.D_6: + case codes.D_7: + case codes.D_8: + case codes.D_9: + const nextDelimIndex = yield this.findDelimiterIndexAsync(true, i + 1); + if (nextDelimIndex !== -1) { + const refEndIndex = yield this.findCharIndexAsync(codes.R, false, nextDelimIndex - 1); + if (refEndIndex !== -1 && refEndIndex > i && !SyncDataParser.isRegularChar(arr[refEndIndex + 1])) { + return valueTypes.REF; + } + } + return valueTypes.NUMBER; + case codes.DOT: + case codes.MINUS: + if (SyncDataParser.isDigit(arr[i + 1])) { + return valueTypes.NUMBER; + } + return valueTypes.UNKNOWN; + case codes.s: + if (arr[i + 1] === codes.t + && arr[i + 2] === codes.r + && arr[i + 3] === codes.e + && arr[i + 4] === codes.a + && arr[i + 5] === codes.m) { + return valueTypes.STREAM; + } + return valueTypes.UNKNOWN; + case codes.t: + if (arr[i + 1] === codes.r + && arr[i + 2] === codes.u + && arr[i + 3] === codes.e) { + return valueTypes.BOOLEAN; + } + return valueTypes.UNKNOWN; + case codes.f: + if (arr[i + 1] === codes.a + && arr[i + 2] === codes.l + && arr[i + 3] === codes.s + && arr[i + 4] === codes.e) { + return valueTypes.BOOLEAN; + } + return valueTypes.UNKNOWN; + default: + return valueTypes.UNKNOWN; + } + }); + } + findSubarrayIndexAsync(sub, options) { + var _a, _b, _c; + return __awaiter$1k(this, void 0, void 0, function* () { + const arr = this._data; + if (!(sub === null || sub === void 0 ? void 0 : sub.length)) { + return null; + } + const direction = (_a = options === null || options === void 0 ? void 0 : options.direction) !== null && _a !== void 0 ? _a : true; + const minIndex = Math.max(Math.min((_b = options === null || options === void 0 ? void 0 : options.minIndex) !== null && _b !== void 0 ? _b : 0, this._maxIndex), 0); + const maxIndex = Math.max(Math.min((_c = options === null || options === void 0 ? void 0 : options.maxIndex) !== null && _c !== void 0 ? _c : this._maxIndex, this._maxIndex), 0); + const allowOpened = !(options === null || options === void 0 ? void 0 : options.closedOnly); + const searcher = new NaiveBytePatternSearch(sub); + let start; + let end; + let foundIndexGen; + if (direction) { + foundIndexGen = searcher.run(arr.subarray(minIndex, maxIndex + 1)); + } + else { + foundIndexGen = searcher.runBackwards(arr.subarray(minIndex, maxIndex + 1)); + } + for (const i of foundIndexGen) { + if (i === -1) { + return null; + } + start = i + minIndex; + end = start + sub.length - 1; + if (allowOpened || end === maxIndex || !SyncDataParser.isRegularChar(arr[end + 1])) { + return { start, end }; + } + } + return null; + }); + } + findCharIndexAsync(charCode, direction = true, start) { + return __awaiter$1k(this, void 0, void 0, function* () { + const arr = this._data; + let i = isNaN(start) + ? direction + ? 0 + : this._maxIndex + : start; + if (direction) { + for (i; i <= this._maxIndex; i++) { + if (arr[i] === charCode) { + return i; + } + } + } + else { + for (i; i >= 0; i--) { + if (arr[i] === charCode) { + return i; + } + } + } + return -1; + }); + } + findNewLineIndexAsync(direction = true, start) { + return __awaiter$1k(this, void 0, void 0, function* () { + let lineBreakIndex; + const arr = this._data; + let i = isNaN(start) + ? direction + ? 0 + : this._maxIndex + : start; + if (direction) { + for (i; i <= this._maxIndex; i++) { + if (SyncDataParser.isNewLineChar(arr[i])) { + lineBreakIndex = i; + break; + } + } + } + else { + for (i; i >= 0; i--) { + if (SyncDataParser.isNewLineChar(arr[i])) { + lineBreakIndex = i; + break; + } + } + } + if (lineBreakIndex === undefined) { + return -1; + } + if (direction) { + if (this._data[lineBreakIndex] === codes.CARRIAGE_RETURN + && this._data[lineBreakIndex + 1] === codes.LINE_FEED) { + lineBreakIndex++; + } + return Math.min(lineBreakIndex + 1, this._maxIndex); + } + else { + if (this._data[lineBreakIndex] === codes.LINE_FEED + && this._data[lineBreakIndex - 1] === codes.CARRIAGE_RETURN) { + lineBreakIndex--; + } + return Math.max(lineBreakIndex - 1, 0); + } + }); + } + findSpaceIndexAsync(direction = true, start) { + return __awaiter$1k(this, void 0, void 0, function* () { + const arr = this._data; + let i = isNaN(start) + ? direction + ? 0 + : this._maxIndex + : start; + if (direction) { + for (i; i <= this._maxIndex; i++) { + if (SyncDataParser.isSpaceChar(arr[i])) { + return i; + } + } + } + else { + for (i; i >= 0; i--) { + if (SyncDataParser.isSpaceChar(arr[i])) { + return i; + } + } + } + return -1; + }); + } + findNonSpaceIndexAsync(direction = true, start) { + return __awaiter$1k(this, void 0, void 0, function* () { + const arr = this._data; + let i = isNaN(start) + ? direction + ? 0 + : this._maxIndex + : start; + if (direction) { + for (i; i <= this._maxIndex; i++) { + if (SyncDataParser.isNotSpaceChar(arr[i])) { + return i; + } + } + } + else { + for (i; i >= 0; i--) { + if (SyncDataParser.isNotSpaceChar(arr[i])) { + return i; + } + } + } + return -1; + }); + } + findDelimiterIndexAsync(direction = true, start) { + return __awaiter$1k(this, void 0, void 0, function* () { + const arr = this._data; + let i = isNaN(start) + ? direction + ? 0 + : this._maxIndex + : start; + if (direction) { + for (i; i <= this._maxIndex; i++) { + if (SyncDataParser.isDelimiterChar(arr[i])) { + return i; + } + } + } + else { + for (i; i >= 0; i--) { + if (SyncDataParser.isDelimiterChar(arr[i])) { + return i; + } + } + } + return -1; + }); + } + findNonDelimiterIndexAsync(direction = true, start) { + return __awaiter$1k(this, void 0, void 0, function* () { + const arr = this._data; + let i = isNaN(start) + ? direction + ? 0 + : this._maxIndex + : start; + if (direction) { + for (i; i <= this._maxIndex; i++) { + if (SyncDataParser.isNotDelimiterChar(arr[i])) { + return i; + } + } + } + else { + for (i; i >= 0; i--) { + if (SyncDataParser.isNotDelimiterChar(arr[i])) { + return i; + } + } + } + return -1; + }); + } + findRegularIndexAsync(direction = true, start) { + return __awaiter$1k(this, void 0, void 0, function* () { + const arr = this._data; + let i = isNaN(start) + ? direction + ? 0 + : this._maxIndex + : start; + if (direction) { + for (i; i <= this._maxIndex; i++) { + if (SyncDataParser.isRegularChar(arr[i])) { + return i; + } + } + } + else { + for (i; i >= 0; i--) { + if (SyncDataParser.isRegularChar(arr[i])) { + return i; + } + } + } + return -1; + }); + } + findIrregularIndexAsync(direction = true, start) { + return __awaiter$1k(this, void 0, void 0, function* () { + const arr = this._data; + let i = isNaN(start) + ? direction + ? 0 + : this._maxIndex + : start; + if (direction) { + for (i; i <= this._maxIndex; i++) { + if (SyncDataParser.isNotRegularChar(arr[i])) { + return i; + } + } + } + else { + for (i; i >= 0; i--) { + if (SyncDataParser.isNotRegularChar(arr[i])) { + return i; + } + } + } + return -1; + }); + } + getIndirectObjectBoundsAtAsync(start, skipEmpty = true) { + return __awaiter$1k(this, void 0, void 0, function* () { + if (skipEmpty) { + start = yield this.skipEmptyAsync(start); + } + if (this.isOutside(start)) { + return null; + } + const objStartIndex = yield this.findSubarrayIndexAsync(keywordCodes.OBJ, { minIndex: start, closedOnly: true }); + if (!objStartIndex) { + return null; + } + let contentStart = yield this.findNonSpaceIndexAsync(true, objStartIndex.end + 1); + if (contentStart === -1) { + return null; + } + const objEndIndex = yield this.findSubarrayIndexAsync(keywordCodes.OBJ_END, { minIndex: contentStart, closedOnly: true }); + if (!objEndIndex) { + return null; + } + let contentEnd = yield this.findNonSpaceIndexAsync(false, objEndIndex.start - 1); + if (this.getCharCode(contentStart) === codes.LESS + && this.getCharCode(contentStart + 1) === codes.LESS + && this.getCharCode(contentEnd - 1) === codes.GREATER + && this.getCharCode(contentEnd) === codes.GREATER) { + contentStart += 2; + contentEnd -= 2; + } + return { + start: objStartIndex.start, + end: objEndIndex.end, + contentStart, + contentEnd, + }; + }); + } + getXrefTableBoundsAtAsync(start, skipEmpty = true) { + return __awaiter$1k(this, void 0, void 0, function* () { + if (skipEmpty) { + start = yield this.skipEmptyAsync(start); + } + if (this.isOutside(start) || this._data[start] !== codes.x) { + return null; + } + const xrefStart = yield this.findSubarrayIndexAsync(keywordCodes.XREF_TABLE, { minIndex: start }); + if (!xrefStart) { + return null; + } + const contentStart = yield this.findNonSpaceIndexAsync(true, xrefStart.end + 1); + if (contentStart === -1) { + return null; + } + const xrefEnd = yield this.findSubarrayIndexAsync(keywordCodes.TRAILER, { minIndex: xrefStart.end + 1 }); + if (!xrefEnd) { + return null; + } + const contentEnd = yield this.findNonSpaceIndexAsync(false, xrefEnd.start - 1); + if (contentEnd < contentStart) { + return null; + } + return { + start: xrefStart.start, + end: xrefEnd.end, + contentStart, + contentEnd, + }; + }); + } + getDictBoundsAtAsync(start, skipEmpty = true) { + return __awaiter$1k(this, void 0, void 0, function* () { + if (skipEmpty) { + start = yield this.skipEmptyAsync(start); + } + if (this.isOutside(start) + || this._data[start] !== codes.LESS + || this._data[start + 1] !== codes.LESS) { + return null; + } + const contentStart = yield this.findNonSpaceIndexAsync(true, start + 2); + if (contentStart === -1) { + return null; + } + let dictOpened = 1; + let dictBound = true; + let literalOpened = 0; + let i = contentStart; + let code; + let prevCode; + while (dictOpened) { + prevCode = code; + code = this._data[i++]; + if (code === codes.L_PARENTHESE + && (!literalOpened || prevCode !== codes.BACKSLASH)) { + literalOpened++; + } + if (code === codes.R_PARENTHESE + && (literalOpened && prevCode !== codes.BACKSLASH)) { + literalOpened--; + } + if (literalOpened) { + continue; + } + if (!dictBound) { + if (code === codes.LESS && code === prevCode) { + dictOpened++; + dictBound = true; + } + else if (code === codes.GREATER && code === prevCode) { + dictOpened--; + dictBound = true; + } + } + else { + dictBound = false; + } + } + const end = i - 1; + const contentEnd = yield this.findNonSpaceIndexAsync(false, end - 2); + if (contentEnd < contentStart) { + return { + start, + end, + }; + } + return { + start, + end, + contentStart, + contentEnd, + }; + }); + } + getArrayBoundsAtAsync(start, skipEmpty = true) { + return __awaiter$1k(this, void 0, void 0, function* () { + if (skipEmpty) { + start = yield this.skipEmptyAsync(start); + } + if (this.isOutside(start) || this._data[start] !== codes.L_BRACKET) { + return null; + } + let arraysOpened = 1; + let i = start + 1; + let code; + while (arraysOpened) { + code = this._data[i++]; + if (code === codes.L_BRACKET) { + arraysOpened++; + } + else if (code === codes.R_BRACKET) { + arraysOpened--; + } + } + const arrayEnd = i - 1; + if (arrayEnd - start < 1) { + return null; + } + return { start, end: arrayEnd }; + }); + } + getHexBoundsAtAsync(start, skipEmpty = true) { + return __awaiter$1k(this, void 0, void 0, function* () { + if (skipEmpty) { + start = yield this.skipEmptyAsync(start); + } + if (this.isOutside(start) || this.getCharCode(start) !== codes.LESS) { + return null; + } + const end = yield this.findCharIndexAsync(codes.GREATER, true, start + 1); + if (end === -1) { + return null; + } + return { start, end }; + }); + } + getLiteralBoundsAtAsync(start, skipEmpty = true) { + return __awaiter$1k(this, void 0, void 0, function* () { + if (skipEmpty) { + start = yield this.skipEmptyAsync(start); + } + if (this.isOutside(start) || this.getCharCode(start) !== codes.L_PARENTHESE) { + return null; + } + let i = start; + let code; + let escaped = false; + let opened = 0; + while (opened || code !== codes.R_PARENTHESE || escaped) { + if (i > this._maxIndex) { + return null; + } + code = this.getCharCode(i++); + if (!escaped) { + if (code === codes.L_PARENTHESE) { + opened += 1; + } + else if (opened && code === codes.R_PARENTHESE) { + opened -= 1; + } + } + if (!escaped && code === codes.BACKSLASH) { + escaped = true; + } + else { + escaped = false; + } + } + return { start, end: i - 1 }; + }); + } + parseNumberAtAsync(start, float = false, skipEmpty = true) { + return __awaiter$1k(this, void 0, void 0, function* () { + if (skipEmpty) { + start = yield this.skipEmptyAsync(start); + } + if (this.isOutside(start) || !SyncDataParser.isRegularChar(this._data[start])) { + return null; + } + let i = start; + let numberStr = ""; + let value = this._data[i]; + if (value === codes.MINUS) { + numberStr += "-"; + value = this._data[++i]; + } + else if (value === codes.DOT) { + numberStr += "0."; + value = this._data[++i]; + } + while (SyncDataParser.isDigit(value) + || (float && value === codes.DOT)) { + numberStr += String.fromCharCode(value); + value = this._data[++i]; + } + return numberStr + ? { value: +numberStr, start, end: i - 1 } + : null; + }); + } + parseNameAtAsync(start, includeSlash = true, skipEmpty = true) { + return __awaiter$1k(this, void 0, void 0, function* () { + if (skipEmpty) { + start = yield this.skipEmptyAsync(start); + } + if (this.isOutside(start) || this._data[start] !== codes.SLASH) { + return null; + } + let i = start + 1; + let result = includeSlash + ? "/" + : ""; + let value = this._data[i]; + while (SyncDataParser.isRegularChar(value)) { + result += String.fromCharCode(value); + value = this._data[++i]; + } + return result.length > 1 + ? { value: result, start, end: i - 1 } + : null; + }); + } + parseStringAtAsync(start, skipEmpty = true) { + return __awaiter$1k(this, void 0, void 0, function* () { + if (skipEmpty) { + start = yield this.skipEmptyAsync(start); + } + if (this.isOutside(start)) { + return null; + } + let i = start; + let result = ""; + let value = this._data[i]; + while (SyncDataParser.isRegularChar(value)) { + result += String.fromCharCode(value); + value = this._data[++i]; + } + return result.length !== 0 + ? { value: result, start, end: i - 1 } + : null; + }); + } + parseBoolAtAsync(start, skipEmpty = true) { + return __awaiter$1k(this, void 0, void 0, function* () { + if (skipEmpty) { + start = yield this.skipEmptyAsync(start); + } + if (this.isOutside(start)) { + return null; + } + const nearestDelimiter = yield this.findDelimiterIndexAsync(true, start); + const isTrue = yield this.findSubarrayIndexAsync(keywordCodes.TRUE, { + minIndex: start, + maxIndex: nearestDelimiter === -1 ? this._maxIndex : nearestDelimiter, + }); + if (isTrue) { + return { value: true, start, end: isTrue.end }; + } + const isFalse = yield this.findSubarrayIndexAsync(keywordCodes.FALSE, { + minIndex: start, + maxIndex: nearestDelimiter === -1 ? this._maxIndex : nearestDelimiter, + }); + if (isFalse) { + return { value: false, start, end: isFalse.end }; + } + return null; + }); + } + parseNumberArrayAtAsync(start, float = true, skipEmpty = true) { + return __awaiter$1k(this, void 0, void 0, function* () { + const arrayBounds = yield this.getArrayBoundsAtAsync(start, skipEmpty); + if (!arrayBounds) { + return null; + } + const numbers = []; + let current; + let i = arrayBounds.start + 1; + while (i < arrayBounds.end) { + current = yield this.parseNumberAtAsync(i, float, true); + if (!current) { + break; + } + numbers.push(current.value); + i = current.end + 1; + } + return { value: numbers, start: arrayBounds.start, end: arrayBounds.end }; + }); + } + parseNameArrayAtAsync(start, includeSlash = true, skipEmpty = true) { + return __awaiter$1k(this, void 0, void 0, function* () { + const arrayBounds = yield this.getArrayBoundsAtAsync(start, skipEmpty); + if (!arrayBounds) { + return null; + } + const names = []; + let current; + let i = arrayBounds.start + 1; + while (i < arrayBounds.end) { + current = yield this.parseNameAtAsync(i, includeSlash, true); + if (!current) { + break; + } + names.push(current.value); + i = current.end + 1; + } + return { value: names, start: arrayBounds.start, end: arrayBounds.end }; + }); + } + parseDictTypeAsync(bounds) { + return __awaiter$1k(this, void 0, void 0, function* () { + return yield this.parseDictPropertyByNameAsync(keywordCodes.TYPE, bounds); + }); + } + parseDictSubtypeAsync(bounds) { + return __awaiter$1k(this, void 0, void 0, function* () { + return yield this.parseDictPropertyByNameAsync(keywordCodes.SUBTYPE, bounds); + }); + } + parseDictPropertyByNameAsync(propName, bounds) { + var _a, _b; + return __awaiter$1k(this, void 0, void 0, function* () { + const arr = this._data; + if (!(propName === null || propName === void 0 ? void 0 : propName.length)) { + return null; + } + const minIndex = Math.max(Math.min((_a = bounds.start) !== null && _a !== void 0 ? _a : 0, this._maxIndex), 0); + const maxIndex = Math.max(Math.min((_b = bounds.end) !== null && _b !== void 0 ? _b : this._maxIndex, this._maxIndex), 0); + let propNameBounds; + let i = minIndex; + let j; + let code; + let prevCode; + let dictOpened = 0; + let dictBound = true; + let literalOpened = 0; + outer_loop: for (i; i <= maxIndex; i++) { + prevCode = code; + code = arr[i]; + if (code === codes.L_PARENTHESE + && (!literalOpened || prevCode !== codes.BACKSLASH)) { + literalOpened++; + } + if (code === codes.R_PARENTHESE + && (literalOpened && prevCode !== codes.BACKSLASH)) { + literalOpened--; + } + if (literalOpened) { + continue; + } + if (!dictBound) { + if (code === codes.LESS && code === prevCode) { + dictOpened++; + dictBound = true; + } + else if (code === codes.GREATER && code === prevCode) { + dictOpened--; + dictBound = true; + } + } + else { + dictBound = false; + } + for (j = 0; j < propName.length; j++) { + if (arr[i + j] !== propName[j]) { + continue outer_loop; + } + } + if (dictOpened !== 1) { + continue; + } + if (!SyncDataParser.isRegularChar(arr[i + j])) { + propNameBounds = { start: i, end: i + j - 1 }; + break; + } + } + if (!propNameBounds) { + return null; + } + const type = yield this.parseNameAtAsync(propNameBounds.end + 1); + if (!type) { + return null; + } + return type.value; + }); + } + skipEmptyAsync(start) { + return __awaiter$1k(this, void 0, void 0, function* () { + let index = yield this.findNonSpaceIndexAsync(true, start); + if (index === -1) { + return -1; + } + if (this._data[index] === codes.PERCENT) { + const afterComment = yield this.findNewLineIndexAsync(true, index + 1); + if (afterComment === -1) { + return -1; + } + index = yield this.findNonSpaceIndexAsync(true, afterComment); + } + return index; + }); + } + skipToNextNameAsync(start, max) { + return __awaiter$1k(this, void 0, void 0, function* () { + start || (start = 0); + max = max + ? Math.min(max, this._maxIndex) + : 0; + if (max < start) { + return -1; + } + let i = start; + while (i <= max) { + const value = yield this.getValueTypeAtAsync(i, true); + if (value) { + let skipValueBounds; + switch (value) { + case valueTypes.DICTIONARY: + skipValueBounds = yield this.getDictBoundsAtAsync(i, false); + break; + case valueTypes.ARRAY: + skipValueBounds = yield this.getArrayBoundsAtAsync(i, false); + break; + case valueTypes.STRING_LITERAL: + skipValueBounds = yield this.getLiteralBoundsAtAsync(i, false); + break; + case valueTypes.STRING_HEX: + skipValueBounds = yield this.getHexBoundsAtAsync(i, false); + break; + case valueTypes.NUMBER: + const numberParseResult = yield this.parseNumberAtAsync(i, true, false); + if (numberParseResult) { + skipValueBounds = numberParseResult; + } + break; + case valueTypes.BOOLEAN: + const boolParseResult = yield this.parseBoolAtAsync(i, false); + if (boolParseResult) { + skipValueBounds = boolParseResult; + } + break; + case valueTypes.COMMENT: + break; + case valueTypes.NAME: + return i; + default: + i++; + continue; + } + if (skipValueBounds) { + i = skipValueBounds.end + 1; + skipValueBounds = null; + continue; + } + } + i++; + } + return -1; + }); + } + sliceCharCodesAsync(start, end) { + return __awaiter$1k(this, void 0, void 0, function* () { + return this._data.slice(start, (end || start) + 1); + }); + } + sliceCharsAsync(start, end) { + return __awaiter$1k(this, void 0, void 0, function* () { + return String.fromCharCode(...this._data.slice(start, (end || start) + 1)); + }); + } + getCharCode(index) { + return this._data[index]; + } +} +SyncDataParser.EOL = [ + codes.CARRIAGE_RETURN, + codes.LINE_FEED, +]; +SyncDataParser.delimiterChars = new Set([ + codes.PERCENT, + codes.L_PARENTHESE, + codes.R_PARENTHESE, + codes.SLASH, + codes.LESS, + codes.GREATER, + codes.L_BRACKET, + codes.R_BRACKET, + codes.L_BRACE, + codes.R_BRACE, +]); +SyncDataParser.spaceChars = new Set([ + codes.NULL, + codes.HORIZONTAL_TAB, + codes.LINE_FEED, + codes.FORM_FEED, + codes.CARRIAGE_RETURN, + codes.WHITESPACE, +]); +SyncDataParser.digitChars = new Set([ + codes.D_0, + codes.D_1, + codes.D_2, + codes.D_3, + codes.D_4, + codes.D_5, + codes.D_6, + codes.D_7, + codes.D_8, + codes.D_9, +]); +SyncDataParser.newLineChars = new Set([ + codes.CARRIAGE_RETURN, + codes.LINE_FEED, +]); + +class DataWriter { + get offset() { + return this._pointer; + } + constructor(data) { + this._dataToAppend = []; + if (!(data === null || data === void 0 ? void 0 : data.length)) { + throw new Error("Data is empty"); + } + this._encoder = new TextEncoder(); + this._sourceData = data.slice(0); + this._pointer = data.length; + this.fixEof(); + } + getCurrentData() { + const result = new Uint8Array(this._sourceData.length + this._dataToAppend.length); + result.set(this._sourceData, 0); + result.set(this._dataToAppend, this._sourceData.length); + return result; + } + writeBytes(bytes) { + if (!(bytes === null || bytes === void 0 ? void 0 : bytes.length)) { + return; + } + for (let i = 0; i < bytes.length; i++) { + this._dataToAppend.push(bytes[i]); + } + this._pointer += bytes.length; + } + writeIndirectObject(cryptInfo, obj) { + if (!(cryptInfo === null || cryptInfo === void 0 ? void 0 : cryptInfo.ref) || !obj) { + return; + } + const objBytes = [ + ...this._encoder.encode(`${cryptInfo.ref.id} ${cryptInfo.ref.generation} `), + ...keywordCodes.OBJ, ...keywordCodes.END_OF_LINE, + ...obj.toArray(cryptInfo), ...keywordCodes.END_OF_LINE, + ...keywordCodes.OBJ_END, ...keywordCodes.END_OF_LINE, + ]; + this.writeBytes(objBytes); + } + writeIndirectArray(cryptInfo, objs) { + if (!(cryptInfo === null || cryptInfo === void 0 ? void 0 : cryptInfo.ref) || !objs) { + return; + } + const objBytes = [ + ...this._encoder.encode(`${cryptInfo.ref.id} ${cryptInfo.ref.generation} `), + ...keywordCodes.OBJ, ...keywordCodes.END_OF_LINE, + codes.L_BRACKET, + ]; + for (const obj of objs) { + objBytes.push(codes.WHITESPACE, ...obj.toArray(cryptInfo)); + } + objBytes.push(codes.R_BRACKET, ...keywordCodes.END_OF_LINE, ...keywordCodes.OBJ_END, ...keywordCodes.END_OF_LINE); + this.writeBytes(objBytes); + } + writeEof(xrefOffset) { + const eof = [ + ...keywordCodes.XREF_START, ...keywordCodes.END_OF_LINE, + ...this._encoder.encode(xrefOffset + ""), ...keywordCodes.END_OF_LINE, + ...keywordCodes.END_OF_FILE, ...keywordCodes.END_OF_LINE + ]; + this.writeBytes(eof); + } + fixEof() { + if (this._sourceData[this._pointer - 1] !== codes.LINE_FEED) { + if (this._sourceData[this._pointer - 2] !== codes.CARRIAGE_RETURN) { + this._dataToAppend.push(codes.CARRIAGE_RETURN, codes.LINE_FEED); + this._pointer += 2; + } + else { + this._dataToAppend.push(codes.LINE_FEED); + this._pointer += 1; + } + } + } +} + +class XRefEntry { + constructor(type, id, generation, byteOffset, nextFreeId, streamId, streamIndex) { + this.type = type; + this.id = id; + this.generation = generation; + this.byteOffset = byteOffset; + this.nextFreeId = nextFreeId; + this.streamId = streamId; + this.streamIndex = streamIndex; + } + static isDigit(code) { + return this.digitChars.has(code); + } + static *fromTableBytes(bytes) { + let i = 0; + let j = 0; + while (i < bytes.length) { + const firstIndexBytes = []; + let firstIndexDigit = bytes[i++]; + while (XRefEntry.isDigit(firstIndexDigit)) { + firstIndexBytes.push(firstIndexDigit); + firstIndexDigit = bytes[i++]; + } + let firstIndex = parseInt(firstIndexBytes.map(x => String.fromCharCode(x)).join(""), 10); + const countBytes = []; + let countDigit = bytes[i++]; + while (XRefEntry.isDigit(countDigit)) { + countBytes.push(countDigit); + countDigit = bytes[i++]; + } + const count = parseInt(countBytes.map(x => String.fromCharCode(x)).join(""), 10); + while (!XRefEntry.isDigit(bytes[i])) { + i++; + } + for (j = 0; j < count; j++) { + const value = parseInt(Array.from(bytes.subarray(i, i + 10)) + .map(x => String.fromCharCode(x)).join(""), 10); + i += 11; + const gen = parseInt(Array.from(bytes.subarray(i, i + 5)) + .map(x => String.fromCharCode(x)).join(""), 10); + i += 6; + const typeByte = bytes[i]; + if (typeByte === codes.f) { + yield new XRefEntry(xRefEntryTypes.FREE, firstIndex++, gen, null, value); + } + else if (typeByte === codes.n) { + yield new XRefEntry(xRefEntryTypes.NORMAL, firstIndex++, gen, value); + } + i += 3; + } + } + return; + } + static *fromStreamBytes(bytes, w, index) { + const [w1, w2, w3] = w; + const entryLength = w1 + w2 + w3; + if (bytes.length % entryLength) { + throw new Error("Incorrect stream length"); + } + const count = bytes.length / entryLength; + const ids = new Array(count); + if (index === null || index === void 0 ? void 0 : index.length) { + let id; + let n; + let m = 0; + for (let k = 0; k < index.length; k++) { + if (!(k % 2)) { + id = index[k]; + } + else { + for (n = 0; n < index[k]; n++) { + ids[m++] = id + n; + } + } + } + } + else { + let l = 0; + while (l < count) { + ids[l++] = l; + } + } + let i = 0; + let j = 0; + let type; + let value1; + let value2; + while (i < bytes.length) { + type = w1 + ? ByteUtils.parseIntFromBytes(bytes.slice(i, i + w1)) + : 1; + i += w1; + value1 = ByteUtils.parseIntFromBytes(bytes.slice(i, i + w2)); + i += w2; + value2 = w3 + ? ByteUtils.parseIntFromBytes(bytes.slice(i, i + w3)) + : null; + i += w3; + switch (type) { + case xRefEntryTypes.FREE: + yield new XRefEntry(xRefEntryTypes.FREE, ids[j++], value2 !== null && value2 !== void 0 ? value2 : maxGeneration, null, value1); + break; + case xRefEntryTypes.NORMAL: + yield new XRefEntry(xRefEntryTypes.NORMAL, ids[j++], value2 !== null && value2 !== void 0 ? value2 : 0, value1); + break; + case xRefEntryTypes.COMPRESSED: + yield new XRefEntry(xRefEntryTypes.COMPRESSED, ids[j++], 0, null, null, value1, value2); + break; + } + } + return; + } + static toTableBytes(entries) { + if (!(entries === null || entries === void 0 ? void 0 : entries.length)) { + return null; + } + const encoder = new TextEncoder(); + const groups = this.groupEntries(entries); + let bytes = new Uint8Array(); + let temp; + let line; + for (const group of groups) { + line = `${group[0]} ${group[1].length}\r\n`; + temp = new Uint8Array(bytes.length + line.length); + temp.set(bytes); + temp.set(encoder.encode(line), bytes.length); + bytes = temp; + for (const entry of group[1]) { + switch (entry.type) { + case xRefEntryTypes.FREE: + line = `${entry.nextFreeId.toString().padStart(10, "0")} ${entry.generation.toString().padStart(5, "0")} f\r\n`; + break; + case xRefEntryTypes.NORMAL: + line = `${entry.byteOffset.toString().padStart(10, "0")} ${entry.generation.toString().padStart(5, "0")} n\r\n`; + break; + default: + continue; + } + temp = new Uint8Array(bytes.length + line.length); + temp.set(bytes); + temp.set(encoder.encode(line), bytes.length); + bytes = temp; + } + } + return bytes; + } + static toStreamBytes(entries, w = [1, 4, 2]) { + if (!(entries === null || entries === void 0 ? void 0 : entries.length)) { + return null; + } + if (Math.min(...w) < 0) { + throw new Error("Negative length values are not permitted"); + } + let [w1, w2, w3] = w; + w1 !== null && w1 !== void 0 ? w1 : (w1 = 0); + w2 !== null && w2 !== void 0 ? w2 : (w2 = 4); + w3 !== null && w3 !== void 0 ? w3 : (w3 = 0); + const entryLength = w1 + w2 + w3; + let w1ToBytesFunc; + let w2ToBytesFunc; + let w3ToBytesFunc; + switch (w1) { + case 0: + w1ToBytesFunc = () => new Uint8Array(); + break; + case 1: + w1ToBytesFunc = ByteUtils.int8ToBytes; + break; + case 2: + w1ToBytesFunc = ByteUtils.int16ToBytes; + break; + default: + w2ToBytesFunc = (n) => new Uint8Array([...new Array(w1 - 2) + .fill(0), ...ByteUtils.int16ToBytes(n)]); + break; + } + switch (w2) { + case 1: + w2ToBytesFunc = ByteUtils.int8ToBytes; + break; + case 2: + w2ToBytesFunc = ByteUtils.int16ToBytes; + break; + case 3: + w2ToBytesFunc = (n) => new Uint8Array([0, ...ByteUtils.int16ToBytes(n)]); + break; + case 4: + w2ToBytesFunc = ByteUtils.int32ToBytes; + break; + default: + w2ToBytesFunc = (n) => new Uint8Array([...new Array(w1 - 4) + .fill(0), ...ByteUtils.int32ToBytes(n)]); + break; + } + switch (w3) { + case 0: + w3ToBytesFunc = () => new Uint8Array(); + break; + case 1: + w3ToBytesFunc = ByteUtils.int8ToBytes; + break; + case 2: + w3ToBytesFunc = ByteUtils.int16ToBytes; + break; + default: + w2ToBytesFunc = (n) => new Uint8Array([...new Array(w1 - 2) + .fill(0), ...ByteUtils.int16ToBytes(n)]); + break; + } + new TextEncoder(); + const groups = this.groupEntries(entries); + const index = []; + let bytes = new Uint8Array(); + let temp; + let entryV1; + let entryV2; + let entryV3; + for (const group of groups) { + index.push(group[0], group[1].length); + for (const entry of group[1]) { + switch (entry.type) { + case xRefEntryTypes.FREE: + entryV1 = w1ToBytesFunc(0); + entryV2 = w2ToBytesFunc(entry.nextFreeId); + entryV3 = w3ToBytesFunc(entry.generation); + break; + case xRefEntryTypes.NORMAL: + entryV1 = w1ToBytesFunc(1); + entryV2 = w2ToBytesFunc(entry.byteOffset); + entryV3 = w3ToBytesFunc(entry.generation); + break; + case xRefEntryTypes.COMPRESSED: + entryV1 = w1ToBytesFunc(2); + entryV2 = w2ToBytesFunc(entry.streamId); + entryV3 = w3ToBytesFunc(entry.streamIndex); + break; + default: + continue; + } + temp = new Uint8Array(bytes.length + entryLength); + temp.set(bytes); + temp.set(entryV1, bytes.length); + temp.set(entryV2, bytes.length + w1); + temp.set(entryV3, bytes.length + w1 + w2); + bytes = temp; + } + } + return { bytes, index }; + } + static groupEntries(entries) { + entries.sort((a, b) => a.id - b.id); + const groups = []; + let groupStart; + let groupEntries; + let last; + for (const entry of entries) { + if (entry.id !== last + 1) { + if (groupEntries === null || groupEntries === void 0 ? void 0 : groupEntries.length) { + groups.push([groupStart, groupEntries]); + } + groupStart = entry.id; + groupEntries = [entry]; + } + else { + groupEntries.push(entry); + } + last = entry.id; + } + if (groupEntries === null || groupEntries === void 0 ? void 0 : groupEntries.length) { + groups.push([groupStart, groupEntries]); + } + return groups; + } +} +XRefEntry.digitChars = new Set([ + codes.D_0, + codes.D_1, + codes.D_2, + codes.D_3, + codes.D_4, + codes.D_5, + codes.D_6, + codes.D_7, + codes.D_8, + codes.D_9, +]); + +class ReferenceDataChange { + get size() { + return this._size; + } + constructor(refData) { + this._refData = refData; + this._size = refData.size; + const freeLinkedList = new LinkedList(); + for (const freeRef of refData.freeLinkedList) { + freeLinkedList.push(Object.assign({}, freeRef)); + } + this._freeLinkedList = freeLinkedList; + this._usedMap = new Map(); + } + getUsedRef(id) { + return this._usedMap.get(id); + } + takeFreeRef(byteOffset, forceNew = false) { + let ref; + if (!forceNew && this._freeLinkedList.length > 1) { + const freeRef = this._freeLinkedList.pop(); + this._freeLinkedList.tail.nextFreeId = 0; + ref = { + id: freeRef.id, + generation: freeRef.generation, + byteOffset, + }; + } + else { + ref = { + id: this._size++, + generation: 0, + byteOffset, + }; + } + this._usedMap.set(ref.id, ref); + return ref; + } + setRefFree(id) { + if (this._usedMap.has(id)) { + this._usedMap.delete(id); + if (this._size > this._refData.size && this._size === id + 1) { + this._size--; + } + } + if (this._refData.isUsed(id)) { + const gen = this._refData.getGeneration(id); + const ref = { id: id, generation: gen + 1, nextFreeId: 0 }; + const index = this._freeLinkedList.findIndex(ref, (a, b) => a.id === b.id && a.generation <= b.generation); + if (index !== -1) { + return; + } + const lastFreeRef = this._freeLinkedList.tail; + lastFreeRef.nextFreeId = id; + this._freeLinkedList.push(ref); + } + } + updateUsedRef(ref) { + if (ref.compressed && ref.generation) { + throw new Error(`Compressed ref generation can't be greater than zero: '${ref.id} ${ref.generation} R'`); + } + if (this.isFreed(ref)) { + throw new Error(`The reference is freed: '${ref.id} ${ref.generation} R'`); + } + const current = this._usedMap.get(ref.id); + if (current) { + throw new Error(`Same reference has been issued twice: '${current.id} ${current.generation} R'`); + } + if (this._refData.isUsed(ref.id)) { + const gen = this._refData.getGeneration(ref.id); + if (ref.generation >= gen) { + this._usedMap.set(ref.id, ref); + return true; + } + throw new Error(`The reference has an old generation: '${current.id} ${current.generation} R'`); + } + throw new Error(`The reference is not used: '${current.id} ${current.generation} R'`); + } + exportEntries() { + const entries = []; + for (const entry of this._freeLinkedList) { + entries.push(new XRefEntry(xRefEntryTypes.FREE, entry.id, entry.generation, null, entry.nextFreeId)); + } + this._usedMap.forEach(v => { + if (v.compressed) { + entries.push(new XRefEntry(xRefEntryTypes.COMPRESSED, v.id, 0, null, null, v.streamId, v.streamIndex)); + } + else { + entries.push(new XRefEntry(xRefEntryTypes.NORMAL, v.id, v.generation, v.byteOffset)); + } + }); + return entries; + } + isFreed(ref) { + return this._freeLinkedList.has(ref, (a, b) => a.id === b.id && a.generation < b.generation); + } + isUsedInSource(id) { + return this._refData.isUsed(id); + } +} + +var __awaiter$1j = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class ObjectId { + constructor(id, generation) { + this.id = id !== null && id !== void 0 ? id : 0; + this.generation = generation !== null && generation !== void 0 ? generation : 0; + } + static parseAsync(parser, start, skipEmpty = true) { + return __awaiter$1j(this, void 0, void 0, function* () { + if (skipEmpty) { + start = yield parser.findRegularIndexAsync(true, start); + } + if (start < 0 || start > parser.maxIndex) { + return null; + } + const id = yield parser.parseNumberAtAsync(start, false, false); + if (!id || isNaN(id.value)) { + return null; + } + const generation = yield parser.parseNumberAtAsync(id.end + 2, false, false); + if (!generation || isNaN(generation.value)) { + return null; + } + return { + value: new ObjectId(id.value, generation.value), + start, + end: generation.end, + }; + }); + } + static parseRefAsync(parser, start, skipEmpty = true) { + return __awaiter$1j(this, void 0, void 0, function* () { + const id = yield ObjectId.parseAsync(parser, start, skipEmpty); + if (!id) { + return null; + } + const rIndexSupposed = id.end + 2; + const rIndex = yield parser.findSubarrayIndexAsync([codes.R], { minIndex: rIndexSupposed, closedOnly: true }); + if (!rIndex || rIndex.start !== rIndexSupposed) { + return null; + } + return { + value: id.value, + start: id.start, + end: rIndex.end, + }; + }); + } + static parseRefArrayAsync(parser, start, skipEmpty = true) { + return __awaiter$1j(this, void 0, void 0, function* () { + const arrayBounds = yield parser.getArrayBoundsAtAsync(start, skipEmpty); + if (!arrayBounds) { + return null; + } + const ids = []; + let current; + let i = arrayBounds.start + 1; + while (i < arrayBounds.end) { + current = yield ObjectId.parseRefAsync(parser, i, true); + if (!current) { + break; + } + ids.push(current.value); + i = current.end + 1; + } + return { value: ids, start: arrayBounds.start, end: arrayBounds.end }; + }); + } + static fromRef(ref) { + return new ObjectId(ref.id, ref.generation); + } + equals(other) { + return this.id === other.id + && this.generation === other.generation; + } + toArray(cryptInfo) { + return new TextEncoder().encode(`${this.id} ${this.generation} R`); + } + toString() { + return this.id + "|" + this.generation; + } +} + +var __awaiter$1i = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class DateString { + get source() { + return this._source; + } + get date() { + return new Date(this._date); + } + constructor(source, date) { + this._source = source; + this._date = new Date(date); + } + static parseAsync(parser, start, cryptInfo = null, skipEmpty = true) { + return __awaiter$1i(this, void 0, void 0, function* () { + if (skipEmpty) { + start = yield parser.skipEmptyAsync(start); + } + if (parser.isOutside(start) || !(yield parser.isCodeAtAsync(start, codes.L_PARENTHESE))) { + return null; + } + const end = yield parser.findCharIndexAsync(codes.R_PARENTHESE, true, start); + if (end === -1) { + return null; + } + let bytes = yield parser.sliceCharCodesAsync(start + 1, end - 1); + if ((cryptInfo === null || cryptInfo === void 0 ? void 0 : cryptInfo.ref) && cryptInfo.stringCryptor) { + bytes = cryptInfo.stringCryptor.decrypt(bytes, cryptInfo.ref); + } + try { + const date = DateString.fromArray(bytes); + return { value: date, start, end }; + } + catch (_a) { + return null; + } + }); + } + static fromDate(date) { + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, "0"); + const day = String(date.getDate()).padStart(2, "0"); + const hours = String(date.getHours()).padStart(2, "0"); + const minutes = String(date.getMinutes()).padStart(2, "0"); + const seconds = String(date.getSeconds()).padStart(2, "0"); + const source = `D:${year}${month}${day}${hours}${minutes}${seconds}`; + return new DateString(source, date); + } + static fromString(source) { + const result = /D:(?\d{4})(?\d{2})(?\d{2})(?\d{2})(?\d{2})(?\d{2})/.exec(source); + const date = new Date(+result.groups.Y, +result.groups.M - 1, +result.groups.D, +result.groups.h, +result.groups.m, +result.groups.s); + return new DateString(source, date); + } + static fromArray(arr) { + const source = new TextDecoder().decode(arr); + return DateString.fromString(source); + } + toArray(cryptInfo) { + let bytes = new TextEncoder().encode(this._source); + if ((cryptInfo === null || cryptInfo === void 0 ? void 0 : cryptInfo.ref) && cryptInfo.stringCryptor) { + bytes = cryptInfo.stringCryptor.encrypt(bytes, cryptInfo.ref); + } + return new Uint8Array([ + ...keywordCodes.STR_LITERAL_START, + ...bytes, + ...keywordCodes.STR_LITERAL_END, + ]); + } +} + +var __awaiter$1h = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class HexString { + get literal() { + return this._literal; + } + get hex() { + return this._hex.slice(); + } + get bytes() { + return this._bytes.slice(); + } + constructor(literal, hex, bytes) { + this._literal = literal; + this._hex = hex; + this._bytes = bytes; + } + static parseAsync(parser, start, cryptInfo = null, skipEmpty = true) { + return __awaiter$1h(this, void 0, void 0, function* () { + const bounds = yield parser.getHexBoundsAtAsync(start, skipEmpty); + if (!bounds) { + return null; + } + let bytes = yield parser.sliceCharCodesAsync(bounds.start + 1, bounds.end - 1); + if ((cryptInfo === null || cryptInfo === void 0 ? void 0 : cryptInfo.ref) && cryptInfo.stringCryptor) { + bytes = cryptInfo.stringCryptor.decrypt(bytes, cryptInfo.ref); + } + const hex = HexString.fromBytes(bytes); + return { value: hex, start: bounds.start, end: bounds.end }; + }); + } + static parseArrayAsync(parser, start, cryptInfo = null, skipEmpty = true) { + return __awaiter$1h(this, void 0, void 0, function* () { + const arrayBounds = yield parser.getArrayBoundsAtAsync(start, skipEmpty); + if (!arrayBounds) { + return null; + } + const hexes = []; + let current; + let i = arrayBounds.start + 1; + while (i < arrayBounds.end) { + current = yield HexString.parseAsync(parser, i, cryptInfo, skipEmpty); + if (!current) { + break; + } + hexes.push(current.value); + i = current.end + 1; + } + return { value: hexes, start: arrayBounds.start, end: arrayBounds.end }; + }); + } + static fromBytes(bytes) { + const literal = new TextDecoder().decode(bytes); + const hex = ByteUtils.hexStringToBytes(literal); + return new HexString(literal, hex, bytes); + } + static fromHexBytes(hex) { + let literal = ""; + hex.forEach(x => literal += x.toString(16).padStart(2, "0")); + const bytes = new TextEncoder().encode(literal); + return new HexString(literal, hex, bytes); + } + static fromString(literal) { + const hex = ByteUtils.hexStringToBytes(literal); + const bytes = new TextEncoder().encode(literal); + return new HexString(literal, hex, bytes); + } + ; + toArray(cryptInfo) { + return new Uint8Array([ + ...keywordCodes.STR_HEX_START, + ...this._bytes, + ...keywordCodes.STR_HEX_END, + ]); + } +} + +var __awaiter$1g = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class LiteralString { + get literal() { + return this._literal; + } + get bytes() { + return this._bytes.slice(); + } + constructor(literal, bytes) { + this._literal = literal; + this._bytes = bytes; + } + static parseAsync(parser, start, cryptInfo = null, skipEmpty = true) { + return __awaiter$1g(this, void 0, void 0, function* () { + const bounds = yield parser.getLiteralBoundsAtAsync(start, skipEmpty); + if (!bounds) { + return; + } + let bytes = LiteralString.unescape(yield parser.sliceCharCodesAsync(bounds.start + 1, bounds.end - 1)); + if ((cryptInfo === null || cryptInfo === void 0 ? void 0 : cryptInfo.ref) && cryptInfo.stringCryptor) { + bytes = cryptInfo.stringCryptor.decrypt(bytes, cryptInfo.ref); + } + const result = LiteralString.fromBytes(bytes); + return { value: result, start: bounds.start, end: bounds.end }; + }); + } + static parseArrayAsync(parser, start, cryptInfo = null, skipEmpty = true) { + return __awaiter$1g(this, void 0, void 0, function* () { + const arrayBounds = yield parser.getArrayBoundsAtAsync(start, skipEmpty); + if (!arrayBounds) { + return null; + } + const strings = []; + let current; + let i = arrayBounds.start + 1; + while (i < arrayBounds.end) { + current = yield LiteralString.parseAsync(parser, i, cryptInfo, skipEmpty); + if (!current) { + break; + } + strings.push(current.value); + i = current.end + 1; + } + return { value: strings, start: arrayBounds.start, end: arrayBounds.end }; + }); + } + static fromBytes(bytes) { + const decoder = bytes[0] === 254 && bytes[1] === 255 + ? new TextDecoder("utf-16be") + : new TextDecoder(); + const literal = decoder.decode(bytes); + return new LiteralString(literal, bytes); + } + static fromString(source) { + const bytes = []; + bytes.push(254, 255); + for (let i = 0; i < source.length; i++) { + const charCode = source.charCodeAt(i); + bytes.push((charCode & 0xFF00) >>> 8); + bytes.push(charCode & 0xFF); + } + return new LiteralString(source, new Uint8Array(bytes)); + } + static escape(bytes) { + const result = []; + for (let i = 0; i < bytes.length; i++) { + switch (bytes[i]) { + case codes.LINE_FEED: + result.push(codes.BACKSLASH); + result.push(codes.n); + break; + case codes.CARRIAGE_RETURN: + result.push(codes.BACKSLASH); + result.push(codes.r); + break; + case codes.HORIZONTAL_TAB: + result.push(codes.BACKSLASH); + result.push(codes.t); + break; + case codes.BACKSPACE: + result.push(codes.BACKSLASH); + result.push(codes.b); + break; + case codes.FORM_FEED: + result.push(codes.BACKSLASH); + result.push(codes.f); + break; + case codes.L_PARENTHESE: + result.push(codes.BACKSLASH); + result.push(codes.L_PARENTHESE); + break; + case codes.R_PARENTHESE: + result.push(codes.BACKSLASH); + result.push(codes.R_PARENTHESE); + break; + case codes.BACKSLASH: + result.push(codes.BACKSLASH); + result.push(codes.BACKSLASH); + break; + default: + result.push(bytes[i]); + break; + } + } + return new Uint8Array(result); + } + static unescape(bytes) { + const result = []; + let escaped = false; + for (let i = 0; i < bytes.length; i++) { + if (escaped) { + switch (bytes[i]) { + case codes.n: + result.push(codes.LINE_FEED); + break; + case codes.r: + result.push(codes.CARRIAGE_RETURN); + break; + case codes.t: + result.push(codes.HORIZONTAL_TAB); + break; + case codes.b: + result.push(codes.BACKSPACE); + break; + case codes.f: + result.push(codes.FORM_FEED); + break; + case codes.L_PARENTHESE: + result.push(codes.L_PARENTHESE); + break; + case codes.R_PARENTHESE: + result.push(codes.R_PARENTHESE); + break; + case codes.BACKSLASH: + result.push(codes.BACKSLASH); + break; + default: + result.push(bytes[i]); + break; + } + escaped = false; + continue; + } + if (bytes[i] === codes.BACKSLASH) { + escaped = true; + continue; + } + result.push(bytes[i]); + } + return new Uint8Array(result); + } + toArray(cryptInfo) { + const bytes = (cryptInfo === null || cryptInfo === void 0 ? void 0 : cryptInfo.ref) && cryptInfo.stringCryptor + ? cryptInfo.stringCryptor.encrypt(this._bytes, cryptInfo.ref) + : this._bytes; + return new Uint8Array([ + ...keywordCodes.STR_LITERAL_START, + ...LiteralString.escape(bytes), + ...keywordCodes.STR_LITERAL_END, + ]); + } +} + +var __awaiter$1f = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class PdfObject { + get sourceBytes() { + var _a; + return (_a = this._sourceBytes) === null || _a === void 0 ? void 0 : _a.slice(); + } + get sourceChars() { + return this._sourceBytes + ? String.fromCharCode(...this._sourceBytes.slice(0, this._sourceBytes.length)) + : ""; + } + get ref() { + return this._ref; + } + set ref(ref) { + this._ref = ref; + } + get id() { + var _a; + return (_a = this._ref) === null || _a === void 0 ? void 0 : _a.id; + } + get generation() { + var _a; + return (_a = this._ref) === null || _a === void 0 ? void 0 : _a.generation; + } + get added() { + return this._added; + } + get edited() { + return this._edited; + } + get deleted() { + return this._deleted; + } + constructor() { + this._added = false; + this._edited = false; + this._deleted = false; + this.onChange = { + set: (target, prop, value) => { + if (prop[0] !== "_" && prop[0] !== "$") { + this._edited || (this._edited = true); + if (this.$onChangeAction) { + this.$onChangeAction(); + } + } + target[prop] = value; + return true; + }, + }; + } + static getDataParserAsync(data) { + var _a; + return __awaiter$1f(this, void 0, void 0, function* () { + const parser = (_a = BgDataParser.tryGetParser(data.slice())) !== null && _a !== void 0 ? _a : SyncDataParser.tryGetParser(data); + return parser; + }); + } + markAsDeleted(value = true) { + this._deleted = value; + } + initProxy() { + const proxy = new Proxy(this, this.onChange); + this._proxy = proxy; + return proxy; + } + getProxy() { + return this._proxy || this; + } + encodePrimitiveArray(array, encoder) { + encoder || (encoder = new TextEncoder()); + const bytes = [codes.L_BRACKET]; + array.forEach(x => bytes.push(...encoder.encode(" " + x))); + bytes.push(codes.R_BRACKET); + return bytes; + } + encodeNestedPrimitiveArray(array, encoder) { + encoder || (encoder = new TextEncoder()); + const bytes = [codes.L_BRACKET]; + array.forEach(x => { + bytes.push(codes.L_BRACKET); + x.forEach(y => bytes.push(...encoder.encode(" " + y))); + bytes.push(codes.R_BRACKET); + }); + bytes.push(codes.R_BRACKET); + return bytes; + } + encodeSerializableArray(array, cryptInfo) { + const bytes = [codes.L_BRACKET]; + array.forEach(x => bytes.push(codes.WHITESPACE, ...x.toArray(cryptInfo))); + bytes.push(codes.R_BRACKET); + return bytes; + } + parseRefPropAsync(propName, parser, index) { + return __awaiter$1f(this, void 0, void 0, function* () { + const parsed = yield ObjectId.parseRefAsync(parser, index); + return this.setParsedProp(propName, parsed); + }); + } + parseRefArrayPropAsync(propName, parser, index) { + return __awaiter$1f(this, void 0, void 0, function* () { + const parsed = yield ObjectId.parseRefArrayAsync(parser, index); + return this.setParsedProp(propName, parsed); + }); + } + parseBoolPropAsync(propName, parser, index) { + return __awaiter$1f(this, void 0, void 0, function* () { + const parsed = yield parser.parseBoolAtAsync(index); + return this.setParsedProp(propName, parsed); + }); + } + parseNamePropAsync(propName, parser, index, includeSlash = true) { + return __awaiter$1f(this, void 0, void 0, function* () { + const parsed = yield parser.parseNameAtAsync(index, includeSlash); + return this.setParsedProp(propName, parsed); + }); + } + parseNameArrayPropAsync(propName, parser, index, includeSlash = true) { + return __awaiter$1f(this, void 0, void 0, function* () { + const parsed = yield parser.parseNameArrayAtAsync(index, includeSlash); + return this.setParsedProp(propName, parsed); + }); + } + parseNumberPropAsync(propName, parser, index, float = true) { + return __awaiter$1f(this, void 0, void 0, function* () { + const parsed = yield parser.parseNumberAtAsync(index, float); + return this.setParsedProp(propName, parsed); + }); + } + parseNumberArrayPropAsync(propName, parser, index, float = true) { + return __awaiter$1f(this, void 0, void 0, function* () { + const parsed = yield parser.parseNumberArrayAtAsync(index, float); + return this.setParsedProp(propName, parsed); + }); + } + parseDatePropAsync(propName, parser, index, cryptInfo) { + return __awaiter$1f(this, void 0, void 0, function* () { + const parsed = yield DateString.parseAsync(parser, index, cryptInfo); + return this.setParsedProp(propName, parsed); + }); + } + parseLiteralPropAsync(propName, parser, index, cryptInfo) { + return __awaiter$1f(this, void 0, void 0, function* () { + const parsed = yield LiteralString.parseAsync(parser, index, cryptInfo); + return this.setParsedProp(propName, parsed); + }); + } + parseHexPropAsync(propName, parser, index, cryptInfo) { + return __awaiter$1f(this, void 0, void 0, function* () { + const parsed = yield HexString.parseAsync(parser, index, cryptInfo); + return this.setParsedProp(propName, parsed); + }); + } + setParsedProp(propName, parsed) { + if (!parsed) { + throw new Error(`Can't parse ${propName} property value`); + } + this[propName.slice(1)] = parsed.value; + return parsed.end + 1; + } +} + +var __awaiter$1e = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class PdfDict extends PdfObject { + get streamId() { + return this._streamId; + } + constructor(type) { + super(); + this.Type = type; + } + toArray(cryptInfo) { + const encoder = new TextEncoder(); + const bytes = [...keywordCodes.DICT_START]; + if (this.Type) { + bytes.push(...keywordCodes.TYPE, ...encoder.encode(this.Type)); + } + bytes.push(...keywordCodes.DICT_END); + return new Uint8Array(bytes); + } + parsePropsAsync(parseInfo) { + var _a; + return __awaiter$1e(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parse info is empty"); + } + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + this._ref = (_a = parseInfo.cryptInfo) === null || _a === void 0 ? void 0 : _a.ref; + this._streamId = parseInfo.streamId; + this._sourceBytes = yield parser.sliceCharCodesAsync(start, end); + let i = yield parser.skipToNextNameAsync(start, end - 1); + if (i === -1) { + throw new Error("Dict is empty (has no properties)"); + } + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/Type": + const type = yield parser.parseNameAtAsync(i); + if (type) { + if (this.Type && this.Type !== type.value) { + throw new Error(`Ivalid dict type: '${type.value}' instead of '${this.Type}'`); + } + return; + } + throw new Error("Can't parse /Type property value"); + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + }); + } +} + +var __awaiter$1d = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class DecodeParamsDict extends PdfDict { + constructor() { + super(dictTypes.EMPTY); + this._intPropMap = new Map(); + this._boolPropMap = new Map(); + this._namePropMap = new Map(); + this._refPropMap = new Map(); + } + static parseAsync(parseInfo) { + return __awaiter$1d(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new DecodeParamsDict(); + yield pdfObject.parsePropsAsync(parseInfo); + return { value: pdfObject, start: parseInfo.bounds.start, end: parseInfo.bounds.end }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + static parseArrayAsync(parser, start, cryptInfo = null, skipEmpty = true) { + return __awaiter$1d(this, void 0, void 0, function* () { + const arrayBounds = yield parser.getArrayBoundsAtAsync(start, skipEmpty); + if (!arrayBounds) { + return null; + } + const paramsDicts = []; + let current; + let i = arrayBounds.start + 1; + while (i < arrayBounds.end) { + const paramsBounds = yield parser.getDictBoundsAtAsync(i); + current = yield DecodeParamsDict.parseAsync({ parser, bounds: paramsBounds, cryptInfo }); + if (!current) { + break; + } + paramsDicts.push(current.value); + i = current.end + 1; + } + return { value: paramsDicts, start: arrayBounds.start, end: arrayBounds.end }; + }); + } + getIntProp(name) { + return this._intPropMap.get(name); + } + getBoolProp(name) { + return this._boolPropMap.get(name); + } + getNameProp(name) { + return this._namePropMap.get(name); + } + getRefProp(name) { + return this._refPropMap.get(name); + } + setIntProp(name, value) { + return this._intPropMap.set(name, value); + } + setBoolProp(name, value) { + return this._boolPropMap.set(name, value); + } + setNameProp(name, value) { + return this._namePropMap.set(name, value); + } + setRefProp(name, value) { + return this._refPropMap.set(name, value); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + this._intPropMap.forEach((v, k) => bytes.push(...encoder.encode(k), ...encoder.encode(" " + v))); + this._boolPropMap.forEach((v, k) => bytes.push(...encoder.encode(k), ...encoder.encode(" " + v))); + this._namePropMap.forEach((v, k) => bytes.push(...encoder.encode(k), ...encoder.encode(v))); + this._refPropMap.forEach((v, k) => bytes.push(...encoder.encode(k), ...v.toArray(cryptInfo))); + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$1d(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + const valueType = yield parser.getValueTypeAtAsync(i); + switch (valueType) { + case valueTypes.NUMBER: + const intValue = yield parser.parseNumberAtAsync(i, false); + if (intValue) { + this._intPropMap.set(name, intValue.value); + i = intValue.end + 1; + continue; + } + break; + case valueTypes.BOOLEAN: + const boolValue = yield parser.parseBoolAtAsync(i); + if (boolValue) { + this._boolPropMap.set(name, boolValue.value); + i = boolValue.end + 1; + continue; + } + break; + case valueTypes.NAME: + const nameValue = yield parser.parseNameAtAsync(i); + if (nameValue) { + this._namePropMap.set(name, nameValue.value); + i = nameValue.end + 1; + continue; + } + break; + case valueTypes.REF: + const refValue = yield ObjectId.parseRefAsync(parser, i); + if (refValue) { + this._refPropMap.set(name, refValue.value); + i = refValue.end + 1; + continue; + } + break; + } + i = yield parser.skipToNextNameAsync(i, end - 1); + } + else { + break; + } + } + }); + } +} + +class DecodedStream { + constructor(encodedStream) { + this._minBufferLength = 512; + this._bufferLength = 0; + this._current = 0; + this._ended = false; + this._sourceStream = encodedStream; + } + get length() { + return this._buffer.length; + } + ensureBuffer(size) { + const buffer = this._buffer; + if (buffer && size <= buffer.byteLength) { + return buffer; + } + let length = this._minBufferLength; + while (length < size) { + length *= 2; + } + const enlargedBuffer = new Uint8Array(length); + if (buffer) { + enlargedBuffer.set(buffer); + } + return (this._buffer = enlargedBuffer); + } + takeByte() { + const current = this._current; + while (this._bufferLength <= current) { + if (this._ended) { + return -1; + } + this._readBlock(); + } + return this._buffer[this._current++]; + } + takeBytes(length) { + let end; + const position = this._current; + if (length) { + this.ensureBuffer(position + length); + end = position + length; + while (!this._ended && this._bufferLength < end) { + this._readBlock(); + } + if (end > this._bufferLength) { + end = this._bufferLength; + } + } + else { + while (!this._ended) { + this._readBlock(); + } + end = this._bufferLength; + } + this._current = end; + const subarray = this._buffer.subarray(position, end); + return subarray; + } + takeUint16() { + const byte_0 = this.takeByte(); + const byte_1 = this.takeByte(); + if (byte_0 === -1 || byte_1 === -1) { + return -1; + } + return (byte_0 << 8) + byte_1; + } + takeInt32() { + const byte_0 = this.takeByte(); + const byte_1 = this.takeByte(); + const byte_2 = this.takeByte(); + const byte_3 = this.takeByte(); + return (byte_0 << 24) + (byte_1 << 16) + (byte_2 << 8) + byte_3; + } + peekByte() { + const peekedByte = this.takeByte(); + if (peekedByte !== -1) { + this._current--; + } + return peekedByte; + } + peekBytes(length) { + const bytes = this.takeBytes(length); + this._current -= bytes.length; + return bytes; + } + skip(n) { + this._current += n || 1; + } + reset() { + this._current = 0; + } +} + +class FlateStream extends DecodedStream { + constructor(encodedStream) { + super(encodedStream); + this._codeSize = 0; + this._codeBuf = 0; + const cmf = encodedStream.takeByte(); + const flg = encodedStream.takeByte(); + if (cmf === -1 || flg === -1) { + throw new Error(`Invalid header in flate stream: ${cmf}, ${flg}`); + } + if ((cmf & 0x0f) !== 0x08) { + throw new Error(`Unknown compression method in flate stream: ${cmf}, ${flg}`); + } + if (((cmf << 8) + flg) % 31 !== 0) { + throw new Error(`Bad FCHECK in flate stream: ${cmf}, ${flg}`); + } + if (flg & 0x20) { + throw new Error(`FDICT bit set in flate stream: ${cmf}, ${flg}`); + } + this._codeSize = 0; + this._codeBuf = 0; + } + _readBlock() { + let buffer; + let len; + const str = this._sourceStream; + let header = this.getBits(3); + if (header & 1) { + this._ended = true; + } + header >>= 1; + if (header === 0) { + let b; + if ((b = str.takeByte()) === -1) { + throw new Error("Bad block header in flate stream"); + } + let blockLen = b; + if ((b = str.takeByte()) === -1) { + throw new Error("Bad block header in flate stream"); + } + blockLen |= b << 8; + if ((b = str.takeByte()) === -1) { + throw new Error("Bad block header in flate stream"); + } + let check = b; + if ((b = str.takeByte()) === -1) { + throw new Error("Bad block header in flate stream"); + } + check |= b << 8; + if (check !== (~blockLen & 0xffff) && (blockLen !== 0 || check !== 0)) { + throw new Error("Bad uncompressed block length in flate stream"); + } + this._codeBuf = 0; + this._codeSize = 0; + const bufferLength = this._bufferLength, end = bufferLength + blockLen; + buffer = this.ensureBuffer(end); + this._bufferLength = end; + if (blockLen === 0) { + if (str.peekByte() === -1) { + this._ended = true; + } + } + else { + const block = str.takeBytes(blockLen); + buffer.set(block, bufferLength); + if (block.length < blockLen) { + this._ended = true; + } + } + return; + } + let litCodeTable; + let distCodeTable; + if (header === 1) { + litCodeTable = FlateStream.fixedLitCodeTab; + distCodeTable = FlateStream.fixedDistCodeTab; + } + else if (header === 2) { + const numLitCodes = this.getBits(5) + 257; + const numDistCodes = this.getBits(5) + 1; + const numCodeLenCodes = this.getBits(4) + 4; + const codeLenCodeLengths = new Uint8Array(FlateStream.codeLenCodeMap.length); + let i; + for (i = 0; i < numCodeLenCodes; i++) { + codeLenCodeLengths[FlateStream.codeLenCodeMap[i]] = this.getBits(3); + } + const codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths); + len = 0; + i = 0; + const codes = numLitCodes + numDistCodes; + const codeLengths = new Uint8Array(codes); + let bitsLength; + let bitsOffset; + let what; + while (i < codes) { + const code = this.getCode(codeLenCodeTab); + if (code === 16) { + bitsLength = 2; + bitsOffset = 3; + what = len; + } + else if (code === 17) { + bitsLength = 3; + bitsOffset = 3; + what = len = 0; + } + else if (code === 18) { + bitsLength = 7; + bitsOffset = 11; + what = len = 0; + } + else { + codeLengths[i++] = len = code; + continue; + } + let repeatLength = this.getBits(bitsLength) + bitsOffset; + while (repeatLength-- > 0) { + codeLengths[i++] = what; + } + } + litCodeTable = this.generateHuffmanTable(codeLengths.subarray(0, numLitCodes)); + distCodeTable = this.generateHuffmanTable(codeLengths.subarray(numLitCodes, codes)); + } + else { + throw new Error("Unknown block type in flate stream"); + } + buffer = this._buffer; + let limit = buffer ? buffer.length : 0; + let pos = this._bufferLength; + while (true) { + let code1 = this.getCode(litCodeTable); + if (code1 < 256) { + if (pos + 1 >= limit) { + buffer = this.ensureBuffer(pos + 1); + limit = buffer.length; + } + buffer[pos++] = code1; + continue; + } + if (code1 === 256) { + this._bufferLength = pos; + return; + } + code1 -= 257; + code1 = FlateStream.lengthDecode[code1]; + let code2 = code1 >> 16; + if (code2 > 0) { + code2 = this.getBits(code2); + } + len = (code1 & 0xffff) + code2; + code1 = this.getCode(distCodeTable); + code1 = FlateStream.distDecode[code1]; + code2 = code1 >> 16; + if (code2 > 0) { + code2 = this.getBits(code2); + } + const dist = (code1 & 0xffff) + code2; + if (pos + len >= limit) { + buffer = this.ensureBuffer(pos + len); + limit = buffer.length; + } + for (let k = 0; k < len; ++k, ++pos) { + buffer[pos] = buffer[pos - dist]; + } + } + } + ; + getBits(n) { + const stream = this._sourceStream; + let size = this._codeSize; + let buf = this._codeBuf; + let value; + while (size < n) { + if ((value = stream.takeByte()) === -1) { + throw new Error("Bad encoding in flate stream"); + } + buf |= value << size; + size += 8; + } + value = buf & ((1 << n) - 1); + this._codeBuf = buf >> n; + this._codeSize = size -= n; + return value; + } + ; + getCode(table) { + const stream = this._sourceStream; + const [codes, maxLength] = table; + let size = this._codeSize; + let buf = this._codeBuf; + let value; + while (size < maxLength) { + if ((value = stream.takeByte()) === -1) { + break; + } + buf |= value << size; + size += 8; + } + const code = codes[buf & ((1 << maxLength) - 1)]; + const codeLen = code >> 16; + const codeVal = code & 0xffff; + if (codeLen < 1 || size < codeLen) { + throw new Error("Bad encoding in flate stream"); + } + this._codeBuf = buf >> codeLen; + this._codeSize = size - codeLen; + return codeVal; + } + ; + generateHuffmanTable(lengths) { + const n = lengths.length; + let maxLength = 0; + let i; + for (i = 0; i < n; i++) { + if (lengths[i] > maxLength) { + maxLength = lengths[i]; + } + } + const size = 1 << maxLength; + const codes = new Int32Array(size); + for (let length = 1, code = 0, skip = 2; length <= maxLength; length++, code <<= 1, skip <<= 1) { + for (let value = 0; value < n; value++) { + if (lengths[value] === length) { + let code2 = 0; + let t = code; + for (i = 0; i < length; i++) { + code2 = (code2 << 1) | (t & 1); + t >>= 1; + } + for (i = code2; i < size; i += skip) { + codes[i] = (length << 16) | value; + } + code++; + } + } + } + return [codes, maxLength]; + } + ; +} +FlateStream.codeLenCodeMap = new Int32Array([ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 +]); +FlateStream.lengthDecode = new Int32Array([ + 0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000a, + 0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017, 0x2001b, 0x2001f, + 0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043, 0x40053, 0x40063, 0x40073, + 0x50083, 0x500a3, 0x500c3, 0x500e3, 0x00102, 0x00102, 0x00102 +]); +FlateStream.distDecode = new Int32Array([ + 0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009, 0x2000d, + 0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061, 0x60081, 0x600c1, + 0x70101, 0x70181, 0x80201, 0x80301, 0x90401, 0x90601, 0xa0801, 0xa0c01, + 0xb1001, 0xb1801, 0xc2001, 0xc3001, 0xd4001, 0xd6001 +]); +FlateStream.fixedLitCodeTab = [new Int32Array([ + 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c0, + 0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080, 0x80040, 0x900e0, + 0x70104, 0x80058, 0x80018, 0x90090, 0x70114, 0x80078, 0x80038, 0x900d0, + 0x7010c, 0x80068, 0x80028, 0x900b0, 0x80008, 0x80088, 0x80048, 0x900f0, + 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c8, + 0x7010a, 0x80064, 0x80024, 0x900a8, 0x80004, 0x80084, 0x80044, 0x900e8, + 0x70106, 0x8005c, 0x8001c, 0x90098, 0x70116, 0x8007c, 0x8003c, 0x900d8, + 0x7010e, 0x8006c, 0x8002c, 0x900b8, 0x8000c, 0x8008c, 0x8004c, 0x900f8, + 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c4, + 0x70109, 0x80062, 0x80022, 0x900a4, 0x80002, 0x80082, 0x80042, 0x900e4, + 0x70105, 0x8005a, 0x8001a, 0x90094, 0x70115, 0x8007a, 0x8003a, 0x900d4, + 0x7010d, 0x8006a, 0x8002a, 0x900b4, 0x8000a, 0x8008a, 0x8004a, 0x900f4, + 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cc, + 0x7010b, 0x80066, 0x80026, 0x900ac, 0x80006, 0x80086, 0x80046, 0x900ec, + 0x70107, 0x8005e, 0x8001e, 0x9009c, 0x70117, 0x8007e, 0x8003e, 0x900dc, + 0x7010f, 0x8006e, 0x8002e, 0x900bc, 0x8000e, 0x8008e, 0x8004e, 0x900fc, + 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c2, + 0x70108, 0x80061, 0x80021, 0x900a2, 0x80001, 0x80081, 0x80041, 0x900e2, + 0x70104, 0x80059, 0x80019, 0x90092, 0x70114, 0x80079, 0x80039, 0x900d2, + 0x7010c, 0x80069, 0x80029, 0x900b2, 0x80009, 0x80089, 0x80049, 0x900f2, + 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900ca, + 0x7010a, 0x80065, 0x80025, 0x900aa, 0x80005, 0x80085, 0x80045, 0x900ea, + 0x70106, 0x8005d, 0x8001d, 0x9009a, 0x70116, 0x8007d, 0x8003d, 0x900da, + 0x7010e, 0x8006d, 0x8002d, 0x900ba, 0x8000d, 0x8008d, 0x8004d, 0x900fa, + 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c6, + 0x70109, 0x80063, 0x80023, 0x900a6, 0x80003, 0x80083, 0x80043, 0x900e6, + 0x70105, 0x8005b, 0x8001b, 0x90096, 0x70115, 0x8007b, 0x8003b, 0x900d6, + 0x7010d, 0x8006b, 0x8002b, 0x900b6, 0x8000b, 0x8008b, 0x8004b, 0x900f6, + 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900ce, + 0x7010b, 0x80067, 0x80027, 0x900ae, 0x80007, 0x80087, 0x80047, 0x900ee, + 0x70107, 0x8005f, 0x8001f, 0x9009e, 0x70117, 0x8007f, 0x8003f, 0x900de, + 0x7010f, 0x8006f, 0x8002f, 0x900be, 0x8000f, 0x8008f, 0x8004f, 0x900fe, + 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c1, + 0x70108, 0x80060, 0x80020, 0x900a1, 0x80000, 0x80080, 0x80040, 0x900e1, + 0x70104, 0x80058, 0x80018, 0x90091, 0x70114, 0x80078, 0x80038, 0x900d1, + 0x7010c, 0x80068, 0x80028, 0x900b1, 0x80008, 0x80088, 0x80048, 0x900f1, + 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c9, + 0x7010a, 0x80064, 0x80024, 0x900a9, 0x80004, 0x80084, 0x80044, 0x900e9, + 0x70106, 0x8005c, 0x8001c, 0x90099, 0x70116, 0x8007c, 0x8003c, 0x900d9, + 0x7010e, 0x8006c, 0x8002c, 0x900b9, 0x8000c, 0x8008c, 0x8004c, 0x900f9, + 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c5, + 0x70109, 0x80062, 0x80022, 0x900a5, 0x80002, 0x80082, 0x80042, 0x900e5, + 0x70105, 0x8005a, 0x8001a, 0x90095, 0x70115, 0x8007a, 0x8003a, 0x900d5, + 0x7010d, 0x8006a, 0x8002a, 0x900b5, 0x8000a, 0x8008a, 0x8004a, 0x900f5, + 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cd, + 0x7010b, 0x80066, 0x80026, 0x900ad, 0x80006, 0x80086, 0x80046, 0x900ed, + 0x70107, 0x8005e, 0x8001e, 0x9009d, 0x70117, 0x8007e, 0x8003e, 0x900dd, + 0x7010f, 0x8006e, 0x8002e, 0x900bd, 0x8000e, 0x8008e, 0x8004e, 0x900fd, + 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c3, + 0x70108, 0x80061, 0x80021, 0x900a3, 0x80001, 0x80081, 0x80041, 0x900e3, + 0x70104, 0x80059, 0x80019, 0x90093, 0x70114, 0x80079, 0x80039, 0x900d3, + 0x7010c, 0x80069, 0x80029, 0x900b3, 0x80009, 0x80089, 0x80049, 0x900f3, + 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900cb, + 0x7010a, 0x80065, 0x80025, 0x900ab, 0x80005, 0x80085, 0x80045, 0x900eb, + 0x70106, 0x8005d, 0x8001d, 0x9009b, 0x70116, 0x8007d, 0x8003d, 0x900db, + 0x7010e, 0x8006d, 0x8002d, 0x900bb, 0x8000d, 0x8008d, 0x8004d, 0x900fb, + 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c7, + 0x70109, 0x80063, 0x80023, 0x900a7, 0x80003, 0x80083, 0x80043, 0x900e7, + 0x70105, 0x8005b, 0x8001b, 0x90097, 0x70115, 0x8007b, 0x8003b, 0x900d7, + 0x7010d, 0x8006b, 0x8002b, 0x900b7, 0x8000b, 0x8008b, 0x8004b, 0x900f7, + 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900cf, + 0x7010b, 0x80067, 0x80027, 0x900af, 0x80007, 0x80087, 0x80047, 0x900ef, + 0x70107, 0x8005f, 0x8001f, 0x9009f, 0x70117, 0x8007f, 0x8003f, 0x900df, + 0x7010f, 0x8006f, 0x8002f, 0x900bf, 0x8000f, 0x8008f, 0x8004f, 0x900ff + ]), 9]; +FlateStream.fixedDistCodeTab = [new Int32Array([ + 0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c, 0x5001c, + 0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016, 0x5000e, 0x00000, + 0x50001, 0x50011, 0x50009, 0x50019, 0x50005, 0x50015, 0x5000d, 0x5001d, + 0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000 + ]), 5]; + +class Stream { + constructor(bytes, start = 0, length) { + if (length && length < 0) { + throw new Error("Stream length can't be negative"); + } + this._bytes = bytes instanceof Uint8Array + ? bytes + : new Uint8Array(bytes); + this._start = start; + this._current = start; + this._end = start + length || bytes.length; + } + get length() { + return this._end - this._start; + } + takeByte() { + if (this._current >= this._end) { + return -1; + } + return this._bytes[this._current++]; + } + takeBytes(length) { + const bytes = this._bytes; + const position = this._current; + const bytesEnd = this._end; + if (!length) { + const subarray = bytes.subarray(position, bytesEnd); + return subarray; + } + else { + let end = position + length; + if (end > bytesEnd) { + end = bytesEnd; + } + this._current = end; + const subarray = bytes.subarray(position, end); + return subarray; + } + } + takeUint16() { + const b0 = this.takeByte(); + const b1 = this.takeByte(); + if (b0 === -1 || b1 === -1) { + return -1; + } + return (b0 << 8) + b1; + } + takeInt32() { + const b0 = this.takeByte(); + const b1 = this.takeByte(); + const b2 = this.takeByte(); + const b3 = this.takeByte(); + return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; + } + peekByte() { + const peekedByte = this.takeByte(); + if (peekedByte !== -1) { + this._current--; + } + return peekedByte; + } + peekBytes(length) { + const bytes = this.takeBytes(length); + this._current -= bytes.length; + return bytes; + } + getByte(index) { + return this._bytes[index]; + } + getByteRange(start, end) { + return this._bytes.subarray(Math.max(start, 0), Math.min(end, this._end)); + } + skip(n) { + this._current += n || 1; + } + reset() { + this._current = this._start; + } +} + +class FlateDecoder { + static Decode(input, predictor = flatePredictors.NONE, columns = 1, components = 1, bpc = 8) { + const stream = new Stream(input, 0, input.length); + const flate = new FlateStream(stream); + const inflated = flate.takeBytes(null); + switch (predictor) { + case (flatePredictors.NONE): + return inflated; + case (flatePredictors.PNG_NONE): + case (flatePredictors.PNG_SUB): + case (flatePredictors.PNG_UP): + case (flatePredictors.PNG_AVERAGE): + case (flatePredictors.PNG_PAETH): + case (flatePredictors.PNG_OPTIMUM): + const unfiltered = FlateDecoder.removePngFilter(inflated, columns, components, bpc); + return unfiltered; + case (flatePredictors.TIFF): + throw new Error("Unsupported filter predictor"); + } + } + static Encode(input, predictor = flatePredictors.PNG_UP, columns = 5, components = 1, bpc = 8) { + let filtered; + switch (predictor) { + case (flatePredictors.NONE): + filtered = input; + break; + case (flatePredictors.PNG_NONE): + case (flatePredictors.PNG_SUB): + case (flatePredictors.PNG_UP): + case (flatePredictors.PNG_AVERAGE): + case (flatePredictors.PNG_PAETH): + case (flatePredictors.PNG_OPTIMUM): + filtered = FlateDecoder.applyPngFilter(input, predictor, columns, components, bpc); + break; + case (flatePredictors.TIFF): + throw new Error("Unsupported filter predictor"); + } + const deflated = deflate_1(filtered); + return deflated; + } + static removePngFilter(input, columns, components, bpc) { + const interval = Math.ceil(components * bpc / 8); + const lineLen = columns * interval; + const lineLen_filtered = lineLen + 1; + if (!!(input.length % lineLen_filtered)) { + throw new Error(`Data length doesn't match filter columns: ${input.length} % ${lineLen_filtered}`); + } + const output = new Uint8Array(input.length / lineLen_filtered * lineLen); + const previous = new Array(lineLen).fill(0); + const current = new Array(lineLen).fill(0); + const getLeft = (j) => j - interval < 0 + ? 0 + : current[j - interval]; + const getAbove = (j) => previous[j]; + const getUpperLeft = (j) => j - interval < 0 + ? 0 + : previous[j - interval]; + let x = 0; + let y = 0; + let k = 0; + let rowStart = 0; + let filterType = 0; + let result = 0; + for (let i = 0; i < input.length; i++) { + if (i % lineLen_filtered === 0) { + filterType = input[i]; + x = 0; + if (i) { + for (k = 0; k < lineLen; k++) { + previous[k] = output[rowStart + k]; + } + } + rowStart = y; + } + else { + current[x] = input[i]; + switch (filterType) { + case 0: + result = current[x]; + break; + case 1: + result = (current[x] + getLeft(x)) % 256; + break; + case 2: + result = (current[x] + getAbove(x)) % 256; + break; + case 3: + result = (current[x] + Math.floor((getAbove(x) + getLeft(x)) / 2)) % 256; + break; + case 4: + result = (current[x] + this.paethPredictor(getLeft(x), getAbove(x), getUpperLeft(x))) % 256; + break; + } + output[y++] = result; + x++; + } + } + return output; + } + static applyPngFilter(input, predictor = 12, columns = 5, components = 1, bpc = 8) { + let filterType; + switch (predictor) { + case flatePredictors.PNG_NONE: + filterType = 0; + break; + case flatePredictors.PNG_SUB: + filterType = 1; + break; + case flatePredictors.PNG_UP: + filterType = 2; + break; + case flatePredictors.PNG_AVERAGE: + filterType = 3; + break; + case flatePredictors.PNG_PAETH: + filterType = 4; + break; + default: + throw new Error("Invalid PNG filter type"); + } + const interval = Math.ceil(components * bpc / 8); + const lineLen = columns * interval; + const lineLen_filtered = lineLen + 1; + const lineCount = Math.ceil(input.length / lineLen); + const lenFiltered = lineCount * lineLen_filtered; + const output = new Uint8Array(lenFiltered); + const previous = new Array(lineLen).fill(0); + const current = new Array(lineLen).fill(0); + const getLeft = (j) => j - interval < 0 + ? 0 + : current[j - interval]; + const getAbove = (j) => previous[j]; + const getUpperLeft = (j) => j - interval < 0 + ? 0 + : previous[j - interval]; + let x = 0; + let y = 0; + let k = 0; + let rowStart = 0; + let result = 0; + for (let i = 0; i < lenFiltered; i++) { + if (i % lineLen_filtered === 0) { + x = 0; + if (i) { + for (k = 0; k < lineLen; k++) { + previous[k] = input[rowStart + k]; + } + } + rowStart = y; + output[i] = filterType; + } + else { + current[x] = input[y++] || 0; + switch (filterType) { + case 0: + result = current[x]; + break; + case 1: + result = (current[x] - getLeft(x)) % 256; + break; + case 2: + result = (current[x] - getAbove(x)) % 256; + break; + case 3: + result = (current[x] - Math.floor((getAbove(x) + getLeft(x)) / 2)) % 256; + break; + case 4: + result = (current[x] - this.paethPredictor(getLeft(x), getAbove(x), getUpperLeft(x))) % 256; + break; + } + output[i] = result; + x++; + } + } + return output; + } + static paethPredictor(a, b, c) { + const p = a + b - c; + const pa = Math.abs(p - a); + const pb = Math.abs(p - b); + const pc = Math.abs(p - c); + if (pa <= pb && pa <= pc) { + return a; + } + else if (pb <= pc) { + return b; + } + else { + return c; + } + } +} + +var __awaiter$1c = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class PdfStream extends PdfObject { + get streamData() { + return this._streamData; + } + set streamData(data) { + this.setStreamData(data); + this._edited = true; + } + get decodedStreamData() { + if (!this._decodedStreamData) { + this.decodeStreamData(); + } + return this._decodedStreamData; + } + get decodedStreamDataChars() { + const decoder = new TextDecoder(); + return decoder.decode(this.decodedStreamData); + } + constructor(type) { + super(); + this.Type = type; + } + getStreamDataParserAsync() { + return __awaiter$1c(this, void 0, void 0, function* () { + return yield PdfStream.getDataParserAsync(this.decodedStreamData); + }); + } + toArray(cryptInfo) { + const streamData = (cryptInfo === null || cryptInfo === void 0 ? void 0 : cryptInfo.ref) && cryptInfo.streamCryptor + ? cryptInfo.streamCryptor.encrypt(this.streamData, cryptInfo.ref) + : this.streamData; + const encoder = new TextEncoder(); + const bytes = [...keywordCodes.DICT_START]; + bytes.push(...encoder.encode("/Length "), ...encoder.encode(" " + streamData.length)); + if (this.Type) { + bytes.push(...keywordCodes.TYPE, ...encoder.encode(this.Type)); + } + if (this.Filter) { + bytes.push(...encoder.encode("/Filter "), ...encoder.encode(this.Filter)); + } + if (this.DecodeParms) { + bytes.push(...encoder.encode("/DecodeParms "), ...this.DecodeParms.toArray(cryptInfo)); + } + bytes.push(...keywordCodes.DICT_END, ...keywordCodes.END_OF_LINE, ...keywordCodes.STREAM_START, ...keywordCodes.END_OF_LINE); + for (let i = 0; i < streamData.length; i++) { + bytes.push(streamData[i]); + } + bytes.push(...keywordCodes.END_OF_LINE, ...keywordCodes.STREAM_END); + return new Uint8Array(bytes); + } + setTextStreamData(text) { + const encoder = new TextEncoder(); + const bytes = encoder.encode(text); + this.streamData = bytes; + } + parsePropsAsync(parseInfo) { + var _a, _b; + return __awaiter$1c(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parse info is empty"); + } + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + this._ref = (_a = parseInfo.cryptInfo) === null || _a === void 0 ? void 0 : _a.ref; + this._sourceBytes = yield parser.sliceCharCodesAsync(start, end); + const streamEndIndex = yield parser.findSubarrayIndexAsync(keywordCodes.STREAM_END, { + direction: false, + minIndex: start, + maxIndex: end, + closedOnly: true, + }); + if (!streamEndIndex) { + throw new Error("Object is not a stream"); + } + const streamStartIndex = yield parser.findSubarrayIndexAsync(keywordCodes.STREAM_START, { + direction: false, + minIndex: start, + maxIndex: streamEndIndex.start - 1, + closedOnly: true + }); + if (!streamStartIndex) { + throw new Error("Stream start is out of the data bounds"); + } + const dictBounds = yield parser.getDictBoundsAtAsync(start); + let i = yield parser.skipToNextNameAsync(dictBounds.contentStart, dictBounds.contentEnd); + if (i === -1) { + throw new Error("Dict is empty (has no properties)"); + } + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/Type": + const type = yield parser.parseNameAtAsync(i); + if (type) { + if (this.Type && this.Type !== type.value) { + throw new Error(`Ivalid dict type: '${type.value}' instead of '${this.Type}'`); + } + i = type.end + 1; + } + else { + throw new Error("Can't parse /Type property value"); + } + break; + case "/Length": + case "/DL": + i = yield this.parseNumberPropAsync(name, parser, i, false); + break; + case "/Filter": + const entryType = yield parser.getValueTypeAtAsync(i); + if (entryType === valueTypes.NAME) { + const filter = yield parser.parseNameAtAsync(i); + if (filter && supportedFilters.has(filter.value)) { + this.Filter = filter.value; + i = filter.end + 1; + break; + } + else { + throw new Error(`Unsupported /Filter property value: ${filter.value}`); + } + } + else if (entryType === valueTypes.ARRAY) { + const filterNames = yield parser.parseNameArrayAtAsync(i); + if (filterNames) { + const filterArray = filterNames.value; + if (filterArray.length === 1 && supportedFilters.has(filterArray[0])) { + this.Filter = filterArray[0]; + i = filterNames.end + 1; + break; + } + else { + throw new Error(`Unsupported /Filter property value: ${filterArray.toString()}`); + } + } + } + throw new Error(`Unsupported /Filter property value type: ${entryType}`); + case "/DecodeParms": + const paramsEntryType = yield parser.getValueTypeAtAsync(i); + if (paramsEntryType === valueTypes.DICTIONARY) { + const decodeParamsBounds = yield parser.getDictBoundsAtAsync(i); + if (decodeParamsBounds) { + const params = yield DecodeParamsDict.parseAsync({ parser, + bounds: decodeParamsBounds, cryptInfo: parseInfo.cryptInfo }); + if (params) { + this.DecodeParms = params.value; + i = decodeParamsBounds.end + 1; + break; + } + } + throw new Error("Can't parse /DecodeParms property value"); + } + else if (paramsEntryType === valueTypes.ARRAY) { + const paramsDicts = yield DecodeParamsDict.parseArrayAsync(parser, i, parseInfo.cryptInfo); + if (paramsDicts) { + const paramsArray = paramsDicts.value; + if (paramsArray.length === 1) { + this.DecodeParms = paramsArray[0]; + i = paramsDicts.end + 1; + break; + } + } + throw new Error("Can't parse /DecodeParms property value"); + } + throw new Error(`Unsupported /DecodeParms property value type: ${paramsEntryType}`); + default: + i = yield parser.skipToNextNameAsync(i, dictBounds.contentEnd); + break; + } + } + else { + break; + } + } + const streamStart = yield parser.findNewLineIndexAsync(true, streamStartIndex.end + 1); + const streamEnd = yield parser.findNewLineIndexAsync(false, streamEndIndex.start - 1); + const streamBytes = yield parser.sliceCharCodesAsync(streamStart, streamEnd); + const encodedData = ((_b = parseInfo.cryptInfo) === null || _b === void 0 ? void 0 : _b.ref) && parseInfo.cryptInfo.streamCryptor + ? parseInfo.cryptInfo.streamCryptor.decrypt(streamBytes, parseInfo.cryptInfo.ref) + : streamBytes; + this._streamData = encodedData; + }); + } + setStreamData(data) { + if (!(data === null || data === void 0 ? void 0 : data.length)) { + throw new Error("Can't set emprty stream data"); + } + let params; + if (this.DecodeParms) { + params = this.DecodeParms; + } + else { + let columns; + let i = 10; + while (true) { + if (data.length % i === 0) { + columns = i; + break; + } + i--; + } + params = new DecodeParamsDict(); + params.setIntProp("/Predictor", flatePredictors.PNG_UP); + params.setIntProp("/Columns", columns); + this.DecodeParms = params; + } + const encodedData = FlateDecoder.Encode(data, (params === null || params === void 0 ? void 0 : params.getIntProp("/Predictor")) || flatePredictors.NONE, (params === null || params === void 0 ? void 0 : params.getIntProp("/Columns")) || 1, (params === null || params === void 0 ? void 0 : params.getIntProp("/Colors")) || 1, (params === null || params === void 0 ? void 0 : params.getIntProp("/BitsPerComponent")) || 8); + this._streamData = encodedData; + this.Length = encodedData.length; + this.DL = data.length; + this._decodedStreamData = data; + } + decodeStreamData() { + let decodedData; + switch (this.Filter) { + case streamFilters.FLATE: + if (this.DecodeParms) { + const params = this.DecodeParms; + decodedData = FlateDecoder.Decode(this._streamData, params.getIntProp("/Predictor") || flatePredictors.NONE, params.getIntProp("/Columns") || 1, params.getIntProp("/Colors") || 1, params.getIntProp("/BitsPerComponent") || 8); + } + else { + decodedData = FlateDecoder.Decode(this._streamData); + } + break; + default: + decodedData = new Uint8Array(this._streamData); + break; + } + this._decodedStreamData = decodedData; + } +} + +var __awaiter$1b = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class TrailerStream extends PdfStream { + constructor() { + super(streamTypes.XREF); + } + static parseAsync(parseInfo) { + return __awaiter$1b(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new TrailerStream(); + yield pdfObject.parsePropsAsync(parseInfo); + return { value: pdfObject, start: parseInfo.bounds.start, end: parseInfo.bounds.end }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.Size) { + bytes.push(...encoder.encode("/Size "), ...encoder.encode(" " + this.Size)); + } + if (this.Prev) { + bytes.push(...encoder.encode("/Prev "), ...encoder.encode(" " + this.Prev)); + } + if (this.Root) { + bytes.push(...encoder.encode("/Root "), ...this.Root.toArray(cryptInfo)); + } + if (this.Encrypt) { + bytes.push(...encoder.encode("/Encrypt "), ...this.Encrypt.toArray(cryptInfo)); + } + if (this.Info) { + bytes.push(...encoder.encode("/Info "), ...this.Info.toArray(cryptInfo)); + } + if (this.ID) { + bytes.push(...encoder.encode("/ID "), ...this.encodeSerializableArray(this.ID, cryptInfo)); + } + if (this.Index) { + bytes.push(...encoder.encode("/Index "), ...this.encodePrimitiveArray(this.Index, encoder)); + } + if (this.W) { + bytes.push(...encoder.encode("/W "), ...this.encodePrimitiveArray(this.W, encoder)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + var _a; + return __awaiter$1b(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const dictBounds = yield parser.getDictBoundsAtAsync(start); + let i = yield parser.skipToNextNameAsync(dictBounds.contentStart, dictBounds.contentEnd); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/Size": + case "/Prev": + i = yield this.parseNumberPropAsync(name, parser, i, false); + break; + case "/Root": + case "/Info": + i = yield this.parseRefPropAsync(name, parser, i); + break; + case "/Encrypt": + const entryType = yield parser.getValueTypeAtAsync(i); + if (entryType === valueTypes.REF) { + const encryptId = yield ObjectId.parseRefAsync(parser, i); + if (encryptId) { + this.Encrypt = encryptId.value; + i = encryptId.end + 1; + break; + } + else { + throw new Error("Can't parse /Encrypt property value"); + } + } + throw new Error(`Unsupported /Encrypt property value type: ${entryType}`); + case "/ID": + const hexIds = yield HexString.parseArrayAsync(parser, i); + if (hexIds && hexIds.value[0] && hexIds.value[1]) { + this.ID = [ + hexIds.value[0], + hexIds.value[1], + ]; + i = hexIds.end + 1; + break; + } + const literalIds = yield LiteralString.parseArrayAsync(parser, i); + if (literalIds && literalIds.value[0] && literalIds.value[1]) { + this.ID = [ + HexString.fromHexBytes(literalIds.value[0].bytes), + HexString.fromHexBytes(literalIds.value[1].bytes), + ]; + i = literalIds.end + 1; + break; + } + throw new Error("Can't parse /ID property value"); + case "/Index": + case "/W": + i = yield this.parseNumberArrayPropAsync(name, parser, i, false); + break; + default: + i = yield parser.skipToNextNameAsync(i, dictBounds.contentEnd); + break; + } + } + else { + break; + } + } + if (!this.W || !this.Size || !this.Root || (this.Encrypt && !this.ID)) { + throw new Error("Not all required properties parsed"); + } + if (!((_a = this.Index) === null || _a === void 0 ? void 0 : _a.length)) { + this.Index = [0, this.Size]; + } + }); + } +} + +class XRef { + get type() { + return this._type; + } + get offset() { + return this._offset; + } + constructor(type) { + this._type = type; + } +} + +var __awaiter$1a = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class XRefStream extends XRef { + get prev() { + var _a; + return (_a = this._trailerStream) === null || _a === void 0 ? void 0 : _a.Prev; + } + get size() { + var _a; + return (_a = this._trailerStream) === null || _a === void 0 ? void 0 : _a.Size; + } + get root() { + var _a; + return (_a = this._trailerStream) === null || _a === void 0 ? void 0 : _a.Root; + } + get info() { + var _a; + return (_a = this._trailerStream) === null || _a === void 0 ? void 0 : _a.Info; + } + get encrypt() { + var _a; + return (_a = this._trailerStream) === null || _a === void 0 ? void 0 : _a.Encrypt; + } + get id() { + var _a; + return (_a = this._trailerStream) === null || _a === void 0 ? void 0 : _a.ID; + } + constructor(trailer, offset) { + super(xRefTypes.STREAM); + this._trailerStream = trailer; + this._offset = offset; + } + static createFrom(base, entries, offset) { + if (!(entries === null || entries === void 0 ? void 0 : entries.length) || !base) { + return null; + } + const entriesSize = Math.max(...entries.map(x => x.id)) + 2; + const size = Math.max(entriesSize, base.size); + return XRefStream.create(entries, size, offset, base.root, base.offset, base.info, base.encrypt, base.id); + } + static create(entries, size, offset, root, prev, info, encrypt, id) { + if (!(entries === null || entries === void 0 ? void 0 : entries.length) || !size || !offset || !root) { + return null; + } + const trailer = new TrailerStream(); + trailer.Size = size; + trailer.Root = root; + trailer.Prev = prev; + trailer.Info = info; + trailer.Encrypt = encrypt; + trailer.ID = id; + const w = [1, 4, 2]; + const wSum = w[0] + w[1] + w[2]; + const params = new DecodeParamsDict(); + params.setIntProp("/Predictor", flatePredictors.PNG_UP); + params.setIntProp("/Columns", wSum); + params.setIntProp("/Colors", 1); + params.setIntProp("/BitsPerComponent", 8); + const data = XRefEntry.toStreamBytes(entries, w); + const stream = new XRefStream(trailer, offset); + stream._trailerStream.Filter = streamFilters.FLATE; + stream._trailerStream.DecodeParms = params; + stream._trailerStream.W = w; + stream._trailerStream.Index = data.index; + stream._trailerStream.streamData = data.bytes; + return stream; + } + static parseAsync(parseInfo, offset) { + return __awaiter$1a(this, void 0, void 0, function* () { + if (!parseInfo) { + return null; + } + const trailerStream = yield TrailerStream.parseAsync(parseInfo); + if (!trailerStream) { + return null; + } + const xrefStream = new XRefStream(trailerStream.value, offset); + return { + value: xrefStream, + start: null, + end: null, + }; + }); + } + createUpdate(entries, offset) { + return XRefStream.createFrom(this, entries, offset); + } + getEntries() { + if (!this._trailerStream) { + return []; + } + const entries = XRefEntry.fromStreamBytes(this._trailerStream.decodedStreamData, this._trailerStream.W, this._trailerStream.Index); + return entries; + } + toArray(cryptInfo) { + return this._trailerStream.toArray(cryptInfo); + } +} + +var __awaiter$19 = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class TextStream extends PdfStream { + constructor(type = null) { + super(type); + } + static parseAsync(parseInfo) { + return __awaiter$19(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new TextStream(); + yield pdfObject.parsePropsAsync(parseInfo); + return { value: pdfObject, start: parseInfo.bounds.start, end: parseInfo.bounds.end }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + getText() { + return null; + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + return superBytes; + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$19(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + }); + } +} + +var __awaiter$18 = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class IndexedColorSpaceArray { + constructor(baseColorSpace, highestValue, lookupArray) { + switch (baseColorSpace) { + case colorSpaces.GRAYSCALE: + this.componentsNumber = 1; + break; + case colorSpaces.RGB: + this.componentsNumber = 3; + break; + case colorSpaces.CMYK: + this.componentsNumber = 4; + break; + default: + throw new Error(`Unsupported base color space for indexed color space: ${baseColorSpace}`); + } + this.baseColorSpace = baseColorSpace; + if (lookupArray.length !== this.componentsNumber * (highestValue + 1)) { + throw new Error(`Invalid lookup array length: ${lookupArray.length}`); + } + this.highestValue = highestValue; + this.lookupArray = lookupArray; + } + static parseAsync(parseInfo, skipEmpty = true) { + return __awaiter$18(this, void 0, void 0, function* () { + const { parser, bounds, cryptInfo } = parseInfo; + let i; + if (skipEmpty) { + i = yield parser.findNonSpaceIndexAsync(true, bounds.start); + } + const start = i; + if (i < 0 || i > parser.maxIndex + || !(yield parser.isCodeAtAsync(start, codes.L_BRACKET))) { + console.log("Color space array start not found"); + return null; + } + i++; + const type = yield parser.parseNameAtAsync(i); + if (!type || type.value !== "/Indexed") { + console.log("Array is not representing an indexed color space"); + return null; + } + i = type.end + 1; + const base = yield parser.parseNameAtAsync(i); + if (!base) { + console.log("Can't parse base color space name of the indexed color space"); + return null; + } + i = base.end + 2; + const highestValue = yield parser.parseNumberAtAsync(i); + if (!highestValue || isNaN(highestValue.value)) { + console.log("Can't parse the highest value of the indexed color space"); + return null; + } + i = highestValue.end + 1; + let lookupArray; + const lookupEntryType = yield parser.getValueTypeAtAsync(i); + if (lookupEntryType === valueTypes.REF) { + try { + const lookupId = yield ObjectId.parseRefAsync(parser, i); + const lookupParseInfo = yield parseInfo.parseInfoGetterAsync(lookupId.value.id); + const lookupStream = yield TextStream.parseAsync(lookupParseInfo); + lookupArray = lookupStream.value.decodedStreamData; + i = lookupId.end + 1; + } + catch (e) { + throw new Error(`Can't parse indexed color array lookup ref: ${e.message}`); + } + } + else if (lookupEntryType === valueTypes.STRING_HEX) { + const lookupHex = yield HexString.parseAsync(parser, i, cryptInfo); + if (lookupHex) { + lookupArray = lookupHex.value.hex; + i = lookupHex.end + 1; + } + else { + throw new Error("Can't parse indexed color array lookup hex string"); + } + } + try { + const colorSpace = new IndexedColorSpaceArray(base.value, highestValue.value, lookupArray); + return { + value: colorSpace, + start, + end: i - 1, + }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const encoder = new TextEncoder(); + const bytes = []; + bytes.push(codes.L_BRACKET, ...encoder.encode("/Indexed "), ...encoder.encode(this.baseColorSpace + " "), ...encoder.encode(this.highestValue + " "), ...HexString.fromHexBytes(this.lookupArray).toArray(cryptInfo), codes.R_BRACKET); + return new Uint8Array(bytes); + } + getColor(index) { + switch (this.baseColorSpace) { + case colorSpaces.GRAYSCALE: + const gray = this.lookupArray[index]; + return [gray, gray, gray]; + case colorSpaces.RGB: + return [ + this.lookupArray[index * 3], + this.lookupArray[index * 3 + 1], + this.lookupArray[index * 3 + 2], + ]; + case colorSpaces.CMYK: + const c = this.lookupArray[index * 4] / 255; + const m = this.lookupArray[index * 4 + 1] / 255; + const y = this.lookupArray[index * 4 + 2] / 255; + const k = this.lookupArray[index * 4 + 3] / 255; + return [ + 255 * (1 - c) * (1 - k), + 255 * (1 - m) * (1 - k), + 255 * (1 - y) * (1 - k), + ]; + } + } +} + +var __awaiter$17 = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class ImageStream extends PdfStream { + get sMask() { + return this._sMask; + } + set sMask(value) { + this._sMask = value; + } + constructor() { + super(streamTypes.FORM_XOBJECT); + this.Subtype = "/Image"; + this.ImageMask = false; + this.Interpolate = false; + this.SMaskInData = 0; + } + static parseAsync(parseInfo) { + return __awaiter$17(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new ImageStream(); + yield pdfObject.parsePropsAsync(parseInfo); + return { value: pdfObject, start: parseInfo.bounds.start, end: parseInfo.bounds.end }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.Subtype) { + bytes.push(...encoder.encode("/Subtype "), ...encoder.encode(this.Subtype)); + } + if (this.Width) { + bytes.push(...encoder.encode("/Width "), ...encoder.encode(" " + this.Width)); + } + if (this.Height) { + bytes.push(...encoder.encode("/Height "), ...encoder.encode(" " + this.Height)); + } + if (this.ColorSpace) { + if (this._indexedColorSpace) { + bytes.push(...encoder.encode("/ColorSpace "), ...this._indexedColorSpace.toArray(cryptInfo)); + } + else { + bytes.push(...encoder.encode("/ColorSpace "), ...encoder.encode(this.ColorSpace)); + } + } + if (this.BitsPerComponent) { + bytes.push(...encoder.encode("/BitsPerComponent "), ...encoder.encode(" " + this.BitsPerComponent)); + } + bytes.push(...encoder.encode("/ImageMask "), ...encoder.encode(" " + !!this.ImageMask)); + if (this.Mask) { + bytes.push(...encoder.encode("/Mask "), ...this.encodePrimitiveArray(this.Mask, encoder)); + } + if (this.Decode) { + bytes.push(...encoder.encode("/Decode "), ...this.encodePrimitiveArray(this.Decode, encoder)); + } + bytes.push(...encoder.encode("/Interpolate "), ...encoder.encode(" " + !!this.Interpolate)); + if (this.SMask) { + bytes.push(...encoder.encode("/SMask "), ...this.SMask.toArray(cryptInfo)); + } + if (this.SMaskInData) { + bytes.push(...encoder.encode("/SMaskInData "), ...encoder.encode(" " + this.SMaskInData)); + } + if (this.Matte) { + bytes.push(...encoder.encode("/Matte "), ...this.encodePrimitiveArray(this.Matte, encoder)); + } + if (this.StructParent) { + bytes.push(...encoder.encode("/StructParent "), ...encoder.encode(" " + this.StructParent)); + } + if (this.Metadata) { + bytes.push(...encoder.encode("/Metadata "), ...this.Metadata.toArray(cryptInfo)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + getImageUrlAsync() { + return __awaiter$17(this, void 0, void 0, function* () { + if (this._imageUrl) { + URL.revokeObjectURL(this._imageUrl); + } + if (this.Filter === streamFilters.DCT + || this.Filter === streamFilters.JBIG2 + || this.Filter === streamFilters.JPX) { + const blob = new Blob([this.decodedStreamData], { + type: "application/octet-binary", + }); + const imageUrl = URL.createObjectURL(blob); + this._imageUrl = imageUrl; + return imageUrl; + } + if (this.Filter === streamFilters.FLATE) { + const length = this.Width * this.Height; + let alpha; + if (this.sMask) { + alpha = this.sMask.decodedStreamData; + if (alpha.length !== length) { + throw new Error(`Invalid alpha mask data length: ${alpha.length} (must be ${length})`); + } + } + else { + alpha = new Uint8Array(length).fill(255); + } + const imageBytes = new Uint8ClampedArray(length * 4); + const colors = this.getRgbColors(); + let j; + let k; + for (let i = 0; i < length; i++) { + j = i * 4; + k = i * 3; + imageBytes[j] = colors[k]; + imageBytes[j + 1] = colors[k + 1]; + imageBytes[j + 2] = colors[k + 2]; + imageBytes[j + 3] = alpha[i]; + } + const imageData = new ImageData(imageBytes, this.Width, this.Height); + const urlPromise = new Promise((resolve, reject) => { + const canvas = document.createElement("canvas"); + canvas.width = this.Width; + canvas.height = this.Height; + canvas.getContext("2d").putImageData(imageData, 0, 0); + canvas.toBlob((blob) => { + const url = URL.createObjectURL(blob); + resolve(url); + }); + }); + const imageUrl = yield urlPromise; + this._imageUrl = imageUrl; + return imageUrl; + } + throw new Error(`Unsupported image filter type: ${this.Filter}`); + }); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$17(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const dictBounds = yield parser.getDictBoundsAtAsync(start); + let i = yield parser.skipToNextNameAsync(dictBounds.contentStart, dictBounds.contentEnd); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/Subtype": + const subtype = yield parser.parseNameAtAsync(i); + if (subtype) { + if (this.Subtype && this.Subtype !== subtype.value) { + throw new Error(`Invalid dict subtype: '${subtype.value}' instead of '${this.Subtype}'`); + } + i = subtype.end + 1; + } + else { + throw new Error("Can't parse /Subtype property value"); + } + break; + case "/Width": + case "/Height": + case "/BitsPerComponent": + case "/SMaskInData": + case "/StructParent": + i = yield this.parseNumberPropAsync(name, parser, i, false); + break; + case "/Decode": + i = yield this.parseNumberArrayPropAsync(name, parser, i, false); + break; + case "/Matte": + i = yield this.parseNumberArrayPropAsync(name, parser, i, true); + break; + case "/Interpolate": + i = yield this.parseBoolPropAsync(name, parser, i); + break; + case "/SMask": + case "/Metadata": + i = yield this.parseRefPropAsync(name, parser, i); + break; + case "/ColorSpace": + const colorSpaceEntryType = yield parser.getValueTypeAtAsync(i); + if (colorSpaceEntryType === valueTypes.NAME) { + const colorSpaceName = yield parser.parseNameAtAsync(i); + if (colorSpaceName) { + this.ColorSpace = colorSpaceName.value; + i = colorSpaceName.end + 1; + break; + } + throw new Error("Can't parse /ColorSpace name"); + } + else if (colorSpaceEntryType === valueTypes.ARRAY) { + const colorSpaceArrayBounds = yield parser.getArrayBoundsAtAsync(i); + if (colorSpaceArrayBounds) { + const indexedColorSpace = yield IndexedColorSpaceArray.parseAsync({ + parser, + bounds: colorSpaceArrayBounds, + cryptInfo: parseInfo.cryptInfo, + parseInfoGetterAsync: parseInfo.parseInfoGetterAsync, + }); + if (indexedColorSpace) { + this.ColorSpace = colorSpaces.SPECIAL_INDEXED; + this._indexedColorSpace = indexedColorSpace.value; + i = colorSpaceArrayBounds.end + 1; + break; + } + throw new Error("Can't parse /ColorSpace object:" + + parser.sliceCharsAsync(colorSpaceArrayBounds.start, colorSpaceArrayBounds.end)); + } + throw new Error("Can't parse /ColorSpace value array"); + } + else if (colorSpaceEntryType === valueTypes.REF) { + const colorSpaceRef = yield ObjectId.parseRefAsync(parser, i); + if (colorSpaceRef) { + const colorSpaceParseInfo = yield parseInfo.parseInfoGetterAsync(colorSpaceRef.value.id); + if (colorSpaceParseInfo) { + const indexedColorSpace = yield IndexedColorSpaceArray.parseAsync(colorSpaceParseInfo); + if (indexedColorSpace) { + this.ColorSpace = colorSpaces.SPECIAL_INDEXED; + this._indexedColorSpace = indexedColorSpace.value; + i = colorSpaceRef.end + 1; + break; + } + throw new Error("Can't parse /ColorSpace object:" + + (yield colorSpaceParseInfo.parser.sliceCharsAsync(colorSpaceParseInfo.bounds.start, colorSpaceParseInfo.bounds.end))); + } + } + throw new Error("Can't parse /ColorSpace ref"); + } + throw new Error(`Unsupported /ColorSpace property value type: ${colorSpaceEntryType}`); + case "/ImageMask": + const imageMask = yield parser.parseBoolAtAsync(i, false); + if (imageMask) { + this.ImageMask = imageMask.value; + i = imageMask.end + 1; + if (this.ImageMask) { + this.BitsPerComponent = 1; + } + } + else { + throw new Error("Can't parse /ImageMask property value"); + } + break; + case "/Mask": + const maskEntryType = yield parser.getValueTypeAtAsync(i); + if (maskEntryType === valueTypes.REF) { + const maskStreamId = yield ObjectId.parseRefAsync(parser, i); + if (!maskStreamId) { + throw new Error("Can't parse /Mask value reference: failed to parse ref"); + } + const maskParseInfo = yield parseInfo.parseInfoGetterAsync(maskStreamId.value.id); + if (!maskParseInfo) { + throw new Error("Can't parse /Mask value reference: failed to get image parse info"); + } + const maskStream = yield ImageStream.parseAsync(maskParseInfo); + if (!maskStream) { + throw new Error("Can't parse /Mask value reference: failed to parse image stream"); + } + const maskParser = yield maskStream.value.getStreamDataParserAsync(); + const maskValues = []; + let j = 0; + let value; + while (j <= maskParser.maxIndex) { + value = yield maskParser.parseNumberAtAsync(j, true, true); + if (!value) { + break; + } + maskValues.push(value.value); + j = value.end + 1; + } + if (!maskValues.length) { + throw new Error("Can't parse /Mask value reference: failed to parse decoded image data"); + } + this.Mask = maskValues; + i = maskStreamId.end + 1; + break; + } + else if (maskEntryType === valueTypes.ARRAY) { + const maskArray = yield parser.parseNumberArrayAtAsync(i, false); + if (maskArray) { + this.Mask = maskArray.value; + i = maskArray.end + 1; + break; + } + throw new Error("Can't parse /Mask property value"); + } + throw new Error(`Unsupported /Mask property value type: ${maskEntryType}`); + case "/OC": + case "/Intent": + case "/Alternates": + case "/ID": + case "/OPI": + default: + i = yield parser.skipToNextNameAsync(i, dictBounds.contentEnd); + break; + } + } + else { + break; + } + } + if (!this.Width && !this.Height) { + throw new Error("Not all required properties parsed"); + } + if (this.ImageMask && (this.BitsPerComponent !== 1 || this.ColorSpace)) { + throw new Error("Mutually exclusive properties found"); + } + if (!this.Decode && !(this.Filter === streamFilters.JPX && !this.ImageMask)) { + switch (this.ColorSpace) { + case colorSpaces.GRAYSCALE: + this.Decode = [0, 1]; + break; + case colorSpaces.RGB: + this.Decode = [0, 1, 0, 1, 0, 1]; + break; + case colorSpaces.CMYK: + this.Decode = [0, 1, 0, 1, 0, 1, 0, 1]; + break; + case colorSpaces.SPECIAL_INDEXED: + this.Decode = [0, Math.pow(2, this.BitsPerComponent || 1) - 1]; + break; + default: + this.Decode = [0, 1]; + break; + } + } + if (!this.DecodeParms) { + this.DecodeParms = new DecodeParamsDict(); + } + if (!this.DecodeParms.getIntProp("/BitsPerComponent")) { + this.DecodeParms.setIntProp("/BitsPerComponent", this.BitsPerComponent); + } + if (!this.DecodeParms.getIntProp("/Columns")) { + this.DecodeParms.setIntProp("/Columns", this.Width); + } + if (!this.DecodeParms.getIntProp("/Colors")) { + switch (this.ColorSpace) { + case colorSpaces.GRAYSCALE: + case colorSpaces.SPECIAL_INDEXED: + this.DecodeParms.setIntProp("/Colors", 1); + break; + case colorSpaces.RGB: + this.DecodeParms.setIntProp("/Colors", 3); + break; + case colorSpaces.CMYK: + this.DecodeParms.setIntProp("/Colors", 4); + break; + default: + this.DecodeParms.setIntProp("/Colors", 1); + break; + } + } + if (this.SMask) { + const sMaskParseInfo = yield parseInfo.parseInfoGetterAsync(this.SMask.id); + if (!sMaskParseInfo) { + throw new Error(`Can't get parse info for ref: ${this.SMask.id} ${this.sMask.generation} R`); + } + const sMask = yield ImageStream.parseAsync(sMaskParseInfo); + if (!sMask) { + throw new Error(`Can't parse SMask: ${this.SMask.id} ${this.sMask.generation} R`); + } + this._sMask = sMask.value; + } + }); + } + getRgbColor(index) { + var _a; + const data = this.decodedStreamData; + switch (this.ColorSpace) { + case colorSpaces.GRAYSCALE: + const gray = data[index]; + return [gray, gray, gray]; + case colorSpaces.RGB: + return [ + data[index * 3], + data[index * 3 + 1], + data[index * 3 + 2], + ]; + case colorSpaces.CMYK: + const c = data[index * 4] / 255; + const m = data[index * 4 + 1] / 255; + const y = data[index * 4 + 2] / 255; + const k = data[index * 4 + 3] / 255; + return [ + 255 * (1 - c) * (1 - k), + 255 * (1 - m) * (1 - k), + 255 * (1 - y) * (1 - k), + ]; + case colorSpaces.SPECIAL_INDEXED: + return ((_a = this._indexedColorSpace) === null || _a === void 0 ? void 0 : _a.getColor(index)) || [0, 0, 0]; + } + } + getRgbColors() { + var _a; + const data = this.decodedStreamData; + const pixels = this.Width * this.Height; + const length = pixels * 3; + const result = new Uint8ClampedArray(length); + let i; + let j; + let n; + switch (this.ColorSpace) { + case colorSpaces.GRAYSCALE: + let gray; + for (i = 0; i < pixels; i++) { + gray = data[i]; + j = i * 3; + result[j] = gray; + result[j + 1] = gray; + result[j + 2] = gray; + } + break; + case colorSpaces.RGB: + for (i = 0; i < length; i++) { + result[i] = data[i]; + } + break; + case colorSpaces.CMYK: + let c; + let m; + let y; + let k; + for (i = 0; i < pixels; i++) { + j = i * 3; + n = i * 4; + c = data[n] / 255; + m = data[n + 1] / 255; + y = data[n + 2] / 255; + k = data[n + 3] / 255; + result[j] = 255 * (1 - c) * (1 - k); + result[j + 1] = 255 * (1 - m) * (1 - k); + result[j + 2] = 255 * (1 - y) * (1 - k); + } + break; + case colorSpaces.SPECIAL_INDEXED: + let r; + let g; + let b; + for (i = 0; i < pixels; i++) { + [r, g, b] = ((_a = this._indexedColorSpace) === null || _a === void 0 ? void 0 : _a.getColor(i)) || [0, 0, 0]; + j = i * 3; + result[j] = r; + result[j + 1] = g; + result[j + 2] = b; + } + break; + } + return result; + } +} + +var __awaiter$16 = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class ObjectMapDict extends PdfDict { + constructor() { + super(null); + this._objectIdMap = new Map(); + this._dictParserMap = new Map(); + } + static parseAsync(parseInfo) { + return __awaiter$16(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new ObjectMapDict(); + yield pdfObject.parsePropsAsync(parseInfo); + return { value: pdfObject, start: parseInfo.bounds.start, end: parseInfo.bounds.end }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + getObjectId(name) { + return this._objectIdMap.get(name); + } + *getObjectIds() { + for (const pair of this._objectIdMap) { + yield pair; + } + return; + } + getDictParser(name) { + return this._dictParserMap.get(name); + } + *getDictParsers() { + for (const pair of this._dictParserMap) { + yield pair; + } + return; + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + this._objectIdMap.forEach((v, k) => { + bytes.push(...encoder.encode(k + " "), ...v.toArray(cryptInfo)); + }); + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$16(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + default: + const entryType = yield parser.getValueTypeAtAsync(i); + if (entryType === valueTypes.REF) { + const id = yield ObjectId.parseRefAsync(parser, i); + if (id) { + this._objectIdMap.set(name, id.value); + i = id.end + 1; + break; + } + } + else if (entryType === valueTypes.DICTIONARY) { + const dictBounds = yield parser.getDictBoundsAtAsync(i); + if (dictBounds) { + const dictParseInfo = { + parser: yield PdfDict.getDataParserAsync(yield parser.sliceCharCodesAsync(dictBounds.start, dictBounds.end)), + bounds: { + start: 0, + end: dictBounds.end - dictBounds.start, + contentStart: dictBounds.contentStart - dictBounds.start, + contentEnd: dictBounds.contentEnd - dictBounds.start, + }, + cryptInfo: parseInfo.cryptInfo, + }; + this._dictParserMap.set(name, dictParseInfo); + i = dictBounds.end + 1; + break; + } + } + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + }); + } +} + +var __awaiter$15 = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class UnicodeCmapStream extends PdfStream { + constructor(type = null) { + super(type); + this._codeRanges = []; + this._map = new Map(); + } + static parseAsync(parseInfo) { + return __awaiter$15(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new UnicodeCmapStream(); + yield pdfObject.parsePropsAsync(parseInfo); + return { value: pdfObject, start: parseInfo.bounds.start, end: parseInfo.bounds.end }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + return superBytes; + } + hexBytesToUtfString(bytes) { + let result = ""; + outer: for (let i = 0; i < bytes.length; i++) { + for (let j = 1; i + j <= bytes.length && j <= 4; j++) { + const sub = bytes.subarray(i, i + j); + if (this.isInsideAnyRange(sub)) { + result += this._map.get(ByteUtils.parseIntFromBytes(sub)) || ""; + continue outer; + } + } + } + return result; + } + isInsideAnyRange(bytes) { + outer: for (const range of this._codeRanges) { + if (bytes.length !== range.length) { + continue; + } + for (let i = 0; i < range.length; i++) { + if (bytes[i] < range.start[i] + || bytes[i] > range.end[i]) { + continue outer; + } + } + return true; + } + return false; + } + parseCodeRangesAsync(parser) { + var _a, _b; + return __awaiter$15(this, void 0, void 0, function* () { + let i = 0; + const codeRangeStart = (_a = (yield parser.findSubarrayIndexAsync(keywordCodes.CMAP_BEGIN_CODE_RANGE, { closedOnly: true }))) === null || _a === void 0 ? void 0 : _a.end; + if (!codeRangeStart) { + return; + } + i = codeRangeStart + 1; + const codeRangeEnd = (_b = (yield parser.findSubarrayIndexAsync(keywordCodes.CMAP_END_CODE_RANGE, { closedOnly: true, minIndex: i }))) === null || _b === void 0 ? void 0 : _b.start; + while (i < codeRangeEnd - 1) { + const rangeStart = yield HexString.parseAsync(parser, i); + i = rangeStart.end + 1; + const rangeEnd = yield HexString.parseAsync(parser, i); + i = rangeEnd.end + 1; + this._codeRanges.push({ + length: rangeStart.value.hex.length, + start: rangeStart.value.hex, + end: rangeEnd.value.hex, + }); + } + }); + } + parseCharMapAsync(parser, decoder) { + var _a, _b; + return __awaiter$15(this, void 0, void 0, function* () { + let i = 0; + while (true) { + const charMapStart = (_a = (yield parser.findSubarrayIndexAsync(keywordCodes.CMAP_BEGIN_CHAR, { closedOnly: true, minIndex: i }))) === null || _a === void 0 ? void 0 : _a.end; + if (!charMapStart) { + break; + } + i = charMapStart + 1; + const charMapEnd = (_b = (yield parser.findSubarrayIndexAsync(keywordCodes.CMAP_END_CHAR, { closedOnly: true, minIndex: i }))) === null || _b === void 0 ? void 0 : _b.start; + while (i < charMapEnd - 1) { + const hexKey = yield HexString.parseAsync(parser, i); + i = hexKey.end + 1; + const unicodeValue = yield HexString.parseAsync(parser, i); + i = unicodeValue.end + 1; + this._map.set(ByteUtils.parseIntFromBytes(hexKey.value.hex), decoder.decode(unicodeValue.value.hex)); + } + } + }); + } + parseCharRangesMapAsync(parser, decoder) { + var _a, _b; + return __awaiter$15(this, void 0, void 0, function* () { + let i = 0; + while (true) { + const rangeMapStart = (_a = (yield parser.findSubarrayIndexAsync(keywordCodes.CMAP_BEGIN_RANGE, { closedOnly: true, minIndex: i }))) === null || _a === void 0 ? void 0 : _a.end; + if (!rangeMapStart) { + break; + } + i = rangeMapStart + 1; + const rangeMapEnd = (_b = (yield parser.findSubarrayIndexAsync(keywordCodes.CMAP_END_RANGE, { closedOnly: true, minIndex: i }))) === null || _b === void 0 ? void 0 : _b.start; + while (i < rangeMapEnd - 1) { + const keyRangeStart = yield HexString.parseAsync(parser, i); + i = keyRangeStart.end + 1; + const keyRangeEnd = yield HexString.parseAsync(parser, i); + i = keyRangeEnd.end + 1; + let key = ByteUtils.parseIntFromBytes(keyRangeStart.value.hex); + const nextValueType = yield parser.getValueTypeAtAsync(i, true); + if (nextValueType === valueTypes.ARRAY) { + const valueArray = yield HexString.parseArrayAsync(parser, i); + i = valueArray.end + 1; + for (const value of valueArray.value) { + this._map.set(key++, decoder.decode(value.hex)); + } + } + else { + const startingValue = yield HexString.parseAsync(parser, i); + i = startingValue.end + 1; + let startingUtf = ByteUtils.parseIntFromBytes(startingValue.value.hex); + while (key <= ByteUtils.parseIntFromBytes(keyRangeEnd.value.hex)) { + const hexStringUnpadded = (startingUtf++).toString(16); + const padding = hexStringUnpadded.length % 2 + ? "0" + : ""; + const hexString = padding + hexStringUnpadded; + this._map.set(key++, decoder.decode(ByteUtils.hexStringToBytes(hexString))); + } + } + } + } + }); + } + fillMapAsync() { + return __awaiter$15(this, void 0, void 0, function* () { + this._codeRanges.length = 0; + this._map.clear(); + const parser = yield this.getStreamDataParserAsync(); + const decoder = new TextDecoder("utf-16be"); + yield this.parseCodeRangesAsync(parser); + yield this.parseCharMapAsync(parser, decoder); + yield this.parseCharRangesMapAsync(parser, decoder); + }); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$15(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + yield this.fillMapAsync(); + }); + } +} + +const pdfCharCodesByName = { + A: { + name: "A", + char: "A", + stdCode: 65, + macCode: 65, + winCode: 65, + pdfCode: 65, + utfCode: 65 + }, + AE: { + name: "AE", + char: "Æ", + stdCode: 225, + macCode: 174, + winCode: 198, + pdfCode: 198, + utfCode: 198 + }, + Aacute: { + name: "Aacute", + char: "Á", + stdCode: null, + macCode: 231, + winCode: 193, + pdfCode: 193, + utfCode: 193 + }, + Acircumflex: { + name: "Acircumflex", + char: "Â", + stdCode: null, + macCode: 229, + winCode: 194, + pdfCode: 194, + utfCode: 194 + }, + Adieresis: { + name: "Adieresis", + char: "Ä", + stdCode: null, + macCode: 128, + winCode: 196, + pdfCode: 196, + utfCode: 196 + }, + Agrave: { + name: "Agrave", + char: "À", + stdCode: null, + macCode: 203, + winCode: 192, + pdfCode: 192, + utfCode: 192 + }, + Aring: { + name: "Aring", + char: "Å", + stdCode: null, + macCode: 129, + winCode: 197, + pdfCode: 197, + utfCode: 197 + }, + Atilde: { + name: "Atilde", + char: "Ã", + stdCode: null, + macCode: 204, + winCode: 195, + pdfCode: 195, + utfCode: 195 + }, + B: { + name: "B", + char: "B", + stdCode: 66, + macCode: 66, + winCode: 66, + pdfCode: 66, + utfCode: 66 + }, + C: { + name: "C", + char: "C", + stdCode: 67, + macCode: 67, + winCode: 67, + pdfCode: 67, + utfCode: 67 + }, + Ccedilla: { + name: "Ccedilla", + char: "Ç", + stdCode: null, + macCode: 130, + winCode: 199, + pdfCode: 199, + utfCode: 199 + }, + D: { + name: "D", + char: "D", + stdCode: 68, + macCode: 68, + winCode: 68, + pdfCode: 68, + utfCode: 68 + }, + E: { + name: "E", + char: "E", + stdCode: 69, + macCode: 69, + winCode: 69, + pdfCode: 69, + utfCode: 69 + }, + Eacute: { + name: "Eacute", + char: "É", + stdCode: null, + macCode: 131, + winCode: 201, + pdfCode: 201, + utfCode: 201 + }, + Ecircumflex: { + name: "Ecircumflex", + char: "Ê", + stdCode: null, + macCode: 230, + winCode: 202, + pdfCode: 202, + utfCode: 202 + }, + Edieresis: { + name: "Edieresis", + char: "Ë", + stdCode: null, + macCode: 232, + winCode: 203, + pdfCode: 203, + utfCode: 203 + }, + Egrave: { + name: "Egrave", + char: "È", + stdCode: null, + macCode: 233, + winCode: 200, + pdfCode: 200, + utfCode: 200 + }, + Eth: { + name: "Eth", + char: "Ð", + stdCode: null, + macCode: null, + winCode: 208, + pdfCode: 208, + utfCode: 208 + }, + Euro: { + name: "Euro", + char: "€", + stdCode: null, + macCode: null, + winCode: 128, + pdfCode: 160, + utfCode: 8364, + }, + F: { + name: "F", + char: "F", + stdCode: 70, + macCode: 70, + winCode: 70, + pdfCode: 70, + utfCode: 70 + }, + G: { + name: "G", + char: "G", + stdCode: 71, + macCode: 71, + winCode: 71, + pdfCode: 71, + utfCode: 71 + }, + H: { + name: "H", + char: "H", + stdCode: 72, + macCode: 72, + winCode: 72, + pdfCode: 72, + utfCode: 72 + }, + I: { + name: "I", + char: "I", + stdCode: 73, + macCode: 73, + winCode: 73, + pdfCode: 73, + utfCode: 73 + }, + Iacute: { + name: "Iacute", + char: "Í", + stdCode: null, + macCode: 234, + winCode: 205, + pdfCode: 205, + utfCode: 205 + }, + Icircumflex: { + name: "Icircumflex", + char: "Î", + stdCode: null, + macCode: 235, + winCode: 206, + pdfCode: 206, + utfCode: 206 + }, + Idieresis: { + name: "Idieresis", + char: "Ï", + stdCode: null, + macCode: 236, + winCode: 207, + pdfCode: 207, + utfCode: 207 + }, + Igrave: { + name: "Igrave", + char: "Ì", + stdCode: null, + macCode: 237, + winCode: 204, + pdfCode: 204, + utfCode: 204 + }, + J: { + name: "J", + char: "J", + stdCode: 74, + macCode: 74, + winCode: 74, + pdfCode: 74, + utfCode: 74 + }, + K: { + name: "K", + char: "K", + stdCode: 75, + macCode: 75, + winCode: 75, + pdfCode: 75, + utfCode: 75 + }, + L: { + name: "L", + char: "L", + stdCode: 76, + macCode: 76, + winCode: 76, + pdfCode: 76, + utfCode: 76 + }, + Lslash: { + name: "Lslash", + char: "Ł", + stdCode: 232, + macCode: null, + winCode: null, + pdfCode: 149, + utfCode: 321 + }, + M: { + name: "M", + char: "M", + stdCode: 77, + macCode: 77, + winCode: 77, + pdfCode: 77, + utfCode: 77 + }, + N: { + name: "N", + char: "N", + stdCode: 78, + macCode: 78, + winCode: 78, + pdfCode: 78, + utfCode: 78 + }, + Ntilde: { + name: "Ntilde", + char: "Ñ", + stdCode: null, + macCode: 132, + winCode: 209, + pdfCode: 209, + utfCode: 209 + }, + O: { + name: "O", + char: "O", + stdCode: 79, + macCode: 79, + winCode: 79, + pdfCode: 79, + utfCode: 79 + }, + OE: { + name: "OE", + char: "OE", + stdCode: 234, + macCode: 206, + winCode: 140, + pdfCode: 150, + utfCode: 338 + }, + Oacute: { + name: "Oacute", + char: "Ó", + stdCode: null, + macCode: 238, + winCode: 211, + pdfCode: 211, + utfCode: 211 + }, + Ocircumflex: { + name: "Ocircumflex", + char: "Ô", + stdCode: null, + macCode: 239, + winCode: 212, + pdfCode: 212, + utfCode: 212 + }, + Odieresis: { + name: "Odieresis", + char: "Ö", + stdCode: null, + macCode: 133, + winCode: 214, + pdfCode: 214, + utfCode: 214 + }, + Ograve: { + name: "Ograve", + char: "Ò", + stdCode: null, + macCode: 241, + winCode: 210, + pdfCode: 210, + utfCode: 210 + }, + Oslash: { + name: "Oslash", + char: "Ø", + stdCode: 233, + macCode: 175, + winCode: 216, + pdfCode: 216, + utfCode: 216 + }, + Otilde: { + name: "Otilde", + char: "Õ", + stdCode: null, + macCode: 205, + winCode: 213, + pdfCode: 213, + utfCode: 213 + }, + P: { + name: "P", + char: "P", + stdCode: 80, + macCode: 80, + winCode: 80, + pdfCode: 80, + utfCode: 80 + }, + Q: { + name: "Q", + char: "Q", + stdCode: 81, + macCode: 81, + winCode: 81, + pdfCode: 81, + utfCode: 81 + }, + R: { + name: "R", + char: "R", + stdCode: 82, + macCode: 82, + winCode: 82, + pdfCode: 82, + utfCode: 82 + }, + S: { + name: "S", + char: "S", + stdCode: 83, + macCode: 83, + winCode: 83, + pdfCode: 83, + utfCode: 83 + }, + Scaron: { + name: "Scaron", + char: "Š", + stdCode: null, + macCode: null, + winCode: 138, + pdfCode: 151, + utfCode: 352 + }, + T: { + name: "T", + char: "T", + stdCode: 84, + macCode: 84, + winCode: 84, + pdfCode: 84, + utfCode: 84 + }, + Thorn: { + name: "Thorn", + char: "Þ", + stdCode: null, + macCode: null, + winCode: 222, + pdfCode: 222, + utfCode: 222 + }, + U: { + name: "U", + char: "U", + stdCode: 85, + macCode: 85, + winCode: 85, + pdfCode: 85, + utfCode: 85 + }, + Uacute: { + name: "Uacute", + char: "Ú", + stdCode: null, + macCode: 242, + winCode: 218, + pdfCode: 218, + utfCode: 218 + }, + Ucircumflex: { + name: "Ucircumflex", + char: "Û", + stdCode: null, + macCode: 243, + winCode: 219, + pdfCode: 219, + utfCode: 219 + }, + Udieresis: { + name: "Udieresis", + char: "Ü", + stdCode: null, + macCode: 134, + winCode: 220, + pdfCode: 220, + utfCode: 220 + }, + Ugrave: { + name: "Ugrave", + char: "Ù", + stdCode: null, + macCode: 244, + winCode: 217, + pdfCode: 217, + utfCode: 217 + }, + V: { + name: "V", + char: "V", + stdCode: 86, + macCode: 86, + winCode: 86, + pdfCode: 86, + utfCode: 86 + }, + W: { + name: "W", + char: "W", + stdCode: 87, + macCode: 87, + winCode: 87, + pdfCode: 87, + utfCode: 87 + }, + X: { + name: "X", + char: "X", + stdCode: 88, + macCode: 88, + winCode: 88, + pdfCode: 88, + utfCode: 88 + }, + Y: { + name: "Y", + char: "Y", + stdCode: 89, + macCode: 89, + winCode: 89, + pdfCode: 89, + utfCode: 89 + }, + Yacute: { + name: "Yacute", + char: "Ý", + stdCode: null, + macCode: null, + winCode: 221, + pdfCode: 221, + utfCode: 221 + }, + Ydieresis: { + name: "Ydieresis", + char: "Ÿ", + stdCode: null, + macCode: 217, + winCode: 159, + pdfCode: 152, + utfCode: 376 + }, + Z: { + name: "Z", + char: "Z", + stdCode: 90, + macCode: 90, + winCode: 90, + pdfCode: 90, + utfCode: 90 + }, + Zcaron: { + name: "Zcaron", + char: "Ž", + stdCode: null, + macCode: null, + winCode: 142, + pdfCode: 153, + utfCode: 381 + }, + a: { + name: "a", + char: "a", + stdCode: 97, + macCode: 97, + winCode: 97, + pdfCode: 97, + utfCode: 97 + }, + aacute: { + name: "aacute", + char: "á", + stdCode: null, + macCode: 135, + winCode: 225, + pdfCode: 225, + utfCode: 225 + }, + acircumflex: { + name: "acircumflex", + char: "â", + stdCode: null, + macCode: 137, + winCode: 226, + pdfCode: 226, + utfCode: 226 + }, + acute: { + name: "acute", + char: "´", + stdCode: 194, + macCode: 171, + winCode: 180, + pdfCode: 180, + utfCode: 180 + }, + adieresis: { + name: "adieresis", + char: "ä", + stdCode: null, + macCode: 138, + winCode: 228, + pdfCode: 228, + utfCode: 228 + }, + ae: { + name: "ae", + char: "æ", + stdCode: 241, + macCode: 190, + winCode: 230, + pdfCode: 230, + utfCode: 230 + }, + agrave: { + name: "agrave", + char: "à", + stdCode: null, + macCode: 136, + winCode: 224, + pdfCode: 224, + utfCode: 224 + }, + ampersand: { + name: "ampersand", + char: "&", + stdCode: 38, + macCode: 38, + winCode: 38, + pdfCode: 38, + utfCode: 38 + }, + aring: { + name: "aring", + char: "å", + stdCode: null, + macCode: 140, + winCode: 229, + pdfCode: 229, + utfCode: 229 + }, + asciicircum: { + name: "asciicircum", + char: "^", + stdCode: 94, + macCode: 94, + winCode: 94, + pdfCode: 94, + utfCode: 94 + }, + asciitilde: { + name: "asciitilde", + char: "~", + stdCode: 126, + macCode: 126, + winCode: 126, + pdfCode: 126, + utfCode: 126 + }, + asterisk: { + name: "asterisk", + char: "*", + stdCode: 42, + macCode: 42, + winCode: 42, + pdfCode: 42, + utfCode: 42 + }, + at: { + name: "at", + char: "@", + stdCode: 64, + macCode: 64, + winCode: 64, + pdfCode: 64, + utfCode: 64 + }, + atilde: { + name: "atilde", + char: "ã", + stdCode: null, + macCode: 139, + winCode: 227, + pdfCode: 227, + utfCode: 227 + }, + b: { + name: "b", + char: "b", + stdCode: 98, + macCode: 98, + winCode: 98, + pdfCode: 98, + utfCode: 98 + }, + backslash: { + name: "backslash", + char: "\"", + stdCode: 92, + macCode: 92, + winCode: 92, + pdfCode: 92, + utfCode: 92 + }, + bar: { + name: "bar", + char: "|", + stdCode: 124, + macCode: 124, + winCode: 124, + pdfCode: 124, + utfCode: 124 + }, + braceleft: { + name: "braceleft", + char: "{", + stdCode: 123, + macCode: 123, + winCode: 123, + pdfCode: 123, + utfCode: 123 + }, + braceright: { + name: "braceright", + char: "}", + stdCode: 125, + macCode: 125, + winCode: 125, + pdfCode: 125, + utfCode: 125 + }, + bracketleft: { + name: "bracketleft", + char: "[", + stdCode: 91, + macCode: 91, + winCode: 91, + pdfCode: 91, + utfCode: 91 + }, + bracketright: { + name: "bracketright", + char: "]", + stdCode: 93, + macCode: 93, + winCode: 93, + pdfCode: 93, + utfCode: 93 + }, + breve: { + name: "breve", + char: "˘", + stdCode: 198, + macCode: 249, + winCode: null, + pdfCode: 24, + utfCode: 728 + }, + brokenbar: { + name: "brokenbar", + char: "¦", + stdCode: null, + macCode: null, + winCode: 166, + pdfCode: 166, + utfCode: 166 + }, + bullet: { + name: "bullet", + char: "•", + stdCode: 183, + macCode: 165, + winCode: 149, + pdfCode: 128, + utfCode: 8226 + }, + c: { + name: "c", + char: "c", + stdCode: 99, + macCode: 99, + winCode: 99, + pdfCode: 99, + utfCode: 99 + }, + caron: { + name: "caron", + char: "ˇ", + stdCode: 207, + macCode: 255, + winCode: null, + pdfCode: 25, + utfCode: 711 + }, + ccedilla: { + name: "ccedilla", + char: "ç", + stdCode: null, + macCode: 141, + winCode: 231, + pdfCode: 231, + utfCode: 231 + }, + cedilla: { + name: "cedilla", + char: "¸", + stdCode: 203, + macCode: 252, + winCode: 184, + pdfCode: 184, + utfCode: 184 + }, + cent: { + name: "cent", + char: "¢", + stdCode: 162, + macCode: 162, + winCode: 162, + pdfCode: 162, + utfCode: 162 + }, + circumflex: { + name: "circumflex", + char: "ˆ", + stdCode: 195, + macCode: 246, + winCode: 136, + pdfCode: 26, + utfCode: 710 + }, + colon: { + name: "colon", + char: ":", + stdCode: 58, + macCode: 58, + winCode: 58, + pdfCode: 58, + utfCode: 58 + }, + comma: { + name: "comma", + char: ",", + stdCode: 44, + macCode: 44, + winCode: 44, + pdfCode: 44, + utfCode: 44 + }, + copyright: { + name: "copyright", + char: "©", + stdCode: null, + macCode: 169, + winCode: 169, + pdfCode: 169, + utfCode: 169 + }, + currency1: { + name: "currency1", + char: "¤", + stdCode: 168, + macCode: 219, + winCode: 164, + pdfCode: 164, + utfCode: 164 + }, + d: { + name: "d", + char: "d", + stdCode: 100, + macCode: 100, + winCode: 100, + pdfCode: 100, + utfCode: 100 + }, + dagger: { + name: "dagger", + char: "†", + stdCode: 178, + macCode: 160, + winCode: 134, + pdfCode: 129, + utfCode: 8224 + }, + daggerdbl: { + name: "daggerdbl", + char: "‡", + stdCode: 179, + macCode: 224, + winCode: 135, + pdfCode: 130, + utfCode: 8225 + }, + degree: { + name: "degree", + char: "°", + stdCode: null, + macCode: 161, + winCode: 176, + pdfCode: 176, + utfCode: 176 + }, + dieresis: { + name: "dieresis", + char: "¨", + stdCode: 200, + macCode: 172, + winCode: 168, + pdfCode: 168, + utfCode: 168 + }, + divide: { + name: "divide", + char: "÷", + stdCode: null, + macCode: 214, + winCode: 247, + pdfCode: 247, + utfCode: 247 + }, + dollar: { + name: "dollar", + char: "$", + stdCode: 36, + macCode: 36, + winCode: 36, + pdfCode: 36, + utfCode: 36 + }, + dotaccent: { + name: "dotaccent", + char: "˙", + stdCode: 199, + macCode: 250, + winCode: null, + pdfCode: 27, + utfCode: 729 + }, + dotlessi: { + name: "dotlessi", + char: "ı", + stdCode: 245, + macCode: 245, + winCode: null, + pdfCode: 154, + utfCode: 305 + }, + e: { + name: "e", + char: "e", + stdCode: 101, + macCode: 101, + winCode: 101, + pdfCode: 101, + utfCode: 101 + }, + eacute: { + name: "eacute", + char: "é", + stdCode: null, + macCode: 142, + winCode: 233, + pdfCode: 233, + utfCode: 233 + }, + ecircumflex: { + name: "ecircumflex", + char: "ê", + stdCode: null, + macCode: 144, + winCode: 234, + pdfCode: 234, + utfCode: 234 + }, + edieresis: { + name: "edieresis", + char: "ë", + stdCode: null, + macCode: 145, + winCode: 235, + pdfCode: 235, + utfCode: 235 + }, + egrave: { + name: "egrave", + char: "è", + stdCode: null, + macCode: 143, + winCode: 232, + pdfCode: 232, + utfCode: 232 + }, + eight: { + name: "eight", + char: "8", + stdCode: 56, + macCode: 56, + winCode: 56, + pdfCode: 56, + utfCode: 56 + }, + ellipsis: { + name: "ellipsis", + char: "…", + stdCode: 188, + macCode: 201, + winCode: 133, + pdfCode: 131, + utfCode: 8230 + }, + emdash: { + name: "emdash", + char: "—", + stdCode: 208, + macCode: 209, + winCode: 151, + pdfCode: 132, + utfCode: 8212 + }, + endash: { + name: "endash", + char: "–", + stdCode: 177, + macCode: 208, + winCode: 150, + pdfCode: 133, + utfCode: 8211 + }, + equal: { + name: "equal", + char: "=", + stdCode: 61, + macCode: 61, + winCode: 61, + pdfCode: 61, + utfCode: 61 + }, + eth: { + name: "eth", + char: "ð", + stdCode: null, + macCode: null, + winCode: 240, + pdfCode: 240, + utfCode: 240 + }, + exclam: { + name: "exclam", + char: "!", + stdCode: 33, + macCode: 33, + winCode: 33, + pdfCode: 33, + utfCode: 33 + }, + exclamdown: { + name: "exclamdown", + char: "¡", + stdCode: 161, + macCode: 193, + winCode: 161, + pdfCode: 161, + utfCode: 161 + }, + f: { + name: "f", + char: "f", + stdCode: 102, + macCode: 102, + winCode: 102, + pdfCode: 102, + utfCode: 102 + }, + fi: { + name: "fi", + char: "fi", + stdCode: 174, + macCode: 222, + winCode: null, + pdfCode: 147, + utfCode: 64257 + }, + five: { + name: "five", + char: "5", + stdCode: 53, + macCode: 53, + winCode: 53, + pdfCode: 53, + utfCode: 53 + }, + fl: { + name: "fl", + char: "fl", + stdCode: 175, + macCode: 223, + winCode: null, + pdfCode: 148, + utfCode: 64258 + }, + florin: { + name: "florin", + char: "ƒ", + stdCode: 166, + macCode: 196, + winCode: 131, + pdfCode: 134, + utfCode: 402 + }, + four: { + name: "four", + char: "4", + stdCode: 52, + macCode: 52, + winCode: 52, + pdfCode: 52, + utfCode: 52 + }, + fraction: { + name: "fraction", + char: "⁄", + stdCode: 164, + macCode: 218, + winCode: null, + pdfCode: 135, + utfCode: 8260 + }, + g: { + name: "g", + char: "g", + stdCode: 103, + macCode: 103, + winCode: 103, + pdfCode: 103, + utfCode: 103 + }, + germandbls: { + name: "germandbls", + char: "ß", + stdCode: 251, + macCode: 167, + winCode: 223, + pdfCode: 223, + utfCode: 223 + }, + grave: { + name: "grave", + char: "`", + stdCode: 193, + macCode: 96, + winCode: 96, + pdfCode: 96, + utfCode: 96 + }, + greater: { + name: "greater", + char: ">", + stdCode: 62, + macCode: 62, + winCode: 62, + pdfCode: 62, + utfCode: 62 + }, + guillemotleft: { + name: "guillemotleft", + char: "«", + stdCode: 171, + macCode: 199, + winCode: 171, + pdfCode: 171, + utfCode: 171 + }, + guillemotright: { + name: "guillemotright", + char: "»", + stdCode: 187, + macCode: 200, + winCode: 187, + pdfCode: 187, + utfCode: 187 + }, + guilsinglleft: { + name: "guilsinglleft", + char: "‹", + stdCode: 172, + macCode: 220, + winCode: 139, + pdfCode: 136, + utfCode: 8249 + }, + guilsinglright: { + name: "guilsinglright", + char: "›", + stdCode: 173, + macCode: 221, + winCode: 155, + pdfCode: 137, + utfCode: 8250 + }, + h: { + name: "h", + char: "h", + stdCode: 104, + macCode: 104, + winCode: 104, + pdfCode: 104, + utfCode: 104 + }, + hungarumlaut: { + name: "hungarumlaut", + char: "˝", + stdCode: 205, + macCode: 253, + winCode: null, + pdfCode: 28, + utfCode: 733 + }, + hyphen: { + name: "hyphen", + char: "-", + stdCode: 45, + macCode: 45, + winCode: 45, + pdfCode: 45, + utfCode: 45 + }, + i: { + name: "i", + char: "i", + stdCode: 105, + macCode: 105, + winCode: 105, + pdfCode: 105, + utfCode: 105 + }, + iacute: { + name: "iacute", + char: "í", + stdCode: null, + macCode: 146, + winCode: 237, + pdfCode: 237, + utfCode: 237 + }, + icircumflex: { + name: "icircumflex", + char: "î", + stdCode: null, + macCode: 148, + winCode: 238, + pdfCode: 238, + utfCode: 238 + }, + idieresis: { + name: "idieresis", + char: "ï", + stdCode: null, + macCode: 149, + winCode: 239, + pdfCode: 239, + utfCode: 239 + }, + igrave: { + name: "igrave", + char: "ì", + stdCode: null, + macCode: 147, + winCode: 236, + pdfCode: 236, + utfCode: 236 + }, + j: { + name: "j", + char: "j", + stdCode: 106, + macCode: 106, + winCode: 106, + pdfCode: 106, + utfCode: 106 + }, + k: { + name: "k", + char: "k", + stdCode: 107, + macCode: 107, + winCode: 107, + pdfCode: 107, + utfCode: 107 + }, + l: { + name: "l", + char: "l", + stdCode: 108, + macCode: 108, + winCode: 108, + pdfCode: 108, + utfCode: 108 + }, + less: { + name: "less", + char: "<", + stdCode: 60, + macCode: 60, + winCode: 60, + pdfCode: 60, + utfCode: 60 + }, + logicalnot: { + name: "logicalnot", + char: "¬", + stdCode: null, + macCode: 194, + winCode: 172, + pdfCode: 172, + utfCode: 172 + }, + lslash: { + name: "lslash", + char: "ł", + stdCode: 248, + macCode: null, + winCode: null, + pdfCode: 155, + utfCode: 322 + }, + m: { + name: "m", + char: "m", + stdCode: 109, + macCode: 109, + winCode: 109, + pdfCode: 109, + utfCode: 109 + }, + macron: { + name: "macron", + char: "¯", + stdCode: 197, + macCode: 248, + winCode: 175, + pdfCode: 175, + utfCode: 175 + }, + minus: { + name: "minus", + char: "−", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: 138, + utfCode: 8722 + }, + mu: { + name: "mu", + char: "μ", + stdCode: null, + macCode: 181, + winCode: 181, + pdfCode: 181, + utfCode: 181 + }, + multiply: { + name: "multiply", + char: "×", + stdCode: null, + macCode: null, + winCode: 215, + pdfCode: 215, + utfCode: 215 + }, + n: { + name: "n", + char: "n", + stdCode: 110, + macCode: 110, + winCode: 110, + pdfCode: 110, + utfCode: 110 + }, + nine: { + name: "nine", + char: "9", + stdCode: 57, + macCode: 57, + winCode: 57, + pdfCode: 57, + utfCode: 57 + }, + ntilde: { + name: "ntilde", + char: "ñ", + stdCode: null, + macCode: 150, + winCode: 241, + pdfCode: 241, + utfCode: 241 + }, + numbersign: { + name: "numbersign", + char: "#", + stdCode: 35, + macCode: 35, + winCode: 35, + pdfCode: 35, + utfCode: 35 + }, + o: { + name: "o", + char: "o", + stdCode: 111, + macCode: 111, + winCode: 111, + pdfCode: 111, + utfCode: 111 + }, + oacute: { + name: "oacute", + char: "ó", + stdCode: null, + macCode: 151, + winCode: 243, + pdfCode: 243, + utfCode: 243 + }, + ocircumflex: { + name: "ocircumflex", + char: "ô", + stdCode: null, + macCode: 153, + winCode: 244, + pdfCode: 244, + utfCode: 244 + }, + odieresis: { + name: "odieresis", + char: "ö", + stdCode: null, + macCode: 154, + winCode: 246, + pdfCode: 246, + utfCode: 246 + }, + oe: { + name: "oe", + char: "oe", + stdCode: 250, + macCode: 207, + winCode: 156, + pdfCode: 156, + utfCode: 339 + }, + ogonek: { + name: "ogonek", + char: "˛", + stdCode: 206, + macCode: 254, + winCode: null, + pdfCode: 29, + utfCode: 731 + }, + ograve: { + name: "ograve", + char: "ò", + stdCode: null, + macCode: 152, + winCode: 242, + pdfCode: 242, + utfCode: 242 + }, + one: { + name: "one", + char: "1", + stdCode: 49, + macCode: 49, + winCode: 49, + pdfCode: 49, + utfCode: 49 + }, + onehalf: { + name: "onehalf", + char: "½", + stdCode: null, + macCode: null, + winCode: 189, + pdfCode: 189, + utfCode: 189 + }, + onequarter: { + name: "onequarter", + char: "¼", + stdCode: null, + macCode: null, + winCode: 188, + pdfCode: 188, + utfCode: 188 + }, + onesuperior: { + name: "onesuperior", + char: "¹", + stdCode: null, + macCode: null, + winCode: 185, + pdfCode: 185, + utfCode: 185 + }, + ordfeminine: { + name: "ordfeminine", + char: "ª", + stdCode: 227, + macCode: 187, + winCode: 170, + pdfCode: 170, + utfCode: 170 + }, + ordmasculine: { + name: "ordmasculine", + char: "º", + stdCode: 235, + macCode: 188, + winCode: 186, + pdfCode: 186, + utfCode: 186 + }, + oslash: { + name: "oslash", + char: "ø", + stdCode: 249, + macCode: 191, + winCode: 248, + pdfCode: 248, + utfCode: 248 + }, + otilde: { + name: "otilde", + char: "õ", + stdCode: null, + macCode: 155, + winCode: 245, + pdfCode: 245, + utfCode: 245 + }, + p: { + name: "p", + char: "p", + stdCode: 112, + macCode: 112, + winCode: 112, + pdfCode: 112, + utfCode: 112 + }, + paragraph: { + name: "paragraph", + char: "¶", + stdCode: 182, + macCode: 166, + winCode: 182, + pdfCode: 182, + utfCode: 182 + }, + parenleft: { + name: "parenleft", + char: "(", + stdCode: 40, + macCode: 40, + winCode: 40, + pdfCode: 40, + utfCode: 40 + }, + parenright: { + name: "parenright", + char: ")", + stdCode: 41, + macCode: 41, + winCode: 41, + pdfCode: 41, + utfCode: 41 + }, + percent: { + name: "percent", + char: "%", + stdCode: 37, + macCode: 37, + winCode: 37, + pdfCode: 37, + utfCode: 37 + }, + period: { + name: "period", + char: ".", + stdCode: 46, + macCode: 46, + winCode: 46, + pdfCode: 46, + utfCode: 46 + }, + periodcentered: { + name: "periodcentered", + char: "·", + stdCode: 180, + macCode: 225, + winCode: 183, + pdfCode: 183, + utfCode: 183 + }, + perthousand: { + name: "perthousand", + char: "‰", + stdCode: 189, + macCode: 228, + winCode: 137, + pdfCode: 139, + utfCode: 8240 + }, + plus: { + name: "plus", + char: "+", + stdCode: 43, + macCode: 43, + winCode: 43, + pdfCode: 43, + utfCode: 43 + }, + plusminus: { + name: "plusminus", + char: "±", + stdCode: null, + macCode: 177, + winCode: 177, + pdfCode: 177, + utfCode: 177 + }, + q: { + name: "q", + char: "q", + stdCode: 113, + macCode: 113, + winCode: 113, + pdfCode: 113, + utfCode: 113 + }, + question: { + name: "question", + char: "?", + stdCode: 63, + macCode: 63, + winCode: 63, + pdfCode: 63, + utfCode: 63 + }, + questiondown: { + name: "questiondown", + char: "¿", + stdCode: 191, + macCode: 192, + winCode: 191, + pdfCode: 191, + utfCode: 191 + }, + quotedbl: { + name: "quotedbl", + char: "\"", + stdCode: 34, + macCode: 34, + winCode: 34, + pdfCode: 34, + utfCode: 34 + }, + quotedblbase: { + name: "quotedblbase", + char: "„", + stdCode: 185, + macCode: 227, + winCode: 132, + pdfCode: 140, + utfCode: 8222 + }, + quotedblleft: { + name: "quotedblleft", + char: "“", + stdCode: 170, + macCode: 210, + winCode: 147, + pdfCode: 141, + utfCode: 8220 + }, + quotedblright: { + name: "quotedblright", + char: "”", + stdCode: 186, + macCode: 211, + winCode: 148, + pdfCode: 142, + utfCode: 8221 + }, + quoteleft: { + name: "quoteleft", + char: "‘", + stdCode: 96, + macCode: 212, + winCode: 145, + pdfCode: 143, + utfCode: 8216 + }, + quoteright: { + name: "quoteright", + char: "’", + stdCode: 39, + macCode: 213, + winCode: 146, + pdfCode: 144, + utfCode: 8217 + }, + quotesinglbase: { + name: "quotesinglbase", + char: "‚", + stdCode: 184, + macCode: 226, + winCode: 130, + pdfCode: 145, + utfCode: 8218 + }, + quotesingle: { + name: "quotesingle", + char: "'", + stdCode: 169, + macCode: 39, + winCode: 39, + pdfCode: 39, + utfCode: 39 + }, + r: { + name: "r", + char: "r", + stdCode: 114, + macCode: 114, + winCode: 114, + pdfCode: 114, + utfCode: 114 + }, + registered: { + name: "registered", + char: "®", + stdCode: null, + macCode: 168, + winCode: 174, + pdfCode: 174, + utfCode: 174 + }, + ring: { + name: "ring", + char: "°", + stdCode: 202, + macCode: 251, + winCode: null, + pdfCode: 30, + utfCode: 730 + }, + s: { + name: "s", + char: "s", + stdCode: 115, + macCode: 115, + winCode: 115, + pdfCode: 115, + utfCode: 115 + }, + scaron: { + name: "scaron", + char: "š", + stdCode: null, + macCode: null, + winCode: 154, + pdfCode: 157, + utfCode: 353 + }, + section: { + name: "section", + char: "§", + stdCode: 167, + macCode: 164, + winCode: 167, + pdfCode: 167, + utfCode: 167 + }, + semicolon: { + name: "semicolon", + char: ";", + stdCode: 59, + macCode: 59, + winCode: 59, + pdfCode: 59, + utfCode: 59 + }, + seven: { + name: "seven", + char: "7", + stdCode: 55, + macCode: 55, + winCode: 55, + pdfCode: 55, + utfCode: 55 + }, + six: { + name: "six", + char: "6", + stdCode: 54, + macCode: 54, + winCode: 54, + pdfCode: 54, + utfCode: 54 + }, + slash: { + name: "slash", + char: "/", + stdCode: 47, + macCode: 47, + winCode: 47, + pdfCode: 47, + utfCode: 47 + }, + sterling: { + name: "sterling", + char: "£", + stdCode: 163, + macCode: 163, + winCode: 163, + pdfCode: 163, + utfCode: 163 + }, + t: { + name: "t", + char: "t", + stdCode: 116, + macCode: 116, + winCode: 116, + pdfCode: 116, + utfCode: 116 + }, + thorn: { + name: "thorn", + char: "þ", + stdCode: null, + macCode: null, + winCode: 254, + pdfCode: 254, + utfCode: 254 + }, + three: { + name: "three", + char: "3", + stdCode: 51, + macCode: 51, + winCode: 51, + pdfCode: 51, + utfCode: 51 + }, + threequarters: { + name: "threequarters", + char: "¾", + stdCode: null, + macCode: null, + winCode: 190, + pdfCode: 190, + utfCode: 190 + }, + threesuperior: { + name: "threesuperior", + char: "³", + stdCode: null, + macCode: null, + winCode: 179, + pdfCode: 179, + utfCode: 179 + }, + tilde: { + name: "tilde", + char: "˜", + stdCode: 196, + macCode: 247, + winCode: 152, + pdfCode: 31, + utfCode: 732 + }, + trademark: { + name: "trademark", + char: "™", + stdCode: null, + macCode: 170, + winCode: 153, + pdfCode: 146, + utfCode: 8482 + }, + two: { + name: "two", + char: "2", + stdCode: 50, + macCode: 50, + winCode: 50, + pdfCode: 50, + utfCode: 50 + }, + twosuperior: { + name: "twosuperior", + char: "²", + stdCode: null, + macCode: null, + winCode: 178, + pdfCode: 178, + utfCode: 178 + }, + u: { + name: "u", + char: "u", + stdCode: 117, + macCode: 117, + winCode: 117, + pdfCode: 117, + utfCode: 117 + }, + uacute: { + name: "uacute", + char: "ú", + stdCode: null, + macCode: 156, + winCode: 250, + pdfCode: 250, + utfCode: 250 + }, + ucircumflex: { + name: "ucircumflex", + char: "û", + stdCode: null, + macCode: 158, + winCode: 251, + pdfCode: 251, + utfCode: 251 + }, + udieresis: { + name: "udieresis", + char: "ü", + stdCode: null, + macCode: 159, + winCode: 252, + pdfCode: 252, + utfCode: 252 + }, + ugrave: { + name: "ugrave", + char: "ù", + stdCode: null, + macCode: 157, + winCode: 249, + pdfCode: 249, + utfCode: 249 + }, + underscore: { + name: "underscore", + char: "_", + stdCode: 95, + macCode: 95, + winCode: 95, + pdfCode: 95, + utfCode: 95 + }, + v: { + name: "v", + char: "v", + stdCode: 118, + macCode: 118, + winCode: 118, + pdfCode: 118, + utfCode: 118 + }, + w: { + name: "w", + char: "w", + stdCode: 119, + macCode: 119, + winCode: 119, + pdfCode: 119, + utfCode: 119 + }, + x: { + name: "x", + char: "x", + stdCode: 120, + macCode: 120, + winCode: 120, + pdfCode: 120, + utfCode: 120 + }, + y: { + name: "y", + char: "y", + stdCode: 121, + macCode: 121, + winCode: 121, + pdfCode: 121, + utfCode: 121 + }, + yacute: { + name: "yacute", + char: "ý", + stdCode: null, + macCode: null, + winCode: 253, + pdfCode: 253, + utfCode: 253 + }, + ydieresis: { + name: "ydieresis", + char: "ÿ", + stdCode: null, + macCode: 216, + winCode: 255, + pdfCode: 255, + utfCode: 255 + }, + yen: { + name: "yen", + char: "¥", + stdCode: 165, + macCode: 180, + winCode: 165, + pdfCode: 165, + utfCode: 165 + }, + z: { + name: "z", + char: "z", + stdCode: 122, + macCode: 122, + winCode: 122, + pdfCode: 122, + utfCode: 122 + }, + zcaron: { + name: "zcaron", + char: "ž", + stdCode: null, + macCode: null, + winCode: 158, + pdfCode: 158, + utfCode: 382 + }, + zero: { + name: "zero", + char: "0", + stdCode: 48, + macCode: 48, + winCode: 48, + pdfCode: 48, + utfCode: 48 + }, + Djecyrillic: { + name: "Djecyrillic", + char: "Ђ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1026 + }, + afii10051: { + name: "afii10051", + char: "Ђ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1026 + }, + Gjecyrillic: { + name: "Gjecyrillic", + char: "Ѓ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1027 + }, + afii10052: { + name: "afii10052", + char: "Ѓ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1027 + }, + Ljecyrillic: { + name: "Ljecyrillic", + char: "Љ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1033 + }, + afii10058: { + name: "afii10058", + char: "Љ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1033 + }, + Njecyrillic: { + name: "Njecyrillic", + char: "Њ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1034 + }, + afii10059: { + name: "afii10059", + char: "Њ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1034 + }, + Kjecyrillic: { + name: "Kjecyrillic", + char: "Ќ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1036 + }, + afii10061: { + name: "afii10061", + char: "Ќ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1036 + }, + Tshecyrillic: { + name: "Tshecyrillic", + char: "Ћ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1035 + }, + afii10060: { + name: "afii10060", + char: "Ћ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1035 + }, + Dzhecyrillic: { + name: "Dzhecyrillic", + char: "Џ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1039 + }, + afii10145: { + name: "afii10145", + char: "Џ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1039 + }, + afii10100: { + name: "afii10100", + char: "ѓ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1107 + }, + gjecyrillic: { + name: "gjecyrillic", + char: "ѓ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1107 + }, + afii10099: { + name: "afii10099", + char: "ђ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1106 + }, + djecyrillic: { + name: "djecyrillic", + char: "ђ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1106 + }, + afii10106: { + name: "afii10106", + char: "љ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1113 + }, + ljecyrillic: { + name: "ljecyrillic", + char: "љ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1113 + }, + afii10107: { + name: "afii10107", + char: "њ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1114 + }, + njecyrillic: { + name: "njecyrillic", + char: "њ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1114 + }, + afii10109: { + name: "afii10109", + char: "ќ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1116 + }, + kjecyrillic: { + name: "kjecyrillic", + char: "ќ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1116 + }, + afii10108: { + name: "afii10108", + char: "ћ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1115 + }, + tshecyrillic: { + name: "tshecyrillic", + char: "ћ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1115 + }, + afii10193: { + name: "afii10193", + char: "џ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1119 + }, + dzhecyrillic: { + name: "dzhecyrillic", + char: "џ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1119 + }, + Ushortcyrillic: { + name: "Ushortcyrillic", + char: "Ў", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1038 + }, + afii10062: { + name: "afii10062", + char: "Ў", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1038 + }, + afii10110: { + name: "afii10110", + char: "ў", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1118 + }, + ushortcyrillic: { + name: "ushortcyrillic", + char: "ў", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1118 + }, + Jecyrillic: { + name: "Jecyrillic", + char: "Ј", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1032 + }, + afii10057: { + name: "afii10057", + char: "Ј", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1032 + }, + Gheupturncyrillic: { + name: "Gheupturncyrillic", + char: "Ґ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1168 + }, + afii10050: { + name: "afii10050", + char: "Ґ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1168 + }, + Iocyrillic: { + name: "Iocyrillic", + char: "Ё", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1025 + }, + afii10023: { + name: "afii10023", + char: "Ё", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1025 + }, + Ecyrillic: { + name: "Ecyrillic", + char: "Є", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1028 + }, + afii10053: { + name: "afii10053", + char: "Є", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1028 + }, + Yicyrillic: { + name: "Yicyrillic", + char: "Ї", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1031 + }, + afii10056: { + name: "afii10056", + char: "Ї", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1031 + }, + Icyrillic: { + name: "Icyrillic", + char: "І", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1030 + }, + afii10055: { + name: "afii10055", + char: "І", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1030 + }, + afii10103: { + name: "afii10103", + char: "і", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1110 + }, + icyrillic: { + name: "icyrillic", + char: "і", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1110 + }, + afii10098: { + name: "afii10098", + char: "ґ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1169 + }, + gheupturncyrillic: { + name: "gheupturncyrillic", + char: "ґ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1169 + }, + afii10071: { + name: "afii10071", + char: "ё", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1105 + }, + iocyrillic: { + name: "iocyrillic", + char: "ё", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1105 + }, + afii10101: { + name: "afii10101", + char: "є", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1108 + }, + ecyrillic: { + name: "ecyrillic", + char: "є", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1108 + }, + afii10105: { + name: "afii10105", + char: "ј", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1112 + }, + jecyrillic: { + name: "jecyrillic", + char: "ј", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1112 + }, + Dzecyrillic: { + name: "Dzecyrillic", + char: "Ѕ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1029 + }, + afii10054: { + name: "afii10054", + char: "Ѕ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1029 + }, + afii10102: { + name: "afii10102", + char: "ѕ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1109 + }, + dzecyrillic: { + name: "dzecyrillic", + char: "ѕ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1109 + }, + afii10104: { + name: "afii10104", + char: "ї", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1111 + }, + yicyrillic: { + name: "yicyrillic", + char: "ї", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1111 + }, + Acyrillic: { + name: "Acyrillic", + char: "А", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1040 + }, + afii10017: { + name: "afii10017", + char: "А", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1040 + }, + Becyrillic: { + name: "Becyrillic", + char: "Б", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1041 + }, + afii10018: { + name: "afii10018", + char: "Б", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1041 + }, + Vecyrillic: { + name: "Vecyrillic", + char: "В", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1042 + }, + afii10019: { + name: "afii10019", + char: "В", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1042 + }, + Gecyrillic: { + name: "Gecyrillic", + char: "Г", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1043 + }, + afii10020: { + name: "afii10020", + char: "Г", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1043 + }, + Decyrillic: { + name: "Decyrillic", + char: "Д", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1044 + }, + afii10021: { + name: "afii10021", + char: "Д", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1044 + }, + Iecyrillic: { + name: "Iecyrillic", + char: "Е", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1045 + }, + afii10022: { + name: "afii10022", + char: "Е", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1045 + }, + Zhecyrillic: { + name: "Zhecyrillic", + char: "Ж", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1046 + }, + afii10024: { + name: "afii10024", + char: "Ж", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1046 + }, + Zecyrillic: { + name: "Zecyrillic", + char: "З", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1047 + }, + afii10025: { + name: "afii10025", + char: "З", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1047 + }, + Iicyrillic: { + name: "Iicyrillic", + char: "И", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1048 + }, + afii10026: { + name: "afii10026", + char: "И", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1048 + }, + Iishortcyrillic: { + name: "Iishortcyrillic", + char: "Й", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1049 + }, + afii10027: { + name: "afii10027", + char: "Й", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1049 + }, + Kacyrillic: { + name: "Kacyrillic", + char: "К", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1050 + }, + afii10028: { + name: "afii10028", + char: "К", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1050 + }, + Elcyrillic: { + name: "Elcyrillic", + char: "Л", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1051 + }, + afii10029: { + name: "afii10029", + char: "Л", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1051 + }, + Emcyrillic: { + name: "Emcyrillic", + char: "М", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1052 + }, + afii10030: { + name: "afii10030", + char: "М", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1052 + }, + Encyrillic: { + name: "Encyrillic", + char: "Н", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1053 + }, + afii10031: { + name: "afii10031", + char: "Н", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1053 + }, + Ocyrillic: { + name: "Ocyrillic", + char: "О", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1054 + }, + afii10032: { + name: "afii10032", + char: "О", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1054 + }, + Pecyrillic: { + name: "Pecyrillic", + char: "П", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1055 + }, + afii10033: { + name: "afii10033", + char: "П", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1055 + }, + Ercyrillic: { + name: "Ercyrillic", + char: "Р", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1056 + }, + afii10034: { + name: "afii10034", + char: "Р", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1056 + }, + Escyrillic: { + name: "Escyrillic", + char: "С", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1057 + }, + afii10035: { + name: "afii10035", + char: "С", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1057 + }, + Tecyrillic: { + name: "Tecyrillic", + char: "Т", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1058 + }, + afii10036: { + name: "afii10036", + char: "Т", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1058 + }, + Ucyrillic: { + name: "Ucyrillic", + char: "У", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1059 + }, + afii10037: { + name: "afii10037", + char: "У", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1059 + }, + Efcyrillic: { + name: "Efcyrillic", + char: "Ф", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1060 + }, + afii10038: { + name: "afii10038", + char: "Ф", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1060 + }, + Khacyrillic: { + name: "Khacyrillic", + char: "Х", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1061 + }, + afii10039: { + name: "afii10039", + char: "Х", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1061 + }, + Tsecyrillic: { + name: "Tsecyrillic", + char: "Ц", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1062 + }, + afii10040: { + name: "afii10040", + char: "Ц", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1062 + }, + Checyrillic: { + name: "Checyrillic", + char: "Ч", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1063 + }, + afii10041: { + name: "afii10041", + char: "Ч", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1063 + }, + Shacyrillic: { + name: "Shacyrillic", + char: "Ш", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1064 + }, + afii10042: { + name: "afii10042", + char: "Ш", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1064 + }, + Shchacyrillic: { + name: "Shchacyrillic", + char: "Щ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1065 + }, + afii10043: { + name: "afii10043", + char: "Щ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1065 + }, + Hardsigncyrillic: { + name: "Hardsigncyrillic", + char: "Ъ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1066 + }, + afii10044: { + name: "afii10044", + char: "Ъ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1066 + }, + Yericyrillic: { + name: "Yericyrillic", + char: "Ы", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1067 + }, + afii10045: { + name: "afii10045", + char: "Ы", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1067 + }, + Softsigncyrillic: { + name: "Softsigncyrillic", + char: "Ь", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1068 + }, + afii10046: { + name: "afii10046", + char: "Ь", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1068 + }, + Ereversedcyrillic: { + name: "Ereversedcyrillic", + char: "Э", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1069 + }, + afii10047: { + name: "afii10047", + char: "Э", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1069 + }, + IUcyrillic: { + name: "IUcyrillic", + char: "Ю", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1070 + }, + afii10048: { + name: "afii10048", + char: "Ю", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1070 + }, + IAcyrillic: { + name: "IAcyrillic", + char: "Я", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1071 + }, + afii10049: { + name: "afii10049", + char: "Я", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1071 + }, + afii10065: { + name: "afii10065", + char: "а", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1072 + }, + acyrillic: { + name: "acyrillic", + char: "а", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1072 + }, + afii10066: { + name: "afii10066", + char: "б", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1073 + }, + becyrillic: { + name: "becyrillic", + char: "б", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1073 + }, + afii10067: { + name: "afii10067", + char: "в", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1074 + }, + vecyrillic: { + name: "vecyrillic", + char: "в", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1074 + }, + afii10068: { + name: "afii10068", + char: "г", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1075 + }, + gecyrillic: { + name: "gecyrillic", + char: "г", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1075 + }, + afii10069: { + name: "afii10069", + char: "д", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1076 + }, + decyrillic: { + name: "decyrillic", + char: "д", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1076 + }, + afii10070: { + name: "afii10070", + char: "е", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1077 + }, + iecyrillic: { + name: "iecyrillic", + char: "е", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1077 + }, + afii10072: { + name: "afii10072", + char: "ж", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1078 + }, + zhecyrillic: { + name: "zhecyrillic", + char: "ж", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1078 + }, + afii10073: { + name: "afii10073", + char: "з", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1079 + }, + zecyrillic: { + name: "zecyrillic", + char: "з", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1079 + }, + afii10074: { + name: "afii10074", + char: "и", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1080 + }, + iicyrillic: { + name: "iicyrillic", + char: "и", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1080 + }, + afii10075: { + name: "afii10075", + char: "й", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1081 + }, + iishortcyrillic: { + name: "iishortcyrillic", + char: "й", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1081 + }, + afii10076: { + name: "afii10076", + char: "к", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1082 + }, + kacyrillic: { + name: "kacyrillic", + char: "к", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1082 + }, + afii10077: { + name: "afii10077", + char: "л", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1083 + }, + elcyrillic: { + name: "elcyrillic", + char: "л", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1083 + }, + afii10078: { + name: "afii10078", + char: "м", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1084 + }, + emcyrillic: { + name: "emcyrillic", + char: "м", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1084 + }, + afii10079: { + name: "afii10079", + char: "н", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1085 + }, + encyrillic: { + name: "encyrillic", + char: "н", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1085 + }, + afii10080: { + name: "afii10080", + char: "о", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1086 + }, + ocyrillic: { + name: "ocyrillic", + char: "о", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1086 + }, + afii10081: { + name: "afii10081", + char: "п", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1087 + }, + pecyrillic: { + name: "pecyrillic", + char: "п", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1087 + }, + afii10082: { + name: "afii10082", + char: "р", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1088 + }, + ercyrillic: { + name: "ercyrillic", + char: "р", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1088 + }, + afii10083: { + name: "afii10083", + char: "с", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1089 + }, + escyrillic: { + name: "escyrillic", + char: "с", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1089 + }, + afii10084: { + name: "afii10084", + char: "т", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1090 + }, + tecyrillic: { + name: "tecyrillic", + char: "т", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1090 + }, + afii10085: { + name: "afii10085", + char: "у", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1091 + }, + ucyrillic: { + name: "ucyrillic", + char: "у", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1091 + }, + afii10086: { + name: "afii10086", + char: "ф", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1092 + }, + efcyrillic: { + name: "efcyrillic", + char: "ф", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1092 + }, + afii10087: { + name: "afii10087", + char: "х", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1093 + }, + khacyrillic: { + name: "khacyrillic", + char: "х", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1093 + }, + afii10088: { + name: "afii10088", + char: "ц", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1094 + }, + tsecyrillic: { + name: "tsecyrillic", + char: "ц", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1094 + }, + afii10089: { + name: "afii10089", + char: "ч", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1095 + }, + checyrillic: { + name: "checyrillic", + char: "ч", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1095 + }, + afii10090: { + name: "afii10090", + char: "ш", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1096 + }, + shacyrillic: { + name: "shacyrillic", + char: "ш", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1096 + }, + afii10091: { + name: "afii10091", + char: "щ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1097 + }, + shchacyrillic: { + name: "shchacyrillic", + char: "щ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1097 + }, + afii10092: { + name: "afii10092", + char: "ъ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1098 + }, + hardsigncyrillic: { + name: "hardsigncyrillic", + char: "ъ", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1098 + }, + afii10093: { + name: "afii10093", + char: "ы", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1099 + }, + yericyrillic: { + name: "yericyrillic", + char: "ы", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1099 + }, + afii10094: { + name: "afii10094", + char: "ь", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1100 + }, + softsigncyrillic: { + name: "softsigncyrillic", + char: "ь", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1100 + }, + afii10095: { + name: "afii10095", + char: "э", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1101 + }, + ereversedcyrillic: { + name: "ereversedcyrillic", + char: "э", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1101 + }, + afii10096: { + name: "afii10096", + char: "ю", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1102 + }, + iucyrillic: { + name: "iucyrillic", + char: "ю", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1102 + }, + afii10097: { + name: "afii10097", + char: "я", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1103 + }, + iacyrillic: { + name: "iacyrillic", + char: "я", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 1103 + }, + afii61352: { + name: "afii61352", + char: "№", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 8470 + }, + numero: { + name: "numero", + char: "№", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 8470 + }, + nbspace: { + name: "nbspace", + char: "", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 160 + }, + currency: { + name: "currency", + char: "¤", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 164 + }, + sfthyphen: { + name: "sfthyphen", + char: "", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 173 + }, + middot: { + name: "middot", + char: "·", + stdCode: null, + macCode: null, + winCode: null, + pdfCode: null, + utfCode: 183 + }, + ".notdef": { + name: ".notdef", + char: " ", + stdCode: 32, + macCode: 32, + winCode: 32, + pdfCode: 32, + utfCode: 32 + }, + space: { + name: "space", + char: " ", + stdCode: 32, + macCode: 32, + winCode: 32, + pdfCode: 32, + utfCode: 32 + }, +}; +function getCharCodesMapByCode(encoding) { + const map = new Map(); + let prop; + switch (encoding) { + case "StandardEncoding": + prop = "stdCode"; + break; + case "WinAnsiEncoding": + prop = "winCode"; + break; + case "MacRomanEncoding": + prop = "macCode"; + break; + case "PDFDocEncoding": + prop = "pdfCode"; + break; + case "Utf-16": + prop = "utfCode"; + break; + default: + console.log(`Unsupported encoding: '${encoding}'`); + return map; + } + for (const [, info] of Object.entries(pdfCharCodesByName)) { + if (info[prop]) { + map.set(info[prop], info); + } + } + return map; +} + +var __awaiter$14 = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class EncodingDict extends PdfDict { + get charMap() { + if (!this._charMap) { + this.refreshCharMaps(); + } + return this._charMap; + } + get codeMap() { + if (!this._codeMap) { + this.refreshCharMaps(); + } + return this._codeMap; + } + constructor() { + super(dictTypes.ENCODING); + } + static parseAsync(parseInfo) { + return __awaiter$14(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new EncodingDict(); + yield pdfObject.parsePropsAsync(parseInfo); + return { value: pdfObject, start: parseInfo.bounds.start, end: parseInfo.bounds.end }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.BaseEncoding) { + bytes.push(...encoder.encode("/BaseEncoding "), ...encoder.encode(" " + this.BaseEncoding)); + } + if (this.Differences) { + bytes.push(...encoder.encode("/Differences "), ...this.encodePrimitiveArray(this.Differences, encoder)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$14(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/BaseEncoding": + i = yield this.parseNamePropAsync(name, parser, i); + break; + case "/Differences": + const differencesValueType = yield parser.getValueTypeAtAsync(i, true); + if (differencesValueType === valueTypes.ARRAY) { + this.Differences = []; + const arrayBounds = yield parser.getArrayBoundsAtAsync(i); + let j = arrayBounds.start + 1; + while (j < arrayBounds.end - 1 && j !== -1) { + const nextArrayValueType = yield parser.getValueTypeAtAsync(j, true); + switch (nextArrayValueType) { + case valueTypes.NAME: + const arrayNameResult = yield parser.parseNameAtAsync(j, true); + this.Differences.push(arrayNameResult.value); + j = arrayNameResult.end + 1; + break; + case valueTypes.NUMBER: + const arrayNumberResult = yield parser.parseNumberAtAsync(j, true); + this.Differences.push(arrayNumberResult.value); + j = arrayNumberResult.end + 1; + break; + default: + throw new Error(`Invalid differences array value type: ${nextArrayValueType}`); + } + } + i = arrayBounds.end + 1; + } + else { + throw new Error(`Invalid differences value type: ${differencesValueType}`); + } + break; + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + }); + } + refreshCharMaps() { + if (this.Differences) { + if (typeof this.Differences[0] !== "number") { + throw new Error("First element of encoding difference array must be a number"); + } + let code; + const charInfoMap = getCharCodesMapByCode(this.BaseEncoding.substring(1)); + for (const diff of this.Differences) { + if (typeof diff === "number") { + code = diff; + continue; + } + const charInfo = pdfCharCodesByName[diff.substring(1)]; + if (charInfo) { + charInfoMap.set(code++, charInfo); + } + } + this._charMap = new Map(); + this._codeMap = new Map(); + charInfoMap.forEach((v, k) => { + this.charMap.set(k, v.char); + this._codeMap.set(v.char, k); + }); + } + } +} + +var __awaiter$13 = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class FontDescriptorDict extends PdfDict { + constructor() { + super(dictTypes.FONT_DESCRIPTOR); + this.StemH = 0; + this.Leading = 0; + this.AvgWidth = 0; + this.MaxWidth = 0; + this.MissingWidth = 0; + this.XHeight = 0; + } + static parseAsync(parseInfo) { + return __awaiter$13(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new FontDescriptorDict(); + yield pdfObject.parsePropsAsync(parseInfo); + return { value: pdfObject, start: parseInfo.bounds.start, end: parseInfo.bounds.end }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.FontName) { + bytes.push(...encoder.encode("/FontName "), ...encoder.encode(" " + this.FontName)); + } + if (this.FontFamily) { + bytes.push(...encoder.encode("/FontFamily "), ...this.FontFamily.toArray(cryptInfo)); + } + if (this.FontStretch) { + bytes.push(...encoder.encode("/FontStretch "), ...encoder.encode(" " + this.FontStretch)); + } + if (this.FontWeight) { + bytes.push(...encoder.encode("/FontWeight "), ...encoder.encode(" " + this.FontWeight)); + } + if (this.Flags) { + bytes.push(...encoder.encode("/Flags "), ...encoder.encode(" " + this.Flags)); + } + if (this.FontBBox) { + bytes.push(...encoder.encode("/FontBBox "), ...this.encodePrimitiveArray(this.FontBBox, encoder)); + } + if (this.ItalicAngle || this.ItalicAngle === 0) { + bytes.push(...encoder.encode("/ItalicAngle "), ...encoder.encode(" " + (this.ItalicAngle))); + } + if (this.Ascent) { + bytes.push(...encoder.encode("/Ascent "), ...encoder.encode(" " + this.Ascent)); + } + if (this.Descent) { + bytes.push(...encoder.encode("/Descent "), ...encoder.encode(" " + this.Descent)); + } + if (this.CapHeight) { + bytes.push(...encoder.encode("/CapHeight "), ...encoder.encode(" " + this.CapHeight)); + } + if (this.StemV) { + bytes.push(...encoder.encode("/StemV "), ...encoder.encode(" " + this.StemV)); + } + if (this.StemH) { + bytes.push(...encoder.encode("/StemV "), ...encoder.encode(" " + this.StemH)); + } + if (this.Leading) { + bytes.push(...encoder.encode("/Leading "), ...encoder.encode(" " + this.Leading)); + } + if (this.AvgWidth) { + bytes.push(...encoder.encode("/AvgWidth "), ...encoder.encode(" " + this.AvgWidth)); + } + if (this.MaxWidth) { + bytes.push(...encoder.encode("/MaxWidth "), ...encoder.encode(" " + this.MaxWidth)); + } + if (this.MissingWidth) { + bytes.push(...encoder.encode("/MissingWidth "), ...encoder.encode(" " + this.MissingWidth)); + } + if (this.XHeight) { + bytes.push(...encoder.encode("/XHeight "), ...encoder.encode(" " + this.XHeight)); + } + if (this.CharSet) { + bytes.push(...encoder.encode("/CharSet "), ...this.CharSet.toArray(cryptInfo)); + } + if (this.FontFile) { + bytes.push(...encoder.encode("/FontFile "), ...this.FontFile.toArray(cryptInfo)); + } + if (this.FontFile2) { + bytes.push(...encoder.encode("/FontFile2 "), ...this.FontFile2.toArray(cryptInfo)); + } + if (this.FontFile3) { + bytes.push(...encoder.encode("/FontFile3 "), ...this.FontFile3.toArray(cryptInfo)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$13(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/FontName": + case "/FontStretch": + i = yield this.parseNamePropAsync(name, parser, i); + break; + case "/FontFile": + case "/FontFile2": + case "/FontFile3": + i = yield this.parseRefPropAsync(name, parser, i); + break; + case "/Flags": + i = yield this.parseNumberPropAsync(name, parser, i, false); + break; + case "/FontWeight": + case "/ItalicAngle": + case "/Ascent": + case "/Descent": + case "/Leading": + case "/CapHeight": + case "/XHeight": + case "/StemV": + case "/StemH": + case "/AvgWidth": + case "/MaxWidth": + case "/MissingWidth": + i = yield this.parseNumberPropAsync(name, parser, i, true); + break; + case "/FontBBox": + i = yield this.parseNumberArrayPropAsync(name, parser, i, true); + break; + case "/CharSet": + case "/FontFamily": + const propType = yield parser.getValueTypeAtAsync(i); + if (propType === valueTypes.STRING_HEX) { + i = yield this.parseHexPropAsync(name, parser, i); + } + else if (propType === valueTypes.STRING_LITERAL) { + i = yield this.parseLiteralPropAsync(name, parser, i); + } + else { + throw new Error(`Unsupported '${name}' property value type: '${propType}'`); + } + break; + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + if (!this.FontName + || (!this.Flags && this.Flags !== 0) + || (!this.ItalicAngle && this.ItalicAngle !== 0)) { + throw new Error("Not all required properties parsed"); + } + }); + } +} + +var __awaiter$12 = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +const cyrillicEncodingDifferences = [ + 128, + "/Djecyrillic", + "/Gjecyrillic", + "/quotesinglbase", + "/afii10100", + "/quotedblbase", + "/ellipsis", + "/dagger", + "/daggerdbl", + "/Euro", + "/perthousand", + "/Ljecyrillic", + "/guilsinglleft", + "/Njecyrillic", + "/Kjecyrillic", + "/Tshecyrillic", + "/Dzhecyrillic", + "/afii10099", + "/quoteleft", + "/quoteright", + "/quotedblleft", + "/quotedblright", + "/bullet", + "/endash", + "/emdash", + "/.notdef", + "/trademark", + "/afii10106", + "/guilsinglright", + "/afii10107", + "/afii10109", + "/afii10108", + "/afii10193", + "/nbspace", + "/Ushortcyrillic", + "/afii10110", + "/Jecyrillic", + "/currency", + "/Gheupturncyrillic", + "/brokenbar", + "/section", + "/Iocyrillic", + "/copyright", + "/Ecyrillic", + "/guillemotleft", + "/logicalnot", + "/sfthyphen", + "/registered", + "/Yicyrillic", + "/degree", + "/plusminus", + "/Icyrillic", + "/afii10103", + "/afii10098", + "/mu", + "/paragraph", + "/middot", + "/afii10071", + "/afii61352", + "/afii10101", + "/guillemotright", + "/afii10105", + "/Dzecyrillic", + "/afii10102", + "/afii10104", + "/Acyrillic", + "/Becyrillic", + "/Vecyrillic", + "/Gecyrillic", + "/Decyrillic", + "/Iecyrillic", + "/Zhecyrillic", + "/Zecyrillic", + "/Iicyrillic", + "/Iishortcyrillic", + "/Kacyrillic", + "/Elcyrillic", + "/Emcyrillic", + "/Encyrillic", + "/Ocyrillic", + "/Pecyrillic", + "/Ercyrillic", + "/Escyrillic", + "/Tecyrillic", + "/Ucyrillic", + "/Efcyrillic", + "/Khacyrillic", + "/Tsecyrillic", + "/Checyrillic", + "/Shacyrillic", + "/Shchacyrillic", + "/Hardsigncyrillic", + "/Yericyrillic", + "/Softsigncyrillic", + "/Ereversedcyrillic", + "/IUcyrillic", + "/IAcyrillic", + "/acyrillic", + "/afii10066", + "/afii10067", + "/afii10068", + "/afii10069", + "/afii10070", + "/afii10072", + "/afii10073", + "/afii10074", + "/afii10075", + "/afii10076", + "/afii10077", + "/afii10078", + "/afii10079", + "/afii10080", + "/afii10081", + "/afii10082", + "/afii10083", + "/afii10084", + "/afii10085", + "/afii10086", + "/afii10087", + "/afii10088", + "/afii10089", + "/afii10090", + "/afii10091", + "/afii10092", + "/afii10093", + "/afii10094", + "/afii10095", + "/afii10096", + "/afii10097" +]; +class FontDict extends PdfDict { + get name() { + return this._name; + } + get encoding() { + return this._encoding; + } + set encoding(value) { + this._encoding = value; + this.Encoding = value.ref + ? new ObjectId(value.ref.id, value.ref.generation) + : null; + } + get encodingValue() { + var _a; + if (!this.Encoding && ((_a = this._encoding) === null || _a === void 0 ? void 0 : _a.ref)) { + this.Encoding = new ObjectId(this._encoding.ref.id, this._encoding.ref.generation); + } + return this.Encoding; + } + get descriptor() { + return this._descriptor; + } + set descriptor(value) { + this._descriptor = value; + this.FontDescriptor = value.ref + ? new ObjectId(value.ref.id, value.ref.generation) + : null; + } + get descriptorValue() { + var _a; + if (!this.FontDescriptor && ((_a = this._descriptor) === null || _a === void 0 ? void 0 : _a.ref)) { + this.FontDescriptor = new ObjectId(this._descriptor.ref.id, this._descriptor.ref.generation); + } + return this.FontDescriptor; + } + get toUtfCmap() { + return this._toUtfCmap; + } + get isMonospace() { + var _a; + if (!this._descriptor) { + return false; + } + const flags = (_a = this._descriptor) === null || _a === void 0 ? void 0 : _a.Flags; + return !!ByteUtils.getBit(flags, 0); + } + get isSerif() { + var _a; + if (!this._descriptor) { + return false; + } + const flags = (_a = this._descriptor) === null || _a === void 0 ? void 0 : _a.Flags; + return !!ByteUtils.getBit(flags, 1); + } + get isScript() { + var _a; + if (!this._descriptor) { + return false; + } + const flags = (_a = this._descriptor) === null || _a === void 0 ? void 0 : _a.Flags; + return !!ByteUtils.getBit(flags, 3); + } + get isItalic() { + var _a; + if (!this._descriptor) { + return false; + } + const flags = (_a = this._descriptor) === null || _a === void 0 ? void 0 : _a.Flags; + return !!ByteUtils.getBit(flags, 6); + } + constructor() { + super(dictTypes.FONT); + } + static newFontMap() { + const map = new Map(); + const encoding = new EncodingDict(); + encoding.BaseEncoding = "/WinAnsiEncoding"; + encoding.Differences = cyrillicEncodingDifferences.slice(); + map.set("arial", FontDict.createArialFont(encoding)); + map.set("calibri", FontDict.createCalibriFont(encoding)); + map.set("cambria", FontDict.createCambriaFont(encoding)); + map.set("courier", FontDict.createCourierFont(encoding)); + map.set("tnr", FontDict.createTnrFont(encoding)); + map.set("verdana", FontDict.createVerdanaFont(encoding)); + return map; + } + static parseAsync(parseInfo) { + return __awaiter$12(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new FontDict(); + yield pdfObject.parsePropsAsync(parseInfo); + return { + value: pdfObject.initProxy(), + start: parseInfo.bounds.start, + end: parseInfo.bounds.end, + }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + static createArialFont(encoding) { + const descriptor = new FontDescriptorDict(); + descriptor.FontName = "/ArialMT"; + descriptor.Flags = 32; + descriptor.ItalicAngle = 0; + descriptor.Ascent = 905; + descriptor.Descent = -211; + descriptor.FontBBox = [-664, -324, 2000, 1039]; + descriptor.CapHeight = 716; + descriptor.StemV = 0; + const font = new FontDict(); + font.encoding = encoding; + font.descriptor = descriptor; + font.Subtype = "/TrueType"; + font.BaseFont = "/ArialMT"; + font.FirstChar = 32; + font.LastChar = 255; + font.Widths = [277, 277, 354, 556, 556, 889, 666, 190, 333, 333, 389, 583, 277, 333, + 277, 277, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 277, 277, 583, 583, + 583, 556, 925, 666, 666, 722, 722, 666, 610, 777, 722, 277, 500, 666, 556, 833, + 722, 777, 666, 777, 722, 666, 610, 722, 666, 943, 666, 666, 610, 277, 277, 277, + 469, 556, 333, 556, 556, 500, 556, 556, 277, 556, 556, 222, 222, 500, 222, 833, + 556, 556, 556, 556, 333, 500, 277, 556, 500, 722, 500, 500, 500, 333, 259, 333, + 583, 750, 864, 541, 222, 364, 333, 1000, 556, 556, 556, 1000, 1014, 333, 893, + 582, 854, 718, 556, 222, 222, 333, 333, 350, 556, 1000, 750, 1000, 906, 333, + 812, 437, 556, 552, 277, 635, 500, 500, 556, 488, 259, 556, 666, 736, 718, 556, + 583, 333, 736, 277, 399, 548, 277, 222, 411, 576, 537, 333, 556, 953, 510, 556, + 222, 666, 500, 277, 666, 656, 666, 541, 677, 666, 923, 604, 718, 718, 582, 656, + 833, 722, 777, 718, 666, 722, 610, 635, 760, 666, 739, 666, 916, 937, 791, 885, + 656, 718, 879, 722, 556, 572, 531, 364, 583, 556, 668, 458, 558, 558, 437, 583, + 687, 552, 556, 541, 556, 500, 458, 500, 822, 500, 572, 520, 802, 822, 625, 718, + 520, 510, 750, 541,]; + font._name = "/tspdfFarial"; + return font; + } + static createCalibriFont(encoding) { + const descriptor = new FontDescriptorDict(); + descriptor.FontName = "/Calibri"; + descriptor.Flags = 32; + descriptor.ItalicAngle = 0; + descriptor.Ascent = 750; + descriptor.Descent = -250; + descriptor.FontBBox = [-502, -312, 1240, 1026]; + descriptor.CapHeight = 631; + descriptor.StemV = 0; + const font = new FontDict(); + font.encoding = encoding; + font.descriptor = descriptor; + font.Subtype = "/TrueType"; + font.BaseFont = "/Calibri"; + font.FirstChar = 32; + font.LastChar = 255; + font.Widths = [226, 325, 400, 498, 506, 714, 682, 220, 303, 303, 498, 498, 249, 306, + 252, 386, 506, 506, 506, 506, 506, 506, 506, 506, 506, 506, 267, 267, 498, 498, 498, + 463, 894, 578, 543, 533, 615, 488, 459, 630, 623, 251, 318, 519, 420, 854, 645, 662, + 516, 672, 542, 459, 487, 641, 567, 889, 519, 487, 468, 306, 386, 306, 498, 498, 291, + 479, 525, 422, 525, 497, 305, 470, 525, 229, 239, 454, 229, 798, 525, 527, 525, 525, + 348, 391, 334, 525, 451, 714, 433, 452, 395, 314, 460, 314, 498, 506, 624, 429, 249, + 345, 418, 690, 498, 498, 506, 967, 872, 338, 876, 542, 618, 619, 540, 249, 249, 418, + 418, 498, 498, 905, 0, 705, 750, 338, 769, 463, 532, 524, 226, 527, 452, 318, 498, + 432, 498, 498, 488, 834, 547, 512, 498, 306, 506, 251, 338, 498, 251, 229, 354, 549, + 585, 252, 497, 890, 443, 512, 239, 459, 391, 229, 578, 537, 543, 429, 644, 488, 800, + 473, 641, 641, 542, 610, 854, 623, 662, 621, 516, 533, 487, 527, 697, 519, 638, 555, + 868, 889, 614, 761, 531, 547, 878, 555, 479, 532, 479, 345, 558, 497, 688, 422, 540, + 540, 463, 510, 676, 534, 527, 520, 525, 422, 387, 452, 624, 433, 541, 468, 728, 749, + 536, 666, 469, 442, 721, 474,]; + font._name = "/tspdfFcalibri"; + return font; + } + static createCambriaFont(encoding) { + const descriptor = new FontDescriptorDict(); + descriptor.FontName = "/Cambria"; + descriptor.Flags = 32; + descriptor.ItalicAngle = 0; + descriptor.Ascent = 950; + descriptor.Descent = -222; + descriptor.FontBBox = [-1474, -2463, 2867, 3116]; + descriptor.CapHeight = 666; + descriptor.StemV = 0; + const font = new FontDict(); + font.encoding = encoding; + font.descriptor = descriptor; + font.Subtype = "/TrueType"; + font.BaseFont = "/Cambria"; + font.FirstChar = 32; + font.LastChar = 255; + font.Widths = [220, 285, 393, 619, 505, 889, 687, 236, 381, 381, 427, 553, 205, 332, + 205, 490, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 263, 263, 553, 553, + 553, 422, 885, 623, 611, 562, 661, 575, 536, 610, 686, 324, 306, 629, 536, 815, + 680, 653, 567, 653, 621, 496, 592, 647, 603, 921, 571, 570, 537, 350, 490, 350, + 553, 370, 284, 488, 547, 440, 554, 487, 302, 494, 551, 277, 266, 524, 271, 832, + 558, 530, 556, 546, 413, 429, 338, 552, 503, 774, 483, 503, 454, 387, 316, 387, + 712, 658, 738, 534, 205, 446, 360, 751, 516, 516, 628, 1160, 935, 302, 932, 649, + 752, 666, 538, 221, 221, 375, 375, 443, 500, 1000, 0, 679, 763, 302, 797, 540, + 551, 566, 220, 600, 503, 306, 543, 501, 316, 500, 575, 850, 569, 487, 553, 332, + 850, 324, 375, 553, 324, 277, 416, 543, 587, 282, 487, 927, 470, 487, 266, 496, + 429, 277, 623, 599, 611, 534, 654, 575, 922, 542, 691, 691, 649, 677, 815, 686, + 653, 674, 567, 562, 592, 600, 778, 571, 671, 625, 926, 926, 731, 850, 597, 573, + 920, 630, 488, 541, 522, 446, 558, 487, 713, 458, 589, 589, 540, 559, 672, 588, + 530, 566, 556, 440, 511, 503, 685, 483, 569, 530, 800, 800, 617, 748, + 514, 470, 767, 530,]; + font._name = "/tspdfFcambria"; + return font; + } + static createCourierFont(encoding) { + const descriptor = new FontDescriptorDict(); + descriptor.FontName = "/CourierNewPSMT"; + descriptor.Flags = 32; + descriptor.ItalicAngle = 0; + descriptor.Ascent = 832; + descriptor.Descent = -300; + descriptor.FontBBox = [-121, -679, 622, 1020]; + descriptor.CapHeight = 571; + descriptor.StemV = 0; + const font = new FontDict(); + font.encoding = encoding; + font.descriptor = descriptor; + font.Subtype = "/TrueType"; + font.BaseFont = "/CourierNewPSMT"; + font.FirstChar = 32; + font.LastChar = 255; + font.Widths = [600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600,]; + font._name = "/tspdfFcourier"; + return font; + } + static createTnrFont(encoding) { + const descriptor = new FontDescriptorDict(); + descriptor.FontName = "/TimesNewRomanPSMT"; + descriptor.Flags = 32; + descriptor.ItalicAngle = 0; + descriptor.Ascent = 891; + descriptor.Descent = -216; + descriptor.FontBBox = [-568, -306, 2045, 1039]; + descriptor.CapHeight = 662; + descriptor.StemV = 0; + const font = new FontDict(); + font.encoding = encoding; + font.descriptor = descriptor; + font.Subtype = "/TrueType"; + font.BaseFont = "/TimesNewRomanPSMT"; + font.FirstChar = 32; + font.LastChar = 255; + font.Widths = [250, 333, 408, 500, 500, 833, 777, 180, 333, 333, 500, 563, 250, 333, + 250, 277, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 277, 277, 563, 563, + 563, 443, 920, 722, 666, 666, 722, 610, 556, 722, 722, 333, 389, 722, 610, 889, + 722, 722, 556, 722, 666, 556, 610, 722, 722, 943, 722, 722, 610, 333, 277, 333, + 469, 500, 333, 443, 500, 443, 500, 443, 333, 500, 500, 277, 277, 500, 277, 777, + 500, 500, 500, 500, 333, 389, 277, 500, 500, 722, 500, 500, 443, 479, 200, 479, + 541, 777, 751, 578, 333, 410, 443, 1000, 500, 500, 500, 1000, 872, 333, 872, 666, + 741, 722, 482, 333, 333, 443, 443, 350, 500, 1000, 777, 979, 727, 333, 723, 485, + 500, 535, 250, 708, 500, 389, 500, 450, 200, 500, 610, 759, 660, 500, 563, 333, + 759, 333, 399, 548, 333, 277, 351, 576, 453, 333, 443, 954, 429, 500, 277, 556, + 389, 277, 722, 574, 666, 578, 682, 610, 895, 500, 722, 722, 666, 678, 889, 722, + 722, 722, 556, 666, 610, 708, 790, 722, 722, 649, 953, 953, 706, 872, 574, 660, + 973, 666, 443, 508, 472, 410, 508, 443, 690, 395, 535, 535, 485, 499, 632, 535, + 500, 535, 500, 443, 437, 500, 647, 500, 535, 502, 770, 770, 517, 671, + 456, 429, 747, 459,]; + font._name = "/tspdfFtnr"; + return font; + } + static createVerdanaFont(encoding) { + const descriptor = new FontDescriptorDict(); + descriptor.FontName = "/Verdana"; + descriptor.Flags = 32; + descriptor.ItalicAngle = 0; + descriptor.Ascent = 1005; + descriptor.Descent = -209; + descriptor.FontBBox = [-559, -303, 1522, 1050]; + descriptor.CapHeight = 727; + descriptor.StemV = 0; + const font = new FontDict(); + font.encoding = encoding; + font.descriptor = descriptor; + font.Subtype = "/TrueType"; + font.BaseFont = "/Verdana"; + font.FirstChar = 32; + font.LastChar = 255; + font.Widths = [351, 393, 458, 818, 635, 931, 726, 268, 454, 454, 635, 818, 363, 454, + 363, 454, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 454, 454, 818, 818, 818, + 545, 1000, 683, 685, 698, 770, 632, 574, 775, 751, 420, 454, 692, 556, 842, 748, 787, + 603, 787, 695, 683, 616, 731, 683, 988, 685, 615, 685, 454, 454, 454, 818, 635, 635, + 600, 623, 520, 623, 595, 351, 623, 632, 274, 344, 591, 274, 972, 632, 606, 623, 623, + 426, 520, 394, 632, 591, 818, 591, 591, 525, 634, 454, 634, 818, 1000, 792, 566, 268, + 471, 458, 818, 635, 635, 635, 1374, 1071, 454, 966, 692, 817, 751, 632, 268, 268, 458, + 458, 545, 635, 1000, 1000, 976, 914, 454, 914, 591, 632, 637, 351, 615, 591, 454, 635, + 566, 454, 635, 632, 1000, 700, 644, 818, 454, 1000, 420, 541, 818, 420, 274, 471, 641, + 635, 363, 595, 993, 546, 644, 344, 683, 520, 274, 683, 685, 685, 566, 745, 632, 973, + 615, 750, 750, 692, 734, 842, 751, 787, 751, 603, 698, 616, 615, 818, 685, 761, 711, + 835, 904, 783, 920, 680, 701, 881, 706, 600, 614, 594, 471, 621, 595, 797, 524, 640, + 640, 591, 620, 696, 637, 606, 637, 623, 534, 496, 591, 840, 591, 644, 605, 875, 887, + 640, 794, 570, 546, 838, 599,]; + font._name = "/tspdfFverdana"; + return font; + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.Subtype) { + bytes.push(...encoder.encode("/Subtype "), ...encoder.encode(" " + this.Subtype)); + } + if (this.BaseFont) { + bytes.push(...encoder.encode("/BaseFont "), ...encoder.encode(" " + this.BaseFont)); + } + if (this.ToUnicode) { + bytes.push(...encoder.encode("/G "), ...this.ToUnicode.toArray(cryptInfo)); + } + if (this.FirstChar) { + bytes.push(...encoder.encode("/FirstChar "), ...encoder.encode(" " + this.FirstChar)); + } + if (this.LastChar) { + bytes.push(...encoder.encode("/LastChar "), ...encoder.encode(" " + this.LastChar)); + } + if (this.Widths) { + if (this.Widths instanceof ObjectId) { + bytes.push(...encoder.encode("/Widths "), ...this.Widths.toArray(cryptInfo)); + } + else { + bytes.push(...encoder.encode("/Widths "), ...this.encodePrimitiveArray(this.Widths, encoder)); + } + } + if (this.Encoding || this.encodingValue) { + if (this.Encoding instanceof ObjectId) { + bytes.push(...encoder.encode("/Encoding "), ...this.Encoding.toArray(cryptInfo)); + } + else { + bytes.push(...encoder.encode("/Encoding "), ...encoder.encode(" " + this.Encoding)); + } + } + if (this.descriptorValue) { + bytes.push(...encoder.encode("/FontDescriptor "), ...this.descriptorValue.toArray(cryptInfo)); + } + if (this.Resources) { + bytes.push(...encoder.encode("/Resources "), ...this.Resources); + } + if (this.CharProcs) { + bytes.push(...encoder.encode("/CharProcs "), ...this.CharProcs); + } + if (this.FontBBox) { + bytes.push(...encoder.encode("/FontBBox "), ...this.encodePrimitiveArray(this.FontBBox, encoder)); + } + if (this.FontMatrix) { + bytes.push(...encoder.encode("/FontMatrix "), ...this.encodePrimitiveArray(this.FontMatrix, encoder)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + decodeText(bytes) { + var _a; + if (this.toUtfCmap) { + return this.toUtfCmap.hexBytesToUtfString(bytes); + } + if ((_a = this.encoding) === null || _a === void 0 ? void 0 : _a.charMap) { + const charMap = this.encoding.charMap; + let text = ""; + bytes.forEach(byte => { var _a; return text += (_a = charMap.get(byte)) !== null && _a !== void 0 ? _a : " "; }); + return text; + } + const decoder = bytes[0] === 254 && bytes[1] === 255 + ? new TextDecoder("utf-16be") + : new TextDecoder(); + const literal = decoder.decode(bytes); + return literal || ""; + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$12(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/Subtype": + const subtype = yield parser.parseNameAtAsync(i, true); + if (subtype) { + this.Subtype = subtype.value; + i = subtype.end + 1; + break; + } + throw new Error("Can't parse /Subtype property value"); + case "/BaseFont": + i = yield this.parseNamePropAsync(name, parser, i); + break; + case "/Encoding": + const encodingPropType = yield parser.getValueTypeAtAsync(i); + if (encodingPropType === valueTypes.NAME) { + i = yield this.parseNamePropAsync(name, parser, i); + } + else if (encodingPropType === valueTypes.REF) { + i = yield this.parseRefPropAsync(name, parser, i); + } + else { + throw new Error(`Unsupported '${name}' property value type: '${encodingPropType}'`); + } + break; + case "/ToUnicode": + i = yield this.parseRefPropAsync(name, parser, i); + break; + case "/FirstChar": + case "/LastChar": + i = yield this.parseNumberPropAsync(name, parser, i, false); + break; + case "/FontBBox": + case "/FontMatrix": + i = yield this.parseNumberArrayPropAsync(name, parser, i, true); + break; + case "/Widths": + const widthPropType = yield parser.getValueTypeAtAsync(i); + if (widthPropType === valueTypes.ARRAY) { + i = yield this.parseNumberArrayPropAsync(name, parser, i, true); + } + else if (widthPropType === valueTypes.REF) { + i = yield this.parseRefPropAsync(name, parser, i); + } + else { + throw new Error(`Unsupported '${name}' property value type: '${encodingPropType}'`); + } + break; + case "/FontDescriptor": + i = yield this.parseRefPropAsync(name, parser, i); + break; + case "/Resources": + case "/CharProcs": + const excludedEntryType = yield parser.getValueTypeAtAsync(i); + if (excludedEntryType === valueTypes.REF) { + const excludedDictId = yield ObjectId.parseRefAsync(parser, i); + if (excludedDictId && parseInfo.parseInfoGetterAsync) { + this[name.slice(1)] = yield parser.sliceCharCodesAsync(excludedDictId.start, excludedDictId.end); + i = excludedDictId.end + 1; + break; + } + throw new Error(`Can't parse ${name} value reference`); + } + else if (excludedEntryType === valueTypes.DICTIONARY) { + const excludedDictBounds = yield parser.getDictBoundsAtAsync(i); + if (excludedDictBounds) { + this[name.slice(1)] = yield parser.sliceCharCodesAsync(excludedDictBounds.start, excludedDictBounds.end); + i = excludedDictBounds.end + 1; + break; + } + throw new Error(`Can't parse ${name} dictionary bounds`); + } + throw new Error(`Unsupported ${name} property value type: ${excludedEntryType}`); + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + if (this.Encoding && this.Encoding instanceof ObjectId) { + const encodingParseInfo = yield parseInfo.parseInfoGetterAsync(this.Encoding.id); + const encodingDict = yield EncodingDict.parseAsync(encodingParseInfo); + this._encoding = encodingDict === null || encodingDict === void 0 ? void 0 : encodingDict.value; + } + if (this.ToUnicode) { + const toUtfParseInfo = yield parseInfo.parseInfoGetterAsync(this.ToUnicode.id); + const cmap = yield UnicodeCmapStream.parseAsync(toUtfParseInfo); + this._toUtfCmap = cmap === null || cmap === void 0 ? void 0 : cmap.value; + } + if (this.FontDescriptor) { + const descriptorParseInfo = yield parseInfo.parseInfoGetterAsync(this.FontDescriptor.id); + const descriptor = yield FontDescriptorDict.parseAsync(descriptorParseInfo); + this._descriptor = descriptor === null || descriptor === void 0 ? void 0 : descriptor.value; + } + if (this.Subtype !== "/Type1" + && this.Subtype !== "/Type3" + && this.Subtype !== "/TrueType" + && !(this.Subtype === "/Type0" && this._toUtfCmap)) { + throw new Error(`Font type is not supported: ${this.Subtype}`); + } + if (this.Subtype === "/Type3" + && (!this.FontBBox + || !this.FontMatrix + || !this.Encoding + || !this.FirstChar + || !this.LastChar + || !this.Widths + || !this.CharProcs)) { + throw new Error("Not all required properties parsed"); + } + }); + } + initProxy() { + return super.initProxy(); + } + getProxy() { + return super.getProxy(); + } +} + +var __awaiter$11 = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class SoftMaskDict extends PdfDict { + constructor() { + super(dictTypes.SOFT_MASK); + this.TR = "/Identity"; + } + static parseAsync(parseInfo) { + return __awaiter$11(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new SoftMaskDict(); + yield pdfObject.parsePropsAsync(parseInfo); + return { value: pdfObject, start: parseInfo.bounds.start, end: parseInfo.bounds.end }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.S) { + bytes.push(...encoder.encode("/S "), ...encoder.encode(this.S)); + } + if (this.G) { + bytes.push(...encoder.encode("/G "), ...this.G.toArray(cryptInfo)); + } + if (this.BC) { + bytes.push(...encoder.encode("/BC "), ...this.encodePrimitiveArray(this.BC, encoder)); + } + if (this.TR) { + bytes.push(...encoder.encode("/TR "), ...encoder.encode(" " + this.TR)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$11(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/S": + const softMaskType = yield parser.parseNameAtAsync(i, true); + if (softMaskType && Object.values(softMaskTypes) + .includes(softMaskType.value)) { + this.S = softMaskType.value; + i = softMaskType.end + 1; + } + else { + throw new Error("Can't parse /S property value"); + } + break; + case "/G": + i = yield this.parseRefPropAsync(name, parser, i); + break; + case "/BC": + i = yield this.parseNumberArrayPropAsync(name, parser, i); + break; + case "/TR": + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + }); + } +} + +var __awaiter$10 = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class GraphicsStateDict extends PdfDict { + constructor() { + super(dictTypes.GRAPHICS_STATE); + } + static parseAsync(parseInfo) { + return __awaiter$10(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new GraphicsStateDict(); + yield pdfObject.parsePropsAsync(parseInfo); + return { + value: pdfObject.initProxy(), + start: parseInfo.bounds.start, + end: parseInfo.bounds.end, + }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.LW) { + bytes.push(...encoder.encode("/LW "), ...encoder.encode(" " + this.LW)); + } + if (this.LC) { + bytes.push(...encoder.encode("/LC "), ...encoder.encode(" " + this.LC)); + } + if (this.LJ) { + bytes.push(...encoder.encode("/LJ "), ...encoder.encode(" " + this.LJ)); + } + if (this.ML) { + bytes.push(...encoder.encode("/ML "), ...encoder.encode(" " + this.ML)); + } + if (this.D) { + bytes.push(...encoder.encode("/D "), codes.L_BRACKET, codes.L_BRACKET, ...encoder.encode("" + this.D[0][0]), ...encoder.encode(" " + this.D[0][1]), codes.R_BRACKET, ...encoder.encode(" " + this.D[1]), codes.R_BRACKET); + } + if (this.RI) { + bytes.push(...encoder.encode("/RI "), ...encoder.encode(this.RI)); + } + if (this.OP) { + bytes.push(...encoder.encode("/OP "), ...encoder.encode(" " + this.OP)); + } + if (this.op) { + bytes.push(...encoder.encode("/op "), ...encoder.encode(" " + this.op)); + } + if (this.OPM) { + bytes.push(...encoder.encode("/OPM "), ...encoder.encode(" " + this.OPM)); + } + if (this.Font) { + bytes.push(...encoder.encode("/Font "), codes.L_BRACKET, ...this.Font[0].toArray(cryptInfo), ...encoder.encode(" " + this.Font[1]), codes.R_BRACKET); + } + if (this.FL) { + bytes.push(...encoder.encode("/FL "), ...encoder.encode(" " + this.FL)); + } + if (this.SM) { + bytes.push(...encoder.encode("/SM "), ...encoder.encode(" " + this.SM)); + } + if (this.SA) { + bytes.push(...encoder.encode("/SA "), ...encoder.encode(" " + this.SA)); + } + if (this.BM) { + bytes.push(...encoder.encode("/BM "), ...encoder.encode(this.BM)); + } + if (this.SMask) { + if (this.SMask instanceof SoftMaskDict) { + bytes.push(...encoder.encode("/SMask "), ...this.SMask.toArray(cryptInfo)); + } + else { + bytes.push(...encoder.encode("/SMask "), ...encoder.encode(this.SMask)); + } + } + if (this.CA) { + bytes.push(...encoder.encode("/CA "), ...encoder.encode(" " + this.CA)); + } + if (this.ca) { + bytes.push(...encoder.encode("/ca "), ...encoder.encode(" " + this.ca)); + } + if (this.AIS) { + bytes.push(...encoder.encode("/AIS "), ...encoder.encode(" " + this.AIS)); + } + if (this.TK) { + bytes.push(...encoder.encode("/TK "), ...encoder.encode(" " + this.TK)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + toParams() { + const params = {}; + if (!isNaN(this.LW)) { + params.strokeWidth = this.LW; + } + if (!isNaN(this.LC)) { + switch (this.LC) { + case lineCapStyles.BUTT: + params.strokeLineCap = "butt"; + break; + case lineCapStyles.ROUND: + params.strokeLineCap = "round"; + break; + case lineCapStyles.SQUARE: + params.strokeLineCap = "square"; + break; + } + } + if (!isNaN(this.LJ)) { + switch (this.LJ) { + case lineJoinStyles.BEVEL: + params.strokeLineJoin = "bevel"; + break; + case lineJoinStyles.ROUND: + params.strokeLineJoin = "round"; + break; + case lineJoinStyles.MITER: + params.strokeLineJoin = "miter"; + break; + } + } + if (this.ML) { + params.strokeMiterLimit = this.ML; + } + if (this.D) { + params.strokeDashArray = `${this.D[0][0]} ${this.D[0][1]}`; + params.strokeDashOffset = this.D[1]; + } + if (this.Font) ; + if (this.BM) { + switch (this.BM) { + case "/Normal": + params.mixBlendMode = "normal"; + break; + case "/Multiply": + params.mixBlendMode = "multiply"; + break; + case "/Screen": + params.mixBlendMode = "screen"; + break; + case "/Overlay": + params.mixBlendMode = "overlay"; + break; + case "/Darken": + params.mixBlendMode = "darken"; + break; + case "/Lighten": + params.mixBlendMode = "lighten"; + break; + case "/ColorDodge": + params.mixBlendMode = "color-dodge"; + break; + case "/ColorBurn": + params.mixBlendMode = "color-burn"; + break; + case "/HardLight": + params.mixBlendMode = "hard-light"; + break; + case "/SoftLight": + params.mixBlendMode = "soft-light"; + break; + case "/Difference": + params.mixBlendMode = "difference"; + break; + case "/Exclusion": + params.mixBlendMode = "exclusion"; + break; + default: + throw new Error(`Unsupported blend mode: ${this.BM}`); + } + } + if (this.SMask) ; + if (this.CA) { + params.strokeAlpha = this.CA; + } + if (this.ca) { + params.fillAlpha = this.ca; + } + if (this.AIS) ; + return params; + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$10(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/LC": + const lineCap = yield parser.parseNumberAtAsync(i, true); + if (lineCap && Object.values(lineCapStyles) + .includes(lineCap.value)) { + this.LC = lineCap.value; + i = lineCap.end + 1; + } + else { + throw new Error("Can't parse /LC property value"); + } + break; + case "/OPM": + const overprintMode = yield parser.parseNumberAtAsync(i, true); + if (overprintMode && ([0, 1].includes(overprintMode.value))) { + this.OPM = overprintMode.value; + i = overprintMode.end + 1; + } + else { + throw new Error("Can't parse /OPM property value"); + } + break; + case "/LJ": + const lineJoin = yield parser.parseNumberAtAsync(i, true); + if (lineJoin && Object.values(lineJoinStyles) + .includes(lineJoin.value)) { + this.LJ = lineJoin.value; + i = lineJoin.end + 1; + } + else { + throw new Error("Can't parse /LJ property value"); + } + break; + case "/RI": + const intent = yield parser.parseNameAtAsync(i, true); + if (intent && Object.values(renderingIntents) + .includes(intent.value)) { + this.RI = intent.value; + i = intent.end + 1; + } + else { + throw new Error("Can't parse /RI property value"); + } + break; + case "/BM": + const blendMode = yield parser.parseNameAtAsync(i, true); + if (blendMode && Object.values(blendModes) + .includes(blendMode.value)) { + this.BM = blendMode.value; + i = blendMode.end + 1; + } + else { + throw new Error("Can't parse /BM property value"); + } + break; + case "/SMask": + const sMaskEntryType = yield parser.getValueTypeAtAsync(i); + if (sMaskEntryType === valueTypes.NAME) { + const sMaskName = yield parser.parseNameAtAsync(i); + if (sMaskName) { + this.SMask = sMaskName.value; + i = sMaskName.end + 1; + break; + } + throw new Error("Can't parse /SMask property name"); + } + else if (sMaskEntryType === valueTypes.DICTIONARY) { + const sMaskDictBounds = yield parser.getDictBoundsAtAsync(i); + if (sMaskDictBounds) { + const sMaskDict = yield SoftMaskDict.parseAsync({ parser, bounds: sMaskDictBounds }); + if (sMaskDict) { + this.SMask = sMaskDict.value; + i = sMaskDict.end + 1; + break; + } + } + throw new Error("Can't parse /SMask value dictionary"); + } + throw new Error(`Unsupported /SMask property value type: ${sMaskEntryType}`); + case "/Font": + const fontEntryType = yield parser.getValueTypeAtAsync(i); + if (fontEntryType === valueTypes.ARRAY) { + const fontArrayBounds = yield parser.getArrayBoundsAtAsync(i); + if (fontArrayBounds) { + const fontRef = yield ObjectId.parseAsync(parser, fontArrayBounds.start + 1); + if (fontRef) { + const fontSize = yield parser.parseNumberAtAsync(fontRef.end + 1); + if (fontSize) { + this.Font = [fontRef.value, fontSize.value]; + i = fontArrayBounds.end + 1; + break; + } + } + } + } + else { + throw new Error(`Unsupported /Font property value type: ${fontEntryType}`); + } + throw new Error("Can't parse /Font property value"); + case "/D": + const dashEntryType = yield parser.getValueTypeAtAsync(i); + if (dashEntryType === valueTypes.ARRAY) { + const dashArrayBounds = yield parser.getArrayBoundsAtAsync(i); + if (dashArrayBounds) { + const dashArray = yield parser.parseNumberArrayAtAsync(dashArrayBounds.start + 1); + if (dashArray) { + const dashPhase = yield parser.parseNumberAtAsync(dashArray.end + 1); + if (dashPhase) { + this.D = [[dashArray.value[0], dashArray.value[1]], dashPhase.value]; + i = dashArrayBounds.end + 1; + break; + } + } + } + } + else { + throw new Error(`Unsupported /D property value type: ${dashEntryType}`); + } + throw new Error("Can't parse /D property value"); + case "/OP": + case "/op": + case "/SA": + case "/AIS": + case "/TK": + i = yield this.parseBoolPropAsync(name, parser, i); + break; + case "/LW": + case "/ML": + case "/FL": + case "/SM": + case "/CA": + case "/ca": + i = yield this.parseNumberPropAsync(name, parser, i); + break; + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + }); + } + initProxy() { + return super.initProxy(); + } + getProxy() { + return super.getProxy(); + } +} + +var __awaiter$$ = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class ResourceDict extends PdfDict { + constructor(streamParsers) { + super(null); + this._gsMap = new Map(); + this._fontsMap = new Map(); + this._xObjectsMap = new Map(); + this._streamParsers = streamParsers; + } + static parseAsync(parseInfo, streamParsers) { + return __awaiter$$(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new ResourceDict(streamParsers); + yield pdfObject.parsePropsAsync(parseInfo); + return { + value: pdfObject.initProxy(), + start: parseInfo.bounds.start, + end: parseInfo.bounds.end, + }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this._gsMap.size) { + bytes.push(...encoder.encode("/ExtGState ")); + bytes.push(...keywordCodes.DICT_START); + for (const [name, gsDict] of this._gsMap) { + bytes.push(...encoder.encode(name.slice(10)), codes.WHITESPACE); + if (gsDict.ref) { + bytes.push(...ObjectId.fromRef(gsDict.ref).toArray(cryptInfo)); + } + else { + bytes.push(...gsDict.toArray(cryptInfo)); + } + } + bytes.push(...keywordCodes.DICT_END); + } + if (this._fontsMap.size) { + bytes.push(...encoder.encode("/Font ")); + bytes.push(...keywordCodes.DICT_START); + for (const [name, fontDict] of this._fontsMap) { + bytes.push(...encoder.encode(name.slice(5)), codes.WHITESPACE); + if (fontDict.ref) { + bytes.push(...ObjectId.fromRef(fontDict.ref).toArray(cryptInfo)); + } + else { + bytes.push(...fontDict.toArray(cryptInfo)); + } + } + bytes.push(...keywordCodes.DICT_END); + } + if (this._xObjectsMap.size) { + bytes.push(...encoder.encode("/XObject "), ...keywordCodes.DICT_START); + for (const [name, xObject] of this._xObjectsMap) { + const ref = xObject.ref; + if (!ref) { + throw new Error("XObject has no reference"); + } + bytes.push(...encoder.encode(name.slice(8)), codes.WHITESPACE); + bytes.push(...ObjectId.fromRef(ref).toArray(cryptInfo)); + } + bytes.push(...keywordCodes.DICT_END); + } + if (this.ColorSpace) { + bytes.push(...encoder.encode("/ColorSpace "), ...this.ColorSpace.toArray(cryptInfo)); + } + if (this.Pattern) { + bytes.push(...encoder.encode("/Pattern "), ...this.Pattern.toArray(cryptInfo)); + } + if (this.Shading) { + bytes.push(...encoder.encode("/Shading "), ...this.Shading.toArray(cryptInfo)); + } + if (this.Properties) { + bytes.push(...encoder.encode("/Properties "), ...this.Properties.toArray(cryptInfo)); + } + if (this.ProcSet) { + bytes.push(...encoder.encode("/ProcSet "), ...this.encodePrimitiveArray(this.ProcSet, encoder)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + getGraphicsState(name) { + return this._gsMap.get(name); + } + *getGraphicsStates() { + for (const pair of this._gsMap) { + yield pair; + } + return; + } + setGraphicsState(name, state) { + this._gsMap.set(`/ExtGState${name}`, state); + this._edited = true; + } + getFont(name) { + return this._fontsMap.get("/Font" + name); + } + *getFonts() { + for (const pair of this._fontsMap) { + yield pair; + } + return; + } + setFont(name, font) { + this._fontsMap.set(`/Font${name}`, font); + this._edited = true; + } + getXObject(name) { + return this._xObjectsMap.get(name); + } + *getXObjects() { + for (const pair of this._xObjectsMap) { + yield pair; + } + return; + } + setXObject(name, xObject) { + this._xObjectsMap.set(`/XObject${name}`, xObject); + this._edited = true; + } + fillMapsAsync(parseInfoGetterAsync, cryptInfo) { + return __awaiter$$(this, void 0, void 0, function* () { + this._gsMap.clear(); + this._fontsMap.clear(); + this._xObjectsMap.clear(); + if (this.ExtGState) { + for (const [name, objectId] of this.ExtGState.getObjectIds()) { + const streamParseInfo = yield parseInfoGetterAsync(objectId.id); + if (!streamParseInfo) { + continue; + } + const stream = yield GraphicsStateDict.parseAsync(streamParseInfo); + if (stream) { + this._gsMap.set(`/ExtGState${name}`, stream.value); + } + } + for (const [name, parseInfo] of this.ExtGState.getDictParsers()) { + const dict = yield GraphicsStateDict.parseAsync(parseInfo); + if (dict) { + this._gsMap.set(`/ExtGState${name}`, dict.value); + } + } + } + if (this.XObject && this._streamParsers) { + for (const [name, objectId] of this.XObject.getObjectIds()) { + const streamParseInfo = yield parseInfoGetterAsync(objectId.id); + if (!streamParseInfo) { + continue; + } + const stream = (yield streamParseInfo.parser.findSubarrayIndexAsync(keywordCodes.FORM, { + direction: true, + minIndex: streamParseInfo.bounds.start, + maxIndex: streamParseInfo.bounds.end, + })) + ? yield this._streamParsers.xform(streamParseInfo) + : yield this._streamParsers.image(streamParseInfo); + if (stream) { + this._xObjectsMap.set(`/XObject${name}`, stream.value); + } + } + } + if (this.Font) { + for (const [name, objectId] of this.Font.getObjectIds()) { + const dictParseInfo = yield parseInfoGetterAsync(objectId.id); + if (!dictParseInfo) { + continue; + } + const dict = yield FontDict.parseAsync(dictParseInfo); + if (dict) { + this._fontsMap.set(`/Font${name}`, dict.value); + } + } + } + }); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$$(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/ExtGState": + case "/ColorSpace": + case "/Pattern": + case "/Shading": + case "/XObject": + case "/Font": + case "/Properties": + const mapEntryType = yield parser.getValueTypeAtAsync(i); + if (mapEntryType === valueTypes.REF) { + const mapDictId = yield ObjectId.parseRefAsync(parser, i); + if (mapDictId && parseInfo.parseInfoGetterAsync) { + const mapParseInfo = yield parseInfo.parseInfoGetterAsync(mapDictId.value.id); + if (mapParseInfo) { + const mapDict = yield ObjectMapDict.parseAsync(mapParseInfo); + if (mapDict) { + this[name.slice(1)] = mapDict.value; + i = mapDict.end + 1; + break; + } + } + } + throw new Error(`Can't parse ${name} value reference`); + } + else if (mapEntryType === valueTypes.DICTIONARY) { + const mapBounds = yield parser.getDictBoundsAtAsync(i); + if (mapBounds) { + const map = yield ObjectMapDict.parseAsync({ parser, bounds: mapBounds }); + if (map) { + this[name.slice(1)] = map.value; + i = mapBounds.end + 1; + break; + } + else { + throw new Error(`Can't parse ${name} value dictionary`); + } + } + throw new Error(`Can't parse ${name} dictionary bounds`); + } + throw new Error(`Unsupported /Resources property value type: ${mapEntryType}`); + case "/ProcSet": + i = yield this.parseNameArrayPropAsync(name, parser, i); + break; + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + if (parseInfo.parseInfoGetterAsync) { + yield this.fillMapsAsync(parseInfo.parseInfoGetterAsync, parseInfo.cryptInfo); + } + }); + } + initProxy() { + return super.initProxy(); + } + getProxy() { + return super.getProxy(); + } +} + +var __awaiter$_ = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class MeasureDict extends PdfDict { + constructor() { + super(dictTypes.MEASURE); + this.Subtype = "/RL"; + } + static parseAsync(parseInfo) { + return __awaiter$_(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new MeasureDict(); + yield pdfObject.parsePropsAsync(parseInfo); + return { value: pdfObject, start: parseInfo.bounds.start, end: parseInfo.bounds.end }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.Subtype) { + bytes.push(...encoder.encode("/Subtype "), ...encoder.encode(this.Subtype)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$_(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/Subtype": + const subtype = yield parser.parseNameAtAsync(i); + if (subtype) { + if (this.Subtype && this.Subtype !== subtype.value) { + throw new Error(`Invalid dict subtype: '${subtype.value}' instead of '${this.Subtype}'`); + } + i = subtype.end + 1; + } + else { + throw new Error("Can't parse /Subtype property value"); + } + break; + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + }); + } +} + +var __awaiter$Z = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class GroupDict extends PdfDict { + constructor() { + super(dictTypes.GROUP); + this.S = "/Transparency"; + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.S) { + bytes.push(...encoder.encode("/S "), ...encoder.encode(this.S)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$Z(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/S": + const intent = yield parser.parseNameAtAsync(i, true); + if (intent) { + if (Object.values(groupDictTypes).includes(intent.value)) { + this.S = intent.value; + i = intent.end + 1; + } + else { + throw new Error(`Invalid dict subtype: '${intent.value}'`); + } + } + else { + throw new Error("Can't parse /S property value"); + } + break; + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + }); + } +} + +var __awaiter$Y = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class TransparencyGroupDict extends GroupDict { + constructor() { + super(); + this.I = false; + this.K = false; + } + static parseAsync(parseInfo) { + return __awaiter$Y(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new TransparencyGroupDict(); + yield pdfObject.parsePropsAsync(parseInfo); + return { value: pdfObject, start: parseInfo.bounds.start, end: parseInfo.bounds.end }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.CS) { + bytes.push(...encoder.encode("/CS "), ...encoder.encode(this.CS)); + } + if (this.I) { + bytes.push(...encoder.encode("/I "), ...encoder.encode(" " + this.I)); + } + if (this.K) { + bytes.push(...encoder.encode("/K "), ...encoder.encode(" " + this.K)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$Y(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + if (this.S !== "/Transparency") { + throw new Error("Not a transparency dict"); + } + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/CS": + const colorSpaceEntryType = yield parser.getValueTypeAtAsync(i); + if (colorSpaceEntryType === valueTypes.NAME) { + const colorSpaceName = yield parser.parseNameAtAsync(i); + if (colorSpaceName) { + this.CS = colorSpaceName.value; + i = colorSpaceName.end + 1; + break; + } + throw new Error("Can't parse /CS property name"); + } + else if (colorSpaceEntryType === valueTypes.ARRAY) { + const colorSpaceArrayBounds = yield parser.getArrayBoundsAtAsync(i); + if (colorSpaceArrayBounds) { + i = colorSpaceArrayBounds.end + 1; + break; + } + throw new Error("Can't parse /CS value dictionary"); + } + throw new Error(`Unsupported /CS property value type: ${colorSpaceEntryType}`); + case "/I": + case "/K": + i = yield this.parseBoolPropAsync(name, parser, i); + break; + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + }); + } +} + +var __awaiter$X = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class XFormStream extends PdfStream { + get matrix() { + const apMatrix = new l(); + if (this.Matrix) { + const [m0, m1, m3, m4, m6, m7] = this.Matrix; + apMatrix.set(m0, m1, 0, m3, m4, 0, m6, m7, 1); + } + return apMatrix; + } + set matrix(matrix) { + if (!matrix) { + return; + } + this.Matrix = [...matrix.toFloatShortArray()]; + } + get bBox() { + return { + ll: new u(this.BBox[0], this.BBox[1]), + lr: new u(this.BBox[2], this.BBox[1]), + ur: new u(this.BBox[2], this.BBox[3]), + ul: new u(this.BBox[0], this.BBox[3]), + }; + } + get transformedBBox() { + const matrix = new l(); + if (this.Matrix) { + const [m0, m1, m3, m4, m6, m7] = this.Matrix; + matrix.set(m0, m1, 0, m3, m4, 0, m6, m7, 1); + } + const bBoxLL = new u(this.BBox[0], this.BBox[1]); + const bBoxLR = new u(this.BBox[2], this.BBox[1]); + const bBoxUR = new u(this.BBox[2], this.BBox[3]); + const bBoxUL = new u(this.BBox[0], this.BBox[3]); + return { + ll: u.applyMat3(bBoxLL, matrix), + lr: u.applyMat3(bBoxLR, matrix), + ur: u.applyMat3(bBoxUR, matrix), + ul: u.applyMat3(bBoxUL, matrix), + }; + } + get edited() { + return this._edited || this.Resources.edited; + } + constructor() { + super(streamTypes.FORM_XOBJECT); + this.Subtype = "/Form"; + this.FormType = 1; + this.Matrix = [1, 0, 0, 1, 0, 0]; + } + static parseAsync(parseInfo) { + return __awaiter$X(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new XFormStream(); + yield pdfObject.parsePropsAsync(parseInfo); + return { + value: pdfObject.initProxy(), + start: parseInfo.bounds.start, + end: parseInfo.bounds.end, + }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.Subtype) { + bytes.push(...encoder.encode("/Subtype "), ...encoder.encode(this.Subtype)); + } + if (this.FormType) { + bytes.push(...encoder.encode("/FormType "), ...encoder.encode(" " + this.FormType)); + } + if (this.BBox) { + bytes.push(...encoder.encode("/BBox "), ...this.encodePrimitiveArray(this.BBox, encoder)); + } + if (this.Matrix) { + bytes.push(...encoder.encode("/Matrix "), ...this.encodePrimitiveArray(this.Matrix, encoder)); + } + if (this.Resources) { + bytes.push(...encoder.encode("/Resources "), ...this.Resources.toArray(cryptInfo)); + } + if (this.Metadata) { + bytes.push(...encoder.encode("/Metadata "), ...this.Metadata.toArray(cryptInfo)); + } + if (this.LastModified) { + bytes.push(...encoder.encode("/LastModified "), ...this.LastModified.toArray(cryptInfo)); + } + if (this.StructParent) { + bytes.push(...encoder.encode("/StructParent "), ...encoder.encode(" " + this.StructParent)); + } + if (this.StructParents) { + bytes.push(...encoder.encode("/StructParents "), ...encoder.encode(" " + this.StructParents)); + } + if (this.Measure) { + bytes.push(...encoder.encode("/Measure "), ...this.Measure.toArray(cryptInfo)); + } + if (this.Group) { + bytes.push(...encoder.encode("/Group "), ...this.Group.toArray(cryptInfo)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$X(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const dictBounds = yield parser.getDictBoundsAtAsync(start); + let i = yield parser.skipToNextNameAsync(dictBounds.contentStart, dictBounds.contentEnd); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/Subtype": + const subtype = yield parser.parseNameAtAsync(i); + if (subtype) { + if (this.Subtype && this.Subtype !== subtype.value) { + throw new Error(`Invalid dict subtype: '${subtype.value}' instead of '${this.Subtype}'`); + } + i = subtype.end + 1; + } + else { + throw new Error("Can't parse /Subtype property value"); + } + break; + case "/FormType": + const formType = yield parser.parseNumberAtAsync(i, false); + if (formType) { + if (formType.value !== 1) { + throw new Error(`Ivalid form type: '${formType.value}' instead of '1'`); + } + i = formType.end + 1; + } + else { + throw new Error("Can't parse /FormType property value"); + } + break; + case "/BBox": + case "/Matrix": + i = yield this.parseNumberArrayPropAsync(name, parser, i, true); + break; + case "/LastModified": + i = yield this.parseDatePropAsync(name, parser, i, parseInfo.cryptInfo); + break; + case "/Metadata": + i = yield this.parseRefPropAsync(name, parser, i); + break; + case "/StructParent": + case "/StructParents": + i = yield this.parseNumberPropAsync(name, parser, i, false); + break; + case "/Resources": + const resEntryType = yield parser.getValueTypeAtAsync(i); + if (resEntryType === valueTypes.REF) { + const resDictId = yield ObjectId.parseRefAsync(parser, i); + if (resDictId && parseInfo.parseInfoGetterAsync) { + const resParseInfo = yield parseInfo.parseInfoGetterAsync(resDictId.value.id); + if (resParseInfo) { + const resDict = yield ResourceDict.parseAsync(resParseInfo, { xform: XFormStream.parseAsync, image: ImageStream.parseAsync }); + if (resDict) { + this.Resources = resDict.value; + i = resDict.end + 1; + break; + } + } + } + throw new Error("Can't parse /Resources value reference"); + } + else if (resEntryType === valueTypes.DICTIONARY) { + const resDictBounds = yield parser.getDictBoundsAtAsync(i); + if (resDictBounds) { + if (resDictBounds.contentStart) { + const resDict = yield ResourceDict.parseAsync({ + parser, + bounds: resDictBounds, + parseInfoGetterAsync: parseInfo.parseInfoGetterAsync, + }, { xform: XFormStream.parseAsync, image: ImageStream.parseAsync }); + if (resDict) { + this.Resources = resDict.value; + } + else { + throw new Error("Can't parse /Resources value dictionary"); + } + } + i = resDictBounds.end + 1; + break; + } + throw new Error("Can't parse /Resources dictionary bounds"); + } + throw new Error(`Unsupported /Resources property value type: ${resEntryType}`); + case "/Measure": + const measureEntryType = yield parser.getValueTypeAtAsync(i); + if (measureEntryType === valueTypes.REF) { + const measureDictId = yield ObjectId.parseRefAsync(parser, i); + if (measureDictId && parseInfo.parseInfoGetterAsync) { + const measureParseInfo = yield parseInfo.parseInfoGetterAsync(measureDictId.value.id); + if (measureParseInfo) { + const measureDict = yield MeasureDict.parseAsync(measureParseInfo); + if (measureDict) { + this.Measure = measureDict.value; + i = measureDict.end + 1; + break; + } + } + } + throw new Error("Can't parse /Measure value reference"); + } + else if (measureEntryType === valueTypes.DICTIONARY) { + const measureDictBounds = yield parser.getDictBoundsAtAsync(i); + if (measureDictBounds) { + const measureDict = yield MeasureDict.parseAsync({ parser, bounds: measureDictBounds, cryptInfo: parseInfo.cryptInfo }); + if (measureDict) { + this.Measure = measureDict.value; + i = measureDict.end + 1; + break; + } + } + throw new Error("Can't parse /Measure value dictionary"); + } + throw new Error(`Unsupported /Measure property value type: ${measureEntryType}`); + case "/Group": + const groupEntryType = yield parser.getValueTypeAtAsync(i); + if (groupEntryType === valueTypes.REF) { + const groupDictId = yield ObjectId.parseRefAsync(parser, i); + if (groupDictId && parseInfo.parseInfoGetterAsync) { + const groupParseInfo = yield parseInfo.parseInfoGetterAsync(groupDictId.value.id); + if (groupParseInfo) { + const groupDict = yield TransparencyGroupDict.parseAsync(groupParseInfo); + if (groupDict) { + this.Group = groupDict.value; + i = groupDict.end + 1; + break; + } + } + } + throw new Error("Can't parse /Group value reference"); + } + else if (groupEntryType === valueTypes.DICTIONARY) { + const groupDictBounds = yield parser.getDictBoundsAtAsync(i); + if (groupDictBounds) { + const groupDict = yield TransparencyGroupDict.parseAsync({ parser, bounds: groupDictBounds, cryptInfo: parseInfo.cryptInfo }); + if (groupDict) { + this.Group = groupDict.value; + i = groupDict.end + 1; + break; + } + } + throw new Error("Can't parse /Group value dictionary"); + } + throw new Error(`Unsupported /Group property value type: ${groupEntryType}`); + case "/OC": + case "/OPI": + default: + i = yield parser.skipToNextNameAsync(i, dictBounds.contentEnd); + break; + } + } + else { + break; + } + } + if (!this.BBox) { + throw new Error("Not all required properties parsed"); + } + }); + } + initProxy() { + return super.initProxy(); + } + getProxy() { + return super.getProxy(); + } +} + +var __awaiter$W = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class TextData { + static buildAsync(text, options) { + return __awaiter$W(this, void 0, void 0, function* () { + let result; + if (text) { + const pTemp = document.createElement("p"); + pTemp.style.color = "black"; + pTemp.style.fontSize = options.fontSize + "px"; + pTemp.style.fontFamily = "arial"; + pTemp.style.fontWeight = "normal"; + pTemp.style.fontStyle = "normal"; + pTemp.style.lineHeight = "normal"; + pTemp.style.overflowWrap = "normal"; + pTemp.style.textAlign = options.textAlign; + pTemp.style.textDecoration = "none"; + pTemp.style.verticalAlign = "top"; + pTemp.style.whiteSpace = "pre-wrap"; + pTemp.style.wordBreak = "normal"; + pTemp.style.position = "fixed"; + pTemp.style.left = "0"; + pTemp.style.top = "0"; + pTemp.style.margin = "0"; + pTemp.style.padding = "0"; + pTemp.style.maxWidth = options.maxWidth.toFixed() + "px"; + pTemp.style.visibility = "hidden"; + pTemp.style.transform = "scale(0.1)"; + pTemp.style.transformOrigin = "top left"; + document.body.append(pTemp); + const words = text.split(/([- \n\r])/u); + const lines = []; + let currentLineText = ""; + let previousHeight = 0; + for (let i = 0; i < words.length; i++) { + const word = words[i]; + pTemp.textContent += word; + yield DomUtils.runEmptyTimeout(); + const currentHeight = pTemp.offsetHeight; + previousHeight || (previousHeight = currentHeight); + if (currentHeight > previousHeight) { + lines.push(currentLineText); + currentLineText = word; + previousHeight = currentHeight; + } + else { + currentLineText += word; + } + } + lines.push(currentLineText); + pTemp.innerHTML = ""; + const lineSpans = []; + for (const line of lines) { + const lineSpan = document.createElement("span"); + lineSpan.style.position = "relative"; + lineSpan.textContent = line; + lineSpans.push(lineSpan); + pTemp.append(lineSpan); + } + yield DomUtils.runEmptyTimeout(); + const textWidth = pTemp.offsetWidth; + const textHeight = pTemp.offsetHeight; + let pivotPoint; + switch (options.pivotPoint) { + case "top-left": + pivotPoint = new u(0, textHeight); + break; + case "bottom-margin": + pivotPoint = new u(textWidth / 2, options.strokeWidth); + break; + case "center": + default: + pivotPoint = new u(textWidth / 2, textHeight / 2); + break; + } + const lineData = []; + for (let i = 0; i < lines.length; i++) { + const span = lineSpans[i]; + const x = span.offsetLeft; + const y = span.offsetTop; + const width = span.offsetWidth; + const height = span.offsetHeight; + const lineBottomLeftPdf = new u(x, textHeight - (y + height)); + const lineTopRightPdf = new u(x + width, textHeight - y); + const lineRect = [ + lineBottomLeftPdf.x, lineBottomLeftPdf.y, + lineTopRightPdf.x, lineTopRightPdf.y + ]; + const lineBottomLeftPdfRel = u.subtract(lineBottomLeftPdf, pivotPoint); + const lineTopRightPdfRel = u.subtract(lineTopRightPdf, pivotPoint); + const lineRelativeRect = [ + lineBottomLeftPdfRel.x, lineBottomLeftPdfRel.y, + lineTopRightPdfRel.x, lineTopRightPdfRel.y + ]; + lineData.push({ + text: lines[i], + rect: lineRect, + relativeRect: lineRelativeRect, + }); + } + const textRect = [0, 0, textWidth, textHeight]; + const textRelativeRect = [ + 0 - pivotPoint.x, 0 - pivotPoint.y, + textWidth - pivotPoint.x, textHeight - pivotPoint.y + ]; + const textData = { + width: textWidth, + height: textHeight, + rect: textRect, + relativeRect: textRelativeRect, + lines: lineData, + }; + pTemp.remove(); + result = textData; + } + else { + result = null; + } + return result; + }); + } +} + +const SELECTION_STROKE_WIDTH = 20; +const BEZIER_CONSTANT = 0.551915; +const LINE_END_MULTIPLIER = 3; +const LINE_END_MIN_SIZE = 10; +function buildSquigglyLine(start, end, maxWaveSize) { + if (!start || !end) { + return null; + } + if (isNaN(maxWaveSize) || maxWaveSize <= 0) { + throw new Error(`Invalid maximal squiggle size ${maxWaveSize}`); + } + const lineLength = u.subtract(start, end).getMagnitude(); + if (!lineLength) { + return null; + } + const resultPoints = [start.clone()]; + const zeroVec = new u(); + const lengthVec = new u(lineLength, 0); + const matrix = l.from4Vec2(zeroVec, lengthVec, start, end); + const waveCount = Math.ceil(lineLength / maxWaveSize); + const waveSize = lineLength / waveCount; + const halfWaveSize = waveSize / 2; + for (let i = 0; i < waveCount; i++) { + resultPoints.push(new u(i * waveSize + halfWaveSize, -halfWaveSize).applyMat3(matrix).truncate(2), new u((i + 1) * waveSize, 0).applyMat3(matrix).truncate(2)); + } + return resultPoints; +} +function calcPdfBBoxToRectMatrices(bBox, rect, matrix) { + const matAP = new l(); + if (matrix) { + const [m0, m1, m3, m4, m6, m7] = matrix; + matAP.set(m0, m1, 0, m3, m4, 0, m6, m7, 1); + } + const bBoxLL = new u(bBox[0], bBox[1]); + const bBoxLR = new u(bBox[2], bBox[1]); + const bBoxUR = new u(bBox[2], bBox[3]); + const bBoxUL = new u(bBox[0], bBox[3]); + const { min: appBoxMin, max: appBoxMax } = u.minMax(u.applyMat3(bBoxLL, matAP), u.applyMat3(bBoxLR, matAP), u.applyMat3(bBoxUR, matAP), u.applyMat3(bBoxUL, matAP)); + const rectMin = new u(rect[0], rect[1]); + const rectMax = new u(rect[2], rect[3]); + const matA = l.from4Vec2(appBoxMin, appBoxMax, rectMin, rectMax); + const matAA = l.fromMat3(matAP).multiply(matA); + return { matAP, matA, matAA }; +} + +class TextState { + constructor(params) { + Object.assign(this, TextState.defaultParams, params); + } + clone(params) { + const copy = new TextState(this); + if (params) { + return Object.assign(copy, params); + } + return copy; + } + setWordSpacing(value) { + this.wordSpacing = !value + ? "normal" + : value + "px"; + } + setLetterSpacing(value) { + this.letterSpacing = !value + ? "normal" + : value + "px"; + } + setScale(value) { + this.horizontalScale = !value + ? 1 + : value / 100; + } + setLeading(value) { + if (value) { + this.leading = value; + this.lineHeight = Math.abs(this.leading) + "px"; + } + else { + this.leading = parseInt(this.fontSize, 10) * -1.2; + this.lineHeight = "1"; + } + } + setFontSize(value) { + this.fontSize = (value || 12) + "px"; + } + setVerticalAlign(value) { + this.verticalAlign = !value + ? "0" + : value / 10 + "em"; + } + moveAlongPx(value) { + const tx = value; + const transformationMatrix = new l().set(1, 0, 0, 0, 1, 0, tx, 0, 1); + this.matrix = transformationMatrix.multiply(this.matrix); + } + moveAlongPdfUnits(value) { + const tx = (-value / 1000) * parseInt(this.fontSize, 10); + const transformationMatrix = new l().set(1, 0, 0, 0, 1, 0, tx, 0, 1); + this.matrix = transformationMatrix.multiply(this.matrix); + } + nextLine(tx, ty) { + tx !== null && tx !== void 0 ? tx : (tx = 0); + ty !== null && ty !== void 0 ? ty : (ty = this.leading || parseInt(this.fontSize, 10) * -1.2); + const translationMatrix = new l().set(1, 0, 0, 0, 1, 0, tx, ty, 1); + this.lineMatrix = translationMatrix.multiply(this.lineMatrix); + this.matrix = this.lineMatrix.clone(); + } +} +TextState.defaultParams = { + matrix: new l(), + lineMatrix: new l(), + leading: 12 * -1.2, + renderMode: textRenderModes.FILL, + fontFamily: "helvetica, arial, sans-serif", + fontSize: "10px", + lineHeight: "1", + letterSpacing: "normal", + wordSpacing: "normal", + horizontalScale: 1, + verticalAlign: "0", + knockOut: true, +}; + +class GraphicsState { + get stroke() { + const { x: r, y: g, z: b } = this.strokeColor; + const a = this.strokeAlpha; + return `rgba(${r},${g},${b},${a})`; + } + get fill() { + const { x: r, y: g, z: b } = this.fillColor; + const a = this.fillAlpha; + return `rgba(${r},${g},${b},${a})`; + } + constructor(params) { + var _a, _b, _c, _d; + Object.assign(this, GraphicsState.defaultParams, params); + this.matrix = (_a = this.matrix) === null || _a === void 0 ? void 0 : _a.clone(); + this.textState = (_b = this.textState) === null || _b === void 0 ? void 0 : _b.clone(); + this.strokeColor = (_c = this.strokeColor) === null || _c === void 0 ? void 0 : _c.clone(); + this.fillColor = (_d = this.fillColor) === null || _d === void 0 ? void 0 : _d.clone(); + } + clone(params) { + const copy = new GraphicsState(this); + if (params) { + return Object.assign(copy, params); + } + return copy; + } + setColor(type, ...params) { + let r, g, b; + switch (params.length) { + case 1: + r = g = b = params[0] * 255; + break; + case 3: + r = params[0] * 255; + g = params[1] * 255; + b = params[2] * 255; + break; + case 4: + const [c, m, y, k] = params; + r = 255 * (1 - c) * (1 - k); + g = 255 * (1 - m) * (1 - k); + b = 255 * (1 - y) * (1 - k); + break; + } + if (type === "stroke") { + this.strokeColor.set(r, g, b); + } + else { + this.fillColor.set(r, g, b); + } + } +} +GraphicsState.defaultParams = { + matrix: new l(), + textState: new TextState(), + strokeColorSpace: "rgb", + strokeAlpha: 1, + strokeColor: new z(), + fillColorSpace: "rgb", + fillAlpha: 1, + fillColor: new z(), + strokeWidth: 1, + strokeMiterLimit: 10, + strokeLineCap: "square", + strokeLineJoin: "miter", +}; + +var __awaiter$V = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class AppearanceStreamRenderer { + get state() { + return this._graphicsStates[this._graphicsStates.length - 1]; + } + constructor(stream, rect, objectName) { + this._clipPaths = []; + this._selectionCopies = []; + this._graphicsStates = []; + if (!stream) { + throw new Error("Stream is not defined"); + } + this._stream = stream; + this._objectName = objectName; + const { matAA } = calcPdfBBoxToRectMatrices(stream.BBox, rect, stream.Matrix); + const [xMin, yMin, xMax, yMax] = stream.BBox; + const clipBottomLeft = new u(xMin, yMin).applyMat3(matAA); + const clipBottomRight = new u(xMax, yMin).applyMat3(matAA); + const clipTopRight = new u(xMax, yMax).applyMat3(matAA); + const clipTopLeft = new u(xMin, yMax).applyMat3(matAA); + const clipPath = document.createElementNS("http://www.w3.org/2000/svg", "clipPath"); + clipPath.id = `clip0_${objectName}`; + clipPath.innerHTML = ""; + this._clipPaths.push(clipPath); + this._graphicsStates.push(new GraphicsState({ matrix: matAA, clipPath })); + } + static parseNextCommandAsync(parser, i) { + return __awaiter$V(this, void 0, void 0, function* () { + const parameters = []; + let operator; + command: while (!operator) { + const nextValueType = yield parser.getValueTypeAtAsync(i, true); + switch (nextValueType) { + case valueTypes.NUMBER: + const numberResult = yield parser.parseNumberAtAsync(i, true); + parameters.push(numberResult.value); + i = numberResult.end + 1; + break; + case valueTypes.NAME: + const nameResult = yield parser.parseNameAtAsync(i, true); + parameters.push(nameResult.value); + i = nameResult.end + 1; + break; + case valueTypes.ARRAY: + const arrayBounds = yield parser.getArrayBoundsAtAsync(i); + let j = arrayBounds.start + 1; + while (j < arrayBounds.end - 1 && j !== -1) { + const nextArrayValueType = yield parser.getValueTypeAtAsync(j, true); + switch (nextArrayValueType) { + case valueTypes.STRING_LITERAL: + const arrayLiteralResult = yield LiteralString.parseAsync(parser, j); + parameters.push(arrayLiteralResult.value.bytes); + j = arrayLiteralResult.end + 1; + break; + case valueTypes.NUMBER: + const arrayNumberResult = yield parser.parseNumberAtAsync(j, true); + parameters.push(arrayNumberResult.value); + j = arrayNumberResult.end + 1; + break; + default: + console.log(`Unsupported value type in AP stream parameter array: ${nextArrayValueType}`); + j = yield parser.findDelimiterIndexAsync(true, j + 1); + break; + } + } + i = arrayBounds.end + 1; + break; + case valueTypes.STRING_LITERAL: + const literalResult = yield LiteralString.parseAsync(parser, i); + parameters.push(literalResult.value.literal); + i = literalResult.end + 1; + break; + case valueTypes.STRING_HEX: + const hexResult = yield HexString.parseAsync(parser, i); + parameters.push(hexResult.value.hex); + i = hexResult.end + 1; + break; + case valueTypes.UNKNOWN: + const operatorResult = yield parser.parseStringAtAsync(i); + operator = operatorResult.value; + i = operatorResult.end + 1; + break command; + default: + throw new Error(`Invalid appearance stream value type: ${nextValueType}`); + } + } + return { nextIndex: i, parameters, operator }; + }); + } + renderAsync() { + return __awaiter$V(this, void 0, void 0, function* () { + this.reset(); + const elements = yield this.drawStreamAsync(this._stream); + return { + elements, + clipPaths: this._clipPaths.slice(), + pickHelpers: this._selectionCopies.slice(), + }; + }); + } + reset() { + this._graphicsStates.length = 1; + this._clipPaths.length = 1; + this._selectionCopies.length = 0; + } + pushState(params) { + const lastState = this._graphicsStates[this._graphicsStates.length - 1]; + const newState = lastState.clone(params); + this._graphicsStates.push(newState); + } + popState() { + if (this._graphicsStates.length === 1) { + return null; + } + return this._graphicsStates.pop(); + } + pushClipPath(clippingElement, nonzero) { + const lastCpIndex = this._clipPaths.length - 1; + const clipPath = document.createElementNS("http://www.w3.org/2000/svg", "clipPath"); + clipPath.setAttribute("clip-rule", nonzero ? "nonzero" : "evenodd"); + clipPath.setAttribute("clip-path", `url(#${this._clipPaths[lastCpIndex]})`); + clipPath.id = `clip${lastCpIndex + 1}_${this._objectName}`; + clipPath.append(clippingElement); + this._clipPaths.push(clipPath); + this.state.clipPath = clipPath; + } + tryApplyingStateOperator(operator, parameters) { + switch (operator) { + case "q": + this.pushState(); + break; + case "Q": + this.popState(); + break; + case "gs": + const externalState = this._stream.Resources.getGraphicsState(`/ExtGState${parameters[0]}`); + if (!externalState) { + throw new Error("External state specified in appearance stream not found"); + } + const params = externalState.toParams(); + Object.assign(this.state, params); + break; + case "cm": + const [m0, m1, m3, m4, m6, m7] = parameters; + const matrix = new l().set(m0, m1, 0, m3, m4, 0, m6, m7, 1); + this.state.matrix = matrix.multiply(this.state.matrix); + break; + case "w": + this.state.strokeWidth = +parameters[0] || 1; + break; + case "J": + switch (parameters[0]) { + case lineCapStyles.ROUND: + this.state.strokeLineCap = "round"; + break; + case lineCapStyles.SQUARE: + this.state.strokeLineCap = "square"; + break; + case lineCapStyles.BUTT: + default: + this.state.strokeLineCap = "butt"; + break; + } + break; + case "j": + switch (parameters[0]) { + case lineJoinStyles.BEVEL: + this.state.strokeLineJoin = "bevel"; + break; + case lineJoinStyles.ROUND: + this.state.strokeLineJoin = "round"; + break; + case lineJoinStyles.MITER: + default: + this.state.strokeLineJoin = "miter"; + break; + } + break; + case "M": + this.state.strokeMiterLimit = +parameters[0] || 10; + break; + case "d": + let a = 3; + let b = 0; + let c = 0; + if (parameters.length === 3) { + a = +parameters[0]; + b = +parameters[1]; + c = +parameters[2]; + } + else if (parameters.length === 2) { + a = +parameters[0]; + c = +parameters[1]; + } + else if (parameters.length === 1) { + c = +parameters[0]; + } + this.state.strokeDashArray = `${a} ${b}`; + this.state.strokeDashOffset = c; + break; + case "CS": + switch (parameters[0]) { + case colorSpaces.GRAYSCALE: + this.state.strokeColorSpace = "grayscale"; + break; + case colorSpaces.RGB: + this.state.strokeColorSpace = "rgb"; + break; + case colorSpaces.CMYK: + this.state.strokeColorSpace = "cmyk"; + break; + default: + throw new Error("Unsupported color space in appearance stream"); + } + break; + case "cs": + switch (parameters[0]) { + case colorSpaces.GRAYSCALE: + this.state.fillColorSpace = "grayscale"; + break; + case colorSpaces.RGB: + this.state.fillColorSpace = "rgb"; + break; + case colorSpaces.CMYK: + this.state.fillColorSpace = "cmyk"; + break; + default: + throw new Error("Unsupported color space in appearance stream"); + } + break; + case "G": + this.state.strokeColorSpace = "grayscale"; + this.state.setColor("stroke", ...parameters); + break; + case "g": + this.state.fillColorSpace = "grayscale"; + this.state.setColor("fill", ...parameters); + break; + case "RG": + this.state.strokeColorSpace = "rgb"; + this.state.setColor("stroke", ...parameters); + break; + case "rg": + this.state.fillColorSpace = "rgb"; + this.state.setColor("fill", ...parameters); + break; + case "K": + this.state.strokeColorSpace = "cmyk"; + this.state.setColor("stroke", ...parameters); + break; + case "k": + this.state.fillColorSpace = "cmyk"; + this.state.setColor("fill", ...parameters); + break; + case "SC": + this.state.setColor("stroke", ...parameters); + break; + case "cs": + this.state.setColor("fill", ...parameters); + break; + case "ri": + case "i": + break; + case "Tc": + this.state.textState.setLetterSpacing(+parameters[0]); + break; + case "Tw": + this.state.textState.setWordSpacing(+parameters[0]); + break; + case "Tz": + this.state.textState.setScale(+parameters[0]); + break; + case "TL": + this.state.textState.setLeading(+parameters[0]); + break; + case "Tf": + this.state.textState.customFontName = parameters[0] || ""; + this.state.textState.setFontSize(+parameters[1]); + break; + case "Tr": + switch (parameters[0]) { + case 0: + default: + this.state.textState.renderMode = textRenderModes.FILL; + break; + case 1: + this.state.textState.renderMode = textRenderModes.STROKE; + break; + case 2: + this.state.textState.renderMode = textRenderModes.FILL_STROKE; + break; + case 3: + this.state.textState.renderMode = textRenderModes.INVISIBLE; + break; + case 4: + this.state.textState.renderMode = textRenderModes.FILL_USE_AS_CLIP; + break; + case 5: + this.state.textState.renderMode = textRenderModes.STROKE_USE_AS_CLIP; + break; + case 6: + this.state.textState.renderMode = textRenderModes.FILL_STROKE_USE_AS_CLIP; + break; + case 7: + this.state.textState.renderMode = textRenderModes.USE_AS_CLIP; + break; + } + break; + case "Ts": + this.state.textState.setVerticalAlign(+parameters[0]); + break; + case "Td": + if (parameters.length > 1) { + const [tx, ty] = parameters; + this.state.textState.nextLine(tx, ty); + } + break; + case "TD": + if (parameters.length > 1) { + const [tx, ty] = parameters; + this.state.textState.setLeading(-ty); + this.state.textState.nextLine(tx, ty); + } + break; + case "Tm": + if (parameters.length > 5) { + const [tm0, tm1, tm3, tm4, tm6, tm7] = parameters; + const transformationMatrix = new l().set(tm0, tm1, 0, tm3, tm4, 0, tm6, tm7, 1); + this.state.textState.matrix = transformationMatrix; + this.state.textState.lineMatrix = transformationMatrix.clone(); + } + break; + case "T*": + this.state.textState.nextLine(); + break; + default: + return false; + } + return true; + } + setTextStateFont(fontDict) { + var _a; + const state = this.state.textState; + if (!fontDict) { + state.fontFamily = "arial, sans-serif"; + return; + } + let fallbackFont; + if (fontDict.isMonospace) { + fallbackFont = "courier, monospace"; + } + else if (fontDict.isScript) { + fallbackFont = "cursive"; + } + else if (fontDict.isSerif) { + fallbackFont = "times new roman, serif"; + } + else { + fallbackFont = "arial, sans-serif"; + } + const baseFont = (_a = fontDict.BaseFont) === null || _a === void 0 ? void 0 : _a.substring(1).toLowerCase(); + if (!baseFont) { + state.fontFamily = fallbackFont; + return; + } + if (baseFont.includes("times")) { + state.fontFamily = "times new roman, serif"; + } + else if (baseFont.includes("arial")) { + state.fontFamily = "arial, sans-serif"; + } + else if (baseFont.includes("courier")) { + state.fontFamily = "courier new, monospace"; + } + else { + state.fontFamily = `${baseFont}, ${fallbackFont}`; + } + } + decodeTextParam(textParam, fontDict) { + if (textParam instanceof Uint8Array) { + return fontDict.decodeText(textParam); + } + return textParam + ""; + } + createSvgElement() { + const element = document.createElementNS("http://www.w3.org/2000/svg", "g"); + return element; + } + drawPath(d, stroke, fill, close = false, evenOdd = false) { + if (close && d[d.length - 1] !== "Z") { + d += " Z"; + } + const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); + this.addDescriptionDataAttribute(path, "astream-path"); + applyMatrixToElement(path, this.state.matrix); + path.setAttribute("d", d); + if (fill) { + path.setAttribute("fill", this.state.fill); + path.setAttribute("fill-rule", evenOdd ? "evenodd" : "nonzero"); + } + else { + path.setAttribute("fill", "none"); + } + if (stroke) { + path.setAttribute("stroke", this.state.stroke); + path.setAttribute("stroke-width", this.state.strokeWidth + ""); + path.setAttribute("stroke-miterlimit", this.state.strokeMiterLimit + ""); + path.setAttribute("stroke-linecap", this.state.strokeLineCap); + path.setAttribute("stroke-linejoin", this.state.strokeLineJoin); + if (this.state.strokeDashArray) { + path.setAttribute("stroke-dasharray", this.state.strokeDashArray); + } + if (this.state.strokeDashOffset) { + path.setAttribute("stroke-dashoffset", this.state.strokeDashOffset + ""); + } + } + else { + path.setAttribute("stroke", "none"); + } + const svg = this.createSvgElement(); + svg.setAttribute("clip-path", `url(#${this._clipPaths[this._clipPaths.length - 1].id})`); + svg.append(path); + const clonedSvg = this.createSvgElement(); + this.addDescriptionDataAttribute(clonedSvg, "astream-selection-helper"); + const clonedPath = path.cloneNode(true); + this.addDescriptionDataAttribute(clonedPath, "astream-selection-path"); + const clonedPathStrokeWidth = !stroke || this.state.strokeWidth < SELECTION_STROKE_WIDTH + ? SELECTION_STROKE_WIDTH + : this.state.strokeWidth; + clonedPath.setAttribute("stroke-width", clonedPathStrokeWidth + ""); + clonedPath.setAttribute("stroke", "transparent"); + clonedPath.setAttribute("fill", fill ? "transparent" : "none"); + clonedSvg.append(clonedPath); + this._selectionCopies.push(clonedPath); + return { element: svg, blendMode: this.state.mixBlendMode || "normal" }; + } + drawImageAsync(imageStream) { + return __awaiter$V(this, void 0, void 0, function* () { + const url = yield imageStream.getImageUrlAsync(); + if (!url) { + throw new Error("Can't get image url from external image stream"); + } + const matrix = new l() + .applyTranslation(-imageStream.Width / 2, -imageStream.Height / 2) + .applyScaling(1, -1) + .applyTranslation(imageStream.Width / 2, imageStream.Height / 2) + .applyScaling(1 / imageStream.Width, 1 / imageStream.Height) + .multiply(this.state.matrix); + const image = document.createElementNS("http://www.w3.org/2000/svg", "image"); + this.addDescriptionDataAttribute(image, "astream-image"); + image.onerror = e => { + console.log(`Loading external image stream failed: ${e}`); + }; + image.setAttribute("href", url); + image.setAttribute("width", imageStream.Width + ""); + image.setAttribute("height", imageStream.Height + ""); + applyMatrixToElement(image, matrix); + const imageWrapper = this.createSvgElement(); + imageWrapper.setAttribute("data-tspdf-desc", "astream-image-wrapper"); + imageWrapper.setAttribute("clip-path", `url(#${this._clipPaths[this._clipPaths.length - 1].id})`); + imageWrapper.append(image); + const clonedSvg = this.createSvgElement(); + this.addDescriptionDataAttribute(clonedSvg, "astream-image-selection-helper"); + const clonedRect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + this.addDescriptionDataAttribute(clonedRect, "astream-image-selection-rect"); + clonedRect.setAttribute("width", imageStream.Width + ""); + clonedRect.setAttribute("height", imageStream.Height + ""); + clonedRect.setAttribute("fill", "transparent"); + applyMatrixToElement(clonedRect, matrix); + clonedSvg.append(clonedRect); + this._selectionCopies.push(clonedRect); + return imageWrapper; + }); + } + drawTextAsync(textParam, resources) { + return __awaiter$V(this, void 0, void 0, function* () { + const textState = this.state.textState; + const fontDict = resources.getFont(textState.customFontName); + const text = this.decodeTextParam(textParam, fontDict); + this.setTextStateFont(fontDict); + if (!text) { + console.log(`Can't decode the stream text parameter: '${textParam}'`); + return null; + } + const matrix = new l() + .applyScaling(1, -1) + .applyScaling(textState.horizontalScale, 1) + .multiply(l.multiply(textState.matrix, this.state.matrix)); + const svgText = document.createElementNS("http://www.w3.org/2000/svg", "text"); + this.addDescriptionDataAttribute(svgText, "astream-text"); + applyMatrixToElement(svgText, matrix); + svgText.setAttribute("x", "0"); + svgText.setAttribute("y", "0"); + svgText.textContent = text; + svgText.style.fontFamily = textState.fontFamily; + svgText.style.fontSize = textState.fontSize; + svgText.style.lineHeight = textState.lineHeight; + svgText.style.letterSpacing = textState.letterSpacing; + svgText.style.wordSpacing = textState.wordSpacing; + svgText.style.verticalAlign = textState.verticalAlign; + svgText.style.whiteSpace = "pre"; + svgText.style.userSelect = "none"; + let fill; + let stroke; + let clip; + switch (textState.renderMode) { + case textRenderModes.FILL: + default: + fill = this.state.fill; + break; + case textRenderModes.STROKE: + stroke = true; + break; + case textRenderModes.FILL_STROKE: + fill = this.state.fill; + stroke = true; + break; + case textRenderModes.INVISIBLE: + break; + case textRenderModes.FILL_USE_AS_CLIP: + fill = this.state.fill; + clip = true; + break; + case textRenderModes.STROKE_USE_AS_CLIP: + stroke = true; + clip = true; + break; + case textRenderModes.FILL_STROKE_USE_AS_CLIP: + fill = this.state.fill; + stroke = true; + clip = true; + break; + case textRenderModes.USE_AS_CLIP: + fill = "transparent"; + clip = true; + break; + } + svgText.style.fill = fill || "none"; + if (stroke) { + svgText.style.stroke = this.state.stroke; + svgText.style.strokeWidth = this.state.strokeWidth + ""; + svgText.style.strokeMiterlimit = this.state.strokeMiterLimit + ""; + svgText.style.strokeLinecap = this.state.strokeLineCap; + svgText.style.strokeLinejoin = this.state.strokeLineJoin; + if (this.state.strokeDashArray) { + svgText.style.strokeDasharray = this.state.strokeDashArray; + } + if (this.state.strokeDashOffset) { + svgText.style.strokeDashoffset = this.state.strokeDashOffset + ""; + } + } + else { + svgText.style.stroke = "none"; + } + if (clip) { + this.pushClipPath(svgText.cloneNode(), true); + } + yield new Promise((resolve, reject) => { + const tempContainer = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + this.addDescriptionDataAttribute(tempContainer, "astream-temp-text-sizer"); + tempContainer.setAttribute("viewBox", "0 0 100 100"); + tempContainer.style.width = "100px"; + tempContainer.style.height = "100px"; + tempContainer.style.zIndex = "-99"; + tempContainer.style.position = "fixed"; + tempContainer.style.left = "0"; + tempContainer.style.top = "0"; + tempContainer.append(svgText); + document.body.append(tempContainer); + setTimeout(() => { + const width = svgText.getBBox().width; + this.state.textState.moveAlongPx(width); + svgText.remove(); + tempContainer.remove(); + resolve(true); + }, 0); + }); + const clonedSvg = this.createSvgElement(); + this.addDescriptionDataAttribute(clonedSvg, "astream-text-selection-helper"); + const clonedPath = svgText.cloneNode(true); + const clonedPathStrokeWidth = !stroke || this.state.strokeWidth < SELECTION_STROKE_WIDTH + ? SELECTION_STROKE_WIDTH + : this.state.strokeWidth; + clonedPath.style.strokeWidth = clonedPathStrokeWidth + ""; + clonedPath.style.stroke = "transparent"; + clonedPath.style.fill = fill ? "transparent" : "none"; + clonedSvg.append(clonedPath); + this._selectionCopies.push(clonedPath); + return { element: svgText, blendMode: this.state.mixBlendMode || "normal" }; + }); + } + drawTextGroupAsync(parser, resources) { + return __awaiter$V(this, void 0, void 0, function* () { + const svgElements = []; + const textState = this.state.textState; + let i = 0; + while (i !== -1) { + const { nextIndex, parameters, operator } = yield AppearanceStreamRenderer.parseNextCommandAsync(parser, i); + i = yield parser.skipEmptyAsync(nextIndex); + switch (operator) { + case "Tj": + svgElements.push(yield this.drawTextAsync(parameters[0], resources)); + break; + case "'": + textState.nextLine(); + svgElements.push(yield this.drawTextAsync(parameters[0], resources)); + break; + case "\"": + const [a, b, c] = parameters; + textState.setWordSpacing(+a); + textState.setLetterSpacing(+b); + textState.nextLine(); + svgElements.push(yield this.drawTextAsync(c, resources)); + break; + case "TJ": + for (const param of parameters) { + if (param instanceof Uint8Array) { + svgElements.push(yield this.drawTextAsync(param, resources)); + } + else if (typeof param === "number") { + if (+(param.toFixed(0))) { + textState.moveAlongPdfUnits(param); + } + } + } + break; + default: + const operatorIsGraphicState = this.tryApplyingStateOperator(operator, parameters); + if (!operatorIsGraphicState) { + throw new Error(`Unsupported appearance stream operator: ${operator}`); + } + } + } + return svgElements.filter(x => x); + }); + } + drawStreamAsync(stream) { + return __awaiter$V(this, void 0, void 0, function* () { + const parser = yield stream.getStreamDataParserAsync(); + const svgElements = []; + const lastCoord = new u(); + let lastOperator; + let d = ""; + let i = 0; + while (i !== -1) { + const { nextIndex, parameters, operator } = yield AppearanceStreamRenderer.parseNextCommandAsync(parser, i); + i = yield parser.skipEmptyAsync(nextIndex + 1); + switch (operator) { + case "m": + const move = new u(+parameters[0], +parameters[1]); + d += ` M ${move.x} ${move.y}`; + lastCoord.setFromVec2(move); + break; + case "l": + const line = new u(+parameters[0], +parameters[1]); + d += ` L ${line.x} ${line.y}`; + lastCoord.setFromVec2(line); + break; + case "re": + const rMin = new u(+parameters[0], +parameters[1]); + const rMax = new u(+parameters[2], +parameters[3]).add(rMin); + d += ` M ${rMin.x} ${rMin.y} L ${rMax.x} ${rMin.y} L ${rMax.x} ${rMax.y} L ${rMin.x} ${rMax.y} L ${rMin.x} ${rMin.y}`; + lastCoord.setFromVec2(rMin); + break; + case "c": + const cControl1 = new u(+parameters[0], +parameters[1]); + const cControl2 = new u(+parameters[2], +parameters[3]); + const cEnd = new u(+parameters[4], +parameters[5]); + d += ` C ${cControl1.x} ${cControl1.y}, ${cControl2.x} ${cControl2.y}, ${cEnd.x} ${cEnd.y}`; + lastCoord.setFromVec2(cEnd); + break; + case "v": + const vControl2 = new u(+parameters[0], +parameters[1]); + const vEnd = new u(+parameters[2], +parameters[3]); + d += ` C ${lastCoord.x} ${lastCoord.y}, ${vControl2.x} ${vControl2.y}, ${vEnd.x} ${vEnd.y}`; + lastCoord.setFromVec2(vEnd); + break; + case "y": + const yControl1 = new u(+parameters[0], +parameters[1]); + const yEnd = new u(+parameters[2], +parameters[3]); + d += ` C ${yControl1.x} ${yControl1.y}, ${yEnd.x} ${yEnd.y}, ${yEnd.x} ${yEnd.y}`; + lastCoord.setFromVec2(yEnd); + break; + case "h": + d += " Z"; + break; + case "S": + svgElements.push(this.drawPath(d, true, false)); + d = ""; + break; + case "s": + svgElements.push(this.drawPath(d, true, false, true)); + d = ""; + break; + case "F": + case "f": + svgElements.push(this.drawPath(d, false, true, true)); + d = ""; + break; + case "F*": + case "f*": + svgElements.push(this.drawPath(d, false, true, true, true)); + d = ""; + break; + case "B": + svgElements.push(this.drawPath(d, true, true, false, false)); + d = ""; + break; + case "B*": + svgElements.push(this.drawPath(d, true, true, false, true)); + d = ""; + break; + case "b": + svgElements.push(this.drawPath(d, true, true, true, false)); + d = ""; + break; + case "b*": + svgElements.push(this.drawPath(d, true, true, true, true)); + d = ""; + break; + case "n": + if (lastOperator === "W" || lastOperator === "W*") { + if (d[d.length - 1] !== "Z") { + d += " Z"; + } + const clippingPath = document.createElementNS("http://www.w3.org/2000/svg", "path"); + clippingPath.setAttribute("d", d); + this.pushClipPath(clippingPath, lastOperator === "W"); + } + d = ""; + break; + case "W": + break; + case "W*": + break; + case "BT": + const textObjectEnd = yield parser.findSubarrayIndexAsync(keywordCodes.AP_STREAM_TEXT_END, { + closedOnly: true, + minIndex: i, + }); + if (textObjectEnd) { + const textParser = yield parser.getSubParserAsync(i, textObjectEnd.start - 1); + const textGroup = yield this.drawTextGroupAsync(textParser, stream.Resources); + svgElements.push(...textGroup); + i = yield parser.skipEmptyAsync(textObjectEnd.end + 1); + break; + } + throw new Error("Can't find the appearance stream text object end"); + case "Do": + const innerStream = stream.Resources.getXObject((`/XObject${parameters[0]}`)); + if (!innerStream) { + throw new Error(`External object not found in the appearance stream resources: ${parameters[0]}`); + } + if (innerStream instanceof XFormStream) { + const [im0, im1, im3, im4, im6, im7] = innerStream.Matrix; + const innerMat = new l().set(im0, im1, 0, im3, im4, 0, im6, im7, 1); + this.pushState(); + this.state.matrix = innerMat.multiply(this.state.matrix); + const innerStreamSvgElements = yield this.drawStreamAsync(innerStream); + svgElements.push(...innerStreamSvgElements); + this.popState(); + } + else if (innerStream instanceof ImageStream) { + const image = yield this.drawImageAsync(innerStream); + svgElements.push({ + element: image, + blendMode: this.state.mixBlendMode || "normal" + }); + } + else { + throw new Error(`Unsupported appearance stream external object: ${parameters[0]}`); + } + break; + default: + const operatorIsGraphicState = this.tryApplyingStateOperator(operator, parameters); + if (!operatorIsGraphicState) { + throw new Error(`Unsupported appearance stream operator: ${operator}`); + } + } + lastOperator = operator; + } + return svgElements; + }); + } + addDescriptionDataAttribute(element, description) { + element.setAttribute("data-tspdf-desc", description); + } +} + +var __awaiter$U = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class BorderStyleDict extends PdfDict { + constructor() { + super(dictTypes.BORDER_STYLE); + this.W = 1; + this.S = borderStyles.SOLID; + this.D = [3, 0]; + } + static parseAsync(parseInfo) { + return __awaiter$U(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new BorderStyleDict(); + yield pdfObject.parsePropsAsync(parseInfo); + return { value: pdfObject, start: parseInfo.bounds.start, end: parseInfo.bounds.end }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.W) { + bytes.push(...encoder.encode("/W "), ...encoder.encode(" " + this.W)); + } + if (this.S) { + bytes.push(...encoder.encode("/S "), ...encoder.encode(this.S)); + } + if (this.D) { + bytes.push(...encoder.encode("/D "), ...this.encodePrimitiveArray(this.D, encoder)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + var _a, _b; + return __awaiter$U(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/W": + i = yield this.parseNumberPropAsync(name, parser, i, true); + break; + case "/S": + const style = yield parser.parseNameAtAsync(i, true); + if (style && Object.values(borderStyles).includes(style.value)) { + this.S = style.value; + i = style.end + 1; + } + else { + throw new Error("Can't parse /S property value"); + } + break; + case "/D": + const dashGap = yield parser.parseNumberArrayAtAsync(i, true); + if (dashGap) { + this.D = [ + (_a = dashGap.value[0]) !== null && _a !== void 0 ? _a : 3, + (_b = dashGap.value[1]) !== null && _b !== void 0 ? _b : 0, + ]; + i = dashGap.end + 1; + } + else { + throw new Error("Can't parse /D property value"); + } + break; + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + }); + } +} + +var __awaiter$T = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class AppearanceDict extends PdfDict { + constructor() { + super(null); + this._streamsMap = new Map(); + } + static parseAsync(parseInfo) { + return __awaiter$T(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new AppearanceDict(); + yield pdfObject.parsePropsAsync(parseInfo); + return { + value: pdfObject.initProxy(), + start: parseInfo.bounds.start, + end: parseInfo.bounds.end, + }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + getStream(key) { + return this._streamsMap.get(key); + } + *getStreams() { + for (const pair of this._streamsMap) { + yield pair[1]; + } + return; + } + setStream(key, stream) { + this._streamsMap.set(key, stream); + this._edited = true; + } + clearStreams() { + this._streamsMap.clear(); + this._edited = true; + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + const nStream = this._streamsMap.get("/N"); + if (nStream) { + bytes.push(...encoder.encode("/N ")); + bytes.push(...ObjectId.fromRef(nStream.ref).toArray(cryptInfo)); + } + else if (this.N) { + bytes.push(...encoder.encode("/N ")); + if (this.N instanceof ObjectMapDict) { + bytes.push(...this.N.toArray(cryptInfo)); + } + else { + bytes.push(...this.N.toArray(cryptInfo)); + } + } + const rStream = this._streamsMap.get("/R"); + if (rStream) { + bytes.push(...encoder.encode("/R ")); + bytes.push(...ObjectId.fromRef(rStream.ref).toArray(cryptInfo)); + } + else if (this.R) { + bytes.push(...encoder.encode("/R ")); + if (this.R instanceof ObjectMapDict) { + bytes.push(...this.R.toArray(cryptInfo)); + } + else { + bytes.push(...this.R.toArray(cryptInfo)); + } + } + const dStream = this._streamsMap.get("/D"); + if (dStream) { + bytes.push(...encoder.encode("/D ")); + bytes.push(...ObjectId.fromRef(dStream.ref).toArray(cryptInfo)); + } + else if (this.D) { + bytes.push(...encoder.encode("/D ")); + if (this.D instanceof ObjectMapDict) { + bytes.push(...this.D.toArray(cryptInfo)); + } + else { + bytes.push(...this.D.toArray(cryptInfo)); + } + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + fillStreamsMapAsync(parseInfoGetterAsync) { + return __awaiter$T(this, void 0, void 0, function* () { + this._streamsMap.clear(); + for (const prop of ["N", "R", "D"]) { + if (this[prop]) { + if (this[prop] instanceof ObjectId) { + const streamParseInfo = yield parseInfoGetterAsync(this[prop].id); + if (!streamParseInfo) { + continue; + } + const stream = yield XFormStream.parseAsync(streamParseInfo); + if (!stream) { + continue; + } + if (stream) { + this._streamsMap.set(`/${prop}`, stream.value); + } + } + else { + for (const [name, objectId] of this[prop].getProps()) { + const streamParseInfo = yield parseInfoGetterAsync(objectId.id); + if (!streamParseInfo) { + continue; + } + const stream = yield XFormStream.parseAsync(streamParseInfo); + if (stream) { + this._streamsMap.set(`/${prop}${name}`, stream.value); + } + } + } + } + } + }); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$T(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/N": + const nEntryType = yield parser.getValueTypeAtAsync(i); + if (nEntryType === valueTypes.REF) { + const nRefId = yield ObjectId.parseRefAsync(parser, i); + if (nRefId) { + this.N = nRefId.value; + i = nRefId.end + 1; + break; + } + } + else if (nEntryType === valueTypes.DICTIONARY) { + const nDictBounds = yield parser.getDictBoundsAtAsync(i); + if (nDictBounds) { + const nSubDict = yield ObjectMapDict.parseAsync({ parser, bounds: nDictBounds }); + if (nSubDict) { + this.N = nSubDict.value; + i = nSubDict.end + 1; + break; + } + } + } + else { + throw new Error(`Unsupported /N property value type: ${nEntryType}`); + } + throw new Error("Can't parse /N property value"); + case "/R": + const rEntryType = yield parser.getValueTypeAtAsync(i); + if (rEntryType === valueTypes.REF) { + const rRefId = yield ObjectId.parseRefAsync(parser, i); + if (rRefId) { + this.R = rRefId.value; + i = rRefId.end + 1; + break; + } + } + else if (rEntryType === valueTypes.DICTIONARY) { + const rDictBounds = yield parser.getDictBoundsAtAsync(i); + if (rDictBounds) { + const rSubDict = yield ObjectMapDict.parseAsync({ parser, bounds: rDictBounds }); + if (rSubDict) { + this.R = rSubDict.value; + i = rSubDict.end + 1; + break; + } + } + } + else { + throw new Error(`Unsupported /R property value type: ${rEntryType}`); + } + throw new Error("Can't parse /R property value"); + case "/D": + const dEntryType = yield parser.getValueTypeAtAsync(i); + if (dEntryType === valueTypes.REF) { + const dRefId = yield ObjectId.parseRefAsync(parser, i); + if (dRefId) { + this.D = dRefId.value; + i = dRefId.end + 1; + break; + } + } + else if (dEntryType === valueTypes.DICTIONARY) { + const dDictBounds = yield parser.getDictBoundsAtAsync(i); + if (dDictBounds) { + const dSubDict = yield ObjectMapDict.parseAsync({ parser, bounds: dDictBounds }); + if (dSubDict) { + this.D = dSubDict.value; + i = dSubDict.end + 1; + break; + } + } + } + else { + throw new Error(`Unsupported /D property value type: ${dEntryType}`); + } + throw new Error("Can't parse /D property value"); + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + if (!this.N) { + throw new Error("Not all required properties parsed"); + } + if (parseInfo.parseInfoGetterAsync) { + yield this.fillStreamsMapAsync(parseInfo.parseInfoGetterAsync); + } + }); + } + initProxy() { + return super.initProxy(); + } + getProxy() { + return super.getProxy(); + } +} + +var __awaiter$S = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class BorderEffectDict extends PdfDict { + constructor() { + super(null); + this.S = borderEffects.NONE; + this.L = 0; + } + static parseAsync(parseInfo) { + return __awaiter$S(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new BorderEffectDict(); + yield pdfObject.parsePropsAsync(parseInfo); + return { value: pdfObject, start: parseInfo.bounds.start, end: parseInfo.bounds.end }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.S) { + bytes.push(...encoder.encode("/S "), ...encoder.encode(this.S)); + } + if (this.L) { + bytes.push(...encoder.encode("/L "), ...encoder.encode(" " + this.L)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$S(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/S": + const style = yield parser.parseNameAtAsync(i, true); + if (style && Object.values(borderEffects).includes(style.value)) { + this.S = style.value; + i = style.end + 1; + } + else { + throw new Error("Can't parse /S property value"); + } + break; + case "/L": + i = yield this.parseNumberPropAsync(name, parser, i, true); + break; + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + }); + } +} + +var __awaiter$R = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class BorderArray { + constructor(hCornerR, vCornerR, width, dash, gap) { + this.hCornerR = hCornerR !== null && hCornerR !== void 0 ? hCornerR : 0; + this.vCornerR = vCornerR !== null && vCornerR !== void 0 ? vCornerR : 0; + this.width = width !== null && width !== void 0 ? width : 1; + this.dash = dash !== null && dash !== void 0 ? dash : 3; + this.gap = gap !== null && gap !== void 0 ? gap : 0; + } + static parseAsync(parser, start, skipEmpty = true) { + return __awaiter$R(this, void 0, void 0, function* () { + if (skipEmpty) { + start = yield parser.findNonSpaceIndexAsync(true, start); + } + if (start < 0 || start > parser.maxIndex + || !(yield parser.isCodeAtAsync(start, codes.L_BRACKET))) { + return null; + } + const hCornerR = yield parser.parseNumberAtAsync(start + 1); + if (!hCornerR || isNaN(hCornerR.value)) { + return null; + } + const vCornerR = yield parser.parseNumberAtAsync(hCornerR.end + 2); + if (!vCornerR || isNaN(vCornerR.value)) { + return null; + } + const width = yield parser.parseNumberAtAsync(vCornerR.end + 2); + if (!width || isNaN(width.value)) { + return null; + } + const next = yield parser.findNonSpaceIndexAsync(true, width.end + 1); + if (!next) { + return null; + } + else if (yield parser.isCodeAtAsync(next, codes.R_BRACKET)) { + return { + value: new BorderArray(hCornerR.value, vCornerR.value, width.value), + start, + end: next, + }; + } + else if (yield parser.isCodeAtAsync(next, codes.L_BRACKET)) { + const dash = yield parser.parseNumberAtAsync(next + 1); + if (!dash || isNaN(dash.value)) { + return null; + } + const gap = yield parser.parseNumberAtAsync(dash.end + 2); + if (!gap || isNaN(gap.value)) { + return null; + } + const dashEnd = yield parser.findNonSpaceIndexAsync(true, gap.end + 1); + if (!dashEnd || !(yield parser.isCodeAtAsync(dashEnd, codes.R_BRACKET))) { + return null; + } + const arrayEnd = yield parser.findNonSpaceIndexAsync(true, dashEnd + 1); + if (!arrayEnd || !(yield parser.isCodeAtAsync(arrayEnd, codes.R_BRACKET))) { + return null; + } + return { + value: new BorderArray(hCornerR.value, vCornerR.value, width.value, dash.value, gap.value), + start, + end: arrayEnd, + }; + } + return null; + }); + } + toArray(cryptInfo) { + const source = this.dash && this.gap + ? `[${this.hCornerR} ${this.vCornerR} ${this.width}]` + : `[${this.hCornerR} ${this.vCornerR} ${this.width} [${this.dash} ${this.gap}]]`; + return new TextEncoder().encode(source); + } +} + +var __awaiter$Q = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class AnnotationDict extends PdfDict { + get apStream() { + var _a; + if (!this._apStream) { + const streams = (_a = this.AP) === null || _a === void 0 ? void 0 : _a.getStreams(); + if (streams) { + this._apStream = [...streams][0]; + } + } + return this._apStream; + } + set apStream(value) { + this._apStream = value; + this._edited = true; + } + get lastRenderResult() { + if (!this._renderedControls || !this._renderedContent) { + return null; + } + return { + controls: this._renderedControls, + content: this._renderedContent, + }; + } + get strokeWidth() { + var _a, _b, _c, _d; + return (_d = (_b = (_a = this.BS) === null || _a === void 0 ? void 0 : _a.W) !== null && _b !== void 0 ? _b : (_c = this.Border) === null || _c === void 0 ? void 0 : _c.width) !== null && _d !== void 0 ? _d : 1; + } + constructor(subType) { + super(dictTypes.ANNOTATION); + this.F = 4; + this.Border = new BorderArray(0, 0, 1); + this._currentAngle = 0; + this._tempTransformationMatrix = new l(); + this._tempStartPoint = new u(); + this._tempVecX = new u(); + this._tempVecY = new u(); + this._svgId = UUID.getRandomUuid(); + this.onSvgPointerEnter = (e) => { + if (this.$onPointerEnterAction) { + this.$onPointerEnterAction(e); + } + }; + this.onSvgPointerLeave = (e) => { + if (this.$onPointerLeaveAction) { + this.$onPointerLeaveAction(e); + } + }; + this.onSvgPointerDown = (e) => { + if (!this.$pageId) { + return; + } + if (this.$onPointerDownAction) { + this.$onPointerDownAction(e); + } + this.onTranslationPointerDown(e); + }; + this.onTranslationPointerDown = (e) => { + if (!this.$translationEnabled || !e.isPrimary) { + return; + } + const target = e.target; + target.setPointerCapture(e.pointerId); + target.addEventListener("pointerup", this.onTranslationPointerUp); + target.addEventListener("pointerout", this.onTranslationPointerUp); + this._moved = false; + this._transformationTimer = setTimeout(() => { + this._transformationTimer = null; + this._renderedControls.after(this._svgContentCopy); + this._tempStartPoint.setFromVec2(this.convertClientCoordsToPage(e.clientX, e.clientY)); + target.addEventListener("pointermove", this.onTranslationPointerMove); + }, 200); + }; + this.onTranslationPointerMove = (e) => { + if (!e.isPrimary) { + return; + } + const currentPosition = this.convertClientCoordsToPage(e.clientX, e.clientY); + this._tempTransformationMatrix.reset() + .applyTranslation(currentPosition.x - this._tempStartPoint.x, currentPosition.y - this._tempStartPoint.y); + applyMatrixToElement(this._svgContentCopy, this._tempTransformationMatrix); + this._moved = true; + }; + this.onTranslationPointerUp = (e) => { + if (!e.isPrimary) { + return; + } + const target = e.target; + target.removeEventListener("pointermove", this.onTranslationPointerMove); + target.removeEventListener("pointerup", this.onTranslationPointerUp); + target.removeEventListener("pointerout", this.onTranslationPointerUp); + target.releasePointerCapture(e.pointerId); + this.applyTempTransformAsync(); + }; + this.onRotationHandlePointerDown = (e) => { + if (!e.isPrimary) { + return; + } + const target = e.target; + target.setPointerCapture(e.pointerId); + target.addEventListener("pointerup", this.onRotationHandlePointerUp); + target.addEventListener("pointerout", this.onRotationHandlePointerUp); + this._moved = false; + this._transformationTimer = setTimeout(() => { + this._transformationTimer = null; + this._renderedControls.after(this._svgContentCopy); + target.addEventListener("pointermove", this.onRotationHandlePointerMove); + }, 200); + e.stopPropagation(); + }; + this.onRotationHandlePointerMove = (e) => { + if (!e.isPrimary) { + return; + } + const centerX = (this.Rect[0] + this.Rect[2]) / 2; + const centerY = (this.Rect[1] + this.Rect[3]) / 2; + const clientCenter = this.convertPageCoordsToClient(centerX, centerY); + const currentRotation = this.getCurrentRotation(); + const angle = Math.atan2(e.clientY - clientCenter.y, e.clientX - clientCenter.x) + Math.PI / 2 - currentRotation; + this._currentAngle = angle; + this._tempTransformationMatrix.reset() + .applyTranslation(-centerX, -centerY) + .applyRotation(angle) + .applyTranslation(centerX, centerY); + applyMatrixToElement(this._svgContentCopy, this._tempTransformationMatrix); + this._moved = true; + }; + this.onRotationHandlePointerUp = (e) => { + if (!e.isPrimary) { + return; + } + const target = e.target; + target.removeEventListener("pointermove", this.onRotationHandlePointerMove); + target.removeEventListener("pointerup", this.onRotationHandlePointerUp); + target.removeEventListener("pointerout", this.onRotationHandlePointerUp); + target.releasePointerCapture(e.pointerId); + this.applyTempTransformAsync(); + }; + this.onScaleHandlePointerDown = (e) => { + if (!e.isPrimary) { + return; + } + const target = e.target; + target.setPointerCapture(e.pointerId); + target.addEventListener("pointerup", this.onScaleHandlePointerUp); + target.addEventListener("pointerout", this.onScaleHandlePointerUp); + const { ll, lr, ur, ul } = this.getLocalBB(); + const handleName = target.dataset["handleName"]; + switch (handleName) { + case "ll": + this._tempStartPoint.setFromVec2(ur); + this._tempVecX.setFromVec2(ul).subtract(ur); + this._tempVecY.setFromVec2(lr).subtract(ur); + break; + case "lr": + this._tempStartPoint.setFromVec2(ul); + this._tempVecX.setFromVec2(ur).subtract(ul); + this._tempVecY.setFromVec2(ll).subtract(ul); + break; + case "ur": + this._tempStartPoint.setFromVec2(ll); + this._tempVecX.setFromVec2(lr).subtract(ll); + this._tempVecY.setFromVec2(ul).subtract(ll); + break; + case "ul": + this._tempStartPoint.setFromVec2(lr); + this._tempVecX.setFromVec2(ll).subtract(lr); + this._tempVecY.setFromVec2(ur).subtract(lr); + break; + default: + throw new Error(`Invalid handle name: ${handleName}`); + } + this._tempX = this._tempVecX.getMagnitude(); + this._tempY = this._tempVecY.getMagnitude(); + this._moved = false; + this._transformationTimer = setTimeout(() => { + this._transformationTimer = null; + this._renderedControls.after(this._svgContentCopy); + target.addEventListener("pointermove", this.onScaleHandlePointerMove); + }, 200); + e.stopPropagation(); + }; + this.onScaleHandlePointerMove = (e) => { + if (!e.isPrimary) { + return; + } + const currentBoxDiagonal = this.convertClientCoordsToPage(e.clientX, e.clientY) + .subtract(this._tempStartPoint); + const currentBoxDiagonalLength = currentBoxDiagonal.getMagnitude(); + const cos = Math.abs(currentBoxDiagonal.dotProduct(this._tempVecX)) + / currentBoxDiagonalLength / this._tempX; + const currentXSideLength = cos * currentBoxDiagonalLength; + const currentYSideLength = Math.sqrt(currentBoxDiagonalLength * currentBoxDiagonalLength + - currentXSideLength * currentXSideLength); + const scaleX = currentXSideLength / this._tempX; + const scaleY = currentYSideLength / this._tempY; + const annotCenterX = (this.Rect[0] + this.Rect[2]) / 2; + const annotCenterY = (this.Rect[1] + this.Rect[3]) / 2; + const currentRotation = this.getCurrentRotation(); + this._tempTransformationMatrix.reset() + .applyTranslation(-annotCenterX, -annotCenterY) + .applyRotation(-currentRotation) + .applyScaling(scaleX, scaleY) + .applyRotation(currentRotation) + .applyTranslation(annotCenterX, annotCenterY); + const translation = this._tempStartPoint.clone().subtract(this._tempStartPoint.clone().applyMat3(this._tempTransformationMatrix)); + this._tempTransformationMatrix.applyTranslation(translation.x, translation.y); + applyMatrixToElement(this._svgContentCopy, this._tempTransformationMatrix); + this._moved = true; + }; + this.onScaleHandlePointerUp = (e) => { + if (!e.isPrimary) { + return; + } + const target = e.target; + target.removeEventListener("pointermove", this.onScaleHandlePointerMove); + target.removeEventListener("pointerup", this.onScaleHandlePointerUp); + target.removeEventListener("pointerout", this.onScaleHandlePointerUp); + target.releasePointerCapture(e.pointerId); + this.applyTempTransformAsync(); + }; + this.Subtype = subType; + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.Subtype) { + bytes.push(...encoder.encode("/Subtype "), ...encoder.encode(this.Subtype)); + } + if (this.Rect) { + bytes.push(...encoder.encode("/Rect "), ...this.encodePrimitiveArray(this.Rect, encoder)); + } + if (this.Contents) { + bytes.push(...encoder.encode("/Contents "), ...this.Contents.toArray(cryptInfo)); + } + if (this.P) { + bytes.push(...encoder.encode("/P "), ...this.P.toArray(cryptInfo)); + } + if (this.NM) { + bytes.push(...encoder.encode("/NM "), ...this.NM.toArray(cryptInfo)); + } + if (this.M) { + bytes.push(...encoder.encode("/M "), ...this.M.toArray(cryptInfo)); + } + if (this.F) { + bytes.push(...encoder.encode("/F "), ...encoder.encode(" " + this.F)); + } + if (this.AS) { + bytes.push(...encoder.encode("/AS "), ...encoder.encode(this.AS)); + } + if (this.Border) { + bytes.push(...encoder.encode("/Border "), ...this.Border.toArray(cryptInfo)); + } + if (this.BS) { + bytes.push(...encoder.encode("/BS "), ...this.BS.toArray(cryptInfo)); + } + if (this.BE) { + bytes.push(...encoder.encode("/BE "), ...this.BE.toArray(cryptInfo)); + } + if (this.C) { + bytes.push(...encoder.encode("/C "), ...this.encodePrimitiveArray(this.C, encoder)); + } + if (this.StructParent) { + bytes.push(...encoder.encode("/StructParent "), ...encoder.encode(" " + this.StructParent)); + } + if (this.apStream) { + if (!this.AP) { + this.AP = new AppearanceDict(); + } + const apStreamRef = this.apStream.ref; + if (!apStreamRef) { + throw new Error("Appearance stream has no reference"); + } + this.AP.N = ObjectId.fromRef(apStreamRef); + this.AP.R = null; + this.AP.D = null; + this.AP.clearStreams(); + this.AP.setStream("/N", this.apStream); + bytes.push(...encoder.encode("/AP "), ...this.AP.toArray(cryptInfo)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + renderAsync(pageInfo) { + return __awaiter$Q(this, void 0, void 0, function* () { + if (!pageInfo) { + throw new Error("Can't render the annotation: view box is not defined"); + } + this._pageInfo = pageInfo; + if (!this._renderedControls) { + this._renderedControls = this.renderControls(); + } + yield new Promise((resolve, reject) => { + setTimeout(() => __awaiter$Q(this, void 0, void 0, function* () { + yield this.updateRenderAsync(); + resolve(); + }), 0); + }); + return this.lastRenderResult; + }); + } + renderApStreamAsync() { + return __awaiter$Q(this, void 0, void 0, function* () { + const stream = this.apStream; + if (stream) { + try { + const renderer = new AppearanceStreamRenderer(stream, this.Rect, this.$name); + return yield renderer.renderAsync(); + } + catch (e) { + console.log(`Annotation stream render error: ${e.message}`); + } + } + return null; + }); + } + moveToAsync(point) { + return __awaiter$Q(this, void 0, void 0, function* () { + const width = this.Rect[2] - this.Rect[0]; + const height = this.Rect[3] - this.Rect[1]; + const x = point.x - width / 2; + const y = point.y - height / 2; + const mat = l.buildTranslate(x, y); + yield this.applyCommonTransformAsync(mat); + }); + } + rotateByAsync(angle, center) { + return __awaiter$Q(this, void 0, void 0, function* () { + if (!center) { + const [x0, y0, x1, y1] = this.Rect; + center = new u((x0 + x1) / 2, (y0 + y1) / 2); + } + const mat = new l() + .applyTranslation(-center.x, -center.y) + .applyRotation(angle) + .applyTranslation(center.x, center.y); + yield this.applyCommonTransformAsync(mat); + }); + } + toDto() { + var _a, _b, _c, _d, _e; + return { + annotationType: this.Type, + uuid: this.$name, + pageId: this.$pageId, + dateCreated: ((_b = (_a = this["CreationDate"]) === null || _a === void 0 ? void 0 : _a.date) === null || _b === void 0 ? void 0 : _b.toISOString()) || new Date().toISOString(), + dateModified: this.M + ? this.M instanceof LiteralString + ? this.M.literal + : this.M.date.toISOString() + : new Date().toISOString(), + author: (_c = this["T"]) === null || _c === void 0 ? void 0 : _c.literal, + textContent: (_d = this.Contents) === null || _d === void 0 ? void 0 : _d.literal, + rect: this.Rect, + matrix: (_e = this.apStream) === null || _e === void 0 ? void 0 : _e.Matrix, + }; + } + setTextContentAsync(text, undoable = true) { + var _a; + return __awaiter$Q(this, void 0, void 0, function* () { + const dict = this.getProxy(); + const oldText = (_a = dict.Contents) === null || _a === void 0 ? void 0 : _a.literal; + if (!text) { + dict.Contents = null; + } + else { + const literalString = LiteralString.fromString(text); + dict.Contents = literalString; + } + dict.M = DateString.fromDate(new Date()); + if (dict.$onEditAction) { + dict.$onEditAction(undoable + ? () => __awaiter$Q(this, void 0, void 0, function* () { + yield dict.setTextContentAsync(oldText, false); + }) + : undefined); + } + }); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + var _a; + return __awaiter$Q(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/Subtype": + const subtype = yield parser.parseNameAtAsync(i); + if (subtype) { + if (this.Subtype && this.Subtype !== subtype.value) { + throw new Error(`Invalid dict subtype: '${subtype.value}' instead of '${this.Subtype}'`); + } + i = subtype.end + 1; + } + else { + throw new Error("Can't parse /Subtype property value"); + } + break; + case "/Rect": + i = yield this.parseNumberArrayPropAsync(name, parser, i, true); + break; + case "/P": + i = yield this.parseRefPropAsync(name, parser, i); + break; + case "/Contents": + case "/NM": + const contentsEntryType = yield parser.getValueTypeAtAsync(i); + if (contentsEntryType === valueTypes.STRING_LITERAL) { + i = yield this.parseLiteralPropAsync(name, parser, i, parseInfo.cryptInfo); + } + else if (contentsEntryType === valueTypes.STRING_HEX) { + i = yield this.parseHexPropAsync(name, parser, i, parseInfo.cryptInfo); + } + else { + i = yield parser.skipToNextNameAsync(i, end - 1); + } + break; + case "/M": + const date = yield DateString.parseAsync(parser, i, parseInfo.cryptInfo); + if (date) { + this.M = date.value; + i = date.end + 1; + break; + } + else { + const dateLiteral = yield LiteralString.parseAsync(parser, i, parseInfo.cryptInfo); + if (dateLiteral) { + this.M = dateLiteral.value; + i = dateLiteral.end + 1; + break; + } + } + throw new Error("Can't parse /M property value"); + case "/C": + i = yield this.parseNumberArrayPropAsync(name, parser, i, true); + break; + case "/F": + case "/StructParent": + i = yield this.parseNumberPropAsync(name, parser, i, false); + break; + case "/Border": + const borderArray = yield BorderArray.parseAsync(parser, i); + if (borderArray) { + this.Border = borderArray.value; + i = borderArray.end + 1; + } + else { + throw new Error("Can't parse /Border property value"); + } + break; + case "/BS": + const bsEntryType = yield parser.getValueTypeAtAsync(i); + if (bsEntryType === valueTypes.REF) { + const bsDictId = yield ObjectId.parseRefAsync(parser, i); + if (bsDictId && parseInfo.parseInfoGetterAsync) { + const bsParseInfo = yield parseInfo.parseInfoGetterAsync(bsDictId.value.id); + if (bsParseInfo) { + const bsDict = yield BorderStyleDict.parseAsync(bsParseInfo); + if (bsDict) { + this.BS = bsDict.value; + i = bsDict.end + 1; + break; + } + } + } + throw new Error("Can't parse /BS value reference"); + } + else if (bsEntryType === valueTypes.DICTIONARY) { + const bsDictBounds = yield parser.getDictBoundsAtAsync(i); + if (bsDictBounds) { + const bsDict = yield BorderStyleDict.parseAsync({ parser, bounds: bsDictBounds }); + if (bsDict) { + this.BS = bsDict.value; + i = bsDict.end + 1; + break; + } + } + throw new Error("Can't parse /BS value dictionary"); + } + throw new Error(`Unsupported /BS property value type: ${bsEntryType}`); + case "/BE": + const beEntryType = yield parser.getValueTypeAtAsync(i); + if (beEntryType === valueTypes.REF) { + const bsDictId = yield ObjectId.parseRefAsync(parser, i); + if (bsDictId && parseInfo.parseInfoGetterAsync) { + const bsParseInfo = yield parseInfo.parseInfoGetterAsync(bsDictId.value.id); + if (bsParseInfo) { + const bsDict = yield BorderEffectDict.parseAsync(bsParseInfo); + if (bsDict) { + this.BE = bsDict.value; + i = bsDict.end + 1; + break; + } + } + } + throw new Error("Can't parse /BE value reference"); + } + else if (beEntryType === valueTypes.DICTIONARY) { + const bsDictBounds = yield parser.getDictBoundsAtAsync(i); + if (bsDictBounds) { + const bsDict = yield BorderEffectDict.parseAsync({ parser, bounds: bsDictBounds }); + if (bsDict) { + this.BE = bsDict.value; + i = bsDict.end + 1; + break; + } + } + throw new Error("Can't parse /BE value dictionary"); + } + throw new Error(`Unsupported /BE property value type: ${beEntryType}`); + case "/AP": + const apEntryType = yield parser.getValueTypeAtAsync(i); + if (apEntryType === valueTypes.REF) { + const apDictId = yield ObjectId.parseRefAsync(parser, i); + if (apDictId && parseInfo.parseInfoGetterAsync) { + const apParseInfo = yield parseInfo.parseInfoGetterAsync(apDictId.value.id); + if (apParseInfo) { + const apDict = yield AppearanceDict.parseAsync(apParseInfo); + if (apDict) { + this.AP = apDict.value; + i = apDict.end + 1; + break; + } + } + } + throw new Error("Can't parse /AP value reference"); + } + else if (apEntryType === valueTypes.DICTIONARY) { + const apDictBounds = yield parser.getDictBoundsAtAsync(i); + if (apDictBounds) { + const apDict = yield AppearanceDict.parseAsync({ + parser, + bounds: apDictBounds, + parseInfoGetterAsync: parseInfo.parseInfoGetterAsync, + }); + if (apDict) { + this.AP = apDict.value; + i = apDict.end + 1; + break; + } + } + throw new Error("Can't parse /AP value dictionary"); + } + throw new Error(`Unsupported /AP property value type: ${apEntryType}`); + case "/AS": + i = yield this.parseNamePropAsync(name, parser, i); + break; + case "/OC": + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + if (!this.Subtype || !this.Rect) { + throw new Error("Not all required properties parsed"); + } + this.$name = ((_a = this.NM) === null || _a === void 0 ? void 0 : _a.literal) || UUID.getRandomUuid(); + }); + } + getColorString() { + var _a; + let colorString; + if (!((_a = this.C) === null || _a === void 0 ? void 0 : _a.length)) { + colorString = "0 G 0 g"; + } + else if (this.C.length < 3) { + const g = this.C[0]; + colorString = `${g} G ${g} g`; + } + else if (this.C.length === 3) { + const [r, g, b] = this.C; + colorString = `${r} ${g} ${b} RG ${r} ${g} ${b} rg`; + } + else { + const [c, m, y, k] = this.C; + colorString = `${c} ${m} ${y} ${k} K ${c} ${m} ${y} ${k} k`; + } + return colorString; + } + getCurrentRotation() { + var _a; + const matrix = (_a = this.apStream) === null || _a === void 0 ? void 0 : _a.matrix; + if (!matrix) { + return 0; + } + const { r } = matrix.getTRS(); + return r; + } + getLocalBB() { + let bBoxLL; + let bBoxLR; + let bBoxUR; + let bBoxUL; + if (this._bBox) { + return this._bBox; + } + else if (this.apStream) { + const { ll: apTrBoxLL, lr: apTrBoxLR, ur: apTrBoxUR, ul: apTrBoxUL } = this.apStream.transformedBBox; + const { min: boxMin, max: boxMax } = u.minMax(apTrBoxLL, apTrBoxLR, apTrBoxUR, apTrBoxUL); + const rectMin = new u(this.Rect[0], this.Rect[1]); + const rectMax = new u(this.Rect[2], this.Rect[3]); + const mat = l.from4Vec2(boxMin, boxMax, rectMin, rectMax, true); + bBoxLL = apTrBoxLL.applyMat3(mat); + bBoxLR = apTrBoxLR.applyMat3(mat); + bBoxUR = apTrBoxUR.applyMat3(mat); + bBoxUL = apTrBoxUL.applyMat3(mat); + } + else if (this.Rect) { + bBoxLL = new u(this.Rect[0], this.Rect[1]); + bBoxLR = new u(this.Rect[2], this.Rect[1]); + bBoxUR = new u(this.Rect[2], this.Rect[3]); + bBoxUL = new u(this.Rect[0], this.Rect[3]); + } + else { + bBoxLL = new u(); + bBoxLR = new u(); + bBoxUR = new u(); + bBoxUL = new u(); + } + this._bBox = { + ll: bBoxLL, + lr: bBoxLR, + ur: bBoxUR, + ul: bBoxUL, + }; + return this._bBox; + } + convertClientCoordsToPage(clientX, clientY) { + if (!this._pageInfo) { + throw new Error("Can't get exact page coords without page info"); + } + const scale = this._pageInfo.scale; + const rotation = this._pageInfo.rotation; + const [annotPageXMin, annotPageYMin] = this.Rect; + const { x: annotClientXMin, y: annotClientYMin, width: annotClientHorLength, height: annotClientVertLength } = this._renderedBox.getBoundingClientRect(); + const clientPageZero = new u(); + const pageResult = new u(); + switch (rotation) { + case 0: + clientPageZero.set(annotClientXMin - annotPageXMin * scale, annotClientYMin + annotClientVertLength + annotPageYMin * scale); + pageResult.set((clientX - clientPageZero.x) / scale, (clientPageZero.y - clientY) / scale); + break; + case 90: + clientPageZero.set(annotClientXMin - annotPageYMin * scale, annotClientYMin - annotPageXMin * scale); + pageResult.set((clientY - clientPageZero.y) / scale, (clientX - clientPageZero.x) / scale); + break; + case 180: + clientPageZero.set(annotClientXMin + annotClientHorLength + annotPageXMin * scale, annotClientYMin - annotPageYMin * scale); + pageResult.set((clientPageZero.x - clientX) / scale, (clientY - clientPageZero.y) / scale); + break; + case 270: + clientPageZero.set(annotClientXMin + annotClientHorLength + annotPageYMin * scale, annotClientYMin + annotClientVertLength + annotPageXMin * scale); + pageResult.set((clientPageZero.y - clientY) / scale, (clientPageZero.x - clientX) / scale); + break; + default: + throw new Error(`Invalid page rotation value: ${rotation}`); + } + return pageResult; + } + convertPageCoordsToClient(pageX, pageY) { + if (!this._pageInfo) { + throw new Error("Can't get exact page coords without page info"); + } + const scale = this._pageInfo.scale; + const rotation = this._pageInfo.rotation; + const [annotPageXMin, annotPageYMin] = this.Rect; + const { x: annotClientXMin, y: annotClientYMin, width: annotClientHorLength, height: annotClientVertLength } = this._renderedBox.getBoundingClientRect(); + const clientPageZero = new u(); + const clientResult = new u(); + switch (rotation) { + case 0: + clientPageZero.set(annotClientXMin - annotPageXMin * scale, annotClientYMin + annotClientVertLength + annotPageYMin * scale); + clientResult.set(pageX * scale + clientPageZero.x, clientPageZero.y - pageY * scale); + break; + case 90: + clientPageZero.set(annotClientXMin - annotPageYMin * scale, annotClientYMin - annotPageXMin * scale); + clientResult.set(pageY * scale + clientPageZero.x, pageX * scale + clientPageZero.y); + break; + case 180: + clientPageZero.set(annotClientXMin + annotClientHorLength + annotPageXMin * scale, annotClientYMin - annotPageYMin * scale); + clientResult.set(clientPageZero.x - pageX * scale, pageY * scale + clientPageZero.y); + break; + case 270: + clientPageZero.set(annotClientXMin + annotClientHorLength + annotPageYMin * scale, annotClientYMin + annotClientVertLength + annotPageXMin * scale); + clientResult.set(clientPageZero.x - pageY * scale, clientPageZero.y - pageX * scale); + break; + default: + throw new Error(`Invalid page rotation value: ${rotation}`); + } + return clientResult; + } + applyRectTransform(matrix) { + const bBox = this.getLocalBB(); + bBox.ll.applyMat3(matrix); + bBox.lr.applyMat3(matrix); + bBox.ur.applyMat3(matrix); + bBox.ul.applyMat3(matrix); + const { min: newRectMin, max: newRectMax } = u.minMax(bBox.ll, bBox.lr, bBox.ur, bBox.ul); + this.Rect = [newRectMin.x, newRectMin.y, newRectMax.x, newRectMax.y]; + } + applyCommonTransformAsync(matrix, undoable = true) { + return __awaiter$Q(this, void 0, void 0, function* () { + const dict = this.getProxy(); + dict.applyRectTransform(matrix); + const stream = dict.apStream; + if (stream) { + const newApMatrix = l.multiply(stream.matrix, matrix); + dict.apStream.matrix = newApMatrix; + } + dict.M = DateString.fromDate(new Date()); + if (dict.$onEditAction) { + const invertedMat = l.invert(matrix); + dict.$onEditAction(undoable + ? () => __awaiter$Q(this, void 0, void 0, function* () { + yield dict.applyCommonTransformAsync(invertedMat, false); + yield dict.updateRenderAsync(); + }) + : undefined); + } + }); + } + applyTempTransformAsync() { + return __awaiter$Q(this, void 0, void 0, function* () { + if (this._transformationTimer) { + clearTimeout(this._transformationTimer); + this._transformationTimer = null; + return; + } + if (this._transformationPromise) { + yield this._transformationPromise; + } + this._transformationPromise = new Promise((resolve) => __awaiter$Q(this, void 0, void 0, function* () { + this._svgContentCopy.remove(); + applyFlipYToElement(this._svgContentCopy); + if (this._moved) { + yield this.applyCommonTransformAsync(this._tempTransformationMatrix); + yield this.updateRenderAsync(); + } + this._tempTransformationMatrix.reset(); + resolve(); + })); + yield this._transformationPromise; + }); + } + renderAppearance() { + return null; + } + renderRect() { + const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + rect.classList.add("annotation-rect"); + rect.setAttribute("data-annotation-name", this.$name); + rect.setAttribute("x", this.Rect[0] + ""); + rect.setAttribute("y", this.Rect[1] + ""); + rect.setAttribute("width", this.Rect[2] - this.Rect[0] + ""); + rect.setAttribute("height", this.Rect[3] - this.Rect[1] + ""); + return rect; + } + renderBox() { + const { ll, lr, ur, ul } = this.getLocalBB(); + const boxPath = document.createElementNS("http://www.w3.org/2000/svg", "path"); + boxPath.classList.add("annotation-bbox"); + boxPath.setAttribute("data-annotation-name", this.$name); + boxPath.setAttribute("d", `M ${ll.x} ${ll.y} L ${lr.x} ${lr.y} L ${ur.x} ${ur.y} L ${ul.x} ${ul.y} Z`); + return boxPath; + } + renderControls() { + const controlsGroup = document.createElementNS("http://www.w3.org/2000/svg", "g"); + controlsGroup.classList.add("annotation-controls"); + controlsGroup.setAttribute("data-annotation-name", this.$name); + controlsGroup.addEventListener("pointerdown", this.onSvgPointerDown); + controlsGroup.addEventListener("pointerenter", this.onSvgPointerEnter); + controlsGroup.addEventListener("pointerleave", this.onSvgPointerLeave); + return controlsGroup; + } + buildRenderedContentStructure(renderResult) { + var _a; + const content = document.createElement("div"); + content.id = this._svgId; + content.classList.add("annotation-content"); + content.setAttribute("data-annotation-name", this.$name); + content.setAttribute("data-annotation-subtype", this.Subtype); + const { width, height } = this._pageInfo; + if ((_a = renderResult.clipPaths) === null || _a === void 0 ? void 0 : _a.length) { + const clipPathsContainer = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + clipPathsContainer.append(...renderResult.clipPaths); + clipPathsContainer.setAttribute("viewBox", `0 0 ${width} ${height}`); + applyFlipYToElement(clipPathsContainer); + content.append(clipPathsContainer); + } + renderResult.elements.forEach(x => { + const elementContainer = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + elementContainer.classList.add("annotation-content-element"); + elementContainer.setAttribute("viewBox", `0 0 ${width} ${height}`); + elementContainer.style["mixBlendMode"] = x.blendMode; + applyFlipYToElement(elementContainer); + elementContainer.append(x.element); + content.append(elementContainer); + }); + return content; + } + buildRenderContentCopy(contentRenderResult) { + const copy = document.createElementNS("http://www.w3.org/2000/svg", "g"); + contentRenderResult.elements.forEach(x => { + copy.append(x.element.cloneNode(true)); + }); + copy.classList.add("annotation-temp-copy"); + return copy; + } + renderScaleHandles() { + const bBox = this.getLocalBB(); + const handles = []; + ["ll", "lr", "ur", "ul"].forEach(x => { + const handle = document.createElementNS("http://www.w3.org/2000/svg", "line"); + handle.classList.add("annotation-handle", "scale"); + handle.setAttribute("data-handle-name", x); + handle.setAttribute("x1", bBox[x].x + ""); + handle.setAttribute("y1", bBox[x].y + ""); + handle.setAttribute("x2", bBox[x].x + ""); + handle.setAttribute("y2", bBox[x].y + 0.1 + ""); + handle.addEventListener("pointerdown", this.onScaleHandlePointerDown); + handles.push(handle); + }); + return handles; + } + renderRotationHandle() { + const centerX = (this.Rect[0] + this.Rect[2]) / 2; + const centerY = (this.Rect[1] + this.Rect[3]) / 2; + const currentRotation = this.getCurrentRotation(); + const rotationGroup = document.createElementNS("http://www.w3.org/2000/svg", "g"); + rotationGroup.classList.add("annotation-rotator"); + rotationGroup.setAttribute("data-handle-name", "center"); + const rotationGroupCircle = document.createElementNS("http://www.w3.org/2000/svg", "circle"); + rotationGroupCircle.classList.add("circle", "dashed"); + rotationGroupCircle.setAttribute("cx", centerX + ""); + rotationGroupCircle.setAttribute("cy", centerY + ""); + const handleMatrix = new l() + .applyTranslation(-centerX, -centerY + 35) + .applyRotation(currentRotation) + .applyTranslation(centerX, centerY); + const handleCenter = new u(centerX, centerY).applyMat3(handleMatrix); + const rotationGroupLine = document.createElementNS("http://www.w3.org/2000/svg", "line"); + rotationGroupLine.classList.add("dashed"); + rotationGroupLine.setAttribute("x1", centerX + ""); + rotationGroupLine.setAttribute("y1", centerY + ""); + rotationGroupLine.setAttribute("x2", handleCenter.x + ""); + rotationGroupLine.setAttribute("y2", handleCenter.y + ""); + const centerRectHandle = document.createElementNS("http://www.w3.org/2000/svg", "line"); + centerRectHandle.classList.add("annotation-handle", "rotation"); + centerRectHandle.setAttribute("data-handle-name", "center"); + centerRectHandle.setAttribute("x1", handleCenter.x + ""); + centerRectHandle.setAttribute("y1", handleCenter.y + ""); + centerRectHandle.setAttribute("x2", handleCenter.x + ""); + centerRectHandle.setAttribute("y2", handleCenter.y + 0.1 + ""); + centerRectHandle.addEventListener("pointerdown", this.onRotationHandlePointerDown); + rotationGroup.append(rotationGroupCircle, rotationGroupLine, centerRectHandle); + return rotationGroup; + } + renderHandles() { + return [...this.renderScaleHandles(), this.renderRotationHandle()]; + } + updateRenderAsync() { + var _a; + return __awaiter$Q(this, void 0, void 0, function* () { + if (!this._renderedControls) { + return; + } + this._renderedControls.innerHTML = ""; + const contentRenderResult = this.renderAppearance() || (yield this.renderApStreamAsync()); + if (!contentRenderResult || !((_a = contentRenderResult.elements) === null || _a === void 0 ? void 0 : _a.length)) { + this._renderedBox = null; + this._svgContentCopy = null; + return null; + } + const content = this.buildRenderedContentStructure(contentRenderResult); + this._renderedContent = content; + const rect = this.renderRect(); + const box = this.renderBox(); + const handles = this.renderHandles(); + this._renderedBox = box; + this._renderedControls.append(rect, box, ...contentRenderResult.pickHelpers, ...handles); + const copy = this.buildRenderContentCopy(contentRenderResult); + this._svgContentCopy = copy; + if (this.$onRenderUpdatedAction) { + this.$onRenderUpdatedAction(); + } + }); + } + initProxy() { + return super.initProxy(); + } + getProxy() { + return super.getProxy(); + } +} + +var __awaiter$P = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class MarkupAnnotation extends AnnotationDict { + constructor(subType) { + super(subType); + this.RT = markupAnnotationReplyTypes.REPLY; + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.T) { + bytes.push(...encoder.encode("/T "), ...this.T.toArray(cryptInfo)); + } + if (this.Popup) { + bytes.push(...encoder.encode("/Popup "), ...this.Popup.toArray(cryptInfo)); + } + if (this.RC) { + bytes.push(...encoder.encode("/RC "), ...this.RC.toArray(cryptInfo)); + } + if (this.CA) { + bytes.push(...encoder.encode("/CA "), ...encoder.encode(" " + this.CA)); + } + if (this.CreationDate) { + bytes.push(...encoder.encode("/CreationDate "), ...this.CreationDate.toArray(cryptInfo)); + } + if (this.Subj) { + bytes.push(...encoder.encode("/Subj "), ...this.Subj.toArray(cryptInfo)); + } + if (this.IRT) { + bytes.push(...encoder.encode("/IRT "), ...this.IRT.toArray(cryptInfo)); + } + if (this.RT) { + bytes.push(...encoder.encode("/RT "), ...encoder.encode(this.RT)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$P(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/T": + case "/Subj": + i = yield this.parseLiteralPropAsync(name, parser, i, parseInfo.cryptInfo); + break; + case "/Popup": + case "/IRT": + i = yield this.parseRefPropAsync(name, parser, i); + break; + case "/RC": + const rcEntryType = yield parser.getValueTypeAtAsync(i); + if (rcEntryType === valueTypes.REF) { + const rsObjectId = yield ObjectId.parseRefAsync(parser, i); + if (rsObjectId && parseInfo.parseInfoGetterAsync) { + const rcParseInfo = yield parseInfo.parseInfoGetterAsync(rsObjectId.value.id); + if (rcParseInfo) { + const rcObjectType = rcParseInfo.type + || rcParseInfo.parser.getValueTypeAtAsync(rcParseInfo.bounds.contentStart); + if (rcObjectType === valueTypes.STRING_LITERAL) { + const popupTextFromIndirectLiteral = yield LiteralString.parseAsync(rcParseInfo.parser, rcParseInfo.bounds.contentStart); + if (popupTextFromIndirectLiteral) { + this.RC = popupTextFromIndirectLiteral.value; + i = rsObjectId.end + 1; + break; + } + } + else if (rcObjectType === valueTypes.DICTIONARY) { + const popupTextStream = yield TextStream.parseAsync(rcParseInfo); + if (popupTextStream) { + const popupTextFromStream = popupTextStream.value.getText(); + this.RC = LiteralString.fromString(popupTextFromStream); + i = rsObjectId.end + 1; + break; + } + } + else { + throw new Error(`Unsupported /RC property value type: ${rcObjectType}`); + } + } + } + throw new Error("Can't parse /RC value reference"); + } + else if (rcEntryType === valueTypes.STRING_LITERAL) { + const popupTextFromLiteral = yield LiteralString.parseAsync(parser, i, parseInfo.cryptInfo); + if (popupTextFromLiteral) { + this.RC = popupTextFromLiteral.value; + i = popupTextFromLiteral.end + 1; + break; + } + throw new Error("Can't parse /RC property value"); + } + throw new Error(`Unsupported /RC property value type: ${rcEntryType}`); + case "/CA": + i = yield this.parseNumberPropAsync(name, parser, i, true); + break; + case "/CreationDate": + i = yield this.parseDatePropAsync(name, parser, i, parseInfo.cryptInfo); + break; + case "/RT": + const replyType = yield parser.parseNameAtAsync(i, true); + if (replyType && Object.values(markupAnnotationReplyTypes) + .includes(replyType.value)) { + this.RT = replyType.value; + i = replyType.end + 1; + } + else { + throw new Error("Can't parse /RT property value"); + } + break; + case "/ExData": + break; + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + if (!this.Subtype || !this.Rect) { + throw new Error("Not all required properties parsed"); + } + }); + } + getColorRect() { + let r = 0; + let g = 0; + let b = 0; + let a = 1; + if (this.C) { + if (this.C.length === 1) { + const gray = this.C[0]; + r = g = b = gray; + } + else if (this.C.length === 3) { + [r, g, b] = this.C; + } + else if (this.C.length === 4) { + const [c, m, y, k] = this.C; + r = (1 - c) * (1 - k); + g = (1 - m) * (1 - k); + b = (1 - y) * (1 - k); + } + } + if (!isNaN(this.CA)) { + a = this.CA; + } + const color = [r, g, b, a]; + return color; + } + updateTextDataAsync(options) { + var _a; + return __awaiter$P(this, void 0, void 0, function* () { + const text = (_a = this.Contents) === null || _a === void 0 ? void 0 : _a.literal; + const textData = yield TextData.buildAsync(text, options); + this._textData = textData; + return this._textData; + }); + } + getLineEndingStreamPart(point, type, strokeWidth, side) { + const size = Math.max(strokeWidth * LINE_END_MULTIPLIER, LINE_END_MIN_SIZE); + let text = ""; + switch (type) { + case lineEndingTypes.ARROW_OPEN: + if (side === "left") { + text += `\n${point.x + size} ${point.y + size / 2} m`; + text += `\n${point.x} ${point.y} l`; + text += `\n${point.x + size} ${point.y - size / 2} l`; + } + else { + text += `\n${point.x - size} ${point.y + size / 2} m`; + text += `\n${point.x} ${point.y} l`; + text += `\n${point.x - size} ${point.y - size / 2} l`; + } + text += "\nS"; + return text; + case lineEndingTypes.ARROW_OPEN_R: + if (side === "left") { + text += `\n${point.x} ${point.y + size / 2} m`; + text += `\n${point.x + size} ${point.y} l`; + text += `\n${point.x} ${point.y - size / 2} l`; + } + else { + text += `\n${point.x} ${point.y + size / 2} m`; + text += `\n${point.x - size} ${point.y} l`; + text += `\n${point.x} ${point.y - size / 2} l`; + } + text += "\nS"; + return text; + case lineEndingTypes.ARROW_CLOSED: + if (side === "left") { + text += `\n${point.x + size} ${point.y + size / 2} m`; + text += `\n${point.x} ${point.y} l`; + text += `\n${point.x + size} ${point.y - size / 2} l`; + } + else { + text += `\n${point.x - size} ${point.y + size / 2} m`; + text += `\n${point.x} ${point.y} l`; + text += `\n${point.x - size} ${point.y - size / 2} l`; + } + text += "\ns"; + return text; + case lineEndingTypes.ARROW_CLOSED_R: + if (side === "left") { + text += `\n${point.x + size} ${point.y} m`; + text += `\n${point.x} ${point.y + size / 2} l`; + text += `\n${point.x} ${point.y - size / 2} l`; + } + else { + text += `\n${point.x - size} ${point.y} m`; + text += `\n${point.x} ${point.y - size / 2} l`; + text += `\n${point.x} ${point.y + size / 2} l`; + } + text += "\ns"; + return text; + case lineEndingTypes.BUTT: + text += `\n${point.x} ${point.y + size / 2} m`; + text += `\n${point.x} ${point.y - size / 2} l`; + text += "\nS"; + return text; + case lineEndingTypes.SLASH: + text += `\n${point.x + size / 2} ${point.y + size / 2} m`; + text += `\n${point.x - size / 2} ${point.y - size / 2} l`; + text += "\nS"; + return text; + case lineEndingTypes.DIAMOND: + text += `\n${point.x} ${point.y + size / 2} m`; + text += `\n${point.x + size / 2} ${point.y} l`; + text += `\n${point.x} ${point.y - size / 2} l`; + text += `\n${point.x - size / 2} ${point.y} l`; + text += "\ns"; + return text; + case lineEndingTypes.SQUARE: + text += `\n${point.x - size / 2} ${point.y + size / 2} m`; + text += `\n${point.x + size / 2} ${point.y + size / 2} l`; + text += `\n${point.x + size / 2} ${point.y - size / 2} l`; + text += `\n${point.x - size / 2} ${point.y - size / 2} l`; + text += "\ns"; + return text; + case lineEndingTypes.CIRCLE: + const c = BEZIER_CONSTANT; + const r = size / 2; + const cw = c * r; + const xmin = point.x - r; + const ymin = point.y - r; + const xmax = point.x + r; + const ymax = point.y + r; + text += `\n${point.x} ${ymax} m`; + text += `\n${point.x + cw} ${ymax} ${xmax} ${point.y + cw} ${xmax} ${point.y} c`; + text += `\n${xmax} ${point.y - cw} ${point.x + cw} ${ymin} ${point.x} ${ymin} c`; + text += `\n${point.x - cw} ${ymin} ${xmin} ${point.y - cw} ${xmin} ${point.y} c`; + text += `\n${xmin} ${point.y + cw} ${point.x - cw} ${ymax} ${point.x} ${ymax} c`; + text += "\nS"; + return text; + case lineEndingTypes.NONE: + default: + return ""; + } + } +} + +class DataUpdater { + constructor(sourceBytes, lastXref, referenceData, authResult) { + this._writtenIds = new Set(); + this.writeImageXObject = (obj) => { + const sMask = obj.sMask; + if (this.isNew(sMask)) { + const newMaskRef = this.writeIndirectObject(sMask); + obj.SMask = ObjectId.fromRef(newMaskRef); + } + else if (sMask.edited) { + this.writeUpdatedIndirectObject(sMask); + } + if (this.isNew(obj)) { + return this.writeIndirectObject(obj); + } + else if (obj.edited) { + return this.writeUpdatedIndirectObject(obj); + } + else { + return { + id: obj.id, + generation: obj.generation, + byteOffset: this._refData.getOffset(obj.id) + }; + } + }; + this._lastXref = lastXref; + this._refData = referenceData; + this._changeData = new ReferenceDataChange(referenceData); + this._writer = new DataWriter(sourceBytes); + this._stringCryptor = authResult === null || authResult === void 0 ? void 0 : authResult.stringCryptor; + this._streamCryptor = authResult === null || authResult === void 0 ? void 0 : authResult.streamCryptor; + } + getDataWithUpdatedAnnotations(data) { + for (const { page, supportedAnnotations: annotations, allAnnotationIds: refArray } of data) { + if (!(annotations === null || annotations === void 0 ? void 0 : annotations.length)) { + continue; + } + for (const annotation of annotations) { + if (annotation.deleted) { + if (!annotation.ref) { + continue; + } + const refIndex = refArray.findIndex(x => x.id === annotation.id); + refArray.splice(refIndex, 1); + this._changeData.setRefFree(annotation.id); + if (annotation instanceof MarkupAnnotation && annotation.Popup) { + this._changeData.setRefFree(annotation.Popup.id); + } + } + else if (!annotation.ref || annotation.edited) { + const apStream = annotation.apStream; + if (apStream) { + this.writeFormXObject(apStream); + } + if (this.isNew(annotation)) { + const newAnnotRef = this.writeIndirectObject(annotation); + refArray.push(ObjectId.fromRef(newAnnotRef)); + } + else { + this.writeUpdatedIndirectObject(annotation); + } + } + } + if (page.Annots instanceof ObjectId + && this._changeData.isUsedInSource(page.Annots.id)) { + const annotsRef = { + id: page.Annots.id, + generation: page.Annots.generation, + byteOffset: this._writer.offset + }; + const annotsCryptInfo = { + ref: annotsRef, + streamCryptor: this._streamCryptor, + stringCryptor: this._stringCryptor, + }; + this._changeData.updateUsedRef(annotsRef); + this._writer.writeIndirectArray(annotsCryptInfo, refArray); + } + else { + const newAnnotsRef = this._changeData.takeFreeRef(this._writer.offset, true); + const annotsCryptInfo = { + ref: newAnnotsRef, + streamCryptor: this._streamCryptor, + stringCryptor: this._stringCryptor, + }; + this._writer.writeIndirectArray(annotsCryptInfo, refArray); + page.Annots = ObjectId.fromRef(newAnnotsRef); + } + this.writeUpdatedIndirectObject(page); + } + this.writeXref(); + const bytes = this._writer.getCurrentData(); + return bytes; + } + isNew(obj) { + return !obj.ref || !this._changeData.isUsedInSource(obj.id); + } + writeIndirectObject(obj) { + if (this._writtenIds.has(obj.id)) { + return this._changeData.getUsedRef(obj.id); + } + const newRef = this._changeData.takeFreeRef(this._writer.offset, true); + const newObjCryptInfo = { + ref: newRef, + streamCryptor: this._streamCryptor, + stringCryptor: this._stringCryptor, + }; + this._writer.writeIndirectObject(newObjCryptInfo, obj); + obj.ref = newRef; + this._writtenIds.add(newRef.id); + return newRef; + } + writeUpdatedIndirectObject(obj) { + const objRef = { + id: obj.id, + generation: obj.generation, + byteOffset: this._writer.offset + }; + const objCryptInfo = { + ref: objRef, + streamCryptor: this._streamCryptor, + stringCryptor: this._stringCryptor, + }; + this._changeData.updateUsedRef(objRef); + this._writer.writeIndirectObject(objCryptInfo, obj); + return objRef; + } + writeFormXObject(obj) { + const resources = obj.Resources; + if (resources && resources.edited) { + [...resources.getXObjects()].forEach(([name, xObj]) => { + if (xObj instanceof ImageStream) { + this.writeImageXObject(xObj); + } + else if (xObj instanceof XFormStream) { + this.writeFormXObject(xObj); + } + }); + [...resources.getFonts()].forEach(([name, font]) => { + if (font.encoding && this.isNew(font.encoding)) { + this.writeIndirectObject(font.encoding); + } + if (font.descriptor && this.isNew(font.descriptor)) { + this.writeIndirectObject(font.descriptor); + } + if (this.isNew(font)) { + this.writeIndirectObject(font); + } + else if (font.edited) { + this.writeUpdatedIndirectObject(font); + } + }); + } + if (this.isNew(obj)) { + return this.writeIndirectObject(obj); + } + else if (obj.edited) { + return this.writeUpdatedIndirectObject(obj); + } + else { + return { + id: obj.id, + generation: obj.generation, + byteOffset: this._refData.getOffset(obj.id) + }; + } + } + writeXref() { + const newXrefOffset = this._writer.offset; + const newXrefEntries = this._changeData.exportEntries(); + const newXref = this._lastXref.createUpdate(newXrefEntries, newXrefOffset); + if (this._lastXref instanceof XRefStream) { + const newXrefRef = this._changeData.takeFreeRef(newXrefOffset, true); + this._writer.writeIndirectObject({ ref: newXrefRef }, newXref); + } + else { + this._writer.writeBytes(newXref.toArray()); + } + this._writer.writeEof(newXrefOffset); + return newXrefOffset; + } +} + +function bytesToWordArray(data) { + return CryptoES.lib.WordArray.create(data); +} +function wordArrayToBytes(wordArray) { + return ByteUtils.int32ArrayToBytes(wordArray.words).slice(0, wordArray.sigBytes); +} +function md5(data) { + if (data instanceof Uint8Array) { + data = bytesToWordArray(data); + } + const result = CryptoES.MD5(data); + return result; +} +function rc4(data, key) { + if (data instanceof Uint8Array) { + data = bytesToWordArray(data); + } + if (key instanceof Uint8Array) { + key = bytesToWordArray(key); + } + const result = CryptoES.RC4.encrypt(data, key).ciphertext; + return result; +} +function aes(data, key, decrypt = false) { + if (data instanceof Uint8Array) { + data = bytesToWordArray(data); + } + if (key instanceof Uint8Array) { + key = bytesToWordArray(key); + } + if (decrypt) { + const ivWordArray = CryptoES.lib.WordArray.create(data.words.slice(0, 4)); + const d = CryptoES.algo.AES.createDecryptor(key, { + mode: CryptoES.mode.CBC, + iv: ivWordArray, + padding: CryptoES.pad.Pkcs7, + }); + const result = d.finalize(data); + return result; + } + else { + const ivWordArray = CryptoES.lib.WordArray.random(16); + const e = CryptoES.algo.AES.createEncryptor(key, { + mode: CryptoES.mode.CBC, + iv: ivWordArray, + padding: CryptoES.pad.Pkcs7, + }); + const result = e.finalize(data); + return result; + } +} + +const AESV2_KEY_PADDING = [ + 0x73, 0x41, 0x6C, 0x54, +]; +class AESV2DataCryptor { + constructor(key) { + if (!key) { + throw new Error("Empty key"); + } + if (key.length !== 16) { + throw new Error(`Invalid key length: ${key.length} (shall be 16)`); + } + this._n = key.length; + this._key = key; + this._tempKey = new Uint8Array(key.length + 9); + } + encrypt(data, ref) { + return this.run(data, ref.id, ref.generation); + } + decrypt(data, ref) { + return this.run(data, ref.id, ref.generation, true); + } + run(data, id, generation, decrypt = false) { + const idBytes = ByteUtils.int32ToBytes(id, true); + const genBytes = ByteUtils.int32ToBytes(generation, true); + this._tempKey.set(this._key, 0); + this._tempKey.set(idBytes.subarray(0, 3), this._n); + this._tempKey.set(genBytes.subarray(0, 2), this._n + 3); + this._tempKey.set(AESV2_KEY_PADDING, this._n + 5); + const hash = wordArrayToBytes(md5(this._tempKey)); + const n = Math.min(this._n + 5, 16); + const key = hash.slice(0, n); + const result = wordArrayToBytes(aes(data, key, decrypt)); + return decrypt + ? result.slice(16) + : result; + } +} + +class AESV3DataCryptor { + constructor(key) { + if (!key) { + throw new Error("Empty key"); + } + if (key.length !== 32) { + throw new Error(`Invalid key length: ${key.length} (shall be 32)`); + } + this._n = key.length; + this._key = key; + } + encrypt(data, ref) { + return this.run(data, ref.id, ref.generation); + } + decrypt(data, ref) { + return this.run(data, ref.id, ref.generation, true); + } + run(data, id, generation, decrypt = false) { + const result = wordArrayToBytes(aes(data, this._key, decrypt)); + return decrypt + ? result.slice(16) + : result; + } +} + +class IdentityDataCryptor { + constructor() { + } + encrypt(data, ref) { + return data; + } + decrypt(data, ref) { + return data; + } +} + +class RC4DataCryptor { + constructor(key) { + if (!key) { + throw new Error("Empty key"); + } + if (key.length < 5 || key.length > 16) { + throw new Error(`Invalid key length: ${key.length} (shall be a multiple of 8 in the range from 40 to 128)`); + } + this._n = key.length; + this._key = key; + this._tempKey = new Uint8Array(key.length + 5); + } + encrypt(data, ref) { + const idBytes = ByteUtils.int32ToBytes(ref.id, true); + const genBytes = ByteUtils.int32ToBytes(ref.generation, true); + this._tempKey.set(this._key, 0); + this._tempKey.set(idBytes.slice(0, 3), this._n); + this._tempKey.set(genBytes.slice(0, 2), this._n + 3); + const hash = wordArrayToBytes(md5(this._tempKey)); + const n = Math.min(this._n + 5, 16); + const key = hash.slice(0, n); + const encrypted = wordArrayToBytes(rc4(data, key)); + return encrypted; + } + decrypt(data, ref) { + return this.encrypt(data, ref); + } +} + +const PASSWORD_32_PADDING = [ + 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, + 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08, + 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, + 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A, +]; +class DataCryptHandler { + constructor(options, fileId) { + const { filter, version, revision, permissions, encryptMetadata, keyLength, stringKeyLength, streamKeyLength, stringMethod, streamMethod, oPasswordHash, uPasswordHash, oEncPasswordHash, uEncPasswordHash, perms } = options; + if (filter !== "/Standard") { + throw new Error(`Unsupported filter name: ${filter}`); + } + if (![1, 2, 4, 5].includes(version)) { + throw new Error(`Unsupported algorithm version: ${version}`); + } + if (![2, 3, 4, 5, 6].includes(revision)) { + throw new Error(`Unsupported algorithm revision: ${revision}`); + } + if (isNaN(permissions)) { + throw new Error("Permissions not provided"); + } + if (!oPasswordHash || !uPasswordHash) { + throw new Error("Password hash not provided"); + } + this._filter = filter; + this._version = version; + this._revision = revision; + this._permissions = permissions; + this._keyLength = keyLength; + this._encryptMetadata = encryptMetadata; + this._stringKeyLength = stringKeyLength; + this._streamKeyLength = streamKeyLength; + this._stringMethod = stringMethod; + this._streamMethod = streamMethod; + this._oPasswordHash = oPasswordHash; + this._uPasswordHash = uPasswordHash; + this._oEncPasswordHash = oEncPasswordHash; + this._uEncPasswordHash = uEncPasswordHash; + this._perms = perms; + this._fileId = fileId; + } + authenticate(password) { + const version = this._version; + const stringMethod = this._stringMethod; + const streamMethod = this._streamMethod; + let owner = false; + const ownerAuthenticated = this.authOwnerPassword(password); + if (ownerAuthenticated) { + owner = true; + } + else { + const userAuthenticated = this.authUserPassword(password); + if (!userAuthenticated) { + return null; + } + } + const key = this._lastEncryptionKey; + switch (version) { + case 1: + const rc4_40 = new RC4DataCryptor(key); + return { + owner, + stringCryptor: rc4_40, + streamCryptor: rc4_40, + }; + case 2: + const rc4_128 = new RC4DataCryptor(key); + return { + owner, + stringCryptor: rc4_128, + streamCryptor: rc4_128, + }; + case 4: + let v4stringCryptor; + if (!stringMethod || stringMethod === cryptMethods.NONE) { + v4stringCryptor = new IdentityDataCryptor(); + } + else if (stringMethod === cryptMethods.RC4) { + v4stringCryptor = new RC4DataCryptor(key); + } + else if (stringMethod === cryptMethods.AES_128) { + v4stringCryptor = new AESV2DataCryptor(key); + } + else { + throw new Error(`Invalid crypt method: ${stringMethod}`); + } + let v4streamCryptor; + if (!streamMethod || streamMethod === cryptMethods.NONE) { + v4streamCryptor = new IdentityDataCryptor(); + } + else if (streamMethod === cryptMethods.RC4) { + v4streamCryptor = new RC4DataCryptor(key); + } + else if (streamMethod === cryptMethods.AES_128) { + v4streamCryptor = new AESV2DataCryptor(key); + } + else { + throw new Error(`Invalid crypt method: ${streamMethod}`); + } + return { + owner, + stringCryptor: v4stringCryptor, + streamCryptor: v4streamCryptor, + }; + case 5: + let v5stringCryptor; + if (!stringMethod || stringMethod === cryptMethods.NONE) { + v4stringCryptor = new IdentityDataCryptor(); + } + else if (stringMethod === cryptMethods.AES_256) { + v4stringCryptor = new AESV3DataCryptor(key); + } + else { + throw new Error(`Invalid crypt method: ${stringMethod}`); + } + let v5streamCryptor; + if (!streamMethod || streamMethod === cryptMethods.NONE) { + v4streamCryptor = new IdentityDataCryptor(); + } + else if (streamMethod === cryptMethods.AES_256) { + v4streamCryptor = new AESV3DataCryptor(key); + } + else { + throw new Error(`Invalid crypt method: ${streamMethod}`); + } + return { + owner, + stringCryptor: v5stringCryptor, + streamCryptor: v5streamCryptor, + }; + } + } + padPassword32(password) { + if (!password) { + return new Uint8Array(PASSWORD_32_PADDING); + } + const bytes = new TextEncoder().encode(password); + const padded = new Uint8Array(32); + padded.set(bytes.slice(0, 32)); + if (bytes.length < 32) { + padded.set(PASSWORD_32_PADDING.slice(0, 32 - bytes.length), bytes.length); + } + return padded; + } + computeEncryptionKey(password) { + if ([2, 3, 4].includes(this._revision)) { + const paddedPassword = this.padPassword32(password); + const permissionsLe = ByteUtils.int32ToBytes(this._permissions, true); + const metadata = this._revision >= 4 && !this._encryptMetadata + ? new Uint8Array([255, 255, 255, 255]) + : new Uint8Array(0); + const dataToHash = new Uint8Array([ + ...paddedPassword, + ...this._oPasswordHash, + ...permissionsLe, + ...this._fileId, + ...metadata, + ]); + let hash = wordArrayToBytes(md5(dataToHash)); + const keyLength = this._keyLength >> 3; + if (this._revision >= 3) { + for (let i = 0; i < 50; i++) { + hash = wordArrayToBytes(md5(hash.slice(0, keyLength))); + } + } + const encryptionKey = hash.slice(0, keyLength); + this._lastEncryptionKey = encryptionKey; + return encryptionKey; + } + else if (this._revision === 5) { + throw new Error("Not implemented yet"); + } + else if (this._revision === 6) { + throw new Error("Not implemented yet"); + } + } + computeOHashEncryptionKey_R2R3R4(password) { + const paddedPassword = this.padPassword32(password); + let hash = md5(paddedPassword); + if (this._revision >= 3) { + for (let i = 0; i < 50; i++) { + hash = md5(hash); + } + } + const hashArray = wordArrayToBytes(hash); + const keyLength = this._keyLength >> 3; + return hashArray.slice(0, keyLength); + } + computeOHash_R2R3R4(oPassword, uPassword) { + const key = this.computeOHashEncryptionKey_R2R3R4(oPassword || uPassword); + const paddedUPassword = this.padPassword32(uPassword); + let hash = rc4(paddedUPassword, key); + if (this._revision >= 3) { + for (let i = 1; i < 20; i++) { + hash = rc4(hash, ByteUtils.xorBytes(key, i)); + } + } + return wordArrayToBytes(hash); + } + computeUHash_R2(password) { + const key = this.computeEncryptionKey(password); + const padding = new Uint8Array(PASSWORD_32_PADDING); + const u = wordArrayToBytes(rc4(padding, key)); + return u; + } + computeUHash_R3R4(password) { + const key = this.computeEncryptionKey(password); + const dataToHash = new Uint8Array([ + ...PASSWORD_32_PADDING, + ...this._fileId, + ]); + let hash = md5(dataToHash); + hash = rc4(hash, key); + for (let i = 1; i < 20; i++) { + hash = rc4(hash, ByteUtils.xorBytes(key, i)); + } + return wordArrayToBytes(hash); + } + authOwnerPassword(password) { + if ([2, 3, 4].includes(this._revision)) { + const ownerEncryptionKey = this.computeOHashEncryptionKey_R2R3R4(password); + let userPasswordPadded; + if (this._revision === 2) { + userPasswordPadded = wordArrayToBytes(rc4(this._oPasswordHash, ownerEncryptionKey)); + } + else { + let hash = bytesToWordArray(this._oPasswordHash); + for (let i = 19; i >= 0; i--) { + hash = rc4(hash, ByteUtils.xorBytes(ownerEncryptionKey, i)); + } + userPasswordPadded = wordArrayToBytes(hash); + } + const j = ByteUtils.findSubarrayIndex(userPasswordPadded, new Uint8Array(PASSWORD_32_PADDING)); + const userPassword = new TextDecoder().decode(j === -1 + ? userPasswordPadded + : userPasswordPadded.subarray(0, j)); + return this.authUserPassword(userPassword); + } + else if (this._revision === 5) { + throw new Error("Not implemented yet"); + } + else if (this._revision === 6) { + throw new Error("Not implemented yet"); + } + } + authUserPassword(password) { + let u; + if (this._revision === 2) { + u = this.computeUHash_R2(password); + return ByteUtils.arraysEqual(this._uPasswordHash, u); + } + else if (this._revision === 3 || this._revision === 4) { + u = this.computeUHash_R3R4(password); + return ByteUtils.arraysEqual(this._uPasswordHash.subarray(0, 16), u); + } + else if (this._revision === 5) { + throw new Error("Not implemented yet"); + } + else if (this._revision === 6) { + throw new Error("Not implemented yet"); + } + } +} + +var __awaiter$O = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class ObjectStream extends PdfStream { + constructor() { + super(streamTypes.OBJECT_STREAM); + } + static parseAsync(parseInfo) { + return __awaiter$O(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new ObjectStream(); + yield pdfObject.parsePropsAsync(parseInfo); + return { value: pdfObject, start: parseInfo.bounds.start, end: parseInfo.bounds.end }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + getObjectDataAsync(id) { + return __awaiter$O(this, void 0, void 0, function* () { + if (!this._streamData || !this.N || !this.First) { + return null; + } + const parser = yield this.getStreamDataParserAsync(); + const offsetMap = new Map(); + let temp; + let objectId; + let byteOffset; + let position = 0; + for (let n = 0; n < this.N; n++) { + temp = yield parser.parseNumberAtAsync(position, false, false); + objectId = temp.value; + position = temp.end + 2; + temp = yield parser.parseNumberAtAsync(position, false, false); + byteOffset = temp.value; + position = temp.end + 2; + offsetMap.set(objectId, byteOffset); + } + if (!offsetMap.has(id)) { + return null; + } + const objectStart = this.First + offsetMap.get(id); + const objectType = yield parser.getValueTypeAtAsync(objectStart); + if (objectType === null) { + return; + } + let bounds; + let value; + switch (objectType) { + case objectTypes.DICTIONARY: + bounds = yield parser.getDictBoundsAtAsync(objectStart, false); + break; + case objectTypes.ARRAY: + bounds = yield parser.getArrayBoundsAtAsync(objectStart, false); + break; + case objectTypes.STRING_LITERAL: + const literalValue = yield LiteralString.parseAsync(parser, objectStart); + if (literalValue) { + bounds = { start: literalValue.start, end: literalValue.end }; + value = literalValue; + } + break; + case objectTypes.STRING_HEX: + const hexValue = yield HexString.parseAsync(parser, objectStart); + if (hexValue) { + bounds = { start: hexValue.start, end: hexValue.end }; + value = hexValue; + } + break; + case objectTypes.NUMBER: + const numValue = yield parser.parseNumberAtAsync(objectStart); + if (numValue) { + bounds = { start: numValue.start, end: numValue.end }; + value = numValue; + } + break; + } + if (!bounds) { + return null; + } + const bytes = yield parser.sliceCharCodesAsync(bounds.start, bounds.end); + if (!bytes.length) { + throw new Error("Object byte array is empty"); + } + return { + parser: yield PdfStream.getDataParserAsync(bytes), + bounds: { + start: 0, + end: bytes.length - 1, + contentStart: bounds.contentStart + ? bounds.contentStart - bounds.start + : undefined, + contentEnd: bounds.contentEnd + ? bytes.length - 1 - (bounds.end - bounds.contentEnd) + : undefined, + }, + type: objectType, + value, + cryptInfo: { ref: { id, generation: 0 } }, + streamId: this.id, + }; + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.N) { + bytes.push(...encoder.encode("/N "), ...encoder.encode(" " + this.N)); + } + if (this.First) { + bytes.push(...encoder.encode("/First "), ...encoder.encode(" " + this.First)); + } + if (this.Extends) { + bytes.push(...encoder.encode("/Extends "), ...this.Extends.toArray(cryptInfo)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$O(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const dictBounds = yield parser.getDictBoundsAtAsync(start); + let i = yield parser.skipToNextNameAsync(dictBounds.contentStart, dictBounds.contentEnd); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/N": + case "/First": + i = yield this.parseNumberPropAsync(name, parser, i, false); + break; + case "/Extends": + i = yield this.parseRefPropAsync(name, parser, i); + break; + default: + i = yield parser.skipToNextNameAsync(i, dictBounds.contentEnd); + break; + } + } + else { + break; + } + } + }); + } +} + +var __awaiter$N = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class CryptFilterDict extends PdfDict { + constructor() { + super(dictTypes.CRYPT_FILTER); + this.CFM = cryptMethods.NONE; + this.AuthEvent = authEvents.DOC_OPEN; + this.Length = 40; + this.EncryptMetadata = true; + } + static parseAsync(parseInfo) { + return __awaiter$N(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new CryptFilterDict(); + yield pdfObject.parsePropsAsync(parseInfo); + return { value: pdfObject, start: parseInfo.bounds.start, end: parseInfo.bounds.end }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.CFM) { + bytes.push(...encoder.encode("/CFM "), ...encoder.encode(this.CFM)); + } + if (this.AuthEvent) { + bytes.push(...encoder.encode("/AuthEvent "), ...encoder.encode(this.AuthEvent)); + } + if (this.Length) { + bytes.push(...encoder.encode("/Length "), ...encoder.encode(" " + this.Length)); + } + if (this.EncryptMetadata) { + bytes.push(...encoder.encode("/EncryptMetadata "), ...encoder.encode(" " + this.EncryptMetadata)); + } + if (this.Recipients) { + if (this.Recipients instanceof HexString) { + bytes.push(...encoder.encode("/Recipients "), ...this.Recipients.toArray(cryptInfo)); + } + else { + bytes.push(...encoder.encode("/Recipients "), ...this.encodeSerializableArray(this.Recipients, cryptInfo)); + } + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$N(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/CFM": + const method = yield parser.parseNameAtAsync(i, true); + if (method && Object.values(cryptMethods) + .includes(method.value)) { + this.CFM = method.value; + i = method.end + 1; + } + else { + throw new Error("Can't parse /CFM property value"); + } + break; + case "/AuthEvent": + const authEvent = yield parser.parseNameAtAsync(i, true); + if (authEvent && Object.values(authEvents) + .includes(authEvent.value)) { + this.AuthEvent = authEvent.value; + i = authEvent.end + 1; + } + else { + throw new Error("Can't parse /AuthEvent property value"); + } + break; + case "/Length": + i = yield this.parseNumberPropAsync(name, parser, i, false); + break; + case "/EncryptMetadata": + i = yield this.parseBoolPropAsync(name, parser, i); + break; + case "/Recipients": + const entryType = yield parser.getValueTypeAtAsync(i); + if (entryType === valueTypes.STRING_HEX) { + const recipient = yield HexString.parseAsync(parser, i, parseInfo.cryptInfo); + if (recipient) { + this.Recipients = recipient.value; + i = recipient.end + 1; + break; + } + else { + throw new Error("Can't parse /Recipients property value"); + } + } + else if (entryType === valueTypes.ARRAY) { + const recipients = yield HexString.parseArrayAsync(parser, i); + if (recipients) { + this.Recipients = recipients.value; + i = recipients.end + 1; + break; + } + else { + throw new Error("Can't parse /Recipients property value"); + } + } + throw new Error(`Unsupported /Filter property value type: ${entryType}`); + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + }); + } +} + +var __awaiter$M = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class CryptMapDict extends PdfDict { + constructor() { + super(null); + this._filtersMap = new Map(); + } + static parseAsync(parseInfo) { + return __awaiter$M(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new CryptMapDict(); + yield pdfObject.parsePropsAsync(parseInfo); + return { value: pdfObject, start: parseInfo.bounds.start, end: parseInfo.bounds.end }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + getProp(name) { + return this._filtersMap.get(name); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this._filtersMap.size) { + this._filtersMap.forEach((v, k) => bytes.push(...encoder.encode(k), ...v.toArray(cryptInfo))); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$M(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + default: + const entryType = yield parser.getValueTypeAtAsync(i); + if (entryType === valueTypes.DICTIONARY) { + const dictBounds = yield parser.getDictBoundsAtAsync(i); + if (dictBounds) { + const filter = yield CryptFilterDict.parseAsync({ parser, bounds: dictBounds }); + if (filter) { + this._filtersMap.set(name, filter.value); + i = filter.end + 1; + break; + } + } + } + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + }); + } +} + +var __awaiter$L = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class EncryptionDict extends PdfDict { + constructor() { + super(dictTypes.EMPTY); + this.Filter = "/Standard"; + this.Length = 40; + this.StmF = "/Identity"; + this.StrF = "/Identity"; + this.EncryptMetadata = true; + } + static parseAsync(parseInfo) { + return __awaiter$L(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new EncryptionDict(); + yield pdfObject.parsePropsAsync(parseInfo); + return { value: pdfObject, start: parseInfo.bounds.start, end: parseInfo.bounds.end }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.Filter) { + bytes.push(...encoder.encode("/Filter "), ...encoder.encode(this.Filter)); + } + if (this.SubFilter) { + bytes.push(...encoder.encode("/SubFilter "), ...encoder.encode(this.SubFilter)); + } + if (this.V) { + bytes.push(...encoder.encode("/V "), ...encoder.encode(" " + this.V)); + } + if (this.Length) { + bytes.push(...encoder.encode("/Length "), ...encoder.encode(" " + this.Length)); + } + if (this.CF) { + bytes.push(...encoder.encode("/CF "), ...this.CF.toArray(cryptInfo)); + } + if (this.StmF) { + bytes.push(...encoder.encode("/StmF "), ...encoder.encode(this.StmF)); + } + if (this.StrF) { + bytes.push(...encoder.encode("/StrF "), ...encoder.encode(this.StrF)); + } + if (this.EFF) { + bytes.push(...encoder.encode("/EFF "), ...encoder.encode(this.EFF)); + } + if (this.R) { + bytes.push(...encoder.encode("/R "), ...encoder.encode(" " + this.R)); + } + if (this.O) { + bytes.push(...encoder.encode("/O "), ...this.O.toArray(cryptInfo)); + } + if (this.U) { + bytes.push(...encoder.encode("/U "), ...this.U.toArray(cryptInfo)); + } + if (this.OE) { + bytes.push(...encoder.encode("/OE "), ...this.OE.toArray(cryptInfo)); + } + if (this.UE) { + bytes.push(...encoder.encode("/UE "), ...this.UE.toArray(cryptInfo)); + } + if (this.P) { + bytes.push(...encoder.encode("/P "), ...encoder.encode(" " + this.P)); + } + if (this.Perms) { + bytes.push(...encoder.encode("/Perms "), ...this.Perms.toArray(cryptInfo)); + } + if (this.U) { + bytes.push(...encoder.encode("/U "), ...this.U.toArray(cryptInfo)); + } + if (this.EncryptMetadata) { + bytes.push(...encoder.encode("/EncryptMetadata "), ...encoder.encode(" " + this.EncryptMetadata)); + } + if (this.Recipients) { + if (this.Recipients instanceof HexString) { + bytes.push(...encoder.encode("/Recipients "), ...this.Recipients.toArray(cryptInfo)); + } + else { + bytes.push(...encoder.encode("/Recipients "), ...this.encodeSerializableArray(this.Recipients, cryptInfo)); + } + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + toCryptOptions() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j; + if (!this.V) { + return null; + } + return { + filter: this.Filter, + version: this.V, + revision: this.R, + permissions: this.P, + keyLength: this.Length, + encryptMetadata: this.EncryptMetadata, + stringKeyLength: (_a = this.stringFilter) === null || _a === void 0 ? void 0 : _a.Length, + streamKeyLength: (_b = this.streamFilter) === null || _b === void 0 ? void 0 : _b.Length, + stringMethod: (_c = this.stringFilter) === null || _c === void 0 ? void 0 : _c.CFM, + streamMethod: (_d = this.streamFilter) === null || _d === void 0 ? void 0 : _d.CFM, + oPasswordHash: (_e = this.O) === null || _e === void 0 ? void 0 : _e.bytes, + uPasswordHash: (_f = this.U) === null || _f === void 0 ? void 0 : _f.bytes, + oEncPasswordHash: (_g = this.OE) === null || _g === void 0 ? void 0 : _g.bytes, + uEncPasswordHash: (_h = this.UE) === null || _h === void 0 ? void 0 : _h.bytes, + perms: (_j = this.Perms) === null || _j === void 0 ? void 0 : _j.bytes, + }; + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + var _a, _b; + return __awaiter$L(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/Filter": + case "/SubFilter": + case "/StmF": + case "/StrF": + case "/EFF": + i = yield this.parseNamePropAsync(name, parser, i); + break; + case "/V": + const algorithm = yield parser.parseNumberAtAsync(i, false); + if (algorithm && Object.values(cryptVersions) + .includes(algorithm.value)) { + this.V = algorithm.value; + i = algorithm.end + 1; + } + else { + throw new Error("Can't parse /V property value"); + } + break; + case "/R": + const revision = yield parser.parseNumberAtAsync(i, false); + if (revision && Object.values(cryptRevisions) + .includes(revision.value)) { + this.R = revision.value; + i = revision.end + 1; + } + else { + throw new Error("Can't parse /R property value"); + } + break; + case "/Length": + case "/P": + i = yield this.parseNumberPropAsync(name, parser, i, false); + break; + case "/O": + case "/U": + case "/OE": + case "/UE": + case "/Perms": + i = yield this.parseLiteralPropAsync(name, parser, i, parseInfo.cryptInfo); + break; + case "/EncryptMetadata": + i = yield this.parseBoolPropAsync(name, parser, i); + break; + case "/CF": + const dictBounds = yield parser.getDictBoundsAtAsync(i); + if (bounds) { + const cryptMap = yield CryptMapDict.parseAsync({ parser, bounds: dictBounds }); + if (cryptMap) { + this.CF = cryptMap.value; + i = cryptMap.end + 1; + } + } + else { + throw new Error("Can't parse /CF property value"); + } + break; + case "/Recipients": + const entryType = yield parser.getValueTypeAtAsync(i); + if (entryType === valueTypes.STRING_HEX) { + const recipient = yield HexString.parseAsync(parser, i, parseInfo.cryptInfo); + if (recipient) { + this.Recipients = recipient.value; + i = recipient.end + 1; + break; + } + else { + throw new Error("Can't parse /Recipients property value"); + } + } + else if (entryType === valueTypes.ARRAY) { + const recipients = yield HexString.parseArrayAsync(parser, i); + if (recipients) { + this.Recipients = recipients.value; + i = recipients.end + 1; + break; + } + else { + throw new Error("Can't parse /Recipients property value"); + } + } + throw new Error(`Unsupported /Filter property value type: ${entryType}`); + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + if (!this.Filter) { + throw new Error("Not all required properties parsed"); + } + if (this.Filter === "/Standard" + && (!this.R + || !this.O + || !this.U + || isNaN(this.P) + || (this.V === 5 && (this.R < 5 || !this.OE || !this.UE || !this.Perms)))) { + throw new Error("Not all required properties parsed"); + } + if ((this.SubFilter === "adbe.pkcs7.s3" || this.SubFilter === "adbe.pkcs7.s4") + && !this.Recipients) { + throw new Error("Not all required properties parsed"); + } + if (this.StrF !== "/Identity") { + this.stringFilter = (_a = this.CF) === null || _a === void 0 ? void 0 : _a.getProp(this.StrF); + } + if (this.StmF !== "/Identity") { + this.streamFilter = (_b = this.CF) === null || _b === void 0 ? void 0 : _b.getProp(this.StmF); + } + }); + } +} + +var __awaiter$K = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class TrailerDict extends PdfDict { + constructor() { + super(dictTypes.EMPTY); + } + static parseAsync(parseInfo) { + return __awaiter$K(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new TrailerDict(); + yield pdfObject.parsePropsAsync(parseInfo); + return { value: pdfObject, start: parseInfo.bounds.start, end: parseInfo.bounds.end }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.Size) { + bytes.push(...encoder.encode("/Size "), ...encoder.encode(" " + this.Size)); + } + if (this.Prev) { + bytes.push(...encoder.encode("/Prev "), ...encoder.encode(" " + this.Prev)); + } + if (this.Root) { + bytes.push(...encoder.encode("/Root "), ...this.Root.toArray(cryptInfo)); + } + if (this.Encrypt) { + bytes.push(...encoder.encode("/Encrypt "), ...this.Encrypt.toArray(cryptInfo)); + } + if (this.Info) { + bytes.push(...encoder.encode("/Info "), ...this.Info.toArray(cryptInfo)); + } + if (this.ID) { + bytes.push(...encoder.encode("/ID "), ...this.encodeSerializableArray(this.ID, cryptInfo)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$K(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/Size": + case "/Prev": + i = yield this.parseNumberPropAsync(name, parser, i, false); + break; + case "/Root": + case "/Info": + i = yield this.parseRefPropAsync(name, parser, i); + break; + case "/Encrypt": + const entryType = yield parser.getValueTypeAtAsync(i); + if (entryType === valueTypes.REF) { + const encryptId = yield ObjectId.parseRefAsync(parser, i); + if (encryptId) { + this.Encrypt = encryptId.value; + i = encryptId.end + 1; + break; + } + else { + throw new Error("Can't parse /Encrypt property value"); + } + } + throw new Error(`Unsupported /Encrypt property value type: ${entryType}`); + case "/ID": + const hexIds = yield HexString.parseArrayAsync(parser, i); + if (hexIds && hexIds.value[0] && hexIds.value[1]) { + this.ID = [ + hexIds.value[0], + hexIds.value[1], + ]; + i = hexIds.end + 1; + break; + } + const literalIds = yield LiteralString.parseArrayAsync(parser, i); + if (literalIds && literalIds.value[0] && literalIds.value[1]) { + this.ID = [ + HexString.fromHexBytes(literalIds.value[0].bytes), + HexString.fromHexBytes(literalIds.value[1].bytes), + ]; + i = literalIds.end + 1; + break; + } + throw new Error("Can't parse /ID property value"); + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + if (!this.Root) { + console.log("Trailer 'Root' property is missing. Look like the file is linearized, which is not oficially supported atm!"); + } + if (!this.Size) { + throw new Error("Not all required properties parsed: Size is missing"); + } + if (this.Encrypt && !this.ID) { + throw new Error("Not all required properties parsed: ID is missing while Encryption is used"); + } + }); + } +} + +var __awaiter$J = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class XRefTable extends XRef { + get prev() { + var _a; + return (_a = this._trailerDict) === null || _a === void 0 ? void 0 : _a.Prev; + } + get size() { + var _a; + return (_a = this._trailerDict) === null || _a === void 0 ? void 0 : _a.Size; + } + get root() { + var _a; + return (_a = this._trailerDict) === null || _a === void 0 ? void 0 : _a.Root; + } + get info() { + var _a; + return (_a = this._trailerDict) === null || _a === void 0 ? void 0 : _a.Root; + } + get encrypt() { + var _a; + return (_a = this._trailerDict) === null || _a === void 0 ? void 0 : _a.Encrypt; + } + get id() { + var _a; + return (_a = this._trailerDict) === null || _a === void 0 ? void 0 : _a.ID; + } + constructor(table, trailer, offset) { + super(xRefTypes.TABLE); + this._table = table; + this._trailerDict = trailer; + this._offset = offset; + } + static createFrom(base, entries, offset) { + if (!(entries === null || entries === void 0 ? void 0 : entries.length) || !base) { + return null; + } + const entriesSize = Math.max(...entries.map(x => x.id)) + 1; + const size = Math.max(entriesSize, base.size); + return XRefTable.create(entries, size, offset, base.root, base.offset, base.info, base.encrypt, base.id); + } + static create(entries, size, offset, root, prev, info, encrypt, id) { + if (!(entries === null || entries === void 0 ? void 0 : entries.length) || !size || !offset || !root) { + return null; + } + const trailer = new TrailerDict(); + trailer.Size = size; + trailer.Prev = prev; + trailer.Root = root; + trailer.Info = info; + trailer.Encrypt = encrypt; + trailer.ID = id; + const data = XRefEntry.toTableBytes(entries); + const table = new XRefTable(data, trailer, offset); + return table; + } + static parseAsync(parser, start, offset) { + return __awaiter$J(this, void 0, void 0, function* () { + if (!parser || isNaN(start)) { + return null; + } + const xrefTableBounds = yield parser.getXrefTableBoundsAtAsync(start); + if (!xrefTableBounds) { + return null; + } + const trailerDictBounds = yield parser.getDictBoundsAtAsync(xrefTableBounds.end + 1); + if (!trailerDictBounds) { + return null; + } + const table = yield parser.sliceCharCodesAsync(xrefTableBounds.contentStart, xrefTableBounds.contentEnd); + const trailerDict = yield TrailerDict.parseAsync({ parser, bounds: trailerDictBounds }); + if (!trailerDict) { + return null; + } + const xrefTable = new XRefTable(table, trailerDict.value, offset); + return { + value: xrefTable, + start: null, + end: null, + }; + }); + } + createUpdate(entries, offset) { + return XRefTable.createFrom(this, entries, offset); + } + getEntries() { + if (!this._table.length) { + return []; + } + const entries = XRefEntry.fromTableBytes(this._table); + return entries; + } + toArray(cryptInfo) { + const trailerBytes = this._trailerDict.toArray(cryptInfo); + const bytes = [ + ...keywordCodes.XREF_TABLE, ...keywordCodes.END_OF_LINE, + ...this._table, + ...keywordCodes.TRAILER, ...keywordCodes.END_OF_LINE, + ...trailerBytes, ...keywordCodes.END_OF_LINE, + ]; + return new Uint8Array(bytes); + } +} + +var __awaiter$I = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class XrefParser { + constructor(parser) { + if (!parser) { + throw new Error("Parser is not defined"); + } + this._dataParser = parser; + } + getPdfVersionAsync() { + var _a; + return __awaiter$I(this, void 0, void 0, function* () { + const i = yield this._dataParser.findSubarrayIndexAsync(keywordCodes.VERSION); + if (!i) { + return null; + } + const version = (_a = (yield this._dataParser.parseNumberAtAsync(i.end + 1, true))) === null || _a === void 0 ? void 0 : _a.value; + if (!version) { + return null; + } + return version.toFixed(1); + }); + } + getLastXrefIndexAsync() { + return __awaiter$I(this, void 0, void 0, function* () { + const xrefStartIndex = yield this._dataParser.findSubarrayIndexAsync(keywordCodes.XREF_START, { maxIndex: this._dataParser.maxIndex, direction: false }); + if (!xrefStartIndex) { + return null; + } + const xrefIndex = this._dataParser.parseNumberAtAsync(xrefStartIndex.end + 1); + if (!xrefIndex) { + return null; + } + return xrefIndex; + }); + } + parseXrefAsync(start, max) { + return __awaiter$I(this, void 0, void 0, function* () { + if (!start) { + return null; + } + const offset = start; + const xrefTableIndex = yield this._dataParser.findSubarrayIndexAsync(keywordCodes.XREF_TABLE, { minIndex: start, closedOnly: true }); + if (xrefTableIndex && xrefTableIndex.start === start) { + const xrefStmIndexProp = yield this._dataParser.findSubarrayIndexAsync(keywordCodes.XREF_HYBRID, { minIndex: start, maxIndex: max, closedOnly: true }); + if (xrefStmIndexProp) { + const streamXrefIndex = yield this._dataParser.parseNumberAtAsync(xrefStmIndexProp.end + 1); + if (!streamXrefIndex) { + return null; + } + start = streamXrefIndex.value; + } + else { + const xrefTable = yield XRefTable.parseAsync(this._dataParser, start, offset); + return xrefTable === null || xrefTable === void 0 ? void 0 : xrefTable.value; + } + } + const id = yield ObjectId.parseAsync(this._dataParser, start, false); + if (!id) { + return null; + } + const xrefStreamBounds = yield this._dataParser.getIndirectObjectBoundsAtAsync(id.end + 1); + if (!xrefStreamBounds) { + return null; + } + const xrefStream = yield XRefStream.parseAsync({ parser: this._dataParser, bounds: xrefStreamBounds }, offset); + return xrefStream === null || xrefStream === void 0 ? void 0 : xrefStream.value; + }); + } + parseAllXrefsAsync(start) { + return __awaiter$I(this, void 0, void 0, function* () { + const xrefs = []; + let max = this._dataParser.maxIndex; + let xref; + while (start) { + xref = yield this.parseXrefAsync(start, max); + if (xref) { + xrefs.push(xref); + max = start; + start = xref.prev; + } + else { + break; + } + } + return xrefs; + }); + } +} + +class ReferenceData { + constructor(xrefs) { + var _a; + const allFreeEntries = []; + const allNormalEntries = []; + const allCompressedEntries = []; + let maxId = 0; + xrefs.forEach(x => { + for (const entry of x.getEntries()) { + switch (entry.type) { + case xRefEntryTypes.FREE: + allFreeEntries.push(entry); + break; + case xRefEntryTypes.NORMAL: + allNormalEntries.push(entry); + break; + case xRefEntryTypes.COMPRESSED: + allCompressedEntries.push(entry); + break; + default: + continue; + } + if (entry.id > maxId) { + maxId = entry.id; + } + } + }); + this.size = maxId + 1; + const zeroFreeRef = { + id: 0, + generation: maxGeneration, + nextFreeId: 0, + }; + const freeLinkedList = new LinkedList(zeroFreeRef); + const freeOutsideListMap = new Map(); + const freeMap = new Map(); + let zeroFound = false; + for (const entry of allFreeEntries) { + if (!zeroFound && entry.id === 0) { + zeroFound = true; + zeroFreeRef.nextFreeId = entry.nextFreeId; + continue; + } + const valueFromMap = freeMap.get(entry.id); + if (!valueFromMap || valueFromMap.generation < entry.generation) { + freeMap.set(entry.id, { + id: entry.id, + generation: entry.generation, + nextFreeId: entry.nextFreeId + }); + } + } + let nextId = zeroFreeRef.nextFreeId; + let next; + while (nextId) { + next = freeMap.get(nextId); + freeMap.delete(nextId); + freeLinkedList.push(next); + nextId = next.nextFreeId; + } + [...freeMap].forEach(x => { + const value = x[1]; + if (value.generation === maxGeneration && value.nextFreeId === 0) { + freeOutsideListMap.set(value.id, value); + } + }); + this.freeLinkedList = freeLinkedList; + this.freeOutsideListMap = freeOutsideListMap; + const normalRefs = new Map(); + for (const entry of allNormalEntries) { + if (this.isFreed(entry)) { + continue; + } + const valueFromMap = normalRefs.get(entry.id); + if (valueFromMap && valueFromMap.generation >= entry.generation) { + continue; + } + normalRefs.set(entry.id, { + id: entry.id, + generation: entry.generation, + byteOffset: entry.byteOffset, + }); + } + for (const entry of allCompressedEntries) { + if (this.isFreed(entry)) { + continue; + } + const valueFromMap = normalRefs.get(entry.id); + if (valueFromMap) { + continue; + } + const offset = (_a = normalRefs.get(entry.streamId)) === null || _a === void 0 ? void 0 : _a.byteOffset; + if (offset) { + normalRefs.set(entry.id, { + id: entry.id, + generation: entry.generation, + byteOffset: offset, + compressed: true, + streamId: entry.streamId, + streamIndex: entry.streamIndex, + }); + } + } + this.usedMap = normalRefs; + } + getOffset(id) { + var _a; + return (_a = this.usedMap.get(id)) === null || _a === void 0 ? void 0 : _a.byteOffset; + } + getGeneration(id) { + var _a; + return (_a = this.usedMap.get(id)) === null || _a === void 0 ? void 0 : _a.generation; + } + isFreed(ref) { + return this.freeOutsideListMap.has(ref.id) + || this.freeLinkedList.has(ref, (a, b) => a.id === b.id && a.generation < b.generation); + } + isUsed(id) { + return this.usedMap.has(id); + } +} + +var __awaiter$H = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class CatalogDict extends PdfDict { + constructor() { + super(dictTypes.CATALOG); + } + static parseAsync(parseInfo) { + return __awaiter$H(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new CatalogDict(); + yield pdfObject.parsePropsAsync(parseInfo); + return { value: pdfObject, start: parseInfo.bounds.start, end: parseInfo.bounds.end }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.Version) { + bytes.push(...encoder.encode("/Version "), ...encoder.encode(this.Version)); + } + if (this.Pages) { + bytes.push(...encoder.encode("/Pages "), ...this.Pages.toArray(cryptInfo)); + } + if (this.Lang) { + bytes.push(...encoder.encode("/Lang "), ...this.Lang.toArray(cryptInfo)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$H(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/Version": + i = yield this.parseNamePropAsync(name, parser, i); + break; + case "/Pages": + i = yield this.parseRefPropAsync(name, parser, i); + break; + case "/Lang": + i = yield this.parseLiteralPropAsync(name, parser, i, parseInfo.cryptInfo); + break; + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + if (!this.Pages) { + throw new Error("Not all required properties parsed"); + } + }); + } +} + +var __awaiter$G = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class PageDict extends PdfDict { + constructor() { + super(dictTypes.PAGE); + this.Rotate = 0; + } + static parseAsync(parseInfo) { + return __awaiter$G(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new PageDict(); + yield pdfObject.parsePropsAsync(parseInfo); + return { value: pdfObject, start: parseInfo.bounds.start, end: parseInfo.bounds.end }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.Parent) { + bytes.push(...encoder.encode("/Parent "), ...this.Parent.toArray(cryptInfo)); + } + if (this.LastModified) { + bytes.push(...encoder.encode("/LastModified "), ...this.LastModified.toArray(cryptInfo)); + } + if (this.Resources) { + bytes.push(...encoder.encode("/Resources "), ...this.Resources); + } + if (this.MediaBox) { + bytes.push(...encoder.encode("/MediaBox "), ...this.encodePrimitiveArray(this.MediaBox, encoder)); + } + if (this.CropBox) { + bytes.push(...encoder.encode("/CropBox "), ...this.encodePrimitiveArray(this.CropBox, encoder)); + } + if (this.BleedBox) { + bytes.push(...encoder.encode("/BleedBox "), ...this.encodePrimitiveArray(this.BleedBox, encoder)); + } + if (this.TrimBox) { + bytes.push(...encoder.encode("/TrimBox "), ...this.encodePrimitiveArray(this.TrimBox, encoder)); + } + if (this.ArtBox) { + bytes.push(...encoder.encode("/ArtBox "), ...this.encodePrimitiveArray(this.ArtBox, encoder)); + } + if (this.Contents) { + if (this.Contents instanceof ObjectId) { + bytes.push(...encoder.encode("/Contents "), ...this.Contents.toArray(cryptInfo)); + } + else { + bytes.push(...encoder.encode("/Contents "), ...this.encodeSerializableArray(this.Contents, cryptInfo)); + } + } + if (this.Rotate) { + bytes.push(...encoder.encode("/Rotate "), ...encoder.encode(" " + this.Rotate)); + } + if (this.Thumb) { + bytes.push(...encoder.encode("/Thumb "), ...this.Thumb.toArray(cryptInfo)); + } + if (this.B) { + if (this.B instanceof ObjectId) { + bytes.push(...encoder.encode("/B "), ...this.B.toArray(cryptInfo)); + } + else { + bytes.push(...encoder.encode("/B "), ...this.encodeSerializableArray(this.B, cryptInfo)); + } + } + if (this.Dur) { + bytes.push(...encoder.encode("/Dur "), ...encoder.encode(" " + this.Dur)); + } + if (this.Annots) { + if (this.Annots instanceof ObjectId) { + bytes.push(...encoder.encode("/Annots "), ...this.Annots.toArray(cryptInfo)); + } + else { + bytes.push(...encoder.encode("/Annots "), ...this.encodeSerializableArray(this.Annots, cryptInfo)); + } + } + if (this.Metadata) { + bytes.push(...encoder.encode("/Metadata "), ...this.Metadata.toArray(cryptInfo)); + } + if (this.StructParent) { + bytes.push(...encoder.encode("/StructParent "), ...encoder.encode(" " + this.StructParent)); + } + if (this.ID) { + bytes.push(...encoder.encode("/ID "), ...this.ID.toArray(cryptInfo)); + } + if (this.PZ) { + bytes.push(...encoder.encode("/PZ "), ...encoder.encode(" " + this.PZ)); + } + if (this.Tabs) { + bytes.push(...encoder.encode("/Tabs "), ...encoder.encode(this.Tabs)); + } + if (this.TemplateInstantiated) { + bytes.push(...encoder.encode("/TemplateInstantiated "), ...encoder.encode(this.TemplateInstantiated)); + } + if (this.UserUnit) { + bytes.push(...encoder.encode("/UserUnit "), ...encoder.encode(" " + this.UserUnit)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$G(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/Parent": + case "/Thumb": + case "/Metadata": + i = yield this.parseRefPropAsync(name, parser, i); + break; + case "/LastModified": + i = yield this.parseDatePropAsync(name, parser, i, parseInfo.cryptInfo); + break; + case "/Resources": + const resEntryType = yield parser.getValueTypeAtAsync(i); + if (resEntryType === valueTypes.REF) { + const resDictId = yield ObjectId.parseRefAsync(parser, i); + if (resDictId && parseInfo.parseInfoGetterAsync) { + this.Resources = yield parser.sliceCharCodesAsync(resDictId.start, resDictId.end); + i = resDictId.end + 1; + break; + } + throw new Error("Can't parse /Resources value reference"); + } + else if (resEntryType === valueTypes.DICTIONARY) { + const resDictBounds = yield parser.getDictBoundsAtAsync(i); + if (resDictBounds) { + this.Resources = yield parser.sliceCharCodesAsync(resDictBounds.start, resDictBounds.end); + i = resDictBounds.end + 1; + break; + } + throw new Error("Can't parse /Resources dictionary bounds"); + } + throw new Error(`Unsupported /Resources property value type: ${resEntryType}`); + case "/MediaBox": + case "/CropBox": + case "/BleedBox": + case "/TrimBox": + case "/ArtBox": + i = yield this.parseNumberArrayPropAsync(name, parser, i, true); + break; + case "/Contents": + case "/B": + case "/Annots": + const refEntryType = yield parser.getValueTypeAtAsync(i); + if (refEntryType === valueTypes.REF) { + const refArrayId = yield ObjectId.parseRefAsync(parser, i); + if (refArrayId) { + this[name.slice(1)] = refArrayId.value; + i = refArrayId.end + 1; + break; + } + } + else if (refEntryType === valueTypes.ARRAY) { + const refIds = yield ObjectId.parseRefArrayAsync(parser, i); + if (refIds) { + this[name.slice(1)] = refIds.value; + i = refIds.end + 1; + break; + } + } + throw new Error(`Unsupported ${name} property value type: ${refEntryType}`); + case "/Rotate": + case "/Dur": + case "/StructParent": + case "/PZ": + case "/UserUnit": + i = yield this.parseNumberPropAsync(name, parser, i, false); + break; + case "/ID": + const webCaptureIdEntryType = yield parser.getValueTypeAtAsync(i); + if (webCaptureIdEntryType === valueTypes.REF) { + const webCaptureRefId = yield ObjectId.parseRefAsync(parser, i); + if (webCaptureRefId) { + if (webCaptureRefId && parseInfo.parseInfoGetterAsync) { + const webCaptureIdParseInfo = yield parseInfo.parseInfoGetterAsync(webCaptureRefId.value.id); + if (webCaptureIdParseInfo) { + const webCaptureId = yield HexString.parseAsync(webCaptureIdParseInfo.parser, webCaptureIdParseInfo.bounds.start, webCaptureIdParseInfo.cryptInfo); + if (webCaptureId) { + this.ID = webCaptureId.value; + i = webCaptureRefId.end + 1; + break; + } + } + } + } + throw new Error("Can't parse /ID property value"); + } + else if (webCaptureIdEntryType === valueTypes.STRING_HEX) { + const webCaptureId = yield HexString.parseAsync(parser, i, parseInfo.cryptInfo); + if (webCaptureId) { + this.ID = webCaptureId.value; + i = webCaptureId.end + 1; + break; + } + } + throw new Error(`Unsupported /ID property value type: ${webCaptureIdEntryType}`); + case "/Tabs": + case "/TemplateInstantiated": + i = yield this.parseNamePropAsync(name, parser, i); + break; + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + if (!this.Parent) { + throw new Error("Not all required properties parsed"); + } + }); + } +} + +var __awaiter$F = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class PageTreeDict extends PdfDict { + constructor() { + super(dictTypes.PAGE_TREE); + this.Rotate = 0; + } + static parseAsync(parseInfo) { + return __awaiter$F(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new PageTreeDict(); + yield pdfObject.parsePropsAsync(parseInfo); + return { value: pdfObject, start: parseInfo.bounds.start, end: parseInfo.bounds.end }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.Parent) { + bytes.push(...encoder.encode("/Parent "), ...this.Parent.toArray(cryptInfo)); + } + if (this.Kids) { + bytes.push(...encoder.encode("/Kids "), ...this.encodeSerializableArray(this.Kids, cryptInfo)); + } + if (this.Count) { + bytes.push(...encoder.encode("/Count "), ...encoder.encode(" " + this.Count)); + } + if (this.MediaBox) { + bytes.push(...encoder.encode("/MediaBox "), ...this.encodePrimitiveArray(this.MediaBox, encoder)); + } + if (this.Rotate) { + bytes.push(...encoder.encode("/Rotate "), ...encoder.encode(" " + this.Rotate)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$F(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/Parent": + i = yield this.parseRefPropAsync(name, parser, i); + break; + case "/Kids": + i = yield this.parseRefArrayPropAsync(name, parser, i); + break; + case "/Count": + case "/Rotate": + i = yield this.parseNumberPropAsync(name, parser, i, false); + break; + case "/MediaBox": + i = yield this.parseNumberArrayPropAsync(name, parser, i, true); + break; + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + if (!this.Kids || isNaN(this.Count)) { + throw new Error("Not all required properties parsed"); + } + }); + } +} + +const standardStampColors = { + redColor: [0.804, 0, 0], + greenColor: [0, 0.804, 0], + blueColor: [0, 0, 0.804], +}; +const standardStampBBox = [0, 0, 440, 120]; +const standardStampRect = [0, 0, 220, 60]; +const standardStampForms = { + DRAFT: `33.5 13.4 m + 404.5 6.92 l + 419.6 6.657 431.9 18.52 432.1 33.62 c + 432.89 78.92 l + 433.153 94.02 421.29 106.32 406.19 106.52 c + 35.19 113 l + 20.09 113.263 7.79 101.4 7.59 86.3 c + 6.8 41 l + 6.537 25.9 18.4 13.6 33.5 13.4 c + s + 150 61 m + 150.047 65.947 149.114 70.413 147.2 74.4 c + 145.287 78.333 142.853 81.373 139.9 83.52 c + 137.68 85.127 135.24 86.263 132.58 86.93 c + 129.92 87.593 126.763 87.957 123.11 88.02 c + 106.91 88.29 l + 106.401 35.19 l + 123.001 34.912 l + 126.734 34.85 129.961 35.165 132.681 35.857 c + 135.394 36.524 137.681 37.507 139.541 38.807 c + 142.721 40.994 145.234 43.974 147.081 47.747 c + 148.941 51.5 149.898 55.934 149.951 61.047 c + h + 137.8 61.097 m + 137.767 57.597 137.183 54.621 136.05 52.167 c + 134.937 49.687 133.183 47.764 130.79 46.397 c + 129.57 45.731 128.323 45.287 127.05 45.067 c + 125.797 44.827 123.897 44.728 121.35 44.77 c + 118.36 44.82 l + 118.678 78.12 l + 121.668 78.07 l + 124.481 78.023 126.541 77.846 127.848 77.538 c + 129.161 77.207 130.438 76.637 131.678 75.828 c + 133.818 74.362 135.381 72.432 136.368 70.038 c + 137.348 67.618 137.821 64.648 137.788 61.128 c + f + 185 50 m + 184.987 48.667 184.74 47.53 184.259 46.59 c + 183.778 45.643 182.961 44.907 181.809 44.38 c + 181.002 44.013 180.066 43.802 178.999 43.749 c + 177.932 43.672 176.689 43.645 175.269 43.669 c + 170.989 43.74 l + 171.126 58.04 l + 174.756 57.979 l + 176.643 57.948 178.223 57.814 179.496 57.579 c + 180.769 57.344 181.833 56.837 182.686 56.059 c + 183.499 55.306 184.086 54.486 184.446 53.599 c + 184.827 52.686 185.011 51.483 184.996 49.989 c + h + 203.8 86.6 m + 189.4 86.841 l + 176.7 67.541 l + 171.25 67.632 l + 171.437 87.132 l + 159.637 87.329 l + 159.128 34.229 l + 178.928 33.897 l + 181.635 33.852 183.965 33.991 185.918 34.315 c + 187.871 34.639 189.705 35.382 191.418 36.545 c + 193.151 37.705 194.531 39.228 195.558 41.115 c + 196.605 42.975 197.141 45.335 197.168 48.195 c + 197.206 52.122 196.446 55.335 194.888 57.835 c + 193.355 60.335 191.138 62.432 188.238 64.125 c + f + 251 85.8 m + 238.8 86.004 l + 235.53 75.304 l + 218.53 75.588 l + 215.46 86.388 l + 203.56 86.587 l + 219.96 33.187 l + 233.56 32.959 l + h + 232.6 65.6 m + 226.78 46.6 l + 221.33 65.8 l + f + 290 42.3 m + 268.9 42.653 l + 268.995 52.543 l + 288.495 52.216 l + 288.593 62.516 l + 269.093 62.843 l + 269.31 85.543 l + 257.51 85.74 l + 257.001 32.64 l + 289.801 32.091 l + f + 334 41.5 m + 319.7 41.739 l + 320.11 84.639 l + 308.31 84.837 l + 307.9 41.937 l + 293.6 42.176 l + 293.502 31.876 l + 333.902 31.199 l + f + `, + APPROVED: `33.5 13.4 m + 404.5 6.92 l + 419.6 6.657 431.9 18.52 432.1 33.62 c + 432.89 78.92 l + 433.153 94.02 421.29 106.32 406.19 106.52 c + 35.19 113 l + 20.09 113.263 7.79 101.4 7.59 86.3 c + 6.8 41 l + 6.537 25.9 18.4 13.6 33.5 13.4 c + s + 88.9 86.4 m + 78 86.585 l + 75.08 76.895 l + 59.88 77.153 l + 57.14 86.933 l + 46.54 87.114 l + 61.24 38.714 l + 73.34 38.508 l + h + 72.4 68.1 m + 67.21 50.9 l + 62.35 68.3 l + f + 128 52.8 m + 128.02 54.953 127.72 57.073 127.098 59.16 c + 126.477 61.22 125.577 62.96 124.398 64.38 c + 122.785 66.307 120.975 67.77 118.968 68.77 c + 116.981 69.777 114.495 70.303 111.508 70.35 c + 104.938 70.462 l + 105.086 86.162 l + 94.586 86.341 l + 94.132 38.141 l + 111.532 37.846 l + 114.132 37.802 116.322 38.034 118.102 38.543 c + 119.902 39.03 121.492 39.79 122.872 40.823 c + 124.532 42.07 125.802 43.676 126.682 45.643 c + 127.582 47.61 128.045 49.986 128.072 52.773 c + h + 117.1 53.276 m + 117.087 51.916 116.765 50.756 116.133 49.796 c + 115.501 48.816 114.771 48.139 113.943 47.766 c + 112.836 47.267 111.763 47.005 110.723 46.98 c + 109.676 46.933 108.283 46.924 106.543 46.954 c + 104.733 46.985 l + 104.869 61.385 l + 107.889 61.333 l + 109.682 61.303 111.156 61.149 112.309 60.87 c + 113.476 60.592 114.449 60.058 115.229 59.27 c + 115.902 58.57 116.379 57.744 116.659 56.79 c + 116.961 55.817 117.106 54.64 117.093 53.26 c + f + 170 52.1 m + 170.02 54.253 169.72 56.373 169.098 58.46 c + 168.477 60.52 167.577 62.26 166.398 63.68 c + 164.785 65.607 162.975 67.07 160.968 68.07 c + 158.981 69.077 156.495 69.603 153.508 69.65 c + 146.938 69.762 l + 147.086 85.462 l + 136.586 85.641 l + 136.132 37.441 l + 153.532 37.146 l + 156.132 37.102 158.322 37.334 160.102 37.843 c + 161.902 38.33 163.492 39.09 164.872 40.123 c + 166.532 41.37 167.802 42.976 168.682 44.943 c + 169.582 46.91 170.045 49.286 170.072 52.073 c + h + 159.1 52.576 m + 159.087 51.216 158.765 50.056 158.133 49.096 c + 157.501 48.116 156.771 47.439 155.943 47.066 c + 154.836 46.567 153.763 46.305 152.723 46.28 c + 151.676 46.233 150.283 46.224 148.543 46.254 c + 146.733 46.285 l + 146.869 60.685 l + 149.889 60.633 l + 151.682 60.603 153.156 60.449 154.309 60.17 c + 155.476 59.892 156.449 59.358 157.229 58.57 c + 157.902 57.87 158.379 57.044 158.659 56.09 c + 158.961 55.117 159.106 53.94 159.093 52.56 c + f + 200 51.1 m + 199.989 49.893 199.768 48.863 199.339 48.01 c + 198.91 47.157 198.18 46.49 197.149 46.01 c + 196.429 45.677 195.592 45.487 194.639 45.438 c + 193.686 45.368 192.576 45.344 191.309 45.365 c + 187.489 45.43 l + 187.611 58.43 l + 190.851 58.375 l + 192.538 58.346 193.948 58.225 195.081 58.012 c + 196.214 57.799 197.161 57.342 197.921 56.642 c + 198.648 55.962 199.171 55.219 199.491 54.412 c + 199.831 53.585 199.995 52.492 199.982 51.132 c + h + 216.8 84.2 m + 203.9 84.419 l + 192.6 66.919 l + 187.74 67.002 l + 187.906 84.702 l + 177.406 84.88 l + 176.952 36.68 l + 194.652 36.379 l + 197.072 36.338 199.152 36.464 200.892 36.758 c + 202.632 37.052 204.269 37.725 205.802 38.778 c + 207.349 39.831 208.579 41.211 209.492 42.918 c + 210.425 44.604 210.902 46.741 210.922 49.328 c + 210.956 52.888 210.279 55.801 208.892 58.068 c + 207.519 60.334 205.539 62.234 202.952 63.768 c + f + 261 59.4 m + 261.073 67.067 259.263 73.2 255.57 77.8 c + 251.877 82.373 246.743 84.713 240.17 84.82 c + 233.597 84.932 228.43 82.765 224.67 78.32 c + 220.89 73.853 218.963 67.787 218.89 60.12 c + 218.817 52.387 220.627 46.253 224.32 41.72 c + 228.013 37.147 233.147 34.807 239.72 34.7 c + 246.273 34.589 251.44 36.755 255.22 41.2 c + 259.013 45.62 260.947 51.687 261.02 59.4 c + h + 247.1 71.8 m + 248.113 70.313 248.857 68.577 249.33 66.59 c + 249.805 64.577 250.03 62.223 250.005 59.53 c + 249.978 56.643 249.671 54.19 249.084 52.17 c + 248.497 50.15 247.741 48.523 246.814 47.29 c + 245.867 46.01 244.777 45.09 243.544 44.53 c + 242.331 43.968 241.064 43.698 239.744 43.721 c + 238.404 43.744 237.144 44.045 235.964 44.626 c + 234.797 45.207 233.724 46.153 232.744 47.466 c + 231.837 48.686 231.101 50.369 230.534 52.516 c + 229.986 54.636 229.725 57.099 229.752 59.906 c + 229.779 62.773 230.077 65.216 230.645 67.236 c + 231.232 69.229 231.988 70.856 232.915 72.116 c + 233.842 73.376 234.922 74.296 236.155 74.876 c + 237.388 75.459 238.682 75.739 240.035 75.716 c + 241.388 75.693 242.675 75.369 243.895 74.745 c + 245.115 74.099 246.178 73.122 247.085 71.815 c + f + 306 34.6 m + 291.5 83 l + 279.7 83.201 l + 264.3 35.301 l + 275.4 35.113 l + 285.6 68.813 l + 295.17 34.813 l + f + 342 82.1 m + 312.4 82.603 l + 311.946 34.403 l + 341.546 33.9 l + 341.634 43.22 l + 322.534 43.544 l + 322.612 51.854 l + 340.312 51.553 l + 340.4 60.873 l + 322.7 61.174 l + 322.812 73.074 l + 341.912 72.75 l + f + 389 57.3 m + 389.042 61.787 388.209 65.82 386.5 69.4 c + 384.793 72.967 382.62 75.72 379.98 77.66 c + 378 79.12 375.82 80.15 373.44 80.75 c + 371.067 81.351 368.25 81.68 364.99 81.735 c + 350.59 81.98 l + 350.136 33.78 l + 364.936 33.528 l + 368.269 33.471 371.146 33.757 373.566 34.384 c + 375.993 34.99 378.033 35.883 379.686 37.064 c + 382.526 39.044 384.769 41.744 386.416 45.164 c + 388.076 48.564 388.929 52.597 388.976 57.264 c + h + 378.1 57.388 m + 378.07 54.222 377.55 51.525 376.54 49.298 c + 375.547 47.052 373.983 45.308 371.85 44.068 c + 370.763 43.461 369.65 43.058 368.51 42.858 c + 367.39 42.64 365.693 42.551 363.42 42.589 c + 360.76 42.634 l + 361.044 72.734 l + 363.704 72.689 l + 366.211 72.647 368.051 72.486 369.224 72.207 c + 370.391 71.907 371.531 71.391 372.644 70.657 c + 374.557 69.331 375.951 67.581 376.824 65.407 c + 377.704 63.214 378.127 60.521 378.094 57.327 c + f + `, + NOT_APPROVED: `33.5 13.4 m + 404.5 6.92 l + 419.6 6.657 431.9 18.52 432.1 33.62 c + 432.89 78.92 l + 433.153 94.02 421.29 106.32 406.19 106.52 c + 35.19 113 l + 20.09 113.263 7.79 101.4 7.59 86.3 c + 6.8 41 l + 6.537 25.9 18.4 13.6 33.5 13.4 c + s + 57.1 85.5 m + 49.12 85.636 l + 35.32 55.036 l + 35.469 85.936 l + 27.879 86.066 l + 27.662 41.066 l + 37.562 40.897 l + 49.362 66.497 l + 49.238 40.697 l + 56.828 40.567 l + f + 96.4 62.4 m + 96.435 69.533 94.995 75.267 92.08 79.6 c + 89.167 83.86 85.133 86.033 79.98 86.12 c + 74.82 86.208 70.753 84.175 67.78 80.02 c + 64.827 75.84 63.333 70.173 63.3 63.02 c + 63.265 55.82 64.705 50.087 67.62 45.82 c + 70.533 41.56 74.567 39.387 79.72 39.3 c + 84.867 39.212 88.933 41.245 91.92 45.4 c + 94.887 49.533 96.387 55.2 96.42 62.4 c + h + 85.5 74 m + 86.3 72.62 86.89 71 87.27 69.14 c + 87.649 67.26 87.833 65.063 87.82 62.55 c + 87.807 59.85 87.573 57.56 87.118 55.68 c + 86.663 53.793 86.073 52.273 85.348 51.12 c + 84.608 49.927 83.755 49.067 82.788 48.54 c + 81.835 48.013 80.841 47.758 79.808 47.776 c + 78.761 47.794 77.771 48.073 76.838 48.612 c + 75.918 49.151 75.075 50.031 74.308 51.252 c + 73.595 52.392 73.011 53.962 72.558 55.962 c + 72.122 57.942 71.91 60.242 71.923 62.862 c + 71.936 65.542 72.163 67.822 72.603 69.702 c + 73.058 71.569 73.648 73.089 74.373 74.262 c + 75.1 75.435 75.946 76.295 76.913 76.842 c + 77.88 77.389 78.893 77.654 79.953 77.635 c + 81.02 77.617 82.033 77.318 82.993 76.738 c + 83.953 76.138 84.79 75.228 85.503 74.008 c + f + 128 48 m + 118 48.172 l + 118.175 84.472 l + 109.895 84.614 l + 109.72 48.314 l + 99.72 48.486 l + 99.678 39.786 l + 127.978 39.301 l + f + 178 83.4 m + 169.44 83.546 l + 167.18 74.496 l + 155.28 74.7 l + 153.1 83.83 l + 144.76 83.973 l + 156.36 38.773 l + 165.89 38.61 l + h + 165.1 66.3 m + 161.08 50.2 l + 157.21 66.4 l + f + 209 52.1 m + 209.01 54.113 208.768 56.09 208.274 58.03 c + 207.78 59.95 207.07 61.573 206.144 62.9 c + 204.871 64.693 203.447 66.057 201.874 66.99 c + 200.314 67.923 198.361 68.41 196.014 68.45 c + 190.864 68.538 l + 190.935 83.138 l + 182.655 83.28 l + 182.438 38.28 l + 196.038 38.047 l + 198.078 38.012 199.798 38.235 201.198 38.714 c + 202.611 39.173 203.858 39.886 204.938 40.854 c + 206.238 42.021 207.231 43.524 207.918 45.364 c + 208.618 47.204 208.974 49.421 208.988 52.014 c + h + 200.44 52.518 m + 200.434 51.251 200.184 50.168 199.691 49.268 c + 199.198 48.348 198.628 47.715 197.981 47.368 c + 197.114 46.9 196.271 46.653 195.451 46.626 c + 194.631 46.58 193.538 46.568 192.171 46.592 c + 190.751 46.616 l + 190.816 60.116 l + 193.186 60.075 l + 194.593 60.051 195.749 59.911 196.656 59.653 c + 197.576 59.396 198.343 58.899 198.956 58.163 c + 199.485 57.51 199.861 56.74 200.086 55.853 c + 200.326 54.947 200.443 53.847 200.437 52.553 c + f + 241 51.6 m + 241.01 53.613 240.768 55.59 240.274 57.53 c + 239.78 59.45 239.07 61.073 238.144 62.4 c + 236.871 64.193 235.447 65.557 233.874 66.49 c + 232.314 67.423 230.361 67.91 228.014 67.95 c + 222.864 68.038 l + 222.935 82.638 l + 214.655 82.78 l + 214.438 37.78 l + 228.038 37.547 l + 230.078 37.512 231.798 37.735 233.198 38.214 c + 234.611 38.673 235.858 39.386 236.938 40.354 c + 238.238 41.521 239.231 43.024 239.918 44.864 c + 240.618 46.704 240.974 48.921 240.988 51.514 c + h + 232.44 52.018 m + 232.434 50.751 232.184 49.668 231.691 48.768 c + 231.198 47.848 230.628 47.215 229.981 46.868 c + 229.114 46.4 228.271 46.153 227.451 46.126 c + 226.631 46.08 225.538 46.068 224.171 46.092 c + 222.751 46.116 l + 222.816 59.616 l + 225.186 59.575 l + 226.593 59.551 227.749 59.411 228.656 59.153 c + 229.576 58.896 230.343 58.399 230.956 57.663 c + 231.485 57.01 231.861 56.24 232.086 55.353 c + 232.326 54.447 232.443 53.347 232.437 52.053 c + f + 265 50.7 m + 264.995 49.573 264.825 48.61 264.49 47.81 c + 264.155 47.01 263.585 46.387 262.78 45.94 c + 262.218 45.627 261.565 45.447 260.82 45.4 c + 260.073 45.332 259.203 45.307 258.21 45.324 c + 255.21 45.375 l + 255.269 57.475 l + 257.809 57.432 l + 259.129 57.409 260.235 57.299 261.129 57.103 c + 262.022 56.906 262.769 56.479 263.369 55.823 c + 263.941 55.189 264.354 54.499 264.609 53.753 c + 264.878 52.986 265.01 51.966 265.004 50.693 c + h + 278.1 81.7 m + 268 81.873 l + 259.17 65.573 l + 255.35 65.638 l + 255.43 82.138 l + 247.19 82.279 l + 246.973 37.279 l + 260.873 37.041 l + 262.773 37.009 264.406 37.132 265.773 37.41 c + 267.139 37.689 268.423 38.322 269.623 39.31 c + 270.836 40.297 271.799 41.59 272.513 43.19 c + 273.239 44.77 273.609 46.767 273.623 49.18 c + 273.639 52.5 273.099 55.217 272.003 57.33 c + 270.923 59.444 269.366 61.21 267.333 62.63 c + f + 313 58.7 m + 313.035 65.833 311.595 71.567 308.68 75.9 c + 305.767 80.16 301.733 82.333 296.58 82.42 c + 291.42 82.508 287.353 80.475 284.38 76.32 c + 281.427 72.14 279.933 66.473 279.9 59.32 c + 279.865 52.12 281.305 46.387 284.22 42.12 c + 287.133 37.86 291.167 35.687 296.32 35.6 c + 301.467 35.512 305.533 37.545 308.52 41.7 c + 311.487 45.833 312.987 51.5 313.02 58.7 c + h + 302.1 70.3 m + 302.9 68.92 303.49 67.3 303.87 65.44 c + 304.249 63.56 304.433 61.363 304.42 58.85 c + 304.407 56.15 304.173 53.86 303.718 51.98 c + 303.263 50.093 302.673 48.573 301.948 47.42 c + 301.208 46.227 300.355 45.367 299.388 44.84 c + 298.435 44.313 297.441 44.058 296.408 44.076 c + 295.361 44.094 294.371 44.373 293.438 44.912 c + 292.518 45.451 291.675 46.331 290.908 47.552 c + 290.195 48.692 289.611 50.262 289.158 52.262 c + 288.722 54.242 288.51 56.542 288.523 59.162 c + 288.536 61.842 288.763 64.122 289.203 66.002 c + 289.658 67.869 290.248 69.389 290.973 70.562 c + 291.7 71.735 292.546 72.595 293.513 73.142 c + 297.62 73.917 298.633 73.618 299.593 73.038 c + 300.553 72.438 301.39 71.528 302.103 70.308 c + f + 348 35.6 m + 336.5 80.8 l + 327.23 80.959 l + 315.33 36.159 l + 324.02 36.01 l + 331.93 67.41 l + 339.54 35.71 l + f + 376 80 m + 352.8 80.397 l + 352.583 35.397 l + 375.783 35 l + 375.825 43.7 l + 360.825 43.956 l + 360.863 51.716 l + 374.762 51.478 l + 374.804 60.178 l + 360.904 60.416 l + 360.958 71.516 l + 375.958 71.26 l + f + 413 57 m + 413.02 61.187 412.357 64.953 411.01 68.3 c + 409.663 71.627 407.95 74.193 405.87 76 c + 404.31 77.353 402.597 78.31 400.73 78.87 c + 398.863 79.425 396.65 79.725 394.09 79.769 c + 382.79 79.963 l + 382.573 34.963 l + 394.173 34.764 l + 396.786 34.719 399.043 34.993 400.943 35.584 c + 402.843 36.155 404.443 36.992 405.743 38.094 c + 407.963 39.947 409.713 42.474 410.993 45.674 c + 412.286 48.854 412.943 52.621 412.963 56.974 c + h + 404.44 57.056 m + 404.426 54.096 404.026 51.576 403.24 49.496 c + 402.467 47.396 401.243 45.766 399.57 44.606 c + 398.717 44.037 397.847 43.66 396.96 43.476 c + 396.08 43.269 394.75 43.181 392.97 43.212 c + 390.88 43.248 l + 391.016 71.348 l + 393.106 71.312 l + 395.073 71.278 396.516 71.133 397.436 70.876 c + 398.356 70.599 399.253 70.122 400.126 69.446 c + 401.626 68.213 402.726 66.583 403.426 64.556 c + 404.119 62.509 404.459 59.996 404.446 57.016 c + f + `, + DEPARTMENTAL: `33.5 13.4 m + 404.5 6.92 l + 419.6 6.657 431.9 18.52 432.1 33.62 c + 432.89 78.92 l + 433.153 94.02 421.29 106.32 406.19 106.52 c + 35.19 113 l + 20.09 113.263 7.79 101.4 7.59 86.3 c + 6.8 41 l + 6.537 25.9 18.4 13.6 33.5 13.4 c + s + 56.4 63.1 m + 56.412 67.46 55.746 71.393 54.4 74.9 c + 53.06 78.36 51.36 81.03 49.3 82.91 c + 47.753 84.317 46.053 85.31 44.2 85.89 c + 26.42 86.996 l + 26.286 40.196 l + 37.786 40.009 l + 40.379 39.967 42.616 40.256 44.496 40.875 c + 46.376 41.474 47.959 42.35 49.246 43.505 c + 51.446 45.438 53.176 48.072 54.436 51.405 c + 55.709 54.718 56.353 58.652 56.366 63.205 c + h + 47.92 63.143 m + 47.911 60.063 47.518 57.437 46.74 55.263 c + 45.98 53.077 44.773 51.377 43.12 50.163 c + 42.28 49.569 41.417 49.175 40.53 48.983 c + 39.663 48.767 38.347 48.673 36.58 48.701 c + 34.51 48.735 l + 34.594 78.035 l + 36.664 78.001 l + 38.617 77.97 40.047 77.821 40.954 77.554 c + 41.867 77.267 42.757 76.77 43.624 76.064 c + 45.117 74.784 46.207 73.088 46.894 70.974 c + 47.587 68.848 47.927 66.231 47.914 63.124 c + f + 85.8 86 m + 62.8 86.373 l + 62.666 39.573 l + 85.666 39.2 l + 85.692 48.26 l + 70.892 48.501 l + 70.915 56.581 l + 84.715 56.357 l + 84.741 65.417 l + 70.941 65.641 l + 70.974 77.241 l + 85.774 77 l + f + 119 53.4 m + 119.006 55.493 118.763 57.553 118.27 59.58 c + 117.777 61.58 117.071 63.27 116.15 64.65 c + 114.89 66.517 113.477 67.933 111.91 68.9 c + 110.363 69.867 108.43 70.37 106.11 70.41 c + 101.01 70.493 l + 101.054 85.793 l + 92.854 85.926 l + 92.72 39.126 l + 106.22 38.907 l + 108.24 38.874 109.943 39.108 111.33 39.61 c + 112.723 40.091 113.956 40.837 115.03 41.85 c + 116.316 43.063 117.296 44.63 117.97 46.55 c + 118.656 48.47 119.003 50.78 119.01 53.48 c + h + 110.52 53.821 m + 110.516 52.501 110.271 51.374 109.784 50.441 c + 109.297 49.488 108.734 48.824 108.094 48.451 c + 107.241 47.962 106.407 47.703 105.594 47.674 c + 104.781 47.624 103.697 47.61 102.344 47.632 c + 100.934 47.655 l + 100.974 61.655 l + 103.324 61.617 l + 104.717 61.595 105.864 61.45 106.764 61.184 c + 107.677 60.918 108.437 60.401 109.044 59.634 c + 109.569 58.954 109.945 58.151 110.174 57.224 c + 110.413 56.278 110.531 55.134 110.527 53.794 c + f + 154 84.9 m + 145.52 85.038 l + 143.29 75.608 l + 131.49 75.799 l + 129.32 85.299 l + 121.06 85.433 l + 132.66 38.433 l + 142.1 38.28 l + h + 141.3 67.1 m + 137.34 50.4 l + 133.48 67.3 l + f + 176 52 m + 175.997 50.827 175.83 49.823 175.5 48.99 c + 175.17 48.157 174.607 47.507 173.81 47.04 c + 173.254 46.713 172.604 46.525 171.86 46.474 c + 171.12 46.402 170.26 46.374 169.28 46.39 c + 166.31 46.438 l + 166.346 59.038 l + 168.866 58.998 l + 170.173 58.976 171.269 58.864 172.156 58.662 c + 173.036 58.458 173.776 58.015 174.376 57.332 c + 174.943 56.672 175.353 55.952 175.606 55.172 c + 175.874 54.372 176.006 53.312 176.003 51.992 c + h + 188.9 84.3 m + 178.9 84.463 l + 170.18 67.463 l + 166.4 67.524 l + 166.449 84.724 l + 158.289 84.856 l + 158.155 38.056 l + 171.955 37.833 l + 173.835 37.803 175.452 37.934 176.805 38.226 c + 178.158 38.519 179.428 39.179 180.615 40.206 c + 181.815 41.233 182.765 42.58 183.465 44.246 c + 184.178 45.893 184.542 47.973 184.555 50.486 c + 184.565 53.946 184.025 56.776 182.935 58.976 c + 181.862 61.176 180.315 63.016 178.295 64.496 c + f + 218 46.1 m + 208.07 46.261 l + 208.178 84.061 l + 199.978 84.194 l + 199.87 46.394 l + 189.94 46.555 l + 189.914 37.495 l + 218.014 37.039 l + f + 256 83.2 m + 247.84 83.332 l + 247.75 51.932 l + 241.91 72.332 l + 236.25 72.424 l + 230.3 52.124 l + 230.39 83.524 l + 222.66 83.65 l + 222.526 36.85 l + 232.046 36.695 l + 239.266 60.095 l + 246.336 36.495 l + 255.856 36.34 l + f + 287 82.7 m + 264 83.073 l + 263.866 36.273 l + 286.866 35.9 l + 286.892 44.96 l + 272.092 45.201 l + 272.115 53.281 l + 285.915 53.057 l + 285.941 62.117 l + 272.141 62.341 l + 272.174 73.941 l + 286.974 73.7 l + f + 323 82.2 m + 315.1 82.328 l + 301.5 50.428 l + 301.592 82.528 l + 294.072 82.65 l + 293.938 35.85 l + 303.738 35.691 l + 315.438 62.291 l + 315.361 35.491 l + 322.881 35.369 l + f + 356 43.9 m + 346.07 44.061 l + 346.178 81.861 l + 337.978 81.994 l + 337.87 44.194 l + 327.94 44.355 l + 327.914 35.295 l + 356.014 34.839 l + f + 390 81.1 m + 381.52 81.238 l + 379.29 71.808 l + 367.49 71.999 l + 365.32 81.499 l + 357.06 81.633 l + 368.66 34.633 l + 378.1 34.48 l + h + 377.3 63.3 m + 373.34 46.6 l + 369.48 63.5 l + f + 418 80.6 m + 395.1 80.972 l + 394.966 34.172 l + 403.166 34.039 l + 403.274 71.839 l + 417.974 71.6 l + f + `, + CONFIDENTIAL: `33.5 13.4 m + 404.5 6.92 l + 419.6 6.657 431.9 18.52 432.1 33.62 c + 432.89 78.92 l + 433.153 94.02 421.29 106.32 406.19 106.52 c + 35.19 113 l + 20.09 113.263 7.79 101.4 7.59 86.3 c + 6.8 41 l + 6.537 25.9 18.4 13.6 33.5 13.4 c + s + 48 86.5 m + 45.613 86.541 43.403 86.084 41.37 85.13 c + 39.35 84.177 37.61 82.737 36.15 80.81 c + 34.69 78.883 33.55 76.467 32.73 73.56 c + 31.923 70.653 31.513 67.287 31.5 63.46 c + 31.483 59.9 31.849 56.663 32.6 53.75 c + 33.347 50.837 34.44 48.333 35.88 46.24 c + 37.267 44.227 38.983 42.657 41.03 41.53 c + 43.097 40.41 45.35 39.827 47.79 39.78 c + 49.143 39.757 50.36 39.847 51.44 40.05 c + 52.533 40.233 53.54 40.487 54.46 40.814 c + 55.427 41.18 56.297 41.597 57.07 42.064 c + 57.863 42.513 58.557 42.933 59.15 43.324 c + 59.203 54.224 l + 58.254 54.24 l + 57.849 53.764 57.336 53.201 56.714 52.55 c + 56.107 51.896 55.414 51.253 54.634 50.62 c + 53.84 49.99 52.984 49.46 52.064 49.03 c + 51.144 48.603 50.157 48.398 49.104 48.416 c + 47.937 48.436 46.83 48.717 45.784 49.258 c + 44.737 49.78 43.77 50.643 42.884 51.848 c + 42.044 53.008 41.36 54.538 40.834 56.438 c + 40.326 58.338 40.078 60.638 40.091 63.338 c + 40.104 66.158 40.396 68.508 40.966 70.388 c + 41.55 72.268 42.276 73.745 43.146 74.818 c + 44.026 75.912 45.006 76.692 46.086 77.158 c + 47.166 77.603 48.229 77.816 49.276 77.798 c + 50.282 77.781 51.272 77.553 52.246 77.113 c + 53.232 76.674 54.142 76.084 54.976 75.343 c + 55.676 74.747 56.326 74.111 56.926 73.433 c + 57.526 72.76 58.02 72.177 58.406 71.683 c + 59.268 71.668 l + 59.32 82.368 l + 58.52 82.885 57.753 83.372 57.02 83.828 c + 56.286 84.284 55.52 84.68 54.72 85.018 c + 53.673 85.459 52.69 85.799 51.77 86.038 c + f + 96.6 62.3 m + 96.635 69.433 95.195 75.167 92.28 79.5 c + 89.367 83.76 85.333 85.933 80.18 86.02 c + 75.02 86.108 70.953 84.075 67.98 79.92 c + 65.027 75.74 63.533 70.073 63.5 62.92 c + 63.465 55.72 64.905 49.987 67.82 45.72 c + 70.733 41.46 74.767 39.287 79.92 39.2 c + 85.067 39.112 89.133 41.145 92.12 45.3 c + 95.087 49.433 96.587 55.1 96.62 62.3 c + h + 85.7 73.9 m + 86.5 72.52 87.09 70.9 87.47 69.04 c + 87.849 67.16 88.033 64.963 88.02 62.45 c + 88.007 59.75 87.773 57.46 87.318 55.58 c + 86.863 53.693 86.273 52.173 85.548 51.02 c + 84.808 49.827 83.955 48.967 82.988 48.44 c + 82.035 47.913 81.041 47.658 80.008 47.676 c + 78.961 47.694 77.971 47.973 77.038 48.512 c + 76.118 49.051 75.275 49.931 74.508 51.152 c + 73.795 52.292 73.211 53.862 72.758 55.862 c + 72.322 57.842 72.11 60.142 72.123 62.762 c + 72.136 65.442 72.363 67.722 72.803 69.602 c + 73.258 71.469 73.848 72.989 74.573 74.162 c + 75.3 75.335 76.146 76.195 77.113 76.742 c + 78.08 77.289 79.093 77.554 80.153 77.535 c + 81.22 77.517 82.233 77.218 83.193 76.638 c + 84.153 76.038 84.99 75.128 85.703 73.908 c + f + 132 84.2 m + 124.02 84.336 l + 110.22 53.736 l + 110.369 84.636 l + 102.779 84.766 l + 102.562 39.766 l + 112.462 39.597 l + 124.262 65.197 l + 124.138 39.397 l + 131.728 39.267 l + f + 163 47.4 m + 148.2 47.653 l + 148.24 56.013 l + 161.94 55.779 l + 161.982 64.479 l + 148.282 64.713 l + 148.375 83.913 l + 140.135 84.054 l + 139.918 39.054 l + 162.918 38.66 l + f + 186 83.3 m + 167.2 83.622 l + 167.161 75.652 l + 172.421 75.562 l + 172.281 46.562 l + 167.022 46.652 l + 166.983 38.682 l + 185.783 38.36 l + 185.822 46.33 l + 180.562 46.42 l + 180.702 75.42 l + 185.962 75.33 l + f + 223 60.2 m + 223.02 64.387 222.357 68.153 221.01 71.5 c + 219.663 74.827 217.95 77.393 215.87 79.2 c + 214.31 80.553 212.597 81.51 210.73 82.07 c + 208.863 82.625 206.65 82.925 204.09 82.969 c + 192.79 83.163 l + 192.573 38.163 l + 204.173 37.964 l + 206.786 37.919 209.043 38.193 210.943 38.784 c + 212.843 39.355 214.443 40.192 215.743 41.294 c + 217.963 43.147 219.713 45.674 220.993 48.874 c + 222.286 52.054 222.943 55.821 222.963 60.174 c + h + 214.44 60.256 m + 214.426 57.296 214.026 54.776 213.24 52.696 c + 212.467 50.596 211.243 48.966 209.57 47.806 c + 208.717 47.237 207.847 46.86 206.96 46.676 c + 206.08 46.469 204.75 46.381 202.97 46.412 c + 200.88 46.448 l + 201.016 74.548 l + 203.106 74.512 l + 205.073 74.478 206.516 74.333 207.436 74.076 c + 208.356 73.799 209.253 73.322 210.126 72.646 c + 211.626 71.413 212.726 69.783 213.426 67.756 c + 214.119 65.709 214.459 63.196 214.446 60.216 c + f + 253 82.1 m + 229.8 82.497 l + 229.583 37.497 l + 252.783 37.1 l + 252.825 45.8 l + 237.825 46.056 l + 237.862 53.816 l + 251.762 53.578 l + 251.804 62.278 l + 237.904 62.516 l + 237.958 73.616 l + 252.958 73.36 l + f + 289 81.5 m + 281.02 81.636 l + 267.22 51.036 l + 267.369 81.936 l + 259.779 82.066 l + 259.562 37.066 l + 269.462 36.897 l + 281.262 62.497 l + 281.138 36.697 l + 288.728 36.567 l + f + 322 44.7 m + 312 44.872 l + 312.175 81.172 l + 303.895 81.314 l + 303.72 45.014 l + 293.72 45.186 l + 293.678 36.486 l + 321.978 36.001 l + f + 345 80.6 m + 326.2 80.922 l + 326.161 72.952 l + 331.421 72.862 l + 331.281 43.862 l + 326.022 43.952 l + 325.983 35.982 l + 344.783 35.66 l + 344.822 43.63 l + 339.562 43.72 l + 339.702 72.72 l + 344.962 72.63 l + f + 381 79.9 m + 372.44 80.046 l + 370.18 70.996 l + 358.28 71.2 l + 356.1 80.33 l + 347.76 80.473 l + 359.36 35.273 l + 368.89 35.11 l + h + 368.1 62.8 m + 364.08 46.7 l + 360.21 62.9 l + f + 409 79.5 m + 385.8 79.896 l + 385.583 34.896 l + 393.863 34.754 l + 394.038 71.054 l + 408.938 70.799 l + f + `, + FINAL: `33.5 13.4 m + 404.5 6.92 l + 419.6 6.657 431.9 18.52 432.1 33.62 c + 432.89 78.92 l + 433.153 94.02 421.29 106.32 406.19 106.52 c + 35.19 113 l + 20.09 113.263 7.79 101.4 7.59 86.3 c + 6.8 41 l + 6.537 25.9 18.4 13.6 33.5 13.4 c + s + 148 44.7 m + 126.9 45.053 l + 126.995 54.943 l + 146.495 54.616 l + 146.593 64.916 l + 127.093 65.243 l + 127.31 87.943 l + 115.51 88.14 l + 115.001 35.04 l + 147.801 34.491 l + f + 181 87 m + 154.2 87.449 l + 154.11 78.029 l + 161.62 77.903 l + 161.292 43.603 l + 153.782 43.729 l + 153.692 34.309 l + 180.492 33.86 l + 180.582 43.28 l + 173.072 43.406 l + 173.4 77.706 l + 180.91 77.58 l + f + 233 86.1 m + 221.6 86.291 l + 201.8 50.191 l + 202.149 86.691 l + 191.349 86.872 l + 190.84 33.772 l + 204.94 33.536 l + 221.94 63.736 l + 221.649 33.336 l + 232.449 33.155 l + f + 287 85.2 m + 274.8 85.404 l + 271.53 74.704 l + 254.53 74.988 l + 251.46 85.788 l + 239.56 85.987 l + 255.96 32.587 l + 269.56 32.359 l + h + 268.6 65 m + 262.78 46 l + 257.33 65.2 l + f + 326 84.5 m + 292.9 85.053 l + 292.391 31.953 l + 304.191 31.755 l + 304.601 74.655 l + 325.801 74.3 l + f + `, + EXPIRED: `33.5 13.4 m + 404.5 6.92 l + 419.6 6.657 431.9 18.52 432.1 33.62 c + 432.89 78.92 l + 433.153 94.02 421.29 106.32 406.19 106.52 c + 35.19 113 l + 20.09 113.263 7.79 101.4 7.59 86.3 c + 6.8 41 l + 6.537 25.9 18.4 13.6 33.5 13.4 c + s + 99.4 88.3 m + 66.3 88.855 l + 65.791 35.755 l + 98.891 35.2 l + 98.989 45.5 l + 77.589 45.858 l + 77.677 55.028 l + 97.577 54.696 l + 97.676 64.996 l + 77.776 65.328 l + 77.902 78.428 l + 99.302 78.07 l + f + 151 87.5 m + 137.3 87.729 l + 127.3 70.429 l + 117.4 88.129 l + 104.3 88.347 l + 120.3 61.347 l + 104.1 35.247 l + 117.7 35.019 l + 127.4 51.419 l + 137.06 34.719 l + 150.16 34.5 l + 134.36 60.6 l + f + 195 50.4 m + 195.023 52.78 194.686 55.117 193.99 57.41 c + 193.297 59.683 192.29 61.603 190.97 63.17 c + 189.163 65.297 187.137 66.913 184.89 68.02 c + 182.663 69.127 179.877 69.71 176.53 69.77 c + 169.17 69.893 l + 169.336 87.193 l + 157.536 87.391 l + 157.027 34.291 l + 176.527 33.966 l + 179.44 33.917 181.894 34.174 183.887 34.735 c + 185.9 35.272 187.684 36.112 189.237 37.255 c + 191.097 38.628 192.52 40.402 193.507 42.575 c + 194.514 44.748 195.03 47.368 195.057 50.435 c + h + 182.8 50.926 m + 182.786 49.426 182.426 48.146 181.72 47.086 c + 181.013 46.006 180.197 45.259 179.27 44.846 c + 178.037 44.295 176.833 44.006 175.66 43.978 c + 174.487 43.926 172.927 43.917 170.98 43.949 c + 168.95 43.983 l + 169.102 59.883 l + 172.492 59.827 l + 174.505 59.793 176.155 59.623 177.442 59.316 c + 178.755 59.008 179.849 58.418 180.722 57.546 c + 181.475 56.772 182.012 55.859 182.332 54.806 c + 182.671 53.732 182.833 52.432 182.818 50.906 c + f + 228 86.2 m + 201.2 86.649 l + 201.11 77.229 l + 208.62 77.103 l + 208.292 42.803 l + 200.782 42.929 l + 200.692 33.509 l + 227.492 33.06 l + 227.582 42.48 l + 220.072 42.606 l + 220.4 76.906 l + 227.91 76.78 l + f + 263 48.7 m + 262.987 47.367 262.74 46.23 262.259 45.29 c + 261.778 44.343 260.961 43.607 259.809 43.08 c + 259.002 42.713 258.066 42.502 256.999 42.449 c + 255.932 42.372 254.689 42.345 253.269 42.369 c + 248.989 42.44 l + 249.126 56.74 l + 252.756 56.679 l + 254.643 56.648 256.223 56.514 257.496 56.279 c + 258.769 56.044 259.833 55.537 260.686 54.759 c + 261.499 54.006 262.086 53.186 262.446 52.299 c + 262.827 51.386 263.011 50.183 262.996 48.689 c + h + 281.8 85.3 m + 267.4 85.541 l + 254.7 66.241 l + 249.25 66.332 l + 249.437 85.832 l + 237.637 86.029 l + 237.128 32.929 l + 256.928 32.597 l + 259.635 32.552 261.965 32.691 263.918 33.015 c + 265.871 33.339 267.705 34.082 269.418 35.245 c + 271.151 36.405 272.531 37.928 273.558 39.815 c + 274.605 41.675 275.141 44.035 275.168 46.895 c + 275.206 50.822 274.446 54.035 272.888 56.535 c + 271.355 59.035 269.138 61.132 266.238 62.825 c + f + 321 84.6 m + 287.9 85.155 l + 287.391 32.055 l + 320.491 31.5 l + 320.589 41.8 l + 299.189 42.158 l + 299.277 51.328 l + 319.177 50.996 l + 319.276 61.296 l + 299.376 61.628 l + 299.502 74.728 l + 320.902 74.37 l + f + 373 57.2 m + 373.047 62.147 372.114 66.613 370.2 70.6 c + 368.287 74.533 365.853 77.573 362.9 79.72 c + 360.68 81.327 358.24 82.463 355.58 83.13 c + 352.92 83.793 349.763 84.157 346.11 84.22 c + 329.91 84.49 l + 329.401 31.39 l + 346.001 31.112 l + 349.734 31.05 352.961 31.365 355.681 32.057 c + 358.394 32.724 360.681 33.707 362.541 35.007 c + 365.721 37.194 368.234 40.174 370.081 43.947 c + 371.941 47.7 372.898 52.134 372.951 57.247 c + h + 360.8 57.297 m + 360.767 53.797 360.183 50.821 359.05 48.367 c + 357.937 45.887 356.183 43.964 353.79 42.597 c + 352.57 41.931 351.323 41.487 350.05 41.267 c + 348.797 41.027 346.897 40.928 344.35 40.97 c + 341.36 41.02 l + 341.678 74.32 l + 344.668 74.27 l + 347.481 74.223 349.541 74.046 350.848 73.738 c + 352.161 73.407 353.438 72.837 354.678 72.028 c + 356.818 70.562 358.381 68.632 359.368 66.238 c + 360.348 63.818 360.821 60.848 360.788 57.328 c + f + `, + AS_IS: `33.5 13.4 m + 404.5 6.92 l + 419.6 6.657 431.9 18.52 432.1 33.62 c + 432.89 78.92 l + 433.153 94.02 421.29 106.32 406.19 106.52 c + 35.19 113 l + 20.09 113.263 7.79 101.4 7.59 86.3 c + 6.8 41 l + 6.537 25.9 18.4 13.6 33.5 13.4 c + s + 170 87.2 m + 157.8 87.404 l + 154.53 76.704 l + 137.53 76.988 l + 134.46 87.788 l + 122.56 87.987 l + 138.96 34.587 l + 152.56 34.359 l + h + 151.6 67 m + 145.78 48 l + 140.33 67.2 l + f + 213 69.7 m + 213.05 74.933 211.173 79.233 207.37 82.6 c + 203.583 85.927 198.417 87.643 191.87 87.75 c + 188.077 87.813 184.76 87.488 181.92 86.774 c + 179.1 86.034 176.453 85.091 173.98 83.944 c + 173.858 71.244 l + 175.148 71.222 l + 177.615 73.442 180.361 75.132 183.388 76.292 c + 186.435 77.452 189.355 78.009 192.148 77.962 c + 192.868 77.95 193.811 77.863 194.978 77.7 c + 196.145 77.538 197.098 77.284 197.838 76.938 c + 198.738 76.495 199.471 75.948 200.038 75.298 c + 200.627 74.646 200.915 73.689 200.903 72.428 c + 200.892 71.262 200.452 70.268 199.583 69.448 c + 198.736 68.608 197.49 67.975 195.843 67.548 c + 194.116 67.101 192.286 66.691 190.353 66.318 c + 188.44 65.922 186.64 65.415 184.953 64.798 c + 181.08 63.412 178.28 61.495 176.553 59.048 c + 174.846 56.575 173.976 53.495 173.943 49.808 c + 173.896 44.862 175.766 40.795 179.553 37.608 c + 183.36 34.402 188.26 32.748 194.253 32.648 c + 197.266 32.598 200.246 32.893 203.193 33.534 c + 206.153 34.151 208.716 34.954 210.883 35.944 c + 211 48.144 l + 209.74 48.166 l + 207.88 46.486 205.6 45.095 202.9 43.995 c + 200.22 42.875 197.487 42.339 194.7 42.386 c + 193.713 42.402 192.73 42.502 191.75 42.684 c + 190.79 42.843 189.86 43.144 188.96 43.587 c + 188.16 43.958 187.477 44.518 186.91 45.267 c + 186.342 45.994 186.063 46.821 186.072 47.747 c + 186.085 49.154 186.559 50.227 187.492 50.967 c + 188.425 51.687 190.175 52.337 192.742 52.917 c + 194.429 53.293 196.042 53.66 197.582 54.017 c + 199.142 54.372 200.819 54.869 202.612 55.508 c + 206.132 56.781 208.735 58.557 210.422 60.837 c + 212.129 63.091 212.999 66.051 213.032 69.718 c + f + 267 85.5 m + 240.2 85.949 l + 240.11 76.529 l + 247.62 76.403 l + 247.292 42.103 l + 239.782 42.229 l + 239.692 32.809 l + 266.492 32.36 l + 266.582 41.78 l + 259.072 41.906 l + 259.4 76.206 l + 266.91 76.08 l + f + 313 68.1 m + 313.05 73.333 311.173 77.633 307.37 81 c + 303.583 84.327 298.417 86.043 291.87 86.15 c + 288.077 86.213 284.76 85.888 281.92 85.174 c + 279.1 84.434 276.453 83.491 273.98 82.344 c + 273.858 69.644 l + 275.148 69.622 l + 277.615 71.842 280.361 73.532 283.388 74.692 c + 286.435 75.852 289.355 76.409 292.148 76.362 c + 292.868 76.35 293.811 76.263 294.978 76.1 c + 298.738 74.895 299.471 74.348 300.038 73.698 c + 300.627 73.046 300.915 72.089 300.903 70.828 c + 300.892 69.662 300.452 68.668 299.583 67.848 c + 298.736 67.008 297.49 66.375 295.843 65.948 c + 294.116 65.501 292.286 65.091 290.353 64.718 c + 288.44 64.322 286.64 63.815 284.953 63.198 c + 281.08 61.812 278.28 59.895 276.553 57.448 c + 274.846 54.975 273.976 51.895 273.943 48.208 c + 273.896 43.262 275.766 39.195 279.553 36.008 c + 283.36 32.802 288.26 31.148 294.253 31.048 c + 297.266 30.998 300.246 31.293 303.193 31.934 c + 306.153 32.551 308.716 33.354 310.883 34.344 c + 311 46.544 l + 309.74 46.565 l + 307.88 44.885 305.6 43.495 302.9 42.395 c + 300.22 41.275 297.487 40.739 294.7 40.785 c + 293.713 40.802 292.73 40.902 291.75 41.084 c + 290.79 41.243 289.86 41.544 288.96 41.987 c + 288.16 42.357 287.477 42.917 286.91 43.667 c + 286.342 44.394 286.063 45.221 286.072 46.147 c + 286.085 47.554 286.559 48.627 287.492 49.367 c + 288.425 50.087 290.175 50.737 292.742 51.317 c + 294.429 51.693 296.042 52.06 297.582 52.417 c + 299.142 52.772 300.819 53.269 302.612 53.907 c + 306.132 55.181 308.735 56.957 310.422 59.237 c + 312.129 61.491 312.999 64.451 313.032 68.117 c + f + `, + SOLD: `33.5 13.4 m + 404.5 6.92 l + 419.6 6.657 431.9 18.52 432.1 33.62 c + 432.89 78.92 l + 433.153 94.02 421.29 106.32 406.19 106.52 c + 35.19 113 l + 20.09 113.263 7.79 101.4 7.59 86.3 c + 6.8 41 l + 6.537 25.9 18.4 13.6 33.5 13.4 c + s + 166 70.5 m + 166.05 75.733 164.173 80.033 160.37 83.4 c + 156.583 86.727 151.417 88.443 144.87 88.55 c + 141.077 88.613 137.76 88.288 134.92 87.574 c + 132.1 86.834 129.453 85.891 126.98 84.744 c + 126.858 72.044 l + 128.148 72.022 l + 130.615 74.242 133.361 75.932 136.388 77.092 c + 139.435 78.252 142.355 78.809 145.148 78.762 c + 145.868 78.75 146.811 78.663 147.978 78.5 c + 149.145 78.338 150.098 78.084 150.838 77.738 c + 151.738 77.295 152.471 76.748 153.038 76.098 c + 153.627 75.446 153.915 74.489 153.903 73.228 c + 153.892 72.062 153.452 71.068 152.583 70.248 c + 151.736 69.408 150.49 68.775 148.843 68.348 c + 147.116 67.901 145.286 67.491 143.353 67.118 c + 141.44 66.722 139.64 66.215 137.953 65.598 c + 134.08 64.212 131.28 62.295 129.553 59.848 c + 127.846 57.375 126.976 54.295 126.943 50.608 c + 126.896 45.662 128.766 41.595 132.553 38.408 c + 136.36 35.202 141.26 33.548 147.253 33.448 c + 150.266 33.398 153.246 33.693 156.193 34.334 c + 159.153 34.951 161.716 35.754 163.883 36.744 c + 164 48.944 l + 162.74 48.965 l + 160.88 47.285 158.6 45.895 155.9 44.795 c + 153.22 43.675 150.487 43.139 147.7 43.185 c + 146.713 43.202 145.73 43.302 144.75 43.484 c + 143.79 43.643 142.86 43.944 141.96 44.387 c + 141.16 44.757 140.477 45.317 139.91 46.067 c + 139.342 46.794 139.063 47.621 139.072 48.547 c + 139.085 49.954 139.559 51.027 140.492 51.767 c + 141.425 52.487 143.175 53.137 145.742 53.717 c + 147.429 54.093 149.042 54.46 150.582 54.817 c + 152.142 55.172 153.819 55.669 155.612 56.307 c + 159.132 57.581 161.735 59.357 163.422 61.637 c + 165.129 63.891 165.999 66.851 166.032 70.517 c + f + 218 59.8 m + 218.081 68.267 216.051 75.033 211.91 80.1 c + 207.77 85.14 202.003 87.723 194.61 87.85 c + 187.277 87.973 181.477 85.583 177.21 80.68 c + 172.977 75.753 170.82 69.053 170.74 60.58 c + 170.658 52.047 172.688 45.28 176.83 40.28 c + 180.97 35.24 186.737 32.657 194.13 32.53 c + 201.463 32.407 207.263 34.797 211.53 39.7 c + 215.783 44.58 217.95 51.28 218.03 59.8 c + h + 202.5 73.5 m + 203.633 71.86 204.467 69.943 205 67.75 c + 205.533 65.53 205.785 62.933 205.757 59.96 c + 205.726 56.773 205.383 54.067 204.727 51.84 c + 204.07 49.613 203.22 47.82 202.177 46.46 c + 201.117 45.047 199.897 44.033 198.517 43.42 c + 197.157 42.8 195.737 42.502 194.257 42.527 c + 192.757 42.552 191.344 42.885 190.017 43.526 c + 188.71 44.167 187.51 45.21 186.417 46.656 c + 185.404 48.003 184.58 49.859 183.947 52.226 c + 183.333 54.566 183.041 57.283 183.071 60.376 c + 183.101 63.543 183.435 66.239 184.071 68.466 c + 184.728 70.666 185.578 72.459 186.621 73.846 c + 187.661 75.233 188.871 76.246 190.251 76.886 c + 191.631 77.529 193.081 77.838 194.601 77.813 c + 196.121 77.788 197.564 77.431 198.931 76.743 c + 200.298 76.03 201.488 74.95 202.501 73.503 c + f + 261 85.6 m + 227.9 86.153 l + 227.391 33.053 l + 239.191 32.855 l + 239.601 75.755 l + 260.801 75.4 l + f + 311 58.3 m + 311.047 63.247 310.114 67.713 308.2 71.7 c + 306.287 75.633 303.853 78.673 300.9 80.82 c + 298.68 82.427 296.24 83.563 293.58 84.23 c + 267.91 85.59 l + 267.401 32.49 l + 284.001 32.212 l + 287.734 32.15 290.961 32.465 293.681 33.157 c + 296.394 33.824 298.681 34.807 300.541 36.107 c + 303.721 38.294 306.234 41.274 308.081 45.047 c + 309.941 48.8 310.898 53.234 310.951 58.347 c + h + 298.8 58.397 m + 298.767 54.897 298.183 51.921 297.05 49.467 c + 295.937 46.987 294.183 45.064 291.79 43.697 c + 290.57 43.031 289.323 42.587 288.05 42.367 c + 286.797 42.127 284.897 42.028 282.35 42.07 c + 279.36 42.12 l + 279.678 75.42 l + 282.668 75.37 l + 285.481 75.323 287.541 75.146 288.848 74.838 c + 290.161 74.507 291.438 73.937 292.678 73.128 c + 294.818 71.662 296.381 69.732 297.368 67.338 c + 298.348 64.918 298.821 61.948 298.788 58.428 c + f + `, + EXPERIMENTAL: `33.5 13.4 m + 404.5 6.92 l + 419.6 6.657 431.9 18.52 432.1 33.62 c + 432.89 78.92 l + 433.153 94.02 421.29 106.32 406.19 106.52 c + 35.19 113 l + 20.09 113.263 7.79 101.4 7.59 86.3 c + 6.8 41 l + 6.537 25.9 18.4 13.6 33.5 13.4 c + s + 55.9 86.5 m + 32.9 86.873 l + 32.766 40.073 l + 55.766 39.7 l + 55.792 48.76 l + 40.992 49.001 l + 41.015 57.081 l + 54.815 56.857 l + 54.841 65.917 l + 41.041 66.141 l + 41.074 77.741 l + 55.874 77.5 l + f + 91.6 85.9 m + 82.12 86.054 l + 75.22 70.754 l + 68.28 86.254 l + 59.23 86.401 l + 70.43 62.601 l + 59.33 39.501 l + 68.79 39.347 l + 75.45 53.847 l + 82.22 39.147 l + 91.3 39 l + 80.3 61.9 l + f + 122 53.4 m + 122 55.493 121.757 57.553 121.27 59.58 c + 120.777 61.58 120.071 63.27 119.15 64.65 c + 117.89 66.517 116.477 67.933 114.91 68.9 c + 113.363 69.867 111.43 70.37 109.11 70.41 c + 104.01 70.493 l + 104.054 85.793 l + 95.854 85.926 l + 95.72 39.126 l + 109.22 38.907 l + 111.24 38.874 112.943 39.108 114.33 39.61 c + 115.723 40.091 116.956 40.837 118.03 41.85 c + 119.316 43.063 120.296 44.63 120.97 46.55 c + 121.656 48.47 122.003 50.78 122.01 53.48 c + h + 113.52 53.821 m + 113.52 52.501 113.275 51.374 112.784 50.441 c + 112.297 49.488 111.734 48.824 111.094 48.451 c + 110.241 47.962 109.407 47.703 108.594 47.674 c + 107.781 47.624 106.697 47.61 105.344 47.632 c + 103.934 47.655 l + 103.974 61.655 l + 106.324 61.617 l + 107.717 61.595 108.864 61.45 109.764 61.184 c + 110.677 60.918 111.437 60.401 112.044 59.634 c + 112.569 58.954 112.945 58.151 113.174 57.224 c + 113.413 56.278 113.531 55.134 113.527 53.794 c + f + 151 84.9 m + 128 85.273 l + 127.866 38.473 l + 150.866 38.1 l + 150.892 47.16 l + 136.092 47.401 l + 136.115 55.481 l + 149.915 55.257 l + 149.941 64.317 l + 136.141 64.541 l + 136.174 76.141 l + 150.974 75.9 l + f + 176 52.1 m + 176 50.927 175.833 49.923 175.5 49.09 c + 175.17 48.257 174.607 47.607 173.81 47.14 c + 173.254 46.813 172.604 46.625 171.86 46.574 c + 171.12 46.502 170.26 46.474 169.28 46.49 c + 166.31 46.538 l + 166.346 59.138 l + 168.866 59.098 l + 170.173 59.076 171.269 58.964 172.156 58.762 c + 173.036 58.558 173.776 58.115 174.376 57.432 c + 174.943 56.772 175.353 56.052 175.606 55.272 c + 175.874 54.471 176.006 53.411 176.003 52.092 c + h + 188.9 84.4 m + 178.9 84.563 l + 170.18 67.563 l + 166.4 67.624 l + 166.449 84.824 l + 158.289 84.956 l + 158.155 38.156 l + 171.955 37.933 l + 173.835 37.903 175.452 38.034 176.805 38.326 c + 178.158 38.619 179.428 39.279 180.615 40.306 c + 181.815 41.333 182.765 42.68 183.465 44.346 c + 184.178 45.993 184.542 48.073 184.555 50.586 c + 184.565 54.046 184.025 56.876 182.935 59.076 c + 181.862 61.276 180.315 63.116 178.295 64.596 c + f + 210 84 m + 191.4 84.302 l + 191.376 76.002 l + 196.586 75.917 l + 196.5 45.717 l + 191.29 45.802 l + 191.266 37.502 l + 209.866 37.2 l + 209.89 45.5 l + 204.68 45.585 l + 204.766 75.785 l + 209.976 75.7 l + f + 250 83.3 m + 241.84 83.432 l + 241.75 52.032 l + 235.91 72.432 l + 230.25 72.524 l + 224.3 52.224 l + 224.39 83.624 l + 216.66 83.75 l + 216.526 36.95 l + 226.046 36.795 l + 233.266 60.195 l + 240.336 36.595 l + 249.856 36.44 l + f + 281 82.8 m + 258 83.173 l + 257.866 36.373 l + 280.866 36 l + 280.892 45.06 l + 266.092 45.301 l + 266.115 53.381 l + 279.915 53.157 l + 279.941 62.217 l + 266.141 62.441 l + 266.174 74.041 l + 280.974 73.8 l + f + 316 82.3 m + 308.1 82.428 l + 294.5 50.528 l + 294.592 82.628 l + 287.072 82.75 l + 286.938 35.95 l + 296.738 35.791 l + 308.438 62.391 l + 308.361 35.591 l + 315.881 35.469 l + f + 349 44 m + 339.07 44.161 l + 339.178 81.961 l + 330.978 82.094 l + 330.87 44.294 l + 320.94 44.455 l + 320.914 35.395 l + 349.014 34.939 l + f + 384 81.2 m + 375.52 81.338 l + 373.29 71.908 l + 361.49 72.099 l + 359.32 81.599 l + 351.06 81.733 l + 362.66 34.733 l + 372.1 34.58 l + h + 371.3 63.4 m + 367.34 46.7 l + 363.48 63.6 l + f + 411 80.7 m + 388.1 81.072 l + 387.966 34.272 l + 396.166 34.139 l + 396.274 71.939 l + 410.974 71.7 l + f + `, + FOR_COMMENT: `33.5 13.4 m + 404.5 6.92 l + 419.6 6.657 431.9 18.52 432.1 33.62 c + 432.89 78.92 l + 433.153 94.02 421.29 106.32 406.19 106.52 c + 35.19 113 l + 20.09 113.263 7.79 101.4 7.59 86.3 c + 6.8 41 l + 6.537 25.9 18.4 13.6 33.5 13.4 c + s + 61.6 49.9 m + 46.8 50.184 l + 46.866 58.134 l + 60.566 57.871 l + 60.635 66.141 l + 46.935 66.404 l + 47.087 84.704 l + 38.837 84.862 l + 38.48 42.162 l + 61.48 41.72 l + f + 98.7 62.3 m + 98.757 69.1 97.334 74.533 94.43 78.6 c + 91.523 82.653 87.49 84.73 82.33 84.83 c + 77.163 84.929 73.097 83.006 70.13 79.06 c + 67.157 75.1 65.643 69.7 65.59 62.86 c + 65.533 55.993 66.956 50.527 69.86 46.46 c + 72.767 42.407 76.8 40.33 81.96 40.23 c + 87.113 40.131 91.18 42.055 94.16 46 c + 97.147 49.927 98.667 55.327 98.72 62.2 c + h + 87.8 73.3 m + 88.593 71.98 89.177 70.437 89.55 68.67 c + 89.924 66.883 90.101 64.793 90.081 62.4 c + 90.06 59.833 89.818 57.657 89.357 55.87 c + 88.896 54.077 88.299 52.633 87.567 51.54 c + 86.82 50.407 85.964 49.59 84.997 49.09 c + 84.044 48.591 83.047 48.352 82.007 48.372 c + 80.954 48.392 79.964 48.66 79.037 49.176 c + 78.117 49.691 77.274 50.531 76.507 51.696 c + 75.794 52.783 75.217 54.276 74.777 56.176 c + 74.346 58.063 74.141 60.249 74.162 62.736 c + 74.183 65.283 74.417 67.449 74.864 69.236 c + 75.325 71.009 75.922 72.453 76.654 73.566 c + 80.171 76.533 81.187 76.782 82.254 76.761 c + 83.321 76.741 84.334 76.453 85.294 75.899 c + 86.254 75.326 87.091 74.459 87.804 73.299 c + f + 123 53.6 m + 122.991 52.527 122.818 51.61 122.48 50.85 c + 122.143 50.09 121.569 49.497 120.76 49.07 c + 120.196 48.775 119.539 48.605 118.79 48.562 c + 118.043 48.5 117.173 48.478 116.18 48.497 c + 113.18 48.555 l + 113.276 60.055 l + 115.826 60.006 l + 117.153 59.981 118.259 59.873 119.146 59.684 c + 120.039 59.495 120.786 59.088 121.386 58.464 c + 121.957 57.86 122.37 57.2 122.626 56.484 c + 122.893 55.751 123.022 54.781 123.012 53.574 c + h + 136.2 83 m + 126.1 83.194 l + 117.2 67.694 l + 113.38 67.767 l + 113.511 83.467 l + 105.261 83.625 l + 104.904 40.925 l + 118.804 40.658 l + 120.704 40.622 122.341 40.734 123.714 40.995 c + 125.087 41.256 126.374 41.853 127.574 42.785 c + 128.794 43.719 129.761 44.945 130.474 46.465 c + 131.207 47.965 131.584 49.862 131.604 52.155 c + 131.63 55.315 131.097 57.899 130.004 59.905 c + 128.924 61.919 127.367 63.605 125.334 64.965 c + f + 169 83.2 m + 166.607 83.246 164.393 82.819 162.36 81.92 c + 160.333 81.02 158.587 79.657 157.12 77.83 c + 155.653 76.003 154.503 73.71 153.67 70.95 c + 152.857 68.19 152.433 64.993 152.4 61.36 c + 152.372 57.973 152.728 54.893 153.47 52.12 c + 154.21 49.347 155.3 46.963 156.74 44.97 c + 158.12 43.05 159.837 41.553 161.89 40.48 c + 163.957 39.407 166.213 38.847 168.66 38.8 c + 170.013 38.774 171.23 38.856 172.31 39.046 c + 173.403 39.217 174.413 39.456 175.34 39.763 c + 176.307 40.108 177.18 40.502 177.96 40.943 c + 178.753 41.368 179.447 41.764 180.04 42.133 c + 180.127 52.533 l + 179.177 52.551 l + 178.77 52.1 178.253 51.563 177.627 50.941 c + 177.017 50.321 176.32 49.711 175.537 49.111 c + 174.737 48.514 173.877 48.014 172.957 47.611 c + 168.83 47.059 167.723 47.329 166.677 47.846 c + 165.63 48.345 164.663 49.168 163.777 50.316 c + 162.937 51.423 162.257 52.88 161.737 54.686 c + 161.233 56.493 160.992 58.68 161.014 61.246 c + 161.036 63.926 161.335 66.16 161.912 67.946 c + 162.502 69.733 163.236 71.136 164.112 72.156 c + 164.998 73.19 165.985 73.926 167.072 74.366 c + 168.158 74.786 169.225 74.985 170.272 74.965 c + 171.278 74.946 172.271 74.726 173.251 74.305 c + 174.245 73.885 175.155 73.321 175.981 72.615 c + 176.681 72.047 177.332 71.44 177.931 70.795 c + 178.531 70.152 179.024 69.599 179.411 69.135 c + 180.275 69.119 l + 180.361 79.319 l + 179.561 79.813 178.794 80.276 178.061 80.709 c + 177.327 81.144 176.561 81.524 175.761 81.849 c + 174.714 82.271 173.731 82.596 172.811 82.824 c + 171.891 83.052 170.624 83.181 169.011 83.213 c + f + 218 60 m + 218.057 66.8 216.634 72.233 213.73 76.3 c + 210.823 80.353 206.79 82.43 201.63 82.53 c + 196.463 82.629 192.397 80.706 189.43 76.76 c + 186.457 72.8 184.943 67.4 184.89 60.56 c + 184.833 53.693 186.256 48.227 189.16 44.16 c + 192.067 40.107 196.1 38.03 201.26 37.93 c + 206.413 37.831 210.48 39.755 213.46 43.7 c + 216.447 47.627 217.967 53.027 218.02 59.9 c + h + 207.1 71 m + 207.893 69.68 208.477 68.137 208.85 66.37 c + 209.224 64.583 209.401 62.493 209.381 60.1 c + 209.36 57.533 209.118 55.357 208.657 53.57 c + 208.196 51.777 207.599 50.333 206.867 49.24 c + 206.12 48.107 205.264 47.29 204.297 46.79 c + 203.344 46.291 202.347 46.052 201.307 46.072 c + 200.254 46.092 199.264 46.36 198.337 46.876 c + 197.417 47.391 196.574 48.231 195.807 49.396 c + 195.094 50.483 194.517 51.976 194.077 53.876 c + 193.646 55.763 193.441 57.949 193.462 60.436 c + 193.483 62.983 193.717 65.149 194.164 66.936 c + 194.625 68.709 195.222 70.153 195.954 71.266 c + 199.471 74.233 200.487 74.482 201.554 74.461 c + 202.621 74.441 203.634 74.153 204.594 73.599 c + 205.554 73.026 206.391 72.159 207.104 70.999 c + f + 258 80.6 m + 249.75 80.758 l + 249.511 52.158 l + 243.701 70.858 l + 237.981 70.968 l + 231.861 52.468 l + 232.1 81.068 l + 224.28 81.218 l + 223.923 38.518 l + 233.553 38.333 l + 240.963 59.633 l + 247.993 38.033 l + 257.623 37.848 l + f + 300 79.8 m + 291.75 79.958 l + 291.511 51.358 l + 285.701 70.058 l + 279.981 70.168 l + 273.861 51.668 l + 274.1 80.268 l + 266.28 80.418 l + 265.923 37.718 l + 275.553 37.533 l + 282.963 58.833 l + 289.993 37.233 l + 299.623 37.048 l + f + 332 79.2 m + 308.7 79.646 l + 308.343 36.946 l + 331.643 36.5 l + 331.712 44.77 l + 316.712 45.058 l + 316.774 52.438 l + 330.674 52.171 l + 330.743 60.441 l + 316.843 60.708 l + 316.931 71.308 l + 331.931 71.02 l + f + 368 78.5 m + 360.01 78.653 l + 346.11 49.553 l + 346.355 78.853 l + 338.755 78.999 l + 338.398 36.299 l + 348.308 36.109 l + 360.208 60.409 l + 360.004 35.909 l + 367.604 35.763 l + f + 401 43.4 m + 391 43.593 l + 391.288 78.093 l + 382.998 78.252 l + 382.71 43.752 l + 372.71 43.945 l + 372.641 35.675 l + 401.041 35.131 l + f + `, + TOP_SECRET: `33.5 13.4 m + 404.5 6.92 l + 419.6 6.657 431.9 18.52 432.1 33.62 c + 432.89 78.92 l + 433.153 94.02 421.29 106.32 406.19 106.52 c + 35.19 113 l + 20.09 113.263 7.79 101.4 7.59 86.3 c + 6.8 41 l + 6.537 25.9 18.4 13.6 33.5 13.4 c + s + 67.5 47.4 m + 55 47.623 l + 55.357 87.423 l + 45.057 87.607 l + 44.7 47.807 l + 32.2 48.03 l + 32.114 38.48 l + 67.314 37.851 l + f + 113 61.7 m + 113.071 69.567 111.304 75.867 107.7 80.6 c + 104.093 85.287 99.06 87.687 92.6 87.8 c + 86.187 87.915 81.12 85.695 77.4 81.14 c + 73.713 76.56 71.833 70.327 71.76 62.44 c + 71.689 54.507 73.455 48.207 77.06 43.54 c + 80.667 38.853 85.667 36.453 92.06 36.34 c + 98.453 36.226 103.52 38.446 107.26 43 c + 110.967 47.533 112.853 53.767 112.92 61.7 c + h + 99.5 74.4 m + 100.487 72.88 101.213 71.097 101.68 69.05 c + 102.144 66.983 102.364 64.57 102.339 61.81 c + 102.312 58.85 102.013 56.333 101.44 54.26 c + 100.867 52.193 100.127 50.527 99.22 49.26 c + 98.3 47.947 97.237 47.003 96.03 46.43 c + 94.843 45.854 93.607 45.577 92.32 45.6 c + 91.013 45.623 89.783 45.933 88.63 46.528 c + 87.49 47.123 86.443 48.093 85.49 49.438 c + 84.61 50.691 83.893 52.418 83.34 54.618 c + 82.805 56.798 82.551 59.325 82.577 62.198 c + 82.603 65.138 82.894 67.645 83.449 69.718 c + 84.022 71.765 84.762 73.431 85.669 74.718 c + 86.576 76.005 87.629 76.948 88.829 77.548 c + 90.029 78.146 91.292 78.433 92.619 78.409 c + 93.939 78.385 95.196 78.053 96.389 77.413 c + 97.582 76.75 98.619 75.747 99.499 74.403 c + f + 153 51.9 m + 153.02 54.113 152.726 56.287 152.12 58.42 c + 151.513 60.533 150.637 62.317 149.49 63.77 c + 147.917 65.743 146.153 67.247 144.2 68.28 c + 142.26 69.307 139.833 69.847 136.92 69.9 c + 130.51 70.014 l + 130.654 86.114 l + 120.354 86.298 l + 119.911 36.898 l + 136.811 36.596 l + 139.351 36.551 141.488 36.789 143.221 37.311 c + 144.974 37.81 146.528 38.59 147.881 39.651 c + 149.501 40.924 150.741 42.571 151.601 44.591 c + 152.474 46.611 152.924 49.048 152.951 51.901 c + h + 142.4 52.388 m + 142.388 50.995 142.073 49.805 141.457 48.818 c + 140.84 47.811 140.127 47.115 139.317 46.728 c + 138.237 46.217 137.19 45.948 136.177 45.922 c + 135.157 45.874 133.8 45.865 132.107 45.895 c + 130.337 45.927 l + 130.47 60.727 l + 133.42 60.674 l + 135.173 60.643 136.61 60.485 137.73 60.199 c + 138.87 59.913 139.82 59.367 140.58 58.559 c + 141.235 57.839 141.701 56.989 141.98 56.009 c + 142.275 55.009 142.416 53.803 142.403 52.389 c + f + 211 69.1 m + 211.044 73.967 209.407 77.967 206.09 81.1 c + 202.797 84.187 198.297 85.783 192.59 85.89 c + 189.283 85.949 186.393 85.647 183.92 84.983 c + 181.467 84.296 179.163 83.42 177.01 82.353 c + 176.904 70.553 l + 178.034 70.533 l + 180.181 72.593 182.571 74.166 185.204 75.253 c + 187.857 76.333 190.401 76.853 192.834 76.813 c + 193.459 76.802 194.279 76.721 195.294 76.57 c + 196.314 76.419 197.144 76.183 197.784 75.862 c + 198.564 75.45 199.204 74.94 199.704 74.332 c + 200.217 73.726 200.468 72.836 200.457 71.662 c + 200.447 70.575 200.064 69.652 199.307 68.892 c + 198.567 68.112 197.48 67.522 196.047 67.122 c + 194.54 66.707 192.947 66.327 191.267 65.982 c + 189.6 65.613 188.034 65.143 186.567 64.572 c + 183.194 63.285 180.757 61.505 179.257 59.232 c + 177.77 56.939 177.01 54.079 176.977 50.652 c + 176.936 46.052 178.562 42.285 181.857 39.352 c + 185.17 36.372 189.437 34.835 194.657 34.742 c + 197.284 34.695 199.877 34.969 202.437 35.565 c + 205.017 36.138 207.247 36.885 209.127 37.805 c + 209.229 49.205 l + 208.129 49.225 l + 206.509 47.658 204.522 46.368 202.169 45.355 c + 199.836 44.315 197.456 43.815 195.029 43.855 c + 194.169 43.87 193.312 43.963 192.459 44.133 c + 191.619 44.281 190.809 44.561 190.029 44.973 c + 189.336 45.317 188.742 45.837 188.249 46.533 c + 187.754 47.206 187.511 47.973 187.519 48.833 c + 187.531 50.139 187.941 51.139 188.749 51.833 c + 189.562 52.506 191.086 53.109 193.319 53.643 c + 194.786 53.993 196.192 54.333 197.539 54.663 c + 198.899 54.992 200.359 55.452 201.919 56.043 c + 204.986 57.229 207.252 58.879 208.719 60.993 c + 210.206 63.086 210.962 65.836 210.989 69.243 c + f + 248 84 m + 219.1 84.515 l + 218.657 35.115 l + 247.557 34.6 l + 247.643 44.15 l + 229.043 44.483 l + 229.119 53.003 l + 246.419 52.694 l + 246.505 62.244 l + 229.205 62.553 l + 229.314 74.753 l + 247.914 74.42 l + f + 274 84.5 m + 271.033 84.553 268.287 84.06 265.76 83.02 c + 263.247 81.98 261.08 80.403 259.26 78.29 c + 257.433 76.177 256.007 73.527 254.98 70.34 c + 253.967 67.153 253.443 63.453 253.41 59.24 c + 253.375 55.327 253.815 51.76 254.73 48.54 c + 255.65 45.34 257 42.583 258.78 40.27 c + 260.493 38.05 262.623 36.32 265.17 35.08 c + 267.73 33.84 270.53 33.193 273.57 33.14 c + 275.25 33.11 276.76 33.205 278.1 33.424 c + 279.46 33.621 280.713 33.897 281.86 34.253 c + 283.06 34.652 284.147 35.108 285.12 35.623 c + 286.107 36.114 286.97 36.574 287.71 37.003 c + 287.817 49.003 l + 286.637 49.024 l + 286.132 48.502 285.492 47.882 284.717 47.164 c + 283.957 46.451 283.094 45.747 282.127 45.054 c + 281.14 44.361 280.07 43.784 278.917 43.324 c + 277.77 42.858 276.544 42.637 275.237 42.66 c + 273.79 42.686 272.417 42.998 271.117 43.596 c + 269.817 44.172 268.62 45.122 267.527 46.446 c + 266.487 47.726 265.644 49.409 264.997 51.496 c + 264.372 53.589 264.073 56.116 264.1 59.076 c + 264.128 62.169 264.498 64.749 265.21 66.816 c + 265.943 68.883 266.85 70.503 267.93 71.676 c + 269.03 72.876 270.253 73.729 271.6 74.236 c + 272.947 74.721 274.27 74.951 275.57 74.928 c + 276.823 74.906 278.053 74.651 279.26 74.165 c + 280.487 73.678 281.617 73.028 282.65 72.215 c + 283.517 71.558 284.323 70.858 285.07 70.115 c + 285.817 69.375 286.427 68.735 286.9 68.195 c + 287.97 68.176 l + 288.076 79.976 l + 287.083 80.547 286.133 81.083 285.226 81.586 c + 284.319 82.089 283.366 82.525 282.366 82.896 c + 281.066 83.383 279.846 83.76 278.706 84.026 c + 277.566 84.289 275.996 84.439 273.996 84.475 c + f + 318 48.5 m + 317.989 47.26 317.774 46.203 317.355 45.33 c + 316.936 44.45 316.223 43.767 315.215 43.28 c + 314.515 42.939 313.702 42.743 312.775 42.693 c + 311.848 42.621 310.768 42.596 309.535 42.618 c + 305.805 42.685 l + 305.924 55.985 l + 309.084 55.928 l + 310.731 55.899 312.104 55.775 313.204 55.556 c + 314.311 55.338 315.237 54.868 315.984 54.146 c + 316.691 53.446 317.201 52.686 317.514 51.866 c + 317.846 51.02 318.006 49.9 317.993 48.506 c + h + 334.4 82.5 m + 321.8 82.724 l + 310.8 64.824 l + 306.06 64.909 l + 306.222 83.009 l + 296.022 83.192 l + 295.579 33.792 l + 312.879 33.484 l + 315.239 33.442 317.269 33.571 318.969 33.873 c + 320.669 34.174 322.266 34.864 323.759 35.943 c + 325.272 37.023 326.472 38.439 327.359 40.193 c + 328.266 41.926 328.732 44.119 328.759 46.773 c + 328.792 50.419 328.132 53.406 326.779 55.733 c + 325.439 58.059 323.509 60.006 320.989 61.573 c + f + 368 81.9 m + 339.1 82.415 l + 338.657 33.015 l + 367.557 32.5 l + 367.643 42.05 l + 349.043 42.383 l + 349.119 50.903 l + 366.419 50.594 l + 366.505 60.144 l + 349.205 60.453 l + 349.314 72.653 l + 367.914 72.32 l + f + 407 41.3 m + 394.5 41.523 l + 394.857 81.323 l + 384.557 81.507 l + 384.2 41.707 l + 371.7 41.93 l + 371.614 32.38 l + 406.814 31.751 l + f + `, + FOR_PUBLIC_RELEASE: `33.5 13.4 m + 404.5 6.92 l + 419.6 6.657 431.9 18.52 432.1 33.62 c + 432.89 78.92 l + 433.153 94.02 421.29 106.32 406.19 106.52 c + 35.19 113 l + 20.09 113.263 7.79 101.4 7.59 86.3 c + 6.8 41 l + 6.537 25.9 18.4 13.6 33.5 13.4 c + s + 93.2 32.1 m + 78.5 32.323 l + 78.566 38.583 l + 92.166 38.376 l + 92.234 44.886 l + 78.634 45.093 l + 78.785 59.493 l + 70.605 59.618 l + 70.251 25.918 l + 93.151 25.57 l + f + 130 41.8 m + 130.056 47.167 128.646 51.467 125.77 54.7 c + 122.89 57.893 118.89 59.53 113.77 59.61 c + 108.643 59.688 104.61 58.175 101.67 55.07 c + 98.723 51.95 97.223 47.717 97.17 42.37 c + 97.113 36.957 98.523 32.657 101.4 29.47 c + 104.28 26.277 108.28 24.64 113.4 24.56 c + 118.513 24.482 122.547 25.995 125.5 29.1 c + 128.46 32.187 129.97 36.453 130.03 41.9 c + h + 119.2 50.49 m + 119.987 49.45 120.567 48.237 120.94 46.85 c + 121.311 45.443 121.486 43.797 121.466 41.91 c + 121.445 39.89 121.205 38.177 120.748 36.77 c + 120.291 35.363 119.701 34.227 118.978 33.36 c + 118.238 32.467 117.388 31.823 116.428 31.43 c + 115.481 31.037 114.495 30.849 113.468 30.865 c + 112.428 30.881 111.445 31.092 110.518 31.498 c + 109.611 31.904 108.775 32.564 108.008 33.478 c + 107.301 34.331 106.728 35.508 106.288 37.008 c + 105.861 38.495 105.657 40.215 105.678 42.168 c + 105.699 44.175 105.931 45.881 106.375 47.288 c + 106.832 48.681 107.422 49.818 108.145 50.698 c + 108.865 51.578 109.708 52.221 110.675 52.628 c + 111.635 53.035 112.645 53.231 113.705 53.215 c + 114.758 53.199 115.762 52.973 116.715 52.536 c + 117.668 52.085 118.495 51.401 119.195 50.486 c + f + 154 34.9 m + 153.991 34.053 153.819 33.333 153.485 32.74 c + 153.15 32.142 152.58 31.675 151.775 31.34 c + 151.216 31.107 150.566 30.974 149.825 30.94 c + 149.085 30.891 148.222 30.874 147.235 30.889 c + 144.255 30.934 l + 144.35 39.994 l + 146.88 39.956 l + 148.194 39.936 149.294 39.851 150.18 39.702 c + 151.067 39.552 151.807 39.232 152.4 38.741 c + 152.966 38.265 153.376 37.745 153.63 37.181 c + 153.896 36.604 154.023 35.841 154.013 34.891 c + h + 167.1 58.1 m + 157.1 58.253 l + 148.27 46.053 l + 144.48 46.111 l + 144.61 58.411 l + 136.43 58.536 l + 136.076 24.836 l + 149.876 24.626 l + 151.763 24.597 153.386 24.685 154.746 24.891 c + 156.106 25.096 157.383 25.566 158.576 26.301 c + 159.783 27.034 160.743 28.001 161.456 29.201 c + 162.183 30.381 162.556 31.874 162.576 33.681 c + 162.602 36.167 162.072 38.204 160.986 39.791 c + 159.919 41.377 158.376 42.704 156.356 43.771 c + f + 212 34.4 m + 212.016 35.907 211.782 37.387 211.297 38.84 c + 210.812 40.28 210.112 41.497 209.197 42.49 c + 207.937 43.837 206.527 44.86 204.967 45.56 c + 203.42 46.26 201.48 46.63 199.147 46.67 c + 194.027 46.748 l + 194.142 57.748 l + 185.922 57.873 l + 185.568 24.173 l + 199.068 23.967 l + 201.095 23.936 202.801 24.098 204.188 24.454 c + 205.588 24.795 206.828 25.325 207.908 26.044 c + 209.201 26.911 210.191 28.034 210.878 29.414 c + 211.578 30.787 211.938 32.447 211.958 34.394 c + h + 203.5 34.733 m + 203.49 33.786 203.239 32.976 202.746 32.303 c + 202.253 31.616 201.683 31.143 201.036 30.883 c + 200.176 30.534 199.339 30.351 198.526 30.333 c + 197.713 30.3 196.626 30.294 195.266 30.315 c + 193.856 30.336 l + 193.962 40.436 l + 196.322 40.4 l + 197.722 40.379 198.872 40.271 199.772 40.076 c + 200.685 39.882 201.445 39.508 202.052 38.956 c + 202.575 38.466 202.949 37.886 203.172 37.216 c + 203.407 36.536 203.52 35.713 203.51 34.746 c + f + 246 44.7 m + 246.044 48.86 244.877 52.067 242.5 54.32 c + 240.127 56.573 236.593 57.733 231.9 57.8 c + 227.233 57.871 223.7 56.818 221.3 54.64 c + 218.893 52.46 217.667 49.3 217.62 45.16 c + 217.394 23.66 l + 225.664 23.534 l + 225.885 44.534 l + 225.91 46.867 226.393 48.601 227.335 49.734 c + 228.275 50.867 229.788 51.417 231.875 51.384 c + 233.928 51.353 235.422 50.779 236.355 49.664 c + 237.302 48.551 237.762 46.781 237.735 44.354 c + 237.514 23.354 l + 245.784 23.228 l + f + 281 46.1 m + 281.017 47.727 280.718 49.187 280.103 50.48 c + 279.502 51.773 278.662 52.85 277.583 53.71 c + 276.336 54.723 274.96 55.453 273.453 55.9 c + 271.96 56.345 270.056 56.585 267.743 56.62 c + 253.843 56.832 l + 253.489 23.132 l + 265.889 22.944 l + 268.462 22.905 270.342 22.967 271.529 23.129 c + 272.729 23.292 273.919 23.672 275.099 24.269 c + 276.319 24.898 277.229 25.758 277.829 26.849 c + 278.44 27.922 278.753 29.162 278.768 30.569 c + 278.785 32.196 278.392 33.642 277.588 34.909 c + 276.788 36.156 275.648 36.156 274.168 34.909 c + 276.255 35.314 277.915 36.194 279.148 37.549 c + 280.388 38.902 281.021 40.702 281.048 42.949 c + h + 270.3 32.4 m + 270.3 31.843 270.158 31.286 269.875 30.73 c + 269.612 30.176 269.142 29.769 268.465 29.51 c + 267.863 29.278 267.113 29.161 266.215 29.16 c + 265.328 29.143 264.078 29.147 262.465 29.172 c + 261.694 29.184 l + 261.769 36.304 l + 263.059 36.284 l + 264.359 36.264 265.466 36.225 266.379 36.166 c + 267.292 36.107 268.012 35.945 268.539 35.681 c + 269.279 35.323 269.759 34.87 269.979 34.321 c + 270.202 33.76 270.309 33.116 270.301 32.391 c + h + 272.46 46.1 m + 272.449 45.033 272.24 44.217 271.834 43.65 c + 271.442 43.068 270.772 42.641 269.824 42.37 c + 269.179 42.184 268.293 42.092 267.164 42.094 c + 266.037 42.096 264.861 42.107 263.634 42.125 c + 261.834 42.153 l + 261.922 50.543 l + 262.522 50.534 l + 264.836 50.498 266.492 50.466 267.492 50.435 c + 268.492 50.405 269.412 50.195 270.252 49.805 c + 271.106 49.415 271.686 48.909 271.992 48.285 c + 272.314 47.647 272.471 46.921 272.462 46.105 c + f + 310 55.9 m + 287 56.25 l + 286.646 22.55 l + 294.866 22.425 l + 295.152 49.525 l + 309.952 49.3 l + f + 332 55.6 m + 313.3 55.884 l + 313.237 49.914 l + 318.467 49.834 l + 318.239 28.134 l + 313.009 28.214 l + 312.946 22.244 l + 331.646 21.96 l + 331.709 27.93 l + 326.479 28.01 l + 326.707 49.71 l + 331.937 49.63 l + f + 353 55.9 m + 350.627 55.936 348.43 55.599 346.41 54.89 c + 344.403 54.183 342.67 53.11 341.21 51.67 c + 339.75 50.23 338.61 48.423 337.79 46.25 c + 336.983 44.077 336.563 41.56 336.53 38.7 c + 336.502 36.033 336.855 33.61 337.59 31.43 c + 338.323 29.25 339.403 27.373 340.83 25.8 c + 342.197 24.287 343.897 23.107 345.93 22.26 c + 347.977 21.413 350.213 20.973 352.64 20.94 c + 353.98 20.92 355.187 20.984 356.26 21.134 c + 357.347 21.268 358.347 21.456 359.26 21.699 c + 360.22 21.971 361.087 22.282 361.86 22.632 c + 362.647 22.967 363.337 23.28 363.93 23.573 c + 364.016 31.733 l + 363.074 31.747 l + 362.67 31.392 362.16 30.969 361.544 30.477 c + 360.939 29.989 360.249 29.509 359.474 29.037 c + 358.68 28.567 357.827 28.174 356.914 27.857 c + 355.994 27.54 355.014 27.389 353.974 27.404 c + 352.82 27.422 351.724 27.635 350.684 28.042 c + 349.644 28.435 348.687 29.082 347.814 29.982 c + 346.98 30.856 346.307 32.002 345.794 33.422 c + 345.294 34.849 345.055 36.572 345.077 38.592 c + 345.099 40.699 345.396 42.459 345.968 43.872 c + 346.554 45.279 347.28 46.382 348.148 47.182 c + 349.028 47.996 350.004 48.576 351.078 48.922 c + 352.151 49.252 353.211 49.41 354.258 49.394 c + 355.258 49.379 356.241 49.206 357.208 48.874 c + 358.188 48.543 359.091 48.1 359.918 47.544 c + 360.611 47.096 361.254 46.62 361.848 46.114 c + 362.442 45.608 362.929 45.171 363.308 44.804 c + 364.165 44.791 l + 364.249 52.841 l + 363.456 53.23 362.696 53.597 361.969 53.941 c + 361.243 54.284 360.483 54.582 359.689 54.835 c + 358.649 55.168 357.673 55.424 356.759 55.603 c + 355.846 55.783 354.589 55.885 352.989 55.909 c + f + 130 74.7 m + 129.991 73.853 129.819 73.133 129.485 72.54 c + 129.15 71.942 128.58 71.475 127.775 71.14 c + 127.216 70.907 126.566 70.774 125.825 70.74 c + 125.085 70.691 124.222 70.674 123.235 70.689 c + 120.255 70.734 l + 120.35 79.794 l + 122.88 79.756 l + 124.194 79.736 125.294 79.651 126.18 79.502 c + 127.067 79.352 127.807 79.032 128.4 78.541 c + 128.966 78.065 129.376 77.545 129.63 76.981 c + 129.896 76.404 130.023 75.641 130.013 74.691 c + h + 143.1 97.9 m + 133.1 98.053 l + 124.27 85.853 l + 120.48 85.911 l + 120.61 98.211 l + 112.43 98.336 l + 112.076 64.636 l + 125.876 64.426 l + 127.763 64.397 129.386 64.485 130.746 64.691 c + 132.106 64.896 133.383 65.366 134.576 66.101 c + 135.783 66.834 136.743 67.801 137.456 69.001 c + 138.183 70.181 138.556 71.674 138.576 73.481 c + 138.602 75.967 138.072 78.004 136.986 79.591 c + 135.919 81.177 134.376 82.504 132.356 83.571 c + f + 170 97.4 m + 146.9 97.751 l + 146.546 64.051 l + 169.646 63.7 l + 169.714 70.21 l + 154.814 70.437 l + 154.876 76.247 l + 168.676 76.037 l + 168.744 82.547 l + 154.944 82.757 l + 155.032 91.077 l + 169.932 90.85 l + f + 200 97 m + 177 97.35 l + 176.646 63.65 l + 184.866 63.525 l + 185.152 90.625 l + 199.952 90.4 l + f + 228 96.5 m + 204.9 96.851 l + 204.546 63.151 l + 227.646 62.8 l + 227.714 69.31 l + 212.814 69.537 l + 212.876 75.347 l + 226.676 75.137 l + 226.744 81.647 l + 212.944 81.857 l + 213.032 90.177 l + 227.932 89.95 l + f + 264 96 m + 255.5 96.129 l + 253.22 89.359 l + 241.42 89.539 l + 239.29 96.379 l + 231 96.505 l + 242.4 62.705 l + 251.87 62.561 l + h + 251.2 83.2 m + 247.15 71.2 l + 243.36 83.3 l + f + 294 84.9 m + 294.035 88.213 292.728 90.93 290.08 93.05 c + 287.447 95.157 283.847 96.243 279.28 96.31 c + 276.64 96.35 274.33 96.144 272.35 95.692 c + 270.39 95.225 268.55 94.628 266.83 93.902 c + 266.745 85.832 l + 267.645 85.818 l + 269.358 87.225 271.268 88.295 273.375 89.028 c + 275.495 89.762 277.525 90.115 279.465 90.088 c + 279.965 90.081 280.622 90.025 281.435 89.922 c + 282.248 89.82 282.912 89.659 283.425 89.44 c + 284.05 89.16 284.56 88.813 284.955 88.4 c + 285.365 87.987 285.566 87.38 285.557 86.58 c + 285.549 85.84 285.243 85.21 284.637 84.69 c + 284.046 84.157 283.179 83.757 282.037 83.49 c + 280.837 83.207 279.564 82.948 278.217 82.712 c + 276.884 82.461 275.63 82.141 274.457 81.752 c + 271.764 80.872 269.817 79.659 268.617 78.112 c + 267.43 76.546 266.824 74.596 266.797 72.262 c + 266.764 69.129 268.064 66.556 270.697 64.542 c + 273.344 62.516 276.744 61.469 280.897 61.402 c + 282.997 61.37 285.07 61.557 287.117 61.963 c + 289.177 62.354 290.96 62.861 292.467 63.483 c + 292.549 71.233 l + 291.671 71.247 l + 290.377 70.18 288.791 69.3 286.911 68.607 c + 285.044 67.893 283.141 67.553 281.201 67.587 c + 280.514 67.597 279.831 67.66 279.151 67.777 c + 278.477 67.877 277.831 68.068 277.211 68.349 c + 276.656 68.583 276.183 68.937 275.791 69.409 c + 275.395 69.867 275.201 70.39 275.208 70.979 c + 275.217 71.865 275.545 72.545 276.193 73.019 c + 276.84 73.476 278.057 73.886 279.843 74.249 c + 281.016 74.487 282.139 74.719 283.213 74.944 c + 284.299 75.168 285.466 75.482 286.713 75.885 c + 289.166 76.691 290.976 77.818 292.143 79.265 c + 293.329 80.691 293.936 82.565 293.963 84.885 c + f + 323 95.1 m + 299.9 95.451 l + 299.546 61.751 l + 322.646 61.4 l + 322.714 67.91 l + 307.815 68.137 l + 307.876 73.947 l + 321.676 73.737 l + 321.744 80.247 l + 307.944 80.457 l + 308.032 88.777 l + 322.932 88.55 l + f + `, + NOT_FOR_PUBLIC_RELEASE: `33.5 13.4 m + 404.5 6.92 l + 419.6 6.657 431.9 18.52 432.1 33.62 c + 432.89 78.92 l + 433.153 94.02 421.29 106.32 406.19 106.52 c + 35.19 113 l + 20.09 113.263 7.79 101.4 7.59 86.3 c + 6.8 41 l + 6.537 25.9 18.4 13.6 33.5 13.4 c + s + 140 57.9 m + 132.53 58.021 l + 119.53 35.121 l + 119.759 58.221 l + 112.649 58.336 l + 112.315 24.636 l + 121.585 24.486 l + 132.785 43.586 l + 132.594 24.286 l + 139.704 24.171 l + f + 177 40.5 m + 177.053 45.867 175.723 50.167 173.01 53.4 c + 170.297 56.593 166.53 58.23 161.71 58.31 c + 156.877 58.388 153.077 56.875 150.31 53.77 c + 147.53 50.65 146.113 46.417 146.06 41.07 c + 146.006 35.657 147.336 31.357 150.05 28.17 c + 152.763 24.977 156.53 23.34 161.35 23.26 c + 166.17 23.182 169.97 24.695 172.75 27.8 c + 175.543 30.887 176.967 35.153 177.02 40.6 c + h + 166.8 49.19 m + 167.547 48.15 168.093 46.937 168.44 45.55 c + 168.789 44.143 168.955 42.497 168.936 40.61 c + 168.916 38.59 168.69 36.877 168.259 35.47 c + 167.828 34.063 167.271 32.927 166.589 32.06 c + 165.896 31.167 165.096 30.523 164.189 30.13 c + 163.296 29.737 162.366 29.549 161.399 29.565 c + 160.419 29.581 159.492 29.792 158.619 30.198 c + 157.759 30.604 156.972 31.264 156.259 32.178 c + 155.594 33.031 155.054 34.208 154.639 35.708 c + 154.236 37.195 154.045 38.915 154.064 40.868 c + 154.084 42.875 154.303 44.581 154.721 45.988 c + 155.152 47.381 155.709 48.518 156.391 49.398 c + 157.071 50.278 157.864 50.921 158.771 51.328 c + 159.678 51.735 160.628 51.931 161.621 51.915 c + 162.614 51.899 163.561 51.673 164.461 51.236 c + 165.361 50.785 166.141 50.101 166.801 49.186 c + f + 207 29.7 m + 197.61 29.852 l + 197.879 56.952 l + 190.129 57.077 l + 189.86 29.977 l + 180.47 30.129 l + 180.406 23.619 l + 206.906 23.19 l + f + 247 29 m + 233.2 29.223 l + 233.262 35.483 l + 246.062 35.276 l + 246.127 41.786 l + 233.327 41.993 l + 233.47 56.393 l + 225.76 56.518 l + 225.426 22.818 l + 246.926 22.47 l + f + 282 38.8 m + 282.053 44.167 280.723 48.467 278.01 51.7 c + 275.297 54.893 271.53 56.53 266.71 56.61 c + 261.877 56.688 258.077 55.175 255.31 52.07 c + 252.53 48.95 251.113 44.717 251.06 39.37 c + 251.006 33.957 252.336 29.657 255.05 26.47 c + 257.763 23.277 261.53 21.64 266.35 21.56 c + 271.17 21.482 274.97 22.995 277.75 26.1 c + 280.543 29.187 281.967 33.453 282.02 38.9 c + h + 271.8 47.49 m + 272.547 46.45 273.093 45.237 273.44 43.85 c + 273.789 42.443 273.955 40.797 273.936 38.91 c + 273.916 36.89 273.69 35.177 273.259 33.77 c + 272.828 32.363 272.271 31.227 271.589 30.36 c + 270.896 29.467 270.096 28.823 269.189 28.43 c + 268.296 28.037 267.366 27.849 266.399 27.865 c + 265.419 27.881 264.492 28.092 263.619 28.498 c + 262.759 28.904 261.972 29.564 261.259 30.478 c + 260.594 31.331 260.054 32.508 259.639 34.008 c + 259.236 35.495 259.045 37.215 259.064 39.168 c + 259.084 41.175 259.303 42.881 259.721 44.288 c + 260.152 45.681 260.709 46.818 261.391 47.698 c + 262.071 48.578 262.864 49.221 263.771 49.628 c + 264.678 50.035 265.628 50.231 266.621 50.215 c + 267.614 50.199 268.561 49.973 269.461 49.536 c + 270.361 49.085 271.141 48.401 271.801 47.486 c + f + 304 31.9 m + 303.992 31.053 303.83 30.333 303.514 29.74 c + 303.199 29.142 302.662 28.675 301.904 28.34 c + 301.377 28.107 300.763 27.974 300.064 27.94 c + 299.364 27.891 298.551 27.874 297.624 27.889 c + 294.814 27.934 l + 294.904 36.994 l + 297.284 36.956 l + 298.524 36.936 299.561 36.851 300.394 36.702 c + 301.227 36.552 301.924 36.232 302.484 35.741 c + 303.018 35.265 303.405 34.745 303.644 34.181 c + 303.894 33.604 304.014 32.841 304.005 31.891 c + h + 316.3 55.1 m + 306.83 55.253 l + 298.51 43.053 l + 294.94 43.111 l + 295.062 55.411 l + 287.352 55.536 l + 287.018 21.836 l + 300.018 21.626 l + 301.791 21.597 303.321 21.685 304.608 21.891 c + 305.888 22.096 307.091 22.566 308.218 23.301 c + 309.358 24.034 310.261 25.001 310.928 26.201 c + 311.615 27.381 311.965 28.874 311.978 30.681 c + 312.003 33.167 311.506 35.204 310.488 36.791 c + 309.481 38.377 308.028 39.704 306.128 40.771 c + f + 52 75.7 m + 52.015 77.207 51.794 78.687 51.337 80.14 c + 50.88 81.58 50.22 82.797 49.357 83.79 c + 48.17 85.137 46.84 86.16 45.367 86.86 c + 43.907 87.56 42.08 87.93 39.887 87.97 c + 35.057 88.048 l + 35.166 99.048 l + 27.416 99.173 l + 27.082 65.473 l + 39.882 65.267 l + 41.795 65.236 43.405 65.398 44.712 65.754 c + 46.032 66.095 47.202 66.625 48.222 67.344 c + 49.442 68.211 50.375 69.334 51.022 70.714 c + 51.682 72.087 52.022 73.747 52.042 75.694 c + h + 43.99 76.033 m + 43.981 75.086 43.744 74.276 43.279 73.603 c + 42.814 72.916 42.278 72.443 41.669 72.183 c + 40.856 71.834 40.066 71.651 39.299 71.633 c + 38.532 71.6 37.509 71.594 36.229 71.615 c + 34.899 71.636 l + 34.999 81.736 l + 37.219 81.7 l + 38.539 81.679 39.622 81.571 40.469 81.376 c + 41.329 81.182 42.046 80.808 42.619 80.256 c + 43.112 79.766 43.462 79.186 43.669 78.516 c + 43.891 77.836 43.997 77.013 43.988 76.046 c + f + 83.9 86 m + 83.941 90.16 82.841 93.367 80.6 95.62 c + 78.36 97.873 75.04 99.033 70.64 99.1 c + 66.24 99.171 62.907 98.118 60.64 95.94 c + 58.373 93.76 57.217 90.6 57.17 86.46 c + 56.957 64.96 l + 64.747 64.834 l + 64.955 85.834 l + 64.978 88.167 65.431 89.901 66.315 91.034 c + 67.202 92.167 68.628 92.717 70.595 92.684 c + 72.535 92.653 73.942 92.079 74.815 90.964 c + 75.708 89.851 76.142 88.081 76.115 85.654 c + 75.907 64.654 l + 83.697 64.528 l + f + 117 87.3 m + 117.016 88.927 116.734 90.387 116.155 91.68 c + 115.589 92.973 114.799 94.05 113.785 94.91 c + 112.612 95.923 111.312 96.653 109.885 97.1 c + 108.478 97.545 106.685 97.785 104.505 97.82 c + 91.405 98.032 l + 91.071 64.332 l + 102.771 64.144 l + 105.191 64.105 106.961 64.167 108.081 64.329 c + 109.214 64.492 110.334 64.872 111.441 65.469 c + 112.594 66.098 113.451 66.958 114.011 68.049 c + 114.587 69.122 114.882 70.362 114.896 71.769 c + 114.912 73.396 114.542 74.842 113.786 76.109 c + 113.033 77.356 111.959 77.356 110.566 76.109 c + 112.533 76.514 114.096 77.394 115.256 78.749 c + 116.429 80.102 117.026 81.902 117.046 84.149 c + h + 106.9 73.6 m + 106.9 73.043 106.767 72.486 106.5 71.93 c + 106.252 71.376 105.812 70.969 105.18 70.71 c + 104.612 70.478 103.905 70.361 103.06 70.36 c + 102.227 70.343 101.05 70.347 99.53 70.372 c + 98.803 70.384 l + 98.874 77.504 l + 100.084 77.484 l + 101.31 77.464 102.354 77.425 103.214 77.366 c + 104.074 77.307 104.75 77.145 105.244 76.881 c + 105.937 76.523 106.39 76.07 106.604 75.521 c + 106.814 74.96 106.915 74.316 106.908 73.591 c + h + 108.93 87.3 m + 108.919 86.233 108.723 85.417 108.34 84.85 c + 107.971 84.268 107.341 83.841 106.45 83.57 c + 105.843 83.384 105.006 83.292 103.94 83.294 c + 102.873 83.296 101.763 83.307 100.61 83.325 c + 98.91 83.353 l + 98.993 91.743 l + 99.558 91.733 l + 101.738 91.698 103.298 91.666 104.238 91.635 c + 105.178 91.605 106.045 91.395 106.838 91.005 c + 107.645 90.615 108.191 90.109 108.478 89.485 c + 108.781 88.847 108.929 88.121 108.921 87.305 c + f + 144 97.2 m + 122.3 97.55 l + 121.966 63.85 l + 129.716 63.725 l + 129.985 90.825 l + 143.885 90.6 l + f + 165 96.9 m + 147.4 97.184 l + 147.341 91.214 l + 152.271 91.134 l + 152.056 69.434 l + 147.126 69.514 l + 147.067 63.544 l + 164.667 63.26 l + 164.726 69.23 l + 159.796 69.31 l + 160.011 91.01 l + 164.941 90.93 l + f + 185 97.2 m + 182.767 97.236 180.697 96.899 178.79 96.19 c + 176.897 95.483 175.263 94.41 173.89 92.97 c + 172.517 91.53 171.443 89.723 170.67 87.55 c + 169.91 85.377 169.513 82.86 169.48 80 c + 169.454 77.333 169.786 74.91 170.478 72.73 c + 171.171 70.55 172.188 68.673 173.528 67.1 c + 174.821 65.587 176.425 64.407 178.338 63.56 c + 180.271 62.713 182.381 62.273 184.668 62.24 c + 185.935 62.22 187.071 62.284 188.078 62.434 c + 189.105 62.568 190.048 62.756 190.908 62.999 c + 191.815 63.271 192.631 63.582 193.358 63.932 c + 194.105 64.267 194.755 64.58 195.308 64.873 c + 195.389 73.033 l + 194.501 73.047 l + 194.12 72.692 193.637 72.269 193.051 71.777 c + 192.481 71.289 191.831 70.809 191.101 70.337 c + 190.354 69.867 189.551 69.474 188.691 69.157 c + 187.824 68.84 186.901 68.689 185.921 68.704 c + 184.828 68.722 183.794 68.935 182.821 69.342 c + 181.841 69.735 180.938 70.382 180.111 71.282 c + 179.324 72.156 178.691 73.302 178.211 74.722 c + 177.74 76.149 177.515 77.872 177.535 79.892 c + 177.556 81.999 177.836 83.759 178.375 85.172 c + 178.928 86.579 179.611 87.682 180.425 88.482 c + 181.252 89.296 182.172 89.876 183.185 90.222 c + 184.198 90.552 185.195 90.71 186.175 90.694 c + 187.115 90.679 188.042 90.506 188.955 90.174 c + 189.882 89.843 190.732 89.4 191.505 88.844 c + 192.16 88.396 192.767 87.92 193.325 87.414 c + 193.886 86.908 194.346 86.471 194.705 86.104 c + 195.513 86.091 l + 195.593 94.141 l + 194.846 94.53 194.129 94.897 193.443 95.241 c + 192.763 95.584 192.046 95.882 191.293 96.135 c + 190.313 96.468 189.393 96.724 188.533 96.903 c + f + 232 72.4 m + 231.992 71.553 231.83 70.833 231.514 70.24 c + 231.199 69.642 230.662 69.175 229.904 68.84 c + 229.377 68.607 228.763 68.474 228.064 68.44 c + 227.364 68.391 226.551 68.374 225.624 68.389 c + 222.814 68.434 l + 222.904 77.494 l + 225.284 77.456 l + 226.524 77.436 227.56 77.351 228.394 77.202 c + 229.227 77.052 229.924 76.732 230.484 76.241 c + 231.018 75.765 231.404 75.245 231.644 74.681 c + 231.894 74.104 232.014 73.341 232.005 72.391 c + h + 244.3 95.6 m + 234.83 95.753 l + 226.51 83.553 l + 222.94 83.611 l + 223.062 95.911 l + 215.352 96.036 l + 215.018 62.336 l + 228.018 62.126 l + 229.791 62.097 231.321 62.185 232.608 62.391 c + 233.888 62.596 235.091 63.066 236.218 63.801 c + 237.358 64.534 238.261 65.501 238.928 66.701 c + 239.615 67.881 239.965 69.374 239.978 71.181 c + 240.003 73.667 239.506 75.704 238.488 77.291 c + 237.481 78.877 236.028 80.204 234.128 81.271 c + f + 270 95.2 m + 248.3 95.551 l + 247.966 61.851 l + 269.666 61.5 l + 269.731 68.01 l + 255.731 68.237 l + 255.788 74.047 l + 268.788 73.837 l + 268.853 80.347 l + 255.853 80.557 l + 255.935 88.877 l + 269.935 88.65 l + f + 298 94.7 m + 276.3 95.05 l + 275.966 61.35 l + 283.716 61.225 l + 283.985 88.325 l + 297.885 88.1 l + f + 324 94.3 m + 302.3 94.651 l + 301.966 60.951 l + 323.666 60.6 l + 323.731 67.11 l + 309.731 67.337 l + 309.788 73.147 l + 322.788 72.937 l + 322.853 79.447 l + 309.853 79.657 l + 309.935 87.977 l + 323.935 87.75 l + f + 359 93.7 m + 350.99 93.829 l + 348.84 87.059 l + 337.74 87.239 l + 335.73 94.079 l + 327.92 94.205 l + 338.72 60.405 l + 347.64 60.261 l + h + 346.9 80.9 m + 343.09 68.9 l + 339.52 81 l + f + 387 82.7 m + 387.033 86.013 385.8 88.73 383.3 90.85 c + 380.82 92.957 377.42 94.043 373.1 94.11 c + 370.613 94.15 368.437 93.944 366.57 93.492 c + 364.723 93.025 362.987 92.428 361.36 91.702 c + 361.28 83.632 l + 362.128 83.618 l + 363.741 85.025 365.541 86.095 367.528 86.828 c + 369.528 87.562 371.445 87.915 373.278 87.888 c + 373.749 87.881 374.369 87.825 375.138 87.722 c + 375.905 87.62 376.528 87.459 377.008 87.24 c + 377.597 86.96 378.077 86.613 378.448 86.2 c + 378.834 85.787 379.023 85.18 379.016 84.38 c + 379.009 83.64 378.72 83.01 378.149 82.49 c + 377.592 81.957 376.772 81.557 375.689 81.29 c + 374.556 81.007 373.356 80.748 372.089 80.512 c + 370.836 80.261 369.656 79.941 368.549 79.552 c + 366.009 78.672 364.172 77.459 363.039 75.912 c + 361.919 74.346 361.349 72.396 361.329 70.062 c + 361.298 66.929 362.525 64.356 365.009 62.342 c + 367.509 60.316 370.729 59.269 374.669 59.202 c + 376.649 59.17 378.602 59.357 380.529 59.763 c + 382.469 60.154 384.149 60.661 385.569 61.283 c + 385.646 69.033 l + 384.818 69.047 l + 383.598 67.98 382.101 67.1 380.328 66.407 c + 378.568 65.693 376.775 65.353 374.948 65.387 c + 374.302 65.397 373.655 65.46 373.008 65.577 c + 372.376 65.677 371.766 65.868 371.178 66.149 c + 370.655 66.383 370.209 66.737 369.838 67.209 c + 369.465 67.667 369.282 68.19 369.288 68.779 c + 369.297 69.665 369.606 70.345 370.217 70.819 c + 370.827 71.276 371.974 71.686 373.657 72.049 c + 374.764 72.287 375.824 72.519 376.837 72.744 c + 377.864 72.968 378.964 73.282 380.137 73.685 c + 382.444 74.491 384.15 75.618 385.257 77.065 c + 386.377 78.491 386.947 80.365 386.967 82.685 c + f + 414 92.9 m + 392.3 93.251 l + 391.966 59.551 l + 413.666 59.2 l + 413.731 65.71 l + 399.731 65.937 l + 399.788 71.747 l + 412.788 71.537 l + 412.853 78.047 l + 399.853 78.257 l + 399.935 86.577 l + 413.935 86.35 l + f + `, +}; +const standardStampCreationInfos = { + "/Draft": { + textStreamData: standardStampForms.DRAFT, + color: standardStampColors.redColor, + subject: "Draft", + bbox: standardStampBBox, + rect: standardStampRect, + }, + "/Approved": { + textStreamData: standardStampForms.APPROVED, + color: standardStampColors.greenColor, + subject: "Approved", + bbox: standardStampBBox, + rect: standardStampRect, + }, + "/NotApproved": { + textStreamData: standardStampForms.NOT_APPROVED, + color: standardStampColors.redColor, + subject: "Not Approved", + bbox: standardStampBBox, + rect: standardStampRect, + }, + "/Departmental": { + textStreamData: standardStampForms.DEPARTMENTAL, + color: standardStampColors.blueColor, + subject: "Departmental", + bbox: standardStampBBox, + rect: standardStampRect, + }, + "/Confidential": { + textStreamData: standardStampForms.CONFIDENTIAL, + color: standardStampColors.redColor, + subject: "Confidential", + bbox: standardStampBBox, + rect: standardStampRect, + }, + "/Final": { + textStreamData: standardStampForms.FINAL, + color: standardStampColors.redColor, + subject: "Final", + bbox: standardStampBBox, + rect: standardStampRect, + }, + "/Expired": { + textStreamData: standardStampForms.EXPIRED, + color: standardStampColors.redColor, + subject: "Expired", + bbox: standardStampBBox, + rect: standardStampRect, + }, + "/AsIs": { + textStreamData: standardStampForms.AS_IS, + color: standardStampColors.redColor, + subject: "As Is", + bbox: standardStampBBox, + rect: standardStampRect, + }, + "/Sold": { + textStreamData: standardStampForms.SOLD, + color: standardStampColors.blueColor, + subject: "Sold", + bbox: standardStampBBox, + rect: standardStampRect, + }, + "/Experimental": { + textStreamData: standardStampForms.EXPERIMENTAL, + color: standardStampColors.blueColor, + subject: "Experimental", + bbox: standardStampBBox, + rect: standardStampRect, + }, + "/ForComment": { + textStreamData: standardStampForms.FOR_COMMENT, + color: standardStampColors.greenColor, + subject: "For Comment", + bbox: standardStampBBox, + rect: standardStampRect, + }, + "/TopSecret": { + textStreamData: standardStampForms.TOP_SECRET, + color: standardStampColors.redColor, + subject: "Top Secret", + bbox: standardStampBBox, + rect: standardStampRect, + }, + "/ForPublicRelease": { + textStreamData: standardStampForms.FOR_PUBLIC_RELEASE, + color: standardStampColors.greenColor, + subject: "For Public Release", + bbox: standardStampBBox, + rect: standardStampRect, + }, + "/NotForPublicRelease": { + textStreamData: standardStampForms.NOT_FOR_PUBLIC_RELEASE, + color: standardStampColors.redColor, + subject: "Not For Public Release", + bbox: standardStampBBox, + rect: standardStampRect, + }, +}; + +var __awaiter$E = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class StampAnnotation extends MarkupAnnotation { + constructor() { + super(annotationTypes.STAMP); + this.Name = stampTypes.DRAFT; + this.IT = "/Stamp"; + } + static createFromDto(dto) { + var _a; + if (dto.annotationType !== "/Stamp") { + throw new Error("Invalid annotation type"); + } + const created = DateString.fromDate(new Date(dto.dateCreated)); + const modified = DateString.fromDate(new Date(dto.dateModified)); + const apStream = new XFormStream(); + apStream.LastModified = modified; + apStream.Filter = "/FlateDecode"; + apStream.Resources = new ResourceDict(); + apStream.Matrix = dto.matrix || [1, 0, 0, 1, 0, 0]; + const annotation = new StampAnnotation(); + annotation.$name = dto.uuid; + annotation.NM = LiteralString.fromString(dto.uuid); + annotation.T = LiteralString.fromString(dto.author || "unknown"); + annotation.M = modified; + annotation.CreationDate = created; + annotation.Name = dto.stampType; + annotation.apStream = apStream; + const stampCreationInfo = standardStampCreationInfos[dto.stampType]; + if (stampCreationInfo) { + const stampForm = new XFormStream(); + stampForm.LastModified = modified; + stampForm.Filter = "/FlateDecode"; + stampForm.setTextStreamData(stampCreationInfo.textStreamData); + const color = stampCreationInfo.color; + const subject = stampCreationInfo.subject; + const bBox = stampCreationInfo.bbox; + const rect = dto.rect || stampCreationInfo.rect || stampCreationInfo.bbox; + stampForm.BBox = bBox; + const r = color[0].toFixed(3); + const g = color[1].toFixed(3); + const b = color[2].toFixed(3); + const colorString = `${r} ${g} ${b} rg ${r} ${g} ${b} RG`; + apStream.BBox = bBox; + apStream.Resources.setXObject("/Fm", stampForm); + apStream.setTextStreamData(`q 1 0 0 -1 0 ${bBox[3]} cm ${colorString} 1 j 8.58 w /Fm Do Q`); + annotation.Rect = rect; + annotation.Subj = LiteralString.fromString(subject); + annotation.Contents = dto.textContent + ? LiteralString.fromString(dto.textContent) + : annotation.Subj; + annotation.C = color; + annotation.CA = 1; + } + else if (((_a = dto.stampImageData) === null || _a === void 0 ? void 0 : _a.length) && !(dto.stampImageData.length % 4)) { + const data = new Uint8Array(dto.stampImageData); + annotation._customImageData = data; + const stampMask = new ImageStream(); + const stampMaskDecodeParams = new DecodeParamsDict(); + stampMaskDecodeParams.setIntProp("/Predictor", 12); + stampMaskDecodeParams.setIntProp("/Colors", 1); + stampMaskDecodeParams.setIntProp("/BitsPerComponent", 8); + stampMaskDecodeParams.setIntProp("/Columns", dto.bbox[2]); + stampMask.DecodeParms = stampMaskDecodeParams; + stampMask.Filter = "/FlateDecode"; + stampMask.BitsPerComponent = 8; + stampMask.Width = dto.bbox[2]; + stampMask.Height = dto.bbox[3]; + stampMask.ColorSpace = colorSpaces.GRAYSCALE; + stampMask.streamData = data.filter((v, i) => (i + 1) % 4 === 0); + const stampImage = new ImageStream(); + const stampImageDecodeParams = new DecodeParamsDict(); + stampImageDecodeParams.setIntProp("/Predictor", 12); + stampImageDecodeParams.setIntProp("/Colors", 3); + stampImageDecodeParams.setIntProp("/BitsPerComponent", 8); + stampImageDecodeParams.setIntProp("/Columns", dto.bbox[2]); + stampImage.DecodeParms = stampImageDecodeParams; + stampImage.Filter = "/FlateDecode"; + stampImage.BitsPerComponent = 8; + stampImage.Width = dto.bbox[2]; + stampImage.Height = dto.bbox[3]; + stampImage.ColorSpace = colorSpaces.RGB; + stampImage.streamData = data.filter((v, i) => (i + 1) % 4 !== 0); + stampImage.sMask = stampMask; + apStream.BBox = dto.bbox; + apStream.Resources.setXObject("/Im", stampImage); + apStream.setTextStreamData(`q ${dto.bbox[2]} 0 0 ${dto.bbox[3]} 0 0 cm /Im Do Q`); + annotation.Rect = dto.rect; + annotation.Subj = dto.stampSubject + ? LiteralString.fromString(dto.stampSubject) + : LiteralString.fromString(dto.stampType); + annotation.Contents = dto.textContent + ? LiteralString.fromString(dto.textContent) + : annotation.Subj; + } + else { + throw new Error("Custom stamp has no valid image data"); + } + annotation._added = true; + return annotation.initProxy(); + } + static parseAsync(parseInfo) { + return __awaiter$E(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new StampAnnotation(); + yield pdfObject.parsePropsAsync(parseInfo); + return { + value: pdfObject.initProxy(), + start: parseInfo.bounds.start, + end: parseInfo.bounds.end, + }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.Name) { + bytes.push(...encoder.encode("/Name "), ...encoder.encode(this.Name)); + } + if (this.IT) { + bytes.push(...encoder.encode("/IT "), ...encoder.encode(this.IT)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + toDto() { + var _a, _b, _c, _d, _e, _f; + return { + annotationType: "/Stamp", + uuid: this.$name, + pageId: this.$pageId, + dateCreated: ((_a = this.CreationDate) === null || _a === void 0 ? void 0 : _a.date.toISOString()) || new Date().toISOString(), + dateModified: this.M + ? this.M instanceof LiteralString + ? this.M.literal + : this.M.date.toISOString() + : new Date().toISOString(), + author: (_b = this.T) === null || _b === void 0 ? void 0 : _b.literal, + textContent: (_c = this.Contents) === null || _c === void 0 ? void 0 : _c.literal, + rect: this.Rect, + bbox: (_d = this.apStream) === null || _d === void 0 ? void 0 : _d.BBox, + matrix: (_e = this.apStream) === null || _e === void 0 ? void 0 : _e.Matrix, + stampType: this.Name, + stampSubject: (_f = this.Subj) === null || _f === void 0 ? void 0 : _f.literal, + stampImageData: this._customImageData ? [...this._customImageData] : null, + }; + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$E(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/Name": + i = yield this.parseNamePropAsync(name, parser, i); + break; + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + if (!this.Name) { + throw new Error("Not all required properties parsed"); + } + }); + } + initProxy() { + return super.initProxy(); + } + getProxy() { + return super.getProxy(); + } +} + +var __awaiter$D = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +const textNoteForms = { + NOTE: `25 10 m + 175 10 l + 175 10 190 10 190 25 c + 190 135 l + 190 135 190 150 175 150 c + 95 150 l + 10 190 l + 35 150 l + 25 150 l + 25 150 10 150 10 135 c + 10 25 l + 10 25 10 10 25 10 c + b + 35 35 m + 165 35 l + S + 35 55 m + 165 55 l + S + 35 75 m + 125 75 l + S + 35 95 m + 165 95 l + S + 35 115 m + 115 115 l + S + `, +}; +const textNoteCreationInfos = { + "/Note": { + textStreamData: textNoteForms.NOTE, + fillColor: [1, 1, 0.4], + subject: "Note", + bBox: [0, 0, 200, 200], + rect: [0, 0, 25, 25], + }, +}; +class TextAnnotation extends MarkupAnnotation { + constructor() { + super(annotationTypes.TEXT); + this.Open = false; + this.Name = annotationIconTypes.NOTE; + } + static createStandard(userName, color, type = annotationIconTypes.NOTE) { + const nowString = new Date().toISOString(); + const dto = { + uuid: UUID.getRandomUuid(), + annotationType: "/Text", + pageId: null, + dateCreated: nowString, + dateModified: nowString, + author: userName || "unknown", + textContent: null, + rect: null, + matrix: null, + color, + textNoteType: type, + }; + return this.createFromDto(dto); + } + static createFromDto(dto) { + if (dto.annotationType !== "/Text") { + throw new Error("Invalid annotation type"); + } + const created = DateString.fromDate(new Date(dto.dateCreated)); + const modified = DateString.fromDate(new Date(dto.dateModified)); + const stampForm = new XFormStream(); + stampForm.LastModified = modified; + stampForm.Filter = "/FlateDecode"; + const stampCreationInfo = textNoteCreationInfos[dto.textNoteType]; + if (!stampCreationInfo) { + throw new Error(`Stamp type '${dto.textNoteType}' is not supported`); + } + stampForm.setTextStreamData(stampCreationInfo.textStreamData); + const strokeColor = dto.color; + const fillColor = stampCreationInfo.fillColor; + const subject = stampCreationInfo.subject; + const bBox = stampCreationInfo.bBox; + stampForm.BBox = bBox; + const strokeR = strokeColor[0].toFixed(3); + const strokeG = strokeColor[1].toFixed(3); + const strokeB = strokeColor[2].toFixed(3); + const fillR = fillColor[0].toFixed(3); + const fillG = fillColor[1].toFixed(3); + const fillB = fillColor[2].toFixed(3); + const strokeString = `${fillR} ${fillG} ${fillB} rg ${strokeR} ${strokeG} ${strokeB} RG`; + const apStream = new XFormStream(); + apStream.LastModified = modified; + apStream.BBox = bBox; + apStream.Matrix = dto.matrix || [1, 0, 0, 1, 0, 0]; + apStream.Resources = new ResourceDict(); + apStream.Resources.setXObject("/Fm", stampForm); + apStream.Filter = "/FlateDecode"; + apStream.setTextStreamData(`q 1 0 0 -1 0 ${bBox[3]} cm ${strokeString} 1 j 8.58 w /Fm Do Q`); + const annotation = new TextAnnotation(); + annotation.$name = dto.uuid; + annotation.NM = LiteralString.fromString(dto.uuid); + annotation.T = LiteralString.fromString(dto.author || "unknown"); + annotation.M = modified; + annotation.CreationDate = created; + annotation.Contents = dto.textContent + ? LiteralString.fromString(dto.textContent) + : LiteralString.fromString(subject); + annotation.Subj = LiteralString.fromString(subject); + annotation.Name = dto.textNoteType; + annotation.State = dto.textNoteState; + annotation.StateModel = dto.textNoteStateModel; + annotation.Rect = dto.rect || stampCreationInfo.rect; + annotation.C = strokeColor; + annotation.CA = 1; + annotation.apStream = apStream; + annotation._added = true; + return annotation.initProxy(); + } + static parseAsync(parseInfo) { + return __awaiter$D(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new TextAnnotation(); + yield pdfObject.parsePropsAsync(parseInfo); + return { + value: pdfObject.initProxy(), + start: parseInfo.bounds.start, + end: parseInfo.bounds.end, + }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.Open) { + bytes.push(...encoder.encode("/Open "), ...encoder.encode(" " + this.Open)); + } + if (this.Name) { + bytes.push(...encoder.encode("/Name "), ...encoder.encode(this.Name)); + } + if (this.State) { + bytes.push(...encoder.encode("/State "), ...encoder.encode(this.State)); + } + if (this.StateModel) { + bytes.push(...encoder.encode("/StateModel "), ...encoder.encode(this.StateModel)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + toDto() { + var _a, _b, _c, _d, _e; + const color = this.getColorRect(); + return { + annotationType: "/Text", + uuid: this.$name, + pageId: this.$pageId, + dateCreated: ((_a = this.CreationDate) === null || _a === void 0 ? void 0 : _a.date.toISOString()) || new Date().toISOString(), + dateModified: this.M + ? this.M instanceof LiteralString + ? this.M.literal + : this.M.date.toISOString() + : new Date().toISOString(), + author: (_b = this.T) === null || _b === void 0 ? void 0 : _b.literal, + textContent: (_c = this.Contents) === null || _c === void 0 ? void 0 : _c.literal, + rect: this.Rect, + bbox: (_d = this.apStream) === null || _d === void 0 ? void 0 : _d.BBox, + matrix: (_e = this.apStream) === null || _e === void 0 ? void 0 : _e.Matrix, + color, + textNoteType: this.Name, + textNoteState: this.State, + textNoteStateModel: this.StateModel, + }; + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$D(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/Open": + i = yield this.parseBoolPropAsync(name, parser, i); + break; + case "/Name": + const iconType = yield parser.parseNameAtAsync(i, true); + if (iconType && Object.values(annotationIconTypes) + .includes(iconType.value)) { + this.Name = iconType.value; + i = iconType.end + 1; + } + else { + throw new Error("Can't parse /Name property value"); + } + break; + case "/State": + const state = yield parser.parseNameAtAsync(i, true); + if (state && Object.values(annotationMarkedStates) + .concat(Object.values(annotationReviewStates)) + .includes(state.value)) { + this.State = state.value; + i = state.end + 1; + } + else { + throw new Error("Can't parse /State property value"); + } + break; + case "/StateModel": + const stateModelType = yield parser.parseNameAtAsync(i, true); + if (stateModelType && Object.values(annotationStateModelTypes) + .includes(stateModelType.value)) { + this.StateModel = stateModelType.value; + i = stateModelType.end + 1; + } + else { + throw new Error("Can't parse /StateModel property value"); + } + break; + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + }); + } + renderHandles() { + return []; + } + initProxy() { + return super.initProxy(); + } + getProxy() { + return super.getProxy(); + } +} + +var __awaiter$C = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class InkAnnotation extends MarkupAnnotation { + constructor() { + super(annotationTypes.INK); + } + static createFromDto(dto) { + if (dto.annotationType !== "/Ink") { + throw new Error("Invalid annotation type"); + } + const bs = new BorderStyleDict(); + bs.W = dto.strokeWidth; + if (dto.strokeDashGap) { + bs.D = dto.strokeDashGap; + } + const annotation = new InkAnnotation(); + annotation.$name = dto.uuid; + annotation.NM = LiteralString.fromString(dto.uuid); + annotation.T = LiteralString.fromString(dto.author); + annotation.M = DateString.fromDate(new Date(dto.dateModified)); + annotation.CreationDate = DateString.fromDate(new Date(dto.dateCreated)); + annotation.Contents = dto.textContent + ? LiteralString.fromString(dto.textContent) + : null; + annotation.InkList = dto.inkList; + annotation.Rect = dto.rect; + annotation.C = dto.color.slice(0, 3); + annotation.CA = dto.color[3]; + annotation.BS = bs; + annotation.generateApStream(); + annotation._added = true; + return annotation.initProxy(); + } + static parseAsync(parseInfo) { + return __awaiter$C(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new InkAnnotation(); + yield pdfObject.parsePropsAsync(parseInfo); + return { + value: pdfObject.initProxy(), + start: parseInfo.bounds.start, + end: parseInfo.bounds.end, + }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.InkList) { + bytes.push(...encoder.encode("/InkList "), ...this.encodeNestedPrimitiveArray(this.InkList)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + toDto() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l; + const color = this.getColorRect(); + return { + annotationType: "/Ink", + uuid: this.$name, + pageId: this.$pageId, + dateCreated: ((_a = this.CreationDate) === null || _a === void 0 ? void 0 : _a.date.toISOString()) || new Date().toISOString(), + dateModified: this.M + ? this.M instanceof LiteralString + ? this.M.literal + : this.M.date.toISOString() + : new Date().toISOString(), + author: (_b = this.T) === null || _b === void 0 ? void 0 : _b.literal, + textContent: (_c = this.Contents) === null || _c === void 0 ? void 0 : _c.literal, + rect: this.Rect, + bbox: (_d = this.apStream) === null || _d === void 0 ? void 0 : _d.BBox, + matrix: (_e = this.apStream) === null || _e === void 0 ? void 0 : _e.Matrix, + inkList: this.InkList, + color, + strokeWidth: (_j = (_g = (_f = this.BS) === null || _f === void 0 ? void 0 : _f.W) !== null && _g !== void 0 ? _g : (_h = this.Border) === null || _h === void 0 ? void 0 : _h.width) !== null && _j !== void 0 ? _j : 1, + strokeDashGap: (_l = (_k = this.BS) === null || _k === void 0 ? void 0 : _k.D) !== null && _l !== void 0 ? _l : [3, 0], + }; + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + var _a; + return __awaiter$C(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/InkList": + i = yield parser.skipEmptyAsync(i); + const inkType = yield parser.getValueTypeAtAsync(i); + if (inkType === valueTypes.ARRAY) { + const inkList = []; + let inkArrayPos = ++i; + while (true) { + const sublist = yield parser.parseNumberArrayAtAsync(inkArrayPos); + if (!sublist) { + break; + } + inkList.push(sublist.value); + inkArrayPos = sublist.end + 1; + } + this.InkList = inkList; + break; + } + throw new Error("Can't parse /InkList property value"); + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + if (!((_a = this.InkList) === null || _a === void 0 ? void 0 : _a.length)) { + throw new Error("Not all required properties parsed"); + } + yield this.bakeRotationAsync(); + }); + } + generateApStream() { + var _a, _b, _c, _d, _e, _f, _g, _h; + const apStream = new XFormStream(); + apStream.Filter = "/FlateDecode"; + apStream.LastModified = DateString.fromDate(new Date()); + apStream.BBox = [this.Rect[0], this.Rect[1], this.Rect[2], this.Rect[3]]; + const opacity = this.CA || 1; + const strokeWidth = this.strokeWidth; + const strokeDash = (_d = (_b = (_a = this.BS) === null || _a === void 0 ? void 0 : _a.D[0]) !== null && _b !== void 0 ? _b : (_c = this.Border) === null || _c === void 0 ? void 0 : _c.dash) !== null && _d !== void 0 ? _d : 3; + const strokeGap = (_h = (_f = (_e = this.BS) === null || _e === void 0 ? void 0 : _e.D[1]) !== null && _f !== void 0 ? _f : (_g = this.Border) === null || _g === void 0 ? void 0 : _g.gap) !== null && _h !== void 0 ? _h : 0; + const gs = new GraphicsStateDict(); + gs.AIS = true; + gs.BM = "/Normal"; + gs.CA = opacity; + gs.ca = opacity; + gs.LW = strokeWidth; + gs.LJ = lineJoinStyles.ROUND; + gs.LC = lineCapStyles.ROUND; + gs.D = [[strokeDash, strokeGap], 0]; + const colorString = this.getColorString(); + let streamTextData = `q ${colorString} /GS0 gs`; + let px; + let py; + this.InkList.forEach(list => { + px = list[0]; + py = list[1]; + streamTextData += `\n${px} ${py} m`; + for (let i = 2; i < list.length; i = i + 2) { + px = list[i]; + py = list[i + 1]; + streamTextData += `\n${px} ${py} l`; + } + streamTextData += "\nS"; + }); + streamTextData += "\nQ"; + apStream.Resources = new ResourceDict(); + apStream.Resources.setGraphicsState("/GS0", gs); + apStream.setTextStreamData(streamTextData); + this.apStream = apStream; + } + applyCommonTransformAsync(matrix, undoable = true) { + var _a, _b, _c, _d; + return __awaiter$C(this, void 0, void 0, function* () { + const dict = this.getProxy(); + let x; + let y; + let xMin; + let yMin; + let xMax; + let yMax; + const vec = new u(); + dict.InkList.forEach(list => { + for (let i = 0; i < list.length; i = i + 2) { + x = list[i]; + y = list[i + 1]; + vec.set(x, y).applyMat3(matrix); + list[i] = vec.x; + list[i + 1] = vec.y; + if (!xMin || vec.x < xMin) { + xMin = vec.x; + } + if (!yMin || vec.y < yMin) { + yMin = vec.y; + } + if (!xMax || vec.x > xMax) { + xMax = vec.x; + } + if (!yMax || vec.y > yMax) { + yMax = vec.y; + } + } + }); + const margin = ((_d = (_b = (_a = dict.BS) === null || _a === void 0 ? void 0 : _a.W) !== null && _b !== void 0 ? _b : (_c = dict.Border) === null || _c === void 0 ? void 0 : _c.width) !== null && _d !== void 0 ? _d : 1) / 2; + xMin -= margin; + yMin -= margin; + xMax += margin; + yMax += margin; + this.Rect = [xMin, yMin, xMax, yMax]; + if (this._bBox) { + const bBox = dict.getLocalBB(); + bBox.ll.set(xMin, yMin); + bBox.lr.set(xMax, yMin); + bBox.ur.set(xMax, yMax); + bBox.ul.set(xMin, yMax); + } + this.generateApStream(); + dict.M = DateString.fromDate(new Date()); + if (dict.$onEditAction) { + const invertedMat = l.invert(matrix); + dict.$onEditAction(undoable + ? () => __awaiter$C(this, void 0, void 0, function* () { + yield dict.applyCommonTransformAsync(invertedMat, false); + yield dict.updateRenderAsync(); + }) + : undefined); + } + }); + } + bakeRotationAsync() { + return __awaiter$C(this, void 0, void 0, function* () { + const angle = this.getCurrentRotation(); + const centerX = (this.Rect[0] + this.Rect[2]) / 2; + const centerY = (this.Rect[1] + this.Rect[3]) / 2; + const matrix = new l() + .applyTranslation(-centerX, -centerY) + .applyRotation(angle) + .applyTranslation(centerX, centerY); + yield this.applyCommonTransformAsync(matrix); + }); + } + initProxy() { + return super.initProxy(); + } + getProxy() { + return super.getProxy(); + } +} + +var __awaiter$B = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class GeometricAnnotation extends MarkupAnnotation { + constructor(type) { + super(type); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.IC) { + bytes.push(...encoder.encode("/IC "), ...this.encodePrimitiveArray(this.IC, encoder)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$B(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/IC": + i = yield this.parseNumberArrayPropAsync(name, parser, i, true); + break; + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + }); + } +} + +var __awaiter$A = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class SquareAnnotation extends GeometricAnnotation { + constructor() { + super(annotationTypes.SQUARE); + } + static createFromDto(dto) { + if (dto.annotationType !== "/Square") { + throw new Error("Invalid annotation type"); + } + const bs = new BorderStyleDict(); + bs.W = dto.strokeWidth; + if (dto.strokeDashGap) { + bs.D = dto.strokeDashGap; + } + const annotation = new SquareAnnotation(); + annotation.$name = dto.uuid; + annotation.NM = LiteralString.fromString(dto.uuid); + annotation.T = LiteralString.fromString(dto.author); + annotation.M = DateString.fromDate(new Date(dto.dateModified)); + annotation.CreationDate = DateString.fromDate(new Date(dto.dateCreated)); + annotation.Contents = dto.textContent + ? LiteralString.fromString(dto.textContent) + : null; + annotation.Rect = dto.rect; + annotation.RD = dto.rectMargins; + annotation.C = dto.color.slice(0, 3); + annotation.CA = dto.color[3]; + annotation.BS = bs; + annotation._cloud = dto.cloud; + annotation.generateApStream(dto.bbox, dto.matrix); + annotation._added = true; + return annotation.initProxy(); + } + static parseAsync(parseInfo) { + return __awaiter$A(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new SquareAnnotation(); + yield pdfObject.parsePropsAsync(parseInfo); + return { + value: pdfObject.initProxy(), + start: parseInfo.bounds.start, + end: parseInfo.bounds.end, + }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.RD) { + bytes.push(...encoder.encode("/RD "), ...this.encodePrimitiveArray(this.RD, encoder)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + toDto() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l; + const color = this.getColorRect(); + return { + annotationType: "/Square", + uuid: this.$name, + pageId: this.$pageId, + dateCreated: ((_a = this.CreationDate) === null || _a === void 0 ? void 0 : _a.date.toISOString()) || new Date().toISOString(), + dateModified: this.M + ? this.M instanceof LiteralString + ? this.M.literal + : this.M.date.toISOString() + : new Date().toISOString(), + author: (_b = this.T) === null || _b === void 0 ? void 0 : _b.literal, + textContent: (_c = this.Contents) === null || _c === void 0 ? void 0 : _c.literal, + rect: this.Rect, + rectMargins: this.RD, + bbox: (_d = this.apStream) === null || _d === void 0 ? void 0 : _d.BBox, + matrix: (_e = this.apStream) === null || _e === void 0 ? void 0 : _e.Matrix, + cloud: this._cloud, + color, + strokeWidth: (_j = (_g = (_f = this.BS) === null || _f === void 0 ? void 0 : _f.W) !== null && _g !== void 0 ? _g : (_h = this.Border) === null || _h === void 0 ? void 0 : _h.width) !== null && _j !== void 0 ? _j : 1, + strokeDashGap: (_l = (_k = this.BS) === null || _k === void 0 ? void 0 : _k.D) !== null && _l !== void 0 ? _l : [3, 0], + }; + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$A(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/RD": + i = yield this.parseNumberArrayPropAsync(name, parser, i, true); + break; + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + }); + } + generateApStream(bbox, matrix) { + var _a, _b, _c, _d, _e, _f, _g, _h; + const apStream = new XFormStream(); + apStream.Filter = "/FlateDecode"; + apStream.LastModified = DateString.fromDate(new Date()); + const streamBbox = bbox + ? [bbox[0], bbox[1], bbox[2], bbox[3]] + : [this.Rect[0], this.Rect[1], this.Rect[2], this.Rect[3]]; + apStream.BBox = streamBbox; + const streamMatrix = matrix + ? [matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]] + : [1, 0, 0, 1, 0, 0]; + apStream.Matrix = streamMatrix; + const opacity = this.CA || 1; + const strokeWidth = this.strokeWidth; + const strokeDash = (_d = (_b = (_a = this.BS) === null || _a === void 0 ? void 0 : _a.D[0]) !== null && _b !== void 0 ? _b : (_c = this.Border) === null || _c === void 0 ? void 0 : _c.dash) !== null && _d !== void 0 ? _d : 3; + const strokeGap = (_h = (_f = (_e = this.BS) === null || _e === void 0 ? void 0 : _e.D[1]) !== null && _f !== void 0 ? _f : (_g = this.Border) === null || _g === void 0 ? void 0 : _g.gap) !== null && _h !== void 0 ? _h : 0; + const gs = new GraphicsStateDict(); + gs.AIS = true; + gs.BM = "/Normal"; + gs.CA = opacity; + gs.ca = opacity; + gs.LW = strokeWidth; + gs.D = [[strokeDash, strokeGap], 0]; + if (!this.RD) { + const defaultMargin = this._cloud + ? SquareAnnotation.cloudArcSize / 2 + : strokeWidth / 2; + this.RD || (this.RD = [defaultMargin, defaultMargin, defaultMargin, defaultMargin]); + } + const bBoxToRectMat = calcPdfBBoxToRectMatrices(streamBbox, this.Rect, streamMatrix).matAA; + const invMatArray = l.invert(bBoxToRectMat).toFloatShortArray(); + const { r: rotation } = apStream.matrix.getTRS(); + const marginsRotationMat = new l().applyRotation(rotation); + const boxLL = new u(streamBbox[0], streamBbox[1]); + const boxLR = new u(streamBbox[2], streamBbox[1]); + const boxUR = new u(streamBbox[2], streamBbox[3]); + const boxUL = new u(streamBbox[0], streamBbox[3]); + const [marginLeft, marginTop, marginRight, marginBottom] = this.RD; + const marginLL = new u(marginLeft, marginBottom).applyMat3(marginsRotationMat); + const marginLR = new u(-marginRight, marginBottom).applyMat3(marginsRotationMat); + const marginUR = new u(-marginRight, -marginTop).applyMat3(marginsRotationMat); + const marginUL = new u(marginLeft, -marginTop).applyMat3(marginsRotationMat); + const trBoxLL = u.applyMat3(boxLL, bBoxToRectMat).add(marginLL); + const trBoxLR = u.applyMat3(boxLR, bBoxToRectMat).add(marginLR); + const trBoxUR = u.applyMat3(boxUR, bBoxToRectMat).add(marginUR); + const trBoxUL = u.applyMat3(boxUL, bBoxToRectMat).add(marginUL); + const colorString = this.getColorString(); + let streamTextData = `q ${colorString} /GS0 gs`; + streamTextData += `\n${invMatArray[0]} ${invMatArray[1]} ${invMatArray[2]} ${invMatArray[3]} ${invMatArray[4]} ${invMatArray[5]} cm`; + if (this._cloud) { + gs.LC = lineCapStyles.ROUND; + gs.LJ = lineJoinStyles.ROUND; + const curveData = CloudCurveData.buildFromPolyline([ + trBoxLL.clone(), + trBoxLR.clone(), + trBoxUR.clone(), + trBoxUL.clone(), + trBoxLL.clone(), + ], SquareAnnotation.cloudArcSize); + streamTextData += `\n${curveData.start.x} ${curveData.start.y} m`; + curveData.curves.forEach(x => { + streamTextData += `\n${x[0].x} ${x[0].y} ${x[1].x} ${x[1].y} ${x[2].x} ${x[2].y} c`; + }); + streamTextData += "\nS"; + } + else { + gs.LC = lineCapStyles.SQUARE; + gs.LJ = lineJoinStyles.MITER; + streamTextData += `\n${trBoxLL.x} ${trBoxLL.y} m`; + streamTextData += `\n${trBoxLR.x} ${trBoxLR.y} l`; + streamTextData += `\n${trBoxUR.x} ${trBoxUR.y} l`; + streamTextData += `\n${trBoxUL.x} ${trBoxUL.y} l`; + streamTextData += "\ns"; + } + streamTextData += "\nQ"; + apStream.Resources = new ResourceDict(); + apStream.Resources.setGraphicsState("/GS0", gs); + apStream.setTextStreamData(streamTextData); + this.apStream = apStream; + } + applyCommonTransformAsync(matrix, undoable = true) { + return __awaiter$A(this, void 0, void 0, function* () { + const dict = this.getProxy(); + dict.applyRectTransform(matrix); + const stream = dict.apStream; + if (stream) { + const newApMatrix = l.multiply(stream.matrix, matrix); + dict.generateApStream(stream.BBox, newApMatrix.toFloatShortArray()); + } + dict.M = DateString.fromDate(new Date()); + if (dict.$onEditAction) { + const invertedMat = l.invert(matrix); + dict.$onEditAction(undoable + ? () => __awaiter$A(this, void 0, void 0, function* () { + yield dict.applyCommonTransformAsync(invertedMat, false); + yield dict.updateRenderAsync(); + }) + : undefined); + } + }); + } + initProxy() { + return super.initProxy(); + } + getProxy() { + return super.getProxy(); + } +} +SquareAnnotation.cloudArcSize = 20; + +var __awaiter$z = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class CircleAnnotation extends GeometricAnnotation { + constructor() { + super(annotationTypes.CIRCLE); + } + static createFromDto(dto) { + if (dto.annotationType !== "/Circle") { + throw new Error("Invalid annotation type"); + } + const bs = new BorderStyleDict(); + bs.W = dto.strokeWidth; + if (dto.strokeDashGap) { + bs.D = dto.strokeDashGap; + } + const annotation = new CircleAnnotation(); + annotation.$name = dto.uuid; + annotation.NM = LiteralString.fromString(dto.uuid); + annotation.T = LiteralString.fromString(dto.author); + annotation.M = DateString.fromDate(new Date(dto.dateModified)); + annotation.CreationDate = DateString.fromDate(new Date(dto.dateCreated)); + annotation.Contents = dto.textContent + ? LiteralString.fromString(dto.textContent) + : null; + annotation.Rect = dto.rect; + annotation.RD = dto.rectMargins; + annotation.C = dto.color.slice(0, 3); + annotation.CA = dto.color[3]; + annotation.BS = bs; + annotation._cloud = dto.cloud; + annotation.generateApStream(dto.bbox, dto.matrix); + annotation._added = true; + return annotation.initProxy(); + } + static parseAsync(parseInfo) { + return __awaiter$z(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new CircleAnnotation(); + yield pdfObject.parsePropsAsync(parseInfo); + return { + value: pdfObject.initProxy(), + start: parseInfo.bounds.start, + end: parseInfo.bounds.end, + }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.RD) { + bytes.push(...encoder.encode("/RD "), ...this.encodePrimitiveArray(this.RD, encoder)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + toDto() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l; + const color = this.getColorRect(); + return { + annotationType: "/Circle", + uuid: this.$name, + pageId: this.$pageId, + dateCreated: ((_a = this.CreationDate) === null || _a === void 0 ? void 0 : _a.date.toISOString()) || new Date().toISOString(), + dateModified: this.M + ? this.M instanceof LiteralString + ? this.M.literal + : this.M.date.toISOString() + : new Date().toISOString(), + author: (_b = this.T) === null || _b === void 0 ? void 0 : _b.literal, + textContent: (_c = this.Contents) === null || _c === void 0 ? void 0 : _c.literal, + rect: this.Rect, + rectMargins: this.RD, + bbox: (_d = this.apStream) === null || _d === void 0 ? void 0 : _d.BBox, + matrix: (_e = this.apStream) === null || _e === void 0 ? void 0 : _e.Matrix, + cloud: this._cloud, + color, + strokeWidth: (_j = (_g = (_f = this.BS) === null || _f === void 0 ? void 0 : _f.W) !== null && _g !== void 0 ? _g : (_h = this.Border) === null || _h === void 0 ? void 0 : _h.width) !== null && _j !== void 0 ? _j : 1, + strokeDashGap: (_l = (_k = this.BS) === null || _k === void 0 ? void 0 : _k.D) !== null && _l !== void 0 ? _l : [3, 0], + }; + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$z(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/RD": + i = yield this.parseNumberArrayPropAsync(name, parser, i, true); + break; + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + }); + } + generateApStream(bbox, matrix) { + var _a, _b, _c, _d, _e, _f, _g, _h; + const apStream = new XFormStream(); + apStream.Filter = "/FlateDecode"; + apStream.LastModified = DateString.fromDate(new Date()); + const streamBbox = bbox + ? [bbox[0], bbox[1], bbox[2], bbox[3]] + : [this.Rect[0], this.Rect[1], this.Rect[2], this.Rect[3]]; + apStream.BBox = streamBbox; + const streamMatrix = matrix + ? [matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]] + : [1, 0, 0, 1, 0, 0]; + apStream.Matrix = streamMatrix; + const opacity = this.CA || 1; + const strokeWidth = this.strokeWidth; + const strokeDash = (_d = (_b = (_a = this.BS) === null || _a === void 0 ? void 0 : _a.D[0]) !== null && _b !== void 0 ? _b : (_c = this.Border) === null || _c === void 0 ? void 0 : _c.dash) !== null && _d !== void 0 ? _d : 3; + const strokeGap = (_h = (_f = (_e = this.BS) === null || _e === void 0 ? void 0 : _e.D[1]) !== null && _f !== void 0 ? _f : (_g = this.Border) === null || _g === void 0 ? void 0 : _g.gap) !== null && _h !== void 0 ? _h : 0; + const gs = new GraphicsStateDict(); + gs.AIS = true; + gs.BM = "/Normal"; + gs.CA = opacity; + gs.ca = opacity; + gs.LW = strokeWidth; + gs.D = [[strokeDash, strokeGap], 0]; + gs.LC = lineCapStyles.ROUND; + gs.LJ = lineJoinStyles.ROUND; + if (!this.RD) { + const defaultMargin = this._cloud + ? CircleAnnotation.cloudArcSize / 2 + : strokeWidth / 2; + this.RD || (this.RD = [defaultMargin, defaultMargin, defaultMargin, defaultMargin]); + } + const bBoxToRectMat = calcPdfBBoxToRectMatrices(streamBbox, this.Rect, streamMatrix).matAA; + const invMatArray = l.invert(bBoxToRectMat).toFloatShortArray(); + const { r: rotation } = apStream.matrix.getTRS(); + const marginsRotationMat = new l().applyRotation(rotation); + const boxLL = new u(streamBbox[0], streamBbox[1]); + const boxLR = new u(streamBbox[2], streamBbox[1]); + const boxUR = new u(streamBbox[2], streamBbox[3]); + const boxUL = new u(streamBbox[0], streamBbox[3]); + const [marginLeft, marginTop, marginRight, marginBottom] = this.RD; + const marginLL = new u(marginLeft, marginBottom).applyMat3(marginsRotationMat); + const marginLR = new u(-marginRight, marginBottom).applyMat3(marginsRotationMat); + const marginUR = new u(-marginRight, -marginTop).applyMat3(marginsRotationMat); + const marginUL = new u(marginLeft, -marginTop).applyMat3(marginsRotationMat); + const trBoxLL = u.applyMat3(boxLL, bBoxToRectMat).add(marginLL); + const trBoxLR = u.applyMat3(boxLR, bBoxToRectMat).add(marginLR); + const trBoxUR = u.applyMat3(boxUR, bBoxToRectMat).add(marginUR); + const trBoxUL = u.applyMat3(boxUL, bBoxToRectMat).add(marginUL); + const trBoxCenter = u.add(trBoxLL, trBoxUR).multiplyByScalar(0.5); + const trBoxLeft = u.add(trBoxLL, trBoxUL).multiplyByScalar(0.5); + const trBoxTop = u.add(trBoxUL, trBoxUR).multiplyByScalar(0.5); + const trBoxRight = u.add(trBoxLR, trBoxUR).multiplyByScalar(0.5); + const trBoxBottom = u.add(trBoxLL, trBoxLR).multiplyByScalar(0.5); + const rx = u.subtract(trBoxRight, trBoxLeft).multiplyByScalar(0.5); + const ry = u.subtract(trBoxTop, trBoxBottom).multiplyByScalar(0.5); + const colorString = this.getColorString(); + let streamTextData = `q ${colorString} /GS0 gs`; + streamTextData += `\n${invMatArray[0]} ${invMatArray[1]} ${invMatArray[2]} ${invMatArray[3]} ${invMatArray[4]} ${invMatArray[5]} cm`; + if (this._cloud) { + const curveData = CloudCurveData.buildFromEllipse(rx.getMagnitude(), ry.getMagnitude(), CircleAnnotation.cloudArcSize, new l().applyRotation(rotation).applyTranslation(trBoxCenter.x, trBoxCenter.y)); + streamTextData += `\n${curveData.start.x} ${curveData.start.y} m`; + curveData.curves.forEach(x => { + streamTextData += `\n${x[0].x} ${x[0].y} ${x[1].x} ${x[1].y} ${x[2].x} ${x[2].y} c`; + }); + streamTextData += "\nS"; + } + else { + const c = BEZIER_CONSTANT; + const cx = u.multiplyByScalar(rx, c); + const cy = u.multiplyByScalar(ry, c); + const controlTR1 = u.add(u.add(trBoxCenter, ry), cx); + const controlTR2 = u.add(u.add(trBoxCenter, cy), rx); + const controlRB1 = u.add(u.subtract(trBoxCenter, cy), rx); + const controlRB2 = u.add(u.subtract(trBoxCenter, ry), cx); + const controlBL1 = u.subtract(u.subtract(trBoxCenter, ry), cx); + const controlBL2 = u.subtract(u.subtract(trBoxCenter, cy), rx); + const controlLT1 = u.subtract(u.add(trBoxCenter, cy), rx); + const controlLT2 = u.subtract(u.add(trBoxCenter, ry), cx); + streamTextData += `\n${trBoxTop.x} ${trBoxTop.y} m`; + streamTextData += `\n${controlTR1.x} ${controlTR1.y} ${controlTR2.x} ${controlTR2.y} ${trBoxRight.x} ${trBoxRight.y} c`; + streamTextData += `\n${controlRB1.x} ${controlRB1.y} ${controlRB2.x} ${controlRB2.y} ${trBoxBottom.x} ${trBoxBottom.y} c`; + streamTextData += `\n${controlBL1.x} ${controlBL1.y} ${controlBL2.x} ${controlBL2.y} ${trBoxLeft.x} ${trBoxLeft.y} c`; + streamTextData += `\n${controlLT1.x} ${controlLT1.y} ${controlLT2.x} ${controlLT2.y} ${trBoxTop.x} ${trBoxTop.y} c`; + streamTextData += "\ns"; + } + streamTextData += "\nQ"; + apStream.Resources = new ResourceDict(); + apStream.Resources.setGraphicsState("/GS0", gs); + apStream.setTextStreamData(streamTextData); + this.apStream = apStream; + } + applyCommonTransformAsync(matrix, undoable = true) { + return __awaiter$z(this, void 0, void 0, function* () { + const dict = this.getProxy(); + dict.applyRectTransform(matrix); + const stream = dict.apStream; + if (stream) { + const newApMatrix = l.multiply(stream.matrix, matrix); + dict.generateApStream(stream.BBox, newApMatrix.toFloatShortArray()); + } + dict.M = DateString.fromDate(new Date()); + if (dict.$onEditAction) { + const invertedMat = l.invert(matrix); + dict.$onEditAction(undoable + ? () => __awaiter$z(this, void 0, void 0, function* () { + yield dict.applyCommonTransformAsync(invertedMat, false); + yield dict.updateRenderAsync(); + }) + : undefined); + } + }); + } + initProxy() { + return super.initProxy(); + } + getProxy() { + return super.getProxy(); + } +} +CircleAnnotation.cloudArcSize = 20; + +var __awaiter$y = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class PolyAnnotation extends GeometricAnnotation { + constructor(type) { + super(type); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.Vertices) { + bytes.push(...encoder.encode("/Vertices "), ...this.encodePrimitiveArray(this.Vertices, encoder)); + } + if (this.IT) { + bytes.push(...encoder.encode("/IT "), ...encoder.encode(this.IT)); + } + if (this.Measure) { + bytes.push(...encoder.encode("/Measure "), ...this.Measure.toArray(cryptInfo)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$y(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/Vertices": + i = yield this.parseNumberArrayPropAsync(name, parser, i, true); + break; + case "/IT": + const intent = yield parser.parseNameAtAsync(i, true); + if (intent) { + if (Object.values(polyIntents).includes(intent.value)) { + this.IT = intent.value; + i = intent.end + 1; + break; + } + } + throw new Error("Can't parse /IT property value"); + case "/Measure": + const measureEntryType = yield parser.getValueTypeAtAsync(i); + if (measureEntryType === valueTypes.REF) { + const measureDictId = yield ObjectId.parseRefAsync(parser, i); + if (measureDictId && parseInfo.parseInfoGetterAsync) { + const measureParseInfo = yield parseInfo.parseInfoGetterAsync(measureDictId.value.id); + if (measureParseInfo) { + const measureDict = yield MeasureDict.parseAsync(measureParseInfo); + if (measureDict) { + this.Measure = measureDict.value; + i = measureDict.end + 1; + break; + } + } + } + throw new Error("Can't parse /Measure value reference"); + } + else if (measureEntryType === valueTypes.DICTIONARY) { + const measureDictBounds = yield parser.getDictBoundsAtAsync(i); + if (measureDictBounds) { + const measureDict = yield MeasureDict.parseAsync({ parser, bounds: measureDictBounds }); + if (measureDict) { + this.Measure = measureDict.value; + i = measureDict.end + 1; + break; + } + } + throw new Error("Can't parse /Measure value dictionary"); + } + throw new Error(`Unsupported /Measure property value type: ${measureEntryType}`); + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + if (!this.Vertices) { + throw new Error("Not all required properties parsed"); + } + }); + } +} + +var __awaiter$x = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class PolygonAnnotation extends PolyAnnotation { + constructor() { + super(annotationTypes.POLYGON); + } + static createFromDto(dto) { + if (dto.annotationType !== "/Polygon") { + throw new Error("Invalid annotation type"); + } + const bs = new BorderStyleDict(); + bs.W = dto.strokeWidth; + if (dto.strokeDashGap) { + bs.D = dto.strokeDashGap; + } + const annotation = new PolygonAnnotation(); + annotation.$name = dto.uuid; + annotation.NM = LiteralString.fromString(dto.uuid); + annotation.T = LiteralString.fromString(dto.author); + annotation.M = DateString.fromDate(new Date(dto.dateModified)); + annotation.CreationDate = DateString.fromDate(new Date(dto.dateCreated)); + annotation.Contents = dto.textContent + ? LiteralString.fromString(dto.textContent) + : null; + annotation.Rect = dto.rect; + annotation.C = dto.color.slice(0, 3); + annotation.CA = dto.color[3]; + annotation.BS = bs; + annotation.IT = dto.cloud + ? polyIntents.CLOUD + : polyIntents.POLYGON_DIMENSION; + annotation.Vertices = dto.vertices; + annotation.generateApStream(); + annotation._added = true; + return annotation.initProxy(); + } + static parseAsync(parseInfo) { + return __awaiter$x(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new PolygonAnnotation(); + yield pdfObject.parsePropsAsync(parseInfo); + return { + value: pdfObject.initProxy(), + start: parseInfo.bounds.start, + end: parseInfo.bounds.end, + }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + return superBytes; + } + toDto() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l; + const color = this.getColorRect(); + return { + annotationType: "/Polygon", + uuid: this.$name, + pageId: this.$pageId, + dateCreated: ((_a = this.CreationDate) === null || _a === void 0 ? void 0 : _a.date.toISOString()) || new Date().toISOString(), + dateModified: this.M + ? this.M instanceof LiteralString + ? this.M.literal + : this.M.date.toISOString() + : new Date().toISOString(), + author: (_b = this.T) === null || _b === void 0 ? void 0 : _b.literal, + textContent: (_c = this.Contents) === null || _c === void 0 ? void 0 : _c.literal, + rect: this.Rect, + bbox: (_d = this.apStream) === null || _d === void 0 ? void 0 : _d.BBox, + matrix: (_e = this.apStream) === null || _e === void 0 ? void 0 : _e.Matrix, + vertices: this.Vertices, + cloud: this.IT === polyIntents.CLOUD, + color, + strokeWidth: (_j = (_g = (_f = this.BS) === null || _f === void 0 ? void 0 : _f.W) !== null && _g !== void 0 ? _g : (_h = this.Border) === null || _h === void 0 ? void 0 : _h.width) !== null && _j !== void 0 ? _j : 1, + strokeDashGap: (_l = (_k = this.BS) === null || _k === void 0 ? void 0 : _k.D) !== null && _l !== void 0 ? _l : [3, 0], + }; + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$x(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + yield this.bakeRotationAsync(); + }); + } + generateApStream() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j; + if (!((_a = this.Vertices) === null || _a === void 0 ? void 0 : _a.length) || this.Vertices.length < 6) { + return; + } + const apStream = new XFormStream(); + apStream.Filter = "/FlateDecode"; + apStream.LastModified = DateString.fromDate(new Date()); + apStream.BBox = [this.Rect[0], this.Rect[1], this.Rect[2], this.Rect[3]]; + const opacity = this.CA || 1; + const strokeWidth = this.strokeWidth; + const strokeDash = (_e = (_c = (_b = this.BS) === null || _b === void 0 ? void 0 : _b.D[0]) !== null && _c !== void 0 ? _c : (_d = this.Border) === null || _d === void 0 ? void 0 : _d.dash) !== null && _e !== void 0 ? _e : 3; + const strokeGap = (_j = (_g = (_f = this.BS) === null || _f === void 0 ? void 0 : _f.D[1]) !== null && _g !== void 0 ? _g : (_h = this.Border) === null || _h === void 0 ? void 0 : _h.gap) !== null && _j !== void 0 ? _j : 0; + const gs = new GraphicsStateDict(); + gs.AIS = true; + gs.BM = "/Normal"; + gs.CA = opacity; + gs.ca = opacity; + gs.LW = strokeWidth; + gs.D = [[strokeDash, strokeGap], 0]; + const colorString = this.getColorString(); + const list = this.Vertices; + let streamTextData = `q ${colorString} /GS0 gs`; + if (this.IT === polyIntents.CLOUD) { + gs.LC = lineCapStyles.ROUND; + gs.LJ = lineJoinStyles.ROUND; + const vertices = []; + for (let i = 0; i < list.length; i = i + 2) { + vertices.push(new u(list[i], list[i + 1])); + } + vertices.push(new u(list[0], list[1])); + const curveData = CloudCurveData.buildFromPolyline(vertices, PolygonAnnotation.cloudArcSize); + streamTextData += `\n${curveData.start.x} ${curveData.start.y} m`; + curveData.curves.forEach(x => { + streamTextData += `\n${x[0].x} ${x[0].y} ${x[1].x} ${x[1].y} ${x[2].x} ${x[2].y} c`; + }); + streamTextData += "\nS"; + } + else { + gs.LC = lineCapStyles.SQUARE; + gs.LJ = lineJoinStyles.MITER; + let px; + let py; + streamTextData += `\n${list[0]} ${list[1]} m`; + for (let i = 2; i < list.length; i = i + 2) { + px = list[i]; + py = list[i + 1]; + streamTextData += `\n${px} ${py} l`; + } + streamTextData += "\ns"; + } + streamTextData += "\nQ"; + apStream.Resources = new ResourceDict(); + apStream.Resources.setGraphicsState("/GS0", gs); + apStream.setTextStreamData(streamTextData); + this.apStream = apStream; + } + applyCommonTransformAsync(matrix, undoable = true) { + var _a, _b, _c, _d; + return __awaiter$x(this, void 0, void 0, function* () { + const dict = this.getProxy(); + let x; + let y; + let xMin; + let yMin; + let xMax; + let yMax; + const vec = new u(); + const list = dict.Vertices; + for (let i = 0; i < list.length; i = i + 2) { + x = list[i]; + y = list[i + 1]; + vec.set(x, y).applyMat3(matrix); + list[i] = vec.x; + list[i + 1] = vec.y; + if (!xMin || vec.x < xMin) { + xMin = vec.x; + } + if (!yMin || vec.y < yMin) { + yMin = vec.y; + } + if (!xMax || vec.x > xMax) { + xMax = vec.x; + } + if (!yMax || vec.y > yMax) { + yMax = vec.y; + } + } + const halfStrokeWidth = ((_d = (_b = (_a = dict.BS) === null || _a === void 0 ? void 0 : _a.W) !== null && _b !== void 0 ? _b : (_c = dict.Border) === null || _c === void 0 ? void 0 : _c.width) !== null && _d !== void 0 ? _d : 1) / 2; + const margin = dict.IT === polyIntents.CLOUD + ? PolygonAnnotation.cloudArcSize / 2 + halfStrokeWidth + : halfStrokeWidth; + xMin -= margin; + yMin -= margin; + xMax += margin; + yMax += margin; + dict.Rect = [xMin, yMin, xMax, yMax]; + if (dict._bBox) { + const bBox = dict.getLocalBB(); + bBox.ll.set(xMin, yMin); + bBox.lr.set(xMax, yMin); + bBox.ur.set(xMax, yMax); + bBox.ul.set(xMin, yMax); + } + dict.generateApStream(); + dict.M = DateString.fromDate(new Date()); + if (dict.$onEditAction) { + const invertedMat = l.invert(matrix); + dict.$onEditAction(undoable + ? () => __awaiter$x(this, void 0, void 0, function* () { + yield dict.applyCommonTransformAsync(invertedMat, false); + yield dict.updateRenderAsync(); + }) + : undefined); + } + }); + } + bakeRotationAsync() { + return __awaiter$x(this, void 0, void 0, function* () { + const angle = this.getCurrentRotation(); + const centerX = (this.Rect[0] + this.Rect[2]) / 2; + const centerY = (this.Rect[1] + this.Rect[3]) / 2; + const matrix = new l() + .applyTranslation(-centerX, -centerY) + .applyRotation(angle) + .applyTranslation(centerX, centerY); + yield this.applyCommonTransformAsync(matrix); + }); + } + initProxy() { + return super.initProxy(); + } + getProxy() { + return super.getProxy(); + } +} +PolygonAnnotation.cloudArcSize = 20; + +var __awaiter$w = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class PolylineAnnotation extends PolyAnnotation { + constructor() { + super(annotationTypes.POLYLINE); + this.LE = [lineEndingTypes.NONE, lineEndingTypes.NONE]; + } + static createFromDto(dto) { + if (dto.annotationType !== "/Polyline") { + throw new Error("Invalid annotation type"); + } + const bs = new BorderStyleDict(); + bs.W = dto.strokeWidth; + if (dto.strokeDashGap) { + bs.D = dto.strokeDashGap; + } + const annotation = new PolylineAnnotation(); + annotation.$name = dto.uuid; + annotation.NM = LiteralString.fromString(dto.uuid); + annotation.T = LiteralString.fromString(dto.author); + annotation.M = DateString.fromDate(new Date(dto.dateModified)); + annotation.CreationDate = DateString.fromDate(new Date(dto.dateCreated)); + annotation.Contents = dto.textContent + ? LiteralString.fromString(dto.textContent) + : null; + annotation.Rect = dto.rect; + annotation.C = dto.color.slice(0, 3); + annotation.CA = dto.color[3]; + annotation.BS = bs; + annotation.IT = polyIntents.POLYLINE_DIMENSION; + annotation.LE = dto.endingType || [lineEndingTypes.NONE, lineEndingTypes.NONE]; + annotation.Vertices = dto.vertices; + annotation.generateApStream(); + annotation._added = true; + return annotation.initProxy(); + } + static parseAsync(parseInfo) { + return __awaiter$w(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new PolylineAnnotation(); + yield pdfObject.parsePropsAsync(parseInfo); + return { + value: pdfObject.initProxy(), + start: parseInfo.bounds.start, + end: parseInfo.bounds.end, + }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.LE) { + bytes.push(...encoder.encode("/LE "), ...this.encodePrimitiveArray(this.LE, encoder)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + toDto() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l; + const color = this.getColorRect(); + return { + annotationType: "/PolyLine", + uuid: this.$name, + pageId: this.$pageId, + dateCreated: ((_a = this.CreationDate) === null || _a === void 0 ? void 0 : _a.date.toISOString()) || new Date().toISOString(), + dateModified: this.M + ? this.M instanceof LiteralString + ? this.M.literal + : this.M.date.toISOString() + : new Date().toISOString(), + author: (_b = this.T) === null || _b === void 0 ? void 0 : _b.literal, + textContent: (_c = this.Contents) === null || _c === void 0 ? void 0 : _c.literal, + rect: this.Rect, + bbox: (_d = this.apStream) === null || _d === void 0 ? void 0 : _d.BBox, + matrix: (_e = this.apStream) === null || _e === void 0 ? void 0 : _e.Matrix, + vertices: this.Vertices, + endingType: this.LE, + color, + strokeWidth: (_j = (_g = (_f = this.BS) === null || _f === void 0 ? void 0 : _f.W) !== null && _g !== void 0 ? _g : (_h = this.Border) === null || _h === void 0 ? void 0 : _h.width) !== null && _j !== void 0 ? _j : 1, + strokeDashGap: (_l = (_k = this.BS) === null || _k === void 0 ? void 0 : _k.D) !== null && _l !== void 0 ? _l : [3, 0], + }; + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$w(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/LE": + const lineEndings = yield parser.parseNameArrayAtAsync(i, true); + if (lineEndings + && Object.values(lineEndingTypes).includes(lineEndings.value[0]) + && Object.values(lineEndingTypes).includes(lineEndings.value[1])) { + this.LE = [ + lineEndings.value[0], + lineEndings.value[1], + ]; + i = lineEndings.end + 1; + } + else { + throw new Error("Can't parse /LE property value"); + } + break; + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + yield this.bakeRotationAsync(); + }); + } + generateApStream() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j; + if (!((_a = this.Vertices) === null || _a === void 0 ? void 0 : _a.length) || this.Vertices.length < 4) { + return; + } + const apStream = new XFormStream(); + apStream.Filter = "/FlateDecode"; + apStream.LastModified = DateString.fromDate(new Date()); + apStream.BBox = [this.Rect[0], this.Rect[1], this.Rect[2], this.Rect[3]]; + const opacity = this.CA || 1; + const strokeWidth = this.strokeWidth; + const strokeDash = (_e = (_c = (_b = this.BS) === null || _b === void 0 ? void 0 : _b.D[0]) !== null && _c !== void 0 ? _c : (_d = this.Border) === null || _d === void 0 ? void 0 : _d.dash) !== null && _e !== void 0 ? _e : 3; + const strokeGap = (_j = (_g = (_f = this.BS) === null || _f === void 0 ? void 0 : _f.D[1]) !== null && _g !== void 0 ? _g : (_h = this.Border) === null || _h === void 0 ? void 0 : _h.gap) !== null && _j !== void 0 ? _j : 0; + const gs = new GraphicsStateDict(); + gs.AIS = true; + gs.BM = "/Normal"; + gs.CA = opacity; + gs.ca = opacity; + gs.LW = strokeWidth; + gs.D = [[strokeDash, strokeGap], 0]; + gs.LC = lineCapStyles.SQUARE; + gs.LJ = lineJoinStyles.MITER; + const colorString = this.getColorString(); + const list = this.Vertices; + let streamTextData = `q ${colorString} /GS0 gs`; + let px; + let py; + streamTextData += `\n${list[0]} ${list[1]} m`; + for (let i = 2; i < list.length; i = i + 2) { + px = list[i]; + py = list[i + 1]; + streamTextData += `\n${px} ${py} l`; + } + streamTextData += "\nS"; + streamTextData += "\nQ"; + apStream.Resources = new ResourceDict(); + apStream.Resources.setGraphicsState("/GS0", gs); + apStream.setTextStreamData(streamTextData); + this.apStream = apStream; + } + applyCommonTransformAsync(matrix, undoable = true) { + var _a, _b, _c, _d; + return __awaiter$w(this, void 0, void 0, function* () { + const dict = this.getProxy(); + let x; + let y; + let xMin; + let yMin; + let xMax; + let yMax; + const vec = new u(); + const list = dict.Vertices; + for (let i = 0; i < list.length; i = i + 2) { + x = list[i]; + y = list[i + 1]; + vec.set(x, y).applyMat3(matrix); + list[i] = vec.x; + list[i + 1] = vec.y; + if (!xMin || vec.x < xMin) { + xMin = vec.x; + } + if (!yMin || vec.y < yMin) { + yMin = vec.y; + } + if (!xMax || vec.x > xMax) { + xMax = vec.x; + } + if (!yMax || vec.y > yMax) { + yMax = vec.y; + } + } + const margin = ((_d = (_b = (_a = dict.BS) === null || _a === void 0 ? void 0 : _a.W) !== null && _b !== void 0 ? _b : (_c = dict.Border) === null || _c === void 0 ? void 0 : _c.width) !== null && _d !== void 0 ? _d : 1) / 2; + xMin -= margin; + yMin -= margin; + xMax += margin; + yMax += margin; + dict.Rect = [xMin, yMin, xMax, yMax]; + if (dict._bBox) { + const bBox = dict.getLocalBB(); + bBox.ll.set(xMin, yMin); + bBox.lr.set(xMax, yMin); + bBox.ur.set(xMax, yMax); + bBox.ul.set(xMin, yMax); + } + dict.generateApStream(); + dict.M = DateString.fromDate(new Date()); + if (dict.$onEditAction) { + const invertedMat = l.invert(matrix); + dict.$onEditAction(undoable + ? () => __awaiter$w(this, void 0, void 0, function* () { + yield dict.applyCommonTransformAsync(invertedMat, false); + yield dict.updateRenderAsync(); + }) + : undefined); + } + }); + } + bakeRotationAsync() { + return __awaiter$w(this, void 0, void 0, function* () { + const angle = this.getCurrentRotation(); + const centerX = (this.Rect[0] + this.Rect[2]) / 2; + const centerY = (this.Rect[1] + this.Rect[3]) / 2; + const matrix = new l() + .applyTranslation(-centerX, -centerY) + .applyRotation(angle) + .applyTranslation(centerX, centerY); + yield this.applyCommonTransformAsync(matrix); + }); + } + initProxy() { + return super.initProxy(); + } + getProxy() { + return super.getProxy(); + } +} + +var __awaiter$v = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class LineAnnotation extends GeometricAnnotation { + get offsetY() { + return (Math.abs(this.LL || 0) + (this.LLO || 0)) * (this.LL < 0 ? -1 : 1); + } + get minMargin() { + const strokeWidth = this.strokeWidth; + const halfStrokeWidth = strokeWidth / 2; + let marginMin = 0; + if (this.LE[0] !== lineEndingTypes.NONE || this.LE[1] !== lineEndingTypes.NONE) { + const endingSizeInner = Math.max(strokeWidth * LINE_END_MULTIPLIER, LINE_END_MIN_SIZE); + const endingSize = endingSizeInner + strokeWidth; + marginMin = endingSize / 2; + } + else { + marginMin = halfStrokeWidth; + } + return marginMin; + } + constructor() { + super(annotationTypes.LINE); + this.IT = lineIntents.DIMENSION; + this.LE = [lineEndingTypes.NONE, lineEndingTypes.NONE]; + this.LLE = 0; + this.LL = 0; + this.LLO = 0; + this.Cap = false; + this.CP = lineCaptionPositions.INLINE; + this.CO = [0, 0]; + this._svgTemp = new SvgTempPath(); + this.onLineEndHandlePointerDown = (e) => { + if (!e.isPrimary) { + return; + } + const target = e.target; + target.setPointerCapture(e.pointerId); + target.addEventListener("pointerup", this.onLineEndHandlePointerUp); + target.addEventListener("pointerout", this.onLineEndHandlePointerUp); + const handleName = target.dataset.handleName; + switch (handleName) { + case "start": + this._scaleHandleActive = "start"; + break; + case "end": + this._scaleHandleActive = "end"; + break; + default: + throw new Error(`Invalid handle name: ${handleName}`); + } + this._moved = false; + this._transformationTimer = setTimeout(() => { + this._transformationTimer = null; + this._svgTemp.insertAfter(this._renderedControls); + target.addEventListener("pointermove", this.onLineEndHandlePointerMove); + }, 200); + e.stopPropagation(); + }; + this.onLineEndHandlePointerMove = (e) => { + if (!e.isPrimary || !this._scaleHandleActive) { + return; + } + const start = new u(this.L[0], this.L[1]); + const end = new u(this.L[2], this.L[3]); + let startTemp; + let endTemp; + if (this._scaleHandleActive === "start") { + startTemp = this.convertClientCoordsToPage(e.clientX, e.clientY); + endTemp = end.clone(); + } + else { + startTemp = start.clone(); + endTemp = this.convertClientCoordsToPage(e.clientX, e.clientY); + } + this._tempTransformationMatrix = l.from4Vec2(start, end, startTemp, endTemp); + this._svgTemp.set("none", "blue", this.strokeWidth, [startTemp, endTemp]); + this._moved = true; + }; + this.onLineEndHandlePointerUp = (e) => { + if (!e.isPrimary) { + return; + } + const target = e.target; + target.removeEventListener("pointermove", this.onLineEndHandlePointerMove); + target.removeEventListener("pointerup", this.onLineEndHandlePointerUp); + target.removeEventListener("pointerout", this.onLineEndHandlePointerUp); + target.releasePointerCapture(e.pointerId); + this._svgTemp.remove(); + this.applyTempTransformAsync(); + }; + } + static createFromDtoAsync(dto, fontMap) { + return __awaiter$v(this, void 0, void 0, function* () { + if (dto.annotationType !== "/Line") { + throw new Error("Invalid annotation type"); + } + const bs = new BorderStyleDict(); + bs.W = dto.strokeWidth; + if (dto.strokeDashGap) { + bs.D = dto.strokeDashGap; + } + const annotation = new LineAnnotation(); + annotation.$name = dto.uuid; + annotation.NM = LiteralString.fromString(dto.uuid); + annotation.T = LiteralString.fromString(dto.author); + annotation.M = DateString.fromDate(new Date(dto.dateModified)); + annotation.CreationDate = DateString.fromDate(new Date(dto.dateCreated)); + annotation.Contents = dto.textContent + ? LiteralString.fromString(dto.textContent) + : null; + annotation.Rect = dto.rect; + annotation.C = dto.color.slice(0, 3); + annotation.CA = dto.color[3]; + annotation.BS = bs; + annotation.IT = dto.intent || lineIntents.DIMENSION; + annotation.LE = dto.endingType || [lineEndingTypes.NONE, lineEndingTypes.NONE]; + annotation.L = dto.vertices; + annotation.LL = dto.leaderLineLength || 0; + annotation.LLE = dto.leaderLineExtension || 0; + annotation.LLO = dto.leaderLineOffset || 0; + annotation.Cap = dto.caption; + annotation.CP = dto.captionPosition || lineCaptionPositions.INLINE; + annotation.CO = dto.captionOffset || [0, 0]; + annotation._fontMap = fontMap; + yield annotation.generateApStreamAsync(); + annotation._added = true; + return annotation.initProxy(); + }); + } + static parseAsync(parseInfo, fontMap) { + return __awaiter$v(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new LineAnnotation(); + yield pdfObject.parsePropsAsync(parseInfo); + pdfObject._fontMap = fontMap; + return { + value: pdfObject.initProxy(), + start: parseInfo.bounds.start, + end: parseInfo.bounds.end, + }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.L) { + bytes.push(...encoder.encode("/L "), ...this.encodePrimitiveArray(this.L, encoder)); + } + if (this.LE) { + bytes.push(...encoder.encode("/LE "), ...this.encodePrimitiveArray(this.LE, encoder)); + } + if (this.LL) { + bytes.push(...encoder.encode("/LL "), ...encoder.encode(" " + this.LL)); + } + if (this.LLE) { + bytes.push(...encoder.encode("/LLE "), ...encoder.encode(" " + this.LLE)); + } + if (this.Cap) { + bytes.push(...encoder.encode("/Cap "), ...encoder.encode(" " + this.Cap)); + } + if (this.IT) { + bytes.push(...encoder.encode("/IT "), ...encoder.encode(this.IT)); + } + if (this.LLO) { + bytes.push(...encoder.encode("/LLO "), ...encoder.encode(" " + this.LLO)); + } + if (this.CP) { + bytes.push(...encoder.encode("/CP "), ...encoder.encode(this.CP)); + } + if (this.Measure) { + bytes.push(...encoder.encode("/Measure "), ...this.Measure.toArray(cryptInfo)); + } + if (this.CO) { + bytes.push(...encoder.encode("/CO "), ...this.encodePrimitiveArray(this.CO, encoder)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + toDto() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l; + const color = this.getColorRect(); + return { + annotationType: "/Line", + uuid: this.$name, + pageId: this.$pageId, + dateCreated: ((_a = this.CreationDate) === null || _a === void 0 ? void 0 : _a.date.toISOString()) || new Date().toISOString(), + dateModified: this.M + ? this.M instanceof LiteralString + ? this.M.literal + : this.M.date.toISOString() + : new Date().toISOString(), + author: (_b = this.T) === null || _b === void 0 ? void 0 : _b.literal, + textContent: (_c = this.Contents) === null || _c === void 0 ? void 0 : _c.literal, + rect: this.Rect, + bbox: (_d = this.apStream) === null || _d === void 0 ? void 0 : _d.BBox, + matrix: (_e = this.apStream) === null || _e === void 0 ? void 0 : _e.Matrix, + vertices: this.L, + intent: this.IT, + endingType: this.LE, + leaderLineLength: this.LL, + leaderLineExtension: this.LLE, + leaderLineOffset: this.LLO, + caption: this.Cap, + captionPosition: this.CP, + captionOffset: this.CO, + color, + strokeWidth: (_j = (_g = (_f = this.BS) === null || _f === void 0 ? void 0 : _f.W) !== null && _g !== void 0 ? _g : (_h = this.Border) === null || _h === void 0 ? void 0 : _h.width) !== null && _j !== void 0 ? _j : 1, + strokeDashGap: (_l = (_k = this.BS) === null || _k === void 0 ? void 0 : _k.D) !== null && _l !== void 0 ? _l : [3, 0], + }; + } + setTextContentAsync(text, undoable = true) { + const _super = Object.create(null, { + setTextContentAsync: { get: () => super.setTextContentAsync } + }); + return __awaiter$v(this, void 0, void 0, function* () { + yield _super.setTextContentAsync.call(this, text, undoable); + yield this.updateStreamAsync(); + }); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + var _a; + return __awaiter$v(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/L": + case "/CO": + i = yield this.parseNumberArrayPropAsync(name, parser, i, true); + break; + case "/LE": + const lineEndings = yield parser.parseNameArrayAtAsync(i, true); + if (lineEndings + && Object.values(lineEndingTypes).includes(lineEndings.value[0]) + && Object.values(lineEndingTypes).includes(lineEndings.value[1])) { + this.LE = [ + lineEndings.value[0], + lineEndings.value[1], + ]; + i = lineEndings.end + 1; + } + else { + throw new Error("Can't parse /LE property value"); + } + break; + case "/IT": + const intent = yield parser.parseNameAtAsync(i, true); + if (intent) { + if (Object.values(lineIntents).includes(intent.value)) { + this.IT = intent.value; + i = intent.end + 1; + break; + } + } + throw new Error("Can't parse /IT property value"); + case "/CP": + const captionPosition = yield parser.parseNameAtAsync(i, true); + if (captionPosition && Object.values(lineCaptionPositions) + .includes(captionPosition.value)) { + this.CP = captionPosition.value; + i = captionPosition.end + 1; + } + else { + throw new Error("Can't parse /CP property value"); + } + break; + case "/LL": + case "/LLE": + case "/LLO": + i = yield this.parseNumberPropAsync(name, parser, i, false); + break; + case "/Cap": + i = yield this.parseBoolPropAsync(name, parser, i); + break; + case "/Measure": + const measureEntryType = yield parser.getValueTypeAtAsync(i); + if (measureEntryType === valueTypes.REF) { + const measureDictId = yield ObjectId.parseRefAsync(parser, i); + if (measureDictId && parseInfo.parseInfoGetterAsync) { + const measureParseInfo = yield parseInfo.parseInfoGetterAsync(measureDictId.value.id); + if (measureParseInfo) { + const measureDict = yield MeasureDict.parseAsync(measureParseInfo); + if (measureDict) { + this.Measure = measureDict.value; + i = measureDict.end + 1; + break; + } + } + } + throw new Error("Can't parse /BS value reference"); + } + else if (measureEntryType === valueTypes.DICTIONARY) { + const measureDictBounds = yield parser.getDictBoundsAtAsync(i); + if (measureDictBounds) { + const measureDict = yield MeasureDict.parseAsync({ parser, bounds: measureDictBounds }); + if (measureDict) { + this.Measure = measureDict.value; + i = measureDict.end + 1; + break; + } + } + throw new Error("Can't parse /Measure value dictionary"); + } + throw new Error(`Unsupported /Measure property value type: ${measureEntryType}`); + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + if (this.RC) { + const domParser = new DOMParser(); + const body = (_a = domParser.parseFromString(this.RC.literal, "text/xml")) === null || _a === void 0 ? void 0 : _a.querySelector("body"); + if (body) { + const style = body.getAttribute("style"); + const p = body.querySelector("p"); + this._rtStyle = style || ""; + this._rtText = (p === null || p === void 0 ? void 0 : p.textContent) || ""; + } + } + }); + } + applyCommonTransformAsync(matrix, undoable = true) { + return __awaiter$v(this, void 0, void 0, function* () { + const dict = this.getProxy(); + const [x1, y1, x2, y2] = dict.L; + const start = new u(x1, y1).applyMat3(matrix); + const end = new u(x2, y2).applyMat3(matrix); + dict.L = [start.x, start.y, end.x, end.y]; + yield dict.generateApStreamAsync(); + dict.M = DateString.fromDate(new Date()); + if (dict.$onEditAction) { + const invertedMat = l.invert(matrix); + dict.$onEditAction(undoable + ? () => __awaiter$v(this, void 0, void 0, function* () { + yield dict.applyCommonTransformAsync(invertedMat, false); + yield dict.updateRenderAsync(); + }) + : undefined); + } + }); + } + updateStreamAsync() { + return __awaiter$v(this, void 0, void 0, function* () { + const dict = this.getProxy(); + yield dict.generateApStreamAsync(); + yield dict.updateRenderAsync(); + }); + } + calculateStreamBboxAsync() { + return __awaiter$v(this, void 0, void 0, function* () { + const [x1, y1, x2, y2] = this.L; + const length = new u(x2 - x1, y2 - y1).getMagnitude(); + const strokeWidth = this.strokeWidth; + const halfStrokeWidth = strokeWidth / 2; + const marginMin = this.minMargin; + const textMargin = 4 * marginMin; + const textMaxWidth = length > textMargin + ? length - textMargin + : length; + const textData = yield this.updateTextDataAsync({ + maxWidth: textMaxWidth, + fontSize: 9, + strokeWidth, + textAlign: "center", + pivotPoint: this.CP === lineCaptionPositions.INLINE + ? "center" + : "bottom-margin", + }); + const marginFront = Math.max(Math.abs(this.LL || 0) + (this.LLO || 0) + halfStrokeWidth, marginMin); + const marginBack = Math.max((this.LLE || 0) + halfStrokeWidth, marginMin); + const height = marginFront + marginBack; + const top = this.LL < 0 + ? marginMin + : height; + const bottom = this.LL < 0 + ? height + : marginMin; + let xMin = -marginMin; + let yMin = -bottom; + let xMax = length + marginMin; + let yMax = top; + if (textData) { + const offsetY = this.offsetY; + const [textXMin, textYMin, textXMax, textYMax] = textData.relativeRect; + xMin = Math.min(xMin, textXMin + length / 2); + yMin = Math.min(yMin, textYMin + offsetY); + xMax = Math.max(xMax, textXMax + length / 2); + yMax = Math.max(yMax, textYMax + offsetY); + } + const bbox = [new u(xMin, yMin), new u(xMax, yMax)]; + return bbox; + }); + } + calculateStreamMatrix() { + const [x1, y1, x2, y2] = this.L; + const start = new u(x1, y1); + const end = new u(x2, y2); + const length = u.subtract(end, start).getMagnitude(); + const xAlignedStart = new u(); + const xAlignedEnd = new u(length, 0); + const matrix = l.from4Vec2(xAlignedStart, xAlignedEnd, start, end); + return matrix; + } + updateRect(bbox, matrix) { + const localBox = this.getLocalBB(); + localBox.ll.set(bbox[0].x, bbox[0].y).applyMat3(matrix); + localBox.lr.set(bbox[1].x, bbox[0].y).applyMat3(matrix); + localBox.ur.set(bbox[1].x, bbox[1].y).applyMat3(matrix); + localBox.ul.set(bbox[0].x, bbox[1].y).applyMat3(matrix); + const { min: rectMin, max: rectMax } = u.minMax(localBox.ll, localBox.lr, localBox.ur, localBox.ul); + this.Rect = [rectMin.x, rectMin.y, rectMax.x, rectMax.y]; + } + getLineEndsStreamCoords(matrix) { + const matrixInv = l.invert(matrix); + const apStart = new u(this.L[0], this.L[1]) + .applyMat3(matrixInv) + .truncate(); + const apEnd = new u(this.L[2], this.L[3]) + .applyMat3(matrixInv) + .truncate(); + const offsetY = this.offsetY; + apStart.y += offsetY; + apEnd.y += offsetY; + return [apStart, apEnd]; + } + getLineStreamPart(start, end) { + let lineStream = ""; + lineStream += `\n${start.x} ${start.y} m`; + lineStream += `\n${end.x} ${end.y} l`; + lineStream += "\nS"; + if (this.LL) { + if (this.LL > 0) { + lineStream += `\n${start.x} ${start.y - Math.abs(this.LL)} m`; + lineStream += `\n${start.x} ${start.y + this.LLE} l`; + lineStream += "\nS"; + lineStream += `\n${end.x} ${end.y - Math.abs(this.LL)} m`; + lineStream += `\n${end.x} ${end.y + this.LLE} l`; + lineStream += "\nS"; + } + else { + lineStream += `\n${start.x} ${start.y + Math.abs(this.LL)} m`; + lineStream += `\n${start.x} ${start.y - this.LLE} l`; + lineStream += "\nS"; + lineStream += `\n${end.x} ${end.y + Math.abs(this.LL)} m`; + lineStream += `\n${end.x} ${end.y - this.LLE} l`; + lineStream += "\nS"; + } + } + return lineStream; + } + getTextStreamPartAsync(pivotPoint, font) { + return __awaiter$v(this, void 0, void 0, function* () { + const textData = this._textData; + if (!textData) { + return ""; + } + const [xMin, yMin, xMax, yMax] = textData.relativeRect; + const bottomLeftLCS = new u(xMin, yMin).add(pivotPoint); + const topRightLCS = new u(xMax, yMax).add(pivotPoint); + const textBgRectStream = "\nq 1 g 1 G" + + `\n${bottomLeftLCS.x} ${bottomLeftLCS.y} m` + + `\n${bottomLeftLCS.x} ${topRightLCS.y} l` + + `\n${topRightLCS.x} ${topRightLCS.y} l` + + `\n${topRightLCS.x} ${bottomLeftLCS.y} l` + + "\nf" + + "\nQ"; + let textStream = "\nq 0 g 0 G"; + const fontSize = 9; + for (const line of textData.lines) { + if (!line.text) { + continue; + } + const lineStart = new u(line.relativeRect[0], line.relativeRect[1]).add(pivotPoint); + let lineHex = ""; + for (const char of line.text) { + const code = font.encoding.codeMap.get(char); + if (code) { + lineHex += code.toString(16).padStart(2, "0"); + } + } + textStream += `\nBT 0 Tc 0 Tw 100 Tz ${font.name} ${fontSize} Tf 0 Tr`; + textStream += `\n1 0 0 1 ${lineStart.x} ${lineStart.y + fontSize * 0.2} Tm`; + textStream += `\n<${lineHex}> Tj`; + textStream += "\nET"; + } + textStream += "\nQ"; + return textBgRectStream + textStream; + }); + } + generateApStreamAsync() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; + return __awaiter$v(this, void 0, void 0, function* () { + if (!this.L) { + return; + } + const bbox = yield this.calculateStreamBboxAsync(); + const matrix = this.calculateStreamMatrix(); + this.updateRect(bbox, matrix); + const apStream = new XFormStream(); + apStream.Filter = "/FlateDecode"; + apStream.LastModified = DateString.fromDate(new Date()); + apStream.BBox = [bbox[0].x, bbox[0].y, bbox[1].x, bbox[1].y]; + apStream.Matrix = matrix.toFloatShortArray(); + apStream.Resources = new ResourceDict(); + const opacity = this.CA || 1; + const strokeWidth = this.strokeWidth; + const strokeDash = (_d = (_b = (_a = this.BS) === null || _a === void 0 ? void 0 : _a.D[0]) !== null && _b !== void 0 ? _b : (_c = this.Border) === null || _c === void 0 ? void 0 : _c.dash) !== null && _d !== void 0 ? _d : 3; + const strokeGap = (_h = (_f = (_e = this.BS) === null || _e === void 0 ? void 0 : _e.D[1]) !== null && _f !== void 0 ? _f : (_g = this.Border) === null || _g === void 0 ? void 0 : _g.gap) !== null && _h !== void 0 ? _h : 0; + const gs = new GraphicsStateDict(); + gs.AIS = true; + gs.BM = "/Normal"; + gs.CA = opacity; + gs.ca = opacity; + gs.LW = strokeWidth; + gs.D = [[strokeDash, strokeGap], 0]; + gs.LC = lineCapStyles.SQUARE; + gs.LJ = lineJoinStyles.MITER; + apStream.Resources.setGraphicsState("/GS0", gs); + const fontFamily = "arial"; + const font = (_j = this._fontMap) === null || _j === void 0 ? void 0 : _j.get(fontFamily); + if (!font || !((_k = font.encoding) === null || _k === void 0 ? void 0 : _k.codeMap)) { + throw new Error(`Suitable font is not found in the font map: '${fontFamily}'`); + } + apStream.Resources.setFont(font.name, font); + const colorString = this.getColorString(); + const [apStart, apEnd] = this.getLineEndsStreamCoords(matrix); + const lineStreamPart = this.getLineStreamPart(apStart, apEnd); + const leftEndingStreamPart = this.getLineEndingStreamPart(apStart, this.LE[0], strokeWidth, "left"); + const rightEndingStreamPart = this.getLineEndingStreamPart(apEnd, this.LE[1], strokeWidth, "right"); + const textStreamPart = yield this.getTextStreamPartAsync(u.add(apStart, apEnd).multiplyByScalar(0.5), font); + const streamTextData = `q ${colorString} /GS0 gs` + + lineStreamPart + + leftEndingStreamPart + + rightEndingStreamPart + + textStreamPart + + "\nQ"; + apStream.setTextStreamData(streamTextData); + this.apStream = apStream; + }); + } + renderHandles() { + return [...this.renderLineEndHandles(), this.renderRotationHandle()]; + } + renderLineEndHandles() { + const startHandle = document.createElementNS("http://www.w3.org/2000/svg", "line"); + startHandle.classList.add("annotation-handle", "scale"); + startHandle.setAttribute("data-handle-name", "start"); + startHandle.setAttribute("x1", this.L[0] + ""); + startHandle.setAttribute("y1", this.L[1] + ""); + startHandle.setAttribute("x2", this.L[0] + ""); + startHandle.setAttribute("y2", this.L[1] + 0.1 + ""); + startHandle.addEventListener("pointerdown", this.onLineEndHandlePointerDown); + const endHandle = document.createElementNS("http://www.w3.org/2000/svg", "line"); + endHandle.classList.add("annotation-handle", "scale"); + endHandle.setAttribute("data-handle-name", "end"); + endHandle.setAttribute("x1", this.L[2] + ""); + endHandle.setAttribute("y1", this.L[3] + ""); + endHandle.setAttribute("x2", this.L[2] + ""); + endHandle.setAttribute("y2", this.L[3] + 0.1 + ""); + endHandle.addEventListener("pointerdown", this.onLineEndHandlePointerDown); + return [startHandle, endHandle]; + } + initProxy() { + return super.initProxy(); + } + getProxy() { + return super.getProxy(); + } +} + +var __awaiter$u = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class TextMarkupAnnotation extends MarkupAnnotation { + constructor(type) { + super(type); + this.onTranslationPointerDown = (e) => { }; + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.QuadPoints) { + bytes.push(...encoder.encode("/QuadPoints "), ...this.encodePrimitiveArray(this.QuadPoints, encoder)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$u(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/QuadPoints": + i = yield this.parseNumberArrayPropAsync(name, parser, i, true); + break; + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + if (!this.QuadPoints) { + throw new Error("Not all required properties parsed"); + } + }); + } + renderHandles() { + return []; + } +} + +var __awaiter$t = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class HighlightAnnotation extends TextMarkupAnnotation { + constructor() { + super(annotationTypes.HIGHLIGHT); + } + static createFromDto(dto) { + var _a; + if (dto.annotationType !== "/Highlight") { + throw new Error("Invalid annotation type"); + } + if (!((_a = dto === null || dto === void 0 ? void 0 : dto.quadPoints) === null || _a === void 0 ? void 0 : _a.length) || dto.quadPoints.length % 8) { + return; + } + const bs = new BorderStyleDict(); + bs.W = dto.strokeWidth; + if (dto.strokeDashGap) { + bs.D = dto.strokeDashGap; + } + const annotation = new HighlightAnnotation(); + annotation.$name = dto.uuid; + annotation.NM = LiteralString.fromString(dto.uuid); + annotation.T = LiteralString.fromString(dto.author); + annotation.M = DateString.fromDate(new Date(dto.dateModified)); + annotation.CreationDate = DateString.fromDate(new Date(dto.dateCreated)); + annotation.Contents = dto.textContent + ? LiteralString.fromString(dto.textContent) + : null; + if (dto.rect) { + annotation.Rect = dto.rect; + } + else { + const vectors = []; + for (let i = 0; i < dto.quadPoints.length; i += 2) { + vectors.push(new u(dto.quadPoints[i], dto.quadPoints[i + 1])); + } + const { min, max } = u.minMax(...vectors); + annotation.Rect = [min.x, min.y, max.x, max.y]; + } + annotation.C = dto.color.slice(0, 3); + annotation.CA = dto.color[3]; + annotation.BS = bs; + annotation.QuadPoints = dto.quadPoints; + annotation.generateApStream(); + annotation._added = true; + return annotation.initProxy(); + } + static parseAsync(parseInfo) { + return __awaiter$t(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new HighlightAnnotation(); + yield pdfObject.parsePropsAsync(parseInfo); + return { + value: pdfObject.initProxy(), + start: parseInfo.bounds.start, + end: parseInfo.bounds.end, + }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + return superBytes; + } + toDto() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l; + const color = this.getColorRect(); + return { + annotationType: "/Highlight", + uuid: this.$name, + pageId: this.$pageId, + dateCreated: ((_a = this.CreationDate) === null || _a === void 0 ? void 0 : _a.date.toISOString()) || new Date().toISOString(), + dateModified: this.M + ? this.M instanceof LiteralString + ? this.M.literal + : this.M.date.toISOString() + : new Date().toISOString(), + author: (_b = this.T) === null || _b === void 0 ? void 0 : _b.literal, + textContent: (_c = this.Contents) === null || _c === void 0 ? void 0 : _c.literal, + rect: this.Rect, + bbox: (_d = this.apStream) === null || _d === void 0 ? void 0 : _d.BBox, + matrix: (_e = this.apStream) === null || _e === void 0 ? void 0 : _e.Matrix, + quadPoints: this.QuadPoints, + color, + strokeWidth: (_j = (_g = (_f = this.BS) === null || _f === void 0 ? void 0 : _f.W) !== null && _g !== void 0 ? _g : (_h = this.Border) === null || _h === void 0 ? void 0 : _h.width) !== null && _j !== void 0 ? _j : 1, + strokeDashGap: (_l = (_k = this.BS) === null || _k === void 0 ? void 0 : _k.D) !== null && _l !== void 0 ? _l : [3, 0], + }; + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$t(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + }); + } + generateApStream() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j; + if (!((_a = this.QuadPoints) === null || _a === void 0 ? void 0 : _a.length) || this.QuadPoints.length % 8) { + return; + } + const apStream = new XFormStream(); + apStream.Filter = "/FlateDecode"; + apStream.LastModified = DateString.fromDate(new Date()); + apStream.BBox = [this.Rect[0], this.Rect[1], this.Rect[2], this.Rect[3]]; + const opacity = this.CA || 1; + const strokeWidth = this.strokeWidth; + const strokeDash = (_e = (_c = (_b = this.BS) === null || _b === void 0 ? void 0 : _b.D[0]) !== null && _c !== void 0 ? _c : (_d = this.Border) === null || _d === void 0 ? void 0 : _d.dash) !== null && _e !== void 0 ? _e : 3; + const strokeGap = (_j = (_g = (_f = this.BS) === null || _f === void 0 ? void 0 : _f.D[1]) !== null && _g !== void 0 ? _g : (_h = this.Border) === null || _h === void 0 ? void 0 : _h.gap) !== null && _j !== void 0 ? _j : 0; + const gs = new GraphicsStateDict(); + gs.AIS = true; + gs.BM = "/Normal"; + gs.CA = opacity; + gs.ca = opacity; + gs.LW = strokeWidth; + gs.LC = lineCapStyles.SQUARE; + gs.LJ = lineJoinStyles.MITER; + gs.D = [[strokeDash, strokeGap], 0]; + gs.BM = blendModes.MULTIPLY; + const colorString = this.getColorString(); + let streamTextData = `q ${colorString} /GS0 gs`; + const bottomLeft = new u(); + const bottomRight = new u(); + const topRight = new u(); + const topLeft = new u(); + const q = this.QuadPoints; + for (let i = 0; i < q.length; i += 8) { + bottomLeft.set(q[i + 4], q[i + 5]); + bottomRight.set(q[i + 6], q[i + 7]); + topRight.set(q[i + 2], q[i + 3]); + topLeft.set(q[i + 0], q[i + 1]); + streamTextData += `\n${bottomLeft.x} ${bottomLeft.y} m`; + streamTextData += `\n${bottomRight.x} ${bottomRight.y} l`; + streamTextData += `\n${topRight.x} ${topRight.y} l`; + streamTextData += `\n${topLeft.x} ${topLeft.y} l`; + streamTextData += "\nf"; + } + streamTextData += "\nQ"; + apStream.Resources = new ResourceDict(); + apStream.Resources.setGraphicsState("/GS0", gs); + apStream.setTextStreamData(streamTextData); + this.apStream = apStream; + } + initProxy() { + return super.initProxy(); + } + getProxy() { + return super.getProxy(); + } +} + +var __awaiter$s = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class UnderlineAnnotation extends TextMarkupAnnotation { + constructor() { + super(annotationTypes.UNDERLINE); + } + static createFromDto(dto) { + var _a; + if (dto.annotationType !== "/Underline") { + throw new Error("Invalid annotation type"); + } + if (!((_a = dto === null || dto === void 0 ? void 0 : dto.quadPoints) === null || _a === void 0 ? void 0 : _a.length) || dto.quadPoints.length % 8) { + return; + } + const bs = new BorderStyleDict(); + bs.W = dto.strokeWidth; + if (dto.strokeDashGap) { + bs.D = dto.strokeDashGap; + } + const annotation = new UnderlineAnnotation(); + annotation.$name = dto.uuid; + annotation.NM = LiteralString.fromString(dto.uuid); + annotation.T = LiteralString.fromString(dto.author); + annotation.M = DateString.fromDate(new Date(dto.dateModified)); + annotation.CreationDate = DateString.fromDate(new Date(dto.dateCreated)); + annotation.Contents = dto.textContent + ? LiteralString.fromString(dto.textContent) + : null; + if (dto.rect) { + annotation.Rect = dto.rect; + } + else { + const vectors = []; + for (let i = 0; i < dto.quadPoints.length; i += 2) { + vectors.push(new u(dto.quadPoints[i], dto.quadPoints[i + 1])); + } + const { min, max } = u.minMax(...vectors); + const margin = dto.strokeWidth + ? dto.strokeWidth / 2 + : 1; + annotation.Rect = [min.x - margin, min.y - margin, max.x + margin, max.y + margin]; + } + annotation.C = dto.color.slice(0, 3); + annotation.CA = dto.color[3]; + annotation.BS = bs; + annotation.QuadPoints = dto.quadPoints; + annotation.generateApStream(); + annotation._added = true; + return annotation.initProxy(); + } + static parseAsync(parseInfo) { + return __awaiter$s(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new UnderlineAnnotation(); + yield pdfObject.parsePropsAsync(parseInfo); + return { + value: pdfObject.initProxy(), + start: parseInfo.bounds.start, + end: parseInfo.bounds.end, + }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + return superBytes; + } + toDto() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l; + const color = this.getColorRect(); + return { + annotationType: "/Underline", + uuid: this.$name, + pageId: this.$pageId, + dateCreated: ((_a = this.CreationDate) === null || _a === void 0 ? void 0 : _a.date.toISOString()) || new Date().toISOString(), + dateModified: this.M + ? this.M instanceof LiteralString + ? this.M.literal + : this.M.date.toISOString() + : new Date().toISOString(), + author: (_b = this.T) === null || _b === void 0 ? void 0 : _b.literal, + textContent: (_c = this.Contents) === null || _c === void 0 ? void 0 : _c.literal, + rect: this.Rect, + bbox: (_d = this.apStream) === null || _d === void 0 ? void 0 : _d.BBox, + matrix: (_e = this.apStream) === null || _e === void 0 ? void 0 : _e.Matrix, + quadPoints: this.QuadPoints, + color, + strokeWidth: (_j = (_g = (_f = this.BS) === null || _f === void 0 ? void 0 : _f.W) !== null && _g !== void 0 ? _g : (_h = this.Border) === null || _h === void 0 ? void 0 : _h.width) !== null && _j !== void 0 ? _j : 1, + strokeDashGap: (_l = (_k = this.BS) === null || _k === void 0 ? void 0 : _k.D) !== null && _l !== void 0 ? _l : [3, 0], + }; + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$s(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + }); + } + generateApStream() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j; + if (!((_a = this.QuadPoints) === null || _a === void 0 ? void 0 : _a.length) || this.QuadPoints.length % 8) { + return; + } + const apStream = new XFormStream(); + apStream.Filter = "/FlateDecode"; + apStream.LastModified = DateString.fromDate(new Date()); + apStream.BBox = [this.Rect[0], this.Rect[1], this.Rect[2], this.Rect[3]]; + const opacity = this.CA || 1; + const strokeWidth = this.strokeWidth; + const strokeDash = (_e = (_c = (_b = this.BS) === null || _b === void 0 ? void 0 : _b.D[0]) !== null && _c !== void 0 ? _c : (_d = this.Border) === null || _d === void 0 ? void 0 : _d.dash) !== null && _e !== void 0 ? _e : 3; + const strokeGap = (_j = (_g = (_f = this.BS) === null || _f === void 0 ? void 0 : _f.D[1]) !== null && _g !== void 0 ? _g : (_h = this.Border) === null || _h === void 0 ? void 0 : _h.gap) !== null && _j !== void 0 ? _j : 0; + const gs = new GraphicsStateDict(); + gs.AIS = true; + gs.BM = "/Normal"; + gs.CA = opacity; + gs.ca = opacity; + gs.LW = strokeWidth; + gs.LC = lineCapStyles.SQUARE; + gs.LJ = lineJoinStyles.MITER; + gs.D = [[strokeDash, strokeGap], 0]; + const colorString = this.getColorString(); + let streamTextData = `q ${colorString} /GS0 gs`; + const bottomLeft = new u(); + const bottomRight = new u(); + const q = this.QuadPoints; + for (let i = 0; i < q.length; i += 8) { + bottomLeft.set(q[i + 4], q[i + 5]); + bottomRight.set(q[i + 6], q[i + 7]); + streamTextData += `\n${bottomLeft.x} ${bottomLeft.y} m`; + streamTextData += `\n${bottomRight.x} ${bottomRight.y} l`; + streamTextData += "\nS"; + } + streamTextData += "\nQ"; + apStream.Resources = new ResourceDict(); + apStream.Resources.setGraphicsState("/GS0", gs); + apStream.setTextStreamData(streamTextData); + this.apStream = apStream; + } + initProxy() { + return super.initProxy(); + } + getProxy() { + return super.getProxy(); + } +} + +var __awaiter$r = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class StrikeoutAnnotation extends TextMarkupAnnotation { + constructor() { + super(annotationTypes.STRIKEOUT); + } + static createFromDto(dto) { + var _a; + if (dto.annotationType !== "/Strikeout") { + throw new Error("Invalid annotation type"); + } + if (!((_a = dto === null || dto === void 0 ? void 0 : dto.quadPoints) === null || _a === void 0 ? void 0 : _a.length) || dto.quadPoints.length % 8) { + return; + } + const bs = new BorderStyleDict(); + bs.W = dto.strokeWidth; + if (dto.strokeDashGap) { + bs.D = dto.strokeDashGap; + } + const annotation = new StrikeoutAnnotation(); + annotation.$name = dto.uuid; + annotation.NM = LiteralString.fromString(dto.uuid); + annotation.T = LiteralString.fromString(dto.author); + annotation.M = DateString.fromDate(new Date(dto.dateModified)); + annotation.CreationDate = DateString.fromDate(new Date(dto.dateCreated)); + annotation.Contents = dto.textContent + ? LiteralString.fromString(dto.textContent) + : null; + if (dto.rect) { + annotation.Rect = dto.rect; + } + else { + const vectors = []; + for (let i = 0; i < dto.quadPoints.length; i += 2) { + vectors.push(new u(dto.quadPoints[i], dto.quadPoints[i + 1])); + } + const { min, max } = u.minMax(...vectors); + annotation.Rect = [min.x, min.y, max.x, max.y]; + } + annotation.C = dto.color.slice(0, 3); + annotation.CA = dto.color[3]; + annotation.BS = bs; + annotation.QuadPoints = dto.quadPoints; + annotation.generateApStream(); + annotation._added = true; + return annotation.initProxy(); + } + static parseAsync(parseInfo) { + return __awaiter$r(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new StrikeoutAnnotation(); + yield pdfObject.parsePropsAsync(parseInfo); + return { + value: pdfObject.initProxy(), + start: parseInfo.bounds.start, + end: parseInfo.bounds.end, + }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + return superBytes; + } + toDto() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l; + const color = this.getColorRect(); + return { + annotationType: "/Strikeout", + uuid: this.$name, + pageId: this.$pageId, + dateCreated: ((_a = this.CreationDate) === null || _a === void 0 ? void 0 : _a.date.toISOString()) || new Date().toISOString(), + dateModified: this.M + ? this.M instanceof LiteralString + ? this.M.literal + : this.M.date.toISOString() + : new Date().toISOString(), + author: (_b = this.T) === null || _b === void 0 ? void 0 : _b.literal, + textContent: (_c = this.Contents) === null || _c === void 0 ? void 0 : _c.literal, + rect: this.Rect, + bbox: (_d = this.apStream) === null || _d === void 0 ? void 0 : _d.BBox, + matrix: (_e = this.apStream) === null || _e === void 0 ? void 0 : _e.Matrix, + quadPoints: this.QuadPoints, + color, + strokeWidth: (_j = (_g = (_f = this.BS) === null || _f === void 0 ? void 0 : _f.W) !== null && _g !== void 0 ? _g : (_h = this.Border) === null || _h === void 0 ? void 0 : _h.width) !== null && _j !== void 0 ? _j : 1, + strokeDashGap: (_l = (_k = this.BS) === null || _k === void 0 ? void 0 : _k.D) !== null && _l !== void 0 ? _l : [3, 0], + }; + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$r(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + }); + } + generateApStream() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j; + if (!((_a = this.QuadPoints) === null || _a === void 0 ? void 0 : _a.length) || this.QuadPoints.length % 8) { + return; + } + const apStream = new XFormStream(); + apStream.Filter = "/FlateDecode"; + apStream.LastModified = DateString.fromDate(new Date()); + apStream.BBox = [this.Rect[0], this.Rect[1], this.Rect[2], this.Rect[3]]; + const opacity = this.CA || 1; + const strokeWidth = this.strokeWidth; + const strokeDash = (_e = (_c = (_b = this.BS) === null || _b === void 0 ? void 0 : _b.D[0]) !== null && _c !== void 0 ? _c : (_d = this.Border) === null || _d === void 0 ? void 0 : _d.dash) !== null && _e !== void 0 ? _e : 3; + const strokeGap = (_j = (_g = (_f = this.BS) === null || _f === void 0 ? void 0 : _f.D[1]) !== null && _g !== void 0 ? _g : (_h = this.Border) === null || _h === void 0 ? void 0 : _h.gap) !== null && _j !== void 0 ? _j : 0; + const gs = new GraphicsStateDict(); + gs.AIS = true; + gs.BM = "/Normal"; + gs.CA = opacity; + gs.ca = opacity; + gs.LW = strokeWidth; + gs.LC = lineCapStyles.SQUARE; + gs.LJ = lineJoinStyles.MITER; + gs.D = [[strokeDash, strokeGap], 0]; + const colorString = this.getColorString(); + let streamTextData = `q ${colorString} /GS0 gs`; + const bottomLeft = new u(); + const bottomRight = new u(); + const topRight = new u(); + const topLeft = new u(); + const start = new u(); + const end = new u(); + const q = this.QuadPoints; + for (let i = 0; i < q.length; i += 8) { + bottomLeft.set(q[i + 4], q[i + 5]); + bottomRight.set(q[i + 6], q[i + 7]); + topRight.set(q[i + 2], q[i + 3]); + topLeft.set(q[i + 0], q[i + 1]); + start.setFromVec2(bottomLeft).add(topLeft).multiplyByScalar(0.5); + end.setFromVec2(bottomRight).add(topRight).multiplyByScalar(0.5); + streamTextData += `\n${start.x} ${start.y} m`; + streamTextData += `\n${end.x} ${end.y} l`; + streamTextData += "\nS"; + } + streamTextData += "\nQ"; + apStream.Resources = new ResourceDict(); + apStream.Resources.setGraphicsState("/GS0", gs); + apStream.setTextStreamData(streamTextData); + this.apStream = apStream; + } + initProxy() { + return super.initProxy(); + } + getProxy() { + return super.getProxy(); + } +} + +var __awaiter$q = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class SquigglyAnnotation extends TextMarkupAnnotation { + constructor() { + super(annotationTypes.SQUIGGLY); + } + static createFromDto(dto) { + var _a; + if (dto.annotationType !== "/Squiggly") { + throw new Error("Invalid annotation type"); + } + if (!((_a = dto === null || dto === void 0 ? void 0 : dto.quadPoints) === null || _a === void 0 ? void 0 : _a.length) || dto.quadPoints.length % 8) { + return; + } + const bs = new BorderStyleDict(); + bs.W = dto.strokeWidth; + if (dto.strokeDashGap) { + bs.D = dto.strokeDashGap; + } + const annotation = new SquigglyAnnotation(); + annotation.$name = dto.uuid; + annotation.NM = LiteralString.fromString(dto.uuid); + annotation.T = LiteralString.fromString(dto.author); + annotation.M = DateString.fromDate(new Date(dto.dateModified)); + annotation.CreationDate = DateString.fromDate(new Date(dto.dateCreated)); + annotation.Contents = dto.textContent + ? LiteralString.fromString(dto.textContent) + : null; + if (dto.rect) { + annotation.Rect = dto.rect; + } + else { + const vectors = []; + for (let i = 0; i < dto.quadPoints.length; i += 2) { + vectors.push(new u(dto.quadPoints[i], dto.quadPoints[i + 1])); + } + const { min, max } = u.minMax(...vectors); + const margin = this.squiggleSize / 2 + (dto.strokeWidth || 2) / 2; + annotation.Rect = [min.x - margin, min.y - margin, max.x + margin, max.y + margin]; + } + annotation.C = dto.color.slice(0, 3); + annotation.CA = dto.color[3]; + annotation.BS = bs; + annotation.QuadPoints = dto.quadPoints; + annotation.generateApStream(); + annotation._added = true; + return annotation.initProxy(); + } + static parseAsync(parseInfo) { + return __awaiter$q(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new SquigglyAnnotation(); + yield pdfObject.parsePropsAsync(parseInfo); + return { + value: pdfObject.initProxy(), + start: parseInfo.bounds.start, + end: parseInfo.bounds.end, + }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + return superBytes; + } + toDto() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l; + const color = this.getColorRect(); + return { + annotationType: "/Squiggly", + uuid: this.$name, + pageId: this.$pageId, + dateCreated: ((_a = this.CreationDate) === null || _a === void 0 ? void 0 : _a.date.toISOString()) || new Date().toISOString(), + dateModified: this.M + ? this.M instanceof LiteralString + ? this.M.literal + : this.M.date.toISOString() + : new Date().toISOString(), + author: (_b = this.T) === null || _b === void 0 ? void 0 : _b.literal, + textContent: (_c = this.Contents) === null || _c === void 0 ? void 0 : _c.literal, + rect: this.Rect, + bbox: (_d = this.apStream) === null || _d === void 0 ? void 0 : _d.BBox, + matrix: (_e = this.apStream) === null || _e === void 0 ? void 0 : _e.Matrix, + quadPoints: this.QuadPoints, + color, + strokeWidth: (_j = (_g = (_f = this.BS) === null || _f === void 0 ? void 0 : _f.W) !== null && _g !== void 0 ? _g : (_h = this.Border) === null || _h === void 0 ? void 0 : _h.width) !== null && _j !== void 0 ? _j : 1, + strokeDashGap: (_l = (_k = this.BS) === null || _k === void 0 ? void 0 : _k.D) !== null && _l !== void 0 ? _l : [3, 0], + }; + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + return __awaiter$q(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + }); + } + generateApStream() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j; + if (!((_a = this.QuadPoints) === null || _a === void 0 ? void 0 : _a.length) || this.QuadPoints.length % 8) { + return; + } + const apStream = new XFormStream(); + apStream.Filter = "/FlateDecode"; + apStream.LastModified = DateString.fromDate(new Date()); + apStream.BBox = [this.Rect[0], this.Rect[1], this.Rect[2], this.Rect[3]]; + const opacity = this.CA || 1; + const strokeWidth = this.strokeWidth; + const strokeDash = (_e = (_c = (_b = this.BS) === null || _b === void 0 ? void 0 : _b.D[0]) !== null && _c !== void 0 ? _c : (_d = this.Border) === null || _d === void 0 ? void 0 : _d.dash) !== null && _e !== void 0 ? _e : 3; + const strokeGap = (_j = (_g = (_f = this.BS) === null || _f === void 0 ? void 0 : _f.D[1]) !== null && _g !== void 0 ? _g : (_h = this.Border) === null || _h === void 0 ? void 0 : _h.gap) !== null && _j !== void 0 ? _j : 0; + const gs = new GraphicsStateDict(); + gs.AIS = true; + gs.BM = "/Normal"; + gs.CA = opacity; + gs.ca = opacity; + gs.LW = strokeWidth; + gs.LC = lineCapStyles.SQUARE; + gs.LJ = lineJoinStyles.MITER; + gs.D = [[strokeDash, strokeGap], 0]; + const colorString = this.getColorString(); + let streamTextData = `q ${colorString} /GS0 gs`; + const bottomLeft = new u(); + const bottomRight = new u(); + const q = this.QuadPoints; + for (let i = 0; i < q.length; i += 8) { + bottomLeft.set(q[i + 4], q[i + 5]); + bottomRight.set(q[i + 6], q[i + 7]); + const squigglyLinePoints = buildSquigglyLine(bottomLeft, bottomRight, SquigglyAnnotation.squiggleSize); + if (!(squigglyLinePoints === null || squigglyLinePoints === void 0 ? void 0 : squigglyLinePoints.length)) { + continue; + } + streamTextData += `\n${squigglyLinePoints[0].x} ${squigglyLinePoints[0].y} m`; + for (let j = 1; j < squigglyLinePoints.length; j++) { + streamTextData += `\n${squigglyLinePoints[j].x} ${squigglyLinePoints[j].y} l`; + } + streamTextData += "\nS"; + } + streamTextData += "\nQ"; + apStream.Resources = new ResourceDict(); + apStream.Resources.setGraphicsState("/GS0", gs); + apStream.setTextStreamData(streamTextData); + this.apStream = apStream; + } + initProxy() { + return super.initProxy(); + } + getProxy() { + return super.getProxy(); + } +} +SquigglyAnnotation.squiggleSize = 6; + +var __awaiter$p = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class FreeTextAnnotation extends MarkupAnnotation { + get pointsStreamCS() { + const stroke = this.strokeWidth; + const halfStroke = stroke / 2; + const [apXMin, apYMin, apXMax, apYMax] = this.apStream.BBox; + const [mLeft, mBottom, mRight, mTop] = this.RD || [halfStroke, halfStroke, halfStroke, halfStroke]; + const apBL = new u(apXMin + mLeft, apYMin + mBottom); + const apTR = new u(apXMax - mRight, apYMax - mTop); + const apBR = new u(apTR.x, apBL.y); + const apTL = new u(apBL.x, apTR.y); + const apL = u.add(apBL, apTL).multiplyByScalar(0.5); + const apT = u.add(apTL, apTR).multiplyByScalar(0.5); + const apR = u.add(apBR, apTR).multiplyByScalar(0.5); + const apB = u.add(apBL, apBR).multiplyByScalar(0.5); + const cl = this.CL; + let apCoBase; + let apCoPointer; + let apCoKnee; + if (cl) { + if (cl.length === 6) { + apCoBase = new u(cl[4], cl[5]); + apCoKnee = new u(cl[2], cl[3]); + apCoPointer = new u(cl[0], cl[1]); + } + else if (cl.length === 4) { + apCoBase = new u(cl[2], cl[3]); + apCoPointer = new u(cl[0], cl[1]); + } + } + return { + bl: apBL, tr: apTR, br: apBR, tl: apTL, + l: apL, t: apT, r: apR, b: apB, + cob: apCoBase, cok: apCoKnee, cop: apCoPointer, + }; + } + get pointsPageCS() { + const points = this.pointsStreamCS; + const { matAA: mat } = calcPdfBBoxToRectMatrices(this.apStream.BBox, this.Rect, this.apStream.Matrix); + return { + bl: points.bl.applyMat3(mat), + tr: points.tr.applyMat3(mat), + br: points.br.applyMat3(mat), + tl: points.tl.applyMat3(mat), + l: points.l.applyMat3(mat), + t: points.t.applyMat3(mat), + r: points.r.applyMat3(mat), + b: points.b.applyMat3(mat), + cob: points.cob ? points.cob.applyMat3(mat) : null, + cok: points.cok ? points.cok.applyMat3(mat) : null, + cop: points.cop ? points.cop.applyMat3(mat) : null, + }; + } + get minMargin() { + const strokeWidth = this.strokeWidth; + const halfStrokeWidth = strokeWidth / 2; + let marginMin; + if (this.LE && this.LE !== lineEndingTypes.NONE) { + const endingSizeWoStroke = Math.max(strokeWidth * LINE_END_MULTIPLIER, LINE_END_MIN_SIZE); + const endingSize = endingSizeWoStroke + strokeWidth; + marginMin = endingSize / 2; + } + else { + marginMin = halfStrokeWidth; + } + return marginMin; + } + constructor() { + super(annotationTypes.FREE_TEXT); + this.Q = justificationTypes.LEFT; + this.IT = freeTextIntents.PLAIN_TEXT; + this.LE = lineEndingTypes.NONE; + this._svgTemp = new SvgTempPath(); + this.onTextBoxCornerHandlePointerDown = (e) => { + if (!e.isPrimary) { + return; + } + const target = e.target; + target.setPointerCapture(e.pointerId); + target.addEventListener("pointerup", this.onTextBoxCornerHandlePointerUp); + target.addEventListener("pointerout", this.onTextBoxCornerHandlePointerUp); + this._pointsTemp = this.pointsPageCS; + this._moved = false; + this._transformationTimer = setTimeout(() => { + this._transformationTimer = null; + this._svgTemp.insertAfter(this._renderedControls); + target.addEventListener("pointermove", this.onTextBoxCornerHandlePointerMove); + }, 200); + e.stopPropagation(); + }; + this.onTextBoxCornerHandlePointerMove = (e) => { + var _a; + if (!e.isPrimary) { + return; + } + const target = e.target; + const handleName = target.dataset.handleName; + const points = this._pointsTemp; + const p = this.convertClientCoordsToPage(e.clientX, e.clientY); + const horLength = u.subtract(points.br, points.bl).getMagnitude(); + const vertLength = u.subtract(points.tl, points.bl).getMagnitude(); + const matToAligned = l.from4Vec2(points.bl, points.br, new u(), new u(horLength, 0)); + let oppositeP; + switch (handleName) { + case "tb-bl": + oppositeP = points.tr; + break; + case "tb-br": + oppositeP = points.tl; + break; + case "tb-tr": + oppositeP = points.bl; + break; + case "tb-tl": + oppositeP = points.br; + break; + default: + return; + } + const pAligned = u.applyMat3(p, matToAligned); + const oppositePAligned = u.applyMat3(oppositeP, matToAligned); + const transformedHorLength = Math.abs(pAligned.x - oppositePAligned.x); + const transformedVertLength = Math.abs(pAligned.y - oppositePAligned.y); + const scaleX = transformedHorLength / horLength; + const scaleY = transformedVertLength / vertLength; + const { r: rotation } = matToAligned.getTRS(); + const mat = new l() + .applyTranslation(-oppositeP.x, -oppositeP.y) + .applyRotation(rotation) + .applyScaling(scaleX, scaleY) + .applyRotation(-rotation) + .applyTranslation(oppositeP.x, oppositeP.y); + points.bl.applyMat3(mat); + points.br.applyMat3(mat); + points.tr.applyMat3(mat); + points.tl.applyMat3(mat); + points.l.applyMat3(mat); + points.t.applyMat3(mat); + points.r.applyMat3(mat); + points.b.applyMat3(mat); + (_a = points.cob) === null || _a === void 0 ? void 0 : _a.applyMat3(mat); + this._svgTemp.set("lightblue", "blue", this.strokeWidth, [points.bl, points.br, points.tr, points.tl], true); + this._moved = true; + }; + this.onTextBoxCornerHandlePointerUp = (e) => { + if (!e.isPrimary) { + return; + } + const target = e.target; + target.removeEventListener("pointermove", this.onTextBoxCornerHandlePointerMove); + target.removeEventListener("pointerup", this.onTextBoxCornerHandlePointerUp); + target.removeEventListener("pointerout", this.onTextBoxCornerHandlePointerUp); + target.releasePointerCapture(e.pointerId); + this._svgTemp.remove(); + if (this._moved) { + this.updateStreamAsync(this._pointsTemp); + } + }; + this.onSideHandlePointerUp = (e) => { + if (!e.isPrimary) { + return; + } + const target = e.target; + const handleName = target.dataset.handleName; + const points = this.pointsPageCS; + switch (handleName) { + case "co-pivot-l": + if (u.equals(points.cob, points.l)) { + return; + } + points.cob.setFromVec2(points.l); + break; + case "co-pivot-t": + if (u.equals(points.cob, points.t)) { + return; + } + points.cob.setFromVec2(points.t); + break; + case "co-pivot-r": + if (u.equals(points.cob, points.r)) { + return; + } + points.cob.setFromVec2(points.r); + break; + case "co-pivot-b": + if (u.equals(points.cob, points.b)) { + return; + } + points.cob.setFromVec2(points.b); + break; + default: + return; + } + this.updateStreamAsync(points); + }; + this.onCalloutHandlePointerDown = (e) => { + if (!e.isPrimary) { + return; + } + const target = e.target; + target.setPointerCapture(e.pointerId); + target.addEventListener("pointerup", this.onCalloutHandlePointerUp); + target.addEventListener("pointerout", this.onCalloutHandlePointerUp); + this._pointsTemp = this.pointsPageCS; + this._moved = false; + this._transformationTimer = setTimeout(() => { + this._transformationTimer = null; + this._svgTemp.insertAfter(this._renderedControls); + target.addEventListener("pointermove", this.onCalloutHandlePointerMove); + }, 200); + e.stopPropagation(); + }; + this.onCalloutHandlePointerMove = (e) => { + if (!e.isPrimary) { + return; + } + const target = e.target; + const handleName = target.dataset.handleName; + switch (handleName) { + case "co-knee": + this._pointsTemp.cok.setFromVec2(this.convertClientCoordsToPage(e.clientX, e.clientY)); + break; + case "co-pointer": + this._pointsTemp.cop.setFromVec2(this.convertClientCoordsToPage(e.clientX, e.clientY)); + break; + default: + return; + } + this._svgTemp.set("none", "blue", this.strokeWidth, this._pointsTemp.cok + ? [this._pointsTemp.cob, this._pointsTemp.cok, this._pointsTemp.cop] + : [this._pointsTemp.cob, this._pointsTemp.cop]); + this._moved = true; + }; + this.onCalloutHandlePointerUp = (e) => { + if (!e.isPrimary) { + return; + } + const target = e.target; + target.removeEventListener("pointermove", this.onCalloutHandlePointerMove); + target.removeEventListener("pointerup", this.onCalloutHandlePointerUp); + target.removeEventListener("pointerout", this.onCalloutHandlePointerUp); + target.releasePointerCapture(e.pointerId); + this._svgTemp.remove(); + if (this._moved) { + this.updateStreamAsync(this._pointsTemp); + } + }; + } + static createFromDtoAsync(dto, fontMap) { + return __awaiter$p(this, void 0, void 0, function* () { + if (dto.annotationType !== "/FreeText") { + throw new Error("Invalid annotation type"); + } + const bs = new BorderStyleDict(); + bs.W = dto.strokeWidth; + if (dto.strokeDashGap) { + bs.D = dto.strokeDashGap; + } + const annotation = new FreeTextAnnotation(); + annotation.$name = dto.uuid; + annotation.NM = LiteralString.fromString(dto.uuid); + annotation.T = LiteralString.fromString(dto.author); + annotation.M = DateString.fromDate(new Date(dto.dateModified)); + annotation.CreationDate = DateString.fromDate(new Date(dto.dateCreated)); + annotation.Contents = dto.textContent + ? LiteralString.fromString(dto.textContent) + : null; + annotation.Rect = dto.rect; + annotation.C = dto.color.slice(0, 3); + annotation.CA = dto.color[3]; + annotation.BS = bs; + annotation.IT = dto.intent || freeTextIntents.PLAIN_TEXT; + annotation.LE = dto.calloutEndingType || lineEndingTypes.NONE; + annotation.Q = dto.justification || justificationTypes.LEFT; + annotation._fontMap = fontMap; + const { bl, tr, br, tl, l, t, r, b, cob, cok, cop } = dto.points; + const points = { + bl: new u(bl[0], bl[1]), + tr: new u(tr[0], tr[1]), + br: new u(br[0], br[1]), + tl: new u(tl[0], tl[1]), + l: new u(l[0], l[1]), + t: new u(t[0], t[1]), + r: new u(r[0], r[1]), + b: new u(b[0], b[1]), + cob: cob ? new u(cob[0], cob[1]) : null, + cok: cok ? new u(cok[0], cok[1]) : null, + cop: cop ? new u(cop[0], cop[1]) : null, + }; + yield annotation.generateApStreamAsync(points); + annotation._added = true; + return annotation.initProxy(); + }); + } + static parseAsync(parseInfo, fontMap) { + return __awaiter$p(this, void 0, void 0, function* () { + if (!parseInfo) { + throw new Error("Parsing information not passed"); + } + try { + const pdfObject = new FreeTextAnnotation(); + yield pdfObject.parsePropsAsync(parseInfo); + pdfObject._fontMap = fontMap; + return { + value: pdfObject.initProxy(), + start: parseInfo.bounds.start, + end: parseInfo.bounds.end, + }; + } + catch (e) { + console.log(e.message); + return null; + } + }); + } + toArray(cryptInfo) { + const superBytes = super.toArray(cryptInfo); + const encoder = new TextEncoder(); + const bytes = []; + if (this.DA) { + bytes.push(...encoder.encode("/DA "), ...this.DA.toArray(cryptInfo)); + } + if (this.Q) { + bytes.push(...encoder.encode("/Q "), ...encoder.encode(" " + this.Q)); + } + if (this.DS) { + bytes.push(...encoder.encode("/DS "), ...this.DS.toArray(cryptInfo)); + } + if (this.RC) { + bytes.push(...encoder.encode("/RC "), ...this.RC.toArray(cryptInfo)); + } + if (this.CL) { + bytes.push(...encoder.encode("/CL "), ...this.encodePrimitiveArray(this.CL, encoder)); + } + if (this.IT) { + bytes.push(...encoder.encode("/IT "), ...encoder.encode(this.IT)); + } + if (this.RD) { + bytes.push(...encoder.encode("/RD "), ...this.encodePrimitiveArray(this.RD, encoder)); + } + if (this.LE) { + bytes.push(...encoder.encode("/LE "), ...encoder.encode(this.LE)); + } + const totalBytes = [ + ...superBytes.subarray(0, 2), + ...bytes, + ...superBytes.subarray(2, superBytes.length) + ]; + return new Uint8Array(totalBytes); + } + toDto() { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m; + const color = this.getColorRect(); + const { bl, tr, br, tl, l, t, r, b, cob, cok, cop } = this.pointsPageCS; + const points = { + bl: bl.truncate().toFloatArray(), + tr: tr.truncate().toFloatArray(), + br: br.truncate().toFloatArray(), + tl: tl.truncate().toFloatArray(), + l: l.truncate().toFloatArray(), + t: t.truncate().toFloatArray(), + r: r.truncate().toFloatArray(), + b: b.truncate().toFloatArray(), + cob: cob ? cob.truncate().toFloatArray() : null, + cok: cok ? cok.truncate().toFloatArray() : null, + cop: cop ? cop.truncate().toFloatArray() : null, + }; + return { + annotationType: "/FreeText", + uuid: this.$name, + pageId: this.$pageId, + dateCreated: ((_b = (_a = this["CreationDate"]) === null || _a === void 0 ? void 0 : _a.date) === null || _b === void 0 ? void 0 : _b.toISOString()) || new Date().toISOString(), + dateModified: this.M + ? this.M instanceof LiteralString + ? this.M.literal + : this.M.date.toISOString() + : new Date().toISOString(), + author: (_c = this["T"]) === null || _c === void 0 ? void 0 : _c.literal, + textContent: (_d = this.Contents) === null || _d === void 0 ? void 0 : _d.literal, + rect: this.Rect, + bbox: (_e = this.apStream) === null || _e === void 0 ? void 0 : _e.BBox, + matrix: (_f = this.apStream) === null || _f === void 0 ? void 0 : _f.Matrix, + points, + color, + strokeWidth: (_k = (_h = (_g = this.BS) === null || _g === void 0 ? void 0 : _g.W) !== null && _h !== void 0 ? _h : (_j = this.Border) === null || _j === void 0 ? void 0 : _j.width) !== null && _k !== void 0 ? _k : 1, + strokeDashGap: (_m = (_l = this.BS) === null || _l === void 0 ? void 0 : _l.D) !== null && _m !== void 0 ? _m : [3, 0], + intent: this.IT, + justification: this.Q, + calloutEndingType: this.LE, + }; + } + setTextContentAsync(text, undoable = true) { + const _super = Object.create(null, { + setTextContentAsync: { get: () => super.setTextContentAsync } + }); + return __awaiter$p(this, void 0, void 0, function* () { + yield _super.setTextContentAsync.call(this, text, undoable); + yield this.updateStreamAsync(null); + }); + } + parsePropsAsync(parseInfo) { + const _super = Object.create(null, { + parsePropsAsync: { get: () => super.parsePropsAsync } + }); + var _a; + return __awaiter$p(this, void 0, void 0, function* () { + yield _super.parsePropsAsync.call(this, parseInfo); + const { parser, bounds } = parseInfo; + const start = bounds.contentStart || bounds.start; + const end = bounds.contentEnd || bounds.end; + let i = yield parser.skipToNextNameAsync(start, end - 1); + let name; + let parseResult; + while (true) { + parseResult = yield parser.parseNameAtAsync(i); + if (parseResult) { + i = parseResult.end + 1; + name = parseResult.value; + switch (name) { + case "/DA": + case "/DS": + case "/RC": + i = yield this.parseLiteralPropAsync(name, parser, i, parseInfo.cryptInfo); + break; + case "/Q": + const justification = yield parser.parseNumberAtAsync(i, true); + if (justification && Object.values(justificationTypes) + .includes(justification.value)) { + this.Q = justification.value; + i = justification.end + 1; + } + else { + throw new Error("Can't parse /Q property value"); + } + break; + case "/LE": + const lineEndingType = yield parser.parseNameAtAsync(i, true); + if (lineEndingType && Object.values(lineEndingTypes) + .includes(lineEndingType.value)) { + this.LE = lineEndingType.value; + i = lineEndingType.end + 1; + } + else { + throw new Error("Can't parse /LE property value"); + } + break; + case "/CL": + case "/RD": + i = yield this.parseNumberArrayPropAsync(name, parser, i, true); + break; + case "/IT": + const intent = yield parser.parseNameAtAsync(i, true); + if (intent) { + if (intent.value === "/FreeTextTypewriter") { + this.IT = freeTextIntents.CLICK_TO_TYPE; + i = intent.end + 1; + break; + } + else if (Object.values(freeTextIntents).includes(intent.value)) { + this.IT = intent.value; + i = intent.end + 1; + break; + } + } + throw new Error("Can't parse /IT property value"); + default: + i = yield parser.skipToNextNameAsync(i, end - 1); + break; + } + } + else { + break; + } + } + if (this.DS) { + this._defaultStyle = this.DS.literal; + } + if (this.RC) { + const domParser = new DOMParser(); + const body = (_a = domParser.parseFromString(this.RC.literal, "text/xml")) === null || _a === void 0 ? void 0 : _a.querySelector("body"); + if (body) { + const style = body.getAttribute("style"); + const p = body.querySelector("p"); + this._rtStyle = style || ""; + this._rtText = (p === null || p === void 0 ? void 0 : p.textContent) || ""; + } + } + if (!this.DA) { + throw new Error("Not all required properties parsed"); + } + if (!this.C || (this.C[0] === 1 && this.C[1] === 1 && this.C[2] === 1)) { + this.C = [1, 0, 0]; + } + }); + } + calculateStreamMatrix(tbTopLeftPage, tbTopRightPage) { + const length = u.subtract(tbTopRightPage, tbTopLeftPage).getMagnitude(); + const alignedTL = new u(); + const alignedTR = new u(length, 0); + const matrix = l.from4Vec2(alignedTL, alignedTR, tbTopLeftPage, tbTopRightPage); + return matrix; + } + calculateStreamBbox(pPoints, matrixStreamToPage) { + const { bl: pBL, tr: pTR, br: pBR, tl: pTL, l: pL, t: pT, r: pR, b: pB, cob: pCoBase, cok: pCoKnee, cop: pCoPointer } = pPoints; + const minMargin = this.minMargin; + const matrixPageToStream = l.invert(matrixStreamToPage); + const sBL = u.applyMat3(pBL, matrixPageToStream).truncate(); + const sTR = u.applyMat3(pTR, matrixPageToStream).truncate(); + const sBR = u.applyMat3(pBR, matrixPageToStream).truncate(); + const sTL = u.applyMat3(pTL, matrixPageToStream).truncate(); + const sL = u.applyMat3(pL, matrixPageToStream).truncate(); + const sT = u.applyMat3(pT, matrixPageToStream).truncate(); + const sR = u.applyMat3(pR, matrixPageToStream).truncate(); + const sB = u.applyMat3(pB, matrixPageToStream).truncate(); + const sCoBase = pCoBase ? u.applyMat3(pCoBase, matrixPageToStream).truncate() : null; + const sCoKnee = pCoKnee ? u.applyMat3(pCoKnee, matrixPageToStream).truncate() : null; + const sCoPointer = pCoPointer ? u.applyMat3(pCoPointer, matrixPageToStream).truncate() : null; + const actualPoints = [sBL, sTR, sBR, sTL, sCoKnee, sCoPointer].filter(x => x); + const { min: boxMinNoMargin, max: boxMaxNoMargin } = u.minMax(...actualPoints); + const boxMin = new u(boxMinNoMargin.x - minMargin, boxMinNoMargin.y - minMargin); + const boxMax = new u(boxMaxNoMargin.x + minMargin, boxMaxNoMargin.y + minMargin); + return { + bbox: [boxMin, boxMax], + points: { + bl: sBL, + tr: sTR, + br: sBR, + tl: sTL, + l: sL, + t: sT, + r: sR, + b: sB, + cob: sCoBase, + cok: sCoKnee, + cop: sCoPointer, + }, + }; + } + updateAnnotCoords(sPoints, matrixStreamToPage, bbox) { + const { bl: sBL, tr: sTR, cob: sCoBase, cok: sCoKnee, cop: sCoPointer } = sPoints; + const [boxMin, boxMax] = bbox; + const localBox = this.getLocalBB(); + localBox.ll.set(boxMin.x, boxMin.y).applyMat3(matrixStreamToPage).truncate(); + localBox.lr.set(boxMax.x, boxMin.y).applyMat3(matrixStreamToPage).truncate(); + localBox.ur.set(boxMax.x, boxMax.y).applyMat3(matrixStreamToPage).truncate(); + localBox.ul.set(boxMin.x, boxMax.y).applyMat3(matrixStreamToPage).truncate(); + const { min: rectMin, max: rectMax } = u.minMax(localBox.ll, localBox.lr, localBox.ur, localBox.ul); + this.Rect = [rectMin.x, rectMin.y, rectMax.x, rectMax.y]; + if (sCoPointer && sCoBase) { + if (sCoKnee) { + this.CL = [sCoPointer.x, sCoPointer.y, sCoKnee.x, sCoKnee.y, sCoBase.x, sCoBase.y]; + } + else { + this.CL = [sCoPointer.x, sCoPointer.y, sCoBase.x, sCoBase.y]; + } + this.IT = freeTextIntents.WITH_CALLOUT; + } + else { + this.CL = undefined; + this.IT = freeTextIntents.PLAIN_TEXT; + } + this.RD = [ + sBL.x - boxMin.x, + sBL.y - boxMin.y, + boxMax.x - sTR.x, + boxMax.y - sTR.y, + ]; + } + getColorString() { + const [r, g, b] = this.getColorRect(); + return `${r} ${g} ${b} RG 1 g`; + } + getCalloutStreamPart(sPoints) { + let calloutStream = ""; + if (sPoints.cop && sPoints.cob) { + calloutStream += `\n${sPoints.cob.x} ${sPoints.cob.y} m`; + if (sPoints.cok) { + calloutStream += `\n${sPoints.cok.x} ${sPoints.cok.y} l`; + } + calloutStream += `\n${sPoints.cop.x} ${sPoints.cop.y} l`; + calloutStream += "\nS"; + const coEnds = sPoints.cok + ? [sPoints.cok, sPoints.cop] + : [sPoints.cob, sPoints.cop]; + const [coStart, coEnd] = coEnds; + const coStartAligned = new u(0, 0); + const coEndAligned = new u(u.subtract(coEnd, coStart).getMagnitude()); + const coMat = l.from4Vec2(coStartAligned, coEndAligned, coStart, coEnd); + const calloutPointerStream = this.getLineEndingStreamPart(coEndAligned, this.LE, this.strokeWidth, "right"); + const coMatShort = coMat.toFloatShortArray(); + calloutStream += "\nq " + + `${coMatShort[0].toFixed(5)} ` + + `${coMatShort[1].toFixed(5)} ` + + `${coMatShort[2].toFixed(5)} ` + + `${coMatShort[3].toFixed(5)} ` + + `${coMatShort[4].toFixed(5)} ` + + `${coMatShort[5].toFixed(5)} ` + + "cm"; + calloutStream += calloutPointerStream; + calloutStream += "\nQ"; + } + return calloutStream; + } + getTextStreamPartAsync(sPoints, font) { + return __awaiter$p(this, void 0, void 0, function* () { + const w = this.strokeWidth; + const textMaxWidth = sPoints.br.x - sPoints.bl.x - 2 * w; + if (textMaxWidth <= 0) { + return ""; + } + const fontSize = 12; + let textAlign; + if (this.Q) { + textAlign = this.Q === justificationTypes.CENTER + ? "center" + : "right"; + } + else { + textAlign = "left"; + } + const textData = yield this.updateTextDataAsync({ + maxWidth: textMaxWidth, + fontSize, + strokeWidth: w, + textAlign: textAlign, + pivotPoint: "top-left", + }); + if (!textData) { + return ""; + } + let textStream = "\nq 0 g 0 G"; + const codeMap = font.encoding.codeMap; + for (const line of textData.lines) { + if (!line.text) { + continue; + } + const lineStart = new u(line.relativeRect[0], line.relativeRect[1]) + .add(sPoints.tl) + .add(new u(w, -w)) + .truncate(); + let lineHex = ""; + for (const char of line.text) { + const code = codeMap.get(char); + if (code) { + lineHex += code.toString(16).padStart(2, "0"); + } + } + textStream += `\nBT 0 Tc 0 Tw 100 Tz ${font.name} ${fontSize} Tf 0 Tr`; + textStream += `\n1 0 0 1 ${lineStart.x} ${lineStart.y + fontSize * 0.2} Tm`; + textStream += `\n<${lineHex}> Tj`; + textStream += "\nET"; + } + textStream += "\nQ"; + return textStream; + }); + } + generateApStreamAsync(pPoints) { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; + return __awaiter$p(this, void 0, void 0, function* () { + if (!pPoints) { + throw new Error("No key annotation point coordinates passed"); + } + const matrix = this.calculateStreamMatrix(pPoints.tl, pPoints.tr); + const { bbox, points: sPoints } = this.calculateStreamBbox(pPoints, matrix); + this.updateAnnotCoords(sPoints, matrix, bbox); + const apStream = new XFormStream(); + apStream.Filter = "/FlateDecode"; + apStream.LastModified = DateString.fromDate(new Date()); + apStream.BBox = [bbox[0].x, bbox[0].y, bbox[1].x, bbox[1].y]; + apStream.Matrix = matrix.toFloatShortArray(); + apStream.Resources = new ResourceDict(); + const opacity = this.CA || 1; + const strokeWidth = this.strokeWidth; + const strokeDash = (_d = (_b = (_a = this.BS) === null || _a === void 0 ? void 0 : _a.D[0]) !== null && _b !== void 0 ? _b : (_c = this.Border) === null || _c === void 0 ? void 0 : _c.dash) !== null && _d !== void 0 ? _d : 3; + const strokeGap = (_h = (_f = (_e = this.BS) === null || _e === void 0 ? void 0 : _e.D[1]) !== null && _f !== void 0 ? _f : (_g = this.Border) === null || _g === void 0 ? void 0 : _g.gap) !== null && _h !== void 0 ? _h : 0; + const gs = new GraphicsStateDict(); + gs.AIS = true; + gs.BM = "/Normal"; + gs.CA = opacity; + gs.ca = opacity; + gs.LW = strokeWidth; + gs.D = [[strokeDash, strokeGap], 0]; + gs.LC = lineCapStyles.SQUARE; + gs.LJ = lineJoinStyles.MITER; + apStream.Resources.setGraphicsState("/GS0", gs); + const fontFamily = "arial"; + const font = (_j = this._fontMap) === null || _j === void 0 ? void 0 : _j.get(fontFamily); + if (!font || !((_k = font.encoding) === null || _k === void 0 ? void 0 : _k.codeMap)) { + throw new Error(`Suitable font is not found in the font map: '${fontFamily}'`); + } + apStream.Resources.setFont(font.name, font); + const colorString = this.getColorString(); + const calloutStreamPart = this.getCalloutStreamPart(sPoints); + const textBoxStreamPart = `\n${sPoints.bl.x} ${sPoints.bl.y} m` + + `\n${sPoints.br.x} ${sPoints.br.y} l` + + `\n${sPoints.tr.x} ${sPoints.tr.y} l` + + `\n${sPoints.tl.x} ${sPoints.tl.y} l` + + "\nb"; + const textStreamPart = yield this.getTextStreamPartAsync(sPoints, font); + const streamTextData = `q ${colorString} /GS0 gs` + + calloutStreamPart + + textBoxStreamPart + + textStreamPart + + "\nQ"; + apStream.setTextStreamData(streamTextData); + this.apStream = apStream; + }); + } + updateStreamAsync(points, undoable = true) { + return __awaiter$p(this, void 0, void 0, function* () { + const dict = this.getProxy(); + const oldPoints = dict.pointsPageCS; + yield dict.generateApStreamAsync(points || oldPoints); + yield dict.updateRenderAsync(); + if (points && dict.$onEditAction) { + dict.$onEditAction(undoable + ? () => __awaiter$p(this, void 0, void 0, function* () { + yield dict.updateStreamAsync(oldPoints, false); + }) + : undefined); + } + }); + } + renderHandles() { + const points = this.pointsPageCS; + return [ + ...this.renderTextBoxCornerHandles(points), + ...this.renderCalloutHandles(points), + this.renderRotationHandle() + ]; + } + renderTextBoxCornerHandles(points) { + const { bl: pBL, br: pBR, tr: pTR, tl: pTL } = points; + const cornerMap = new Map(); + cornerMap.set("tb-bl", pBL); + cornerMap.set("tb-br", pBR); + cornerMap.set("tb-tr", pTR); + cornerMap.set("tb-tl", pTL); + const handles = []; + ["tb-bl", "tb-br", "tb-tr", "tb-tl"].forEach(x => { + const { x: cx, y: cy } = cornerMap.get(x); + const handle = document.createElementNS("http://www.w3.org/2000/svg", "line"); + handle.classList.add("annotation-handle", "scale"); + handle.setAttribute("data-handle-name", x); + handle.setAttribute("x1", cx + ""); + handle.setAttribute("y1", cy + ""); + handle.setAttribute("x2", cx + ""); + handle.setAttribute("y2", cy + 0.1 + ""); + handle.addEventListener("pointerdown", this.onTextBoxCornerHandlePointerDown); + handles.push(handle); + }); + return handles; + } + renderCalloutHandles(points) { + const handles = []; + if (!points.cop) { + return handles; + } + ["l", "t", "r", "b"].forEach(x => { + const side = points[x]; + const sideHandle = document.createElementNS("http://www.w3.org/2000/svg", "line"); + sideHandle.classList.add("annotation-handle", "helper"); + sideHandle.setAttribute("data-handle-name", `co-pivot-${x}`); + sideHandle.setAttribute("x1", side.x + ""); + sideHandle.setAttribute("y1", side.y + ""); + sideHandle.setAttribute("x2", side.x + ""); + sideHandle.setAttribute("y2", side.y + 0.1 + ""); + sideHandle.addEventListener("pointerdown", this.onSideHandlePointerUp); + handles.push(sideHandle); + }); + if (points.cok) { + const pCoKnee = points.cok; + const kneeHandle = document.createElementNS("http://www.w3.org/2000/svg", "line"); + kneeHandle.classList.add("annotation-handle", "translation"); + kneeHandle.setAttribute("data-handle-name", "co-knee"); + kneeHandle.setAttribute("x1", pCoKnee.x + ""); + kneeHandle.setAttribute("y1", pCoKnee.y + ""); + kneeHandle.setAttribute("x2", pCoKnee.x + ""); + kneeHandle.setAttribute("y2", pCoKnee.y + 0.1 + ""); + kneeHandle.addEventListener("pointerdown", this.onCalloutHandlePointerDown); + handles.push(kneeHandle); + } + const pCoPointer = points.cop; + const pointerHandle = document.createElementNS("http://www.w3.org/2000/svg", "line"); + pointerHandle.classList.add("annotation-handle", "translation"); + pointerHandle.setAttribute("data-handle-name", "co-pointer"); + pointerHandle.setAttribute("x1", pCoPointer.x + ""); + pointerHandle.setAttribute("y1", pCoPointer.y + ""); + pointerHandle.setAttribute("x2", pCoPointer.x + ""); + pointerHandle.setAttribute("y2", pCoPointer.y + 0.1 + ""); + pointerHandle.addEventListener("pointerdown", this.onCalloutHandlePointerDown); + handles.push(pointerHandle); + return handles; + } + initProxy() { + return super.initProxy(); + } + getProxy() { + return super.getProxy(); + } +} + +var __awaiter$o = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class AnnotationParser { + static ParseAnnotationFromInfoAsync(info, fontMap) { + return __awaiter$o(this, void 0, void 0, function* () { + const annotationType = yield info.parser.parseDictSubtypeAsync(info.bounds); + let annot; + switch (annotationType) { + case annotationTypes.STAMP: + annot = yield StampAnnotation.parseAsync(info); + break; + case annotationTypes.TEXT: + annot = yield TextAnnotation.parseAsync(info); + break; + case annotationTypes.INK: + annot = yield InkAnnotation.parseAsync(info); + break; + case annotationTypes.SQUARE: + annot = yield SquareAnnotation.parseAsync(info); + break; + case annotationTypes.CIRCLE: + annot = yield CircleAnnotation.parseAsync(info); + break; + case annotationTypes.POLYGON: + annot = yield PolygonAnnotation.parseAsync(info); + break; + case annotationTypes.POLYLINE: + annot = yield PolylineAnnotation.parseAsync(info); + break; + case annotationTypes.LINE: + annot = yield LineAnnotation.parseAsync(info, fontMap); + break; + case annotationTypes.HIGHLIGHT: + annot = yield HighlightAnnotation.parseAsync(info); + break; + case annotationTypes.SQUIGGLY: + annot = yield SquigglyAnnotation.parseAsync(info); + break; + case annotationTypes.STRIKEOUT: + annot = yield StrikeoutAnnotation.parseAsync(info); + break; + case annotationTypes.UNDERLINE: + annot = yield UnderlineAnnotation.parseAsync(info); + break; + case annotationTypes.FREE_TEXT: + annot = yield FreeTextAnnotation.parseAsync(info, fontMap); + break; + } + return annot === null || annot === void 0 ? void 0 : annot.value; + }); + } + static ParseAnnotationFromDtoAsync(dto, fontMap) { + return __awaiter$o(this, void 0, void 0, function* () { + let annotation; + switch (dto.annotationType) { + case "/Stamp": + annotation = StampAnnotation.createFromDto(dto); + break; + case "/Text": + annotation = TextAnnotation.createFromDto(dto); + break; + case "/Ink": + annotation = InkAnnotation.createFromDto(dto); + break; + case "/Square": + annotation = SquareAnnotation.createFromDto(dto); + break; + case "/Circle": + annotation = CircleAnnotation.createFromDto(dto); + break; + case "/Polygon": + annotation = PolygonAnnotation.createFromDto(dto); + break; + case "/Polyline": + annotation = PolylineAnnotation.createFromDto(dto); + break; + case "/Line": + annotation = yield LineAnnotation.createFromDtoAsync(dto, fontMap); + break; + case "/Highlight": + annotation = HighlightAnnotation.createFromDto(dto); + break; + case "/Squiggly": + annotation = SquigglyAnnotation.createFromDto(dto); + break; + case "/Strikeout": + annotation = StrikeoutAnnotation.createFromDto(dto); + break; + case "/Underline": + annotation = UnderlineAnnotation.createFromDto(dto); + break; + default: + throw new Error(`Unsupported annotation type: ${dto.annotationType}`); + } + return annotation; + }); + } +} + +var __awaiter$n = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +const annotSelectionRequestEvent = "tspdf-annotselectionrequest"; +const annotFocusRequestEvent = "tspdf-annotfocusrequest"; +const annotChangeEvent = "tspdf-annotchange"; +const docServiceStateChangeEvent = "tspdf-docservicechange"; +class AnnotSelectionRequestEvent extends CustomEvent { + constructor(detail) { + super(annotSelectionRequestEvent, { detail }); + } +} +class AnnotFocusRequestEvent extends CustomEvent { + constructor(detail) { + super(annotFocusRequestEvent, { detail }); + } +} +class AnnotEvent extends CustomEvent { + constructor(detail) { + super(annotChangeEvent, { detail }); + } +} +class DocServiceStateChangeEvent extends CustomEvent { + constructor(detail) { + super(docServiceStateChangeEvent, { detail }); + } +} +class DocumentService { + get eventService() { + return this._eventService; + } + get userName() { + return this._userName; + } + get focusedAnnotation() { + return this._focusedAnnotation; + } + get selectedAnnotation() { + return this._selectedAnnotation; + } + get fontMap() { + return this._fontMap; + } + get size() { + var _a; + if ((_a = this._xrefs) === null || _a === void 0 ? void 0 : _a.length) { + return this._xrefs[0].size; + } + else { + return 0; + } + } + get encrypted() { + return !!this._encryption; + } + get authenticated() { + return !this._encryption || !!this._authResult; + } + constructor(eventService, data, userName) { + this._pageById = new Map(); + this._annotIdsByPageId = new Map(); + this._lastCommands = []; + this.getObjectParseInfoAsync = (id) => __awaiter$n(this, void 0, void 0, function* () { + var _a, _b, _c; + if (!id) { + return null; + } + const offset = (_a = this._referenceData) === null || _a === void 0 ? void 0 : _a.getOffset(id); + if (isNaN(offset)) { + return null; + } + const objectId = yield ObjectId.parseAsync(this._docParser, offset); + if (!objectId) { + return null; + } + const bounds = yield this._docParser.getIndirectObjectBoundsAtAsync(objectId.end + 1, true); + if (!bounds) { + return null; + } + const parseInfoGetterAsync = this.getObjectParseInfoAsync; + const info = { + parser: this._docParser, + bounds, + parseInfoGetterAsync: parseInfoGetterAsync, + cryptInfo: { + ref: { id: objectId.value.id, generation: objectId.value.generation }, + stringCryptor: (_b = this._authResult) === null || _b === void 0 ? void 0 : _b.stringCryptor, + streamCryptor: (_c = this._authResult) === null || _c === void 0 ? void 0 : _c.streamCryptor, + }, + }; + if (objectId.value.id === id) { + return info; + } + const stream = yield ObjectStream.parseAsync(info); + if (!stream) { + return; + } + const objectParseInfo = yield stream.value.getObjectDataAsync(id); + if (objectParseInfo) { + objectParseInfo.parseInfoGetterAsync = parseInfoGetterAsync; + return objectParseInfo; + } + return null; + }); + this.onAnnotationSelectionRequest = (e) => { + var _a; + if ((_a = e.detail) === null || _a === void 0 ? void 0 : _a.annotation) { + this.setSelectedAnnotation(e.detail.annotation); + } + else { + this.setSelectedAnnotation(null); + } + }; + this.onAnnotationFocusRequest = (e) => { + var _a; + if ((_a = e.detail) === null || _a === void 0 ? void 0 : _a.annotation) { + this.setFocusedAnnotation(e.detail.annotation); + } + else { + this.setFocusedAnnotation(null); + } + }; + if (!eventService) { + throw new Error("Event controller is not defined"); + } + this._data = data; + this._userName = userName; + this._fontMap = FontDict.newFontMap(); + this._eventService = eventService; + this._eventService.addListener(annotSelectionRequestEvent, this.onAnnotationSelectionRequest); + this._eventService.addListener(annotFocusRequestEvent, this.onAnnotationFocusRequest); + this._initPromise = this.initAsync(); + } + static createNewAsync(eventService, data, userName) { + return __awaiter$n(this, void 0, void 0, function* () { + const service = new DocumentService(eventService, data, userName); + yield service._initPromise; + return service; + }); + } + destroy() { + this._initPromise.then(() => { + var _a; + this._lastCommands.length = 0; + this.emitStateChanged(); + this.getAllSupportedAnnotationsAsync().then(map => map.forEach(x => { + x.$onEditAction = null; + x.$onRenderUpdatedAction = null; + })); + this._eventService.removeListener(annotSelectionRequestEvent, this.onAnnotationSelectionRequest); + this._eventService.removeListener(annotFocusRequestEvent, this.onAnnotationFocusRequest); + (_a = this._docParser) === null || _a === void 0 ? void 0 : _a.destroy(); + BgDataParser.destroy(); + }); + } + tryAuthenticate(password = "") { + if (!this.authenticated) { + return this.authenticate(password); + } + return true; + } + getPlainData() { + return this._data.slice(); + } + undoAsync() { + return __awaiter$n(this, void 0, void 0, function* () { + yield this.undoCommandAsync(); + }); + } + getDataWithoutSupportedAnnotationsAsync() { + return __awaiter$n(this, void 0, void 0, function* () { + const annotationMap = yield this.getSupportedAnnotationMapAsync(); + const annotationMarkedToDelete = []; + if (annotationMap === null || annotationMap === void 0 ? void 0 : annotationMap.size) { + annotationMap.forEach((v, k) => { + const annotations = v.slice(); + annotations.forEach(x => { + if (!x.deleted) { + x.markAsDeleted(true); + annotationMarkedToDelete.push(x); + } + }); + }); + } + const refined = yield this.getDataWithUpdatedAnnotationsAsync(); + annotationMarkedToDelete.forEach(x => x.markAsDeleted(false)); + return refined; + }); + } + getDataWithUpdatedAnnotationsAsync() { + return __awaiter$n(this, void 0, void 0, function* () { + const annotationMap = yield this.getSupportedAnnotationMapAsync(); + const updaterData = []; + annotationMap.forEach((pageAnnotations, pageId) => { + const page = this._pageById.get(pageId); + if (page) { + const allAnnotationIds = this._annotIdsByPageId.get(pageId).slice() || []; + updaterData.push({ + page, + allAnnotationIds, + supportedAnnotations: pageAnnotations || [], + }); + } + else { + console.log(`Page with id '${pageId}' not found`); + } + }); + const updater = new DataUpdater(this._data, this._xrefs[0], this._referenceData, this._authResult); + const updatedBytes = updater.getDataWithUpdatedAnnotations(updaterData); + return updatedBytes; + }); + } + getPageAnnotationsAsync(pageId) { + return __awaiter$n(this, void 0, void 0, function* () { + const annotationMap = yield this.getSupportedAnnotationMapAsync(); + const annotations = annotationMap.get(pageId); + return annotations || []; + }); + } + serializeAnnotationsAsync(addedOnly = false) { + return __awaiter$n(this, void 0, void 0, function* () { + const result = []; + const annotationMap = yield this.getSupportedAnnotationMapAsync(); + annotationMap.forEach((v, k) => { + v.forEach(x => { + if (!addedOnly || x.added) { + result.push(x.toDto()); + } + }); + }); + return result; + }); + } + appendAnnotationToPageAsync(pageId, annotation) { + return __awaiter$n(this, void 0, void 0, function* () { + yield this.appendAnnotationAsync(pageId, annotation, true, "add"); + }); + } + appendSerializedAnnotationsAsync(dtos) { + return __awaiter$n(this, void 0, void 0, function* () { + let annotation; + for (const dto of dtos) { + annotation = yield AnnotationParser.ParseAnnotationFromDtoAsync(dto, this._fontMap); + yield this.appendAnnotationAsync(dto.pageId, annotation, false, "import"); + } + }); + } + removeAnnotationFromPage(annotation) { + this.removeAnnotation(annotation, true); + } + removeSelectedAnnotation() { + const annotation = this._selectedAnnotation; + if (annotation) { + this.removeAnnotation(annotation, true); + } + } + setSelectedAnnotation(annotation) { + var _a, _b, _c; + if (annotation === this._selectedAnnotation) { + return; + } + if (this._selectedAnnotation) { + this._selectedAnnotation.$translationEnabled = false; + const oldSelectedSvg = (_b = (_a = this._selectedAnnotation) === null || _a === void 0 ? void 0 : _a.lastRenderResult) === null || _b === void 0 ? void 0 : _b.controls; + oldSelectedSvg === null || oldSelectedSvg === void 0 ? void 0 : oldSelectedSvg.classList.remove("selected"); + } + const newSelectedSvg = (_c = annotation === null || annotation === void 0 ? void 0 : annotation.lastRenderResult) === null || _c === void 0 ? void 0 : _c.controls; + if (!newSelectedSvg) { + this._selectedAnnotation = null; + } + else { + annotation.$translationEnabled = true; + newSelectedSvg.classList.add("selected"); + this._selectedAnnotation = annotation; + } + this._eventService.dispatchEvent(new AnnotEvent({ + type: "select", + annotations: this._selectedAnnotation + ? [this._selectedAnnotation.toDto()] + : [], + })); + return this._selectedAnnotation; + } + setFocusedAnnotation(annotation) { + var _a, _b, _c; + if (annotation === this._focusedAnnotation) { + return; + } + if (this._focusedAnnotation) { + this._focusedAnnotation.$translationEnabled = false; + const oldFocusedSvg = (_b = (_a = this._focusedAnnotation) === null || _a === void 0 ? void 0 : _a.lastRenderResult) === null || _b === void 0 ? void 0 : _b.controls; + oldFocusedSvg === null || oldFocusedSvg === void 0 ? void 0 : oldFocusedSvg.classList.remove("focused"); + } + const newFocusedSvg = (_c = annotation === null || annotation === void 0 ? void 0 : annotation.lastRenderResult) === null || _c === void 0 ? void 0 : _c.controls; + if (!newFocusedSvg) { + this._focusedAnnotation = null; + } + else { + annotation.$translationEnabled = true; + newFocusedSvg.classList.add("focused"); + this._focusedAnnotation = annotation; + } + this._eventService.dispatchEvent(new AnnotEvent({ + type: "focus", + annotations: this._focusedAnnotation + ? [this._focusedAnnotation.toDto()] + : [], + })); + return this._focusedAnnotation; + } + getSelectedAnnotationTextContent() { + var _a, _b; + return (_b = (_a = this._selectedAnnotation) === null || _a === void 0 ? void 0 : _a.Contents) === null || _b === void 0 ? void 0 : _b.literal; + } + setSelectedAnnotationTextContentAsync(text) { + var _a; + return __awaiter$n(this, void 0, void 0, function* () { + yield ((_a = this._selectedAnnotation) === null || _a === void 0 ? void 0 : _a.setTextContentAsync(text)); + }); + } + parseXrefsAsync() { + return __awaiter$n(this, void 0, void 0, function* () { + const xrefParser = new XrefParser(this._docParser); + this._version = yield xrefParser.getPdfVersionAsync(); + if (!this._version) { + throw new Error("Error parsing PDF version number"); + } + const lastXrefIndex = yield xrefParser.getLastXrefIndexAsync(); + if (!lastXrefIndex) { + { + throw new Error("File doesn't contain update section"); + } + } + const xrefs = yield xrefParser.parseAllXrefsAsync(lastXrefIndex.value); + if (!xrefs.length) { + { + throw new Error("Failed to parse cross-reference sections"); + } + } + this._xrefs = xrefs; + this._referenceData = new ReferenceData(xrefs); + }); + } + initAsync() { + var _a; + return __awaiter$n(this, void 0, void 0, function* () { + this._docParser = (_a = BgDataParser.tryGetParser(this._data.slice())) !== null && _a !== void 0 ? _a : SyncDataParser.tryGetParser(this._data); + yield this.parseXrefsAsync(); + yield this.parseEncryptionAsync(); + }); + } + pushCommand(command) { + this._lastCommands.push(command); + this.emitStateChanged(); + } + undoCommandAsync() { + return __awaiter$n(this, void 0, void 0, function* () { + if (!this._lastCommands.length) { + return; + } + const lastCommand = this._lastCommands.pop(); + yield lastCommand.undo(); + this.emitStateChanged(); + }); + } + emitStateChanged() { + this._eventService.dispatchEvent(new DocServiceStateChangeEvent({ + undoableCount: this._lastCommands.length, + })); + } + appendAnnotationAsync(pageId, annotation, undoable, raiseEvent) { + return __awaiter$n(this, void 0, void 0, function* () { + if (!annotation) { + throw new Error("Annotation is not defined"); + } + const page = this._pageById.get(pageId); + if (!page) { + throw new Error(`Page with id ${pageId} is not found`); + } + annotation.markAsDeleted(false); + annotation.$pageId = page.id; + annotation.$onEditAction = this.getOnAnnotEditAction(annotation); + annotation.$onRenderUpdatedAction = this.getOnAnnotRenderUpdatedAction(annotation); + const annotationMap = yield this.getSupportedAnnotationMapAsync(); + const pageAnnotations = annotationMap.get(pageId); + if (pageAnnotations) { + pageAnnotations.push(annotation); + } + else { + annotationMap.set(pageId, [annotation]); + } + if (undoable) { + this.pushCommand({ + timestamp: Date.now(), + undo: () => __awaiter$n(this, void 0, void 0, function* () { + this.removeAnnotation(annotation, false); + if (this.selectedAnnotation === annotation) { + this.setSelectedAnnotation(null); + } + }) + }); + } + this._eventService.dispatchEvent(new AnnotEvent({ + type: raiseEvent, + annotations: [annotation.toDto()], + })); + }); + } + removeAnnotation(annotation, undoable) { + if (!annotation) { + return; + } + annotation.markAsDeleted(true); + this.setSelectedAnnotation(null); + if (undoable) { + this.pushCommand({ + timestamp: Date.now(), + undo: () => __awaiter$n(this, void 0, void 0, function* () { + yield this.appendAnnotationAsync(annotation.$pageId, annotation, false, "add"); + }) + }); + } + this._eventService.dispatchEvent(new AnnotEvent({ + type: "delete", + annotations: [annotation.toDto()], + })); + } + getOnAnnotEditAction(annotation) { + if (!annotation) { + return null; + } + return (undo) => { + if (!annotation.$pageId) { + return; + } + if (undo) { + this.pushCommand({ timestamp: Date.now(), undo }); + } + this._eventService.dispatchEvent(new AnnotEvent({ + type: "edit", + annotations: [annotation.toDto()], + })); + }; + } + getOnAnnotRenderUpdatedAction(annotation) { + if (!annotation) { + return null; + } + return () => this._eventService.dispatchEvent(new AnnotEvent({ + type: "render", + annotations: [annotation.toDto()], + })); + } + authenticate(password) { + if (this.authenticated) { + return true; + } + const cryptOptions = this._encryption.toCryptOptions(); + const fileId = this._xrefs[0].id[0].hex; + const cryptorSource = new DataCryptHandler(cryptOptions, fileId); + this._authResult = cryptorSource.authenticate(password); + return this.authenticated; + } + checkAuthentication() { + if (!this.authenticated) { + throw new Error("Unauthorized access to file data"); + } + } + parseEncryptionAsync() { + return __awaiter$n(this, void 0, void 0, function* () { + const encryptionId = this._xrefs[0].encrypt; + if (!encryptionId) { + return; + } + const encryptionParseInfo = yield this.getObjectParseInfoAsync(encryptionId.id); + const encryption = yield EncryptionDict.parseAsync(encryptionParseInfo); + if (!encryption) { + throw new Error("Encryption dict can't be parsed"); + } + this._encryption = encryption.value; + }); + } + parsePagesAsync(output, tree) { + return __awaiter$n(this, void 0, void 0, function* () { + if (!tree.Kids.length) { + return; + } + for (const kid of tree.Kids) { + const parseInfo = yield this.getObjectParseInfoAsync(kid.id); + if (!parseInfo) { + continue; + } + const type = yield parseInfo.parser.parseDictTypeAsync(parseInfo.bounds); + if (type === dictTypes.PAGE_TREE) { + const kidTree = yield PageTreeDict.parseAsync(parseInfo); + if (kidTree) { + yield this.parsePagesAsync(output, kidTree.value); + } + } + else if (type === dictTypes.PAGE) { + const kidPage = yield PageDict.parseAsync(parseInfo); + if (kidPage) { + output.push(kidPage.value); + } + } + } + }); + } + ; + parsePageTreeAsync() { + return __awaiter$n(this, void 0, void 0, function* () { + const catalogId = this._xrefs[0].root; + const catalogParseInfo = yield this.getObjectParseInfoAsync(catalogId.id); + const catalog = yield CatalogDict.parseAsync(catalogParseInfo); + if (!catalog) { + throw new Error("Document root catalog not found"); + } + this._catalog = catalog.value; + const pageRootId = catalog.value.Pages; + const pageRootParseInfo = yield this.getObjectParseInfoAsync(pageRootId.id); + const pageRootTree = yield PageTreeDict.parseAsync(pageRootParseInfo); + if (!pageRootTree) { + throw new Error("Document root page tree not found"); + } + const pages = []; + yield this.parsePagesAsync(pages, pageRootTree.value); + this._pages = pages; + this._pageById.clear(); + pages.forEach(x => this._pageById.set(x.ref.id, x)); + }); + } + parseSupportedAnnotationsAsync() { + var _a; + return __awaiter$n(this, void 0, void 0, function* () { + this.checkAuthentication(); + if (!this._catalog) { + yield this.parsePageTreeAsync(); + } + const annotIdsByPageId = new Map(); + const annotationMap = new Map(); + for (const page of this._pages) { + const annotationIds = []; + if (Array.isArray(page.Annots)) { + annotationIds.push(...page.Annots); + } + else if (page.Annots instanceof ObjectId) { + const parseInfo = yield this.getObjectParseInfoAsync(page.Annots.id); + if (parseInfo) { + const annotationRefs = yield ObjectId.parseRefArrayAsync(parseInfo.parser, parseInfo.bounds.contentStart); + if ((_a = annotationRefs === null || annotationRefs === void 0 ? void 0 : annotationRefs.value) === null || _a === void 0 ? void 0 : _a.length) { + annotationIds.push(...annotationRefs.value); + } + } + } + annotIdsByPageId.set(page.ref.id, annotationIds); + const processAnnotation = (objectId) => __awaiter$n(this, void 0, void 0, function* () { + const info = yield this.getObjectParseInfoAsync(objectId.id); + info.rect = page.MediaBox; + const annot = yield AnnotationParser.ParseAnnotationFromInfoAsync(info, this._fontMap); + if (annot) { + annot.$pageId = page.id; + annot.$onEditAction = this.getOnAnnotEditAction(annot); + annot.$onRenderUpdatedAction = this.getOnAnnotRenderUpdatedAction(annot); + } + return annot; + }); + const annotations = (yield Promise.all(annotationIds.map(x => processAnnotation(x)))) + .filter(x => x); + annotationMap.set(page.id, annotations); + } + this._annotIdsByPageId = annotIdsByPageId; + this._supportedAnnotsByPageId = annotationMap; + }); + } + getSupportedAnnotationMapAsync() { + return __awaiter$n(this, void 0, void 0, function* () { + this.checkAuthentication(); + if (this._supportedAnnotsByPageId) { + return this._supportedAnnotsByPageId; + } + yield this.parseSupportedAnnotationsAsync(); + return this._supportedAnnotsByPageId; + }); + } + getAllSupportedAnnotationsAsync() { + return __awaiter$n(this, void 0, void 0, function* () { + const result = []; + const annotationMap = yield this.getSupportedAnnotationMapAsync(); + annotationMap.forEach((v, k) => { + result.push(...v); + }); + return result; + }); + } +} + +var __awaiter$m = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class PageAnnotationView { + constructor(docService, pageInfo, pageDimensions) { + this._rendered = new Set(); + this.onAnnotationSelectionChange = (e) => { + var _a; + if (!this._destroyed && e.detail.type === "select") { + if ((_a = e.detail.annotations) === null || _a === void 0 ? void 0 : _a.length) { + this._container.style.touchAction = "none"; + } + else { + this._container.style.touchAction = ""; + } + } + }; + if (!docService || !pageInfo || !pageDimensions) { + throw new Error("Required argument not found"); + } + this._pageInfo = pageInfo; + this._viewbox = [0, 0, pageDimensions.x, pageDimensions.y]; + this._docService = docService; + this._container = document.createElement("div"); + this._container.classList.add("page-annotations"); + this._svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + this._svg.classList.add("page-annotations-controls"); + this._svg.setAttribute("data-page-id", pageInfo.id + ""); + this._svg.setAttribute("viewBox", `0 0 ${pageDimensions.x} ${pageDimensions.y}`); + applyFlipYToElement(this._svg); + this._svg.addEventListener("pointerdown", (e) => { + if (e.target === this._svg) { + docService.setSelectedAnnotation(null); + } + }); + } + destroy() { + this._destroyed = true; + this.remove(); + this._container = null; + this._rendered.forEach(x => { + x.$onPointerDownAction = null; + x.$onPointerEnterAction = null; + x.$onPointerLeaveAction = null; + }); + this._rendered.clear(); + } + remove() { + var _a; + (_a = this._container) === null || _a === void 0 ? void 0 : _a.remove(); + this._docService.eventService.removeListener(annotChangeEvent, this.onAnnotationSelectionChange); + } + appendAsync(parent) { + var _a; + return __awaiter$m(this, void 0, void 0, function* () { + if (this._destroyed) { + return; + } + parent.append(this._container); + const renderResult = yield this.renderAnnotationsAsync(); + if (!renderResult) { + (_a = this._container) === null || _a === void 0 ? void 0 : _a.remove(); + return; + } + this._docService.eventService.addListener(annotChangeEvent, this.onAnnotationSelectionChange); + }); + } + renderAnnotationsAsync() { + return __awaiter$m(this, void 0, void 0, function* () { + if (this._destroyed) { + return false; + } + this.clear(); + const annotations = (yield this._docService + .getPageAnnotationsAsync(this._pageInfo.id)) + .filter(x => !x.deleted) + || []; + const processAnnotation = (annotation) => __awaiter$m(this, void 0, void 0, function* () { + let renderResult; + if (!this._rendered.has(annotation)) { + annotation.$onPointerDownAction = (e) => { + this._docService.eventService.dispatchEvent(new AnnotSelectionRequestEvent({ annotation })); + }; + annotation.$onPointerEnterAction = (e) => { + this._docService.eventService.dispatchEvent(new AnnotFocusRequestEvent({ annotation })); + }; + annotation.$onPointerLeaveAction = (e) => { + this._docService.eventService.dispatchEvent(new AnnotFocusRequestEvent({ annotation: null })); + }; + renderResult = yield annotation.renderAsync(this._pageInfo); + } + else { + renderResult = annotation.lastRenderResult || (yield annotation.renderAsync(this._pageInfo)); + } + if (renderResult && !this._destroyed) { + this._rendered.add(annotation); + this._svg.append(renderResult.controls); + this._container.append(renderResult.content); + } + }); + yield Promise.all(annotations.map(x => processAnnotation(x))); + if (this._destroyed) { + return false; + } + this._container.append(this._svg); + return true; + }); + } + clear() { + this._container.innerHTML = ""; + this._svg.innerHTML = ""; + } +} + +var __awaiter$l = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class PageComparisonView { + constructor(comparisonService, subjectPageInfo, pageDimensions) { + this.onAreaPointerDown = (e) => { + const area = e.target.closest(".comparison-area"); + if (!area) { + return; + } + if (area.classList.contains("transparent")) { + area.classList.remove("transparent"); + area.classList.add("opaque"); + } + else if (area.classList.contains("opaque")) { + area.classList.remove("opaque"); + } + else { + area.classList.add("transparent"); + } + }; + this.onAreaPointerEnter = (e) => { + const area = e.target; + area.classList.remove("opaque"); + area.classList.add("transparent"); + }; + this.onAreaPointerLeave = (e) => { + const area = e.target; + area.classList.remove("opaque"); + area.classList.remove("transparent"); + }; + if (!comparisonService || !subjectPageInfo || !pageDimensions) { + throw new Error("Required argument not found"); + } + this._comparisonService = comparisonService; + this._subjectPageInfo = subjectPageInfo; + this._subjectPageHeight = pageDimensions.y; + this._container = document.createElement("div"); + this._container.classList.add("page-comparison"); + this._svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + this._svg.classList.add("page-comparison-areas"); + this._svg.setAttribute("data-page-id", subjectPageInfo.id + ""); + this._svg.setAttribute("viewBox", `0 0 ${pageDimensions.x} ${pageDimensions.y}`); + applyFlipYToElement(this._svg); + this._container.append(this._svg); + } + destroy() { + this._destroyed = true; + this.remove(); + this._container = null; + this._lastRenderResult = null; + } + remove() { + var _a; + (_a = this._container) === null || _a === void 0 ? void 0 : _a.remove(); + } + appendAsync(parent, agentPageProxy, scale) { + var _a; + return __awaiter$l(this, void 0, void 0, function* () { + this.remove(); + if (this._destroyed || !agentPageProxy) { + return; + } + const comparisonResult = this._comparisonService + .getComparisonResultForPage(this._subjectPageInfo.index); + if (!((_a = comparisonResult === null || comparisonResult === void 0 ? void 0 : comparisonResult.areas) === null || _a === void 0 ? void 0 : _a.length)) { + return; + } + if (!this._lastRenderResult + || this._lastRenderResult.pageProxy !== agentPageProxy + || this._lastRenderResult.scale !== scale) { + this._lastRenderResult = yield this.renderPageAsync(agentPageProxy, scale); + } + if (!this._lastRenderResult) { + return; + } + this.clear(); + parent.append(this._container); + const [offsetX, offsetY] = comparisonResult.offset; + for (const comparisonArea of comparisonResult.areas) { + const changedAreaGroup = document.createElementNS("http://www.w3.org/2000/svg", "g"); + changedAreaGroup.classList.add("comparison-area"); + changedAreaGroup.addEventListener("pointerdown", this.onAreaPointerDown); + changedAreaGroup.addEventListener("pointerenter", this.onAreaPointerEnter); + changedAreaGroup.addEventListener("pointerleave", this.onAreaPointerLeave); + const sx = comparisonArea[0]; + const sy = comparisonArea[1]; + const syPdf = this._subjectPageHeight - Math.max(comparisonArea[1], comparisonArea[3]); + const sw = Math.max(Math.abs(comparisonArea[2] - comparisonArea[0]), 1); + const sh = Math.max(Math.abs(comparisonArea[3] - comparisonArea[1]), 1); + const swScaled = sw * scale; + const shScaled = sh * scale; + const tmpCanvas = document.createElement("canvas"); + tmpCanvas.width = swScaled; + tmpCanvas.height = shScaled; + tmpCanvas.getContext("2d").scale(1, -1); + tmpCanvas.getContext("2d").drawImage(this._lastRenderResult.canvas, (sx + offsetX) * scale, (sy + offsetY) * scale, swScaled, shScaled, 0, 0, swScaled, -shScaled); + const imageUrl = tmpCanvas.toDataURL("image/png"); + const image = document.createElementNS("http://www.w3.org/2000/svg", "image"); + image.classList.add("comparison-area-image"); + image.setAttribute("x", sx + ""); + image.setAttribute("y", syPdf + ""); + image.setAttribute("width", sw + ""); + image.setAttribute("height", sh + ""); + image.setAttribute("href", imageUrl); + const area = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + area.classList.add("comparison-area-rect"); + area.setAttribute("x", sx + ""); + area.setAttribute("y", syPdf + ""); + area.setAttribute("width", sw + ""); + area.setAttribute("height", sh + ""); + changedAreaGroup.append(image); + changedAreaGroup.append(area); + this._svg.append(changedAreaGroup); + } + }); + } + clear() { + this._svg.innerHTML = ""; + } + renderPageAsync(pageProxy, scale) { + return __awaiter$l(this, void 0, void 0, function* () { + if (!pageProxy) { + return null; + } + const viewport = pageProxy.getViewport({ scale, rotation: 0 }); + const { width, height } = viewport; + const canvas = document.createElement("canvas"); + canvas.width = width; + canvas.height = height; + const canvasCtx = canvas.getContext("2d"); + const params = { + canvasContext: canvasCtx, + viewport: viewport, + enableWebGL: true, + }; + const renderTask = pageProxy.render(params); + yield renderTask.promise; + return { + canvas, + pageProxy, + scale, + }; + }); + } +} + +var __awaiter$k = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class PageView { + get previewContainer() { + return this._previewContainer; + } + get viewContainer() { + return this._viewOuterContainer; + } + set _viewRendered(value) { + this.$viewRendered = value; + this._viewOuterContainer.setAttribute("data-loaded", value + ""); + } + get _viewRendered() { + return this.$viewRendered; + } + get rotation() { + return this._rotation; + } + set rotation(value) { + if (!PageView.validRotationValues.includes(value) + || this._rotation === value) { + return; + } + this._rotation = value; + this.refreshDimensions(); + } + get scale() { + return this._scale; + } + set scale(value) { + if (value <= 0 || this._scale === value) { + return; + } + this._scale = value; + this.refreshDimensions(); + } + get width() { + return this._dimensions.width; + } + get height() { + return this._dimensions.height; + } + get modeNotChanged() { + return this._lastRenderMode === this._modeService.mode; + } + get viewValid() { + return this._dimensionsIsValid && this._viewRendered; + } + constructor(modeService, docManagerService, pageIndex, previewWidth) { + this._rotation = 0; + this._scale = 1; + if (!modeService) { + throw new Error("Mode service is not defined"); + } + if (!docManagerService) { + throw new Error("Loader service is not defined"); + } + this._modeService = modeService; + this._docManagerService = docManagerService; + const pageProxy = docManagerService.getPageProxy("main", pageIndex); + if (!pageProxy) { + throw new Error("Page proxy is not defined"); + } + this._pageProxy = pageProxy; + this._defaultViewport = pageProxy.getViewport({ scale: 1, rotation: 0 }); + this._rotation = pageProxy.rotate; + this.index = pageIndex; + this.number = pageProxy.pageNumber; + this.id = pageProxy.ref["num"]; + this.generation = pageProxy.ref["gen"]; + this.initDom(previewWidth); + } + destroy() { + this._destroyed = true; + this._previewContainer.remove(); + this._viewOuterContainer.remove(); + this._pageProxy.cleanup(); + } + renderPreviewAsync(force = false) { + return __awaiter$k(this, void 0, void 0, function* () { + if (this._renderPromise) { + if (force) { + this.cancelRenderTask(); + } + yield this._renderPromise; + } + if (!force && this._previewRendered) { + return; + } + this._renderPromise = this.runPreviewRenderAsync(); + return this._renderPromise; + }); + } + renderViewAsync(force = false) { + return __awaiter$k(this, void 0, void 0, function* () { + if (this._renderPromise) { + if (force) { + this.cancelRenderTask(); + } + yield this._renderPromise; + } + if (!force && this.viewValid && this.modeNotChanged) { + return; + } + this._renderPromise = this.runViewRenderAsync(force); + return this._renderPromise; + }); + } + clearPreview() { + this._previewContainer.innerHTML = ""; + } + clearView() { + var _a, _b, _c, _d; + (_a = this._comparison) === null || _a === void 0 ? void 0 : _a.destroy(); + this._comparison = null; + (_b = this._annotations) === null || _b === void 0 ? void 0 : _b.destroy(); + this._annotations = null; + (_c = this._text) === null || _c === void 0 ? void 0 : _c.destroy(); + this._text = null; + (_d = this._viewCanvas) === null || _d === void 0 ? void 0 : _d.remove(); + this._viewRendered = false; + } + rotateClockwise() { + if (!this._rotation) { + this.rotation = 270; + } + else { + this.rotation = this._rotation - 90; + } + } + rotateCounterClockwise() { + if (this._rotation === 270) { + this.rotation = 0; + } + else { + this.rotation = (this._rotation || 0) + 90; + } + } + initDom(previewWidth) { + const { width, height } = this._defaultViewport; + previewWidth = Math.max(previewWidth !== null && previewWidth !== void 0 ? previewWidth : 0, 50); + const previewHeight = previewWidth * (height / width); + this._dimensions = { width, height, previewWidth, previewHeight }; + this._previewContainer = document.createElement("div"); + this._previewContainer.classList.add("page-preview"); + this._previewContainer.setAttribute("data-page-number", this.number + ""); + this._previewContainer.setAttribute("data-page-id", this.id + ""); + this._previewContainer.setAttribute("data-page-gen", this.generation + ""); + this._previewContainer.style.width = this._dimensions.previewWidth + "px"; + this._previewContainer.style.height = this._dimensions.previewHeight + "px"; + this._viewOuterContainer = document.createElement("div"); + this._viewOuterContainer.classList.add("page-container"); + this._viewOuterContainer.setAttribute("data-page-number", this.number + ""); + this._viewOuterContainer.setAttribute("data-page-id", this.id + ""); + this._viewOuterContainer.setAttribute("data-page-gen", this.generation + ""); + this._viewInnerContainer = document.createElement("div"); + this._viewInnerContainer.classList.add("page"); + this._viewInnerContainer.setAttribute("data-page-number", this.number + ""); + this._viewInnerContainer.setAttribute("data-page-id", this.id + ""); + this._viewInnerContainer.setAttribute("data-page-gen", this.generation + ""); + this._viewOuterContainer.append(this._viewInnerContainer); + this.refreshDimensions(); + } + refreshDimensions() { + const dpr = window.devicePixelRatio; + this._currentViewport = this._defaultViewport.clone({ + scale: this.scale * dpr, + }); + this._dimensions.scaledWidth = this._dimensions.width * this._scale; + this._dimensions.scaledHeight = this._dimensions.height * this._scale; + this._dimensions.scaledDprWidth = this._dimensions.scaledWidth * dpr; + this._dimensions.scaledDprHeight = this._dimensions.scaledHeight * dpr; + const w = this._dimensions.scaledWidth + "px"; + const h = this._dimensions.scaledHeight + "px"; + if (this._viewCanvas) { + this._viewCanvas.style.width = w; + this._viewCanvas.style.height = h; + } + this._viewInnerContainer.style.width = w; + this._viewInnerContainer.style.height = h; + switch (this.rotation) { + case 0: + this._viewOuterContainer.style.width = w; + this._viewOuterContainer.style.height = h; + this._viewInnerContainer.style.transform = ""; + break; + case 90: + this._viewOuterContainer.style.width = h; + this._viewOuterContainer.style.height = w; + this._viewInnerContainer.style.transform = "rotate(90deg) translateY(-100%)"; + break; + case 180: + this._viewOuterContainer.style.width = w; + this._viewOuterContainer.style.height = h; + this._viewInnerContainer.style.transform = "rotate(180deg) translateX(-100%) translateY(-100%)"; + break; + case 270: + this._viewOuterContainer.style.width = h; + this._viewOuterContainer.style.height = w; + this._viewInnerContainer.style.transform = "rotate(270deg) translateX(-100%)"; + break; + default: + throw new Error(`Invalid rotation degree: ${this.rotation}`); + } + this._dimensionsIsValid = false; + } + cancelRenderTask() { + if (this._renderTask) { + this._renderTask.cancel(); + this._renderTask = null; + } + } + runRenderTaskAsync(renderParams) { + return __awaiter$k(this, void 0, void 0, function* () { + if (this._destroyed) { + return false; + } + this.cancelRenderTask(); + try { + this._renderTask = this._pageProxy.render(renderParams); + yield this._renderTask.promise; + } + catch (error) { + if (error instanceof pdfExports.RenderingCancelledException) { + return false; + } + else { + console.log(error.message); + } + } + finally { + this._renderTask = null; + } + return true; + }); + } + createPreviewCanvas() { + const canvas = document.createElement("canvas"); + canvas.classList.add("page-canvas"); + const dpr = window.devicePixelRatio; + const { previewWidth: width, previewHeight: height } = this._dimensions; + canvas.style.width = width + "px"; + canvas.style.height = height + "px"; + canvas.width = width * dpr; + canvas.height = height * dpr; + return canvas; + } + createViewCanvas() { + const canvas = document.createElement("canvas"); + canvas.classList.add("page-canvas"); + canvas.style.width = this._dimensions.scaledWidth + "px"; + canvas.style.height = this._dimensions.scaledHeight + "px"; + canvas.width = this._dimensions.scaledDprWidth; + canvas.height = this._dimensions.scaledDprHeight; + return canvas; + } + runPreviewRenderAsync() { + return __awaiter$k(this, void 0, void 0, function* () { + if (this._destroyed) { + return; + } + const canvas = this.createPreviewCanvas(); + const params = { + canvasContext: canvas.getContext("2d"), + viewport: this._defaultViewport.clone({ scale: canvas.width / this._dimensions.width, rotation: 0 }), + }; + const result = yield this.runRenderTaskAsync(params); + if (!result) { + this._previewRendered = false; + return; + } + this._previewContainer.innerHTML = ""; + this._previewContainer.append(canvas); + this._previewRendered = true; + }); + } + runViewRenderAsync(force) { + var _a; + return __awaiter$k(this, void 0, void 0, function* () { + if (this._destroyed) { + return; + } + const mode = this._modeService.mode; + const scale = this._scale; + this.clearTextLayer(); + if (force || !this.viewValid) { + const canvasRendered = yield this.renderCanvasLayerAsync(scale); + if (!canvasRendered) { + return; + } + } + if (mode === "text" + || mode === "annotation") { + yield this.renderTextLayerAsync(scale); + } + if (mode !== "comparison") { + yield this.renderAnnotationLayerAsync(); + } + else { + (_a = this._annotations) === null || _a === void 0 ? void 0 : _a.remove(); + yield this.renderComparisonLayerAsync(); + } + this._lastRenderMode = mode; + if (scale === this._scale) { + this._dimensionsIsValid = true; + } + }); + } + clearTextLayer() { + var _a, _b; + (_a = this._text) === null || _a === void 0 ? void 0 : _a.destroy(); + (_b = this._text) === null || _b === void 0 ? void 0 : _b.remove(); + } + renderCanvasLayerAsync(scale) { + var _a; + return __awaiter$k(this, void 0, void 0, function* () { + const canvas = this.createViewCanvas(); + const params = { + canvasContext: canvas.getContext("2d"), + viewport: this._currentViewport, + enableWebGL: true, + }; + const result = yield this.runRenderTaskAsync(params); + if (!result || scale !== this._scale) { + return false; + } + (_a = this._viewCanvas) === null || _a === void 0 ? void 0 : _a.remove(); + this._viewInnerContainer.append(canvas); + this._viewCanvas = canvas; + this._viewRendered = true; + return true; + }); + } + renderTextLayerAsync(scale) { + return __awaiter$k(this, void 0, void 0, function* () { + this._text = yield PageTextView.appendPageTextAsync(this._pageProxy, this._viewInnerContainer, scale); + }); + } + renderAnnotationLayerAsync() { + return __awaiter$k(this, void 0, void 0, function* () { + if (!this._annotations) { + const { width: x, height: y } = this._dimensions; + this._annotations = new PageAnnotationView(this._docManagerService.docService, this, new u(x, y)); + } + yield this._annotations.appendAsync(this._viewInnerContainer); + }); + } + renderComparisonLayerAsync() { + var _a; + return __awaiter$k(this, void 0, void 0, function* () { + const comparisonPageProxy = this._docManagerService.getPageProxy("compared", this.index); + if (!comparisonPageProxy) { + (_a = this._comparison) === null || _a === void 0 ? void 0 : _a.remove(); + return; + } + if (!this._comparison) { + const { width: x, height: y } = this._dimensions; + this._comparison = new PageComparisonView(this._docManagerService.comparisonService, this, new u(x, y)); + } + yield this._comparison.appendAsync(this._viewInnerContainer, comparisonPageProxy, this._scale); + }); + } +} +PageView.validRotationValues = [0, 90, 180, 270]; + +var __awaiter$j = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +const currentPageChangeRequestEvent = "tspdf-currentpagechangerequest"; +class CurrentPageChangeRequestEvent extends CustomEvent { + constructor(detail) { + super(currentPageChangeRequestEvent, { detail }); + } +} +const currentPageChangeEvent = "tspdf-currentpagechange"; +class CurrentPageChangeEvent extends CustomEvent { + constructor(detail) { + super(currentPageChangeEvent, { detail }); + } +} +const pagesLoadedEvent = "tspdf-pagesloaded"; +class PagesLoadedEvent extends CustomEvent { + constructor(detail) { + super(pagesLoadedEvent, { detail }); + } +} +const pagesRenderedEvent = "tspdf-pagesrendered"; +class PagesRenderedEvent extends CustomEvent { + constructor(detail) { + super(pagesRenderedEvent, { detail }); + } +} +const scaleChangedEvent = "tspdf-scalechanged"; +class ScaleChangedEvent extends CustomEvent { + constructor(detail) { + super(scaleChangedEvent, { detail }); + } +} +class PageService { + get eventService() { + return this._eventService; + } + get currentPageIndex() { + return this._currentPageIndex || 0; + } + get pages() { + return this._pages.slice(); + } + set pages(value) { + this._pages.forEach(x => x.destroy()); + this._pages = value.slice(); + this._eventService.dispatchEvent(new PagesLoadedEvent({ pages: value.slice() })); + this.setCurrentPageIndex(0); + } + get renderedPages() { + return this._renderedPages.slice(); + } + get length() { + return this._pages.length || 0; + } + get scale() { + var _a; + return ((_a = this._renderedPages[0]) === null || _a === void 0 ? void 0 : _a.scale) || 1; + } + set scale(value) { + if (!value || isNaN(value)) { + value = 1; + } + this._pages.forEach(x => x.scale = value); + this._eventService.dispatchEvent(new ScaleChangedEvent({ scale: value })); + } + constructor(eventService, modeService, docManagerService, options) { + this._pages = []; + this._renderedPages = []; + if (!eventService) { + throw new Error("Event service is not defined"); + } + if (!modeService) { + throw new Error("Mode service is not defined"); + } + if (!docManagerService) { + throw new Error("Doc manager service is not defined"); + } + this._modeService = modeService; + this._eventService = eventService; + this._docManagerService = docManagerService; + this._previewCanvasWidth = (options === null || options === void 0 ? void 0 : options.previewCanvasWidth) || 100; + this._visibleAdjPages = (options === null || options === void 0 ? void 0 : options.visibleAdjPages) || 0; + } + destroy() { + this._pages.forEach(x => x.destroy); + } + getPage(index) { + return this._pages[index]; + } + getCurrentPage() { + return this._pages[this._currentPageIndex]; + } + reloadPagesAsync() { + return __awaiter$j(this, void 0, void 0, function* () { + const docPagesNumber = this._docManagerService.pageCount; + const pages = []; + if (docPagesNumber) { + for (let i = 0; i < docPagesNumber; i++) { + const page = new PageView(this._modeService, this._docManagerService, i, this._previewCanvasWidth); + pages.push(page); + } + } + this.pages = pages; + }); + } + requestSetCurrentPageIndex(index) { + index = n$1(index || 0, 0, this._pages.length - 1); + if (index !== this._currentPageIndex) { + this._eventService.dispatchEvent(new CurrentPageChangeRequestEvent({ pageIndex: index })); + } + } + renderVisiblePages(container, force) { + const pages = this._pages; + const { minFinal: minPageNumber, maxFinal: maxPageNumber } = this.getVisiblePageIndices(container); + const renderedPages = []; + for (let i = 0; i < pages.length; i++) { + const page = pages[i]; + if (i >= minPageNumber && i <= maxPageNumber) { + renderedPages.push(page); + page.renderViewAsync(force); + } + else { + page.clearView(); + } + } + this._renderedPages = renderedPages; + this._eventService.dispatchEvent(new PagesRenderedEvent({ pages: renderedPages.slice() })); + this.updateCurrentPage(container); + } + renderVisiblePreviews(container) { + const pages = this._pages; + const visible = this.getVisiblePageIndices(container, true); + for (let i = 0; i < pages.length; i++) { + const page = pages[i]; + if (i >= visible.minFinal && i <= visible.maxFinal) { + page.renderPreviewAsync(); + } + } + } + renderSpecifiedPages(pageIdSet) { + if (!(pageIdSet === null || pageIdSet === void 0 ? void 0 : pageIdSet.size)) { + return; + } + this._renderedPages.forEach(x => { + if (pageIdSet.has(x.id)) { + x.renderViewAsync(true); + } + }); + } + getPageCoordsUnderPointer(pointerX, pointerY) { + for (const page of this._renderedPages) { + const { left: pageRectMinX, top: pageRectMinY, width: pageRectWidth, height: pageRectHeight } = page.viewContainer.getBoundingClientRect(); + const pageRectMaxX = pageRectMinX + pageRectWidth; + const pageRectMaxY = pageRectMinY + pageRectHeight; + if (pointerX < pageRectMinX || pointerX > pageRectMaxX) { + continue; + } + if (pointerY < pageRectMinY || pointerY > pageRectMaxY) { + continue; + } + let x; + let y; + const scale = this.scale; + const rotation = page.rotation; + switch (rotation) { + case 0: + x = (pointerX - pageRectMinX) / scale; + y = (pageRectMaxY - pointerY) / scale; + break; + case 90: + x = (pointerY - pageRectMinY) / scale; + y = (pointerX - pageRectMinX) / scale; + break; + case 180: + x = (pageRectMaxX - pointerX) / scale; + y = (pointerY - pageRectMinY) / scale; + break; + case 270: + x = (pageRectMaxY - pointerY) / scale; + y = (pageRectMaxX - pointerX) / scale; + break; + default: + throw new Error(`Invalid rotation degree: ${rotation}`); + } + return { + pageId: page.id, + pageX: x, + pageY: y, + pageRotation: rotation, + }; + } + return null; + } + setCurrentPageIndex(index) { + var _a, _b; + const newIndex = n$1(index || 0, 0, this._pages.length - 1); + if (newIndex !== this._currentPageIndex) { + const oldIndex = this._currentPageIndex; + this._currentPageIndex = newIndex; + (_a = this._pages[oldIndex]) === null || _a === void 0 ? void 0 : _a.previewContainer.classList.remove("current"); + (_b = this._pages[newIndex]) === null || _b === void 0 ? void 0 : _b.previewContainer.classList.add("current"); + this._eventService.dispatchEvent(new CurrentPageChangeEvent({ oldIndex, newIndex })); + } + } + getVisiblePageIndices(container, preview = false) { + const pages = this._pages; + if (!pages.length) { + return { + actual: [], + minFinal: null, + maxFinal: null, + }; + } + const indices = new Set(); + const cRect = container.getBoundingClientRect(); + const cTop = cRect.top; + const cBottom = cRect.top + cRect.height; + for (let i = 0; i < pages.length; i++) { + const page = pages[i]; + const pRect = preview + ? page.previewContainer.getBoundingClientRect() + : page.viewContainer.getBoundingClientRect(); + const pTop = pRect.top; + const pBottom = pRect.top + pRect.height; + if (pTop < cBottom && pBottom > cTop) { + indices.add(i); + } + else if (indices.size) { + break; + } + } + const indicesArray = [...indices]; + return { + actual: indicesArray, + minFinal: Math.max(Math.min(...indicesArray) - this._visibleAdjPages, 0), + maxFinal: Math.min(Math.max(...indicesArray) + this._visibleAdjPages, pages.length - 1), + }; + } + updateCurrentPage(container) { + const pages = this._pages; + const visible = this.getVisiblePageIndices(container); + const { actual: indices } = visible; + if (!indices.length) { + this.setCurrentPageIndex(0); + return; + } + else if (indices.length === 1) { + this.setCurrentPageIndex(indices[0]); + return; + } + const cRect = container.getBoundingClientRect(); + const cTop = cRect.top; + const cMiddle = cRect.top + cRect.height / 2; + for (const i of indices) { + const pRect = pages[i].viewContainer.getBoundingClientRect(); + const pTop = pRect.top; + if (pTop > cTop) { + if (pTop > cMiddle) { + this.setCurrentPageIndex(i - 1); + return; + } + else { + this.setCurrentPageIndex(i); + return; + } + } + } + throw new Error("Incorrect argument"); + } +} + +const annotatorTypes = ["geom", "pen", "stamp", "text"]; +const annotatorDataChangeEvent = "tspdf-annotatordatachange"; +class AnnotatorDataChangeEvent extends CustomEvent { + constructor(detail) { + super(annotatorDataChangeEvent, { detail }); + } +} +const textSelectionChangeEvent = "tspdf-textselectionchange"; +class TextSelectionChangeEvent extends CustomEvent { + constructor(detail) { + super(textSelectionChangeEvent, { detail }); + } +} +class Annotator { + get overlayContainer() { + return this._overlayContainer; + } + constructor(docService, pageService, parent) { + this.onPagesRendered = (event) => { + this.refreshViewBox(); + }; + this.onParentScroll = () => { + this.refreshViewBox(); + }; + this.onOverlayPointerDown = (e) => { + if (!e.isPrimary) { + return; + } + this._lastPointerDownInfo = { + timestamp: performance.now(), + clientX: e.clientX, + clientY: e.clientY, + }; + }; + if (!docService) { + throw new Error("Document service not defined"); + } + if (!pageService) { + throw new Error("Page service not defined"); + } + if (!parent) { + throw new Error("Parent container not defined"); + } + this._docService = docService; + this._parent = parent; + this._pageService = pageService; + } + destroy() { + var _a, _b, _c; + this._docService.eventService.removeListener(pagesRenderedEvent, this.onPagesRendered); + (_a = this._parent) === null || _a === void 0 ? void 0 : _a.removeEventListener("scroll", this.onParentScroll); + (_b = this._parentMutationObserver) === null || _b === void 0 ? void 0 : _b.disconnect(); + (_c = this._parentResizeObserver) === null || _c === void 0 ? void 0 : _c.disconnect(); + this._overlayContainer.remove(); + } + refreshViewBox() { + const { width: w, height: h } = this._overlay.getBoundingClientRect(); + if (!w || !h) { + return; + } + this._overlay.style.left = this._parent.scrollLeft + "px"; + this._overlay.style.top = this._parent.scrollTop + "px"; + const viewBoxWidth = w / this._pageService.scale; + const viewBoxHeight = h / this._pageService.scale; + this._svgWrapper.setAttribute("viewBox", `0 0 ${viewBoxWidth} ${viewBoxHeight}`); + this.refreshGroupPosition(); + } + init() { + const annotationOverlayContainer = document.createElement("div"); + annotationOverlayContainer.id = "annotation-overlay-container"; + const annotationOverlay = document.createElement("div"); + annotationOverlay.id = "annotation-overlay"; + const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + svg.classList.add("abs-stretch", "no-margin", "no-padding"); + svg.setAttribute("opacity", "0.5"); + applyFlipYToElement(svg); + const g = document.createElementNS("http://www.w3.org/2000/svg", "g"); + svg.append(g); + annotationOverlay.append(svg); + annotationOverlayContainer.append(annotationOverlay); + this._overlayContainer = annotationOverlayContainer; + this._overlay = annotationOverlay; + this._svgWrapper = svg; + this._svgGroup = g; + this._parent.append(this._overlayContainer); + this.refreshViewBox(); + this.initEventHandlers(); + } + initEventHandlers() { + this._overlay.addEventListener("pointerdown", this.onOverlayPointerDown); + this._parent.addEventListener("scroll", this.onParentScroll); + const parentRObserver = new ResizeObserver((entries) => { + this.refreshViewBox(); + }); + const parentMObserver = new MutationObserver((mutations) => { + const record = mutations[0]; + if (!record) { + return; + } + record.addedNodes.forEach(x => { + const element = x; + if (element.classList.contains("page")) { + parentRObserver.observe(x); + } + }); + record.removedNodes.forEach(x => parentRObserver.unobserve(x)); + this.refreshViewBox(); + }); + parentRObserver.observe(this._parent); + parentMObserver.observe(this._parent, { + attributes: false, + childList: true, + subtree: false, + }); + this._parentMutationObserver = parentMObserver; + this._parentResizeObserver = parentRObserver; + this._docService.eventService.addListener(pagesRenderedEvent, this.onPagesRendered); + } + updatePointerCoords(clientX, clientY) { + const pageCoords = this._pageService.getPageCoordsUnderPointer(clientX, clientY); + if (!pageCoords) { + this._svgGroup.classList.add("annotation-out-of-page"); + } + else { + this._svgGroup.classList.remove("annotation-out-of-page"); + } + this._pointerCoordsInPageCS = pageCoords; + } +} + +class GeometricAnnotator extends Annotator { + constructor(docService, pageService, parent, options) { + super(docService, pageService, parent); + this._color = (options === null || options === void 0 ? void 0 : options.color) || [0, 0, 0, 1]; + this._strokeWidth = (options === null || options === void 0 ? void 0 : options.strokeWidth) || 3; + this._cloudMode = (options === null || options === void 0 ? void 0 : options.cloudMode) || false; + } + destroy() { + this.clearGroup(); + super.destroy(); + } + init() { + super.init(); + } + emitDataChanged(count, saveable, clearable, undoable) { + this._docService.eventService.dispatchEvent(new AnnotatorDataChangeEvent({ + annotatorType: "geom", + elementCount: count, + undoable, + clearable, + saveable, + })); + } + clearGroup() { + this._svgGroup.innerHTML = ""; + this.emitDataChanged(0); + } + refreshGroupPosition() { + if (!this._pageId && this._pageId !== 0) { + return; + } + const page = this._pageService.renderedPages.find(x => x.id === this._pageId); + if (!page) { + this._svgGroup.setAttribute("transform", "scale(0)"); + return; + } + const { height: pageHeight, width: pageWidth, top: pageTop, left: pageLeft } = page.viewContainer.getBoundingClientRect(); + const pageBottom = pageTop + pageHeight; + const pageRight = pageLeft + pageWidth; + const { height: overlayHeight, top: overlayTop, left: overlayLeft } = this._overlay.getBoundingClientRect(); + const overlayBottom = overlayTop + overlayHeight; + const rotation = page.rotation; + const scale = page.scale; + let offsetX; + let offsetY; + switch (rotation) { + case 0: + offsetX = (pageLeft - overlayLeft) / scale; + offsetY = (overlayBottom - pageBottom) / scale; + break; + case 90: + offsetX = (pageLeft - overlayLeft) / scale; + offsetY = (overlayBottom - pageTop) / scale; + break; + case 180: + offsetX = (pageRight - overlayLeft) / scale; + offsetY = (overlayBottom - pageTop) / scale; + break; + case 270: + offsetX = (pageRight - overlayLeft) / scale; + offsetY = (overlayBottom - pageBottom) / scale; + break; + default: + throw new Error(`Invalid rotation degree: ${rotation}`); + } + applyTranslateRotateToElement(this._svgGroup, offsetX, offsetY, rotation); + } + buildLineEndingPath(point, type, strokeWidth, side) { + const size = Math.max(strokeWidth * LINE_END_MULTIPLIER, LINE_END_MIN_SIZE); + let text = ""; + switch (type) { + case lineEndingTypes.ARROW_OPEN: + if (side === "left") { + text += `M${point.x + size},${point.y + size / 2}`; + text += ` L${point.x},${point.y}`; + text += ` L${point.x + size},${point.y - size / 2}`; + } + else { + text += `M${point.x - size},${point.y + size / 2}`; + text += ` L${point.x},${point.y}`; + text += ` L${point.x - size},${point.y - size / 2}`; + } + return text; + case lineEndingTypes.ARROW_OPEN_R: + if (side === "left") { + text += `M${point.x},${point.y + size / 2}`; + text += ` L${point.x + size},${point.y}`; + text += ` L${point.x},${point.y - size / 2}`; + } + else { + text += `M${point.x},${point.y + size / 2}`; + text += ` L${point.x - size},${point.y}`; + text += ` L${point.x},${point.y - size / 2}`; + } + return text; + case lineEndingTypes.ARROW_CLOSED: + if (side === "left") { + text += `M${point.x + size},${point.y + size / 2}`; + text += ` L${point.x},${point.y}`; + text += ` L${point.x + size},${point.y - size / 2}`; + } + else { + text += `M${point.x - size},${point.y + size / 2}`; + text += ` L${point.x},${point.y}`; + text += ` L${point.x - size},${point.y - size / 2}`; + } + text += " Z"; + return text; + case lineEndingTypes.ARROW_CLOSED_R: + if (side === "left") { + text += `M${point.x + size},${point.y}`; + text += ` L${point.x},${point.y + size / 2}`; + text += ` L${point.x},${point.y - size / 2}`; + } + else { + text += `M${point.x - size},${point.y}`; + text += ` L${point.x},${point.y - size / 2}`; + text += ` L${point.x},${point.y + size / 2}`; + } + text += " Z"; + return text; + case lineEndingTypes.BUTT: + text += `M${point.x},${point.y + size / 2}`; + text += ` L${point.x},${point.y - size / 2}`; + return text; + case lineEndingTypes.SLASH: + text += `M${point.x + size / 2},${point.y + size / 2}`; + text += ` L${point.x - size / 2},${point.y - size / 2}`; + return text; + case lineEndingTypes.DIAMOND: + text += `M${point.x},${point.y + size / 2}`; + text += ` L${point.x + size / 2},${point.y}`; + text += ` L${point.x},${point.y - size / 2}`; + text += ` L${point.x - size / 2},${point.y}`; + text += " Z"; + return text; + case lineEndingTypes.SQUARE: + text += `M${point.x - size / 2},${point.y + size / 2}`; + text += ` L${point.x + size / 2},${point.y + size / 2}`; + text += ` L${point.x + size / 2},${point.y - size / 2}`; + text += ` L${point.x - size / 2},${point.y - size / 2}`; + text += " Z"; + return text; + case lineEndingTypes.CIRCLE: + const c = BEZIER_CONSTANT; + const r = size / 2; + const cw = c * r; + const xmin = point.x - r; + const ymin = point.y - r; + const xmax = point.x + r; + const ymax = point.y + r; + text += `M${point.x},${ymax}`; + text += ` C${point.x + cw},${ymax} ${xmax},${point.y + cw} ${xmax},${point.y}`; + text += ` C${xmax},${point.y - cw} ${point.x + cw},${ymin} ${point.x},${ymin}`; + text += ` C${point.x - cw},${ymin} ${xmin},${point.y - cw} ${xmin},${point.y}`; + text += ` C${xmin},${point.y + cw} ${point.x - cw},${ymax} ${point.x},${ymax}`; + text += " Z"; + return text; + case lineEndingTypes.NONE: + default: + return ""; + } + } +} + +var __awaiter$i = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class GeometricLineAnnotator extends GeometricAnnotator { + constructor(docService, pageService, parent, options) { + super(docService, pageService, parent, options || {}); + this.onPointerDown = (e) => { + if (!e.isPrimary || e.button === 2) { + return; + } + const { clientX: cx, clientY: cy } = e; + this.updatePointerCoords(cx, cy); + const pageCoords = this._pointerCoordsInPageCS; + if (!pageCoords) { + return; + } + const { pageX: px, pageY: py, pageId } = pageCoords; + this._pageId = pageId; + this._down = new u(px, py); + this.clear(); + this.refreshGroupPosition(); + const target = e.target; + target.addEventListener("pointermove", this.onPointerMove); + target.addEventListener("pointerup", this.onPointerUp); + target.addEventListener("pointerout", this.onPointerUp); + target.setPointerCapture(e.pointerId); + }; + this.onPointerMove = (e) => { + if (!e.isPrimary + || !this._down) { + return; + } + const { clientX: cx, clientY: cy } = e; + this.updatePointerCoords(cx, cy); + const pageCoords = this._pointerCoordsInPageCS; + if (!pageCoords || pageCoords.pageId !== this._pageId) { + return; + } + const { pageX: px, pageY: py } = pageCoords; + const end = new u(px, py); + this.redrawLine(this._down, end); + }; + this.onPointerUp = (e) => { + if (!e.isPrimary) { + return; + } + const target = e.target; + target.removeEventListener("pointermove", this.onPointerMove); + target.removeEventListener("pointerup", this.onPointerUp); + target.removeEventListener("pointerout", this.onPointerUp); + target.releasePointerCapture(e.pointerId); + if (this._vertices) { + this.emitDataChanged(2, true, true); + } + }; + this.init(); + } + destroy() { + super.destroy(); + } + undo() { + this.clear(); + } + clear() { + this._vertices = null; + this.clearGroup(); + } + saveAnnotationAsync() { + return __awaiter$i(this, void 0, void 0, function* () { + if (!this._vertices) { + return; + } + const pageId = this._pageId; + const dto = this.buildAnnotationDto(); + const annotation = yield LineAnnotation.createFromDtoAsync(dto, this._docService.fontMap); + yield this._docService.appendAnnotationToPageAsync(pageId, annotation); + this.clear(); + }); + } + init() { + super.init(); + this._overlay.addEventListener("pointerdown", this.onPointerDown); + } + redrawLine(min, max) { + this._svgGroup.innerHTML = ""; + const [r, g, b, a] = this._color || [0, 0, 0, 1]; + this._vertices = [min.x, min.y, max.x, max.y]; + const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); + path.setAttribute("fill", "none"); + path.setAttribute("stroke", `rgba(${r * 255},${g * 255},${b * 255},${a})`); + path.setAttribute("stroke-width", this._strokeWidth + ""); + path.setAttribute("stroke-linecap", "square"); + const pathString = `M ${min.x},${min.y} L ${max.x},${max.y}`; + path.setAttribute("d", pathString); + this._svgGroup.append(path); + } + buildAnnotationDto() { + const nowString = new Date().toISOString(); + const dto = { + uuid: UUID.getRandomUuid(), + annotationType: "/Line", + pageId: null, + dateCreated: nowString, + dateModified: nowString, + author: this._docService.userName || "unknown", + textContent: null, + rect: null, + vertices: this._vertices, + intent: lineIntents.DIMENSION, + color: this._color, + strokeWidth: this._strokeWidth, + strokeDashGap: null, + }; + return dto; + } +} + +class GeometricArrowAnnotator extends GeometricLineAnnotator { + constructor(docService, pageService, parent, options) { + super(docService, pageService, parent, options || {}); + } + redrawLine(min, max) { + this._svgGroup.innerHTML = ""; + const [r, g, b, a] = this._color || [0, 0, 0, 1]; + this._vertices = [min.x, min.y, max.x, max.y]; + const start = new u(min.x, min.y); + const end = new u(max.x, max.y); + const xAlignedStart = new u(); + const xAlignedEnd = new u(u.subtract(end, start).getMagnitude(), 0); + const matrix = l.from4Vec2(xAlignedStart, xAlignedEnd, start, end); + const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); + path.setAttribute("fill", "none"); + path.setAttribute("stroke", `rgba(${r * 255},${g * 255},${b * 255},${a})`); + path.setAttribute("stroke-width", this._strokeWidth + ""); + path.setAttribute("stroke-linecap", "square"); + let pathString = `M ${xAlignedStart.x},${xAlignedStart.y} L ${xAlignedEnd.x},${xAlignedEnd.y}`; + const arrowSize = Math.max(this._strokeWidth * LINE_END_MULTIPLIER, LINE_END_MIN_SIZE); + pathString += ` M ${xAlignedEnd.x - arrowSize},${xAlignedEnd.y + arrowSize / 2}`; + pathString += ` L ${xAlignedEnd.x},${xAlignedEnd.y}`; + pathString += ` L ${xAlignedEnd.x - arrowSize},${xAlignedEnd.y - arrowSize / 2}`; + path.setAttribute("d", pathString); + applyMatrixToElement(path, matrix); + this._svgGroup.append(path); + } + buildAnnotationDto() { + const nowString = new Date().toISOString(); + const dto = { + uuid: UUID.getRandomUuid(), + annotationType: "/Line", + pageId: null, + dateCreated: nowString, + dateModified: nowString, + author: this._docService.userName || "unknown", + textContent: null, + rect: null, + vertices: this._vertices, + intent: lineIntents.ARROW, + endingType: [lineEndingTypes.NONE, lineEndingTypes.ARROW_OPEN], + color: this._color, + strokeWidth: this._strokeWidth, + strokeDashGap: null, + }; + return dto; + } +} + +var __awaiter$h = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class GeometricCircleAnnotator extends GeometricAnnotator { + constructor(docService, pageService, parent, options) { + super(docService, pageService, parent, options || {}); + this.onPointerDown = (e) => { + if (!e.isPrimary || e.button === 2) { + return; + } + const { clientX: cx, clientY: cy } = e; + this.updatePointerCoords(cx, cy); + const pageCoords = this._pointerCoordsInPageCS; + if (!pageCoords) { + return; + } + const { pageX: px, pageY: py, pageId } = pageCoords; + this._pageId = pageId; + this._down = new u(px, py); + this.clear(); + this.refreshGroupPosition(); + const target = e.target; + target.addEventListener("pointermove", this.onPointerMove); + target.addEventListener("pointerup", this.onPointerUp); + target.addEventListener("pointerout", this.onPointerUp); + target.setPointerCapture(e.pointerId); + }; + this.onPointerMove = (e) => { + if (!e.isPrimary + || !this._down) { + return; + } + const { clientX: cx, clientY: cy } = e; + this.updatePointerCoords(cx, cy); + const pageCoords = this._pointerCoordsInPageCS; + if (!pageCoords || pageCoords.pageId !== this._pageId) { + return; + } + const { pageX: px, pageY: py } = pageCoords; + const { min, max } = u.minMax(this._down, new u(px, py)); + this.redrawCircle(min, max); + }; + this.onPointerUp = (e) => { + if (!e.isPrimary) { + return; + } + const target = e.target; + target.removeEventListener("pointermove", this.onPointerMove); + target.removeEventListener("pointerup", this.onPointerUp); + target.removeEventListener("pointerout", this.onPointerUp); + target.releasePointerCapture(e.pointerId); + if (this._rect) { + this.emitDataChanged(2, true, true); + } + }; + this.init(); + } + destroy() { + super.destroy(); + } + undo() { + this.clear(); + } + clear() { + this._rect = null; + this.clearGroup(); + } + saveAnnotationAsync() { + return __awaiter$h(this, void 0, void 0, function* () { + if (!this._rect) { + return; + } + const pageId = this._pageId; + const dto = this.buildAnnotationDto(); + const annotation = CircleAnnotation.createFromDto(dto); + yield this._docService.appendAnnotationToPageAsync(pageId, annotation); + this.clear(); + }); + } + init() { + super.init(); + this._overlay.addEventListener("pointerdown", this.onPointerDown); + } + redrawCircle(min, max) { + this._svgGroup.innerHTML = ""; + const minSize = this._strokeWidth * 2; + if (max.x - min.x <= minSize || max.y - min.y <= minSize) { + this._rect = null; + return; + } + const [r, g, b, a] = this._color || [0, 0, 0, 1]; + this._rect = [min.x, min.y, max.x, max.y]; + const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); + path.setAttribute("fill", "none"); + path.setAttribute("stroke", `rgba(${r * 255},${g * 255},${b * 255},${a})`); + path.setAttribute("stroke-width", this._strokeWidth + ""); + path.setAttribute("stroke-linecap", "round"); + path.setAttribute("stroke-linejoin", "round"); + let pathString; + const rx = (max.x - min.x) / 2; + const ry = (max.y - min.y) / 2; + const center = new u(min.x + rx, min.y + ry); + if (this._cloudMode) { + const curveData = CloudCurveData.buildFromEllipse(rx, ry, CircleAnnotation.cloudArcSize, new l().applyTranslation(center.x, center.y)); + pathString = "M" + curveData.start.x + "," + curveData.start.y; + curveData.curves.forEach(x => { + pathString += ` C${x[0].x},${x[0].y} ${x[1].x},${x[1].y} ${x[2].x},${x[2].y}`; + }); + } + else { + const c = BEZIER_CONSTANT; + const cw = c * rx; + const ch = c * ry; + pathString = "M" + center.x + "," + max.y; + pathString += ` C${center.x + cw},${max.y} ${max.x},${center.y + ch} ${max.x},${center.y}`; + pathString += ` C${max.x},${center.y - ch} ${center.x + cw},${min.y} ${center.x},${min.y}`; + pathString += ` C${center.x - cw},${min.y} ${min.x},${center.y - ch} ${min.x},${center.y}`; + pathString += ` C${min.x},${center.y + ch} ${center.x - cw},${max.y} ${center.x},${max.y}`; + } + path.setAttribute("d", pathString); + this._svgGroup.append(path); + } + buildAnnotationDto() { + const margin = this._strokeWidth / 2 + (this._cloudMode ? CircleAnnotation.cloudArcSize / 2 : 0); + const lm = margin; + const tm = margin; + const rm = margin; + const bm = margin; + const rectMargins = [lm, tm, rm, bm]; + const [xmin, ymin, xmax, ymax] = this._rect; + const nowString = new Date().toISOString(); + const dto = { + uuid: UUID.getRandomUuid(), + annotationType: "/Circle", + pageId: null, + dateCreated: nowString, + dateModified: nowString, + author: this._docService.userName || "unknown", + textContent: null, + rect: [xmin - lm, ymin - bm, xmax + rm, ymax + tm], + rectMargins, + cloud: this._cloudMode, + color: this._color, + strokeWidth: this._strokeWidth, + strokeDashGap: null, + }; + return dto; + } +} + +var __awaiter$g = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class GeometricPolygonAnnotator extends GeometricAnnotator { + constructor(docService, pageService, parent, options) { + super(docService, pageService, parent, options || {}); + this._points = []; + this.onPointerDown = (e) => { + if (!e.isPrimary || e.button === 2) { + return; + } + const { clientX: cx, clientY: cy } = e; + this.updatePointerCoords(cx, cy); + const pageCoords = this._pointerCoordsInPageCS; + if (!pageCoords) { + return; + } + const { pageX: px, pageY: py, pageId } = pageCoords; + this._pageId = pageId; + this.refreshGroupPosition(); + if (!this._points.length) { + this._points.push(new u(px, py)); + } + this._points.push(new u(px, py)); + const target = e.target; + target.addEventListener("pointermove", this.onPointerMove); + target.addEventListener("pointerup", this.onPointerUp); + target.addEventListener("pointerout", this.onPointerUp); + target.setPointerCapture(e.pointerId); + }; + this.onPointerMove = (e) => { + if (!e.isPrimary) { + return; + } + const { clientX: cx, clientY: cy } = e; + this.updatePointerCoords(cx, cy); + const pageCoords = this._pointerCoordsInPageCS; + if (!pageCoords || pageCoords.pageId !== this._pageId) { + return; + } + const { pageX: px, pageY: py } = pageCoords; + this._points[this._points.length - 1].set(px, py); + this.redraw(); + }; + this.onPointerUp = (e) => { + if (!e.isPrimary) { + return; + } + const target = e.target; + target.removeEventListener("pointermove", this.onPointerMove); + target.removeEventListener("pointerup", this.onPointerUp); + target.removeEventListener("pointerout", this.onPointerUp); + target.releasePointerCapture(e.pointerId); + this.emitPointsDataChanged(); + }; + this.init(); + } + destroy() { + super.destroy(); + } + undo() { + if (this._points.length) { + this._points.pop(); + this.redraw(); + this.emitPointsDataChanged(); + } + } + clear() { + var _a; + if ((_a = this._points) === null || _a === void 0 ? void 0 : _a.length) { + this._points.length = 0; + this.clearGroup(); + } + } + saveAnnotationAsync() { + return __awaiter$g(this, void 0, void 0, function* () { + if (this._points.length < 3) { + return; + } + const pageId = this._pageId; + const dto = this.buildAnnotationDto(); + const annotation = PolygonAnnotation.createFromDto(dto); + yield this._docService.appendAnnotationToPageAsync(pageId, annotation); + this.clear(); + }); + } + init() { + super.init(); + this._overlay.addEventListener("pointerdown", this.onPointerDown); + } + emitPointsDataChanged() { + const count = this._points.length; + this.emitDataChanged(count, count > 1, count > 0, count > 2); + } + redraw() { + this._svgGroup.innerHTML = ""; + if (this._points.length < 2) { + return; + } + const [r, g, b, a] = this._color || [0, 0, 0, 1]; + const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); + path.setAttribute("fill", "none"); + path.setAttribute("stroke", `rgba(${r * 255},${g * 255},${b * 255},${a})`); + path.setAttribute("stroke-width", this._strokeWidth + ""); + let pathString; + if (this._cloudMode) { + path.setAttribute("stroke-linecap", "round"); + path.setAttribute("stroke-linejoin", "round"); + const curveData = CloudCurveData.buildFromPolyline([...this._points, this._points[0]], PolygonAnnotation.cloudArcSize); + pathString = "M" + curveData.start.x + "," + curveData.start.y; + curveData.curves.forEach(x => { + pathString += ` C${x[0].x},${x[0].y} ${x[1].x},${x[1].y} ${x[2].x},${x[2].y}`; + }); + path.setAttribute("d", pathString); + } + else { + path.setAttribute("stroke-linecap", "square"); + path.setAttribute("stroke-linejoin", "miter"); + const start = this._points[0]; + pathString = "M" + start.x + "," + start.y; + for (let i = 1; i < this._points.length; i++) { + const point = this._points[i]; + pathString += " L" + point.x + "," + point.y; + } + pathString += " Z"; + } + path.setAttribute("d", pathString); + this._svgGroup.append(path); + } + buildAnnotationDto() { + const margin = this._strokeWidth / 2 + (this._cloudMode ? PolygonAnnotation.cloudArcSize / 2 : 0); + let xmin; + let ymin; + let xmax; + let ymax; + let vec; + const points = this._points; + const vertices = []; + for (let i = 0; i < points.length; i++) { + vec = points[i]; + if (!xmin || vec.x < xmin) { + xmin = vec.x; + } + if (!ymin || vec.y < ymin) { + ymin = vec.y; + } + if (!xmax || vec.x > xmax) { + xmax = vec.x; + } + if (!ymax || vec.y > ymax) { + ymax = vec.y; + } + vertices.push(vec.x, vec.y); + } + const nowString = new Date().toISOString(); + const dto = { + uuid: UUID.getRandomUuid(), + annotationType: "/Polygon", + pageId: null, + dateCreated: nowString, + dateModified: nowString, + author: this._docService.userName || "unknown", + textContent: null, + rect: [xmin - margin, ymin - margin, xmax + margin, ymax + margin], + vertices, + cloud: this._cloudMode, + color: this._color, + strokeWidth: this._strokeWidth, + strokeDashGap: null, + }; + return dto; + } +} + +var __awaiter$f = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class GeometricPolylineAnnotator extends GeometricAnnotator { + constructor(docService, pageService, parent, options) { + super(docService, pageService, parent, options || {}); + this._points = []; + this.onPointerDown = (e) => { + if (!e.isPrimary || e.button === 2) { + return; + } + const { clientX: cx, clientY: cy } = e; + this.updatePointerCoords(cx, cy); + const pageCoords = this._pointerCoordsInPageCS; + if (!pageCoords) { + return; + } + const { pageX: px, pageY: py, pageId } = pageCoords; + this._pageId = pageId; + this.refreshGroupPosition(); + if (!this._points.length) { + this._points.push(new u(px, py)); + } + this._points.push(new u(px, py)); + const target = e.target; + target.addEventListener("pointermove", this.onPointerMove); + target.addEventListener("pointerup", this.onPointerUp); + target.addEventListener("pointerout", this.onPointerUp); + target.setPointerCapture(e.pointerId); + }; + this.onPointerMove = (e) => { + if (!e.isPrimary) { + return; + } + const { clientX: cx, clientY: cy } = e; + this.updatePointerCoords(cx, cy); + const pageCoords = this._pointerCoordsInPageCS; + if (!pageCoords || pageCoords.pageId !== this._pageId) { + return; + } + const { pageX: px, pageY: py } = pageCoords; + this._points[this._points.length - 1].set(px, py); + this.redraw(); + }; + this.onPointerUp = (e) => { + if (!e.isPrimary) { + return; + } + const target = e.target; + target.removeEventListener("pointermove", this.onPointerMove); + target.removeEventListener("pointerup", this.onPointerUp); + target.removeEventListener("pointerout", this.onPointerUp); + target.releasePointerCapture(e.pointerId); + this.emitPointsDataChanged(); + }; + this.init(); + } + destroy() { + super.destroy(); + } + undo() { + if (this._points.length) { + this._points.pop(); + this.redraw(); + this.emitPointsDataChanged(); + } + } + clear() { + var _a; + if ((_a = this._points) === null || _a === void 0 ? void 0 : _a.length) { + this._points.length = 0; + this.clearGroup(); + } + } + saveAnnotationAsync() { + return __awaiter$f(this, void 0, void 0, function* () { + if (this._points.length < 2) { + return; + } + const pageId = this._pageId; + const dto = this.buildAnnotationDto(); + const annotation = PolylineAnnotation.createFromDto(dto); + yield this._docService.appendAnnotationToPageAsync(pageId, annotation); + this.clear(); + }); + } + init() { + super.init(); + this._overlay.addEventListener("pointerdown", this.onPointerDown); + } + emitPointsDataChanged() { + const count = this._points.length; + this.emitDataChanged(count, count > 1, count > 0, count > 2); + } + redraw() { + this._svgGroup.innerHTML = ""; + if (this._points.length < 2) { + return; + } + const [r, g, b, a] = this._color || [0, 0, 0, 1]; + const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); + path.setAttribute("fill", "none"); + path.setAttribute("stroke", `rgba(${r * 255},${g * 255},${b * 255},${a})`); + path.setAttribute("stroke-width", this._strokeWidth + ""); + path.setAttribute("stroke-linecap", "square"); + path.setAttribute("stroke-linejoin", "miter"); + const start = this._points[0]; + let pathString = "M" + start.x + "," + start.y; + for (let i = 1; i < this._points.length; i++) { + const point = this._points[i]; + pathString += " L" + point.x + "," + point.y; + } + path.setAttribute("d", pathString); + this._svgGroup.append(path); + } + buildAnnotationDto() { + const margin = this._strokeWidth / 2; + let xmin; + let ymin; + let xmax; + let ymax; + let vec; + const points = this._points; + const vertices = []; + for (let i = 0; i < points.length; i++) { + vec = points[i]; + if (!xmin || vec.x < xmin) { + xmin = vec.x; + } + if (!ymin || vec.y < ymin) { + ymin = vec.y; + } + if (!xmax || vec.x > xmax) { + xmax = vec.x; + } + if (!ymax || vec.y > ymax) { + ymax = vec.y; + } + vertices.push(vec.x, vec.y); + } + const nowString = new Date().toISOString(); + const dto = { + uuid: UUID.getRandomUuid(), + annotationType: "/Polyline", + pageId: null, + dateCreated: nowString, + dateModified: nowString, + author: this._docService.userName || "unknown", + textContent: null, + rect: [xmin - margin, ymin - margin, xmax + margin, ymax + margin], + vertices, + color: this._color, + strokeWidth: this._strokeWidth, + strokeDashGap: null, + }; + return dto; + } +} + +var __awaiter$e = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class GeometricSquareAnnotator extends GeometricAnnotator { + constructor(docService, pageService, parent, options) { + super(docService, pageService, parent, options || {}); + this.onPointerDown = (e) => { + if (!e.isPrimary || e.button === 2) { + return; + } + const { clientX: cx, clientY: cy } = e; + this.updatePointerCoords(cx, cy); + const pageCoords = this._pointerCoordsInPageCS; + if (!pageCoords) { + return; + } + const { pageX: px, pageY: py, pageId } = pageCoords; + this._pageId = pageId; + this._down = new u(px, py); + this.clear(); + this.refreshGroupPosition(); + const target = e.target; + target.addEventListener("pointermove", this.onPointerMove); + target.addEventListener("pointerup", this.onPointerUp); + target.addEventListener("pointerout", this.onPointerUp); + target.setPointerCapture(e.pointerId); + }; + this.onPointerMove = (e) => { + if (!e.isPrimary + || !this._down) { + return; + } + const { clientX: cx, clientY: cy } = e; + this.updatePointerCoords(cx, cy); + const pageCoords = this._pointerCoordsInPageCS; + if (!pageCoords || pageCoords.pageId !== this._pageId) { + return; + } + const { pageX: px, pageY: py } = pageCoords; + const { min, max } = u.minMax(this._down, new u(px, py)); + this.redrawRect(min, max); + }; + this.onPointerUp = (e) => { + if (!e.isPrimary) { + return; + } + const target = e.target; + target.removeEventListener("pointermove", this.onPointerMove); + target.removeEventListener("pointerup", this.onPointerUp); + target.removeEventListener("pointerout", this.onPointerUp); + target.releasePointerCapture(e.pointerId); + if (this._rect) { + this.emitDataChanged(2, true, true); + } + }; + this.init(); + } + destroy() { + super.destroy(); + } + undo() { + this.clear(); + } + clear() { + this._rect = null; + this.clearGroup(); + } + saveAnnotationAsync() { + return __awaiter$e(this, void 0, void 0, function* () { + if (!this._rect) { + return; + } + const pageId = this._pageId; + const dto = this.buildAnnotationDto(); + const annotation = SquareAnnotation.createFromDto(dto); + yield this._docService.appendAnnotationToPageAsync(pageId, annotation); + this.clear(); + }); + } + init() { + super.init(); + this._overlay.addEventListener("pointerdown", this.onPointerDown); + } + redrawRect(min, max) { + this._svgGroup.innerHTML = ""; + const minSize = this._strokeWidth * 2; + if (max.x - min.x <= minSize || max.y - min.y <= minSize) { + this._rect = null; + return; + } + const [r, g, b, a] = this._color || [0, 0, 0, 1]; + this._rect = [min.x, min.y, max.x, max.y]; + if (this._cloudMode) { + const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); + path.setAttribute("fill", "none"); + path.setAttribute("stroke", `rgba(${r * 255},${g * 255},${b * 255},${a})`); + path.setAttribute("stroke-width", this._strokeWidth + ""); + path.setAttribute("stroke-linecap", "round"); + path.setAttribute("stroke-linejoin", "round"); + const curveData = CloudCurveData.buildFromPolyline([ + new u(min.x, min.y), + new u(max.x, min.y), + new u(max.x, max.y), + new u(min.x, max.y), + new u(min.x, min.y), + ], SquareAnnotation.cloudArcSize); + let pathString = "M" + curveData.start.x + "," + curveData.start.y; + curveData.curves.forEach(x => { + pathString += ` C${x[0].x},${x[0].y} ${x[1].x},${x[1].y} ${x[2].x},${x[2].y}`; + }); + path.setAttribute("d", pathString); + this._svgGroup.append(path); + } + else { + const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + rect.setAttribute("fill", "none"); + rect.setAttribute("stroke", `rgba(${r * 255},${g * 255},${b * 255},${a})`); + rect.setAttribute("stroke-width", this._strokeWidth + ""); + rect.setAttribute("x", min.x + ""); + rect.setAttribute("y", min.y + ""); + rect.setAttribute("width", max.x - min.x + ""); + rect.setAttribute("height", max.y - min.y + ""); + this._svgGroup.append(rect); + } + } + buildAnnotationDto() { + const margin = this._strokeWidth / 2 + (this._cloudMode ? SquareAnnotation.cloudArcSize / 2 : 0); + const lm = margin; + const tm = margin; + const rm = margin; + const bm = margin; + const rectMargins = [lm, tm, rm, bm]; + const [xmin, ymin, xmax, ymax] = this._rect; + const nowString = new Date().toISOString(); + const dto = { + uuid: UUID.getRandomUuid(), + annotationType: "/Square", + pageId: null, + dateCreated: nowString, + dateModified: nowString, + author: this._docService.userName || "unknown", + textContent: null, + rect: [xmin - lm, ymin - bm, xmax + rm, ymax + tm], + rectMargins, + cloud: this._cloudMode, + color: this._color, + strokeWidth: this._strokeWidth, + strokeDashGap: null, + }; + return dto; + } +} + +const geometricAnnotatorTypes = ["square", "circle", "line", "arrow", "polyline", "polygon"]; +class GeometricAnnotatorFactory { + createAnnotator(docService, pageService, parent, options, type) { + var _a, _b; + if (!docService) { + throw new Error("Document service is not defined"); + } + if (!pageService) { + throw new Error("Page service is not defined"); + } + if (!parent) { + throw new Error("Parent container is not defined"); + } + type || (type = this._lastType || "square"); + this._lastType = type; + const color = (options === null || options === void 0 ? void 0 : options.color) || this._lastColor || [0, 0, 0, 0.9]; + this._lastColor = color; + const strokeWidth = (options === null || options === void 0 ? void 0 : options.strokeWidth) || this._lastStrokeWidth || 3; + this._lastStrokeWidth = strokeWidth; + const cloudMode = (_b = (_a = options === null || options === void 0 ? void 0 : options.cloudMode) !== null && _a !== void 0 ? _a : this._lastCloudMode) !== null && _b !== void 0 ? _b : false; + this._lastCloudMode = cloudMode; + const combinedOptions = { + color, + strokeWidth, + cloudMode, + }; + switch (type) { + case "square": + return new GeometricSquareAnnotator(docService, pageService, parent, combinedOptions); + case "circle": + return new GeometricCircleAnnotator(docService, pageService, parent, combinedOptions); + case "line": + return new GeometricLineAnnotator(docService, pageService, parent, combinedOptions); + case "arrow": + return new GeometricArrowAnnotator(docService, pageService, parent, combinedOptions); + case "polyline": + return new GeometricPolylineAnnotator(docService, pageService, parent, combinedOptions); + case "polygon": + return new GeometricPolygonAnnotator(docService, pageService, parent, combinedOptions); + default: + throw new Error(`Invalid geometric annotator type: ${type}`); + } + } +} + +var __awaiter$d = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class PenAnnotator extends Annotator { + constructor(docService, pageService, parent, options) { + super(docService, pageService, parent); + this.onPointerDown = (e) => { + if (!e.isPrimary || e.button === 2) { + return; + } + const { clientX: cx, clientY: cy } = e; + this.updatePointerCoords(cx, cy); + const pageCoords = this._pointerCoordsInPageCS; + if (!pageCoords) { + return; + } + const { pageX: px, pageY: py, pageId } = pageCoords; + if (!this._annotationPathData || pageId !== this._annotationPathData.id) { + this.resetTempPenData(pageId); + } + this._annotationPathData.newPath(new u(px, py)); + const target = e.target; + target.addEventListener("pointermove", this.onPointerMove); + target.addEventListener("pointerup", this.onPointerUp); + target.addEventListener("pointerout", this.onPointerUp); + target.setPointerCapture(e.pointerId); + }; + this.onPointerMove = (e) => { + if (!e.isPrimary || !this._annotationPathData) { + return; + } + const { clientX: cx, clientY: cy } = e; + this.updatePointerCoords(cx, cy); + const pageCoords = this._pointerCoordsInPageCS; + if (!pageCoords || pageCoords.pageId !== this._annotationPathData.id) { + return; + } + this._annotationPathData.addPosition(new u(pageCoords.pageX, pageCoords.pageY)); + }; + this.onPointerUp = (e) => { + var _a; + if (!e.isPrimary) { + return; + } + const target = e.target; + target.removeEventListener("pointermove", this.onPointerMove); + target.removeEventListener("pointerup", this.onPointerUp); + target.removeEventListener("pointerout", this.onPointerUp); + target.releasePointerCapture(e.pointerId); + (_a = this._annotationPathData) === null || _a === void 0 ? void 0 : _a.endPath(); + this.emitDataChanged(); + }; + this.init(); + this._color = (options === null || options === void 0 ? void 0 : options.color) || [0, 0, 0, 0.9]; + this._strokeWidth = (options === null || options === void 0 ? void 0 : options.strokeWidth) || 3; + } + destroy() { + this.removeTempPenData(); + super.destroy(); + } + undo() { + var _a; + (_a = this._annotationPathData) === null || _a === void 0 ? void 0 : _a.removeLastPath(); + this.emitDataChanged(); + } + clear() { + this.removeTempPenData(); + } + saveAnnotationAsync() { + return __awaiter$d(this, void 0, void 0, function* () { + if (!this._annotationPathData) { + return; + } + const pageId = this._annotationPathData.id; + const dto = this.buildAnnotationDto(this._annotationPathData); + const annotation = InkAnnotation.createFromDto(dto); + yield this._docService.appendAnnotationToPageAsync(pageId, annotation); + this.clear(); + }); + } + init() { + super.init(); + this._overlay.addEventListener("pointerdown", this.onPointerDown); + } + refreshGroupPosition() { + if (!this._annotationPathData) { + return; + } + const page = this._pageService.renderedPages.find(x => x.id === this._annotationPathData.id); + if (!page) { + this._annotationPathData.group.setAttribute("transform", "scale(0)"); + return; + } + const { height: pageHeight, width: pageWidth, top: pageTop, left: pageLeft } = page.viewContainer.getBoundingClientRect(); + const pageBottom = pageTop + pageHeight; + const pageRight = pageLeft + pageWidth; + const { height: overlayHeight, top: overlayTop, left: overlayLeft } = this._overlay.getBoundingClientRect(); + const overlayBottom = overlayTop + overlayHeight; + const rotation = page.rotation; + const scale = page.scale; + let offsetX; + let offsetY; + switch (rotation) { + case 0: + offsetX = (pageLeft - overlayLeft) / scale; + offsetY = (overlayBottom - pageBottom) / scale; + break; + case 90: + offsetX = (pageLeft - overlayLeft) / scale; + offsetY = (overlayBottom - pageTop) / scale; + break; + case 180: + offsetX = (pageRight - overlayLeft) / scale; + offsetY = (overlayBottom - pageTop) / scale; + break; + case 270: + offsetX = (pageRight - overlayLeft) / scale; + offsetY = (overlayBottom - pageBottom) / scale; + break; + default: + throw new Error(`Invalid rotation degree: ${rotation}`); + } + applyTranslateRotateToElement(this._annotationPathData.group, offsetX, offsetY, rotation); + } + removeTempPenData() { + if (this._annotationPathData) { + this._annotationPathData.group.remove(); + this._annotationPathData = null; + this.emitDataChanged(); + } + } + resetTempPenData(pageId) { + this.removeTempPenData(); + this._annotationPathData = new SvgSmoothPath({ + id: pageId, + color: this._color, + strokeWidth: this._strokeWidth, + }); + this._svgGroup.append(this._annotationPathData.group); + this.refreshGroupPosition(); + } + emitDataChanged() { + var _a; + const count = ((_a = this._annotationPathData) === null || _a === void 0 ? void 0 : _a.pathCount) || 0; + this._docService.eventService.dispatchEvent(new AnnotatorDataChangeEvent({ + annotatorType: "pen", + elementCount: count, + undoable: count > 1, + clearable: count > 0, + saveable: count > 0, + })); + } + buildAnnotationDto(data) { + const positions = []; + const inkList = []; + data.paths.forEach(path => { + const ink = []; + path.positions.forEach(pos => { + positions.push(pos); + ink.push(pos.x, pos.y); + }); + inkList.push(ink); + }); + const { min: newRectMin, max: newRectMax } = u.minMax(...positions); + const halfW = data.strokeWidth / 2; + const rect = [ + newRectMin.x - halfW, + newRectMin.y - halfW, + newRectMax.x + halfW, + newRectMax.y + halfW, + ]; + const nowString = new Date().toISOString(); + const dto = { + uuid: UUID.getRandomUuid(), + annotationType: "/Ink", + pageId: null, + dateCreated: nowString, + dateModified: nowString, + author: this._docService.userName || "unknown", + textContent: null, + rect, + matrix: [1, 0, 0, 1, 0, 0], + inkList, + color: data.color, + strokeWidth: data.strokeWidth, + strokeDashGap: null, + }; + return dto; + } +} + +var __awaiter$c = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +const supportedStampTypes = [ + { type: "/Draft", name: "Draft" }, + { type: "/Approved", name: "Approved" }, + { type: "/NotApproved", name: "Not Approved" }, + { type: "/Departmental", name: "Departmental" }, + { type: "/Confidential", name: "Confidential" }, + { type: "/Final", name: "Final" }, + { type: "/Expired", name: "Expired" }, + { type: "/AsIs", name: "As Is" }, + { type: "/Sold", name: "Sold" }, + { type: "/Experimental", name: "Experimental" }, + { type: "/ForComment", name: "For Comment" }, + { type: "/TopSecret", name: "Top Secret" }, + { type: "/ForPublicRelease", name: "For Public" }, + { type: "/NotForPublicRelease", name: "Not For Public" }, +]; +class StampAnnotator extends Annotator { + constructor(docService, pageService, parent, type, creationInfo) { + super(docService, pageService, parent); + this.onPointerMove = (e) => { + if (!e.isPrimary) { + return; + } + const { clientX: cx, clientY: cy } = e; + const { height: oh, top, left: ox } = this._parent.getBoundingClientRect(); + const oy = top + oh; + const offsetX = (cx - ox) / this._pageService.scale; + const offsetY = (oy - cy) / this._pageService.scale; + if (this._tempAnnotation) { + const [x1, y1, x2, y2] = this._tempAnnotation.Rect; + this._svgGroup.setAttribute("transform", `translate(${offsetX - (x2 - x1) / 2} ${offsetY - (y2 - y1) / 2})`); + } + this.updatePointerCoords(cx, cy); + }; + this.onPointerUp = (e) => __awaiter$c(this, void 0, void 0, function* () { + var _a, _b, _c; + if (!e.isPrimary || e.button === 2) { + return; + } + const { clientX: cx, clientY: cy } = e; + if (e.pointerType === "touch") { + const longTap = performance.now() - ((_a = this._lastPointerDownInfo) === null || _a === void 0 ? void 0 : _a.timestamp) > 700; + if (longTap) { + const downX = ((_b = this._lastPointerDownInfo) === null || _b === void 0 ? void 0 : _b.clientX) || 0; + const downY = ((_c = this._lastPointerDownInfo) === null || _c === void 0 ? void 0 : _c.clientY) || 0; + const displacement = Math.abs(h(cx, cy, downX, downY)); + const displaced = displacement > 7.5; + if (!displaced) { + return; + } + } + } + const pageCoords = this._pageService.getPageCoordsUnderPointer(cx, cy); + this._pointerCoordsInPageCS = pageCoords; + if (!pageCoords || !this._tempAnnotation) { + return; + } + const { pageId, pageX, pageY, pageRotation } = this._pointerCoordsInPageCS; + yield this._tempAnnotation.moveToAsync(new u(pageX, pageY)); + if (pageRotation) { + yield this._tempAnnotation.rotateByAsync(-pageRotation / 180 * Math.PI); + } + this._pageId = pageId; + yield this.saveAnnotationAsync(); + }); + if (!type) { + throw new Error("Stamp type is not defined"); + } + this._type = type; + this._creationInfo = creationInfo; + this.init(); + } + destroy() { + this._tempAnnotation = null; + super.destroy(); + } + undo() { + this.clear(); + } + clear() { + this._tempAnnotation = null; + } + saveAnnotationAsync() { + return __awaiter$c(this, void 0, void 0, function* () { + if (!this._pageId || !this._tempAnnotation) { + return; + } + yield this._docService.appendAnnotationToPageAsync(this._pageId, this._tempAnnotation); + yield this.createTempStampAnnotationAsync(); + }); + } + init() { + super.init(); + this._overlay.addEventListener("pointermove", this.onPointerMove); + this._overlay.addEventListener("pointerup", this.onPointerUp); + this.createTempStampAnnotationAsync(); + } + createStandardStamp(type, userName) { + const nowString = new Date().toISOString(); + const dto = { + uuid: UUID.getRandomUuid(), + annotationType: "/Stamp", + pageId: null, + dateCreated: nowString, + dateModified: nowString, + author: userName || "unknown", + textContent: null, + rect: null, + matrix: null, + stampType: type, + stampSubject: null, + stampImageData: null, + }; + return StampAnnotation.createFromDto(dto); + } + createCustomStamp(creationInfo, userName) { + const nowString = new Date().toISOString(); + const dto = { + uuid: UUID.getRandomUuid(), + annotationType: "/Stamp", + pageId: null, + dateCreated: nowString, + dateModified: nowString, + author: userName || "unknown", + textContent: null, + rect: creationInfo.rect || creationInfo.bbox, + bbox: creationInfo.bbox, + matrix: null, + stampType: creationInfo.type, + stampSubject: creationInfo.subject, + stampImageData: [...creationInfo.imageData], + }; + return StampAnnotation.createFromDto(dto); + } + createTempStampAnnotationAsync() { + return __awaiter$c(this, void 0, void 0, function* () { + let stamp; + if (standardStampCreationInfos[this._type]) { + stamp = this.createStandardStamp(this._type, this._docService.userName); + } + else if (this._creationInfo) { + stamp = this.createCustomStamp(this._creationInfo, this._docService.userName); + } + else { + throw new Error(`Unsupported stamp type: ${this._type}`); + } + const renderResult = yield stamp.renderApStreamAsync(); + this._svgGroup.innerHTML = ""; + this._svgGroup.append(...renderResult.clipPaths); + this._svgGroup.append(...renderResult.elements.map(x => x.element)); + this._tempAnnotation = stamp; + }); + } + refreshGroupPosition() { + } +} + +class TextAnnotator extends Annotator { + constructor(docService, pageService, parent, options) { + super(docService, pageService, parent); + this._color = (options === null || options === void 0 ? void 0 : options.color) || [0, 0, 0, 1]; + this._strokeWidth = (options === null || options === void 0 ? void 0 : options.strokeWidth) || 3; + } + emitDataChanged(count, saveable, clearable, undoable) { + this._docService.eventService.dispatchEvent(new AnnotatorDataChangeEvent({ + annotatorType: "text", + elementCount: count, + undoable, + clearable, + saveable, + })); + } +} + +class TextMarkupAnnotator extends TextAnnotator { + constructor(docService, pageService, parent, options) { + super(docService, pageService, parent, options); + this._svgGroupByPageId = new Map(); + this._coordsByPageId = new Map(); + this.onTextSelectionChange = (e) => { + var _a; + this.updateCoords(((_a = e === null || e === void 0 ? void 0 : e.detail) === null || _a === void 0 ? void 0 : _a.selectionInfos) || []); + }; + } + destroy() { + this._docService.eventService.removeListener(textSelectionChangeEvent, this.onTextSelectionChange); + this.clearGroup(); + super.destroy(); + } + undo() { + this.clear(); + } + clear() { + this._coordsByPageId.clear(); + this.clearGroup(); + } + init() { + super.init(); + this._docService.eventService.addListener(textSelectionChangeEvent, this.onTextSelectionChange); + } + clearGroup() { + this._svgGroupByPageId.forEach(x => x.innerHTML = ""); + this.emitDataChanged(0); + } + refreshGroupPosition() { + const { height: overlayHeight, top: overlayTop, left: overlayLeft } = this._overlay.getBoundingClientRect(); + const overlayBottom = overlayTop + overlayHeight; + const scale = this._pageService.scale; + this._pageService.renderedPages.forEach(x => { + const { height: pageHeight, width: pageWidth, top: pageTop, left: pageLeft } = x.viewContainer.getBoundingClientRect(); + const pageBottom = pageTop + pageHeight; + const pageRight = pageLeft + pageWidth; + const rotation = x.rotation; + let offsetX; + let offsetY; + switch (rotation) { + case 0: + offsetX = (pageLeft - overlayLeft) / scale; + offsetY = (overlayBottom - pageBottom) / scale; + break; + case 90: + offsetX = (pageLeft - overlayLeft) / scale; + offsetY = (overlayBottom - pageTop) / scale; + break; + case 180: + offsetX = (pageRight - overlayLeft) / scale; + offsetY = (overlayBottom - pageTop) / scale; + break; + case 270: + offsetX = (pageRight - overlayLeft) / scale; + offsetY = (overlayBottom - pageBottom) / scale; + break; + default: + throw new Error(`Invalid rotation degree: ${rotation}`); + } + let svg; + if (this._svgGroupByPageId.has(x.id)) { + svg = this._svgGroupByPageId.get(x.id); + } + else { + svg = document.createElementNS("http://www.w3.org/2000/svg", "g"); + this._svgGroupByPageId.set(x.id, svg); + this._svgGroup.append(svg); + } + applyTranslateRotateToElement(svg, offsetX, offsetY, rotation); + }); + } + updateCoords(selections) { + var _a; + this._coordsByPageId.clear(); + for (const selection of selections) { + const bl = this._pageService.getPageCoordsUnderPointer(selection.bottomLeft.x, selection.bottomLeft.y); + const br = this._pageService.getPageCoordsUnderPointer(selection.bottomRight.x, selection.bottomRight.y); + const tr = this._pageService.getPageCoordsUnderPointer(selection.topRight.x, selection.topRight.y); + const tl = this._pageService.getPageCoordsUnderPointer(selection.topLeft.x, selection.topLeft.y); + if (!bl || !br || !tr || !tl) { + continue; + } + if (new Set([bl.pageId, br.pageId, tr.pageId, tl.pageId]).size > 1) { + throw new Error("Not all the text selection corners are inside the same page"); + } + const quadPoints = [ + tl.pageX, tl.pageY, + tr.pageX, tr.pageY, + bl.pageX, bl.pageY, + br.pageX, br.pageY, + ]; + const pageId = bl.pageId; + if (this._coordsByPageId.has(pageId)) { + this._coordsByPageId.get(pageId).push(quadPoints); + } + else { + this._coordsByPageId.set(pageId, [quadPoints]); + } + } + this.redraw(); + if ((_a = this._coordsByPageId) === null || _a === void 0 ? void 0 : _a.size) { + this.emitDataChanged(this._coordsByPageId.size, true, true); + } + else { + this.emitDataChanged(0); + } + } + buildAnnotationDtos(type) { + const nowString = new Date().toISOString(); + const dtos = []; + this._coordsByPageId.forEach((quads, pageId) => { + const dto = { + uuid: UUID.getRandomUuid(), + annotationType: type, + pageId, + dateCreated: nowString, + dateModified: nowString, + author: this._docService.userName || "unknown", + textContent: null, + rect: null, + quadPoints: quads.flat(), + color: this._color, + strokeWidth: this._strokeWidth, + strokeDashGap: null, + }; + dtos.push(dto); + }); + return dtos; + } +} + +var __awaiter$b = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class TextHighlightAnnotator extends TextMarkupAnnotator { + constructor(docService, pageService, parent, options) { + super(docService, pageService, parent, options || {}); + this.init(); + } + saveAnnotationAsync() { + return __awaiter$b(this, void 0, void 0, function* () { + if (!this._coordsByPageId.size) { + return; + } + const dtos = this.buildAnnotationDtos("/Highlight"); + for (const dto of dtos) { + const annotation = HighlightAnnotation.createFromDto(dto); + yield this._docService.appendAnnotationToPageAsync(dto.pageId, annotation); + } + this.clear(); + }); + } + redraw() { + const [r, g, b, a] = this._color || [0, 0, 0, 1]; + this._svgGroupByPageId.forEach((group, pageId) => { + group.innerHTML = ""; + const quads = this._coordsByPageId.get(pageId); + if (quads === null || quads === void 0 ? void 0 : quads.length) { + quads.forEach(quad => { + const [x3, y3, x2, y2, x0, y0, x1, y1] = quad; + const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); + path.setAttribute("fill", `rgba(${r * 255},${g * 255},${b * 255},${a})`); + path.setAttribute("stroke", "none"); + path.setAttribute("d", `M ${x0},${y0} L ${x1},${y1} L ${x2},${y2} L ${x3},${y3} Z`); + group.append(path); + }); + } + }); + } +} + +var __awaiter$a = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class TextSquigglyAnnotator extends TextMarkupAnnotator { + constructor(docService, pageService, parent, options) { + super(docService, pageService, parent, options || {}); + this.init(); + } + saveAnnotationAsync() { + return __awaiter$a(this, void 0, void 0, function* () { + if (!this._coordsByPageId.size) { + return; + } + const dtos = this.buildAnnotationDtos("/Squiggly"); + for (const dto of dtos) { + const annotation = SquigglyAnnotation.createFromDto(dto); + yield this._docService.appendAnnotationToPageAsync(dto.pageId, annotation); + } + this.clear(); + }); + } + redraw() { + const [r, g, b, a] = this._color || [0, 0, 0, 1]; + this._svgGroupByPageId.forEach((group, pageId) => { + group.innerHTML = ""; + const quads = this._coordsByPageId.get(pageId); + if (quads === null || quads === void 0 ? void 0 : quads.length) { + quads.forEach(quad => { + const [, , , , x0, y0, x1, y1] = quad; + const squigglyLinePoints = buildSquigglyLine(new u(x0, y0), new u(x1, y1), SquigglyAnnotation.squiggleSize); + if (squigglyLinePoints === null || squigglyLinePoints === void 0 ? void 0 : squigglyLinePoints.length) { + let pathTextData = `M ${squigglyLinePoints[0].x},${squigglyLinePoints[0].y} `; + for (let j = 1; j < squigglyLinePoints.length; j++) { + pathTextData += `L ${squigglyLinePoints[j].x},${squigglyLinePoints[j].y} `; + } + const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); + path.setAttribute("fill", "none"); + path.setAttribute("stroke", `rgba(${r * 255},${g * 255},${b * 255},${a})`); + path.setAttribute("stroke-width", this._strokeWidth + ""); + path.setAttribute("stroke-linecap", "square"); + path.setAttribute("d", pathTextData); + group.append(path); + } + }); + } + }); + } +} + +var __awaiter$9 = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class TextStrikeoutAnnotator extends TextMarkupAnnotator { + constructor(docService, pageService, parent, options) { + super(docService, pageService, parent, options || {}); + this.init(); + } + saveAnnotationAsync() { + return __awaiter$9(this, void 0, void 0, function* () { + if (!this._coordsByPageId.size) { + return; + } + const dtos = this.buildAnnotationDtos("/Strikeout"); + for (const dto of dtos) { + const annotation = StrikeoutAnnotation.createFromDto(dto); + yield this._docService.appendAnnotationToPageAsync(dto.pageId, annotation); + } + this.clear(); + }); + } + redraw() { + const [r, g, b, a] = this._color || [0, 0, 0, 1]; + this._svgGroupByPageId.forEach((group, pageId) => { + group.innerHTML = ""; + const quads = this._coordsByPageId.get(pageId); + const bottomLeft = new u(); + const bottomRight = new u(); + const topRight = new u(); + const topLeft = new u(); + const start = new u(); + const end = new u(); + if (quads === null || quads === void 0 ? void 0 : quads.length) { + quads.forEach(quad => { + const [x3, y3, x2, y2, x0, y0, x1, y1] = quad; + bottomLeft.set(x0, y0); + bottomRight.set(x1, y1); + topRight.set(x2, y2); + topLeft.set(x3, y3); + start.setFromVec2(bottomLeft).add(topLeft).multiplyByScalar(0.5); + end.setFromVec2(bottomRight).add(topRight).multiplyByScalar(0.5); + const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); + path.setAttribute("fill", "none"); + path.setAttribute("stroke", `rgba(${r * 255},${g * 255},${b * 255},${a})`); + path.setAttribute("stroke-width", this._strokeWidth + ""); + path.setAttribute("stroke-linecap", "square"); + path.setAttribute("d", `M ${start.x},${start.y} L ${end.x},${end.y}`); + group.append(path); + }); + } + }); + } +} + +var __awaiter$8 = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class TextUnderlineAnnotator extends TextMarkupAnnotator { + constructor(docService, pageService, parent, options) { + super(docService, pageService, parent, options || {}); + this.init(); + } + saveAnnotationAsync() { + return __awaiter$8(this, void 0, void 0, function* () { + if (!this._coordsByPageId.size) { + return; + } + const dtos = this.buildAnnotationDtos("/Underline"); + for (const dto of dtos) { + const annotation = UnderlineAnnotation.createFromDto(dto); + yield this._docService.appendAnnotationToPageAsync(dto.pageId, annotation); + } + this.clear(); + }); + } + redraw() { + const [r, g, b, a] = this._color || [0, 0, 0, 1]; + this._svgGroupByPageId.forEach((group, pageId) => { + group.innerHTML = ""; + const quads = this._coordsByPageId.get(pageId); + if (quads === null || quads === void 0 ? void 0 : quads.length) { + quads.forEach(quad => { + const [, , , , x0, y0, x1, y1] = quad; + const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); + path.setAttribute("fill", "none"); + path.setAttribute("stroke", `rgba(${r * 255},${g * 255},${b * 255},${a})`); + path.setAttribute("stroke-width", this._strokeWidth + ""); + path.setAttribute("stroke-linecap", "square"); + path.setAttribute("d", `M ${x0},${y0} L ${x1},${y1}`); + group.append(path); + }); + } + }); + } +} + +var __awaiter$7 = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class TextNoteAnnotator extends TextAnnotator { + constructor(docService, pageService, viewer, options) { + super(docService, pageService, viewer.container, options || {}); + this.onPointerMove = (e) => { + if (!e.isPrimary) { + return; + } + const { clientX: cx, clientY: cy } = e; + const { height: oh, top, left: ox } = this._parent.getBoundingClientRect(); + const oy = top + oh; + const offsetX = (cx - ox) / this._pageService.scale; + const offsetY = (oy - cy) / this._pageService.scale; + const [x1, y1, x2, y2] = this._tempAnnotation.Rect; + this._svgGroup.setAttribute("transform", `translate(${offsetX - (x2 - x1) / 4} ${offsetY - (y2 - y1) / 4})`); + this.updatePointerCoords(cx, cy); + }; + this.onPointerUp = (e) => __awaiter$7(this, void 0, void 0, function* () { + var _a, _b, _c; + if (!e.isPrimary || e.button === 2) { + return; + } + const { clientX: cx, clientY: cy } = e; + if (e.pointerType === "touch") { + const longTap = performance.now() - ((_a = this._lastPointerDownInfo) === null || _a === void 0 ? void 0 : _a.timestamp) > 700; + if (longTap) { + const downX = ((_b = this._lastPointerDownInfo) === null || _b === void 0 ? void 0 : _b.clientX) || 0; + const downY = ((_c = this._lastPointerDownInfo) === null || _c === void 0 ? void 0 : _c.clientY) || 0; + const displacement = Math.abs(h(cx, cy, downX, downY)); + const displaced = displacement > 7.5; + if (!displaced) { + return; + } + } + } + const pageCoords = this._pageService.getPageCoordsUnderPointer(cx, cy); + this._pointerCoordsInPageCS = pageCoords; + if (!pageCoords || !this._tempAnnotation) { + return; + } + const { pageId, pageX, pageY, pageRotation } = this._pointerCoordsInPageCS; + const [x1, y1, x2, y2] = this._tempAnnotation.Rect; + yield this._tempAnnotation.moveToAsync(new u(pageX + (x2 - x1) / 4, pageY + (y2 - y1) / 4)); + if (pageRotation) { + yield this._tempAnnotation.rotateByAsync(-pageRotation / 180 * Math.PI, new u(pageX, pageY)); + } + this._pageId = pageId; + yield this.saveAnnotationAsync(); + }); + this._viewer = viewer; + this.init(); + } + destroy() { + this._tempAnnotation = null; + super.destroy(); + } + undo() { + this.clear(); + } + clear() { + this._tempAnnotation = null; + } + saveAnnotationAsync() { + var _a, _b; + return __awaiter$7(this, void 0, void 0, function* () { + if (!this._pageId || !this._tempAnnotation) { + return; + } + const initialText = (_b = (_a = this._tempAnnotation) === null || _a === void 0 ? void 0 : _a.Contents) === null || _b === void 0 ? void 0 : _b.literal; + const text = yield this._viewer.showTextDialogAsync(initialText); + if (text !== null) { + yield this._tempAnnotation.setTextContentAsync(text); + yield this._docService.appendAnnotationToPageAsync(this._pageId, this._tempAnnotation); + } + yield this.createTempNoteAnnotationAsync(); + }); + } + init() { + super.init(); + this._overlay.addEventListener("pointermove", this.onPointerMove); + this._overlay.addEventListener("pointerup", this.onPointerUp); + this.createTempNoteAnnotationAsync(); + } + createTempNoteAnnotationAsync() { + return __awaiter$7(this, void 0, void 0, function* () { + const note = TextAnnotation.createStandard(this._docService.userName, this._color); + const renderResult = yield note.renderApStreamAsync(); + this._svgGroup.innerHTML = ""; + this._svgGroup.append(...renderResult.clipPaths); + this._svgGroup.append(...renderResult.elements.map(x => x.element)); + this._tempAnnotation = note; + }); + } + refreshGroupPosition() { + } +} + +var __awaiter$6 = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class FreeTextAnnotator extends TextAnnotator { + constructor(docService, pageService, viewer, options) { + super(docService, pageService, viewer.container, options || {}); + this.onPointerDown = (e) => { + if (!e.isPrimary || e.button === 2) { + return; + } + const { clientX: cx, clientY: cy } = e; + this.updatePointerCoords(cx, cy); + const pageCoords = this._pointerCoordsInPageCS; + if (!pageCoords) { + return; + } + const { pageX: px, pageY: py, pageId } = pageCoords; + this._pageId = pageId; + this._down = new u(px, py); + this.clear(); + this.refreshGroupPosition(); + const target = e.target; + target.addEventListener("pointermove", this.onPointerMove); + target.addEventListener("pointerup", this.onPointerUp); + target.addEventListener("pointerout", this.onPointerUp); + target.setPointerCapture(e.pointerId); + }; + this.onPointerMove = (e) => { + if (!e.isPrimary + || !this._down) { + return; + } + const { clientX: cx, clientY: cy } = e; + this.updatePointerCoords(cx, cy); + const pageCoords = this._pointerCoordsInPageCS; + if (!pageCoords || pageCoords.pageId !== this._pageId) { + return; + } + const { pageX: px, pageY: py } = pageCoords; + const { min, max } = u.minMax(this._down, new u(px, py)); + this.redrawRect(min, max); + }; + this.onPointerUp = (e) => __awaiter$6(this, void 0, void 0, function* () { + if (!e.isPrimary) { + return; + } + const target = e.target; + target.removeEventListener("pointermove", this.onPointerMove); + target.removeEventListener("pointerup", this.onPointerUp); + target.removeEventListener("pointerout", this.onPointerUp); + target.releasePointerCapture(e.pointerId); + if (this._rect) { + yield this.saveAnnotationAsync(); + } + }); + this._viewer = viewer; + this.init(); + } + destroy() { + this.emitDataChanged(0); + super.destroy(); + } + undo() { + this.clear(); + } + clear() { + this._rect = null; + this._svgGroup.innerHTML = ""; + this.emitDataChanged(0); + } + saveAnnotationAsync() { + return __awaiter$6(this, void 0, void 0, function* () { + if (!this._pageId || !this._rect) { + return; + } + const text = yield this._viewer.showTextDialogAsync(""); + if (text !== null) { + const pageId = this._pageId; + const dto = this.buildAnnotationDto(text); + if (dto) { + const annotation = yield FreeTextAnnotation.createFromDtoAsync(dto, this._docService.fontMap); + yield this._docService.appendAnnotationToPageAsync(pageId, annotation); + } + } + this.clear(); + }); + } + init() { + super.init(); + this._overlay.addEventListener("pointerdown", this.onPointerDown); + } + redrawRect(min, max) { + this._svgGroup.innerHTML = ""; + const minSize = this._strokeWidth * 2; + if (max.x - min.x <= minSize || max.y - min.y <= minSize) { + this._rect = null; + return; + } + const [r, g, b, a] = this._color || [0, 0, 0, 1]; + this._rect = [min.x, min.y, max.x, max.y]; + const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + rect.setAttribute("fill", "white"); + rect.setAttribute("stroke", `rgba(${r * 255},${g * 255},${b * 255},${a})`); + rect.setAttribute("stroke-width", this._strokeWidth + ""); + rect.setAttribute("x", min.x + ""); + rect.setAttribute("y", min.y + ""); + rect.setAttribute("width", max.x - min.x + ""); + rect.setAttribute("height", max.y - min.y + ""); + this._svgGroup.append(rect); + } + refreshGroupPosition() { + if (!this._pageId && this._pageId !== 0) { + return; + } + const page = this._pageService.renderedPages.find(x => x.id === this._pageId); + if (!page) { + this._svgGroup.setAttribute("transform", "scale(0)"); + return; + } + const { height: pageHeight, width: pageWidth, top: pageTop, left: pageLeft } = page.viewContainer.getBoundingClientRect(); + const pageBottom = pageTop + pageHeight; + const pageRight = pageLeft + pageWidth; + const { height: overlayHeight, top: overlayTop, left: overlayLeft } = this._overlay.getBoundingClientRect(); + const overlayBottom = overlayTop + overlayHeight; + const rotation = page.rotation; + const scale = page.scale; + let offsetX; + let offsetY; + switch (rotation) { + case 0: + offsetX = (pageLeft - overlayLeft) / scale; + offsetY = (overlayBottom - pageBottom) / scale; + break; + case 90: + offsetX = (pageLeft - overlayLeft) / scale; + offsetY = (overlayBottom - pageTop) / scale; + break; + case 180: + offsetX = (pageRight - overlayLeft) / scale; + offsetY = (overlayBottom - pageTop) / scale; + break; + case 270: + offsetX = (pageRight - overlayLeft) / scale; + offsetY = (overlayBottom - pageBottom) / scale; + break; + default: + throw new Error(`Invalid rotation degree: ${rotation}`); + } + applyTranslateRotateToElement(this._svgGroup, offsetX, offsetY, rotation); + } + buildAnnotationDto(text) { + const margin = this._strokeWidth / 2; + const lm = margin; + const tm = margin; + const rm = margin; + const bm = margin; + const [xmin, ymin, xmax, ymax] = this._rect; + const horCenterX = (xmin + xmax) / 2; + const vertCenterY = (ymin + ymax) / 2; + const points = { + bl: [xmin, ymin], + tr: [xmax, ymax], + br: [xmax, ymin], + tl: [xmin, ymax], + l: [xmin, vertCenterY], + t: [horCenterX, ymax], + r: [xmax, vertCenterY], + b: [horCenterX, ymin], + }; + const nowString = new Date().toISOString(); + const dto = { + uuid: UUID.getRandomUuid(), + annotationType: "/FreeText", + pageId: null, + dateCreated: nowString, + dateModified: nowString, + author: this._docService.userName || "unknown", + textContent: text, + rect: [xmin - lm, ymin - bm, xmax + rm, ymax + tm], + points, + color: [this._color[0], this._color[1], this._color[2], 1], + strokeWidth: this._strokeWidth, + strokeDashGap: null, + }; + return dto; + } +} + +var __awaiter$5 = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class FreeTextCalloutAnnotator extends TextAnnotator { + constructor(docService, pageService, viewer, options) { + super(docService, pageService, viewer.container, options || {}); + this.onPointerDown = (e) => { + if (!e.isPrimary || e.button === 2) { + return; + } + const { clientX: cx, clientY: cy } = e; + this.updatePointerCoords(cx, cy); + const pageCoords = this._pointerCoordsInPageCS; + if (!pageCoords) { + return; + } + const { pageX: px, pageY: py, pageId } = pageCoords; + if (pageId !== this._pageId) { + this.clear(); + } + this._pageId = pageId; + this._down = new u(px, py); + this.refreshGroupPosition(); + const target = e.target; + target.addEventListener("pointermove", this.onPointerMove); + target.addEventListener("pointerup", this.onPointerUp); + target.addEventListener("pointerout", this.onPointerUp); + target.setPointerCapture(e.pointerId); + }; + this.onPointerMove = (e) => { + if (!e.isPrimary + || !this._down) { + return; + } + const { clientX: cx, clientY: cy } = e; + this.updatePointerCoords(cx, cy); + if (!this._points) { + const pageCoords = this._pointerCoordsInPageCS; + if (!pageCoords || pageCoords.pageId !== this._pageId) { + return; + } + const { pageX: px, pageY: py } = pageCoords; + const { min, max } = u.minMax(this._down, new u(px, py)); + this.redrawRect(min, max); + } + }; + this.onPointerUp = (e) => { + if (!e.isPrimary) { + return; + } + const target = e.target; + target.removeEventListener("pointermove", this.onPointerMove); + target.removeEventListener("pointerup", this.onPointerUp); + target.removeEventListener("pointerout", this.onPointerUp); + target.releasePointerCapture(e.pointerId); + if (!this._rect) { + return; + } + if (!this._points) { + this.initPoints(); + return; + } + const pageCoords = this._pointerCoordsInPageCS; + if (!pageCoords || pageCoords.pageId !== this._pageId) { + return; + } + const { pageX: px, pageY: py } = pageCoords; + const p = new u(px, py); + const { l, b, r, t } = this._points; + const lv = new u(l[0], l[1]); + const bv = new u(b[0], b[1]); + const rv = new u(r[0], r[1]); + const tv = new u(t[0], t[1]); + let cob = lv; + let minDistance = u.subtract(p, lv).getMagnitude(); + const bvToP = u.subtract(p, bv).getMagnitude(); + if (bvToP < minDistance) { + minDistance = bvToP; + cob = bv; + } + const rvToP = u.subtract(p, rv).getMagnitude(); + if (rvToP < minDistance) { + minDistance = rvToP; + cob = rv; + } + const tvToP = u.subtract(p, tv).getMagnitude(); + if (tvToP < minDistance) { + minDistance = tvToP; + cob = tv; + } + this._points.cob = cob.toFloatArray(); + if (!this._points.cop) { + this._points.cop = p.toFloatArray(); + } + else { + this._points.cok = p.toFloatArray(); + } + this.redrawCallout(); + }; + this._viewer = viewer; + this.init(); + } + destroy() { + this.emitDataChanged(0); + super.destroy(); + } + undo() { + this.clear(); + } + clear() { + this._rect = null; + this._points = null; + this._svgGroup.innerHTML = ""; + this.emitDataChanged(0); + } + saveAnnotationAsync() { + return __awaiter$5(this, void 0, void 0, function* () { + if (!this._pageId || !this._rect) { + return; + } + const text = yield this._viewer.showTextDialogAsync(""); + if (text !== null) { + const pageId = this._pageId; + const dto = this.buildAnnotationDto(text); + if (dto) { + const annotation = yield FreeTextAnnotation.createFromDtoAsync(dto, this._docService.fontMap); + yield this._docService.appendAnnotationToPageAsync(pageId, annotation); + } + } + this.clear(); + }); + } + init() { + super.init(); + this._overlay.addEventListener("pointerdown", this.onPointerDown); + } + initPoints() { + const [xmin, ymin, xmax, ymax] = this._rect; + const horCenterX = (xmin + xmax) / 2; + const vertCenterY = (ymin + ymax) / 2; + const points = { + bl: [xmin, ymin], + tr: [xmax, ymax], + br: [xmax, ymin], + tl: [xmin, ymax], + l: [xmin, vertCenterY], + t: [horCenterX, ymax], + r: [xmax, vertCenterY], + b: [horCenterX, ymin], + }; + this._points = points; + this.emitDataChanged(2, true, true); + } + redrawRect(min, max) { + this._svgGroup.innerHTML = ""; + const minSize = this._strokeWidth * 2; + if (max.x - min.x <= minSize || max.y - min.y <= minSize) { + this._rect = null; + return; + } + const [r, g, b, a] = this._color || [0, 0, 0, 1]; + this._rect = [min.x, min.y, max.x, max.y]; + const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + rect.setAttribute("fill", "white"); + rect.setAttribute("stroke", `rgba(${r * 255},${g * 255},${b * 255},${a})`); + rect.setAttribute("stroke-width", this._strokeWidth + ""); + rect.setAttribute("x", min.x + ""); + rect.setAttribute("y", min.y + ""); + rect.setAttribute("width", max.x - min.x + ""); + rect.setAttribute("height", max.y - min.y + ""); + this._svgGroup.append(rect); + } + redrawCallout() { + const svgRect = this._svgGroup.lastChild; + svgRect.remove(); + this._svgGroup.innerHTML = ""; + const [r, g, b, a] = this._color || [0, 0, 0, 1]; + const callout = document.createElementNS("http://www.w3.org/2000/svg", "path"); + callout.setAttribute("fill", "none"); + callout.setAttribute("stroke", `rgba(${r * 255},${g * 255},${b * 255},${a})`); + callout.setAttribute("stroke-width", this._strokeWidth + ""); + let d = `M${this._points.cob[0]},${this._points.cob[1]} `; + if (this._points.cok) { + d += `L${this._points.cok[0]},${this._points.cok[1]} `; + } + d += `L${this._points.cop[0]},${this._points.cop[1]}`; + callout.setAttribute("d", d); + this._svgGroup.append(callout); + this._svgGroup.append(svgRect); + } + refreshGroupPosition() { + if (!this._pageId && this._pageId !== 0) { + return; + } + const page = this._pageService.renderedPages.find(x => x.id === this._pageId); + if (!page) { + this._svgGroup.setAttribute("transform", "scale(0)"); + return; + } + const { height: pageHeight, width: pageWidth, top: pageTop, left: pageLeft } = page.viewContainer.getBoundingClientRect(); + const pageBottom = pageTop + pageHeight; + const pageRight = pageLeft + pageWidth; + const { height: overlayHeight, top: overlayTop, left: overlayLeft } = this._overlay.getBoundingClientRect(); + const overlayBottom = overlayTop + overlayHeight; + const rotation = page.rotation; + const scale = page.scale; + let offsetX; + let offsetY; + switch (rotation) { + case 0: + offsetX = (pageLeft - overlayLeft) / scale; + offsetY = (overlayBottom - pageBottom) / scale; + break; + case 90: + offsetX = (pageLeft - overlayLeft) / scale; + offsetY = (overlayBottom - pageTop) / scale; + break; + case 180: + offsetX = (pageRight - overlayLeft) / scale; + offsetY = (overlayBottom - pageTop) / scale; + break; + case 270: + offsetX = (pageRight - overlayLeft) / scale; + offsetY = (overlayBottom - pageBottom) / scale; + break; + default: + throw new Error(`Invalid rotation degree: ${rotation}`); + } + applyTranslateRotateToElement(this._svgGroup, offsetX, offsetY, rotation); + } + buildAnnotationDto(text) { + let margin; + if (this._points.cob) { + const endingSizeWoStroke = Math.max(this._strokeWidth * LINE_END_MULTIPLIER, LINE_END_MIN_SIZE); + const endingSize = endingSizeWoStroke + this._strokeWidth; + margin = endingSize / 2; + } + else { + margin = this._strokeWidth / 2; + } + const lm = margin; + const tm = margin; + const rm = margin; + const bm = margin; + const { bl, tr, br, tl, l, t, r, b, cob, cok, cop } = this._points; + const { min, max } = u.minMax(new u(bl[0], bl[1]), new u(tr[0], tr[1]), new u(br[0], br[1]), new u(tl[0], tl[1]), new u(l[0], l[1]), new u(t[0], t[1]), new u(r[0], r[1]), new u(b[0], b[1]), cob ? new u(cob[0], cob[1]) : new u(bl[0], bl[1]), cok ? new u(cok[0], cok[1]) : new u(bl[0], bl[1]), cop ? new u(cop[0], cop[1]) : new u(bl[0], bl[1])); + const nowString = new Date().toISOString(); + const dto = { + uuid: UUID.getRandomUuid(), + annotationType: "/FreeText", + pageId: null, + dateCreated: nowString, + dateModified: nowString, + author: this._docService.userName || "unknown", + textContent: text, + rect: [min.x - lm, min.y - bm, max.x + rm, max.y + tm], + points: this._points, + intent: this._points.cob ? freeTextIntents.WITH_CALLOUT : freeTextIntents.PLAIN_TEXT, + calloutEndingType: this._points.cob ? lineEndingTypes.ARROW_OPEN : null, + color: [this._color[0], this._color[1], this._color[2], 1], + strokeWidth: this._strokeWidth, + strokeDashGap: null, + }; + return dto; + } +} + +const textAnnotatorTypes = ["highlight", "strikeout", "squiggly", "underline", + "note", "freeText", "freeTextCallout"]; +class TextAnnotatorFactory { + createAnnotator(docService, pageService, viewer, options, type) { + if (!docService) { + throw new Error("Document service is not defined"); + } + if (!pageService) { + throw new Error("Page service is not defined"); + } + if (!viewer) { + throw new Error("Viewer is not defined"); + } + type || (type = this._lastType || "highlight"); + this._lastType = type; + const color = (options === null || options === void 0 ? void 0 : options.color) || this._lastColor || [0, 0, 0, 0.9]; + this._lastColor = color; + const strokeWidth = (options === null || options === void 0 ? void 0 : options.strokeWidth) || this._lastStrokeWidth || 2; + this._lastStrokeWidth = strokeWidth; + const combinedOptions = { + color, + strokeWidth, + }; + switch (type) { + case "note": + return new TextNoteAnnotator(docService, pageService, viewer, combinedOptions); + case "freeText": + return new FreeTextAnnotator(docService, pageService, viewer, combinedOptions); + case "freeTextCallout": + return new FreeTextCalloutAnnotator(docService, pageService, viewer, combinedOptions); + case "highlight": + return new TextHighlightAnnotator(docService, pageService, viewer.container, combinedOptions); + case "squiggly": + return new TextSquigglyAnnotator(docService, pageService, viewer.container, combinedOptions); + case "strikeout": + return new TextStrikeoutAnnotator(docService, pageService, viewer.container, combinedOptions); + case "underline": + return new TextUnderlineAnnotator(docService, pageService, viewer.container, combinedOptions); + default: + throw new Error(`Invalid geometric annotator type: ${type}`); + } + } +} + +class AnnotatorService { + get mode() { + return this._mode; + } + set mode(value) { + this.setMode(value); + } + get annotator() { + return this._annotator; + } + constructor(docService, pageService, customStampService, viewer) { + this._annotationColors = [ + [0, 0, 0, 0.5], + [0.804, 0, 0, 0.5], + [0, 0.804, 0, 0.5], + [0, 0, 0.804, 0.5], + [1, 0.5, 0, 0.5], + [1, 0.2, 1, 0.5], + ]; + this._strokeColor = this._annotationColors[0]; + this._strokeWidth = 3; + this._stampType = supportedStampTypes[0].type; + this._geometricCloudMode = false; + this._geometricSubmode = geometricAnnotatorTypes[0]; + this._textSubmode = textAnnotatorTypes[0]; + this.onContextMenu = (event) => { + if (this._contextMenu.enabled) { + event.preventDefault(); + this._contextMenu.show(new u(event.clientX, event.clientY), this._viewer.container); + } + }; + this.onPagesRendered = (event) => { + this._contextMenu.hide(); + }; + if (!docService) { + throw new Error("Document service is not defined"); + } + if (!pageService) { + throw new Error("Page service is not defined"); + } + if (!customStampService) { + throw new Error("Custom stamp service is not defined"); + } + if (!viewer) { + throw new Error("Viewer is not defined"); + } + this._docService = docService; + this._pageService = pageService; + this._customStampService = customStampService; + this._viewer = viewer; + this.init(); + } + destroy() { + var _a, _b, _c; + this._docService.eventService.removeListener(pagesRenderedEvent, this.onPagesRendered); + this._viewer.container.removeEventListener("contextmenu", this.onContextMenu); + (_a = this._viewerResizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect(); + (_b = this._contextMenu) === null || _b === void 0 ? void 0 : _b.destroy(); + (_c = this._annotator) === null || _c === void 0 ? void 0 : _c.destroy(); + } + init() { + this._docService.eventService.addListener(pagesRenderedEvent, this.onPagesRendered); + this._viewer.container.addEventListener("contextmenu", this.onContextMenu); + const viewerRObserver = new ResizeObserver((entries) => { + var _a; + (_a = this._contextMenu) === null || _a === void 0 ? void 0 : _a.hide(); + }); + viewerRObserver.observe(this._viewer.container); + this._viewerResizeObserver = viewerRObserver; + this._contextMenu = new ContextMenu(); + this._geometricFactory = new GeometricAnnotatorFactory(); + this._textFactory = new TextAnnotatorFactory(); + } + setMode(mode) { + var _a; + mode || (mode = this._mode); + this._contextMenu.content = []; + (_a = this._annotator) === null || _a === void 0 ? void 0 : _a.destroy(); + this._docService.setSelectedAnnotation(null); + this._mode = mode; + if (this._mode === "text" + && (this._textSubmode === "highlight" + || this._textSubmode === "squiggly" + || this._textSubmode === "strikeout" + || this._textSubmode === "underline")) { + this._viewer.container.classList.add("mode-text-markup"); + } + else { + this._viewer.container.classList.remove("mode-text-markup"); + } + switch (mode) { + case "select": + this._contextMenu.enabled = false; + return; + case "stamp": + this._annotator = new StampAnnotator(this._docService, this._pageService, this._viewer.container, this._stampType, this._stampCreationInfo); + break; + case "pen": + this._annotator = new PenAnnotator(this._docService, this._pageService, this._viewer.container, { + strokeWidth: this._strokeWidth, + color: this._strokeColor, + }); + break; + case "geometric": + this._annotator = this._geometricFactory.createAnnotator(this._docService, this._pageService, this._viewer.container, { + strokeWidth: this._strokeWidth, + color: this._strokeColor, + cloudMode: this._geometricCloudMode, + }, this._geometricSubmode); + break; + case "text": + this._strokeWidth = 2; + this._annotator = this._textFactory.createAnnotator(this._docService, this._pageService, this._viewer, { + strokeWidth: this._strokeWidth, + color: this._strokeColor, + }, this._textSubmode); + break; + default: + throw new Error(`Invalid annotation mode: ${mode}`); + } + const cmContent = this.buildContextMenuContent(); + this._contextMenu.content = cmContent; + this._contextMenu.enabled = true; + } + buildContextMenuContent() { + switch (this._mode) { + case "select": + return []; + case "stamp": + return [ + this.buildCustomStampButtons(), + this.buildStampTypePicker(), + ]; + case "pen": + return [ + this.buildStrokeColorPicker(), + this.buildStrokeWidthSlider(false), + ]; + case "geometric": + return [ + this.buildGeometricSubmodePicker(), + this.buildStrokeColorPicker(), + this.buildStrokeWidthSlider(true), + ]; + case "text": + return [ + this.buildTextSubmodePicker(), + this.buildStrokeColorPicker(), + ]; + default: + throw new Error(`Invalid annotation mode: ${this._mode}`); + } + } + buildCustomStampButtons() { + const buttonsContainer = DomUtils.htmlToElements(HtmlTemplates.stampContextButtonsHtml)[0]; + buttonsContainer.querySelector(".stamp-load-image").addEventListener("click", () => { + this._customStampService.startLoadingImage(); + }); + buttonsContainer.querySelector(".stamp-draw-image").addEventListener("click", () => { + this._customStampService.startDrawing(); + }); + if (this._stampCreationInfo) { + const deleteButton = buttonsContainer.querySelector(".stamp-delete"); + deleteButton.addEventListener("click", () => { + this._customStampService.removeCustomStamp(this._stampType); + }); + deleteButton.classList.remove("disabled"); + } + return buttonsContainer; + } + buildStampTypePicker() { + const stampTypes = supportedStampTypes; + const pickerDiv = document.createElement("div"); + pickerDiv.classList.add("context-menu-content", "column"); + [...stampTypes, ...this._customStampService.getCustomStamps()].forEach(x => { + const item = document.createElement("div"); + item.classList.add("context-menu-stamp-select-button"); + if (x.type === this._stampType) { + item.classList.add("on"); + } + item.addEventListener("click", () => { + this._stampType = x.type; + if (x["imageData"]) { + this._stampCreationInfo = x; + } + else { + this._stampCreationInfo = null; + } + this.setMode(); + }); + const stampName = document.createElement("div"); + stampName.innerHTML = x.name; + item.append(stampName); + pickerDiv.append(item); + }); + return pickerDiv; + } + buildGeometricSubmodePicker() { + const submodePicker = document.createElement("div"); + submodePicker.classList.add("context-menu-content", "row"); + geometricAnnotatorTypes.forEach(x => { + const item = document.createElement("div"); + item.classList.add("panel-button"); + if (x === this._geometricSubmode) { + item.classList.add("on"); + } + item.addEventListener("click", () => { + this._geometricSubmode = x; + this.setMode(); + }); + item.innerHTML = Icons.geometricIcons[x]; + submodePicker.append(item); + }); + return submodePicker; + } + buildTextSubmodePicker() { + const submodePicker = document.createElement("div"); + submodePicker.classList.add("context-menu-content", "row"); + textAnnotatorTypes.forEach(x => { + const item = document.createElement("div"); + item.classList.add("panel-button"); + if (x === this._textSubmode) { + item.classList.add("on"); + } + item.addEventListener("click", () => { + this._textSubmode = x; + this.setMode(); + }); + item.innerHTML = Icons.textIcons[x]; + submodePicker.append(item); + }); + return submodePicker; + } + buildStrokeColorPicker() { + const colorPickerDiv = document.createElement("div"); + colorPickerDiv.classList.add("context-menu-content", "row"); + this._annotationColors.forEach(x => { + const item = document.createElement("div"); + item.classList.add("panel-button"); + if (x === this._strokeColor) { + item.classList.add("on"); + } + item.addEventListener("click", () => { + this._strokeColor = x; + this.setMode(); + }); + const colorIcon = document.createElement("div"); + colorIcon.classList.add("context-menu-color-icon"); + colorIcon.style.backgroundColor = `rgb(${x[0] * 255},${x[1] * 255},${x[2] * 255})`; + item.append(colorIcon); + colorPickerDiv.append(item); + }); + return colorPickerDiv; + } + buildStrokeWidthSlider(cloudButtons) { + const disableLineTypeButtons = !cloudButtons + || this._geometricSubmode === "polyline" + || this._geometricSubmode === "line" + || this._geometricSubmode === "arrow"; + const div = document.createElement("div"); + div.classList.add("context-menu-content", "row"); + const cloudyLineButton = document.createElement("div"); + cloudyLineButton.classList.add("panel-button"); + if (disableLineTypeButtons) { + cloudyLineButton.classList.add("disabled"); + } + else { + if (this._geometricCloudMode) { + cloudyLineButton.classList.add("on"); + } + cloudyLineButton.addEventListener("click", () => { + this._geometricCloudMode = true; + this.setMode(); + }); + } + cloudyLineButton.innerHTML = Icons.lineTypeIcons.cloudy; + div.append(cloudyLineButton); + const straightLineButton = document.createElement("div"); + straightLineButton.classList.add("panel-button"); + if (disableLineTypeButtons) { + straightLineButton.classList.add("disabled"); + } + else { + if (!this._geometricCloudMode) { + straightLineButton.classList.add("on"); + } + straightLineButton.addEventListener("click", () => { + this._geometricCloudMode = false; + this.setMode(); + }); + } + straightLineButton.innerHTML = Icons.lineTypeIcons.straight; + div.append(straightLineButton); + const slider = document.createElement("input"); + slider.setAttribute("type", "range"); + slider.setAttribute("min", "1"); + slider.setAttribute("max", "32"); + slider.setAttribute("step", "1"); + slider.setAttribute("value", this._strokeWidth + ""); + slider.classList.add("context-menu-slider"); + slider.addEventListener("change", () => { + this._strokeWidth = slider.valueAsNumber; + this.setMode(); + }); + div.append(slider); + return div; + } +} + +const viewerModes = ["text", "hand", "annotation", "comparison"]; +class ModeService { + get mode() { + return this._mode; + } + set mode(value) { + var _a; + if ((_a = this._onModeChangeStarted) === null || _a === void 0 ? void 0 : _a.size) { + this._onModeChangeStarted.forEach(x => x()); + } + if (!value || value === this._mode) { + return; + } + this._mode = value; + } + constructor(options) { + this._onModeChangeStarted = new Set(); + const modes = []; + viewerModes.forEach(x => { + var _a; + if (!((_a = options === null || options === void 0 ? void 0 : options.disabledModes) === null || _a === void 0 ? void 0 : _a.length) + || !options.disabledModes.includes(x)) { + modes.push(x); + } + }); + if (!modes.length) { + throw new Error("All viewer modes are disabled"); + } + this.enabledModes = modes; + } + addOnModeChangeStarted(action) { + this._onModeChangeStarted.add(action); + } + removeOnModeChangeStarted(action) { + this._onModeChangeStarted.delete(action); + } +} + +var __awaiter$4 = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class PdfLoaderService { + get pageCount() { + var _a; + return ((_a = this._pdfDocument) === null || _a === void 0 ? void 0 : _a.numPages) || 0; + } + get docLoaded() { + return !!this._pdfDocument; + } + get docService() { + return this._docService; + } + get docProxy() { + return this._pdfDocument; + } + get fileName() { + return this._fileName; + } + constructor(eventService) { + if (!eventService) { + throw new Error("Event controller is not defined"); + } + this._eventService = eventService; + } + destroy() { + var _a, _b; + (_a = this._pdfLoadingTask) === null || _a === void 0 ? void 0 : _a.destroy(); + if (this._pdfDocument) { + this._pdfDocument.cleanup(); + this._pdfDocument.destroy(); + } + (_b = this._docService) === null || _b === void 0 ? void 0 : _b.destroy(); + } + openPdfAsync(src, fileName, userName, getPasswordAsync, onProgress) { + var _a; + return __awaiter$4(this, void 0, void 0, function* () { + yield this.closePdfAsync(); + let data; + let doc; + try { + data = yield DomUtils.loadFileDataAsync(src); + } + catch (e) { + throw new Error(`Cannot load file data: ${e.message}`); + } + const docService = yield DocumentService.createNewAsync(this._eventService, data, userName); + let password; + while (true) { + const authenticated = docService.tryAuthenticate(password); + if (!authenticated) { + password = yield getPasswordAsync(); + if (password === null) { + throw new Error("File loading cancelled: authentication aborted"); + } + continue; + } + break; + } + try { + if (this._pdfLoadingTask) { + yield this.closePdfAsync(); + return this.openPdfAsync(data, userName, fileName, getPasswordAsync, onProgress); + } + const dataWithoutAnnotations = yield docService.getDataWithoutSupportedAnnotationsAsync(); + this._pdfLoadingTask = pdfExports.getDocument({ + data: dataWithoutAnnotations, + password, + }); + if (onProgress) { + this._pdfLoadingTask.onProgress = onProgress; + } + doc = yield this._pdfLoadingTask.promise; + this._pdfLoadingTask = null; + } + catch (e) { + throw new Error(`Cannot open PDF: ${e.message}`); + } + this._pdfDocument = doc; + const pageMap = new Map(); + for (let i = 0; i < doc.numPages; i++) { + const pageProxy = yield ((_a = this._pdfDocument) === null || _a === void 0 ? void 0 : _a.getPage(i + 1)); + pageMap.set(i, pageProxy); + } + this._pdfPageProxies = pageMap; + this._docService = docService; + this._fileName = fileName; + }); + } + closePdfAsync() { + var _a, _b; + return __awaiter$4(this, void 0, void 0, function* () { + if (this._pdfLoadingTask) { + if (!this._pdfLoadingTask.destroyed) { + yield this._pdfLoadingTask.destroy(); + } + this._pdfLoadingTask = null; + } + this._pdfPageProxies = null; + (_a = this._pdfDocument) === null || _a === void 0 ? void 0 : _a.destroy(); + this._pdfDocument = null; + (_b = this._docService) === null || _b === void 0 ? void 0 : _b.destroy(); + this._docService = null; + this._fileName = null; + }); + } + getPage(pageIndex) { + var _a; + if (!((_a = this._pdfPageProxies) === null || _a === void 0 ? void 0 : _a.size)) { + return null; + } + return this._pdfPageProxies.get(pageIndex); + } +} + +var __awaiter$3 = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class ComparisonService { + constructor() { } + destroy() { } + getComparisonResult() { + return this._comparisonResult; + } + getComparisonResultForPage(pageIndex) { + const comparisonResult = this.getComparisonResult(); + return comparisonResult === null || comparisonResult === void 0 ? void 0 : comparisonResult.get(pageIndex); + } + clearComparisonResult() { + return this._comparisonResult = null; + } + compareAsync(subjectDocProxy, agentDocProxy, offsets) { + return __awaiter$3(this, void 0, void 0, function* () { + const result = new Map(); + if (!subjectDocProxy || !agentDocProxy) { + return result; + } + const subjectPagesCount = subjectDocProxy.numPages; + const agentPagesCount = agentDocProxy.numPages; + for (let i = 0; i < subjectPagesCount; i++) { + const subjectPage = yield subjectDocProxy.getPage(i + 1); + const agentPage = i < agentPagesCount + ? yield agentDocProxy.getPage(i + 1) + : null; + const pageComparisonResult = yield this.comparePagesAsync(subjectPage, agentPage, offsets === null || offsets === void 0 ? void 0 : offsets.get(i)); + result.set(i, pageComparisonResult); + } + this._comparisonResult = result; + return this._comparisonResult; + }); + } + comparePagesAsync(subjectPageProxy, agentPageProxy, offset) { + return __awaiter$3(this, void 0, void 0, function* () { + const subjectImageData = yield this.renderPageAsync(subjectPageProxy); + const agentImageData = yield this.renderPageAsync(agentPageProxy); + const pageComparisonResult = yield this.compareImageDataAsync(subjectImageData, agentImageData, { offset }); + return pageComparisonResult; + }); + } + renderPageAsync(pageProxy) { + return __awaiter$3(this, void 0, void 0, function* () { + if (!pageProxy) { + return null; + } + const viewport = pageProxy.getViewport({ scale: 1, rotation: 0 }); + const { width, height } = viewport; + const canvas = document.createElement("canvas"); + canvas.width = width; + canvas.height = height; + const canvasCtx = canvas.getContext("2d"); + const params = { + canvasContext: canvasCtx, + viewport: viewport, + enableWebGL: true, + }; + const renderTask = pageProxy.render(params); + yield renderTask.promise; + const imageData = canvasCtx.getImageData(0, 0, width, height); + return imageData; + }); + } + compareImageDataAsync(subjectImageData, agentImageData, options) { + var _a; + return __awaiter$3(this, void 0, void 0, function* () { + const threshold = (_a = options === null || options === void 0 ? void 0 : options.threshold) !== null && _a !== void 0 ? _a : 5; + const offset = (options === null || options === void 0 ? void 0 : options.offset) || [0, 0]; + if (!subjectImageData) { + return { + areas: [], + offset: [0, 0], + }; + } + if (!agentImageData) { + return { + areas: [[0, 0, subjectImageData.width, subjectImageData.height]], + offset: [0, 0], + }; + } + const aabbs = []; + const sw = subjectImageData.width; + const sh = subjectImageData.height; + const aw = agentImageData.width; + const ah = agentImageData.height; + const sBytes = subjectImageData.data; + const aBytes = agentImageData.data; + let si; + let ai; + let ax; + let ay; + for (let sx = 0; sx < sw; sx++) { + for (let sy = 0; sy < sh; sy++) { + ax = sx + offset[0]; + ay = sy + offset[1]; + if (ax < 0 || ay < 0 + || ax >= aw || ay >= ah) { + continue; + } + si = (sw * sy + sx) * 4; + ai = (aw * ay + ax) * 4; + if (sBytes[si] !== aBytes[ai] + || sBytes[si + 1] !== aBytes[ai + 1] + || sBytes[si + 2] !== aBytes[ai + 2] + || sBytes[si + 3] !== aBytes[ai + 3]) { + this.addPixelToAabbs(aabbs, sx, sy, threshold, sw, sh); + } + } + } + const mergedAabbs = this.mergeIntersectingAabbs(aabbs); + return { + areas: mergedAabbs, + offset, + }; + }); + } + addPixelToAabbs(aabbs, x, y, threshold, pageWidth, pageHeight) { + let merged; + const cxmin = Math.max(x - threshold, 0); + const cymin = Math.max(y - threshold, 0); + const cxmax = Math.min(x + threshold, pageWidth); + const cymax = Math.min(y + threshold, pageHeight); + for (let j = 0; j < aabbs.length; j++) { + const [mxmin, mymin, mxmax, mymax] = aabbs[j]; + if (Math.max(cxmin, mxmin) < Math.min(cxmax, mxmax) + && Math.max(cymin, mymin) < Math.min(cymax, mymax)) { + aabbs[j] = [Math.min(cxmin, mxmin), Math.min(cymin, mymin), + Math.max(cxmax, mxmax), Math.max(cymax, mymax)]; + merged = true; + break; + } + } + if (!merged) { + aabbs.push([cxmin, cymin, cxmax, cymax]); + } + } + compareImageDataDbscanAsync(subjectImageData, agentImageData, threshold = 10) { + return __awaiter$3(this, void 0, void 0, function* () { + if (!subjectImageData) { + return []; + } + if (!agentImageData) { + return [[0, 0, subjectImageData.width, subjectImageData.height]]; + } + const changedPixels = this.getChangedPixels(subjectImageData, agentImageData); + if (changedPixels.length > this._maxChangedPixels) { + return [[0, 0, subjectImageData.width, subjectImageData.height]]; + } + const clusters = yield DBSCAN.runAsync(changedPixels, threshold, 1); + const aabbs = this.convertClustersToAabbs(clusters); + const mergedAabbs = this.mergeIntersectingAabbs(aabbs); + return mergedAabbs; + }); + } + getChangedPixels(subjectImageData, agentImageData) { + const sw = subjectImageData.width; + const sh = subjectImageData.height; + const aw = agentImageData.width; + const ah = agentImageData.height; + const sBytes = subjectImageData.data; + const aBytes = agentImageData.data; + const changedPixels = []; + let si; + let ai; + for (let x = 0; x < sw; x++) { + for (let y = 0; y < sh; y++) { + if (x >= aw || y >= ah) { + changedPixels.push(new u(x, y)); + continue; + } + si = (sw * y + x) * 4; + ai = (aw * y + x) * 4; + if (sBytes[si] !== aBytes[ai] + || sBytes[si + 1] !== aBytes[ai + 1] + || sBytes[si + 2] !== aBytes[ai + 2] + || sBytes[si + 3] !== aBytes[ai + 3]) { + changedPixels.push(new u(x, y)); + } + } + } + return changedPixels; + } + convertClustersToAabbs(clusters) { + const aabbs = []; + for (const cluster of clusters) { + if (!(cluster === null || cluster === void 0 ? void 0 : cluster.length)) { + continue; + } + let aabb; + for (const vec of cluster) { + if (!aabb) { + aabb = [vec.x, vec.y, vec.x, vec.y]; + continue; + } + if (vec.x < aabb[0]) { + aabb[0] = vec.x; + } + else if (vec.x > aabb[2]) { + aabb[2] = vec.x; + } + if (vec.y < aabb[1]) { + aabb[1] = vec.y; + } + else if (vec.y > aabb[3]) { + aabb[3] = vec.y; + } + } + aabbs.push(aabb); + } + return aabbs; + } + mergeIntersectingAabbs(aabbs) { + const mergedAabbs = []; + for (const [cxmin, cymin, cxmax, cymax] of aabbs) { + let merged; + for (let j = 0; j < mergedAabbs.length; j++) { + const [mxmin, mymin, mxmax, mymax] = mergedAabbs[j]; + if (Math.max(cxmin, mxmin) < Math.min(cxmax, mxmax) + && Math.max(cymin, mymin) < Math.min(cymax, mymax)) { + mergedAabbs[j] = [Math.min(cxmin, mxmin), Math.min(cymin, mymin), + Math.max(cxmax, mxmax), Math.max(cymax, mymax)]; + merged = true; + break; + } + } + if (!merged) { + mergedAabbs.push([cxmin, cymin, cxmax, cymax]); + } + } + return mergedAabbs; + } +} +class DBSCAN { + constructor(points, distance, minPoints) { + this._clusters = []; + this._noise = []; + this._points = points !== null && points !== void 0 ? points : []; + this._distance = Math.max(distance, 0) || 1; + this._minPoints = Math.max(minPoints, 1); + this._visited = new Array(points.length); + this._assigned = new Array(points.length); + } + static runAsync(points, epsilon, minPoints) { + return __awaiter$3(this, void 0, void 0, function* () { + const dbScan = new DBSCAN(points, epsilon !== null && epsilon !== void 0 ? epsilon : 1, minPoints !== null && minPoints !== void 0 ? minPoints : 1); + return dbScan.runClustering(); + }); + } + runClustering() { + if (!this._points.length) { + return []; + } + for (let pointId = 0; pointId < this._points.length; pointId++) { + if (!this._visited[pointId]) { + this._visited[pointId] = true; + const neighbours = this.getPointNeighbourIds(pointId); + if (neighbours.length < this._minPoints) { + this._noise.push(pointId); + } + else { + const clusterId = this._clusters.length; + this._clusters.push([]); + this.addPointToCluster(pointId, clusterId); + this.expandCluster(clusterId, neighbours); + } + } + } + return this._clusters; + } + ; + expandCluster(clusterId, neighbours) { + for (let i = 0; i < neighbours.length; i++) { + const neighbourPoint = neighbours[i]; + if (!this._visited[neighbourPoint]) { + this._visited[neighbourPoint] = true; + const newNeighbours = this.getPointNeighbourIds(neighbourPoint); + if (newNeighbours.length >= this._minPoints) { + neighbours.push(...newNeighbours); + } + } + if (!this._assigned[neighbourPoint]) { + this.addPointToCluster(neighbourPoint, clusterId); + } + } + } + ; + addPointToCluster(pointId, clusterId) { + this._clusters[clusterId].push(this._points[pointId]); + this._assigned[pointId] = true; + } + ; + getPointNeighbourIds(pointId) { + const neighbours = []; + for (let i = 0; i < this._points.length; i++) { + const dist = u.getDistance(this._points[pointId], this._points[i]); + if (dist < this._distance) { + neighbours.push(i); + } + } + return neighbours; + } + ; +} + +var __awaiter$2 = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +const docChangeEvent = "tspdf-docchangeevent"; +class DocChangeEvent extends CustomEvent { + constructor(detail) { + super(docChangeEvent, { detail }); + } +} +class DocManagerService { + get comparisonService() { + return this._comparisonService; + } + get docService() { + return this._docLoaders.main.docService; + } + get pageCount() { + return this._docLoaders.main.pageCount; + } + get docLoaded() { + return this._docLoaders.main.docLoaded; + } + get fileName() { + return this._docLoaders.main.fileName; + } + constructor(mainEventService) { + this._dummyDiv = document.createElement("div"); + if (!mainEventService) { + throw new Error("Main event service is not defined"); + } + this._eventService = mainEventService; + this._docLoaders = { + main: new PdfLoaderService(mainEventService), + compared: new PdfLoaderService(new EventService(this._dummyDiv)), + }; + this._comparisonService = new ComparisonService(); + } + destroy() { + this._comparisonService.destroy(); + Object.keys(this._docLoaders).forEach(key => { + this._docLoaders[key].destroy(); + }); + } + openPdfAsync(type, src, fileName, userName, getPasswordAsync, onProgress) { + return __awaiter$2(this, void 0, void 0, function* () { + yield this._docLoaders[type].openPdfAsync(src, fileName, userName, getPasswordAsync, onProgress); + if (type === "main") { + yield this.closePdfAsync("compared"); + this._eventService.dispatchEvent(new DocChangeEvent({ action: "open", type: "main" })); + } + else if (type === "compared") { + yield this.runComparisonAsync(); + this._eventService.dispatchEvent(new DocChangeEvent({ action: "open", type: "compared" })); + } + }); + } + closePdfAsync(type) { + return __awaiter$2(this, void 0, void 0, function* () { + yield this._docLoaders[type].closePdfAsync(); + if (type === "main") { + yield this.closePdfAsync("compared"); + this._eventService.dispatchEvent(new DocChangeEvent({ action: "close", type: "main" })); + } + else if (type === "compared") { + yield this._comparisonService.clearComparisonResult(); + this._eventService.dispatchEvent(new DocChangeEvent({ action: "close", type: "compared" })); + } + }); + } + runComparisonAsync() { + return __awaiter$2(this, void 0, void 0, function* () { + yield this._comparisonService.compareAsync(this._docLoaders.main.docProxy, this._docLoaders.compared.docProxy); + }); + } + getPageProxy(type, pageIndex) { + return this._docLoaders[type].getPage(pageIndex); + } + getComparisonResultForPage(pageIndex) { + return this._comparisonService.getComparisonResultForPage(pageIndex); + } +} + +var __awaiter$1 = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class Viewer { + get container() { + return this._container; + } + get scale() { + return this._scale; + } + constructor(modeService, pageService, container, options) { + this._scale = 1; + this._pointerInfo = { + lastPos: null, + downPos: null, + downScroll: null, + }; + this._pinchInfo = { + active: false, + lastDist: 0, + minDist: 10, + sensitivity: 0.025, + target: null, + }; + this.onPagesLoaded = (event) => { + var _a; + (_a = event.detail.pages) === null || _a === void 0 ? void 0 : _a.forEach(x => { + x.scale = this._scale; + this._container.append(x.viewContainer); + }); + this.renderVisible(); + }; + this.onScrollRequest = (event) => { + this.scrollToPage(event.detail.pageIndex); + }; + this.onPointerMove = (event) => { + const { clientX, clientY } = event; + this._pointerInfo.lastPos = new u(clientX, clientY); + }; + this.onScroll = (e) => { + this.renderVisible(); + }; + this.onPointerDownScroll = (e) => { + if (this._modeService.mode !== "hand") { + return; + } + const { clientX, clientY } = e; + this._pointerInfo.downPos = new u(clientX, clientY); + this._pointerInfo.downScroll = new u(this._container.scrollLeft, this._container.scrollTop); + const onPointerMove = (moveEvent) => { + const { x, y } = this._pointerInfo.downPos; + const { x: left, y: top } = this._pointerInfo.downScroll; + const dX = moveEvent.clientX - x; + const dY = moveEvent.clientY - y; + this._container.scrollTo(left - dX, top - dY); + }; + const onPointerUp = (upEvent) => { + this._pointerInfo.downPos = null; + this._pointerInfo.downScroll = null; + const upTarget = upEvent.target; + upTarget.removeEventListener("pointermove", onPointerMove); + upTarget.removeEventListener("pointerup", onPointerUp); + upTarget.removeEventListener("pointerout", onPointerUp); + upTarget.releasePointerCapture(upEvent.pointerId); + }; + const target = e.target; + target.setPointerCapture(e.pointerId); + target.addEventListener("pointermove", onPointerMove); + target.addEventListener("pointerup", onPointerUp); + target.addEventListener("pointerout", onPointerUp); + }; + this.onWheelZoom = (event) => { + if (!event.ctrlKey) { + return; + } + event.preventDefault(); + if (event.deltaY > 0) { + this.zoomOutCentered(this._pointerInfo.lastPos); + } + else { + this.zoomInCentered(this._pointerInfo.lastPos); + } + }; + this.onTouchZoom = (event) => { + if (event.touches.length !== 2) { + return; + } + const a = event.touches[0]; + const b = event.touches[1]; + this._pinchInfo.active = true; + this._pinchInfo.lastDist = h(a.clientX, a.clientY, b.clientX, b.clientY); + const onTouchMove = (moveEvent) => { + if (moveEvent.touches.length !== 2) { + return; + } + const mA = moveEvent.touches[0]; + const mB = moveEvent.touches[1]; + const dist = h(mA.clientX, mA.clientY, mB.clientX, mB.clientY); + const delta = dist - this._pinchInfo.lastDist; + const factor = Math.floor(delta / this._pinchInfo.minDist); + if (factor) { + const center = new u((mB.clientX + mA.clientX) / 2, (mB.clientY + mA.clientY) / 2); + this._pinchInfo.lastDist = dist; + this.zoom(factor * this._pinchInfo.sensitivity, center); + } + }; + const onTouchEnd = (endEvent) => { + this._pinchInfo.active = false; + this._pinchInfo.lastDist = 0; + event.target.removeEventListener("touchmove", onTouchMove); + event.target.removeEventListener("touchend", onTouchEnd); + event.target.removeEventListener("touchcancel", onTouchEnd); + }; + event.target.addEventListener("touchmove", onTouchMove); + event.target.addEventListener("touchend", onTouchEnd); + event.target.addEventListener("touchcancel", onTouchEnd); + }; + if (!modeService) { + throw new Error("Mode service is not defined"); + } + if (!pageService) { + throw new Error("Page service is not defined"); + } + if (!container) { + throw new Error("Container is not defined"); + } + this._modeService = modeService; + this._pageService = pageService; + this._container = container; + this._minScale = (options === null || options === void 0 ? void 0 : options.minScale) || 0.25; + this._maxScale = (options === null || options === void 0 ? void 0 : options.maxScale) || 4; + this._modeService.addOnModeChangeStarted(() => { + if (this === null || this === void 0 ? void 0 : this._dialogClose) { + this._dialogClose(); + } + }); + this.init(); + } + destroy() { + this._pageService.eventService.removeListener(pagesLoadedEvent, this.onPagesLoaded); + this._pageService.eventService.removeListener(currentPageChangeRequestEvent, this.onScrollRequest); + this._container.removeEventListener("scroll", this.onScroll); + this._container.removeEventListener("wheel", this.onWheelZoom); + this._container.removeEventListener("pointermove", this.onPointerMove); + this._container.removeEventListener("pointerdown", this.onPointerDownScroll); + this._container.removeEventListener("touchstart", this.onTouchZoom); + } + zoomOut() { + this.zoomOutCentered(); + } + zoomIn() { + this.zoomInCentered(); + } + zoomFitViewer() { + const cWidth = this._container.getBoundingClientRect().width; + const pWidth = this._pageService.getCurrentPage().viewContainer.getBoundingClientRect().width; + const scale = n$1((cWidth - 20) / pWidth * this._scale, this._minScale, this._maxScale); + this.setScale(scale); + this.scrollToPage(this._pageService.currentPageIndex); + } + zoomFitPage() { + const { width: cWidth, height: cHeight } = this._container.getBoundingClientRect(); + const { width: pWidth, height: pHeight } = this._pageService.getCurrentPage().viewContainer.getBoundingClientRect(); + const hScale = n$1((cWidth - 20) / pWidth * this._scale, this._minScale, this._maxScale); + const vScale = n$1((cHeight - 20) / pHeight * this._scale, this._minScale, this._maxScale); + this.setScale(Math.min(hScale, vScale)); + this.scrollToPage(this._pageService.currentPageIndex); + } + renderVisible(force) { + this._pageService.renderVisiblePages(this._container, force); + } + showTextDialogAsync(initialText) { + return __awaiter$1(this, void 0, void 0, function* () { + if (this._dialogClose) { + return; + } + const dialog = DomUtils.htmlToElements(HtmlTemplates.textDialogHtml)[0]; + dialog.style.top = this._container.scrollTop + "px"; + dialog.style.left = this._container.scrollLeft + "px"; + this._container.append(dialog); + this._container.classList.add("dialog-shown"); + let value = initialText || ""; + const input = dialog.querySelector(".text-input"); + input.placeholder = "Enter text..."; + input.value = value; + input.addEventListener("change", () => value = input.value); + const textPromise = new Promise((resolve, reject) => { + const ok = () => { + resolve(value || ""); + }; + const cancel = () => { + resolve(null); + }; + dialog.addEventListener("click", (e) => { + if (e.target === dialog) { + cancel(); + } + }); + dialog.querySelector(".text-ok").addEventListener("click", ok); + dialog.querySelector(".text-cancel").addEventListener("click", cancel); + this._dialogClose = () => resolve(null); + }); + const result = yield textPromise; + this._dialogClose = null; + dialog.remove(); + this._container.classList.remove("dialog-shown"); + return result; + }); + } + scrollToPage(pageNumber) { + if (!this._pageService.pages.length) { + return; + } + const { top: cTop } = this._container.getBoundingClientRect(); + const { top: pTop } = this._pageService.getPage(pageNumber).viewContainer.getBoundingClientRect(); + const scroll = pTop - (cTop - this._container.scrollTop) - 20; + this._container.scrollTo(this._container.scrollLeft, scroll); + } + init() { + this._container.addEventListener("scroll", this.onScroll); + this._container.addEventListener("wheel", this.onWheelZoom, { passive: false }); + this._container.addEventListener("pointermove", this.onPointerMove); + this._container.addEventListener("pointerdown", this.onPointerDownScroll); + this._container.addEventListener("touchstart", this.onTouchZoom); + this._pageService.eventService.addListener(pagesLoadedEvent, this.onPagesLoaded); + this._pageService.eventService.addListener(currentPageChangeRequestEvent, this.onScrollRequest); + } + setScale(scale, cursorPosition = null) { + if (!scale || scale === this._scale) { + return; + } + let pageContainerUnderPivot; + let xPageRatio; + let yPageRatio; + if (cursorPosition) { + for (const page of this._pageService.pages) { + const { x: x, y: y } = cursorPosition; + const { x: pX, y: pY, width: pWidth, height: pHeight } = page.viewContainer.getBoundingClientRect(); + if (pX <= x + && pX + pWidth >= x + && pY <= y + && pY + pHeight >= y) { + pageContainerUnderPivot = page.viewContainer; + xPageRatio = (x - pX) / pWidth; + yPageRatio = (y - pY) / pHeight; + break; + } + } + } + this._scale = scale; + this._pageService.scale = scale; + if (pageContainerUnderPivot + && + (this._container.scrollHeight > this._container.clientHeight + || this._container.scrollWidth > this._container.clientWidth)) { + const { x: initialX, y: initialY } = cursorPosition; + const { x: pX, y: pY, width: pWidth, height: pHeight } = pageContainerUnderPivot.getBoundingClientRect(); + const resultX = pX + (pWidth * xPageRatio); + const resultY = pY + (pHeight * yPageRatio); + let scrollLeft = this._container.scrollLeft + (resultX - initialX); + let scrollTop = this._container.scrollTop + (resultY - initialY); + scrollLeft = scrollLeft < 0 + ? 0 + : scrollLeft; + scrollTop = scrollTop < 0 + ? 0 + : scrollTop; + if (scrollTop !== this._container.scrollTop + || scrollLeft !== this._container.scrollLeft) { + this._container.scrollTo(scrollLeft, scrollTop); + return; + } + } + setTimeout(() => this.renderVisible(), 0); + } + zoom(diff, cursorPosition = null) { + const scale = n$1(this._scale + diff, this._minScale, this._maxScale); + this.setScale(scale, cursorPosition || this.getCenterPosition()); + } + zoomOutCentered(center = null) { + this.zoom(-0.25, center); + } + zoomInCentered(center = null) { + this.zoom(0.25, center); + } + getCenterPosition() { + const { x, y, width, height } = this._container.getBoundingClientRect(); + return new u(x + width / 2, y + height / 2); + } +} + +class Previewer { + get hidden() { + return this._hidden; + } + constructor(pageService, container) { + this._hidden = true; + this.onPagesLoaded = (event) => { + var _a; + (_a = event.detail.pages) === null || _a === void 0 ? void 0 : _a.forEach(x => { + x.previewContainer.addEventListener("click", this.onPreviewerPageClick); + this._container.append(x.previewContainer); + }); + this.renderVisible(); + }; + this.onCurrentPageChanged = (event) => { + this.scrollToPreview(event.detail.newIndex); + }; + this.onPreviewerPageClick = (e) => { + let target = e.target; + let pageNumber; + while (target && !pageNumber) { + const data = target.dataset["pageNumber"]; + if (data) { + pageNumber = +data; + } + else { + target = target.parentElement; + } + } + if (pageNumber) { + this._pageService.requestSetCurrentPageIndex(pageNumber - 1); + } + }; + this.onPreviewerScroll = (e) => { + this.renderVisible(); + }; + if (!pageService) { + throw new Error("Page service is not defined"); + } + if (!container) { + throw new Error("Container is not defined"); + } + this._pageService = pageService; + this._container = container; + this.init(); + } + destroy() { + this._pageService.eventService.removeListener(pagesLoadedEvent, this.onPagesLoaded); + this._pageService.eventService.removeListener(currentPageChangeEvent, this.onCurrentPageChanged); + } + show() { + this._hidden = false; + setTimeout(() => this.renderVisible(), 1000); + } + hide() { + this._hidden = true; + } + renderVisible() { + if (this._hidden) { + return; + } + this._pageService.renderVisiblePreviews(this._container); + } + init() { + this._container.addEventListener("scroll", this.onPreviewerScroll); + this._pageService.eventService.addListener(pagesLoadedEvent, this.onPagesLoaded); + this._pageService.eventService.addListener(currentPageChangeEvent, this.onCurrentPageChanged); + } + scrollToPreview(pageIndex) { + if (!this._pageService.pages.length) { + return; + } + const { top: cTop, height: cHeight } = this._container.getBoundingClientRect(); + const { top: pTop, height: pHeight } = this._pageService.getPage(pageIndex).previewContainer.getBoundingClientRect(); + const cCenter = cTop + cHeight / 2; + const pCenter = pTop + pHeight / 2; + const scroll = pCenter - cCenter + this._container.scrollTop; + this._container.scrollTo(0, scroll); + } +} + +var __awaiter = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class TsPdfViewer { + get _docService() { + var _a; + return (_a = this._docManagerService) === null || _a === void 0 ? void 0 : _a.docService; + } + constructor(options) { + this._timers = { + hidePanels: 0, + }; + this.onTextSelectionChange = () => { + const selection = this._shadowRoot.getSelection + ? this._shadowRoot.getSelection() + : document.getSelection(); + if (!selection.rangeCount) { + return; + } + if (this._eventService.hasListenersForKey(textSelectionChangeEvent)) { + const selectionInfos = getSelectionInfosFromSelection(selection); + this._eventService.dispatchEvent(new TextSelectionChangeEvent({ selectionInfos })); + } + }; + this.onFileInput = () => { + const files = this._fileInput.files; + if (files.length === 0) { + return; + } + this.openDocAsync("main", files[0], files[0].name); + this._fileInput.value = null; + }; + this.onOpenFileButtonClick = () => { + this._fileInput.click(); + }; + this.onSaveFileButtonClickAsync = () => __awaiter(this, void 0, void 0, function* () { + var _a; + const blob = yield this.getCurrentPdfAsync(); + if (!blob) { + return; + } + DomUtils.downloadFile(blob, ((_a = this._docManagerService) === null || _a === void 0 ? void 0 : _a.fileName) + || `file_${new Date().toISOString()}.pdf`); + }); + this.onCloseFileButtonClick = () => { + this.closeDocAsync("main"); + }; + this.onComparableFileInput = () => { + const files = this._comparableFileInput.files; + if (files.length === 0) { + return; + } + this.openDocAsync("compared", files[0], files[0].name); + this._comparableFileInput.value = null; + }; + this.onComparableOpenFileButtonClick = () => { + this._comparableFileInput.click(); + }; + this.onComparableCloseFileButtonClick = () => { + this.closeDocAsync("compared"); + }; + this.onViewerModeButtonClick = (e) => { + const parentButton = e.target.closest("*[id^=\"button-mode-\"]"); + if (!parentButton) { + return; + } + const mode = /button-mode-(.+)/.exec(parentButton.id)[1]; + this.setMode(mode); + }; + this.onZoomOutClick = () => { + this._viewer.zoomOut(); + }; + this.onZoomInClick = () => { + this._viewer.zoomIn(); + }; + this.onZoomFitViewerClick = () => { + this._viewer.zoomFitViewer(); + }; + this.onZoomFitPageClick = () => { + this._viewer.zoomFitPage(); + }; + this.onRotateCounterClockwiseClick = () => { + this.rotateCounterClockwise(); + }; + this.onRotateClockwiseClick = () => { + this.rotateClockwise(); + }; + this.onPaginatorInput = (event) => { + if (event.target instanceof HTMLInputElement) { + event.target.value = event.target.value.replace(/[^\d]+/g, ""); + } + }; + this.onPaginatorChange = (event) => { + if (event.target instanceof HTMLInputElement) { + const pageNumber = Math.max(Math.min(+event.target.value, this._docManagerService.pageCount), 1); + if (pageNumber + "" !== event.target.value) { + event.target.value = pageNumber + ""; + } + this._pageService.requestSetCurrentPageIndex(pageNumber - 1); + } + }; + this.onPaginatorPrevClick = () => { + this.moveToPrevPage(); + }; + this.onPaginatorNextClick = () => { + this.moveToNextPage(); + }; + this.onCurrentPagesChanged = (event) => { + const { newIndex } = event.detail; + this._shadowRoot.getElementById("paginator-input").value = newIndex + 1 + ""; + }; + this.annotatorUndo = () => { + var _a; + (_a = this._annotatorService.annotator) === null || _a === void 0 ? void 0 : _a.undo(); + }; + this.annotatorClear = () => { + var _a; + (_a = this._annotatorService.annotator) === null || _a === void 0 ? void 0 : _a.clear(); + }; + this.annotatorSave = () => { + var _a; + (_a = this._annotatorService.annotator) === null || _a === void 0 ? void 0 : _a.saveAnnotationAsync(); + }; + this.onCustomStampChanged = (e) => { + this.setAnnotationMode("stamp"); + if (this._customStampChangeCallback) { + this._customStampChangeCallback(e.detail); + } + }; + this.onAnnotationChange = (e) => { + if (!e.detail) { + return; + } + const annotations = e.detail.annotations; + switch (e.detail.type) { + case "focus": + if (annotations === null || annotations === void 0 ? void 0 : annotations.length) { + this._mainContainer.classList.add("annotation-focused"); + } + else { + this._mainContainer.classList.remove("annotation-focused"); + } + const annotation = annotations[0]; + if (annotation) { + this._shadowRoot.querySelector("#focused-annotation-author") + .textContent = annotation.author || ""; + this._shadowRoot.querySelector("#focused-annotation-date") + .textContent = new Date(annotation.dateModified || annotation.dateCreated).toDateString(); + this._shadowRoot.querySelector("#focused-annotation-text") + .textContent = annotation.textContent || ""; + } + else { + this._shadowRoot.querySelector("#focused-annotation-author") + .textContent = ""; + this._shadowRoot.querySelector("#focused-annotation-date") + .textContent = ""; + this._shadowRoot.querySelector("#focused-annotation-text") + .textContent = ""; + } + break; + case "select": + if (annotations === null || annotations === void 0 ? void 0 : annotations.length) { + this._mainContainer.classList.add("annotation-selected"); + this._mainContainer.classList.add("annotation-focused"); + } + else { + this._mainContainer.classList.remove("annotation-selected"); + this._mainContainer.classList.remove("annotation-focused"); + } + break; + case "add": + case "delete": + case "render": + case "import": + if (annotations === null || annotations === void 0 ? void 0 : annotations.length) { + const pageIdSet = new Set(annotations.map(x => x.pageId)); + this._pageService.renderSpecifiedPages(pageIdSet); + } + break; + } + if (this._annotChangeCallback) { + this._annotChangeCallback(e.detail); + } + }; + this.onAnnotatorDataChanged = (event) => { + annotatorTypes.forEach(x => { + this._mainContainer.classList.remove(x + "-annotator-data-saveable"); + this._mainContainer.classList.remove(x + "-annotator-data-undoable"); + this._mainContainer.classList.remove(x + "-annotator-data-clearable"); + }); + if (event.detail.saveable) { + this._mainContainer.classList.add(event.detail.annotatorType + "-annotator-data-saveable"); + } + if (event.detail.undoable) { + this._mainContainer.classList.add(event.detail.annotatorType + "-annotator-data-undoable"); + } + if (event.detail.clearable) { + this._mainContainer.classList.add(event.detail.annotatorType + "-annotator-data-clearable"); + } + }; + this.onAnnotationEditTextButtonClick = () => __awaiter(this, void 0, void 0, function* () { + var _b, _c; + const initialText = (_b = this._docService) === null || _b === void 0 ? void 0 : _b.getSelectedAnnotationTextContent(); + const text = yield this._viewer.showTextDialogAsync(initialText); + if (text === null) { + return; + } + yield ((_c = this._docService) === null || _c === void 0 ? void 0 : _c.setSelectedAnnotationTextContentAsync(text)); + }); + this.onAnnotationDeleteButtonClick = () => { + var _a; + (_a = this._docService) === null || _a === void 0 ? void 0 : _a.removeSelectedAnnotation(); + }; + this.onAnnotationModeButtonClick = (e) => { + const parentButton = e.target.closest("*[id^=\"button-annotation-mode-\"]"); + if (!parentButton) { + return; + } + const mode = /button-annotation-mode-(.+)/.exec(parentButton.id)[1]; + this.setAnnotationMode(mode); + }; + this.onMainContainerPointerMove = (event) => { + const { clientX, clientY } = event; + const { x: rectX, y: rectY, width, height } = this._mainContainer.getBoundingClientRect(); + const l = clientX - rectX; + const t = clientY - rectY; + const r = width - l; + const b = height - t; + if (Math.min(l, r, t, b) > 150) { + this.hidePanels(); + } + else { + this.showPanels(); + } + }; + this.onPdfLoadingProgress = (progressData) => { + }; + this.docServiceUndo = () => { + var _a; + (_a = this._docService) === null || _a === void 0 ? void 0 : _a.undoAsync(); + }; + this.onDocChangeAsync = (e) => __awaiter(this, void 0, void 0, function* () { + var _d; + if (e.detail.type === "main") { + if (e.detail.action === "open") { + this.setMode(); + yield this.refreshPagesAsync(); + this._annotatorService = new AnnotatorService(this._docService, this._pageService, this._customStampsService, this._viewer); + this.setAnnotationMode("select"); + this._mainContainer.classList.remove("disabled"); + } + else if (e.detail.action === "close") { + this._mainContainer.classList.add("disabled"); + this._mainContainer.classList.remove("annotation-focused"); + this._mainContainer.classList.remove("annotation-selected"); + this.setMode(); + (_d = this._annotatorService) === null || _d === void 0 ? void 0 : _d.destroy(); + yield this.refreshPagesAsync(); + this.showPanels(); + } + } + if (e.detail.type === "compared") { + if (e.detail.action === "open") { + this._mainContainer.classList.add("comparison-loaded"); + } + else if (e.detail.action === "close") { + this._mainContainer.classList.remove("comparison-loaded"); + } + if (this._modeService.mode === "comparison") { + this._viewer.renderVisible(true); + } + } + }); + this.onDocServiceStateChange = (e) => { + if (e.detail.undoableCount) { + this._mainContainer.classList.add("undoable-commands"); + } + else { + this._mainContainer.classList.remove("undoable-commands"); + } + }; + this.onPreviewerToggleClick = () => { + this.togglePreviewer(); + }; + this.showPasswordDialogAsync = () => __awaiter(this, void 0, void 0, function* () { + const passwordPromise = new Promise((resolve, reject) => { + const dialog = DomUtils.htmlToElements(passwordDialogHtml)[0]; + this._mainContainer.append(dialog); + let value = ""; + const input = dialog.querySelector(".password-input"); + input.placeholder = "Enter password..."; + input.addEventListener("change", () => value = input.value); + const ok = () => { + dialog.remove(); + resolve(value); + }; + const cancel = () => { + dialog.remove(); + resolve(null); + }; + dialog.addEventListener("click", (e) => { + if (e.target === dialog) { + cancel(); + } + }); + dialog.querySelector(".password-ok").addEventListener("click", ok); + dialog.querySelector(".password-cancel").addEventListener("click", cancel); + }); + return passwordPromise; + }); + this.onViewerKeyDown = (event) => { + var _a, _b, _c, _d; + switch (event.code) { + case "KeyO": + if (event.ctrlKey && event.altKey) { + event.preventDefault(); + if (this._fileButtons.includes("open")) { + if (this._fileOpenAction) { + this._fileOpenAction(); + } + else if (this.onOpenFileButtonClick) { + this.onOpenFileButtonClick(); + } + } + } + break; + case "KeyS": + if (this._docService && event.ctrlKey && event.altKey) { + event.preventDefault(); + if (this._fileButtons.includes("save")) { + if (this._fileSaveAction) { + this._fileSaveAction(); + } + else if (this.onSaveFileButtonClickAsync) { + this.onSaveFileButtonClickAsync(); + } + } + } + break; + case "KeyX": + if (this._docService && event.ctrlKey && event.altKey) { + event.preventDefault(); + if (this._fileButtons.includes("close")) { + if (this._fileCloseAction) { + this._fileCloseAction(); + } + else if (this.onCloseFileButtonClick) { + this.onCloseFileButtonClick(); + } + } + } + break; + case "KeyT": + if (this._docService && event.ctrlKey && event.altKey) { + event.preventDefault(); + this.togglePreviewer(); + } + break; + case "Digit1": + if (this._docService && event.ctrlKey && event.altKey) { + event.preventDefault(); + this.setMode("text"); + } + break; + case "Digit2": + if (this._docService && event.ctrlKey && event.altKey) { + event.preventDefault(); + this.setMode("hand"); + } + break; + case "Digit3": + if (this._docService && event.ctrlKey && event.altKey) { + event.preventDefault(); + this.setMode("annotation"); + } + break; + case "Digit4": + if (this._docService && event.ctrlKey && event.altKey) { + event.preventDefault(); + this.setMode("comparison"); + } + break; + case "ArrowLeft": + event.preventDefault(); + this.moveToPrevPage(); + break; + case "ArrowRight": + event.preventDefault(); + this.moveToNextPage(); + break; + case "ArrowUp": + event.preventDefault(); + this._viewer.zoomIn(); + break; + case "ArrowDown": + event.preventDefault(); + this._viewer.zoomOut(); + break; + case "Comma": + event.preventDefault(); + this.rotateCounterClockwise(); + break; + case "Period": + event.preventDefault(); + this.rotateClockwise(); + break; + case "Escape": + event.preventDefault(); + (_a = this._annotatorService.annotator) === null || _a === void 0 ? void 0 : _a.clear(); + break; + case "Backspace": + event.preventDefault(); + (_b = this._annotatorService.annotator) === null || _b === void 0 ? void 0 : _b.undo(); + break; + case "Enter": + event.preventDefault(); + (_c = this._annotatorService.annotator) === null || _c === void 0 ? void 0 : _c.saveAnnotationAsync(); + break; + case "KeyZ": + if (event.ctrlKey) { + event.preventDefault(); + (_d = this._docService) === null || _d === void 0 ? void 0 : _d.undoAsync(); + } + break; + default: + return; + } + }; + if (!options) { + throw new Error("No options provided"); + } + const container = document.querySelector(options.containerSelector); + if (!container) { + throw new Error("Container not found"); + } + else if (!(container instanceof HTMLDivElement)) { + throw new Error("Container is not a DIV element"); + } + else { + this._outerContainer = container; + } + if (!options.workerSource) { + throw new Error("Worker source path not defined"); + } + pdfExports.GlobalWorkerOptions.workerSrc = options.workerSource; + this._userName = options.userName || "Guest"; + this._fileButtons = options.fileButtons || []; + this._fileOpenAction = options.fileOpenAction; + this._fileSaveAction = options.fileSaveAction; + this._fileCloseAction = options.fileCloseAction; + this._comparableFileButtons = options.comparableFileButtons || []; + this._comparableFileOpenAction = options.comparableFileOpenAction; + this._comparableFileCloseAction = options.comparableFileCloseAction; + this._annotChangeCallback = options.annotChangeCallback; + this._customStampChangeCallback = options.customStampChangeCallback; + const visibleAdjPages = options.visibleAdjPages || 0; + const previewWidth = options.previewWidth || 100; + const minScale = options.minScale || 0.25; + const maxScale = options.maxScale || 4; + this._shadowRoot = this._outerContainer.attachShadow({ mode: "open" }); + this._shadowRoot.innerHTML = styles + mainHtml; + this._mainContainer = this._shadowRoot.querySelector("div#main-container"); + this._eventService = new EventService(this._mainContainer); + this._modeService = new ModeService({ disabledModes: options.disabledModes || [] }); + this._docManagerService = new DocManagerService(this._eventService); + this._pageService = new PageService(this._eventService, this._modeService, this._docManagerService, { previewCanvasWidth: previewWidth, visibleAdjPages: visibleAdjPages }); + this._customStampsService = new CustomStampService(this._mainContainer, this._eventService); + this._customStampsService.importCustomStamps(options.customStamps); + this._spinner = new Spinner(); + this._previewer = new Previewer(this._pageService, this._shadowRoot.querySelector("#previewer")); + this._viewer = new Viewer(this._modeService, this._pageService, this._shadowRoot.querySelector("#viewer"), { minScale: minScale, maxScale: maxScale }); + this._viewer.container.addEventListener("contextmenu", e => e.preventDefault()); + this.initMainContainerEventHandlers(); + this.initViewControls(); + this.initFileButtons(); + this.initModeSwitchButtons(); + this.initAnnotationButtons(); + this._eventService.addListener(docChangeEvent, this.onDocChangeAsync); + this._eventService.addListener(annotChangeEvent, this.onAnnotationChange); + this._eventService.addListener(currentPageChangeEvent, this.onCurrentPagesChanged); + this._eventService.addListener(annotatorDataChangeEvent, this.onAnnotatorDataChanged); + this._eventService.addListener(customStampEvent, this.onCustomStampChanged); + this._eventService.addListener(docServiceStateChangeEvent, this.onDocServiceStateChange); + document.addEventListener("selectionchange", this.onTextSelectionChange); + this._mainContainer.addEventListener("keydown", this.onViewerKeyDown); + } + destroy() { + var _a, _b; + this._annotChangeCallback = null; + (_a = this._annotatorService) === null || _a === void 0 ? void 0 : _a.destroy(); + this._docManagerService.destroy(); + this._viewer.destroy(); + this._previewer.destroy(); + this._pageService.destroy(); + this._customStampsService.destroy(); + this._eventService.destroy(); + (_b = this._mainContainerRObserver) === null || _b === void 0 ? void 0 : _b.disconnect(); + this._shadowRoot.innerHTML = ""; + document.removeEventListener("selectionchange", this.onTextSelectionChange); + } + openPdfAsync(src, fileName) { + return __awaiter(this, void 0, void 0, function* () { + yield this.openDocAsync("main", src, fileName); + }); + } + closePdfAsync() { + return __awaiter(this, void 0, void 0, function* () { + yield this.closeDocAsync("main"); + }); + } + openComparedPdfAsync(src, fileName) { + return __awaiter(this, void 0, void 0, function* () { + if (!this._docManagerService.docLoaded) { + return; + } + yield this.openDocAsync("compared", src, fileName); + this.setMode("comparison"); + }); + } + closeComparedPdfAsync() { + return __awaiter(this, void 0, void 0, function* () { + yield this.closeDocAsync("compared"); + this.setMode(); + }); + } + importAnnotationsAsync(dtos) { + var _a; + return __awaiter(this, void 0, void 0, function* () { + try { + yield ((_a = this._docService) === null || _a === void 0 ? void 0 : _a.appendSerializedAnnotationsAsync(dtos)); + } + catch (e) { + console.log(`Error while importing annotations: ${e.message}`); + } + }); + } + importAnnotationsFromJsonAsync(json) { + var _a; + return __awaiter(this, void 0, void 0, function* () { + try { + const dtos = JSON.parse(json); + yield ((_a = this._docService) === null || _a === void 0 ? void 0 : _a.appendSerializedAnnotationsAsync(dtos)); + } + catch (e) { + console.log(`Error while importing annotations: ${e.message}`); + } + }); + } + exportAnnotationsAsync() { + var _a; + return __awaiter(this, void 0, void 0, function* () { + const dtos = yield ((_a = this._docService) === null || _a === void 0 ? void 0 : _a.serializeAnnotationsAsync(true)); + return dtos; + }); + } + exportAnnotationsToJsonAsync() { + var _a; + return __awaiter(this, void 0, void 0, function* () { + const dtos = yield ((_a = this._docService) === null || _a === void 0 ? void 0 : _a.serializeAnnotationsAsync(true)); + return JSON.stringify(dtos); + }); + } + importCustomStamps(customStamps) { + try { + this._customStampsService.importCustomStamps(customStamps); + } + catch (e) { + console.log(`Error while importing custom stamps: ${e.message}`); + } + } + importCustomStampsFromJson(json) { + try { + const customStamps = JSON.parse(json); + this._customStampsService.importCustomStamps(customStamps); + } + catch (e) { + console.log(`Error while importing custom stamps: ${e.message}`); + } + } + exportCustomStamps() { + const customStamps = this._customStampsService.getCustomStamps(); + return customStamps; + } + exportCustomStampsToJson() { + const customStamps = this._customStampsService.getCustomStamps(); + return JSON.stringify(customStamps); + } + getCurrentPdfAsync() { + var _a; + return __awaiter(this, void 0, void 0, function* () { + const data = yield ((_a = this._docService) === null || _a === void 0 ? void 0 : _a.getDataWithUpdatedAnnotationsAsync()); + if (!(data === null || data === void 0 ? void 0 : data.length)) { + return null; + } + const blob = new Blob([data], { + type: "application/pdf", + }); + return blob; + }); + } + openDocAsync(type, src, fileName) { + return __awaiter(this, void 0, void 0, function* () { + this._spinner.show(this._mainContainer); + try { + yield this._docManagerService.openPdfAsync(type, src, fileName, this._userName, this.showPasswordDialogAsync, this.onPdfLoadingProgress); + } + catch (e) { + throw e; + } + finally { + this._spinner.hide(); + } + }); + } + closeDocAsync(type) { + return __awaiter(this, void 0, void 0, function* () { + yield this._docManagerService.closePdfAsync(type); + }); + } + initMainContainerEventHandlers() { + const mcResizeObserver = new ResizeObserver((entries) => { + const { width } = this._mainContainer.getBoundingClientRect(); + if (width < 721) { + this._mainContainer.classList.add("mobile"); + } + else { + this._mainContainer.classList.remove("mobile"); + } + if (width < 400) { + this._mainContainer.classList.add("compact"); + } + else { + this._mainContainer.classList.remove("compact"); + } + }); + mcResizeObserver.observe(this._mainContainer); + this._mainContainerRObserver = mcResizeObserver; + this._mainContainer.addEventListener("pointermove", this.onMainContainerPointerMove); + } + initViewControls() { + const paginatorInput = this._shadowRoot.getElementById("paginator-input"); + paginatorInput.addEventListener("input", this.onPaginatorInput); + paginatorInput.addEventListener("change", this.onPaginatorChange); + this._shadowRoot.querySelector("#paginator-prev") + .addEventListener("click", this.onPaginatorPrevClick); + this._shadowRoot.querySelector("#paginator-next") + .addEventListener("click", this.onPaginatorNextClick); + this._shadowRoot.querySelector("#rotate-clockwise") + .addEventListener("click", this.onRotateClockwiseClick); + this._shadowRoot.querySelector("#rotate-counter-clockwise") + .addEventListener("click", this.onRotateCounterClockwiseClick); + this._shadowRoot.querySelector("#zoom-out") + .addEventListener("click", this.onZoomOutClick); + this._shadowRoot.querySelector("#zoom-in") + .addEventListener("click", this.onZoomInClick); + this._shadowRoot.querySelector("#zoom-fit-viewer") + .addEventListener("click", this.onZoomFitViewerClick); + this._shadowRoot.querySelector("#zoom-fit-page") + .addEventListener("click", this.onZoomFitPageClick); + this._shadowRoot.querySelector("#toggle-previewer") + .addEventListener("click", this.onPreviewerToggleClick); + } + initFileButtons() { + const openButton = this._shadowRoot.querySelector("#button-open-file"); + const saveButton = this._shadowRoot.querySelector("#button-save-file"); + const closeButton = this._shadowRoot.querySelector("#button-close-file"); + if (this._fileButtons.includes("open")) { + this._fileInput = this._shadowRoot.getElementById("open-file-input"); + this._fileInput.addEventListener("change", this.onFileInput); + openButton.addEventListener("click", this._fileOpenAction || this.onOpenFileButtonClick); + } + else { + openButton.remove(); + } + if (this._fileButtons.includes("save")) { + saveButton.addEventListener("click", this._fileSaveAction || this.onSaveFileButtonClickAsync); + } + else { + saveButton.remove(); + } + if (this._fileButtons.includes("close")) { + closeButton.addEventListener("click", this._fileCloseAction || this.onCloseFileButtonClick); + } + else { + closeButton.remove(); + } + const comparableOpenButton = this._shadowRoot.querySelector("#button-command-comparison-open"); + const comparableCloseButton = this._shadowRoot.querySelector("#button-command-comparison-close"); + if (this._comparableFileButtons.includes("open")) { + this._comparableFileInput = this._shadowRoot + .getElementById("open-comparable-file-input"); + this._comparableFileInput.addEventListener("change", this.onComparableFileInput); + comparableOpenButton.addEventListener("click", this._comparableFileOpenAction || this.onComparableOpenFileButtonClick); + } + else { + comparableOpenButton.remove(); + } + if (this._comparableFileButtons.includes("close")) { + comparableCloseButton.addEventListener("click", this._comparableFileCloseAction || this.onComparableCloseFileButtonClick); + } + else { + comparableCloseButton.remove(); + } + } + initModeSwitchButtons() { + const modeButtons = this._shadowRoot.querySelectorAll("*[id^=\"button-mode-\"]"); + const enabledModes = this._modeService.enabledModes; + modeButtons.forEach(x => { + const mode = /button-mode-(.+)/.exec(x.id)[1]; + if (enabledModes.includes(mode)) { + x.addEventListener("click", this.onViewerModeButtonClick); + } + else { + x.classList.add("disabled"); + } + }); + } + initAnnotationButtons() { + this._shadowRoot.querySelectorAll("*[id^=\"button-annotation-mode-\"]") + .forEach(x => { + x.addEventListener("click", this.onAnnotationModeButtonClick); + }); + this._shadowRoot.querySelector("#button-annotation-edit-text") + .addEventListener("click", this.onAnnotationEditTextButtonClick); + this._shadowRoot.querySelector("#button-annotation-delete") + .addEventListener("click", this.onAnnotationDeleteButtonClick); + this._shadowRoot.querySelectorAll(".button-annotation-undo") + .forEach(x => x.addEventListener("click", this.annotatorUndo)); + this._shadowRoot.querySelectorAll(".button-annotation-clear") + .forEach(x => x.addEventListener("click", this.annotatorClear)); + this._shadowRoot.querySelectorAll(".button-annotation-save") + .forEach(x => x.addEventListener("click", this.annotatorSave)); + this._shadowRoot.querySelector("#button-command-undo") + .addEventListener("click", this.docServiceUndo); + } + setMode(mode) { + mode = mode || this._modeService.enabledModes[0] || "text"; + viewerModes.forEach(x => { + this._mainContainer.classList.remove("mode-" + x); + this._shadowRoot.querySelector("#button-mode-" + x).classList.remove("on"); + }); + this.setAnnotationMode("select"); + this._mainContainer.classList.add("mode-" + mode); + this._shadowRoot.querySelector("#button-mode-" + mode).classList.add("on"); + this._modeService.mode = mode; + this._viewer.renderVisible(); + } + rotateCounterClockwise() { + if (!this._docService) { + return; + } + this._pageService.getCurrentPage().rotateCounterClockwise(); + this.setAnnotationMode(this._annotatorService.mode); + } + rotateClockwise() { + if (!this._docService) { + return; + } + this._pageService.getCurrentPage().rotateCounterClockwise(); + this.setAnnotationMode(this._annotatorService.mode); + } + moveToPrevPage() { + if (!this._docService) { + return; + } + const pageIndex = n$1(this._pageService.currentPageIndex - 1, 0, this._pageService.length - 1); + this._pageService.requestSetCurrentPageIndex(pageIndex); + } + moveToNextPage() { + if (!this._docService) { + return; + } + const pageIndex = n$1(this._pageService.currentPageIndex + 1, 0, this._pageService.length - 1); + this._pageService.requestSetCurrentPageIndex(pageIndex); + } + setAnnotationMode(mode) { + var _a, _b; + if (!this._annotatorService || !mode) { + return; + } + const prevMode = this._annotatorService.mode; + (_a = this._shadowRoot.querySelector(`#button-annotation-mode-${prevMode}`)) === null || _a === void 0 ? void 0 : _a.classList.remove("on"); + (_b = this._shadowRoot.querySelector(`#button-annotation-mode-${mode}`)) === null || _b === void 0 ? void 0 : _b.classList.add("on"); + this._annotatorService.mode = mode; + } + hidePanels() { + if (!this._panelsHidden && !this._timers.hidePanels) { + this._timers.hidePanels = setTimeout(() => { + var _a; + if (!((_a = this._docManagerService) === null || _a === void 0 ? void 0 : _a.docLoaded)) { + return; + } + this._mainContainer.classList.add("hide-panels"); + this._panelsHidden = true; + this._timers.hidePanels = null; + }, 5000); + } + } + showPanels() { + if (this._timers.hidePanels) { + clearTimeout(this._timers.hidePanels); + this._timers.hidePanels = null; + } + if (this._panelsHidden) { + this._mainContainer.classList.remove("hide-panels"); + this._panelsHidden = false; + } + } + refreshPagesAsync() { + return __awaiter(this, void 0, void 0, function* () { + const docPagesNumber = this._docManagerService.pageCount; + this._shadowRoot.getElementById("paginator-total").innerHTML = docPagesNumber + ""; + yield this._pageService.reloadPagesAsync(); + }); + } + togglePreviewer() { + if (this._previewer.hidden) { + this._mainContainer.classList.remove("hide-previewer"); + this._shadowRoot.querySelector("div#toggle-previewer").classList.add("on"); + this._previewer.show(); + } + else { + this._mainContainer.classList.add("hide-previewer"); + this._shadowRoot.querySelector("div#toggle-previewer").classList.remove("on"); + this._previewer.hide(); + } + } +} + +export { AnnotEvent, TsPdfViewer };