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 };