Fix File
•
/
home
/
sportsfe...
/
httpdocs
/
wp-conte...
/
plugins
/
embedpre...
/
assets
/
pdf
/
build
•
File:
pdf.worker.js
•
Content:
*[$toPages]() { if (!this.subform.children.length) { return HTMLResult.success({ name: "div", children: [] }); } this[$extra] = { overflowNode: null, firstUnsplittable: null, currentContentArea: null, currentPageArea: null, noLayoutFailure: false, pageNumber: 1, pagePosition: "first", oddOrEven: "odd", blankOrNotBlank: "nonBlank", paraStack: [] }; const root = this.subform.children[0]; root.pageSet[$cleanPage](); const pageAreas = root.pageSet.pageArea.children; const mainHtml = { name: "div", children: [] }; let pageArea = null; let breakBefore = null; let breakBeforeTarget = null; if (root.breakBefore.children.length >= 1) { breakBefore = root.breakBefore.children[0]; breakBeforeTarget = breakBefore.target; } else if (root.subform.children.length >= 1 && root.subform.children[0].breakBefore.children.length >= 1) { breakBefore = root.subform.children[0].breakBefore.children[0]; breakBeforeTarget = breakBefore.target; } else if (root.break?.beforeTarget) { breakBefore = root.break; breakBeforeTarget = breakBefore.beforeTarget; } else if (root.subform.children.length >= 1 && root.subform.children[0].break?.beforeTarget) { breakBefore = root.subform.children[0].break; breakBeforeTarget = breakBefore.beforeTarget; } if (breakBefore) { const target = this[$searchNode](breakBeforeTarget, breakBefore[$getParent]()); if (target instanceof PageArea) { pageArea = target; breakBefore[$extra] = {}; } } if (!pageArea) { pageArea = pageAreas[0]; } pageArea[$extra] = { numberOfUse: 1 }; const pageAreaParent = pageArea[$getParent](); pageAreaParent[$extra] = { numberOfUse: 1, pageIndex: pageAreaParent.pageArea.children.indexOf(pageArea), pageSetIndex: 0 }; let targetPageArea; let leader = null; let trailer = null; let hasSomething = true; let hasSomethingCounter = 0; let startIndex = 0; while (true) { if (!hasSomething) { mainHtml.children.pop(); if (++hasSomethingCounter === MAX_EMPTY_PAGES) { warn("XFA - Something goes wrong: please file a bug."); return mainHtml; } } else { hasSomethingCounter = 0; } targetPageArea = null; this[$extra].currentPageArea = pageArea; const page = pageArea[$toHTML]().html; mainHtml.children.push(page); if (leader) { this[$extra].noLayoutFailure = true; page.children.push(leader[$toHTML](pageArea[$extra].space).html); leader = null; } if (trailer) { this[$extra].noLayoutFailure = true; page.children.push(trailer[$toHTML](pageArea[$extra].space).html); trailer = null; } const contentAreas = pageArea.contentArea.children; const htmlContentAreas = page.children.filter(node => node.attributes.class.includes("xfaContentarea")); hasSomething = false; this[$extra].firstUnsplittable = null; this[$extra].noLayoutFailure = false; const flush = index => { const html = root[$flushHTML](); if (html) { hasSomething ||= html.children?.length > 0; htmlContentAreas[index].children.push(html); } }; for (let i = startIndex, ii = contentAreas.length; i < ii; i++) { const contentArea = this[$extra].currentContentArea = contentAreas[i]; const space = { width: contentArea.w, height: contentArea.h }; startIndex = 0; if (leader) { htmlContentAreas[i].children.push(leader[$toHTML](space).html); leader = null; } if (trailer) { htmlContentAreas[i].children.push(trailer[$toHTML](space).html); trailer = null; } const html = root[$toHTML](space); if (html.success) { if (html.html) { hasSomething ||= html.html.children?.length > 0; htmlContentAreas[i].children.push(html.html); } else if (!hasSomething && mainHtml.children.length > 1) { mainHtml.children.pop(); } return mainHtml; } if (html.isBreak()) { const node = html.breakNode; flush(i); if (node.targetType === "auto") { continue; } if (node.leader) { leader = this[$searchNode](node.leader, node[$getParent]()); leader = leader ? leader[0] : null; } if (node.trailer) { trailer = this[$searchNode](node.trailer, node[$getParent]()); trailer = trailer ? trailer[0] : null; } if (node.targetType === "pageArea") { targetPageArea = node[$extra].target; i = Infinity; } else if (!node[$extra].target) { i = node[$extra].index; } else { targetPageArea = node[$extra].target; startIndex = node[$extra].index + 1; i = Infinity; } continue; } if (this[$extra].overflowNode) { const node = this[$extra].overflowNode; this[$extra].overflowNode = null; const overflowExtra = node[$getExtra](); const target = overflowExtra.target; overflowExtra.addLeader = overflowExtra.leader !== null; overflowExtra.addTrailer = overflowExtra.trailer !== null; flush(i); const currentIndex = i; i = Infinity; if (target instanceof PageArea) { targetPageArea = target; } else if (target instanceof ContentArea) { const index = contentAreas.indexOf(target); if (index !== -1) { if (index > currentIndex) { i = index - 1; } else { startIndex = index; } } else { targetPageArea = target[$getParent](); startIndex = targetPageArea.contentArea.children.indexOf(target); } } continue; } flush(i); } this[$extra].pageNumber += 1; if (targetPageArea) { if (targetPageArea[$isUsable]()) { targetPageArea[$extra].numberOfUse += 1; } else { targetPageArea = null; } } pageArea = targetPageArea || pageArea[$getNextPage](); yield null; } } } class Text extends ContentObject { constructor(attributes) { super(TEMPLATE_NS_ID, "text"); this.id = attributes.id || ""; this.maxChars = getInteger({ data: attributes.maxChars, defaultValue: 0, validate: x => x >= 0 }); this.name = attributes.name || ""; this.rid = attributes.rid || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } [$acceptWhitespace]() { return true; } [$onChild](child) { if (child[$namespaceId] === NamespaceIds.xhtml.id) { this[$content] = child; return true; } warn(`XFA - Invalid content in Text: ${child[$nodeName]}.`); return false; } [$onText](str) { if (this[$content] instanceof XFAObject) { return; } super[$onText](str); } [$finalize]() { if (typeof this[$content] === "string") { this[$content] = this[$content].replaceAll("\r\n", "\n"); } } [$getExtra]() { if (typeof this[$content] === "string") { return this[$content].split(/[\u2029\u2028\n]/).reduce((acc, line) => { if (line) { acc.push(line); } return acc; }, []).join("\n"); } return this[$content][$text](); } [$toHTML](availableSpace) { if (typeof this[$content] === "string") { const html = valueToHtml(this[$content]).html; if (this[$content].includes("\u2029")) { html.name = "div"; html.children = []; this[$content].split("\u2029").map(para => para.split(/[\u2028\n]/).reduce((acc, line) => { acc.push({ name: "span", value: line }, { name: "br" }); return acc; }, [])).forEach(lines => { html.children.push({ name: "p", children: lines }); }); } else if (/[\u2028\n]/.test(this[$content])) { html.name = "div"; html.children = []; this[$content].split(/[\u2028\n]/).forEach(line => { html.children.push({ name: "span", value: line }, { name: "br" }); }); } return HTMLResult.success(html); } return this[$content][$toHTML](availableSpace); } } class TextEdit extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "textEdit", true); this.allowRichText = getInteger({ data: attributes.allowRichText, defaultValue: 0, validate: x => x === 1 }); this.hScrollPolicy = getStringOption(attributes.hScrollPolicy, ["auto", "off", "on"]); this.id = attributes.id || ""; this.multiLine = getInteger({ data: attributes.multiLine, defaultValue: "", validate: x => x === 0 || x === 1 }); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.vScrollPolicy = getStringOption(attributes.vScrollPolicy, ["auto", "off", "on"]); this.border = null; this.comb = null; this.extras = null; this.margin = null; } [$toHTML](availableSpace) { const style = toStyle(this, "border", "font", "margin"); let html; const field = this[$getParent]()[$getParent](); if (this.multiLine === "") { this.multiLine = field instanceof Draw ? 1 : 0; } if (this.multiLine === 1) { html = { name: "textarea", attributes: { dataId: field[$data]?.[$uid] || field[$uid], fieldId: field[$uid], class: ["xfaTextfield"], style, "aria-label": ariaLabel(field), "aria-required": false } }; } else { html = { name: "input", attributes: { type: "text", dataId: field[$data]?.[$uid] || field[$uid], fieldId: field[$uid], class: ["xfaTextfield"], style, "aria-label": ariaLabel(field), "aria-required": false } }; } if (isRequired(field)) { html.attributes["aria-required"] = true; html.attributes.required = true; } return HTMLResult.success({ name: "label", attributes: { class: ["xfaLabel"] }, children: [html] }); } } class Time extends StringObject { constructor(attributes) { super(TEMPLATE_NS_ID, "time"); this.id = attributes.id || ""; this.name = attributes.name || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } [$finalize]() { const date = this[$content].trim(); this[$content] = date ? new Date(date) : null; } [$toHTML](availableSpace) { return valueToHtml(this[$content] ? this[$content].toString() : ""); } } class TimeStamp extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "timeStamp"); this.id = attributes.id || ""; this.server = attributes.server || ""; this.type = getStringOption(attributes.type, ["optional", "required"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class ToolTip extends StringObject { constructor(attributes) { super(TEMPLATE_NS_ID, "toolTip"); this.id = attributes.id || ""; this.rid = attributes.rid || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class Traversal extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "traversal", true); this.id = attributes.id || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.extras = null; this.traverse = new XFAObjectArray(); } } class Traverse extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "traverse", true); this.id = attributes.id || ""; this.operation = getStringOption(attributes.operation, ["next", "back", "down", "first", "left", "right", "up"]); this.ref = attributes.ref || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.extras = null; this.script = null; } get name() { return this.operation; } [$isTransparent]() { return false; } } class Ui extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "ui", true); this.id = attributes.id || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.extras = null; this.picture = null; this.barcode = null; this.button = null; this.checkButton = null; this.choiceList = null; this.dateTimeEdit = null; this.defaultUi = null; this.imageEdit = null; this.numericEdit = null; this.passwordEdit = null; this.signature = null; this.textEdit = null; } [$getExtra]() { if (this[$extra] === undefined) { for (const name of Object.getOwnPropertyNames(this)) { if (name === "extras" || name === "picture") { continue; } const obj = this[name]; if (!(obj instanceof XFAObject)) { continue; } this[$extra] = obj; return obj; } this[$extra] = null; } return this[$extra]; } [$toHTML](availableSpace) { const obj = this[$getExtra](); if (obj) { return obj[$toHTML](availableSpace); } return HTMLResult.EMPTY; } } class Validate extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "validate", true); this.formatTest = getStringOption(attributes.formatTest, ["warning", "disabled", "error"]); this.id = attributes.id || ""; this.nullTest = getStringOption(attributes.nullTest, ["disabled", "error", "warning"]); this.scriptTest = getStringOption(attributes.scriptTest, ["error", "disabled", "warning"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.extras = null; this.message = null; this.picture = null; this.script = null; } } class Value extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "value", true); this.id = attributes.id || ""; this.override = getInteger({ data: attributes.override, defaultValue: 0, validate: x => x === 1 }); this.relevant = getRelevant(attributes.relevant); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.arc = null; this.boolean = null; this.date = null; this.dateTime = null; this.decimal = null; this.exData = null; this.float = null; this.image = null; this.integer = null; this.line = null; this.rectangle = null; this.text = null; this.time = null; } [$setValue](value) { const parent = this[$getParent](); if (parent instanceof Field) { if (parent.ui?.imageEdit) { if (!this.image) { this.image = new Image({}); this[$appendChild](this.image); } this.image[$content] = value[$content]; return; } } const valueName = value[$nodeName]; if (this[valueName] !== null) { this[valueName][$content] = value[$content]; return; } for (const name of Object.getOwnPropertyNames(this)) { const obj = this[name]; if (obj instanceof XFAObject) { this[name] = null; this[$removeChild](obj); } } this[value[$nodeName]] = value; this[$appendChild](value); } [$text]() { if (this.exData) { if (typeof this.exData[$content] === "string") { return this.exData[$content].trim(); } return this.exData[$content][$text]().trim(); } for (const name of Object.getOwnPropertyNames(this)) { if (name === "image") { continue; } const obj = this[name]; if (obj instanceof XFAObject) { return (obj[$content] || "").toString().trim(); } } return null; } [$toHTML](availableSpace) { for (const name of Object.getOwnPropertyNames(this)) { const obj = this[name]; if (!(obj instanceof XFAObject)) { continue; } return obj[$toHTML](availableSpace); } return HTMLResult.EMPTY; } } class Variables extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "variables", true); this.id = attributes.id || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.boolean = new XFAObjectArray(); this.date = new XFAObjectArray(); this.dateTime = new XFAObjectArray(); this.decimal = new XFAObjectArray(); this.exData = new XFAObjectArray(); this.float = new XFAObjectArray(); this.image = new XFAObjectArray(); this.integer = new XFAObjectArray(); this.manifest = new XFAObjectArray(); this.script = new XFAObjectArray(); this.text = new XFAObjectArray(); this.time = new XFAObjectArray(); } [$isTransparent]() { return true; } } class TemplateNamespace { static [$buildXFAObject](name, attributes) { if (TemplateNamespace.hasOwnProperty(name)) { const node = TemplateNamespace[name](attributes); node[$setSetAttributes](attributes); return node; } return undefined; } static appearanceFilter(attrs) { return new AppearanceFilter(attrs); } static arc(attrs) { return new Arc(attrs); } static area(attrs) { return new Area(attrs); } static assist(attrs) { return new Assist(attrs); } static barcode(attrs) { return new Barcode(attrs); } static bind(attrs) { return new Bind(attrs); } static bindItems(attrs) { return new BindItems(attrs); } static bookend(attrs) { return new Bookend(attrs); } static boolean(attrs) { return new BooleanElement(attrs); } static border(attrs) { return new Border(attrs); } static break(attrs) { return new Break(attrs); } static breakAfter(attrs) { return new BreakAfter(attrs); } static breakBefore(attrs) { return new BreakBefore(attrs); } static button(attrs) { return new Button(attrs); } static calculate(attrs) { return new Calculate(attrs); } static caption(attrs) { return new Caption(attrs); } static certificate(attrs) { return new Certificate(attrs); } static certificates(attrs) { return new Certificates(attrs); } static checkButton(attrs) { return new CheckButton(attrs); } static choiceList(attrs) { return new ChoiceList(attrs); } static color(attrs) { return new Color(attrs); } static comb(attrs) { return new Comb(attrs); } static connect(attrs) { return new Connect(attrs); } static contentArea(attrs) { return new ContentArea(attrs); } static corner(attrs) { return new Corner(attrs); } static date(attrs) { return new DateElement(attrs); } static dateTime(attrs) { return new DateTime(attrs); } static dateTimeEdit(attrs) { return new DateTimeEdit(attrs); } static decimal(attrs) { return new Decimal(attrs); } static defaultUi(attrs) { return new DefaultUi(attrs); } static desc(attrs) { return new Desc(attrs); } static digestMethod(attrs) { return new DigestMethod(attrs); } static digestMethods(attrs) { return new DigestMethods(attrs); } static draw(attrs) { return new Draw(attrs); } static edge(attrs) { return new Edge(attrs); } static encoding(attrs) { return new Encoding(attrs); } static encodings(attrs) { return new Encodings(attrs); } static encrypt(attrs) { return new Encrypt(attrs); } static encryptData(attrs) { return new EncryptData(attrs); } static encryption(attrs) { return new Encryption(attrs); } static encryptionMethod(attrs) { return new EncryptionMethod(attrs); } static encryptionMethods(attrs) { return new EncryptionMethods(attrs); } static event(attrs) { return new Event(attrs); } static exData(attrs) { return new ExData(attrs); } static exObject(attrs) { return new ExObject(attrs); } static exclGroup(attrs) { return new ExclGroup(attrs); } static execute(attrs) { return new Execute(attrs); } static extras(attrs) { return new Extras(attrs); } static field(attrs) { return new Field(attrs); } static fill(attrs) { return new Fill(attrs); } static filter(attrs) { return new Filter(attrs); } static float(attrs) { return new Float(attrs); } static font(attrs) { return new template_Font(attrs); } static format(attrs) { return new Format(attrs); } static handler(attrs) { return new Handler(attrs); } static hyphenation(attrs) { return new Hyphenation(attrs); } static image(attrs) { return new Image(attrs); } static imageEdit(attrs) { return new ImageEdit(attrs); } static integer(attrs) { return new Integer(attrs); } static issuers(attrs) { return new Issuers(attrs); } static items(attrs) { return new Items(attrs); } static keep(attrs) { return new Keep(attrs); } static keyUsage(attrs) { return new KeyUsage(attrs); } static line(attrs) { return new Line(attrs); } static linear(attrs) { return new Linear(attrs); } static lockDocument(attrs) { return new LockDocument(attrs); } static manifest(attrs) { return new Manifest(attrs); } static margin(attrs) { return new Margin(attrs); } static mdp(attrs) { return new Mdp(attrs); } static medium(attrs) { return new Medium(attrs); } static message(attrs) { return new Message(attrs); } static numericEdit(attrs) { return new NumericEdit(attrs); } static occur(attrs) { return new Occur(attrs); } static oid(attrs) { return new Oid(attrs); } static oids(attrs) { return new Oids(attrs); } static overflow(attrs) { return new Overflow(attrs); } static pageArea(attrs) { return new PageArea(attrs); } static pageSet(attrs) { return new PageSet(attrs); } static para(attrs) { return new Para(attrs); } static passwordEdit(attrs) { return new PasswordEdit(attrs); } static pattern(attrs) { return new template_Pattern(attrs); } static picture(attrs) { return new Picture(attrs); } static proto(attrs) { return new Proto(attrs); } static radial(attrs) { return new Radial(attrs); } static reason(attrs) { return new Reason(attrs); } static reasons(attrs) { return new Reasons(attrs); } static rectangle(attrs) { return new Rectangle(attrs); } static ref(attrs) { return new RefElement(attrs); } static script(attrs) { return new Script(attrs); } static setProperty(attrs) { return new SetProperty(attrs); } static signData(attrs) { return new SignData(attrs); } static signature(attrs) { return new Signature(attrs); } static signing(attrs) { return new Signing(attrs); } static solid(attrs) { return new Solid(attrs); } static speak(attrs) { return new Speak(attrs); } static stipple(attrs) { return new Stipple(attrs); } static subform(attrs) { return new Subform(attrs); } static subformSet(attrs) { return new SubformSet(attrs); } static subjectDN(attrs) { return new SubjectDN(attrs); } static subjectDNs(attrs) { return new SubjectDNs(attrs); } static submit(attrs) { return new Submit(attrs); } static template(attrs) { return new Template(attrs); } static text(attrs) { return new Text(attrs); } static textEdit(attrs) { return new TextEdit(attrs); } static time(attrs) { return new Time(attrs); } static timeStamp(attrs) { return new TimeStamp(attrs); } static toolTip(attrs) { return new ToolTip(attrs); } static traversal(attrs) { return new Traversal(attrs); } static traverse(attrs) { return new Traverse(attrs); } static ui(attrs) { return new Ui(attrs); } static validate(attrs) { return new Validate(attrs); } static value(attrs) { return new Value(attrs); } static variables(attrs) { return new Variables(attrs); } } ;// CONCATENATED MODULE: ./src/core/xfa/bind.js const bind_NS_DATASETS = NamespaceIds.datasets.id; function createText(content) { const node = new Text({}); node[$content] = content; return node; } class Binder { constructor(root) { this.root = root; this.datasets = root.datasets; this.data = root.datasets?.data || new XmlObject(NamespaceIds.datasets.id, "data"); this.emptyMerge = this.data[$getChildren]().length === 0; this.root.form = this.form = root.template[$clone](); } _isConsumeData() { return !this.emptyMerge && this._mergeMode; } _isMatchTemplate() { return !this._isConsumeData(); } bind() { this._bindElement(this.form, this.data); return this.form; } getData() { return this.data; } _bindValue(formNode, data, picture) { formNode[$data] = data; if (formNode[$hasSettableValue]()) { if (data[$isDataValue]()) { const value = data[$getDataValue](); formNode[$setValue](createText(value)); } else if (formNode instanceof Field && formNode.ui?.choiceList?.open === "multiSelect") { const value = data[$getChildren]().map(child => child[$content].trim()).join("\n"); formNode[$setValue](createText(value)); } else if (this._isConsumeData()) { warn(`XFA - Nodes haven't the same type.`); } } else if (!data[$isDataValue]() || this._isMatchTemplate()) { this._bindElement(formNode, data); } else { warn(`XFA - Nodes haven't the same type.`); } } _findDataByNameToConsume(name, isValue, dataNode, global) { if (!name) { return null; } let generator, match; for (let i = 0; i < 3; i++) { generator = dataNode[$getRealChildrenByNameIt](name, false, true); while (true) { match = generator.next().value; if (!match) { break; } if (isValue === match[$isDataValue]()) { return match; } } if (dataNode[$namespaceId] === NamespaceIds.datasets.id && dataNode[$nodeName] === "data") { break; } dataNode = dataNode[$getParent](); } if (!global) { return null; } generator = this.data[$getRealChildrenByNameIt](name, true, false); match = generator.next().value; if (match) { return match; } generator = this.data[$getAttributeIt](name, true); match = generator.next().value; if (match?.[$isDataValue]()) { return match; } return null; } _setProperties(formNode, dataNode) { if (!formNode.hasOwnProperty("setProperty")) { return; } for (const { ref, target, connection } of formNode.setProperty.children) { if (connection) { continue; } if (!ref) { continue; } const nodes = searchNode(this.root, dataNode, ref, false, false); if (!nodes) { warn(`XFA - Invalid reference: ${ref}.`); continue; } const [node] = nodes; if (!node[$isDescendent](this.data)) { warn(`XFA - Invalid node: must be a data node.`); continue; } const targetNodes = searchNode(this.root, formNode, target, false, false); if (!targetNodes) { warn(`XFA - Invalid target: ${target}.`); continue; } const [targetNode] = targetNodes; if (!targetNode[$isDescendent](formNode)) { warn(`XFA - Invalid target: must be a property or subproperty.`); continue; } const targetParent = targetNode[$getParent](); if (targetNode instanceof SetProperty || targetParent instanceof SetProperty) { warn(`XFA - Invalid target: cannot be a setProperty or one of its properties.`); continue; } if (targetNode instanceof BindItems || targetParent instanceof BindItems) { warn(`XFA - Invalid target: cannot be a bindItems or one of its properties.`); continue; } const content = node[$text](); const name = targetNode[$nodeName]; if (targetNode instanceof XFAAttribute) { const attrs = Object.create(null); attrs[name] = content; const obj = Reflect.construct(Object.getPrototypeOf(targetParent).constructor, [attrs]); targetParent[name] = obj[name]; continue; } if (!targetNode.hasOwnProperty($content)) { warn(`XFA - Invalid node to use in setProperty`); continue; } targetNode[$data] = node; targetNode[$content] = content; targetNode[$finalize](); } } _bindItems(formNode, dataNode) { if (!formNode.hasOwnProperty("items") || !formNode.hasOwnProperty("bindItems") || formNode.bindItems.isEmpty()) { return; } for (const item of formNode.items.children) { formNode[$removeChild](item); } formNode.items.clear(); const labels = new Items({}); const values = new Items({}); formNode[$appendChild](labels); formNode.items.push(labels); formNode[$appendChild](values); formNode.items.push(values); for (const { ref, labelRef, valueRef, connection } of formNode.bindItems.children) { if (connection) { continue; } if (!ref) { continue; } const nodes = searchNode(this.root, dataNode, ref, false, false); if (!nodes) { warn(`XFA - Invalid reference: ${ref}.`); continue; } for (const node of nodes) { if (!node[$isDescendent](this.datasets)) { warn(`XFA - Invalid ref (${ref}): must be a datasets child.`); continue; } const labelNodes = searchNode(this.root, node, labelRef, true, false); if (!labelNodes) { warn(`XFA - Invalid label: ${labelRef}.`); continue; } const [labelNode] = labelNodes; if (!labelNode[$isDescendent](this.datasets)) { warn(`XFA - Invalid label: must be a datasets child.`); continue; } const valueNodes = searchNode(this.root, node, valueRef, true, false); if (!valueNodes) { warn(`XFA - Invalid value: ${valueRef}.`); continue; } const [valueNode] = valueNodes; if (!valueNode[$isDescendent](this.datasets)) { warn(`XFA - Invalid value: must be a datasets child.`); continue; } const label = createText(labelNode[$text]()); const value = createText(valueNode[$text]()); labels[$appendChild](label); labels.text.push(label); values[$appendChild](value); values.text.push(value); } } } _bindOccurrences(formNode, matches, picture) { let baseClone; if (matches.length > 1) { baseClone = formNode[$clone](); baseClone[$removeChild](baseClone.occur); baseClone.occur = null; } this._bindValue(formNode, matches[0], picture); this._setProperties(formNode, matches[0]); this._bindItems(formNode, matches[0]); if (matches.length === 1) { return; } const parent = formNode[$getParent](); const name = formNode[$nodeName]; const pos = parent[$indexOf](formNode); for (let i = 1, ii = matches.length; i < ii; i++) { const match = matches[i]; const clone = baseClone[$clone](); parent[name].push(clone); parent[$insertAt](pos + i, clone); this._bindValue(clone, match, picture); this._setProperties(clone, match); this._bindItems(clone, match); } } _createOccurrences(formNode) { if (!this.emptyMerge) { return; } const { occur } = formNode; if (!occur || occur.initial <= 1) { return; } const parent = formNode[$getParent](); const name = formNode[$nodeName]; if (!(parent[name] instanceof XFAObjectArray)) { return; } let currentNumber; if (formNode.name) { currentNumber = parent[name].children.filter(e => e.name === formNode.name).length; } else { currentNumber = parent[name].children.length; } const pos = parent[$indexOf](formNode) + 1; const ii = occur.initial - currentNumber; if (ii) { const nodeClone = formNode[$clone](); nodeClone[$removeChild](nodeClone.occur); nodeClone.occur = null; parent[name].push(nodeClone); parent[$insertAt](pos, nodeClone); for (let i = 1; i < ii; i++) { const clone = nodeClone[$clone](); parent[name].push(clone); parent[$insertAt](pos + i, clone); } } } _getOccurInfo(formNode) { const { name, occur } = formNode; if (!occur || !name) { return [1, 1]; } const max = occur.max === -1 ? Infinity : occur.max; return [occur.min, max]; } _setAndBind(formNode, dataNode) { this._setProperties(formNode, dataNode); this._bindItems(formNode, dataNode); this._bindElement(formNode, dataNode); } _bindElement(formNode, dataNode) { const uselessNodes = []; this._createOccurrences(formNode); for (const child of formNode[$getChildren]()) { if (child[$data]) { continue; } if (this._mergeMode === undefined && child[$nodeName] === "subform") { this._mergeMode = child.mergeMode === "consumeData"; const dataChildren = dataNode[$getChildren](); if (dataChildren.length > 0) { this._bindOccurrences(child, [dataChildren[0]], null); } else if (this.emptyMerge) { const nsId = dataNode[$namespaceId] === bind_NS_DATASETS ? -1 : dataNode[$namespaceId]; const dataChild = child[$data] = new XmlObject(nsId, child.name || "root"); dataNode[$appendChild](dataChild); this._bindElement(child, dataChild); } continue; } if (!child[$isBindable]()) { continue; } let global = false; let picture = null; let ref = null; let match = null; if (child.bind) { switch (child.bind.match) { case "none": this._setAndBind(child, dataNode); continue; case "global": global = true; break; case "dataRef": if (!child.bind.ref) { warn(`XFA - ref is empty in node ${child[$nodeName]}.`); this._setAndBind(child, dataNode); continue; } ref = child.bind.ref; break; default: break; } if (child.bind.picture) { picture = child.bind.picture[$content]; } } const [min, max] = this._getOccurInfo(child); if (ref) { match = searchNode(this.root, dataNode, ref, true, false); if (match === null) { match = createDataNode(this.data, dataNode, ref); if (!match) { continue; } if (this._isConsumeData()) { match[$consumed] = true; } this._setAndBind(child, match); continue; } else { if (this._isConsumeData()) { match = match.filter(node => !node[$consumed]); } if (match.length > max) { match = match.slice(0, max); } else if (match.length === 0) { match = null; } if (match && this._isConsumeData()) { match.forEach(node => { node[$consumed] = true; }); } } } else { if (!child.name) { this._setAndBind(child, dataNode); continue; } if (this._isConsumeData()) { const matches = []; while (matches.length < max) { const found = this._findDataByNameToConsume(child.name, child[$hasSettableValue](), dataNode, global); if (!found) { break; } found[$consumed] = true; matches.push(found); } match = matches.length > 0 ? matches : null; } else { match = dataNode[$getRealChildrenByNameIt](child.name, false, this.emptyMerge).next().value; if (!match) { if (min === 0) { uselessNodes.push(child); continue; } const nsId = dataNode[$namespaceId] === bind_NS_DATASETS ? -1 : dataNode[$namespaceId]; match = child[$data] = new XmlObject(nsId, child.name); if (this.emptyMerge) { match[$consumed] = true; } dataNode[$appendChild](match); this._setAndBind(child, match); continue; } if (this.emptyMerge) { match[$consumed] = true; } match = [match]; } } if (match) { this._bindOccurrences(child, match, picture); } else if (min > 0) { this._setAndBind(child, dataNode); } else { uselessNodes.push(child); } } uselessNodes.forEach(node => node[$getParent]()[$removeChild](node)); } } ;// CONCATENATED MODULE: ./src/core/xfa/data.js class DataHandler { constructor(root, data) { this.data = data; this.dataset = root.datasets || null; } serialize(storage) { const stack = [[-1, this.data[$getChildren]()]]; while (stack.length > 0) { const last = stack.at(-1); const [i, children] = last; if (i + 1 === children.length) { stack.pop(); continue; } const child = children[++last[0]]; const storageEntry = storage.get(child[$uid]); if (storageEntry) { child[$setValue](storageEntry); } else { const attributes = child[$getAttributes](); for (const value of attributes.values()) { const entry = storage.get(value[$uid]); if (entry) { value[$setValue](entry); break; } } } const nodes = child[$getChildren](); if (nodes.length > 0) { stack.push([-1, nodes]); } } const buf = [`<xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">`]; if (this.dataset) { for (const child of this.dataset[$getChildren]()) { if (child[$nodeName] !== "data") { child[$toString](buf); } } } this.data[$toString](buf); buf.push("</xfa:datasets>"); return buf.join(""); } } ;// CONCATENATED MODULE: ./src/core/xfa/config.js const CONFIG_NS_ID = NamespaceIds.config.id; class Acrobat extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "acrobat", true); this.acrobat7 = null; this.autoSave = null; this.common = null; this.validate = null; this.validateApprovalSignatures = null; this.submitUrl = new XFAObjectArray(); } } class Acrobat7 extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "acrobat7", true); this.dynamicRender = null; } } class ADBE_JSConsole extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "ADBE_JSConsole", ["delegate", "Enable", "Disable"]); } } class ADBE_JSDebugger extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "ADBE_JSDebugger", ["delegate", "Enable", "Disable"]); } } class AddSilentPrint extends Option01 { constructor(attributes) { super(CONFIG_NS_ID, "addSilentPrint"); } } class AddViewerPreferences extends Option01 { constructor(attributes) { super(CONFIG_NS_ID, "addViewerPreferences"); } } class AdjustData extends Option10 { constructor(attributes) { super(CONFIG_NS_ID, "adjustData"); } } class AdobeExtensionLevel extends IntegerObject { constructor(attributes) { super(CONFIG_NS_ID, "adobeExtensionLevel", 0, n => n >= 1 && n <= 8); } } class Agent extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "agent", true); this.name = attributes.name ? attributes.name.trim() : ""; this.common = new XFAObjectArray(); } } class AlwaysEmbed extends ContentObject { constructor(attributes) { super(CONFIG_NS_ID, "alwaysEmbed"); } } class Amd extends StringObject { constructor(attributes) { super(CONFIG_NS_ID, "amd"); } } class config_Area extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "area"); this.level = getInteger({ data: attributes.level, defaultValue: 0, validate: n => n >= 1 && n <= 3 }); this.name = getStringOption(attributes.name, ["", "barcode", "coreinit", "deviceDriver", "font", "general", "layout", "merge", "script", "signature", "sourceSet", "templateCache"]); } } class Attributes extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "attributes", ["preserve", "delegate", "ignore"]); } } class AutoSave extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "autoSave", ["disabled", "enabled"]); } } class Base extends StringObject { constructor(attributes) { super(CONFIG_NS_ID, "base"); } } class BatchOutput extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "batchOutput"); this.format = getStringOption(attributes.format, ["none", "concat", "zip", "zipCompress"]); } } class BehaviorOverride extends ContentObject { constructor(attributes) { super(CONFIG_NS_ID, "behaviorOverride"); } [$finalize]() { this[$content] = new Map(this[$content].trim().split(/\s+/).filter(x => x.includes(":")).map(x => x.split(":", 2))); } } class Cache extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "cache", true); this.templateCache = null; } } class Change extends Option01 { constructor(attributes) { super(CONFIG_NS_ID, "change"); } } class Common extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "common", true); this.data = null; this.locale = null; this.localeSet = null; this.messaging = null; this.suppressBanner = null; this.template = null; this.validationMessaging = null; this.versionControl = null; this.log = new XFAObjectArray(); } } class Compress extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "compress"); this.scope = getStringOption(attributes.scope, ["imageOnly", "document"]); } } class CompressLogicalStructure extends Option01 { constructor(attributes) { super(CONFIG_NS_ID, "compressLogicalStructure"); } } class CompressObjectStream extends Option10 { constructor(attributes) { super(CONFIG_NS_ID, "compressObjectStream"); } } class Compression extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "compression", true); this.compressLogicalStructure = null; this.compressObjectStream = null; this.level = null; this.type = null; } } class Config extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "config", true); this.acrobat = null; this.present = null; this.trace = null; this.agent = new XFAObjectArray(); } } class Conformance extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "conformance", ["A", "B"]); } } class ContentCopy extends Option01 { constructor(attributes) { super(CONFIG_NS_ID, "contentCopy"); } } class Copies extends IntegerObject { constructor(attributes) { super(CONFIG_NS_ID, "copies", 1, n => n >= 1); } } class Creator extends StringObject { constructor(attributes) { super(CONFIG_NS_ID, "creator"); } } class CurrentPage extends IntegerObject { constructor(attributes) { super(CONFIG_NS_ID, "currentPage", 0, n => n >= 0); } } class Data extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "data", true); this.adjustData = null; this.attributes = null; this.incrementalLoad = null; this.outputXSL = null; this.range = null; this.record = null; this.startNode = null; this.uri = null; this.window = null; this.xsl = null; this.excludeNS = new XFAObjectArray(); this.transform = new XFAObjectArray(); } } class Debug extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "debug", true); this.uri = null; } } class DefaultTypeface extends ContentObject { constructor(attributes) { super(CONFIG_NS_ID, "defaultTypeface"); this.writingScript = getStringOption(attributes.writingScript, ["*", "Arabic", "Cyrillic", "EastEuropeanRoman", "Greek", "Hebrew", "Japanese", "Korean", "Roman", "SimplifiedChinese", "Thai", "TraditionalChinese", "Vietnamese"]); } } class Destination extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "destination", ["pdf", "pcl", "ps", "webClient", "zpl"]); } } class DocumentAssembly extends Option01 { constructor(attributes) { super(CONFIG_NS_ID, "documentAssembly"); } } class Driver extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "driver", true); this.name = attributes.name ? attributes.name.trim() : ""; this.fontInfo = null; this.xdc = null; } } class DuplexOption extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "duplexOption", ["simplex", "duplexFlipLongEdge", "duplexFlipShortEdge"]); } } class DynamicRender extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "dynamicRender", ["forbidden", "required"]); } } class Embed extends Option01 { constructor(attributes) { super(CONFIG_NS_ID, "embed"); } } class config_Encrypt extends Option01 { constructor(attributes) { super(CONFIG_NS_ID, "encrypt"); } } class config_Encryption extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "encryption", true); this.encrypt = null; this.encryptionLevel = null; this.permissions = null; } } class EncryptionLevel extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "encryptionLevel", ["40bit", "128bit"]); } } class Enforce extends StringObject { constructor(attributes) { super(CONFIG_NS_ID, "enforce"); } } class Equate extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "equate"); this.force = getInteger({ data: attributes.force, defaultValue: 1, validate: n => n === 0 }); this.from = attributes.from || ""; this.to = attributes.to || ""; } } class EquateRange extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "equateRange"); this.from = attributes.from || ""; this.to = attributes.to || ""; this._unicodeRange = attributes.unicodeRange || ""; } get unicodeRange() { const ranges = []; const unicodeRegex = /U\+([0-9a-fA-F]+)/; const unicodeRange = this._unicodeRange; for (let range of unicodeRange.split(",").map(x => x.trim()).filter(x => !!x)) { range = range.split("-", 2).map(x => { const found = x.match(unicodeRegex); if (!found) { return 0; } return parseInt(found[1], 16); }); if (range.length === 1) { range.push(range[0]); } ranges.push(range); } return shadow(this, "unicodeRange", ranges); } } class Exclude extends ContentObject { constructor(attributes) { super(CONFIG_NS_ID, "exclude"); } [$finalize]() { this[$content] = this[$content].trim().split(/\s+/).filter(x => x && ["calculate", "close", "enter", "exit", "initialize", "ready", "validate"].includes(x)); } } class ExcludeNS extends StringObject { constructor(attributes) { super(CONFIG_NS_ID, "excludeNS"); } } class FlipLabel extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "flipLabel", ["usePrinterSetting", "on", "off"]); } } class config_FontInfo extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "fontInfo", true); this.embed = null; this.map = null; this.subsetBelow = null; this.alwaysEmbed = new XFAObjectArray(); this.defaultTypeface = new XFAObjectArray(); this.neverEmbed = new XFAObjectArray(); } } class FormFieldFilling extends Option01 { constructor(attributes) { super(CONFIG_NS_ID, "formFieldFilling"); } } class GroupParent extends StringObject { constructor(attributes) { super(CONFIG_NS_ID, "groupParent"); } } class IfEmpty extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "ifEmpty", ["dataValue", "dataGroup", "ignore", "remove"]); } } class IncludeXDPContent extends StringObject { constructor(attributes) { super(CONFIG_NS_ID, "includeXDPContent"); } } class IncrementalLoad extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "incrementalLoad", ["none", "forwardOnly"]); } } class IncrementalMerge extends Option01 { constructor(attributes) { super(CONFIG_NS_ID, "incrementalMerge"); } } class Interactive extends Option01 { constructor(attributes) { super(CONFIG_NS_ID, "interactive"); } } class Jog extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "jog", ["usePrinterSetting", "none", "pageSet"]); } } class LabelPrinter extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "labelPrinter", true); this.name = getStringOption(attributes.name, ["zpl", "dpl", "ipl", "tcpl"]); this.batchOutput = null; this.flipLabel = null; this.fontInfo = null; this.xdc = null; } } class Layout extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "layout", ["paginate", "panel"]); } } class Level extends IntegerObject { constructor(attributes) { super(CONFIG_NS_ID, "level", 0, n => n > 0); } } class Linearized extends Option01 { constructor(attributes) { super(CONFIG_NS_ID, "linearized"); } } class Locale extends StringObject { constructor(attributes) { super(CONFIG_NS_ID, "locale"); } } class LocaleSet extends StringObject { constructor(attributes) { super(CONFIG_NS_ID, "localeSet"); } } class Log extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "log", true); this.mode = null; this.threshold = null; this.to = null; this.uri = null; } } class MapElement extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "map", true); this.equate = new XFAObjectArray(); this.equateRange = new XFAObjectArray(); } } class MediumInfo extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "mediumInfo", true); this.map = null; } } class config_Message extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "message", true); this.msgId = null; this.severity = null; } } class Messaging extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "messaging", true); this.message = new XFAObjectArray(); } } class Mode extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "mode", ["append", "overwrite"]); } } class ModifyAnnots extends Option01 { constructor(attributes) { super(CONFIG_NS_ID, "modifyAnnots"); } } class MsgId extends IntegerObject { constructor(attributes) { super(CONFIG_NS_ID, "msgId", 1, n => n >= 1); } } class NameAttr extends StringObject { constructor(attributes) { super(CONFIG_NS_ID, "nameAttr"); } } class NeverEmbed extends ContentObject { constructor(attributes) { super(CONFIG_NS_ID, "neverEmbed"); } } class NumberOfCopies extends IntegerObject { constructor(attributes) { super(CONFIG_NS_ID, "numberOfCopies", null, n => n >= 2 && n <= 5); } } class OpenAction extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "openAction", true); this.destination = null; } } class Output extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "output", true); this.to = null; this.type = null; this.uri = null; } } class OutputBin extends StringObject { constructor(attributes) { super(CONFIG_NS_ID, "outputBin"); } } class OutputXSL extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "outputXSL", true); this.uri = null; } } class Overprint extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "overprint", ["none", "both", "draw", "field"]); } } class Packets extends StringObject { constructor(attributes) { super(CONFIG_NS_ID, "packets"); } [$finalize]() { if (this[$content] === "*") { return; } this[$content] = this[$content].trim().split(/\s+/).filter(x => ["config", "datasets", "template", "xfdf", "xslt"].includes(x)); } } class PageOffset extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "pageOffset"); this.x = getInteger({ data: attributes.x, defaultValue: "useXDCSetting", validate: n => true }); this.y = getInteger({ data: attributes.y, defaultValue: "useXDCSetting", validate: n => true }); } } class PageRange extends StringObject { constructor(attributes) { super(CONFIG_NS_ID, "pageRange"); } [$finalize]() { const numbers = this[$content].trim().split(/\s+/).map(x => parseInt(x, 10)); const ranges = []; for (let i = 0, ii = numbers.length; i < ii; i += 2) { ranges.push(numbers.slice(i, i + 2)); } this[$content] = ranges; } } class Pagination extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "pagination", ["simplex", "duplexShortEdge", "duplexLongEdge"]); } } class PaginationOverride extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "paginationOverride", ["none", "forceDuplex", "forceDuplexLongEdge", "forceDuplexShortEdge", "forceSimplex"]); } } class Part extends IntegerObject { constructor(attributes) { super(CONFIG_NS_ID, "part", 1, n => false); } } class Pcl extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "pcl", true); this.name = attributes.name || ""; this.batchOutput = null; this.fontInfo = null; this.jog = null; this.mediumInfo = null; this.outputBin = null; this.pageOffset = null; this.staple = null; this.xdc = null; } } class Pdf extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "pdf", true); this.name = attributes.name || ""; this.adobeExtensionLevel = null; this.batchOutput = null; this.compression = null; this.creator = null; this.encryption = null; this.fontInfo = null; this.interactive = null; this.linearized = null; this.openAction = null; this.pdfa = null; this.producer = null; this.renderPolicy = null; this.scriptModel = null; this.silentPrint = null; this.submitFormat = null; this.tagged = null; this.version = null; this.viewerPreferences = null; this.xdc = null; } } class Pdfa extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "pdfa", true); this.amd = null; this.conformance = null; this.includeXDPContent = null; this.part = null; } } class Permissions extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "permissions", true); this.accessibleContent = null; this.change = null; this.contentCopy = null; this.documentAssembly = null; this.formFieldFilling = null; this.modifyAnnots = null; this.plaintextMetadata = null; this.print = null; this.printHighQuality = null; } } class PickTrayByPDFSize extends Option01 { constructor(attributes) { super(CONFIG_NS_ID, "pickTrayByPDFSize"); } } class config_Picture extends StringObject { constructor(attributes) { super(CONFIG_NS_ID, "picture"); } } class PlaintextMetadata extends Option01 { constructor(attributes) { super(CONFIG_NS_ID, "plaintextMetadata"); } } class Presence extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "presence", ["preserve", "dissolve", "dissolveStructure", "ignore", "remove"]); } } class Present extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "present", true); this.behaviorOverride = null; this.cache = null; this.common = null; this.copies = null; this.destination = null; this.incrementalMerge = null; this.layout = null; this.output = null; this.overprint = null; this.pagination = null; this.paginationOverride = null; this.script = null; this.validate = null; this.xdp = null; this.driver = new XFAObjectArray(); this.labelPrinter = new XFAObjectArray(); this.pcl = new XFAObjectArray(); this.pdf = new XFAObjectArray(); this.ps = new XFAObjectArray(); this.submitUrl = new XFAObjectArray(); this.webClient = new XFAObjectArray(); this.zpl = new XFAObjectArray(); } } class Print extends Option01 { constructor(attributes) { super(CONFIG_NS_ID, "print"); } } class PrintHighQuality extends Option01 { constructor(attributes) { super(CONFIG_NS_ID, "printHighQuality"); } } class PrintScaling extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "printScaling", ["appdefault", "noScaling"]); } } class PrinterName extends StringObject { constructor(attributes) { super(CONFIG_NS_ID, "printerName"); } } class Producer extends StringObject { constructor(attributes) { super(CONFIG_NS_ID, "producer"); } } class Ps extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "ps", true); this.name = attributes.name || ""; this.batchOutput = null; this.fontInfo = null; this.jog = null; this.mediumInfo = null; this.outputBin = null; this.staple = null; this.xdc = null; } } class Range extends ContentObject { constructor(attributes) { super(CONFIG_NS_ID, "range"); } [$finalize]() { this[$content] = this[$content].trim().split(/\s*,\s*/, 2).map(range => range.split("-").map(x => parseInt(x.trim(), 10))).filter(range => range.every(x => !isNaN(x))).map(range => { if (range.length === 1) { range.push(range[0]); } return range; }); } } class Record extends ContentObject { constructor(attributes) { super(CONFIG_NS_ID, "record"); } [$finalize]() { this[$content] = this[$content].trim(); const n = parseInt(this[$content], 10); if (!isNaN(n) && n >= 0) { this[$content] = n; } } } class Relevant extends ContentObject { constructor(attributes) { super(CONFIG_NS_ID, "relevant"); } [$finalize]() { this[$content] = this[$content].trim().split(/\s+/); } } class Rename extends ContentObject { constructor(attributes) { super(CONFIG_NS_ID, "rename"); } [$finalize]() { this[$content] = this[$content].trim(); if (this[$content].toLowerCase().startsWith("xml") || new RegExp("[\\p{L}_][\\p{L}\\d._\\p{M}-]*", "u").test(this[$content])) { warn("XFA - Rename: invalid XFA name"); } } } class RenderPolicy extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "renderPolicy", ["server", "client"]); } } class RunScripts extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "runScripts", ["both", "client", "none", "server"]); } } class config_Script extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "script", true); this.currentPage = null; this.exclude = null; this.runScripts = null; } } class ScriptModel extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "scriptModel", ["XFA", "none"]); } } class Severity extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "severity", ["ignore", "error", "information", "trace", "warning"]); } } class SilentPrint extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "silentPrint", true); this.addSilentPrint = null; this.printerName = null; } } class Staple extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "staple"); this.mode = getStringOption(attributes.mode, ["usePrinterSetting", "on", "off"]); } } class StartNode extends StringObject { constructor(attributes) { super(CONFIG_NS_ID, "startNode"); } } class StartPage extends IntegerObject { constructor(attributes) { super(CONFIG_NS_ID, "startPage", 0, n => true); } } class SubmitFormat extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "submitFormat", ["html", "delegate", "fdf", "xml", "pdf"]); } } class SubmitUrl extends StringObject { constructor(attributes) { super(CONFIG_NS_ID, "submitUrl"); } } class SubsetBelow extends IntegerObject { constructor(attributes) { super(CONFIG_NS_ID, "subsetBelow", 100, n => n >= 0 && n <= 100); } } class SuppressBanner extends Option01 { constructor(attributes) { super(CONFIG_NS_ID, "suppressBanner"); } } class Tagged extends Option01 { constructor(attributes) { super(CONFIG_NS_ID, "tagged"); } } class config_Template extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "template", true); this.base = null; this.relevant = null; this.startPage = null; this.uri = null; this.xsl = null; } } class Threshold extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "threshold", ["trace", "error", "information", "warning"]); } } class To extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "to", ["null", "memory", "stderr", "stdout", "system", "uri"]); } } class TemplateCache extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "templateCache"); this.maxEntries = getInteger({ data: attributes.maxEntries, defaultValue: 5, validate: n => n >= 0 }); } } class Trace extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "trace", true); this.area = new XFAObjectArray(); } } class Transform extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "transform", true); this.groupParent = null; this.ifEmpty = null; this.nameAttr = null; this.picture = null; this.presence = null; this.rename = null; this.whitespace = null; } } class Type extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "type", ["none", "ascii85", "asciiHex", "ccittfax", "flate", "lzw", "runLength", "native", "xdp", "mergedXDP"]); } } class Uri extends StringObject { constructor(attributes) { super(CONFIG_NS_ID, "uri"); } } class config_Validate extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "validate", ["preSubmit", "prePrint", "preExecute", "preSave"]); } } class ValidateApprovalSignatures extends ContentObject { constructor(attributes) { super(CONFIG_NS_ID, "validateApprovalSignatures"); } [$finalize]() { this[$content] = this[$content].trim().split(/\s+/).filter(x => ["docReady", "postSign"].includes(x)); } } class ValidationMessaging extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "validationMessaging", ["allMessagesIndividually", "allMessagesTogether", "firstMessageOnly", "noMessages"]); } } class Version extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "version", ["1.7", "1.6", "1.5", "1.4", "1.3", "1.2"]); } } class VersionControl extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "VersionControl"); this.outputBelow = getStringOption(attributes.outputBelow, ["warn", "error", "update"]); this.sourceAbove = getStringOption(attributes.sourceAbove, ["warn", "error"]); this.sourceBelow = getStringOption(attributes.sourceBelow, ["update", "maintain"]); } } class ViewerPreferences extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "viewerPreferences", true); this.ADBE_JSConsole = null; this.ADBE_JSDebugger = null; this.addViewerPreferences = null; this.duplexOption = null; this.enforce = null; this.numberOfCopies = null; this.pageRange = null; this.pickTrayByPDFSize = null; this.printScaling = null; } } class WebClient extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "webClient", true); this.name = attributes.name ? attributes.name.trim() : ""; this.fontInfo = null; this.xdc = null; } } class Whitespace extends OptionObject { constructor(attributes) { super(CONFIG_NS_ID, "whitespace", ["preserve", "ltrim", "normalize", "rtrim", "trim"]); } } class Window extends ContentObject { constructor(attributes) { super(CONFIG_NS_ID, "window"); } [$finalize]() { const pair = this[$content].trim().split(/\s*,\s*/, 2).map(x => parseInt(x, 10)); if (pair.some(x => isNaN(x))) { this[$content] = [0, 0]; return; } if (pair.length === 1) { pair.push(pair[0]); } this[$content] = pair; } } class Xdc extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "xdc", true); this.uri = new XFAObjectArray(); this.xsl = new XFAObjectArray(); } } class Xdp extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "xdp", true); this.packets = null; } } class Xsl extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "xsl", true); this.debug = null; this.uri = null; } } class Zpl extends XFAObject { constructor(attributes) { super(CONFIG_NS_ID, "zpl", true); this.name = attributes.name ? attributes.name.trim() : ""; this.batchOutput = null; this.flipLabel = null; this.fontInfo = null; this.xdc = null; } } class ConfigNamespace { static [$buildXFAObject](name, attributes) { if (ConfigNamespace.hasOwnProperty(name)) { return ConfigNamespace[name](attributes); } return undefined; } static acrobat(attrs) { return new Acrobat(attrs); } static acrobat7(attrs) { return new Acrobat7(attrs); } static ADBE_JSConsole(attrs) { return new ADBE_JSConsole(attrs); } static ADBE_JSDebugger(attrs) { return new ADBE_JSDebugger(attrs); } static addSilentPrint(attrs) { return new AddSilentPrint(attrs); } static addViewerPreferences(attrs) { return new AddViewerPreferences(attrs); } static adjustData(attrs) { return new AdjustData(attrs); } static adobeExtensionLevel(attrs) { return new AdobeExtensionLevel(attrs); } static agent(attrs) { return new Agent(attrs); } static alwaysEmbed(attrs) { return new AlwaysEmbed(attrs); } static amd(attrs) { return new Amd(attrs); } static area(attrs) { return new config_Area(attrs); } static attributes(attrs) { return new Attributes(attrs); } static autoSave(attrs) { return new AutoSave(attrs); } static base(attrs) { return new Base(attrs); } static batchOutput(attrs) { return new BatchOutput(attrs); } static behaviorOverride(attrs) { return new BehaviorOverride(attrs); } static cache(attrs) { return new Cache(attrs); } static change(attrs) { return new Change(attrs); } static common(attrs) { return new Common(attrs); } static compress(attrs) { return new Compress(attrs); } static compressLogicalStructure(attrs) { return new CompressLogicalStructure(attrs); } static compressObjectStream(attrs) { return new CompressObjectStream(attrs); } static compression(attrs) { return new Compression(attrs); } static config(attrs) { return new Config(attrs); } static conformance(attrs) { return new Conformance(attrs); } static contentCopy(attrs) { return new ContentCopy(attrs); } static copies(attrs) { return new Copies(attrs); } static creator(attrs) { return new Creator(attrs); } static currentPage(attrs) { return new CurrentPage(attrs); } static data(attrs) { return new Data(attrs); } static debug(attrs) { return new Debug(attrs); } static defaultTypeface(attrs) { return new DefaultTypeface(attrs); } static destination(attrs) { return new Destination(attrs); } static documentAssembly(attrs) { return new DocumentAssembly(attrs); } static driver(attrs) { return new Driver(attrs); } static duplexOption(attrs) { return new DuplexOption(attrs); } static dynamicRender(attrs) { return new DynamicRender(attrs); } static embed(attrs) { return new Embed(attrs); } static encrypt(attrs) { return new config_Encrypt(attrs); } static encryption(attrs) { return new config_Encryption(attrs); } static encryptionLevel(attrs) { return new EncryptionLevel(attrs); } static enforce(attrs) { return new Enforce(attrs); } static equate(attrs) { return new Equate(attrs); } static equateRange(attrs) { return new EquateRange(attrs); } static exclude(attrs) { return new Exclude(attrs); } static excludeNS(attrs) { return new ExcludeNS(attrs); } static flipLabel(attrs) { return new FlipLabel(attrs); } static fontInfo(attrs) { return new config_FontInfo(attrs); } static formFieldFilling(attrs) { return new FormFieldFilling(attrs); } static groupParent(attrs) { return new GroupParent(attrs); } static ifEmpty(attrs) { return new IfEmpty(attrs); } static includeXDPContent(attrs) { return new IncludeXDPContent(attrs); } static incrementalLoad(attrs) { return new IncrementalLoad(attrs); } static incrementalMerge(attrs) { return new IncrementalMerge(attrs); } static interactive(attrs) { return new Interactive(attrs); } static jog(attrs) { return new Jog(attrs); } static labelPrinter(attrs) { return new LabelPrinter(attrs); } static layout(attrs) { return new Layout(attrs); } static level(attrs) { return new Level(attrs); } static linearized(attrs) { return new Linearized(attrs); } static locale(attrs) { return new Locale(attrs); } static localeSet(attrs) { return new LocaleSet(attrs); } static log(attrs) { return new Log(attrs); } static map(attrs) { return new MapElement(attrs); } static mediumInfo(attrs) { return new MediumInfo(attrs); } static message(attrs) { return new config_Message(attrs); } static messaging(attrs) { return new Messaging(attrs); } static mode(attrs) { return new Mode(attrs); } static modifyAnnots(attrs) { return new ModifyAnnots(attrs); } static msgId(attrs) { return new MsgId(attrs); } static nameAttr(attrs) { return new NameAttr(attrs); } static neverEmbed(attrs) { return new NeverEmbed(attrs); } static numberOfCopies(attrs) { return new NumberOfCopies(attrs); } static openAction(attrs) { return new OpenAction(attrs); } static output(attrs) { return new Output(attrs); } static outputBin(attrs) { return new OutputBin(attrs); } static outputXSL(attrs) { return new OutputXSL(attrs); } static overprint(attrs) { return new Overprint(attrs); } static packets(attrs) { return new Packets(attrs); } static pageOffset(attrs) { return new PageOffset(attrs); } static pageRange(attrs) { return new PageRange(attrs); } static pagination(attrs) { return new Pagination(attrs); } static paginationOverride(attrs) { return new PaginationOverride(attrs); } static part(attrs) { return new Part(attrs); } static pcl(attrs) { return new Pcl(attrs); } static pdf(attrs) { return new Pdf(attrs); } static pdfa(attrs) { return new Pdfa(attrs); } static permissions(attrs) { return new Permissions(attrs); } static pickTrayByPDFSize(attrs) { return new PickTrayByPDFSize(attrs); } static picture(attrs) { return new config_Picture(attrs); } static plaintextMetadata(attrs) { return new PlaintextMetadata(attrs); } static presence(attrs) { return new Presence(attrs); } static present(attrs) { return new Present(attrs); } static print(attrs) { return new Print(attrs); } static printHighQuality(attrs) { return new PrintHighQuality(attrs); } static printScaling(attrs) { return new PrintScaling(attrs); } static printerName(attrs) { return new PrinterName(attrs); } static producer(attrs) { return new Producer(attrs); } static ps(attrs) { return new Ps(attrs); } static range(attrs) { return new Range(attrs); } static record(attrs) { return new Record(attrs); } static relevant(attrs) { return new Relevant(attrs); } static rename(attrs) { return new Rename(attrs); } static renderPolicy(attrs) { return new RenderPolicy(attrs); } static runScripts(attrs) { return new RunScripts(attrs); } static script(attrs) { return new config_Script(attrs); } static scriptModel(attrs) { return new ScriptModel(attrs); } static severity(attrs) { return new Severity(attrs); } static silentPrint(attrs) { return new SilentPrint(attrs); } static staple(attrs) { return new Staple(attrs); } static startNode(attrs) { return new StartNode(attrs); } static startPage(attrs) { return new StartPage(attrs); } static submitFormat(attrs) { return new SubmitFormat(attrs); } static submitUrl(attrs) { return new SubmitUrl(attrs); } static subsetBelow(attrs) { return new SubsetBelow(attrs); } static suppressBanner(attrs) { return new SuppressBanner(attrs); } static tagged(attrs) { return new Tagged(attrs); } static template(attrs) { return new config_Template(attrs); } static templateCache(attrs) { return new TemplateCache(attrs); } static threshold(attrs) { return new Threshold(attrs); } static to(attrs) { return new To(attrs); } static trace(attrs) { return new Trace(attrs); } static transform(attrs) { return new Transform(attrs); } static type(attrs) { return new Type(attrs); } static uri(attrs) { return new Uri(attrs); } static validate(attrs) { return new config_Validate(attrs); } static validateApprovalSignatures(attrs) { return new ValidateApprovalSignatures(attrs); } static validationMessaging(attrs) { return new ValidationMessaging(attrs); } static version(attrs) { return new Version(attrs); } static versionControl(attrs) { return new VersionControl(attrs); } static viewerPreferences(attrs) { return new ViewerPreferences(attrs); } static webClient(attrs) { return new WebClient(attrs); } static whitespace(attrs) { return new Whitespace(attrs); } static window(attrs) { return new Window(attrs); } static xdc(attrs) { return new Xdc(attrs); } static xdp(attrs) { return new Xdp(attrs); } static xsl(attrs) { return new Xsl(attrs); } static zpl(attrs) { return new Zpl(attrs); } } ;// CONCATENATED MODULE: ./src/core/xfa/connection_set.js const CONNECTION_SET_NS_ID = NamespaceIds.connectionSet.id; class ConnectionSet extends XFAObject { constructor(attributes) { super(CONNECTION_SET_NS_ID, "connectionSet", true); this.wsdlConnection = new XFAObjectArray(); this.xmlConnection = new XFAObjectArray(); this.xsdConnection = new XFAObjectArray(); } } class EffectiveInputPolicy extends XFAObject { constructor(attributes) { super(CONNECTION_SET_NS_ID, "effectiveInputPolicy"); this.id = attributes.id || ""; this.name = attributes.name || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class EffectiveOutputPolicy extends XFAObject { constructor(attributes) { super(CONNECTION_SET_NS_ID, "effectiveOutputPolicy"); this.id = attributes.id || ""; this.name = attributes.name || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class Operation extends StringObject { constructor(attributes) { super(CONNECTION_SET_NS_ID, "operation"); this.id = attributes.id || ""; this.input = attributes.input || ""; this.name = attributes.name || ""; this.output = attributes.output || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class RootElement extends StringObject { constructor(attributes) { super(CONNECTION_SET_NS_ID, "rootElement"); this.id = attributes.id || ""; this.name = attributes.name || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class SoapAction extends StringObject { constructor(attributes) { super(CONNECTION_SET_NS_ID, "soapAction"); this.id = attributes.id || ""; this.name = attributes.name || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class SoapAddress extends StringObject { constructor(attributes) { super(CONNECTION_SET_NS_ID, "soapAddress"); this.id = attributes.id || ""; this.name = attributes.name || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class connection_set_Uri extends StringObject { constructor(attributes) { super(CONNECTION_SET_NS_ID, "uri"); this.id = attributes.id || ""; this.name = attributes.name || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class WsdlAddress extends StringObject { constructor(attributes) { super(CONNECTION_SET_NS_ID, "wsdlAddress"); this.id = attributes.id || ""; this.name = attributes.name || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class WsdlConnection extends XFAObject { constructor(attributes) { super(CONNECTION_SET_NS_ID, "wsdlConnection", true); this.dataDescription = attributes.dataDescription || ""; this.name = attributes.name || ""; this.effectiveInputPolicy = null; this.effectiveOutputPolicy = null; this.operation = null; this.soapAction = null; this.soapAddress = null; this.wsdlAddress = null; } } class XmlConnection extends XFAObject { constructor(attributes) { super(CONNECTION_SET_NS_ID, "xmlConnection", true); this.dataDescription = attributes.dataDescription || ""; this.name = attributes.name || ""; this.uri = null; } } class XsdConnection extends XFAObject { constructor(attributes) { super(CONNECTION_SET_NS_ID, "xsdConnection", true); this.dataDescription = attributes.dataDescription || ""; this.name = attributes.name || ""; this.rootElement = null; this.uri = null; } } class ConnectionSetNamespace { static [$buildXFAObject](name, attributes) { if (ConnectionSetNamespace.hasOwnProperty(name)) { return ConnectionSetNamespace[name](attributes); } return undefined; } static connectionSet(attrs) { return new ConnectionSet(attrs); } static effectiveInputPolicy(attrs) { return new EffectiveInputPolicy(attrs); } static effectiveOutputPolicy(attrs) { return new EffectiveOutputPolicy(attrs); } static operation(attrs) { return new Operation(attrs); } static rootElement(attrs) { return new RootElement(attrs); } static soapAction(attrs) { return new SoapAction(attrs); } static soapAddress(attrs) { return new SoapAddress(attrs); } static uri(attrs) { return new connection_set_Uri(attrs); } static wsdlAddress(attrs) { return new WsdlAddress(attrs); } static wsdlConnection(attrs) { return new WsdlConnection(attrs); } static xmlConnection(attrs) { return new XmlConnection(attrs); } static xsdConnection(attrs) { return new XsdConnection(attrs); } } ;// CONCATENATED MODULE: ./src/core/xfa/datasets.js const DATASETS_NS_ID = NamespaceIds.datasets.id; class datasets_Data extends XmlObject { constructor(attributes) { super(DATASETS_NS_ID, "data", attributes); } [$isNsAgnostic]() { return true; } } class Datasets extends XFAObject { constructor(attributes) { super(DATASETS_NS_ID, "datasets", true); this.data = null; this.Signature = null; } [$onChild](child) { const name = child[$nodeName]; if (name === "data" && child[$namespaceId] === DATASETS_NS_ID || name === "Signature" && child[$namespaceId] === NamespaceIds.signature.id) { this[name] = child; } this[$appendChild](child); } } class DatasetsNamespace { static [$buildXFAObject](name, attributes) { if (DatasetsNamespace.hasOwnProperty(name)) { return DatasetsNamespace[name](attributes); } return undefined; } static datasets(attributes) { return new Datasets(attributes); } static data(attributes) { return new datasets_Data(attributes); } } ;// CONCATENATED MODULE: ./src/core/xfa/locale_set.js const LOCALE_SET_NS_ID = NamespaceIds.localeSet.id; class CalendarSymbols extends XFAObject { constructor(attributes) { super(LOCALE_SET_NS_ID, "calendarSymbols", true); this.name = "gregorian"; this.dayNames = new XFAObjectArray(2); this.eraNames = null; this.meridiemNames = null; this.monthNames = new XFAObjectArray(2); } } class CurrencySymbol extends StringObject { constructor(attributes) { super(LOCALE_SET_NS_ID, "currencySymbol"); this.name = getStringOption(attributes.name, ["symbol", "isoname", "decimal"]); } } class CurrencySymbols extends XFAObject { constructor(attributes) { super(LOCALE_SET_NS_ID, "currencySymbols", true); this.currencySymbol = new XFAObjectArray(3); } } class DatePattern extends StringObject { constructor(attributes) { super(LOCALE_SET_NS_ID, "datePattern"); this.name = getStringOption(attributes.name, ["full", "long", "med", "short"]); } } class DatePatterns extends XFAObject { constructor(attributes) { super(LOCALE_SET_NS_ID, "datePatterns", true); this.datePattern = new XFAObjectArray(4); } } class DateTimeSymbols extends ContentObject { constructor(attributes) { super(LOCALE_SET_NS_ID, "dateTimeSymbols"); } } class Day extends StringObject { constructor(attributes) { super(LOCALE_SET_NS_ID, "day"); } } class DayNames extends XFAObject { constructor(attributes) { super(LOCALE_SET_NS_ID, "dayNames", true); this.abbr = getInteger({ data: attributes.abbr, defaultValue: 0, validate: x => x === 1 }); this.day = new XFAObjectArray(7); } } class Era extends StringObject { constructor(attributes) { super(LOCALE_SET_NS_ID, "era"); } } class EraNames extends XFAObject { constructor(attributes) { super(LOCALE_SET_NS_ID, "eraNames", true); this.era = new XFAObjectArray(2); } } class locale_set_Locale extends XFAObject { constructor(attributes) { super(LOCALE_SET_NS_ID, "locale", true); this.desc = attributes.desc || ""; this.name = "isoname"; this.calendarSymbols = null; this.currencySymbols = null; this.datePatterns = null; this.dateTimeSymbols = null; this.numberPatterns = null; this.numberSymbols = null; this.timePatterns = null; this.typeFaces = null; } } class locale_set_LocaleSet extends XFAObject { constructor(attributes) { super(LOCALE_SET_NS_ID, "localeSet", true); this.locale = new XFAObjectArray(); } } class Meridiem extends StringObject { constructor(attributes) { super(LOCALE_SET_NS_ID, "meridiem"); } } class MeridiemNames extends XFAObject { constructor(attributes) { super(LOCALE_SET_NS_ID, "meridiemNames", true); this.meridiem = new XFAObjectArray(2); } } class Month extends StringObject { constructor(attributes) { super(LOCALE_SET_NS_ID, "month"); } } class MonthNames extends XFAObject { constructor(attributes) { super(LOCALE_SET_NS_ID, "monthNames", true); this.abbr = getInteger({ data: attributes.abbr, defaultValue: 0, validate: x => x === 1 }); this.month = new XFAObjectArray(12); } } class NumberPattern extends StringObject { constructor(attributes) { super(LOCALE_SET_NS_ID, "numberPattern"); this.name = getStringOption(attributes.name, ["full", "long", "med", "short"]); } } class NumberPatterns extends XFAObject { constructor(attributes) { super(LOCALE_SET_NS_ID, "numberPatterns", true); this.numberPattern = new XFAObjectArray(4); } } class NumberSymbol extends StringObject { constructor(attributes) { super(LOCALE_SET_NS_ID, "numberSymbol"); this.name = getStringOption(attributes.name, ["decimal", "grouping", "percent", "minus", "zero"]); } } class NumberSymbols extends XFAObject { constructor(attributes) { super(LOCALE_SET_NS_ID, "numberSymbols", true); this.numberSymbol = new XFAObjectArray(5); } } class TimePattern extends StringObject { constructor(attributes) { super(LOCALE_SET_NS_ID, "timePattern"); this.name = getStringOption(attributes.name, ["full", "long", "med", "short"]); } } class TimePatterns extends XFAObject { constructor(attributes) { super(LOCALE_SET_NS_ID, "timePatterns", true); this.timePattern = new XFAObjectArray(4); } } class TypeFace extends XFAObject { constructor(attributes) { super(LOCALE_SET_NS_ID, "typeFace", true); this.name = attributes.name | ""; } } class TypeFaces extends XFAObject { constructor(attributes) { super(LOCALE_SET_NS_ID, "typeFaces", true); this.typeFace = new XFAObjectArray(); } } class LocaleSetNamespace { static [$buildXFAObject](name, attributes) { if (LocaleSetNamespace.hasOwnProperty(name)) { return LocaleSetNamespace[name](attributes); } return undefined; } static calendarSymbols(attrs) { return new CalendarSymbols(attrs); } static currencySymbol(attrs) { return new CurrencySymbol(attrs); } static currencySymbols(attrs) { return new CurrencySymbols(attrs); } static datePattern(attrs) { return new DatePattern(attrs); } static datePatterns(attrs) { return new DatePatterns(attrs); } static dateTimeSymbols(attrs) { return new DateTimeSymbols(attrs); } static day(attrs) { return new Day(attrs); } static dayNames(attrs) { return new DayNames(attrs); } static era(attrs) { return new Era(attrs); } static eraNames(attrs) { return new EraNames(attrs); } static locale(attrs) { return new locale_set_Locale(attrs); } static localeSet(attrs) { return new locale_set_LocaleSet(attrs); } static meridiem(attrs) { return new Meridiem(attrs); } static meridiemNames(attrs) { return new MeridiemNames(attrs); } static month(attrs) { return new Month(attrs); } static monthNames(attrs) { return new MonthNames(attrs); } static numberPattern(attrs) { return new NumberPattern(attrs); } static numberPatterns(attrs) { return new NumberPatterns(attrs); } static numberSymbol(attrs) { return new NumberSymbol(attrs); } static numberSymbols(attrs) { return new NumberSymbols(attrs); } static timePattern(attrs) { return new TimePattern(attrs); } static timePatterns(attrs) { return new TimePatterns(attrs); } static typeFace(attrs) { return new TypeFace(attrs); } static typeFaces(attrs) { return new TypeFaces(attrs); } } ;// CONCATENATED MODULE: ./src/core/xfa/signature.js const SIGNATURE_NS_ID = NamespaceIds.signature.id; class signature_Signature extends XFAObject { constructor(attributes) { super(SIGNATURE_NS_ID, "signature", true); } } class SignatureNamespace { static [$buildXFAObject](name, attributes) { if (SignatureNamespace.hasOwnProperty(name)) { return SignatureNamespace[name](attributes); } return undefined; } static signature(attributes) { return new signature_Signature(attributes); } } ;// CONCATENATED MODULE: ./src/core/xfa/stylesheet.js const STYLESHEET_NS_ID = NamespaceIds.stylesheet.id; class Stylesheet extends XFAObject { constructor(attributes) { super(STYLESHEET_NS_ID, "stylesheet", true); } } class StylesheetNamespace { static [$buildXFAObject](name, attributes) { if (StylesheetNamespace.hasOwnProperty(name)) { return StylesheetNamespace[name](attributes); } return undefined; } static stylesheet(attributes) { return new Stylesheet(attributes); } } ;// CONCATENATED MODULE: ./src/core/xfa/xdp.js const XDP_NS_ID = NamespaceIds.xdp.id; class xdp_Xdp extends XFAObject { constructor(attributes) { super(XDP_NS_ID, "xdp", true); this.uuid = attributes.uuid || ""; this.timeStamp = attributes.timeStamp || ""; this.config = null; this.connectionSet = null; this.datasets = null; this.localeSet = null; this.stylesheet = new XFAObjectArray(); this.template = null; } [$onChildCheck](child) { const ns = NamespaceIds[child[$nodeName]]; return ns && child[$namespaceId] === ns.id; } } class XdpNamespace { static [$buildXFAObject](name, attributes) { if (XdpNamespace.hasOwnProperty(name)) { return XdpNamespace[name](attributes); } return undefined; } static xdp(attributes) { return new xdp_Xdp(attributes); } } ;// CONCATENATED MODULE: ./src/core/xfa/xhtml.js const XHTML_NS_ID = NamespaceIds.xhtml.id; const $richText = Symbol(); const VALID_STYLES = new Set(["color", "font", "font-family", "font-size", "font-stretch", "font-style", "font-weight", "margin", "margin-bottom", "margin-left", "margin-right", "margin-top", "letter-spacing", "line-height", "orphans", "page-break-after", "page-break-before", "page-break-inside", "tab-interval", "tab-stop", "text-align", "text-decoration", "text-indent", "vertical-align", "widows", "kerning-mode", "xfa-font-horizontal-scale", "xfa-font-vertical-scale", "xfa-spacerun", "xfa-tab-stops"]); const StyleMapping = new Map([["page-break-after", "breakAfter"], ["page-break-before", "breakBefore"], ["page-break-inside", "breakInside"], ["kerning-mode", value => value === "none" ? "none" : "normal"], ["xfa-font-horizontal-scale", value => `scaleX(${Math.max(0, Math.min(parseInt(value) / 100)).toFixed(2)})`], ["xfa-font-vertical-scale", value => `scaleY(${Math.max(0, Math.min(parseInt(value) / 100)).toFixed(2)})`], ["xfa-spacerun", ""], ["xfa-tab-stops", ""], ["font-size", (value, original) => { value = original.fontSize = getMeasurement(value); return measureToString(0.99 * value); }], ["letter-spacing", value => measureToString(getMeasurement(value))], ["line-height", value => measureToString(getMeasurement(value))], ["margin", value => measureToString(getMeasurement(value))], ["margin-bottom", value => measureToString(getMeasurement(value))], ["margin-left", value => measureToString(getMeasurement(value))], ["margin-right", value => measureToString(getMeasurement(value))], ["margin-top", value => measureToString(getMeasurement(value))], ["text-indent", value => measureToString(getMeasurement(value))], ["font-family", value => value], ["vertical-align", value => measureToString(getMeasurement(value))]]); const spacesRegExp = /\s+/g; const crlfRegExp = /[\r\n]+/g; const crlfForRichTextRegExp = /\r\n?/g; function mapStyle(styleStr, node, richText) { const style = Object.create(null); if (!styleStr) { return style; } const original = Object.create(null); for (const [key, value] of styleStr.split(";").map(s => s.split(":", 2))) { const mapping = StyleMapping.get(key); if (mapping === "") { continue; } let newValue = value; if (mapping) { newValue = typeof mapping === "string" ? mapping : mapping(value, original); } if (key.endsWith("scale")) { style.transform = style.transform ? `${style[key]} ${newValue}` : newValue; } else { style[key.replaceAll(/-([a-zA-Z])/g, (_, x) => x.toUpperCase())] = newValue; } } if (style.fontFamily) { setFontFamily({ typeface: style.fontFamily, weight: style.fontWeight || "normal", posture: style.fontStyle || "normal", size: original.fontSize || 0 }, node, node[$globalData].fontFinder, style); } if (richText && style.verticalAlign && style.verticalAlign !== "0px" && style.fontSize) { const SUB_SUPER_SCRIPT_FACTOR = 0.583; const VERTICAL_FACTOR = 0.333; const fontSize = getMeasurement(style.fontSize); style.fontSize = measureToString(fontSize * SUB_SUPER_SCRIPT_FACTOR); style.verticalAlign = measureToString(Math.sign(getMeasurement(style.verticalAlign)) * fontSize * VERTICAL_FACTOR); } if (richText && style.fontSize) { style.fontSize = `calc(${style.fontSize} * var(--scale-factor))`; } fixTextIndent(style); return style; } function checkStyle(node) { if (!node.style) { return ""; } return node.style.trim().split(/\s*;\s*/).filter(s => !!s).map(s => s.split(/\s*:\s*/, 2)).filter(([key, value]) => { if (key === "font-family") { node[$globalData].usedTypefaces.add(value); } return VALID_STYLES.has(key); }).map(kv => kv.join(":")).join(";"); } const NoWhites = new Set(["body", "html"]); class XhtmlObject extends XmlObject { constructor(attributes, name) { super(XHTML_NS_ID, name); this[$richText] = false; this.style = attributes.style || ""; } [$clean](builder) { super[$clean](builder); this.style = checkStyle(this); } [$acceptWhitespace]() { return !NoWhites.has(this[$nodeName]); } [$onText](str, richText = false) { if (!richText) { str = str.replaceAll(crlfRegExp, ""); if (!this.style.includes("xfa-spacerun:yes")) { str = str.replaceAll(spacesRegExp, " "); } } else { this[$richText] = true; } if (str) { this[$content] += str; } } [$pushGlyphs](measure, mustPop = true) { const xfaFont = Object.create(null); const margin = { top: NaN, bottom: NaN, left: NaN, right: NaN }; let lineHeight = null; for (const [key, value] of this.style.split(";").map(s => s.split(":", 2))) { switch (key) { case "font-family": xfaFont.typeface = stripQuotes(value); break; case "font-size": xfaFont.size = getMeasurement(value); break; case "font-weight": xfaFont.weight = value; break; case "font-style": xfaFont.posture = value; break; case "letter-spacing": xfaFont.letterSpacing = getMeasurement(value); break; case "margin": const values = value.split(/ \t/).map(x => getMeasurement(x)); switch (values.length) { case 1: margin.top = margin.bottom = margin.left = margin.right = values[0]; break; case 2: margin.top = margin.bottom = values[0]; margin.left = margin.right = values[1]; break; case 3: margin.top = values[0]; margin.bottom = values[2]; margin.left = margin.right = values[1]; break; case 4: margin.top = values[0]; margin.left = values[1]; margin.bottom = values[2]; margin.right = values[3]; break; } break; case "margin-top": margin.top = getMeasurement(value); break; case "margin-bottom": margin.bottom = getMeasurement(value); break; case "margin-left": margin.left = getMeasurement(value); break; case "margin-right": margin.right = getMeasurement(value); break; case "line-height": lineHeight = getMeasurement(value); break; } } measure.pushData(xfaFont, margin, lineHeight); if (this[$content]) { measure.addString(this[$content]); } else { for (const child of this[$getChildren]()) { if (child[$nodeName] === "#text") { measure.addString(child[$content]); continue; } child[$pushGlyphs](measure); } } if (mustPop) { measure.popFont(); } } [$toHTML](availableSpace) { const children = []; this[$extra] = { children }; this[$childrenToHTML]({}); if (children.length === 0 && !this[$content]) { return HTMLResult.EMPTY; } let value; if (this[$richText]) { value = this[$content] ? this[$content].replaceAll(crlfForRichTextRegExp, "\n") : undefined; } else { value = this[$content] || undefined; } return HTMLResult.success({ name: this[$nodeName], attributes: { href: this.href, style: mapStyle(this.style, this, this[$richText]) }, children, value }); } } class A extends XhtmlObject { constructor(attributes) { super(attributes, "a"); this.href = fixURL(attributes.href) || ""; } } class B extends XhtmlObject { constructor(attributes) { super(attributes, "b"); } [$pushGlyphs](measure) { measure.pushFont({ weight: "bold" }); super[$pushGlyphs](measure); measure.popFont(); } } class Body extends XhtmlObject { constructor(attributes) { super(attributes, "body"); } [$toHTML](availableSpace) { const res = super[$toHTML](availableSpace); const { html } = res; if (!html) { return HTMLResult.EMPTY; } html.name = "div"; html.attributes.class = ["xfaRich"]; return res; } } class Br extends XhtmlObject { constructor(attributes) { super(attributes, "br"); } [$text]() { return "\n"; } [$pushGlyphs](measure) { measure.addString("\n"); } [$toHTML](availableSpace) { return HTMLResult.success({ name: "br" }); } } class Html extends XhtmlObject { constructor(attributes) { super(attributes, "html"); } [$toHTML](availableSpace) { const children = []; this[$extra] = { children }; this[$childrenToHTML]({}); if (children.length === 0) { return HTMLResult.success({ name: "div", attributes: { class: ["xfaRich"], style: {} }, value: this[$content] || "" }); } if (children.length === 1) { const child = children[0]; if (child.attributes?.class.includes("xfaRich")) { return HTMLResult.success(child); } } return HTMLResult.success({ name: "div", attributes: { class: ["xfaRich"], style: {} }, children }); } } class I extends XhtmlObject { constructor(attributes) { super(attributes, "i"); } [$pushGlyphs](measure) { measure.pushFont({ posture: "italic" }); super[$pushGlyphs](measure); measure.popFont(); } } class Li extends XhtmlObject { constructor(attributes) { super(attributes, "li"); } } class Ol extends XhtmlObject { constructor(attributes) { super(attributes, "ol"); } } class P extends XhtmlObject { constructor(attributes) { super(attributes, "p"); } [$pushGlyphs](measure) { super[$pushGlyphs](measure, false); measure.addString("\n"); measure.addPara(); measure.popFont(); } [$text]() { const siblings = this[$getParent]()[$getChildren](); if (siblings.at(-1) === this) { return super[$text](); } return super[$text]() + "\n"; } } class Span extends XhtmlObject { constructor(attributes) { super(attributes, "span"); } } class Sub extends XhtmlObject { constructor(attributes) { super(attributes, "sub"); } } class Sup extends XhtmlObject { constructor(attributes) { super(attributes, "sup"); } } class Ul extends XhtmlObject { constructor(attributes) { super(attributes, "ul"); } } class XhtmlNamespace { static [$buildXFAObject](name, attributes) { if (XhtmlNamespace.hasOwnProperty(name)) { return XhtmlNamespace[name](attributes); } return undefined; } static a(attributes) { return new A(attributes); } static b(attributes) { return new B(attributes); } static body(attributes) { return new Body(attributes); } static br(attributes) { return new Br(attributes); } static html(attributes) { return new Html(attributes); } static i(attributes) { return new I(attributes); } static li(attributes) { return new Li(attributes); } static ol(attributes) { return new Ol(attributes); } static p(attributes) { return new P(attributes); } static span(attributes) { return new Span(attributes); } static sub(attributes) { return new Sub(attributes); } static sup(attributes) { return new Sup(attributes); } static ul(attributes) { return new Ul(attributes); } } ;// CONCATENATED MODULE: ./src/core/xfa/setup.js const NamespaceSetUp = { config: ConfigNamespace, connection: ConnectionSetNamespace, datasets: DatasetsNamespace, localeSet: LocaleSetNamespace, signature: SignatureNamespace, stylesheet: StylesheetNamespace, template: TemplateNamespace, xdp: XdpNamespace, xhtml: XhtmlNamespace }; ;// CONCATENATED MODULE: ./src/core/xfa/unknown.js class UnknownNamespace { constructor(nsId) { this.namespaceId = nsId; } [$buildXFAObject](name, attributes) { return new XmlObject(this.namespaceId, name, attributes); } } ;// CONCATENATED MODULE: ./src/core/xfa/builder.js class Root extends XFAObject { constructor(ids) { super(-1, "root", Object.create(null)); this.element = null; this[$ids] = ids; } [$onChild](child) { this.element = child; return true; } [$finalize]() { super[$finalize](); if (this.element.template instanceof Template) { this[$ids].set($root, this.element); this.element.template[$resolvePrototypes](this[$ids]); this.element.template[$ids] = this[$ids]; } } } class Empty extends XFAObject { constructor() { super(-1, "", Object.create(null)); } [$onChild](_) { return false; } } class Builder { constructor(rootNameSpace = null) { this._namespaceStack = []; this._nsAgnosticLevel = 0; this._namespacePrefixes = new Map(); this._namespaces = new Map(); this._nextNsId = Math.max(...Object.values(NamespaceIds).map(({ id }) => id)); this._currentNamespace = rootNameSpace || new UnknownNamespace(++this._nextNsId); } buildRoot(ids) { return new Root(ids); } build({ nsPrefix, name, attributes, namespace, prefixes }) { const hasNamespaceDef = namespace !== null; if (hasNamespaceDef) { this._namespaceStack.push(this._currentNamespace); this._currentNamespace = this._searchNamespace(namespace); } if (prefixes) { this._addNamespacePrefix(prefixes); } if (attributes.hasOwnProperty($nsAttributes)) { const dataTemplate = NamespaceSetUp.datasets; const nsAttrs = attributes[$nsAttributes]; let xfaAttrs = null; for (const [ns, attrs] of Object.entries(nsAttrs)) { const nsToUse = this._getNamespaceToUse(ns); if (nsToUse === dataTemplate) { xfaAttrs = { xfa: attrs }; break; } } if (xfaAttrs) { attributes[$nsAttributes] = xfaAttrs; } else { delete attributes[$nsAttributes]; } } const namespaceToUse = this._getNamespaceToUse(nsPrefix); const node = namespaceToUse?.[$buildXFAObject](name, attributes) || new Empty(); if (node[$isNsAgnostic]()) { this._nsAgnosticLevel++; } if (hasNamespaceDef || prefixes || node[$isNsAgnostic]()) { node[$cleanup] = { hasNamespace: hasNamespaceDef, prefixes, nsAgnostic: node[$isNsAgnostic]() }; } return node; } isNsAgnostic() { return this._nsAgnosticLevel > 0; } _searchNamespace(nsName) { let ns = this._namespaces.get(nsName); if (ns) { return ns; } for (const [name, { check }] of Object.entries(NamespaceIds)) { if (check(nsName)) { ns = NamespaceSetUp[name]; if (ns) { this._namespaces.set(nsName, ns); return ns; } break; } } ns = new UnknownNamespace(++this._nextNsId); this._namespaces.set(nsName, ns); return ns; } _addNamespacePrefix(prefixes) { for (const { prefix, value } of prefixes) { const namespace = this._searchNamespace(value); let prefixStack = this._namespacePrefixes.get(prefix); if (!prefixStack) { prefixStack = []; this._namespacePrefixes.set(prefix, prefixStack); } prefixStack.push(namespace); } } _getNamespaceToUse(prefix) { if (!prefix) { return this._currentNamespace; } const prefixStack = this._namespacePrefixes.get(prefix); if (prefixStack?.length > 0) { return prefixStack.at(-1); } warn(`Unknown namespace prefix: ${prefix}.`); return null; } clean(data) { const { hasNamespace, prefixes, nsAgnostic } = data; if (hasNamespace) { this._currentNamespace = this._namespaceStack.pop(); } if (prefixes) { prefixes.forEach(({ prefix }) => { this._namespacePrefixes.get(prefix).pop(); }); } if (nsAgnostic) { this._nsAgnosticLevel--; } } } ;// CONCATENATED MODULE: ./src/core/xfa/parser.js class XFAParser extends XMLParserBase { constructor(rootNameSpace = null, richText = false) { super(); this._builder = new Builder(rootNameSpace); this._stack = []; this._globalData = { usedTypefaces: new Set() }; this._ids = new Map(); this._current = this._builder.buildRoot(this._ids); this._errorCode = XMLParserErrorCode.NoError; this._whiteRegex = /^\s+$/; this._nbsps = /\xa0+/g; this._richText = richText; } parse(data) { this.parseXml(data); if (this._errorCode !== XMLParserErrorCode.NoError) { return undefined; } this._current[$finalize](); return this._current.element; } onText(text) { text = text.replace(this._nbsps, match => match.slice(1) + " "); if (this._richText || this._current[$acceptWhitespace]()) { this._current[$onText](text, this._richText); return; } if (this._whiteRegex.test(text)) { return; } this._current[$onText](text.trim()); } onCdata(text) { this._current[$onText](text); } _mkAttributes(attributes, tagName) { let namespace = null; let prefixes = null; const attributeObj = Object.create({}); for (const { name, value } of attributes) { if (name === "xmlns") { if (!namespace) { namespace = value; } else { warn(`XFA - multiple namespace definition in <${tagName}>`); } } else if (name.startsWith("xmlns:")) { const prefix = name.substring("xmlns:".length); if (!prefixes) { prefixes = []; } prefixes.push({ prefix, value }); } else { const i = name.indexOf(":"); if (i === -1) { attributeObj[name] = value; } else { let nsAttrs = attributeObj[$nsAttributes]; if (!nsAttrs) { nsAttrs = attributeObj[$nsAttributes] = Object.create(null); } const [ns, attrName] = [name.slice(0, i), name.slice(i + 1)]; const attrs = nsAttrs[ns] ||= Object.create(null); attrs[attrName] = value; } } } return [namespace, prefixes, attributeObj]; } _getNameAndPrefix(name, nsAgnostic) { const i = name.indexOf(":"); if (i === -1) { return [name, null]; } return [name.substring(i + 1), nsAgnostic ? "" : name.substring(0, i)]; } onBeginElement(tagName, attributes, isEmpty) { const [namespace, prefixes, attributesObj] = this._mkAttributes(attributes, tagName); const [name, nsPrefix] = this._getNameAndPrefix(tagName, this._builder.isNsAgnostic()); const node = this._builder.build({ nsPrefix, name, attributes: attributesObj, namespace, prefixes }); node[$globalData] = this._globalData; if (isEmpty) { node[$finalize](); if (this._current[$onChild](node)) { node[$setId](this._ids); } node[$clean](this._builder); return; } this._stack.push(this._current); this._current = node; } onEndElement(name) { const node = this._current; if (node[$isCDATAXml]() && typeof node[$content] === "string") { const parser = new XFAParser(); parser._globalData = this._globalData; const root = parser.parse(node[$content]); node[$content] = null; node[$onChild](root); } node[$finalize](); this._current = this._stack.pop(); if (this._current[$onChild](node)) { node[$setId](this._ids); } node[$clean](this._builder); } onError(code) { this._errorCode = code; } } ;// CONCATENATED MODULE: ./src/core/xfa/factory.js class XFAFactory { constructor(data) { try { this.root = new XFAParser().parse(XFAFactory._createDocument(data)); const binder = new Binder(this.root); this.form = binder.bind(); this.dataHandler = new DataHandler(this.root, binder.getData()); this.form[$globalData].template = this.form; } catch (e) { warn(`XFA - an error occurred during parsing and binding: ${e}`); } } isValid() { return this.root && this.form; } _createPagesHelper() { const iterator = this.form[$toPages](); return new Promise((resolve, reject) => { const nextIteration = () => { try { const value = iterator.next(); if (value.done) { resolve(value.value); } else { setTimeout(nextIteration, 0); } } catch (e) { reject(e); } }; setTimeout(nextIteration, 0); }); } async _createPages() { try { this.pages = await this._createPagesHelper(); this.dims = this.pages.children.map(c => { const { width, height } = c.attributes.style; return [0, 0, parseInt(width), parseInt(height)]; }); } catch (e) { warn(`XFA - an error occurred during layout: ${e}`); } } getBoundingBox(pageIndex) { return this.dims[pageIndex]; } async getNumPages() { if (!this.pages) { await this._createPages(); } return this.dims.length; } setImages(images) { this.form[$globalData].images = images; } setFonts(fonts) { this.form[$globalData].fontFinder = new FontFinder(fonts); const missingFonts = []; for (let typeface of this.form[$globalData].usedTypefaces) { typeface = stripQuotes(typeface); const font = this.form[$globalData].fontFinder.find(typeface); if (!font) { missingFonts.push(typeface); } } if (missingFonts.length > 0) { return missingFonts; } return null; } appendFonts(fonts, reallyMissingFonts) { this.form[$globalData].fontFinder.add(fonts, reallyMissingFonts); } async getPages() { if (!this.pages) { await this._createPages(); } const pages = this.pages; this.pages = null; return pages; } serializeData(storage) { return this.dataHandler.serialize(storage); } static _createDocument(data) { if (!data["/xdp:xdp"]) { return data["xdp:xdp"]; } return Object.values(data).join(""); } static getRichTextAsHtml(rc) { if (!rc || typeof rc !== "string") { return null; } try { let root = new XFAParser(XhtmlNamespace, true).parse(rc); if (!["body", "xhtml"].includes(root[$nodeName])) { const newRoot = XhtmlNamespace.body({}); newRoot[$appendChild](root); root = newRoot; } const result = root[$toHTML](); if (!result.success) { return null; } const { html } = result; const { attributes } = html; if (attributes) { if (attributes.class) { attributes.class = attributes.class.filter(attr => !attr.startsWith("xfa")); } attributes.dir = "auto"; } return { html, str: root[$text]() }; } catch (e) { warn(`XFA - an error occurred during parsing of rich text: ${e}`); } return null; } } ;// CONCATENATED MODULE: ./src/core/annotation.js class AnnotationFactory { static createGlobals(pdfManager) { return Promise.all([pdfManager.ensureCatalog("acroForm"), pdfManager.ensureDoc("xfaDatasets"), pdfManager.ensureCatalog("structTreeRoot"), pdfManager.ensureCatalog("baseUrl"), pdfManager.ensureCatalog("attachments")]).then(([acroForm, xfaDatasets, structTreeRoot, baseUrl, attachments]) => { return { pdfManager, acroForm: acroForm instanceof Dict ? acroForm : Dict.empty, xfaDatasets, structTreeRoot, baseUrl, attachments }; }, reason => { warn(`createGlobals: "${reason}".`); return null; }); } static async create(xref, ref, annotationGlobals, idFactory, collectFields, pageRef) { const pageIndex = collectFields ? await this._getPageIndex(xref, ref, annotationGlobals.pdfManager) : null; return annotationGlobals.pdfManager.ensure(this, "_create", [xref, ref, annotationGlobals, idFactory, collectFields, pageIndex, pageRef]); } static _create(xref, ref, annotationGlobals, idFactory, collectFields = false, pageIndex = null, pageRef = null) { const dict = xref.fetchIfRef(ref); if (!(dict instanceof Dict)) { return undefined; } const { acroForm, pdfManager } = annotationGlobals; const id = ref instanceof Ref ? ref.toString() : `annot_${idFactory.createObjId()}`; let subtype = dict.get("Subtype"); subtype = subtype instanceof Name ? subtype.name : null; const parameters = { xref, ref, dict, subtype, id, annotationGlobals, collectFields, needAppearances: !collectFields && acroForm.get("NeedAppearances") === true, pageIndex, evaluatorOptions: pdfManager.evaluatorOptions, pageRef }; switch (subtype) { case "Link": return new LinkAnnotation(parameters); case "Text": return new TextAnnotation(parameters); case "Widget": let fieldType = getInheritableProperty({ dict, key: "FT" }); fieldType = fieldType instanceof Name ? fieldType.name : null; switch (fieldType) { case "Tx": return new TextWidgetAnnotation(parameters); case "Btn": return new ButtonWidgetAnnotation(parameters); case "Ch": return new ChoiceWidgetAnnotation(parameters); case "Sig": return new SignatureWidgetAnnotation(parameters); } warn(`Unimplemented widget field type "${fieldType}", ` + "falling back to base field type."); return new WidgetAnnotation(parameters); case "Popup": return new PopupAnnotation(parameters); case "FreeText": return new FreeTextAnnotation(parameters); case "Line": return new LineAnnotation(parameters); case "Square": return new SquareAnnotation(parameters); case "Circle": return new CircleAnnotation(parameters); case "PolyLine": return new PolylineAnnotation(parameters); case "Polygon": return new PolygonAnnotation(parameters); case "Caret": return new CaretAnnotation(parameters); case "Ink": return new InkAnnotation(parameters); case "Highlight": return new HighlightAnnotation(parameters); case "Underline": return new UnderlineAnnotation(parameters); case "Squiggly": return new SquigglyAnnotation(parameters); case "StrikeOut": return new StrikeOutAnnotation(parameters); case "Stamp": return new StampAnnotation(parameters); case "FileAttachment": return new FileAttachmentAnnotation(parameters); default: if (!collectFields) { if (!subtype) { warn("Annotation is missing the required /Subtype."); } else { warn(`Unimplemented annotation type "${subtype}", ` + "falling back to base annotation."); } } return new Annotation(parameters); } } static async _getPageIndex(xref, ref, pdfManager) { try { const annotDict = await xref.fetchIfRefAsync(ref); if (!(annotDict instanceof Dict)) { return -1; } const pageRef = annotDict.getRaw("P"); if (pageRef instanceof Ref) { try { const pageIndex = await pdfManager.ensureCatalog("getPageIndex", [pageRef]); return pageIndex; } catch (ex) { info(`_getPageIndex -- not a valid page reference: "${ex}".`); } } if (annotDict.has("Kids")) { return -1; } const numPages = await pdfManager.ensureDoc("numPages"); for (let pageIndex = 0; pageIndex < numPages; pageIndex++) { const page = await pdfManager.getPage(pageIndex); const annotations = await pdfManager.ensure(page, "annotations"); for (const annotRef of annotations) { if (annotRef instanceof Ref && isRefsEqual(annotRef, ref)) { return pageIndex; } } } } catch (ex) { warn(`_getPageIndex: "${ex}".`); } return -1; } static generateImages(annotations, xref, isOffscreenCanvasSupported) { if (!isOffscreenCanvasSupported) { warn("generateImages: OffscreenCanvas is not supported, cannot save or print some annotations with images."); return null; } let imagePromises; for (const { bitmapId, bitmap } of annotations) { if (!bitmap) { continue; } imagePromises ||= new Map(); imagePromises.set(bitmapId, StampAnnotation.createImage(bitmap, xref)); } return imagePromises; } static async saveNewAnnotations(evaluator, task, annotations, imagePromises) { const xref = evaluator.xref; let baseFontRef; const dependencies = []; const promises = []; const { isOffscreenCanvasSupported } = evaluator.options; for (const annotation of annotations) { if (annotation.deleted) { continue; } switch (annotation.annotationType) { case AnnotationEditorType.FREETEXT: if (!baseFontRef) { const baseFont = new Dict(xref); baseFont.set("BaseFont", Name.get("Helvetica")); baseFont.set("Type", Name.get("Font")); baseFont.set("Subtype", Name.get("Type1")); baseFont.set("Encoding", Name.get("WinAnsiEncoding")); const buffer = []; baseFontRef = xref.getNewTemporaryRef(); await writeObject(baseFontRef, baseFont, buffer, xref); dependencies.push({ ref: baseFontRef, data: buffer.join("") }); } promises.push(FreeTextAnnotation.createNewAnnotation(xref, annotation, dependencies, { evaluator, task, baseFontRef })); break; case AnnotationEditorType.HIGHLIGHT: if (annotation.quadPoints) { promises.push(HighlightAnnotation.createNewAnnotation(xref, annotation, dependencies)); } else { promises.push(InkAnnotation.createNewAnnotation(xref, annotation, dependencies)); } break; case AnnotationEditorType.INK: promises.push(InkAnnotation.createNewAnnotation(xref, annotation, dependencies)); break; case AnnotationEditorType.STAMP: if (!isOffscreenCanvasSupported) { break; } const image = await imagePromises.get(annotation.bitmapId); if (image.imageStream) { const { imageStream, smaskStream } = image; const buffer = []; if (smaskStream) { const smaskRef = xref.getNewTemporaryRef(); await writeObject(smaskRef, smaskStream, buffer, xref); dependencies.push({ ref: smaskRef, data: buffer.join("") }); imageStream.dict.set("SMask", smaskRef); buffer.length = 0; } const imageRef = image.imageRef = xref.getNewTemporaryRef(); await writeObject(imageRef, imageStream, buffer, xref); dependencies.push({ ref: imageRef, data: buffer.join("") }); image.imageStream = image.smaskStream = null; } promises.push(StampAnnotation.createNewAnnotation(xref, annotation, dependencies, { image })); break; } } return { annotations: await Promise.all(promises), dependencies }; } static async printNewAnnotations(annotationGlobals, evaluator, task, annotations, imagePromises) { if (!annotations) { return null; } const { options, xref } = evaluator; const promises = []; for (const annotation of annotations) { if (annotation.deleted) { continue; } switch (annotation.annotationType) { case AnnotationEditorType.FREETEXT: promises.push(FreeTextAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, { evaluator, task, evaluatorOptions: options })); break; case AnnotationEditorType.HIGHLIGHT: if (annotation.quadPoints) { promises.push(HighlightAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, { evaluatorOptions: options })); } else { promises.push(InkAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, { evaluatorOptions: options })); } break; case AnnotationEditorType.INK: promises.push(InkAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, { evaluatorOptions: options })); break; case AnnotationEditorType.STAMP: if (!options.isOffscreenCanvasSupported) { break; } const image = await imagePromises.get(annotation.bitmapId); if (image.imageStream) { const { imageStream, smaskStream } = image; if (smaskStream) { imageStream.dict.set("SMask", smaskStream); } image.imageRef = new JpegStream(imageStream, imageStream.length); image.imageStream = image.smaskStream = null; } promises.push(StampAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, { image, evaluatorOptions: options })); break; } } return Promise.all(promises); } } function getRgbColor(color, defaultColor = new Uint8ClampedArray(3)) { if (!Array.isArray(color)) { return defaultColor; } const rgbColor = defaultColor || new Uint8ClampedArray(3); switch (color.length) { case 0: return null; case 1: ColorSpace.singletons.gray.getRgbItem(color, 0, rgbColor, 0); return rgbColor; case 3: ColorSpace.singletons.rgb.getRgbItem(color, 0, rgbColor, 0); return rgbColor; case 4: ColorSpace.singletons.cmyk.getRgbItem(color, 0, rgbColor, 0); return rgbColor; default: return defaultColor; } } function getPdfColorArray(color) { return Array.from(color, c => c / 255); } function getQuadPoints(dict, rect) { const quadPoints = dict.getArray("QuadPoints"); if (!isNumberArray(quadPoints, null) || quadPoints.length === 0 || quadPoints.length % 8 > 0) { return null; } const quadPointsLists = []; for (let i = 0, ii = quadPoints.length / 8; i < ii; i++) { let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity; for (let j = i * 8, jj = i * 8 + 8; j < jj; j += 2) { const x = quadPoints[j]; const y = quadPoints[j + 1]; minX = Math.min(x, minX); maxX = Math.max(x, maxX); minY = Math.min(y, minY); maxY = Math.max(y, maxY); } if (rect !== null && (minX < rect[0] || maxX > rect[2] || minY < rect[1] || maxY > rect[3])) { return null; } quadPointsLists.push([{ x: minX, y: maxY }, { x: maxX, y: maxY }, { x: minX, y: minY }, { x: maxX, y: minY }]); } return quadPointsLists; } function getTransformMatrix(rect, bbox, matrix) { const [minX, minY, maxX, maxY] = Util.getAxialAlignedBoundingBox(bbox, matrix); if (minX === maxX || minY === maxY) { return [1, 0, 0, 1, rect[0], rect[1]]; } const xRatio = (rect[2] - rect[0]) / (maxX - minX); const yRatio = (rect[3] - rect[1]) / (maxY - minY); return [xRatio, 0, 0, yRatio, rect[0] - minX * xRatio, rect[1] - minY * yRatio]; } class Annotation { constructor(params) { const { dict, xref, annotationGlobals } = params; this.setTitle(dict.get("T")); this.setContents(dict.get("Contents")); this.setModificationDate(dict.get("M")); this.setFlags(dict.get("F")); this.setRectangle(dict.getArray("Rect")); this.setColor(dict.getArray("C")); this.setBorderStyle(dict); this.setAppearance(dict); this.setOptionalContent(dict); const MK = dict.get("MK"); this.setBorderAndBackgroundColors(MK); this.setRotation(MK, dict); this.ref = params.ref instanceof Ref ? params.ref : null; this._streams = []; if (this.appearance) { this._streams.push(this.appearance); } const isLocked = !!(this.flags & AnnotationFlag.LOCKED); const isContentLocked = !!(this.flags & AnnotationFlag.LOCKEDCONTENTS); if (annotationGlobals.structTreeRoot) { let structParent = dict.get("StructParent"); structParent = Number.isInteger(structParent) && structParent >= 0 ? structParent : -1; annotationGlobals.structTreeRoot.addAnnotationIdToPage(params.pageRef, structParent); } this.data = { annotationFlags: this.flags, borderStyle: this.borderStyle, color: this.color, backgroundColor: this.backgroundColor, borderColor: this.borderColor, rotation: this.rotation, contentsObj: this._contents, hasAppearance: !!this.appearance, id: params.id, modificationDate: this.modificationDate, rect: this.rectangle, subtype: params.subtype, hasOwnCanvas: false, noRotate: !!(this.flags & AnnotationFlag.NOROTATE), noHTML: isLocked && isContentLocked }; if (params.collectFields) { const kids = dict.get("Kids"); if (Array.isArray(kids)) { const kidIds = []; for (const kid of kids) { if (kid instanceof Ref) { kidIds.push(kid.toString()); } } if (kidIds.length !== 0) { this.data.kidIds = kidIds; } } this.data.actions = collectActions(xref, dict, AnnotationActionEventType); this.data.fieldName = this._constructFieldName(dict); this.data.pageIndex = params.pageIndex; } this._isOffscreenCanvasSupported = params.evaluatorOptions.isOffscreenCanvasSupported; this._fallbackFontDict = null; this._needAppearances = false; } _hasFlag(flags, flag) { return !!(flags & flag); } _isViewable(flags) { return !this._hasFlag(flags, AnnotationFlag.INVISIBLE) && !this._hasFlag(flags, AnnotationFlag.NOVIEW); } _isPrintable(flags) { return this._hasFlag(flags, AnnotationFlag.PRINT) && !this._hasFlag(flags, AnnotationFlag.HIDDEN) && !this._hasFlag(flags, AnnotationFlag.INVISIBLE); } mustBeViewed(annotationStorage, _renderForms) { const noView = annotationStorage?.get(this.data.id)?.noView; if (noView !== undefined) { return !noView; } return this.viewable && !this._hasFlag(this.flags, AnnotationFlag.HIDDEN); } mustBePrinted(annotationStorage) { const noPrint = annotationStorage?.get(this.data.id)?.noPrint; if (noPrint !== undefined) { return !noPrint; } return this.printable; } get viewable() { if (this.data.quadPoints === null) { return false; } if (this.flags === 0) { return true; } return this._isViewable(this.flags); } get printable() { if (this.data.quadPoints === null) { return false; } if (this.flags === 0) { return false; } return this._isPrintable(this.flags); } _parseStringHelper(data) { const str = typeof data === "string" ? stringToPDFString(data) : ""; const dir = str && bidi(str).dir === "rtl" ? "rtl" : "ltr"; return { str, dir }; } setDefaultAppearance(params) { const { dict, annotationGlobals } = params; const defaultAppearance = getInheritableProperty({ dict, key: "DA" }) || annotationGlobals.acroForm.get("DA"); this._defaultAppearance = typeof defaultAppearance === "string" ? defaultAppearance : ""; this.data.defaultAppearanceData = parseDefaultAppearance(this._defaultAppearance); } setTitle(title) { this._title = this._parseStringHelper(title); } setContents(contents) { this._contents = this._parseStringHelper(contents); } setModificationDate(modificationDate) { this.modificationDate = typeof modificationDate === "string" ? modificationDate : null; } setFlags(flags) { this.flags = Number.isInteger(flags) && flags > 0 ? flags : 0; if (this.flags & AnnotationFlag.INVISIBLE && this.constructor.name !== "Annotation") { this.flags ^= AnnotationFlag.INVISIBLE; } } hasFlag(flag) { return this._hasFlag(this.flags, flag); } setRectangle(rectangle) { this.rectangle = lookupNormalRect(rectangle, [0, 0, 0, 0]); } setColor(color) { this.color = getRgbColor(color); } setLineEndings(lineEndings) { this.lineEndings = ["None", "None"]; if (Array.isArray(lineEndings) && lineEndings.length === 2) { for (let i = 0; i < 2; i++) { const obj = lineEndings[i]; if (obj instanceof Name) { switch (obj.name) { case "None": continue; case "Square": case "Circle": case "Diamond": case "OpenArrow": case "ClosedArrow": case "Butt": case "ROpenArrow": case "RClosedArrow": case "Slash": this.lineEndings[i] = obj.name; continue; } } warn(`Ignoring invalid lineEnding: ${obj}`); } } } setRotation(mk, dict) { this.rotation = 0; let angle = mk instanceof Dict ? mk.get("R") || 0 : dict.get("Rotate") || 0; if (Number.isInteger(angle) && angle !== 0) { angle %= 360; if (angle < 0) { angle += 360; } if (angle % 90 === 0) { this.rotation = angle; } } } setBorderAndBackgroundColors(mk) { if (mk instanceof Dict) { this.borderColor = getRgbColor(mk.getArray("BC"), null); this.backgroundColor = getRgbColor(mk.getArray("BG"), null); } else { this.borderColor = this.backgroundColor = null; } } setBorderStyle(borderStyle) { this.borderStyle = new AnnotationBorderStyle(); if (!(borderStyle instanceof Dict)) { return; } if (borderStyle.has("BS")) { const dict = borderStyle.get("BS"); if (dict instanceof Dict) { const dictType = dict.get("Type"); if (!dictType || isName(dictType, "Border")) { this.borderStyle.setWidth(dict.get("W"), this.rectangle); this.borderStyle.setStyle(dict.get("S")); this.borderStyle.setDashArray(dict.getArray("D")); } } } else if (borderStyle.has("Border")) { const array = borderStyle.getArray("Border"); if (Array.isArray(array) && array.length >= 3) { this.borderStyle.setHorizontalCornerRadius(array[0]); this.borderStyle.setVerticalCornerRadius(array[1]); this.borderStyle.setWidth(array[2], this.rectangle); if (array.length === 4) { this.borderStyle.setDashArray(array[3], true); } } } else { this.borderStyle.setWidth(0); } } setAppearance(dict) { this.appearance = null; const appearanceStates = dict.get("AP"); if (!(appearanceStates instanceof Dict)) { return; } const normalAppearanceState = appearanceStates.get("N"); if (normalAppearanceState instanceof BaseStream) { this.appearance = normalAppearanceState; return; } if (!(normalAppearanceState instanceof Dict)) { return; } const as = dict.get("AS"); if (!(as instanceof Name) || !normalAppearanceState.has(as.name)) { return; } const appearance = normalAppearanceState.get(as.name); if (appearance instanceof BaseStream) { this.appearance = appearance; } } setOptionalContent(dict) { this.oc = null; const oc = dict.get("OC"); if (oc instanceof Name) { warn("setOptionalContent: Support for /Name-entry is not implemented."); } else if (oc instanceof Dict) { this.oc = oc; } } loadResources(keys, appearance) { return appearance.dict.getAsync("Resources").then(resources => { if (!resources) { return undefined; } const objectLoader = new ObjectLoader(resources, keys, resources.xref); return objectLoader.load().then(function () { return resources; }); }); } async getOperatorList(evaluator, task, intent, renderForms, annotationStorage) { const { hasOwnCanvas, id, rect } = this.data; let appearance = this.appearance; const isUsingOwnCanvas = !!(hasOwnCanvas && intent & RenderingIntentFlag.DISPLAY); if (isUsingOwnCanvas && (rect[0] === rect[2] || rect[1] === rect[3])) { this.data.hasOwnCanvas = false; return { opList: new OperatorList(), separateForm: false, separateCanvas: false }; } if (!appearance) { if (!isUsingOwnCanvas) { return { opList: new OperatorList(), separateForm: false, separateCanvas: false }; } appearance = new StringStream(""); appearance.dict = new Dict(); } const appearanceDict = appearance.dict; const resources = await this.loadResources(["ExtGState", "ColorSpace", "Pattern", "Shading", "XObject", "Font"], appearance); const bbox = lookupRect(appearanceDict.getArray("BBox"), [0, 0, 1, 1]); const matrix = lookupMatrix(appearanceDict.getArray("Matrix"), IDENTITY_MATRIX); const transform = getTransformMatrix(rect, bbox, matrix); const opList = new OperatorList(); let optionalContent; if (this.oc) { optionalContent = await evaluator.parseMarkedContentProps(this.oc, null); } if (optionalContent !== undefined) { opList.addOp(OPS.beginMarkedContentProps, ["OC", optionalContent]); } opList.addOp(OPS.beginAnnotation, [id, rect, transform, matrix, isUsingOwnCanvas]); await evaluator.getOperatorList({ stream: appearance, task, resources, operatorList: opList, fallbackFontDict: this._fallbackFontDict }); opList.addOp(OPS.endAnnotation, []); if (optionalContent !== undefined) { opList.addOp(OPS.endMarkedContent, []); } this.reset(); return { opList, separateForm: false, separateCanvas: isUsingOwnCanvas }; } async save(evaluator, task, annotationStorage) { return null; } get hasTextContent() { return false; } async extractTextContent(evaluator, task, viewBox) { if (!this.appearance) { return; } const resources = await this.loadResources(["ExtGState", "Font", "Properties", "XObject"], this.appearance); const text = []; const buffer = []; let firstPosition = null; const sink = { desiredSize: Math.Infinity, ready: true, enqueue(chunk, size) { for (const item of chunk.items) { if (item.str === undefined) { continue; } firstPosition ||= item.transform.slice(-2); buffer.push(item.str); if (item.hasEOL) { text.push(buffer.join("").trimEnd()); buffer.length = 0; } } } }; await evaluator.getTextContent({ stream: this.appearance, task, resources, includeMarkedContent: true, keepWhiteSpace: true, sink, viewBox }); this.reset(); if (buffer.length) { text.push(buffer.join("").trimEnd()); } if (text.length > 1 || text[0]) { const appearanceDict = this.appearance.dict; const bbox = lookupRect(appearanceDict.getArray("BBox"), null); const matrix = lookupMatrix(appearanceDict.getArray("Matrix"), null); this.data.textPosition = this._transformPoint(firstPosition, bbox, matrix); this.data.textContent = text; } } _transformPoint(coords, bbox, matrix) { const { rect } = this.data; bbox ||= [0, 0, 1, 1]; matrix ||= [1, 0, 0, 1, 0, 0]; const transform = getTransformMatrix(rect, bbox, matrix); transform[4] -= rect[0]; transform[5] -= rect[1]; coords = Util.applyTransform(coords, transform); return Util.applyTransform(coords, matrix); } getFieldObject() { if (this.data.kidIds) { return { id: this.data.id, actions: this.data.actions, name: this.data.fieldName, strokeColor: this.data.borderColor, fillColor: this.data.backgroundColor, type: "", kidIds: this.data.kidIds, page: this.data.pageIndex, rotation: this.rotation }; } return null; } reset() { for (const stream of this._streams) { stream.reset(); } } _constructFieldName(dict) { if (!dict.has("T") && !dict.has("Parent")) { warn("Unknown field name, falling back to empty field name."); return ""; } if (!dict.has("Parent")) { return stringToPDFString(dict.get("T")); } const fieldName = []; if (dict.has("T")) { fieldName.unshift(stringToPDFString(dict.get("T"))); } let loopDict = dict; const visited = new RefSet(); if (dict.objId) { visited.put(dict.objId); } while (loopDict.has("Parent")) { loopDict = loopDict.get("Parent"); if (!(loopDict instanceof Dict) || loopDict.objId && visited.has(loopDict.objId)) { break; } if (loopDict.objId) { visited.put(loopDict.objId); } if (loopDict.has("T")) { fieldName.unshift(stringToPDFString(loopDict.get("T"))); } } return fieldName.join("."); } } class AnnotationBorderStyle { constructor() { this.width = 1; this.style = AnnotationBorderStyleType.SOLID; this.dashArray = [3]; this.horizontalCornerRadius = 0; this.verticalCornerRadius = 0; } setWidth(width, rect = [0, 0, 0, 0]) { if (width instanceof Name) { this.width = 0; return; } if (typeof width === "number") { if (width > 0) { const maxWidth = (rect[2] - rect[0]) / 2; const maxHeight = (rect[3] - rect[1]) / 2; if (maxWidth > 0 && maxHeight > 0 && (width > maxWidth || width > maxHeight)) { warn(`AnnotationBorderStyle.setWidth - ignoring width: ${width}`); width = 1; } } this.width = width; } } setStyle(style) { if (!(style instanceof Name)) { return; } switch (style.name) { case "S": this.style = AnnotationBorderStyleType.SOLID; break; case "D": this.style = AnnotationBorderStyleType.DASHED; break; case "B": this.style = AnnotationBorderStyleType.BEVELED; break; case "I": this.style = AnnotationBorderStyleType.INSET; break; case "U": this.style = AnnotationBorderStyleType.UNDERLINE; break; default: break; } } setDashArray(dashArray, forceStyle = false) { if (Array.isArray(dashArray)) { let isValid = true; let allZeros = true; for (const element of dashArray) { const validNumber = +element >= 0; if (!validNumber) { isValid = false; break; } else if (element > 0) { allZeros = false; } } if (dashArray.length === 0 || isValid && !allZeros) { this.dashArray = dashArray; if (forceStyle) { this.setStyle(Name.get("D")); } } else { this.width = 0; } } else if (dashArray) { this.width = 0; } } setHorizontalCornerRadius(radius) { if (Number.isInteger(radius)) { this.horizontalCornerRadius = radius; } } setVerticalCornerRadius(radius) { if (Number.isInteger(radius)) { this.verticalCornerRadius = radius; } } } class MarkupAnnotation extends Annotation { constructor(params) { super(params); const { dict } = params; if (dict.has("IRT")) { const rawIRT = dict.getRaw("IRT"); this.data.inReplyTo = rawIRT instanceof Ref ? rawIRT.toString() : null; const rt = dict.get("RT"); this.data.replyType = rt instanceof Name ? rt.name : AnnotationReplyType.REPLY; } let popupRef = null; if (this.data.replyType === AnnotationReplyType.GROUP) { const parent = dict.get("IRT"); this.setTitle(parent.get("T")); this.data.titleObj = this._title; this.setContents(parent.get("Contents")); this.data.contentsObj = this._contents; if (!parent.has("CreationDate")) { this.data.creationDate = null; } else { this.setCreationDate(parent.get("CreationDate")); this.data.creationDate = this.creationDate; } if (!parent.has("M")) { this.data.modificationDate = null; } else { this.setModificationDate(parent.get("M")); this.data.modificationDate = this.modificationDate; } popupRef = parent.getRaw("Popup"); if (!parent.has("C")) { this.data.color = null; } else { this.setColor(parent.getArray("C")); this.data.color = this.color; } } else { this.data.titleObj = this._title; this.setCreationDate(dict.get("CreationDate")); this.data.creationDate = this.creationDate; popupRef = dict.getRaw("Popup"); if (!dict.has("C")) { this.data.color = null; } } this.data.popupRef = popupRef instanceof Ref ? popupRef.toString() : null; if (dict.has("RC")) { this.data.richText = XFAFactory.getRichTextAsHtml(dict.get("RC")); } } setCreationDate(creationDate) { this.creationDate = typeof creationDate === "string" ? creationDate : null; } _setDefaultAppearance({ xref, extra, strokeColor, fillColor, blendMode, strokeAlpha, fillAlpha, pointsCallback }) { let minX = Number.MAX_VALUE; let minY = Number.MAX_VALUE; let maxX = Number.MIN_VALUE; let maxY = Number.MIN_VALUE; const buffer = ["q"]; if (extra) { buffer.push(extra); } if (strokeColor) { buffer.push(`${strokeColor[0]} ${strokeColor[1]} ${strokeColor[2]} RG`); } if (fillColor) { buffer.push(`${fillColor[0]} ${fillColor[1]} ${fillColor[2]} rg`); } let pointsArray = this.data.quadPoints; if (!pointsArray) { pointsArray = [[{ x: this.rectangle[0], y: this.rectangle[3] }, { x: this.rectangle[2], y: this.rectangle[3] }, { x: this.rectangle[0], y: this.rectangle[1] }, { x: this.rectangle[2], y: this.rectangle[1] }]]; } for (const points of pointsArray) { const [mX, MX, mY, MY] = pointsCallback(buffer, points); minX = Math.min(minX, mX); maxX = Math.max(maxX, MX); minY = Math.min(minY, mY); maxY = Math.max(maxY, MY); } buffer.push("Q"); const formDict = new Dict(xref); const appearanceStreamDict = new Dict(xref); appearanceStreamDict.set("Subtype", Name.get("Form")); const appearanceStream = new StringStream(buffer.join(" ")); appearanceStream.dict = appearanceStreamDict; formDict.set("Fm0", appearanceStream); const gsDict = new Dict(xref); if (blendMode) { gsDict.set("BM", Name.get(blendMode)); } if (typeof strokeAlpha === "number") { gsDict.set("CA", strokeAlpha); } if (typeof fillAlpha === "number") { gsDict.set("ca", fillAlpha); } const stateDict = new Dict(xref); stateDict.set("GS0", gsDict); const resources = new Dict(xref); resources.set("ExtGState", stateDict); resources.set("XObject", formDict); const appearanceDict = new Dict(xref); appearanceDict.set("Resources", resources); const bbox = this.data.rect = [minX, minY, maxX, maxY]; appearanceDict.set("BBox", bbox); this.appearance = new StringStream("/GS0 gs /Fm0 Do"); this.appearance.dict = appearanceDict; this._streams.push(this.appearance, appearanceStream); } static async createNewAnnotation(xref, annotation, dependencies, params) { const annotationRef = annotation.ref ||= xref.getNewTemporaryRef(); const ap = await this.createNewAppearanceStream(annotation, xref, params); const buffer = []; let annotationDict; if (ap) { const apRef = xref.getNewTemporaryRef(); annotationDict = this.createNewDict(annotation, xref, { apRef }); await writeObject(apRef, ap, buffer, xref); dependencies.push({ ref: apRef, data: buffer.join("") }); } else { annotationDict = this.createNewDict(annotation, xref, {}); } if (Number.isInteger(annotation.parentTreeId)) { annotationDict.set("StructParent", annotation.parentTreeId); } buffer.length = 0; await writeObject(annotationRef, annotationDict, buffer, xref); return { ref: annotationRef, data: buffer.join("") }; } static async createNewPrintAnnotation(annotationGlobals, xref, annotation, params) { const ap = await this.createNewAppearanceStream(annotation, xref, params); const annotationDict = this.createNewDict(annotation, xref, { ap }); const newAnnotation = new this.prototype.constructor({ dict: annotationDict, xref, annotationGlobals, evaluatorOptions: params.evaluatorOptions }); if (annotation.ref) { newAnnotation.ref = newAnnotation.refToReplace = annotation.ref; } return newAnnotation; } } class WidgetAnnotation extends Annotation { constructor(params) { super(params); const { dict, xref, annotationGlobals } = params; const data = this.data; this._needAppearances = params.needAppearances; data.annotationType = AnnotationType.WIDGET; if (data.fieldName === undefined) { data.fieldName = this._constructFieldName(dict); } if (data.actions === undefined) { data.actions = collectActions(xref, dict, AnnotationActionEventType); } let fieldValue = getInheritableProperty({ dict, key: "V", getArray: true }); data.fieldValue = this._decodeFormValue(fieldValue); const defaultFieldValue = getInheritableProperty({ dict, key: "DV", getArray: true }); data.defaultFieldValue = this._decodeFormValue(defaultFieldValue); if (fieldValue === undefined && annotationGlobals.xfaDatasets) { const path = this._title.str; if (path) { this._hasValueFromXFA = true; data.fieldValue = fieldValue = annotationGlobals.xfaDatasets.getValue(path); } } if (fieldValue === undefined && data.defaultFieldValue !== null) { data.fieldValue = data.defaultFieldValue; } data.alternativeText = stringToPDFString(dict.get("TU") || ""); this.setDefaultAppearance(params); data.hasAppearance ||= this._needAppearances && data.fieldValue !== undefined && data.fieldValue !== null; const fieldType = getInheritableProperty({ dict, key: "FT" }); data.fieldType = fieldType instanceof Name ? fieldType.name : null; const localResources = getInheritableProperty({ dict, key: "DR" }); const acroFormResources = annotationGlobals.acroForm.get("DR"); const appearanceResources = this.appearance?.dict.get("Resources"); this._fieldResources = { localResources, acroFormResources, appearanceResources, mergedResources: Dict.merge({ xref, dictArray: [localResources, appearanceResources, acroFormResources], mergeSubDicts: true }) }; data.fieldFlags = getInheritableProperty({ dict, key: "Ff" }); if (!Number.isInteger(data.fieldFlags) || data.fieldFlags < 0) { data.fieldFlags = 0; } data.readOnly = this.hasFieldFlag(AnnotationFieldFlag.READONLY); data.required = this.hasFieldFlag(AnnotationFieldFlag.REQUIRED); data.hidden = this._hasFlag(data.annotationFlags, AnnotationFlag.HIDDEN) || this._hasFlag(data.annotationFlags, AnnotationFlag.NOVIEW); } _decodeFormValue(formValue) { if (Array.isArray(formValue)) { return formValue.filter(item => typeof item === "string").map(item => stringToPDFString(item)); } else if (formValue instanceof Name) { return stringToPDFString(formValue.name); } else if (typeof formValue === "string") { return stringToPDFString(formValue); } return null; } hasFieldFlag(flag) { return !!(this.data.fieldFlags & flag); } _isViewable(flags) { return true; } mustBeViewed(annotationStorage, renderForms) { if (renderForms) { return this.viewable; } return super.mustBeViewed(annotationStorage, renderForms) && !this._hasFlag(this.flags, AnnotationFlag.NOVIEW); } getRotationMatrix(annotationStorage) { let rotation = annotationStorage?.get(this.data.id)?.rotation; if (rotation === undefined) { rotation = this.rotation; } if (rotation === 0) { return IDENTITY_MATRIX; } const width = this.data.rect[2] - this.data.rect[0]; const height = this.data.rect[3] - this.data.rect[1]; return getRotationMatrix(rotation, width, height); } getBorderAndBackgroundAppearances(annotationStorage) { let rotation = annotationStorage?.get(this.data.id)?.rotation; if (rotation === undefined) { rotation = this.rotation; } if (!this.backgroundColor && !this.borderColor) { return ""; } const width = this.data.rect[2] - this.data.rect[0]; const height = this.data.rect[3] - this.data.rect[1]; const rect = rotation === 0 || rotation === 180 ? `0 0 ${width} ${height} re` : `0 0 ${height} ${width} re`; let str = ""; if (this.backgroundColor) { str = `${getPdfColor(this.backgroundColor, true)} ${rect} f `; } if (this.borderColor) { const borderWidth = this.borderStyle.width || 1; str += `${borderWidth} w ${getPdfColor(this.borderColor, false)} ${rect} S `; } return str; } async getOperatorList(evaluator, task, intent, renderForms, annotationStorage) { if (renderForms && !(this instanceof SignatureWidgetAnnotation) && !this.data.noHTML && !this.data.hasOwnCanvas) { return { opList: new OperatorList(), separateForm: true, separateCanvas: false }; } if (!this._hasText) { return super.getOperatorList(evaluator, task, intent, renderForms, annotationStorage); } const content = await this._getAppearance(evaluator, task, intent, annotationStorage); if (this.appearance && content === null) { return super.getOperatorList(evaluator, task, intent, renderForms, annotationStorage); } const opList = new OperatorList(); if (!this._defaultAppearance || content === null) { return { opList, separateForm: false, separateCanvas: false }; } const isUsingOwnCanvas = !!(this.data.hasOwnCanvas && intent & RenderingIntentFlag.DISPLAY); const matrix = [1, 0, 0, 1, 0, 0]; const bbox = [0, 0, this.data.rect[2] - this.data.rect[0], this.data.rect[3] - this.data.rect[1]]; const transform = getTransformMatrix(this.data.rect, bbox, matrix); let optionalContent; if (this.oc) { optionalContent = await evaluator.parseMarkedContentProps(this.oc, null); } if (optionalContent !== undefined) { opList.addOp(OPS.beginMarkedContentProps, ["OC", optionalContent]); } opList.addOp(OPS.beginAnnotation, [this.data.id, this.data.rect, transform, this.getRotationMatrix(annotationStorage), isUsingOwnCanvas]); const stream = new StringStream(content); await evaluator.getOperatorList({ stream, task, resources: this._fieldResources.mergedResources, operatorList: opList }); opList.addOp(OPS.endAnnotation, []); if (optionalContent !== undefined) { opList.addOp(OPS.endMarkedContent, []); } return { opList, separateForm: false, separateCanvas: isUsingOwnCanvas }; } _getMKDict(rotation) { const mk = new Dict(null); if (rotation) { mk.set("R", rotation); } if (this.borderColor) { mk.set("BC", getPdfColorArray(this.borderColor)); } if (this.backgroundColor) { mk.set("BG", getPdfColorArray(this.backgroundColor)); } return mk.size > 0 ? mk : null; } amendSavedDict(annotationStorage, dict) {} async save(evaluator, task, annotationStorage) { const storageEntry = annotationStorage?.get(this.data.id); let value = storageEntry?.value, rotation = storageEntry?.rotation; if (value === this.data.fieldValue || value === undefined) { if (!this._hasValueFromXFA && rotation === undefined) { return null; } value ||= this.data.fieldValue; } if (rotation === undefined && !this._hasValueFromXFA && Array.isArray(value) && Array.isArray(this.data.fieldValue) && value.length === this.data.fieldValue.length && value.every((x, i) => x === this.data.fieldValue[i])) { return null; } if (rotation === undefined) { rotation = this.rotation; } let appearance = null; if (!this._needAppearances) { appearance = await this._getAppearance(evaluator, task, RenderingIntentFlag.SAVE, annotationStorage); if (appearance === null) { return null; } } else {} let needAppearances = false; if (appearance?.needAppearances) { needAppearances = true; appearance = null; } const { xref } = evaluator; const originalDict = xref.fetchIfRef(this.ref); if (!(originalDict instanceof Dict)) { return null; } const dict = new Dict(xref); for (const key of originalDict.getKeys()) { if (key !== "AP") { dict.set(key, originalDict.getRaw(key)); } } const xfa = { path: this.data.fieldName, value }; const encoder = val => isAscii(val) ? val : stringToUTF16String(val, true); dict.set("V", Array.isArray(value) ? value.map(encoder) : encoder(value)); this.amendSavedDict(annotationStorage, dict); const maybeMK = this._getMKDict(rotation); if (maybeMK) { dict.set("MK", maybeMK); } const buffer = []; const changes = [{ ref: this.ref, data: "", xfa, needAppearances }]; if (appearance !== null) { const newRef = xref.getNewTemporaryRef(); const AP = new Dict(xref); dict.set("AP", AP); AP.set("N", newRef); const resources = this._getSaveFieldResources(xref); const appearanceStream = new StringStream(appearance); const appearanceDict = appearanceStream.dict = new Dict(xref); appearanceDict.set("Subtype", Name.get("Form")); appearanceDict.set("Resources", resources); appearanceDict.set("BBox", [0, 0, this.data.rect[2] - this.data.rect[0], this.data.rect[3] - this.data.rect[1]]); const rotationMatrix = this.getRotationMatrix(annotationStorage); if (rotationMatrix !== IDENTITY_MATRIX) { appearanceDict.set("Matrix", rotationMatrix); } await writeObject(newRef, appearanceStream, buffer, xref); changes.push({ ref: newRef, data: buffer.join(""), xfa: null, needAppearances: false }); buffer.length = 0; } dict.set("M", `D:${getModificationDate()}`); await writeObject(this.ref, dict, buffer, xref); changes[0].data = buffer.join(""); return changes; } async _getAppearance(evaluator, task, intent, annotationStorage) { const isPassword = this.hasFieldFlag(AnnotationFieldFlag.PASSWORD); if (isPassword) { return null; } const storageEntry = annotationStorage?.get(this.data.id); let value, rotation; if (storageEntry) { value = storageEntry.formattedValue || storageEntry.value; rotation = storageEntry.rotation; } if (rotation === undefined && value === undefined && !this._needAppearances) { if (!this._hasValueFromXFA || this.appearance) { return null; } } const colors = this.getBorderAndBackgroundAppearances(annotationStorage); if (value === undefined) { value = this.data.fieldValue; if (!value) { return `/Tx BMC q ${colors}Q EMC`; } } if (Array.isArray(value) && value.length === 1) { value = value[0]; } assert(typeof value === "string", "Expected `value` to be a string."); value = value.trim(); if (this.data.combo) { const option = this.data.options.find(({ exportValue }) => value === exportValue); value = option?.displayValue || value; } if (value === "") { return `/Tx BMC q ${colors}Q EMC`; } if (rotation === undefined) { rotation = this.rotation; } let lineCount = -1; let lines; if (this.data.multiLine) { lines = value.split(/\r\n?|\n/).map(line => line.normalize("NFC")); lineCount = lines.length; } else { lines = [value.replace(/\r\n?|\n/, "").normalize("NFC")]; } const defaultPadding = 1; const defaultHPadding = 2; let totalHeight = this.data.rect[3] - this.data.rect[1]; let totalWidth = this.data.rect[2] - this.data.rect[0]; if (rotation === 90 || rotation === 270) { [totalWidth, totalHeight] = [totalHeight, totalWidth]; } if (!this._defaultAppearance) { this.data.defaultAppearanceData = parseDefaultAppearance(this._defaultAppearance = "/Helvetica 0 Tf 0 g"); } let font = await WidgetAnnotation._getFontData(evaluator, task, this.data.defaultAppearanceData, this._fieldResources.mergedResources); let defaultAppearance, fontSize, lineHeight; const encodedLines = []; let encodingError = false; for (const line of lines) { const encodedString = font.encodeString(line); if (encodedString.length > 1) { encodingError = true; } encodedLines.push(encodedString.join("")); } if (encodingError && intent & RenderingIntentFlag.SAVE) { return { needAppearances: true }; } if (encodingError && this._isOffscreenCanvasSupported) { const fontFamily = this.data.comb ? "monospace" : "sans-serif"; const fakeUnicodeFont = new FakeUnicodeFont(evaluator.xref, fontFamily); const resources = fakeUnicodeFont.createFontResources(lines.join("")); const newFont = resources.getRaw("Font"); if (this._fieldResources.mergedResources.has("Font")) { const oldFont = this._fieldResources.mergedResources.get("Font"); for (const key of newFont.getKeys()) { oldFont.set(key, newFont.getRaw(key)); } } else { this._fieldResources.mergedResources.set("Font", newFont); } const fontName = fakeUnicodeFont.fontName.name; font = await WidgetAnnotation._getFontData(evaluator, task, { fontName, fontSize: 0 }, resources); for (let i = 0, ii = encodedLines.length; i < ii; i++) { encodedLines[i] = stringToUTF16String(lines[i]); } const savedDefaultAppearance = Object.assign(Object.create(null), this.data.defaultAppearanceData); this.data.defaultAppearanceData.fontSize = 0; this.data.defaultAppearanceData.fontName = fontName; [defaultAppearance, fontSize, lineHeight] = this._computeFontSize(totalHeight - 2 * defaultPadding, totalWidth - 2 * defaultHPadding, value, font, lineCount); this.data.defaultAppearanceData = savedDefaultAppearance; } else { if (!this._isOffscreenCanvasSupported) { warn("_getAppearance: OffscreenCanvas is not supported, annotation may not render correctly."); } [defaultAppearance, fontSize, lineHeight] = this._computeFontSize(totalHeight - 2 * defaultPadding, totalWidth - 2 * defaultHPadding, value, font, lineCount); } let descent = font.descent; if (isNaN(descent)) { descent = BASELINE_FACTOR * lineHeight; } else { descent = Math.max(BASELINE_FACTOR * lineHeight, Math.abs(descent) * fontSize); } const defaultVPadding = Math.min(Math.floor((totalHeight - fontSize) / 2), defaultPadding); const alignment = this.data.textAlignment; if (this.data.multiLine) { return this._getMultilineAppearance(defaultAppearance, encodedLines, font, fontSize, totalWidth, totalHeight, alignment, defaultHPadding, defaultVPadding, descent, lineHeight, annotationStorage); } if (this.data.comb) { return this._getCombAppearance(defaultAppearance, font, encodedLines[0], fontSize, totalWidth, totalHeight, defaultHPadding, defaultVPadding, descent, lineHeight, annotationStorage); } const bottomPadding = defaultVPadding + descent; if (alignment === 0 || alignment > 2) { return `/Tx BMC q ${colors}BT ` + defaultAppearance + ` 1 0 0 1 ${numberToString(defaultHPadding)} ${numberToString(bottomPadding)} Tm (${escapeString(encodedLines[0])}) Tj` + " ET Q EMC"; } const prevInfo = { shift: 0 }; const renderedText = this._renderText(encodedLines[0], font, fontSize, totalWidth, alignment, prevInfo, defaultHPadding, bottomPadding); return `/Tx BMC q ${colors}BT ` + defaultAppearance + ` 1 0 0 1 0 0 Tm ${renderedText}` + " ET Q EMC"; } static async _getFontData(evaluator, task, appearanceData, resources) { const operatorList = new OperatorList(); const initialState = { font: null, clone() { return this; } }; const { fontName, fontSize } = appearanceData; await evaluator.handleSetFont(resources, [fontName && Name.get(fontName), fontSize], null, operatorList, task, initialState, null); return initialState.font; } _getTextWidth(text, font) { return font.charsToGlyphs(text).reduce((width, glyph) => width + glyph.width, 0) / 1000; } _computeFontSize(height, width, text, font, lineCount) { let { fontSize } = this.data.defaultAppearanceData; let lineHeight = (fontSize || 12) * LINE_FACTOR, numberOfLines = Math.round(height / lineHeight); if (!fontSize) { const roundWithTwoDigits = x => Math.floor(x * 100) / 100; if (lineCount === -1) { const textWidth = this._getTextWidth(text, font); fontSize = roundWithTwoDigits(Math.min(height / LINE_FACTOR, textWidth > width ? width / textWidth : Infinity)); numberOfLines = 1; } else { const lines = text.split(/\r\n?|\n/); const cachedLines = []; for (const line of lines) { const encoded = font.encodeString(line).join(""); const glyphs = font.charsToGlyphs(encoded); const positions = font.getCharPositions(encoded); cachedLines.push({ line: encoded, glyphs, positions }); } const isTooBig = fsize => { let totalHeight = 0; for (const cache of cachedLines) { const chunks = this._splitLine(null, font, fsize, width, cache); totalHeight += chunks.length * fsize; if (totalHeight > height) { return true; } } return false; }; numberOfLines = Math.max(numberOfLines, lineCount); while (true) { lineHeight = height / numberOfLines; fontSize = roundWithTwoDigits(lineHeight / LINE_FACTOR); if (isTooBig(fontSize)) { numberOfLines++; continue; } break; } } const { fontName, fontColor } = this.data.defaultAppearanceData; this._defaultAppearance = createDefaultAppearance({ fontSize, fontName, fontColor }); } return [this._defaultAppearance, fontSize, height / numberOfLines]; } _renderText(text, font, fontSize, totalWidth, alignment, prevInfo, hPadding, vPadding) { let shift; if (alignment === 1) { const width = this._getTextWidth(text, font) * fontSize; shift = (totalWidth - width) / 2; } else if (alignment === 2) { const width = this._getTextWidth(text, font) * fontSize; shift = totalWidth - width - hPadding; } else { shift = hPadding; } const shiftStr = numberToString(shift - prevInfo.shift); prevInfo.shift = shift; vPadding = numberToString(vPadding); return `${shiftStr} ${vPadding} Td (${escapeString(text)}) Tj`; } _getSaveFieldResources(xref) { const { localResources, appearanceResources, acroFormResources } = this._fieldResources; const fontName = this.data.defaultAppearanceData?.fontName; if (!fontName) { return localResources || Dict.empty; } for (const resources of [localResources, appearanceResources]) { if (resources instanceof Dict) { const localFont = resources.get("Font"); if (localFont instanceof Dict && localFont.has(fontName)) { return resources; } } } if (acroFormResources instanceof Dict) { const acroFormFont = acroFormResources.get("Font"); if (acroFormFont instanceof Dict && acroFormFont.has(fontName)) { const subFontDict = new Dict(xref); subFontDict.set(fontName, acroFormFont.getRaw(fontName)); const subResourcesDict = new Dict(xref); subResourcesDict.set("Font", subFontDict); return Dict.merge({ xref, dictArray: [subResourcesDict, localResources], mergeSubDicts: true }); } } return localResources || Dict.empty; } getFieldObject() { return null; } } class TextWidgetAnnotation extends WidgetAnnotation { constructor(params) { super(params); this.data.hasOwnCanvas = this.data.readOnly && !this.data.noHTML; this._hasText = true; const dict = params.dict; if (typeof this.data.fieldValue !== "string") { this.data.fieldValue = ""; } let alignment = getInheritableProperty({ dict, key: "Q" }); if (!Number.isInteger(alignment) || alignment < 0 || alignment > 2) { alignment = null; } this.data.textAlignment = alignment; let maximumLength = getInheritableProperty({ dict, key: "MaxLen" }); if (!Number.isInteger(maximumLength) || maximumLength < 0) { maximumLength = 0; } this.data.maxLen = maximumLength; this.data.multiLine = this.hasFieldFlag(AnnotationFieldFlag.MULTILINE); this.data.comb = this.hasFieldFlag(AnnotationFieldFlag.COMB) && !this.hasFieldFlag(AnnotationFieldFlag.MULTILINE) && !this.hasFieldFlag(AnnotationFieldFlag.PASSWORD) && !this.hasFieldFlag(AnnotationFieldFlag.FILESELECT) && this.data.maxLen !== 0; this.data.doNotScroll = this.hasFieldFlag(AnnotationFieldFlag.DONOTSCROLL); } get hasTextContent() { return !!this.appearance && !this._needAppearances; } _getCombAppearance(defaultAppearance, font, text, fontSize, width, height, hPadding, vPadding, descent, lineHeight, annotationStorage) { const combWidth = width / this.data.maxLen; const colors = this.getBorderAndBackgroundAppearances(annotationStorage); const buf = []; const positions = font.getCharPositions(text); for (const [start, end] of positions) { buf.push(`(${escapeString(text.substring(start, end))}) Tj`); } const renderedComb = buf.join(` ${numberToString(combWidth)} 0 Td `); return `/Tx BMC q ${colors}BT ` + defaultAppearance + ` 1 0 0 1 ${numberToString(hPadding)} ${numberToString(vPadding + descent)} Tm ${renderedComb}` + " ET Q EMC"; } _getMultilineAppearance(defaultAppearance, lines, font, fontSize, width, height, alignment, hPadding, vPadding, descent, lineHeight, annotationStorage) { const buf = []; const totalWidth = width - 2 * hPadding; const prevInfo = { shift: 0 }; for (let i = 0, ii = lines.length; i < ii; i++) { const line = lines[i]; const chunks = this._splitLine(line, font, fontSize, totalWidth); for (let j = 0, jj = chunks.length; j < jj; j++) { const chunk = chunks[j]; const vShift = i === 0 && j === 0 ? -vPadding - (lineHeight - descent) : -lineHeight; buf.push(this._renderText(chunk, font, fontSize, width, alignment, prevInfo, hPadding, vShift)); } } const colors = this.getBorderAndBackgroundAppearances(annotationStorage); const renderedText = buf.join("\n"); return `/Tx BMC q ${colors}BT ` + defaultAppearance + ` 1 0 0 1 0 ${numberToString(height)} Tm ${renderedText}` + " ET Q EMC"; } _splitLine(line, font, fontSize, width, cache = {}) { line = cache.line || line; const glyphs = cache.glyphs || font.charsToGlyphs(line); if (glyphs.length <= 1) { return [line]; } const positions = cache.positions || font.getCharPositions(line); const scale = fontSize / 1000; const chunks = []; let lastSpacePosInStringStart = -1, lastSpacePosInStringEnd = -1, lastSpacePos = -1, startChunk = 0, currentWidth = 0; for (let i = 0, ii = glyphs.length; i < ii; i++) { const [start, end] = positions[i]; const glyph = glyphs[i]; const glyphWidth = glyph.width * scale; if (glyph.unicode === " ") { if (currentWidth + glyphWidth > width) { chunks.push(line.substring(startChunk, start)); startChunk = start; currentWidth = glyphWidth; lastSpacePosInStringStart = -1; lastSpacePos = -1; } else { currentWidth += glyphWidth; lastSpacePosInStringStart = start; lastSpacePosInStringEnd = end; lastSpacePos = i; } } else if (currentWidth + glyphWidth > width) { if (lastSpacePosInStringStart !== -1) { chunks.push(line.substring(startChunk, lastSpacePosInStringEnd)); startChunk = lastSpacePosInStringEnd; i = lastSpacePos + 1; lastSpacePosInStringStart = -1; currentWidth = 0; } else { chunks.push(line.substring(startChunk, start)); startChunk = start; currentWidth = glyphWidth; } } else { currentWidth += glyphWidth; } } if (startChunk < line.length) { chunks.push(line.substring(startChunk, line.length)); } return chunks; } getFieldObject() { return { id: this.data.id, value: this.data.fieldValue, defaultValue: this.data.defaultFieldValue || "", multiline: this.data.multiLine, password: this.hasFieldFlag(AnnotationFieldFlag.PASSWORD), charLimit: this.data.maxLen, comb: this.data.comb, editable: !this.data.readOnly, hidden: this.data.hidden, name: this.data.fieldName, rect: this.data.rect, actions: this.data.actions, page: this.data.pageIndex, strokeColor: this.data.borderColor, fillColor: this.data.backgroundColor, rotation: this.rotation, type: "text" }; } } class ButtonWidgetAnnotation extends WidgetAnnotation { constructor(params) { super(params); this.checkedAppearance = null; this.uncheckedAppearance = null; this.data.checkBox = !this.hasFieldFlag(AnnotationFieldFlag.RADIO) && !this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON); this.data.radioButton = this.hasFieldFlag(AnnotationFieldFlag.RADIO) && !this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON); this.data.pushButton = this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON); this.data.isTooltipOnly = false; if (this.data.checkBox) { this._processCheckBox(params); } else if (this.data.radioButton) { this._processRadioButton(params); } else if (this.data.pushButton) { this.data.hasOwnCanvas = true; this.data.noHTML = false; this._processPushButton(params); } else { warn("Invalid field flags for button widget annotation"); } } async getOperatorList(evaluator, task, intent, renderForms, annotationStorage) { if (this.data.pushButton) { return super.getOperatorList(evaluator, task, intent, false, annotationStorage); } let value = null; let rotation = null; if (annotationStorage) { const storageEntry = annotationStorage.get(this.data.id); value = storageEntry ? storageEntry.value : null; rotation = storageEntry ? storageEntry.rotation : null; } if (value === null && this.appearance) { return super.getOperatorList(evaluator, task, intent, renderForms, annotationStorage); } if (value === null || value === undefined) { value = this.data.checkBox ? this.data.fieldValue === this.data.exportValue : this.data.fieldValue === this.data.buttonValue; } const appearance = value ? this.checkedAppearance : this.uncheckedAppearance; if (appearance) { const savedAppearance = this.appearance; const savedMatrix = lookupMatrix(appearance.dict.getArray("Matrix"), IDENTITY_MATRIX); if (rotation) { appearance.dict.set("Matrix", this.getRotationMatrix(annotationStorage)); } this.appearance = appearance; const operatorList = super.getOperatorList(evaluator, task, intent, renderForms, annotationStorage); this.appearance = savedAppearance; appearance.dict.set("Matrix", savedMatrix); return operatorList; } return { opList: new OperatorList(), separateForm: false, separateCanvas: false }; } async save(evaluator, task, annotationStorage) { if (this.data.checkBox) { return this._saveCheckbox(evaluator, task, annotationStorage); } if (this.data.radioButton) { return this._saveRadioButton(evaluator, task, annotationStorage); } return null; } async _saveCheckbox(evaluator, task, annotationStorage) { if (!annotationStorage) { return null; } const storageEntry = annotationStorage.get(this.data.id); let rotation = storageEntry?.rotation, value = storageEntry?.value; if (rotation === undefined) { if (value === undefined) { return null; } const defaultValue = this.data.fieldValue === this.data.exportValue; if (defaultValue === value) { return null; } } const dict = evaluator.xref.fetchIfRef(this.ref); if (!(dict instanceof Dict)) { return null; } if (rotation === undefined) { rotation = this.rotation; } if (value === undefined) { value = this.data.fieldValue === this.data.exportValue; } const xfa = { path: this.data.fieldName, value: value ? this.data.exportValue : "" }; const name = Name.get(value ? this.data.exportValue : "Off"); dict.set("V", name); dict.set("AS", name); dict.set("M", `D:${getModificationDate()}`); const maybeMK = this._getMKDict(rotation); if (maybeMK) { dict.set("MK", maybeMK); } const buffer = []; await writeObject(this.ref, dict, buffer, evaluator.xref); return [{ ref: this.ref, data: buffer.join(""), xfa }]; } async _saveRadioButton(evaluator, task, annotationStorage) { if (!annotationStorage) { return null; } const storageEntry = annotationStorage.get(this.data.id); let rotation = storageEntry?.rotation, value = storageEntry?.value; if (rotation === undefined) { if (value === undefined) { return null; } const defaultValue = this.data.fieldValue === this.data.buttonValue; if (defaultValue === value) { return null; } } const dict = evaluator.xref.fetchIfRef(this.ref); if (!(dict instanceof Dict)) { return null; } if (value === undefined) { value = this.data.fieldValue === this.data.buttonValue; } if (rotation === undefined) { rotation = this.rotation; } const xfa = { path: this.data.fieldName, value: value ? this.data.buttonValue : "" }; const name = Name.get(value ? this.data.buttonValue : "Off"); const buffer = []; let parentData = null; if (value) { if (this.parent instanceof Ref) { const parent = evaluator.xref.fetch(this.parent); parent.set("V", name); await writeObject(this.parent, parent, buffer, evaluator.xref); parentData = buffer.join(""); buffer.length = 0; } else if (this.parent instanceof Dict) { this.parent.set("V", name); } } dict.set("AS", name); dict.set("M", `D:${getModificationDate()}`); const maybeMK = this._getMKDict(rotation); if (maybeMK) { dict.set("MK", maybeMK); } await writeObject(this.ref, dict, buffer, evaluator.xref); const newRefs = [{ ref: this.ref, data: buffer.join(""), xfa }]; if (parentData) { newRefs.push({ ref: this.parent, data: parentData, xfa: null }); } return newRefs; } _getDefaultCheckedAppearance(params, type) { const width = this.data.rect[2] - this.data.rect[0]; const height = this.data.rect[3] - this.data.rect[1]; const bbox = [0, 0, width, height]; const FONT_RATIO = 0.8; const fontSize = Math.min(width, height) * FONT_RATIO; let metrics, char; if (type === "check") { metrics = { width: 0.755 * fontSize, height: 0.705 * fontSize }; char = "\x33"; } else if (type === "disc") { metrics = { width: 0.791 * fontSize, height: 0.705 * fontSize }; char = "\x6C"; } else { unreachable(`_getDefaultCheckedAppearance - unsupported type: ${type}`); } const xShift = numberToString((width - metrics.width) / 2); const yShift = numberToString((height - metrics.height) / 2); const appearance = `q BT /PdfJsZaDb ${fontSize} Tf 0 g ${xShift} ${yShift} Td (${char}) Tj ET Q`; const appearanceStreamDict = new Dict(params.xref); appearanceStreamDict.set("FormType", 1); appearanceStreamDict.set("Subtype", Name.get("Form")); appearanceStreamDict.set("Type", Name.get("XObject")); appearanceStreamDict.set("BBox", bbox); appearanceStreamDict.set("Matrix", [1, 0, 0, 1, 0, 0]); appearanceStreamDict.set("Length", appearance.length); const resources = new Dict(params.xref); const font = new Dict(params.xref); font.set("PdfJsZaDb", this.fallbackFontDict); resources.set("Font", font); appearanceStreamDict.set("Resources", resources); this.checkedAppearance = new StringStream(appearance); this.checkedAppearance.dict = appearanceStreamDict; this._streams.push(this.checkedAppearance); } _processCheckBox(params) { const customAppearance = params.dict.get("AP"); if (!(customAppearance instanceof Dict)) { return; } const normalAppearance = customAppearance.get("N"); if (!(normalAppearance instanceof Dict)) { return; } const asValue = this._decodeFormValue(params.dict.get("AS")); if (typeof asValue === "string") { this.data.fieldValue = asValue; } const yes = this.data.fieldValue !== null && this.data.fieldValue !== "Off" ? this.data.fieldValue : "Yes"; const exportValues = normalAppearance.getKeys(); if (exportValues.length === 0) { exportValues.push("Off", yes); } else if (exportValues.length === 1) { if (exportValues[0] === "Off") { exportValues.push(yes); } else { exportValues.unshift("Off"); } } else if (exportValues.includes(yes)) { exportValues.length = 0; exportValues.push("Off", yes); } else { const otherYes = exportValues.find(v => v !== "Off"); exportValues.length = 0; exportValues.push("Off", otherYes); } if (!exportValues.includes(this.data.fieldValue)) { this.data.fieldValue = "Off"; } this.data.exportValue = exportValues[1]; const checkedAppearance = normalAppearance.get(this.data.exportValue); this.checkedAppearance = checkedAppearance instanceof BaseStream ? checkedAppearance : null; const uncheckedAppearance = normalAppearance.get("Off"); this.uncheckedAppearance = uncheckedAppearance instanceof BaseStream ? uncheckedAppearance : null; if (this.checkedAppearance) { this._streams.push(this.checkedAppearance); } else { this._getDefaultCheckedAppearance(params, "check"); } if (this.uncheckedAppearance) { this._streams.push(this.uncheckedAppearance); } this._fallbackFontDict = this.fallbackFontDict; if (this.data.defaultFieldValue === null) { this.data.defaultFieldValue = "Off"; } } _processRadioButton(params) { this.data.buttonValue = null; const fieldParent = params.dict.get("Parent"); if (fieldParent instanceof Dict) { this.parent = params.dict.getRaw("Parent"); const fieldParentValue = fieldParent.get("V"); if (fieldParentValue instanceof Name) { this.data.fieldValue = this._decodeFormValue(fieldParentValue); } } const appearanceStates = params.dict.get("AP"); if (!(appearanceStates instanceof Dict)) { return; } const normalAppearance = appearanceStates.get("N"); if (!(normalAppearance instanceof Dict)) { return; } for (const key of normalAppearance.getKeys()) { if (key !== "Off") { this.data.buttonValue = this._decodeFormValue(key); break; } } const checkedAppearance = normalAppearance.get(this.data.buttonValue); this.checkedAppearance = checkedAppearance instanceof BaseStream ? checkedAppearance : null; const uncheckedAppearance = normalAppearance.get("Off"); this.uncheckedAppearance = uncheckedAppearance instanceof BaseStream ? uncheckedAppearance : null; if (this.checkedAppearance) { this._streams.push(this.checkedAppearance); } else { this._getDefaultCheckedAppearance(params, "disc"); } if (this.uncheckedAppearance) { this._streams.push(this.uncheckedAppearance); } this._fallbackFontDict = this.fallbackFontDict; if (this.data.defaultFieldValue === null) { this.data.defaultFieldValue = "Off"; } } _processPushButton(params) { const { dict, annotationGlobals } = params; if (!dict.has("A") && !dict.has("AA") && !this.data.alternativeText) { warn("Push buttons without action dictionaries are not supported"); return; } this.data.isTooltipOnly = !dict.has("A") && !dict.has("AA"); Catalog.parseDestDictionary({ destDict: dict, resultObj: this.data, docBaseUrl: annotationGlobals.baseUrl, docAttachments: annotationGlobals.attachments }); } getFieldObject() { let type = "button"; let exportValues; if (this.data.checkBox) { type = "checkbox"; exportValues = this.data.exportValue; } else if (this.data.radioButton) { type = "radiobutton"; exportValues = this.data.buttonValue; } return { id: this.data.id, value: this.data.fieldValue || "Off", defaultValue: this.data.defaultFieldValue, exportValues, editable: !this.data.readOnly, name: this.data.fieldName, rect: this.data.rect, hidden: this.data.hidden, actions: this.data.actions, page: this.data.pageIndex, strokeColor: this.data.borderColor, fillColor: this.data.backgroundColor, rotation: this.rotation, type }; } get fallbackFontDict() { const dict = new Dict(); dict.set("BaseFont", Name.get("ZapfDingbats")); dict.set("Type", Name.get("FallbackType")); dict.set("Subtype", Name.get("FallbackType")); dict.set("Encoding", Name.get("ZapfDingbatsEncoding")); return shadow(this, "fallbackFontDict", dict); } } class ChoiceWidgetAnnotation extends WidgetAnnotation { constructor(params) { super(params); const { dict, xref } = params; this.indices = dict.getArray("I"); this.hasIndices = Array.isArray(this.indices) && this.indices.length > 0; this.data.options = []; const options = getInheritableProperty({ dict, key: "Opt" }); if (Array.isArray(options)) { for (let i = 0, ii = options.length; i < ii; i++) { const option = xref.fetchIfRef(options[i]); const isOptionArray = Array.isArray(option); this.data.options[i] = { exportValue: this._decodeFormValue(isOptionArray ? xref.fetchIfRef(option[0]) : option), displayValue: this._decodeFormValue(isOptionArray ? xref.fetchIfRef(option[1]) : option) }; } } if (!this.hasIndices) { if (typeof this.data.fieldValue === "string") { this.data.fieldValue = [this.data.fieldValue]; } else if (!this.data.fieldValue) { this.data.fieldValue = []; } } else { this.data.fieldValue = []; const ii = this.data.options.length; for (const i of this.indices) { if (Number.isInteger(i) && i >= 0 && i < ii) { this.data.fieldValue.push(this.data.options[i].exportValue); } } } this.data.combo = this.hasFieldFlag(AnnotationFieldFlag.COMBO); this.data.multiSelect = this.hasFieldFlag(AnnotationFieldFlag.MULTISELECT); this._hasText = true; } getFieldObject() { const type = this.data.combo ? "combobox" : "listbox"; const value = this.data.fieldValue.length > 0 ? this.data.fieldValue[0] : null; return { id: this.data.id, value, defaultValue: this.data.defaultFieldValue, editable: !this.data.readOnly, name: this.data.fieldName, rect: this.data.rect, numItems: this.data.fieldValue.length, multipleSelection: this.data.multiSelect, hidden: this.data.hidden, actions: this.data.actions, items: this.data.options, page: this.data.pageIndex, strokeColor: this.data.borderColor, fillColor: this.data.backgroundColor, rotation: this.rotation, type }; } amendSavedDict(annotationStorage, dict) { if (!this.hasIndices) { return; } let values = annotationStorage?.get(this.data.id)?.value; if (!Array.isArray(values)) { values = [values]; } const indices = []; const { options } = this.data; for (let i = 0, j = 0, ii = options.length; i < ii; i++) { if (options[i].exportValue === values[j]) { indices.push(i); j += 1; } } dict.set("I", indices); } async _getAppearance(evaluator, task, intent, annotationStorage) { if (this.data.combo) { return super._getAppearance(evaluator, task, intent, annotationStorage); } let exportedValue, rotation; const storageEntry = annotationStorage?.get(this.data.id); if (storageEntry) { rotation = storageEntry.rotation; exportedValue = storageEntry.value; } if (rotation === undefined && exportedValue === undefined && !this._needAppearances) { return null; } if (exportedValue === undefined) { exportedValue = this.data.fieldValue; } else if (!Array.isArray(exportedValue)) { exportedValue = [exportedValue]; } const defaultPadding = 1; const defaultHPadding = 2; let totalHeight = this.data.rect[3] - this.data.rect[1]; let totalWidth = this.data.rect[2] - this.data.rect[0]; if (rotation === 90 || rotation === 270) { [totalWidth, totalHeight] = [totalHeight, totalWidth]; } const lineCount = this.data.options.length; const valueIndices = []; for (let i = 0; i < lineCount; i++) { const { exportValue } = this.data.options[i]; if (exportedValue.includes(exportValue)) { valueIndices.push(i); } } if (!this._defaultAppearance) { this.data.defaultAppearanceData = parseDefaultAppearance(this._defaultAppearance = "/Helvetica 0 Tf 0 g"); } const font = await WidgetAnnotation._getFontData(evaluator, task, this.data.defaultAppearanceData, this._fieldResources.mergedResources); let defaultAppearance; let { fontSize } = this.data.defaultAppearanceData; if (!fontSize) { const lineHeight = (totalHeight - defaultPadding) / lineCount; let lineWidth = -1; let value; for (const { displayValue } of this.data.options) { const width = this._getTextWidth(displayValue, font); if (width > lineWidth) { lineWidth = width; value = displayValue; } } [defaultAppearance, fontSize] = this._computeFontSize(lineHeight, totalWidth - 2 * defaultHPadding, value, font, -1); } else { defaultAppearance = this._defaultAppearance; } const lineHeight = fontSize * LINE_FACTOR; const vPadding = (lineHeight - fontSize) / 2; const numberOfVisibleLines = Math.floor(totalHeight / lineHeight); let firstIndex = 0; if (valueIndices.length > 0) { const minIndex = Math.min(...valueIndices); const maxIndex = Math.max(...valueIndices); firstIndex = Math.max(0, maxIndex - numberOfVisibleLines + 1); if (firstIndex > minIndex) { firstIndex = minIndex; } } const end = Math.min(firstIndex + numberOfVisibleLines + 1, lineCount); const buf = ["/Tx BMC q", `1 1 ${totalWidth} ${totalHeight} re W n`]; if (valueIndices.length) { buf.push("0.600006 0.756866 0.854904 rg"); for (const index of valueIndices) { if (firstIndex <= index && index < end) { buf.push(`1 ${totalHeight - (index - firstIndex + 1) * lineHeight} ${totalWidth} ${lineHeight} re f`); } } } buf.push("BT", defaultAppearance, `1 0 0 1 0 ${totalHeight} Tm`); const prevInfo = { shift: 0 }; for (let i = firstIndex; i < end; i++) { const { displayValue } = this.data.options[i]; const vpadding = i === firstIndex ? vPadding : 0; buf.push(this._renderText(displayValue, font, fontSize, totalWidth, 0, prevInfo, defaultHPadding, -lineHeight + vpadding)); } buf.push("ET Q EMC"); return buf.join("\n"); } } class SignatureWidgetAnnotation extends WidgetAnnotation { constructor(params) { super(params); this.data.fieldValue = null; this.data.hasOwnCanvas = this.data.noRotate; this.data.noHTML = !this.data.hasOwnCanvas; } getFieldObject() { return { id: this.data.id, value: null, page: this.data.pageIndex, type: "signature" }; } } class TextAnnotation extends MarkupAnnotation { constructor(params) { const DEFAULT_ICON_SIZE = 22; super(params); this.data.noRotate = true; this.data.hasOwnCanvas = this.data.noRotate; this.data.noHTML = false; const { dict } = params; this.data.annotationType = AnnotationType.TEXT; if (this.data.hasAppearance) { this.data.name = "NoIcon"; } else { this.data.rect[1] = this.data.rect[3] - DEFAULT_ICON_SIZE; this.data.rect[2] = this.data.rect[0] + DEFAULT_ICON_SIZE; this.data.name = dict.has("Name") ? dict.get("Name").name : "Note"; } if (dict.has("State")) { this.data.state = dict.get("State") || null; this.data.stateModel = dict.get("StateModel") || null; } else { this.data.state = null; this.data.stateModel = null; } } } class LinkAnnotation extends Annotation { constructor(params) { super(params); const { dict, annotationGlobals } = params; this.data.annotationType = AnnotationType.LINK; this.data.noHTML = false; const quadPoints = getQuadPoints(dict, this.rectangle); if (quadPoints) { this.data.quadPoints = quadPoints; } this.data.borderColor ||= this.data.color; Catalog.parseDestDictionary({ destDict: dict, resultObj: this.data, docBaseUrl: annotationGlobals.baseUrl, docAttachments: annotationGlobals.attachments }); } } class PopupAnnotation extends Annotation { constructor(params) { super(params); const { dict } = params; this.data.annotationType = AnnotationType.POPUP; this.data.noHTML = false; if (this.data.rect[0] === this.data.rect[2] || this.data.rect[1] === this.data.rect[3]) { this.data.rect = null; } let parentItem = dict.get("Parent"); if (!parentItem) { warn("Popup annotation has a missing or invalid parent annotation."); return; } this.data.parentRect = lookupNormalRect(parentItem.getArray("Rect"), null); const rt = parentItem.get("RT"); if (isName(rt, AnnotationReplyType.GROUP)) { parentItem = parentItem.get("IRT"); } if (!parentItem.has("M")) { this.data.modificationDate = null; } else { this.setModificationDate(parentItem.get("M")); this.data.modificationDate = this.modificationDate; } if (!parentItem.has("C")) { this.data.color = null; } else { this.setColor(parentItem.getArray("C")); this.data.color = this.color; } if (!this.viewable) { const parentFlags = parentItem.get("F"); if (this._isViewable(parentFlags)) { this.setFlags(parentFlags); } } this.setTitle(parentItem.get("T")); this.data.titleObj = this._title; this.setContents(parentItem.get("Contents")); this.data.contentsObj = this._contents; if (parentItem.has("RC")) { this.data.richText = XFAFactory.getRichTextAsHtml(parentItem.get("RC")); } this.data.open = !!dict.get("Open"); } } class FreeTextAnnotation extends MarkupAnnotation { constructor(params) { super(params); this.data.hasOwnCanvas = !this.data.noHTML; this.data.noHTML = false; const { evaluatorOptions, xref } = params; this.data.annotationType = AnnotationType.FREETEXT; this.setDefaultAppearance(params); this._hasAppearance = !!this.appearance; if (this._hasAppearance) { const { fontColor, fontSize } = parseAppearanceStream(this.appearance, evaluatorOptions, xref); this.data.defaultAppearanceData.fontColor = fontColor; this.data.defaultAppearanceData.fontSize = fontSize || 10; } else { this.data.defaultAppearanceData.fontSize ||= 10; const { fontColor, fontSize } = this.data.defaultAppearanceData; if (this._contents.str) { this.data.textContent = this._contents.str.split(/\r\n?|\n/).map(line => line.trimEnd()); const { coords, bbox, matrix } = FakeUnicodeFont.getFirstPositionInfo(this.rectangle, this.rotation, fontSize); this.data.textPosition = this._transformPoint(coords, bbox, matrix); } if (this._isOffscreenCanvasSupported) { const strokeAlpha = params.dict.get("CA"); const fakeUnicodeFont = new FakeUnicodeFont(xref, "sans-serif"); this.appearance = fakeUnicodeFont.createAppearance(this._contents.str, this.rectangle, this.rotation, fontSize, fontColor, strokeAlpha); this._streams.push(this.appearance); } else { warn("FreeTextAnnotation: OffscreenCanvas is not supported, annotation may not render correctly."); } } } get hasTextContent() { return this._hasAppearance; } static createNewDict(annotation, xref, { apRef, ap }) { const { color, fontSize, rect, rotation, user, value } = annotation; const freetext = new Dict(xref); freetext.set("Type", Name.get("Annot")); freetext.set("Subtype", Name.get("FreeText")); freetext.set("CreationDate", `D:${getModificationDate()}`); freetext.set("Rect", rect); const da = `/Helv ${fontSize} Tf ${getPdfColor(color, true)}`; freetext.set("DA", da); freetext.set("Contents", isAscii(value) ? value : stringToUTF16String(value, true)); freetext.set("F", 4); freetext.set("Border", [0, 0, 0]); freetext.set("Rotate", rotation); if (user) { freetext.set("T", isAscii(user) ? user : stringToUTF16String(user, true)); } if (apRef || ap) { const n = new Dict(xref); freetext.set("AP", n); if (apRef) { n.set("N", apRef); } else { n.set("N", ap); } } return freetext; } static async createNewAppearanceStream(annotation, xref, params) { const { baseFontRef, evaluator, task } = params; const { color, fontSize, rect, rotation, value } = annotation; const resources = new Dict(xref); const font = new Dict(xref); if (baseFontRef) { font.set("Helv", baseFontRef); } else { const baseFont = new Dict(xref); baseFont.set("BaseFont", Name.get("Helvetica")); baseFont.set("Type", Name.get("Font")); baseFont.set("Subtype", Name.get("Type1")); baseFont.set("Encoding", Name.get("WinAnsiEncoding")); font.set("Helv", baseFont); } resources.set("Font", font); const helv = await WidgetAnnotation._getFontData(evaluator, task, { fontName: "Helv", fontSize }, resources); const [x1, y1, x2, y2] = rect; let w = x2 - x1; let h = y2 - y1; if (rotation % 180 !== 0) { [w, h] = [h, w]; } const lines = value.split("\n"); const scale = fontSize / 1000; let totalWidth = -Infinity; const encodedLines = []; for (let line of lines) { const encoded = helv.encodeString(line); if (encoded.length > 1) { return null; } line = encoded.join(""); encodedLines.push(line); let lineWidth = 0; const glyphs = helv.charsToGlyphs(line); for (const glyph of glyphs) { lineWidth += glyph.width * scale; } totalWidth = Math.max(totalWidth, lineWidth); } let hscale = 1; if (totalWidth > w) { hscale = w / totalWidth; } let vscale = 1; const lineHeight = LINE_FACTOR * fontSize; const lineAscent = (LINE_FACTOR - LINE_DESCENT_FACTOR) * fontSize; const totalHeight = lineHeight * lines.length; if (totalHeight > h) { vscale = h / totalHeight; } const fscale = Math.min(hscale, vscale); const newFontSize = fontSize * fscale; let firstPoint, clipBox, matrix; switch (rotation) { case 0: matrix = [1, 0, 0, 1]; clipBox = [rect[0], rect[1], w, h]; firstPoint = [rect[0], rect[3] - lineAscent]; break; case 90: matrix = [0, 1, -1, 0]; clipBox = [rect[1], -rect[2], w, h]; firstPoint = [rect[1], -rect[0] - lineAscent]; break; case 180: matrix = [-1, 0, 0, -1]; clipBox = [-rect[2], -rect[3], w, h]; firstPoint = [-rect[2], -rect[1] - lineAscent]; break; case 270: matrix = [0, -1, 1, 0]; clipBox = [-rect[3], rect[0], w, h]; firstPoint = [-rect[3], rect[2] - lineAscent]; break; } const buffer = ["q", `${matrix.join(" ")} 0 0 cm`, `${clipBox.join(" ")} re W n`, `BT`, `${getPdfColor(color, true)}`, `0 Tc /Helv ${numberToString(newFontSize)} Tf`]; buffer.push(`${firstPoint.join(" ")} Td (${escapeString(encodedLines[0])}) Tj`); const vShift = numberToString(lineHeight); for (let i = 1, ii = encodedLines.length; i < ii; i++) { const line = encodedLines[i]; buffer.push(`0 -${vShift} Td (${escapeString(line)}) Tj`); } buffer.push("ET", "Q"); const appearance = buffer.join("\n"); const appearanceStreamDict = new Dict(xref); appearanceStreamDict.set("FormType", 1); appearanceStreamDict.set("Subtype", Name.get("Form")); appearanceStreamDict.set("Type", Name.get("XObject")); appearanceStreamDict.set("BBox", rect); appearanceStreamDict.set("Resources", resources); appearanceStreamDict.set("Matrix", [1, 0, 0, 1, -rect[0], -rect[1]]); const ap = new StringStream(appearance); ap.dict = appearanceStreamDict; return ap; } } class LineAnnotation extends MarkupAnnotation { constructor(params) { super(params); const { dict, xref } = params; this.data.annotationType = AnnotationType.LINE; this.data.hasOwnCanvas = this.data.noRotate; this.data.noHTML = false; const lineCoordinates = lookupRect(dict.getArray("L"), [0, 0, 0, 0]); this.data.lineCoordinates = Util.normalizeRect(lineCoordinates); this.setLineEndings(dict.getArray("LE")); this.data.lineEndings = this.lineEndings; if (!this.appearance) { const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0]; const strokeAlpha = dict.get("CA"); const interiorColor = getRgbColor(dict.getArray("IC"), null); const fillColor = interiorColor ? getPdfColorArray(interiorColor) : null; const fillAlpha = fillColor ? strokeAlpha : null; const borderWidth = this.borderStyle.width || 1, borderAdjust = 2 * borderWidth; const bbox = [this.data.lineCoordinates[0] - borderAdjust, this.data.lineCoordinates[1] - borderAdjust, this.data.lineCoordinates[2] + borderAdjust, this.data.lineCoordinates[3] + borderAdjust]; if (!Util.intersect(this.rectangle, bbox)) { this.rectangle = bbox; } this._setDefaultAppearance({ xref, extra: `${borderWidth} w`, strokeColor, fillColor, strokeAlpha, fillAlpha, pointsCallback: (buffer, points) => { buffer.push(`${lineCoordinates[0]} ${lineCoordinates[1]} m`, `${lineCoordinates[2]} ${lineCoordinates[3]} l`, "S"); return [points[0].x - borderWidth, points[1].x + borderWidth, points[3].y - borderWidth, points[1].y + borderWidth]; } }); } } } class SquareAnnotation extends MarkupAnnotation { constructor(params) { super(params); const { dict, xref } = params; this.data.annotationType = AnnotationType.SQUARE; this.data.hasOwnCanvas = this.data.noRotate; this.data.noHTML = false; if (!this.appearance) { const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0]; const strokeAlpha = dict.get("CA"); const interiorColor = getRgbColor(dict.getArray("IC"), null); const fillColor = interiorColor ? getPdfColorArray(interiorColor) : null; const fillAlpha = fillColor ? strokeAlpha : null; if (this.borderStyle.width === 0 && !fillColor) { return; } this._setDefaultAppearance({ xref, extra: `${this.borderStyle.width} w`, strokeColor, fillColor, strokeAlpha, fillAlpha, pointsCallback: (buffer, points) => { const x = points[2].x + this.borderStyle.width / 2; const y = points[2].y + this.borderStyle.width / 2; const width = points[3].x - points[2].x - this.borderStyle.width; const height = points[1].y - points[3].y - this.borderStyle.width; buffer.push(`${x} ${y} ${width} ${height} re`); if (fillColor) { buffer.push("B"); } else { buffer.push("S"); } return [points[0].x, points[1].x, points[3].y, points[1].y]; } }); } } } class CircleAnnotation extends MarkupAnnotation { constructor(params) { super(params); const { dict, xref } = params; this.data.annotationType = AnnotationType.CIRCLE; if (!this.appearance) { const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0]; const strokeAlpha = dict.get("CA"); const interiorColor = getRgbColor(dict.getArray("IC"), null); const fillColor = interiorColor ? getPdfColorArray(interiorColor) : null; const fillAlpha = fillColor ? strokeAlpha : null; if (this.borderStyle.width === 0 && !fillColor) { return; } const controlPointsDistance = 4 / 3 * Math.tan(Math.PI / (2 * 4)); this._setDefaultAppearance({ xref, extra: `${this.borderStyle.width} w`, strokeColor, fillColor, strokeAlpha, fillAlpha, pointsCallback: (buffer, points) => { const x0 = points[0].x + this.borderStyle.width / 2; const y0 = points[0].y - this.borderStyle.width / 2; const x1 = points[3].x - this.borderStyle.width / 2; const y1 = points[3].y + this.borderStyle.width / 2; const xMid = x0 + (x1 - x0) / 2; const yMid = y0 + (y1 - y0) / 2; const xOffset = (x1 - x0) / 2 * controlPointsDistance; const yOffset = (y1 - y0) / 2 * controlPointsDistance; buffer.push(`${xMid} ${y1} m`, `${xMid + xOffset} ${y1} ${x1} ${yMid + yOffset} ${x1} ${yMid} c`, `${x1} ${yMid - yOffset} ${xMid + xOffset} ${y0} ${xMid} ${y0} c`, `${xMid - xOffset} ${y0} ${x0} ${yMid - yOffset} ${x0} ${yMid} c`, `${x0} ${yMid + yOffset} ${xMid - xOffset} ${y1} ${xMid} ${y1} c`, "h"); if (fillColor) { buffer.push("B"); } else { buffer.push("S"); } return [points[0].x, points[1].x, points[3].y, points[1].y]; } }); } } } class PolylineAnnotation extends MarkupAnnotation { constructor(params) { super(params); const { dict, xref } = params; this.data.annotationType = AnnotationType.POLYLINE; this.data.hasOwnCanvas = this.data.noRotate; this.data.noHTML = false; this.data.vertices = []; if (!(this instanceof PolygonAnnotation)) { this.setLineEndings(dict.getArray("LE")); this.data.lineEndings = this.lineEndings; } const rawVertices = dict.getArray("Vertices"); if (!isNumberArray(rawVertices, null)) { return; } for (let i = 0, ii = rawVertices.length; i < ii; i += 2) { this.data.vertices.push({ x: rawVertices[i], y: rawVertices[i + 1] }); } if (!this.appearance) { const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0]; const strokeAlpha = dict.get("CA"); const borderWidth = this.borderStyle.width || 1, borderAdjust = 2 * borderWidth; const bbox = [Infinity, Infinity, -Infinity, -Infinity]; for (const vertex of this.data.vertices) { bbox[0] = Math.min(bbox[0], vertex.x - borderAdjust); bbox[1] = Math.min(bbox[1], vertex.y - borderAdjust); bbox[2] = Math.max(bbox[2], vertex.x + borderAdjust); bbox[3] = Math.max(bbox[3], vertex.y + borderAdjust); } if (!Util.intersect(this.rectangle, bbox)) { this.rectangle = bbox; } this._setDefaultAppearance({ xref, extra: `${borderWidth} w`, strokeColor, strokeAlpha, pointsCallback: (buffer, points) => { const vertices = this.data.vertices; for (let i = 0, ii = vertices.length; i < ii; i++) { buffer.push(`${vertices[i].x} ${vertices[i].y} ${i === 0 ? "m" : "l"}`); } buffer.push("S"); return [points[0].x, points[1].x, points[3].y, points[1].y]; } }); } } } class PolygonAnnotation extends PolylineAnnotation { constructor(params) { super(params); this.data.annotationType = AnnotationType.POLYGON; } } class CaretAnnotation extends MarkupAnnotation { constructor(params) { super(params); this.data.annotationType = AnnotationType.CARET; } } class InkAnnotation extends MarkupAnnotation { constructor(params) { super(params); this.data.hasOwnCanvas = this.data.noRotate; this.data.noHTML = false; const { dict, xref } = params; this.data.annotationType = AnnotationType.INK; this.data.inkLists = []; const rawInkLists = dict.getArray("InkList"); if (!Array.isArray(rawInkLists)) { return; } for (let i = 0, ii = rawInkLists.length; i < ii; ++i) { this.data.inkLists.push([]); if (!Array.isArray(rawInkLists[i])) { continue; } for (let j = 0, jj = rawInkLists[i].length; j < jj; j += 2) { const x = xref.fetchIfRef(rawInkLists[i][j]), y = xref.fetchIfRef(rawInkLists[i][j + 1]); if (typeof x === "number" && typeof y === "number") { this.data.inkLists[i].push({ x, y }); } } } if (!this.appearance) { const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0]; const strokeAlpha = dict.get("CA"); const borderWidth = this.borderStyle.width || 1, borderAdjust = 2 * borderWidth; const bbox = [Infinity, Infinity, -Infinity, -Infinity]; for (const inkLists of this.data.inkLists) { for (const vertex of inkLists) { bbox[0] = Math.min(bbox[0], vertex.x - borderAdjust); bbox[1] = Math.min(bbox[1], vertex.y - borderAdjust); bbox[2] = Math.max(bbox[2], vertex.x + borderAdjust); bbox[3] = Math.max(bbox[3], vertex.y + borderAdjust); } } if (!Util.intersect(this.rectangle, bbox)) { this.rectangle = bbox; } this._setDefaultAppearance({ xref, extra: `${borderWidth} w`, strokeColor, strokeAlpha, pointsCallback: (buffer, points) => { for (const inkList of this.data.inkLists) { for (let i = 0, ii = inkList.length; i < ii; i++) { buffer.push(`${inkList[i].x} ${inkList[i].y} ${i === 0 ? "m" : "l"}`); } buffer.push("S"); } return [points[0].x, points[1].x, points[3].y, points[1].y]; } }); } } static createNewDict(annotation, xref, { apRef, ap }) { const { color, opacity, paths, outlines, rect, rotation, thickness } = annotation; const ink = new Dict(xref); ink.set("Type", Name.get("Annot")); ink.set("Subtype", Name.get("Ink")); ink.set("CreationDate", `D:${getModificationDate()}`); ink.set("Rect", rect); ink.set("InkList", outlines?.points || paths.map(p => p.points)); ink.set("F", 4); ink.set("Rotate", rotation); if (outlines) { ink.set("IT", Name.get("InkHighlight")); } const bs = new Dict(xref); ink.set("BS", bs); bs.set("W", thickness); ink.set("C", Array.from(color, c => c / 255)); ink.set("CA", opacity); const n = new Dict(xref); ink.set("AP", n); if (apRef) { n.set("N", apRef); } else { n.set("N", ap); } return ink; } static async createNewAppearanceStream(annotation, xref, params) { if (annotation.outlines) { return this.createNewAppearanceStreamForHighlight(annotation, xref, params); } const { color, rect, paths, thickness, opacity } = annotation; const appearanceBuffer = [`${thickness} w 1 J 1 j`, `${getPdfColor(color, false)}`]; if (opacity !== 1) { appearanceBuffer.push("/R0 gs"); } const buffer = []; for (const { bezier } of paths) { buffer.length = 0; buffer.push(`${numberToString(bezier[0])} ${numberToString(bezier[1])} m`); if (bezier.length === 2) { buffer.push(`${numberToString(bezier[0])} ${numberToString(bezier[1])} l S`); } else { for (let i = 2, ii = bezier.length; i < ii; i += 6) { const curve = bezier.slice(i, i + 6).map(numberToString).join(" "); buffer.push(`${curve} c`); } buffer.push("S"); } appearanceBuffer.push(buffer.join("\n")); } const appearance = appearanceBuffer.join("\n"); const appearanceStreamDict = new Dict(xref); appearanceStreamDict.set("FormType", 1); appearanceStreamDict.set("Subtype", Name.get("Form")); appearanceStreamDict.set("Type", Name.get("XObject")); appearanceStreamDict.set("BBox", rect); appearanceStreamDict.set("Length", appearance.length); if (opacity !== 1) { const resources = new Dict(xref); const extGState = new Dict(xref); const r0 = new Dict(xref); r0.set("CA", opacity); r0.set("Type", Name.get("ExtGState")); extGState.set("R0", r0); resources.set("ExtGState", extGState); appearanceStreamDict.set("Resources", resources); } const ap = new StringStream(appearance); ap.dict = appearanceStreamDict; return ap; } static async createNewAppearanceStreamForHighlight(annotation, xref, params) { const { color, rect, outlines: { outline }, opacity } = annotation; const appearanceBuffer = [`${getPdfColor(color, true)}`, "/R0 gs"]; appearanceBuffer.push(`${numberToString(outline[4])} ${numberToString(outline[5])} m`); for (let i = 6, ii = outline.length; i < ii; i += 6) { if (isNaN(outline[i]) || outline[i] === null) { appearanceBuffer.push(`${numberToString(outline[i + 4])} ${numberToString(outline[i + 5])} l`); } else { const curve = outline.slice(i, i + 6).map(numberToString).join(" "); appearanceBuffer.push(`${curve} c`); } } appearanceBuffer.push("h f"); const appearance = appearanceBuffer.join("\n"); const appearanceStreamDict = new Dict(xref); appearanceStreamDict.set("FormType", 1); appearanceStreamDict.set("Subtype", Name.get("Form")); appearanceStreamDict.set("Type", Name.get("XObject")); appearanceStreamDict.set("BBox", rect); appearanceStreamDict.set("Length", appearance.length); const resources = new Dict(xref); const extGState = new Dict(xref); resources.set("ExtGState", extGState); appearanceStreamDict.set("Resources", resources); const r0 = new Dict(xref); extGState.set("R0", r0); r0.set("BM", Name.get("Multiply")); if (opacity !== 1) { r0.set("ca", opacity); r0.set("Type", Name.get("ExtGState")); } const ap = new StringStream(appearance); ap.dict = appearanceStreamDict; return ap; } } class HighlightAnnotation extends MarkupAnnotation { constructor(params) { super(params); const { dict, xref } = params; this.data.annotationType = AnnotationType.HIGHLIGHT; const quadPoints = this.data.quadPoints = getQuadPoints(dict, null); if (quadPoints) { const resources = this.appearance?.dict.get("Resources"); if (!this.appearance || !resources?.has("ExtGState")) { if (this.appearance) { warn("HighlightAnnotation - ignoring built-in appearance stream."); } const fillColor = this.color ? getPdfColorArray(this.color) : [1, 1, 0]; const fillAlpha = dict.get("CA"); this._setDefaultAppearance({ xref, fillColor, blendMode: "Multiply", fillAlpha, pointsCallback: (buffer, points) => { buffer.push(`${points[0].x} ${points[0].y} m`, `${points[1].x} ${points[1].y} l`, `${points[3].x} ${points[3].y} l`, `${points[2].x} ${points[2].y} l`, "f"); return [points[0].x, points[1].x, points[3].y, points[1].y]; } }); } } else { this.data.popupRef = null; } } static createNewDict(annotation, xref, { apRef, ap }) { const { color, opacity, rect, rotation, user, quadPoints } = annotation; const highlight = new Dict(xref); highlight.set("Type", Name.get("Annot")); highlight.set("Subtype", Name.get("Highlight")); highlight.set("CreationDate", `D:${getModificationDate()}`); highlight.set("Rect", rect); highlight.set("F", 4); highlight.set("Border", [0, 0, 0]); highlight.set("Rotate", rotation); highlight.set("QuadPoints", quadPoints); highlight.set("C", Array.from(color, c => c / 255)); highlight.set("CA", opacity); if (user) { highlight.set("T", isAscii(user) ? user : stringToUTF16String(user, true)); } if (apRef || ap) { const n = new Dict(xref); highlight.set("AP", n); n.set("N", apRef || ap); } return highlight; } static async createNewAppearanceStream(annotation, xref, params) { const { color, rect, outlines, opacity } = annotation; const appearanceBuffer = [`${getPdfColor(color, true)}`, "/R0 gs"]; const buffer = []; for (const outline of outlines) { buffer.length = 0; buffer.push(`${numberToString(outline[0])} ${numberToString(outline[1])} m`); for (let i = 2, ii = outline.length; i < ii; i += 2) { buffer.push(`${numberToString(outline[i])} ${numberToString(outline[i + 1])} l`); } buffer.push("h"); appearanceBuffer.push(buffer.join("\n")); } appearanceBuffer.push("f*"); const appearance = appearanceBuffer.join("\n"); const appearanceStreamDict = new Dict(xref); appearanceStreamDict.set("FormType", 1); appearanceStreamDict.set("Subtype", Name.get("Form")); appearanceStreamDict.set("Type", Name.get("XObject")); appearanceStreamDict.set("BBox", rect); appearanceStreamDict.set("Length", appearance.length); const resources = new Dict(xref); const extGState = new Dict(xref); resources.set("ExtGState", extGState); appearanceStreamDict.set("Resources", resources); const r0 = new Dict(xref); extGState.set("R0", r0); r0.set("BM", Name.get("Multiply")); if (opacity !== 1) { r0.set("ca", opacity); r0.set("Type", Name.get("ExtGState")); } const ap = new StringStream(appearance); ap.dict = appearanceStreamDict; return ap; } } class UnderlineAnnotation extends MarkupAnnotation { constructor(params) { super(params); const { dict, xref } = params; this.data.annotationType = AnnotationType.UNDERLINE; const quadPoints = this.data.quadPoints = getQuadPoints(dict, null); if (quadPoints) { if (!this.appearance) { const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0]; const strokeAlpha = dict.get("CA"); this._setDefaultAppearance({ xref, extra: "[] 0 d 0.571 w", strokeColor, strokeAlpha, pointsCallback: (buffer, points) => { buffer.push(`${points[2].x} ${points[2].y + 1.3} m`, `${points[3].x} ${points[3].y + 1.3} l`, "S"); return [points[0].x, points[1].x, points[3].y, points[1].y]; } }); } } else { this.data.popupRef = null; } } } class SquigglyAnnotation extends MarkupAnnotation { constructor(params) { super(params); const { dict, xref } = params; this.data.annotationType = AnnotationType.SQUIGGLY; const quadPoints = this.data.quadPoints = getQuadPoints(dict, null); if (quadPoints) { if (!this.appearance) { const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0]; const strokeAlpha = dict.get("CA"); this._setDefaultAppearance({ xref, extra: "[] 0 d 1 w", strokeColor, strokeAlpha, pointsCallback: (buffer, points) => { const dy = (points[0].y - points[2].y) / 6; let shift = dy; let x = points[2].x; const y = points[2].y; const xEnd = points[3].x; buffer.push(`${x} ${y + shift} m`); do { x += 2; shift = shift === 0 ? dy : 0; buffer.push(`${x} ${y + shift} l`); } while (x < xEnd); buffer.push("S"); return [points[2].x, xEnd, y - 2 * dy, y + 2 * dy]; } }); } } else { this.data.popupRef = null; } } } class StrikeOutAnnotation extends MarkupAnnotation { constructor(params) { super(params); const { dict, xref } = params; this.data.annotationType = AnnotationType.STRIKEOUT; const quadPoints = this.data.quadPoints = getQuadPoints(dict, null); if (quadPoints) { if (!this.appearance) { const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0]; const strokeAlpha = dict.get("CA"); this._setDefaultAppearance({ xref, extra: "[] 0 d 1 w", strokeColor, strokeAlpha, pointsCallback: (buffer, points) => { buffer.push(`${(points[0].x + points[2].x) / 2} ` + `${(points[0].y + points[2].y) / 2} m`, `${(points[1].x + points[3].x) / 2} ` + `${(points[1].y + points[3].y) / 2} l`, "S"); return [points[0].x, points[1].x, points[3].y, points[1].y]; } }); } } else { this.data.popupRef = null; } } } class StampAnnotation extends MarkupAnnotation { constructor(params) { super(params); this.data.annotationType = AnnotationType.STAMP; this.data.hasOwnCanvas = this.data.noRotate; this.data.noHTML = false; } static async createImage(bitmap, xref) { const { width, height } = bitmap; const canvas = new OffscreenCanvas(width, height); const ctx = canvas.getContext("2d", { alpha: true }); ctx.drawImage(bitmap, 0, 0); const data = ctx.getImageData(0, 0, width, height).data; const buf32 = new Uint32Array(data.buffer); const hasAlpha = buf32.some(FeatureTest.isLittleEndian ? x => x >>> 24 !== 0xff : x => (x & 0xff) !== 0xff); if (hasAlpha) { ctx.fillStyle = "white"; ctx.fillRect(0, 0, width, height); ctx.drawImage(bitmap, 0, 0); } const jpegBufferPromise = canvas.convertToBlob({ type: "image/jpeg", quality: 1 }).then(blob => blob.arrayBuffer()); const xobjectName = Name.get("XObject"); const imageName = Name.get("Image"); const image = new Dict(xref); image.set("Type", xobjectName); image.set("Subtype", imageName); image.set("BitsPerComponent", 8); image.set("ColorSpace", Name.get("DeviceRGB")); image.set("Filter", Name.get("DCTDecode")); image.set("BBox", [0, 0, width, height]); image.set("Width", width); image.set("Height", height); let smaskStream = null; if (hasAlpha) { const alphaBuffer = new Uint8Array(buf32.length); if (FeatureTest.isLittleEndian) { for (let i = 0, ii = buf32.length; i < ii; i++) { alphaBuffer[i] = buf32[i] >>> 24; } } else { for (let i = 0, ii = buf32.length; i < ii; i++) { alphaBuffer[i] = buf32[i] & 0xff; } } const smask = new Dict(xref); smask.set("Type", xobjectName); smask.set("Subtype", imageName); smask.set("BitsPerComponent", 8); smask.set("ColorSpace", Name.get("DeviceGray")); smask.set("Width", width); smask.set("Height", height); smaskStream = new Stream(alphaBuffer, 0, 0, smask); } const imageStream = new Stream(await jpegBufferPromise, 0, 0, image); return { imageStream, smaskStream, width, height }; } static createNewDict(annotation, xref, { apRef, ap }) { const { rect, rotation, user } = annotation; const stamp = new Dict(xref); stamp.set("Type", Name.get("Annot")); stamp.set("Subtype", Name.get("Stamp")); stamp.set("CreationDate", `D:${getModificationDate()}`); stamp.set("Rect", rect); stamp.set("F", 4); stamp.set("Border", [0, 0, 0]); stamp.set("Rotate", rotation); if (user) { stamp.set("T", isAscii(user) ? user : stringToUTF16String(user, true)); } if (apRef || ap) { const n = new Dict(xref); stamp.set("AP", n); if (apRef) { n.set("N", apRef); } else { n.set("N", ap); } } return stamp; } static async createNewAppearanceStream(annotation, xref, params) { const { rotation } = annotation; const { imageRef, width, height } = params.image; const resources = new Dict(xref); const xobject = new Dict(xref); resources.set("XObject", xobject); xobject.set("Im0", imageRef); const appearance = `q ${width} 0 0 ${height} 0 0 cm /Im0 Do Q`; const appearanceStreamDict = new Dict(xref); appearanceStreamDict.set("FormType", 1); appearanceStreamDict.set("Subtype", Name.get("Form")); appearanceStreamDict.set("Type", Name.get("XObject")); appearanceStreamDict.set("BBox", [0, 0, width, height]); appearanceStreamDict.set("Resources", resources); if (rotation) { const matrix = getRotationMatrix(rotation, width, height); appearanceStreamDict.set("Matrix", matrix); } const ap = new StringStream(appearance); ap.dict = appearanceStreamDict; return ap; } } class FileAttachmentAnnotation extends MarkupAnnotation { constructor(params) { super(params); const { dict, xref } = params; const file = new FileSpec(dict.get("FS"), xref); this.data.annotationType = AnnotationType.FILEATTACHMENT; this.data.hasOwnCanvas = this.data.noRotate; this.data.noHTML = false; this.data.file = file.serializable; const name = dict.get("Name"); this.data.name = name instanceof Name ? stringToPDFString(name.name) : "PushPin"; const fillAlpha = dict.get("ca"); this.data.fillAlpha = typeof fillAlpha === "number" && fillAlpha >= 0 && fillAlpha <= 1 ? fillAlpha : null; } } ;// CONCATENATED MODULE: ./src/core/dataset_reader.js function decodeString(str) { try { return stringToUTF8String(str); } catch (ex) { warn(`UTF-8 decoding failed: "${ex}".`); return str; } } class DatasetXMLParser extends SimpleXMLParser { constructor(options) { super(options); this.node = null; } onEndElement(name) { const node = super.onEndElement(name); if (node && name === "xfa:datasets") { this.node = node; throw new Error("Aborting DatasetXMLParser."); } } } class DatasetReader { constructor(data) { if (data.datasets) { this.node = new SimpleXMLParser({ hasAttributes: true }).parseFromString(data.datasets).documentElement; } else { const parser = new DatasetXMLParser({ hasAttributes: true }); try { parser.parseFromString(data["xdp:xdp"]); } catch {} this.node = parser.node; } } getValue(path) { if (!this.node || !path) { return ""; } const node = this.node.searchNode(parseXFAPath(path), 0); if (!node) { return ""; } const first = node.firstChild; if (first?.nodeName === "value") { return node.children.map(child => decodeString(child.textContent)); } return decodeString(node.textContent); } } ;// CONCATENATED MODULE: ./src/core/xref.js class XRef { #firstXRefStmPos = null; constructor(stream, pdfManager) { this.stream = stream; this.pdfManager = pdfManager; this.entries = []; this._xrefStms = new Set(); this._cacheMap = new Map(); this._pendingRefs = new RefSet(); this._newPersistentRefNum = null; this._newTemporaryRefNum = null; this._persistentRefsCache = null; } getNewPersistentRef(obj) { if (this._newPersistentRefNum === null) { this._newPersistentRefNum = this.entries.length || 1; } const num = this._newPersistentRefNum++; this._cacheMap.set(num, obj); return Ref.get(num, 0); } getNewTemporaryRef() { if (this._newTemporaryRefNum === null) { this._newTemporaryRefNum = this.entries.length || 1; if (this._newPersistentRefNum) { this._persistentRefsCache = new Map(); for (let i = this._newTemporaryRefNum; i < this._newPersistentRefNum; i++) { this._persistentRefsCache.set(i, this._cacheMap.get(i)); this._cacheMap.delete(i); } } } return Ref.get(this._newTemporaryRefNum++, 0); } resetNewTemporaryRef() { this._newTemporaryRefNum = null; if (this._persistentRefsCache) { for (const [num, obj] of this._persistentRefsCache) { this._cacheMap.set(num, obj); } } this._persistentRefsCache = null; } setStartXRef(startXRef) { this.startXRefQueue = [startXRef]; } parse(recoveryMode = false) { let trailerDict; if (!recoveryMode) { trailerDict = this.readXRef(); } else { warn("Indexing all PDF objects"); trailerDict = this.indexObjects(); } trailerDict.assignXref(this); this.trailer = trailerDict; let encrypt; try { encrypt = trailerDict.get("Encrypt"); } catch (ex) { if (ex instanceof MissingDataException) { throw ex; } warn(`XRef.parse - Invalid "Encrypt" reference: "${ex}".`); } if (encrypt instanceof Dict) { const ids = trailerDict.get("ID"); const fileId = ids?.length ? ids[0] : ""; encrypt.suppressEncryption = true; this.encrypt = new CipherTransformFactory(encrypt, fileId, this.pdfManager.password); } let root; try { root = trailerDict.get("Root"); } catch (ex) { if (ex instanceof MissingDataException) { throw ex; } warn(`XRef.parse - Invalid "Root" reference: "${ex}".`); } if (root instanceof Dict) { try { const pages = root.get("Pages"); if (pages instanceof Dict) { this.root = root; return; } } catch (ex) { if (ex instanceof MissingDataException) { throw ex; } warn(`XRef.parse - Invalid "Pages" reference: "${ex}".`); } } if (!recoveryMode) { throw new XRefParseException(); } throw new InvalidPDFException("Invalid Root reference."); } processXRefTable(parser) { if (!("tableState" in this)) { this.tableState = { entryNum: 0, streamPos: parser.lexer.stream.pos, parserBuf1: parser.buf1, parserBuf2: parser.buf2 }; } const obj = this.readXRefTable(parser); if (!isCmd(obj, "trailer")) { throw new FormatError("Invalid XRef table: could not find trailer dictionary"); } let dict = parser.getObj(); if (!(dict instanceof Dict) && dict.dict) { dict = dict.dict; } if (!(dict instanceof Dict)) { throw new FormatError("Invalid XRef table: could not parse trailer dictionary"); } delete this.tableState; return dict; } readXRefTable(parser) { const stream = parser.lexer.stream; const tableState = this.tableState; stream.pos = tableState.streamPos; parser.buf1 = tableState.parserBuf1; parser.buf2 = tableState.parserBuf2; let obj; while (true) { if (!("firstEntryNum" in tableState) || !("entryCount" in tableState)) { if (isCmd(obj = parser.getObj(), "trailer")) { break; } tableState.firstEntryNum = obj; tableState.entryCount = parser.getObj(); } let first = tableState.firstEntryNum; const count = tableState.entryCount; if (!Number.isInteger(first) || !Number.isInteger(count)) { throw new FormatError("Invalid XRef table: wrong types in subsection header"); } for (let i = tableState.entryNum; i < count; i++) { tableState.streamPos = stream.pos; tableState.entryNum = i; tableState.parserBuf1 = parser.buf1; tableState.parserBuf2 = parser.buf2; const entry = {}; entry.offset = parser.getObj(); entry.gen = parser.getObj(); const type = parser.getObj(); if (type instanceof Cmd) { switch (type.cmd) { case "f": entry.free = true; break; case "n": entry.uncompressed = true; break; } } if (!Number.isInteger(entry.offset) || !Number.isInteger(entry.gen) || !(entry.free || entry.uncompressed)) { throw new FormatError(`Invalid entry in XRef subsection: ${first}, ${count}`); } if (i === 0 && entry.free && first === 1) { first = 0; } if (!this.entries[i + first]) { this.entries[i + first] = entry; } } tableState.entryNum = 0; tableState.streamPos = stream.pos; tableState.parserBuf1 = parser.buf1; tableState.parserBuf2 = parser.buf2; delete tableState.firstEntryNum; delete tableState.entryCount; } if (this.entries[0] && !this.entries[0].free) { throw new FormatError("Invalid XRef table: unexpected first object"); } return obj; } processXRefStream(stream) { if (!("streamState" in this)) { const streamParameters = stream.dict; const byteWidths = streamParameters.get("W"); let range = streamParameters.get("Index"); if (!range) { range = [0, streamParameters.get("Size")]; } this.streamState = { entryRanges: range, byteWidths, entryNum: 0, streamPos: stream.pos }; } this.readXRefStream(stream); delete this.streamState; return stream.dict; } readXRefStream(stream) { const streamState = this.streamState; stream.pos = streamState.streamPos; const [typeFieldWidth, offsetFieldWidth, generationFieldWidth] = streamState.byteWidths; const entryRanges = streamState.entryRanges; while (entryRanges.length > 0) { const [first, n] = entryRanges; if (!Number.isInteger(first) || !Number.isInteger(n)) { throw new FormatError(`Invalid XRef range fields: ${first}, ${n}`); } if (!Number.isInteger(typeFieldWidth) || !Number.isInteger(offsetFieldWidth) || !Number.isInteger(generationFieldWidth)) { throw new FormatError(`Invalid XRef entry fields length: ${first}, ${n}`); } for (let i = streamState.entryNum; i < n; ++i) { streamState.entryNum = i; streamState.streamPos = stream.pos; let type = 0, offset = 0, generation = 0; for (let j = 0; j < typeFieldWidth; ++j) { const typeByte = stream.getByte(); if (typeByte === -1) { throw new FormatError("Invalid XRef byteWidths 'type'."); } type = type << 8 | typeByte; } if (typeFieldWidth === 0) { type = 1; } for (let j = 0; j < offsetFieldWidth; ++j) { const offsetByte = stream.getByte(); if (offsetByte === -1) { throw new FormatError("Invalid XRef byteWidths 'offset'."); } offset = offset << 8 | offsetByte; } for (let j = 0; j < generationFieldWidth; ++j) { const generationByte = stream.getByte(); if (generationByte === -1) { throw new FormatError("Invalid XRef byteWidths 'generation'."); } generation = generation << 8 | generationByte; } const entry = {}; entry.offset = offset; entry.gen = generation; switch (type) { case 0: entry.free = true; break; case 1: entry.uncompressed = true; break; case 2: break; default: throw new FormatError(`Invalid XRef entry type: ${type}`); } if (!this.entries[first + i]) { this.entries[first + i] = entry; } } streamState.entryNum = 0; streamState.streamPos = stream.pos; entryRanges.splice(0, 2); } } indexObjects() { const TAB = 0x9, LF = 0xa, CR = 0xd, SPACE = 0x20; const PERCENT = 0x25, LT = 0x3c; function readToken(data, offset) { let token = "", ch = data[offset]; while (ch !== LF && ch !== CR && ch !== LT) { if (++offset >= data.length) { break; } token += String.fromCharCode(ch); ch = data[offset]; } return token; } function skipUntil(data, offset, what) { const length = what.length, dataLength = data.length; let skipped = 0; while (offset < dataLength) { let i = 0; while (i < length && data[offset + i] === what[i]) { ++i; } if (i >= length) { break; } offset++; skipped++; } return skipped; } const gEndobjRegExp = /\b(endobj|\d+\s+\d+\s+obj|xref|trailer\s*<<)\b/g; const gStartxrefRegExp = /\b(startxref|\d+\s+\d+\s+obj)\b/g; const objRegExp = /^(\d+)\s+(\d+)\s+obj\b/; const trailerBytes = new Uint8Array([116, 114, 97, 105, 108, 101, 114]); const startxrefBytes = new Uint8Array([115, 116, 97, 114, 116, 120, 114, 101, 102]); const xrefBytes = new Uint8Array([47, 88, 82, 101, 102]); this.entries.length = 0; this._cacheMap.clear(); const stream = this.stream; stream.pos = 0; const buffer = stream.getBytes(), bufferStr = bytesToString(buffer), length = buffer.length; let position = stream.start; const trailers = [], xrefStms = []; while (position < length) { let ch = buffer[position]; if (ch === TAB || ch === LF || ch === CR || ch === SPACE) { ++position; continue; } if (ch === PERCENT) { do { ++position; if (position >= length) { break; } ch = buffer[position]; } while (ch !== LF && ch !== CR); continue; } const token = readToken(buffer, position); let m; if (token.startsWith("xref") && (token.length === 4 || /\s/.test(token[4]))) { position += skipUntil(buffer, position, trailerBytes); trailers.push(position); position += skipUntil(buffer, position, startxrefBytes); } else if (m = objRegExp.exec(token)) { const num = m[1] | 0, gen = m[2] | 0; const startPos = position + token.length; let contentLength, updateEntries = false; if (!this.entries[num]) { updateEntries = true; } else if (this.entries[num].gen === gen) { try { const parser = new Parser({ lexer: new Lexer(stream.makeSubStream(startPos)) }); parser.getObj(); updateEntries = true; } catch (ex) { if (ex instanceof ParserEOFException) { warn(`indexObjects -- checking object (${token}): "${ex}".`); } else { updateEntries = true; } } } if (updateEntries) { this.entries[num] = { offset: position - stream.start, gen, uncompressed: true }; } gEndobjRegExp.lastIndex = startPos; const match = gEndobjRegExp.exec(bufferStr); if (match) { const endPos = gEndobjRegExp.lastIndex + 1; contentLength = endPos - position; if (match[1] !== "endobj") { warn(`indexObjects: Found "${match[1]}" inside of another "obj", ` + 'caused by missing "endobj" -- trying to recover.'); contentLength -= match[1].length + 1; } } else { contentLength = length - position; } const content = buffer.subarray(position, position + contentLength); const xrefTagOffset = skipUntil(content, 0, xrefBytes); if (xrefTagOffset < contentLength && content[xrefTagOffset + 5] < 64) { xrefStms.push(position - stream.start); this._xrefStms.add(position - stream.start); } position += contentLength; } else if (token.startsWith("trailer") && (token.length === 7 || /\s/.test(token[7]))) { trailers.push(position); const startPos = position + token.length; let contentLength; gStartxrefRegExp.lastIndex = startPos; const match = gStartxrefRegExp.exec(bufferStr); if (match) { const endPos = gStartxrefRegExp.lastIndex + 1; contentLength = endPos - position; if (match[1] !== "startxref") { warn(`indexObjects: Found "${match[1]}" after "trailer", ` + 'caused by missing "startxref" -- trying to recover.'); contentLength -= match[1].length + 1; } } else { contentLength = length - position; } position += contentLength; } else { position += token.length + 1; } } for (const xrefStm of xrefStms) { this.startXRefQueue.push(xrefStm); this.readXRef(true); } const trailerDicts = []; let isEncrypted = false; for (const trailer of trailers) { stream.pos = trailer; const parser = new Parser({ lexer: new Lexer(stream), xref: this, allowStreams: true, recoveryMode: true }); const obj = parser.getObj(); if (!isCmd(obj, "trailer")) { continue; } const dict = parser.getObj(); if (!(dict instanceof Dict)) { continue; } trailerDicts.push(dict); if (dict.has("Encrypt")) { isEncrypted = true; } } let trailerDict, trailerError; for (const dict of [...trailerDicts, "genFallback", ...trailerDicts]) { if (dict === "genFallback") { if (!trailerError) { break; } this._generationFallback = true; continue; } let validPagesDict = false; try { const rootDict = dict.get("Root"); if (!(rootDict instanceof Dict)) { continue; } const pagesDict = rootDict.get("Pages"); if (!(pagesDict instanceof Dict)) { continue; } const pagesCount = pagesDict.get("Count"); if (Number.isInteger(pagesCount)) { validPagesDict = true; } } catch (ex) { trailerError = ex; continue; } if (validPagesDict && (!isEncrypted || dict.has("Encrypt")) && dict.has("ID")) { return dict; } trailerDict = dict; } if (trailerDict) { return trailerDict; } if (this.topDict) { return this.topDict; } throw new InvalidPDFException("Invalid PDF structure."); } readXRef(recoveryMode = false) { const stream = this.stream; const startXRefParsedCache = new Set(); while (this.startXRefQueue.length) { try { const startXRef = this.startXRefQueue[0]; if (startXRefParsedCache.has(startXRef)) { warn("readXRef - skipping XRef table since it was already parsed."); this.startXRefQueue.shift(); continue; } startXRefParsedCache.add(startXRef); stream.pos = startXRef + stream.start; const parser = new Parser({ lexer: new Lexer(stream), xref: this, allowStreams: true }); let obj = parser.getObj(); let dict; if (isCmd(obj, "xref")) { dict = this.processXRefTable(parser); if (!this.topDict) { this.topDict = dict; } obj = dict.get("XRefStm"); if (Number.isInteger(obj) && !this._xrefStms.has(obj)) { this._xrefStms.add(obj); this.startXRefQueue.push(obj); this.#firstXRefStmPos ??= obj; } } else if (Number.isInteger(obj)) { if (!Number.isInteger(parser.getObj()) || !isCmd(parser.getObj(), "obj") || !((obj = parser.getObj()) instanceof BaseStream)) { throw new FormatError("Invalid XRef stream"); } dict = this.processXRefStream(obj); if (!this.topDict) { this.topDict = dict; } if (!dict) { throw new FormatError("Failed to read XRef stream"); } } else { throw new FormatError("Invalid XRef stream header"); } obj = dict.get("Prev"); if (Number.isInteger(obj)) { this.startXRefQueue.push(obj); } else if (obj instanceof Ref) { this.startXRefQueue.push(obj.num); } } catch (e) { if (e instanceof MissingDataException) { throw e; } info("(while reading XRef): " + e); } this.startXRefQueue.shift(); } if (this.topDict) { return this.topDict; } if (recoveryMode) { return undefined; } throw new XRefParseException(); } get lastXRefStreamPos() { return this.#firstXRefStmPos ?? (this._xrefStms.size > 0 ? Math.max(...this._xrefStms) : null); } getEntry(i) { const xrefEntry = this.entries[i]; if (xrefEntry && !xrefEntry.free && xrefEntry.offset) { return xrefEntry; } return null; } fetchIfRef(obj, suppressEncryption = false) { if (obj instanceof Ref) { return this.fetch(obj, suppressEncryption); } return obj; } fetch(ref, suppressEncryption = false) { if (!(ref instanceof Ref)) { throw new Error("ref object is not a reference"); } const num = ref.num; const cacheEntry = this._cacheMap.get(num); if (cacheEntry !== undefined) { if (cacheEntry instanceof Dict && !cacheEntry.objId) { cacheEntry.objId = ref.toString(); } return cacheEntry; } let xrefEntry = this.getEntry(num); if (xrefEntry === null) { this._cacheMap.set(num, xrefEntry); return xrefEntry; } if (this._pendingRefs.has(ref)) { this._pendingRefs.remove(ref); warn(`Ignoring circular reference: ${ref}.`); return CIRCULAR_REF; } this._pendingRefs.put(ref); try { xrefEntry = xrefEntry.uncompressed ? this.fetchUncompressed(ref, xrefEntry, suppressEncryption) : this.fetchCompressed(ref, xrefEntry, suppressEncryption); this._pendingRefs.remove(ref); } catch (ex) { this._pendingRefs.remove(ref); throw ex; } if (xrefEntry instanceof Dict) { xrefEntry.objId = ref.toString(); } else if (xrefEntry instanceof BaseStream) { xrefEntry.dict.objId = ref.toString(); } return xrefEntry; } fetchUncompressed(ref, xrefEntry, suppressEncryption = false) { const gen = ref.gen; let num = ref.num; if (xrefEntry.gen !== gen) { const msg = `Inconsistent generation in XRef: ${ref}`; if (this._generationFallback && xrefEntry.gen < gen) { warn(msg); return this.fetchUncompressed(Ref.get(num, xrefEntry.gen), xrefEntry, suppressEncryption); } throw new XRefEntryException(msg); } const stream = this.stream.makeSubStream(xrefEntry.offset + this.stream.start); const parser = new Parser({ lexer: new Lexer(stream), xref: this, allowStreams: true }); const obj1 = parser.getObj(); const obj2 = parser.getObj(); const obj3 = parser.getObj(); if (obj1 !== num || obj2 !== gen || !(obj3 instanceof Cmd)) { throw new XRefEntryException(`Bad (uncompressed) XRef entry: ${ref}`); } if (obj3.cmd !== "obj") { if (obj3.cmd.startsWith("obj")) { num = parseInt(obj3.cmd.substring(3), 10); if (!Number.isNaN(num)) { return num; } } throw new XRefEntryException(`Bad (uncompressed) XRef entry: ${ref}`); } xrefEntry = this.encrypt && !suppressEncryption ? parser.getObj(this.encrypt.createCipherTransform(num, gen)) : parser.getObj(); if (!(xrefEntry instanceof BaseStream)) { this._cacheMap.set(num, xrefEntry); } return xrefEntry; } fetchCompressed(ref, xrefEntry, suppressEncryption = false) { const tableOffset = xrefEntry.offset; const stream = this.fetch(Ref.get(tableOffset, 0)); if (!(stream instanceof BaseStream)) { throw new FormatError("bad ObjStm stream"); } const first = stream.dict.get("First"); const n = stream.dict.get("N"); if (!Number.isInteger(first) || !Number.isInteger(n)) { throw new FormatError("invalid first and n parameters for ObjStm stream"); } let parser = new Parser({ lexer: new Lexer(stream), xref: this, allowStreams: true }); const nums = new Array(n); const offsets = new Array(n); for (let i = 0; i < n; ++i) { const num = parser.getObj(); if (!Number.isInteger(num)) { throw new FormatError(`invalid object number in the ObjStm stream: ${num}`); } const offset = parser.getObj(); if (!Number.isInteger(offset)) { throw new FormatError(`invalid object offset in the ObjStm stream: ${offset}`); } nums[i] = num; offsets[i] = offset; } const start = (stream.start || 0) + first; const entries = new Array(n); for (let i = 0; i < n; ++i) { const length = i < n - 1 ? offsets[i + 1] - offsets[i] : undefined; if (length < 0) { throw new FormatError("Invalid offset in the ObjStm stream."); } parser = new Parser({ lexer: new Lexer(stream.makeSubStream(start + offsets[i], length, stream.dict)), xref: this, allowStreams: true }); const obj = parser.getObj(); entries[i] = obj; if (obj instanceof BaseStream) { continue; } const num = nums[i], entry = this.entries[num]; if (entry && entry.offset === tableOffset && entry.gen === i) { this._cacheMap.set(num, obj); } } xrefEntry = entries[xrefEntry.gen]; if (xrefEntry === undefined) { throw new XRefEntryException(`Bad (compressed) XRef entry: ${ref}`); } return xrefEntry; } async fetchIfRefAsync(obj, suppressEncryption) { if (obj instanceof Ref) { return this.fetchAsync(obj, suppressEncryption); } return obj; } async fetchAsync(ref, suppressEncryption) { try { return this.fetch(ref, suppressEncryption); } catch (ex) { if (!(ex instanceof MissingDataException)) { throw ex; } await this.pdfManager.requestRange(ex.begin, ex.end); return this.fetchAsync(ref, suppressEncryption); } } getCatalogObj() { return this.root; } } ;// CONCATENATED MODULE: ./src/core/document.js const DEFAULT_USER_UNIT = 1.0; const LETTER_SIZE_MEDIABOX = [0, 0, 612, 792]; class Page { constructor({ pdfManager, xref, pageIndex, pageDict, ref, globalIdFactory, fontCache, builtInCMapCache, standardFontDataCache, globalImageCache, systemFontCache, nonBlendModesSet, xfaFactory }) { this.pdfManager = pdfManager; this.pageIndex = pageIndex; this.pageDict = pageDict; this.xref = xref; this.ref = ref; this.fontCache = fontCache; this.builtInCMapCache = builtInCMapCache; this.standardFontDataCache = standardFontDataCache; this.globalImageCache = globalImageCache; this.systemFontCache = systemFontCache; this.nonBlendModesSet = nonBlendModesSet; this.evaluatorOptions = pdfManager.evaluatorOptions; this.resourcesPromise = null; this.xfaFactory = xfaFactory; const idCounters = { obj: 0 }; this._localIdFactory = class extends globalIdFactory { static createObjId() { return `p${pageIndex}_${++idCounters.obj}`; } static getPageObjId() { return `p${ref.toString()}`; } }; } _getInheritableProperty(key, getArray = false) { const value = getInheritableProperty({ dict: this.pageDict, key, getArray, stopWhenFound: false }); if (!Array.isArray(value)) { return value; } if (value.length === 1 || !(value[0] instanceof Dict)) { return value[0]; } return Dict.merge({ xref: this.xref, dictArray: value }); } get content() { return this.pageDict.getArray("Contents"); } get resources() { const resources = this._getInheritableProperty("Resources"); return shadow(this, "resources", resources instanceof Dict ? resources : Dict.empty); } _getBoundingBox(name) { if (this.xfaData) { return this.xfaData.bbox; } const box = lookupNormalRect(this._getInheritableProperty(name, true), null); if (box) { if (box[2] - box[0] > 0 && box[3] - box[1] > 0) { return box; } warn(`Empty, or invalid, /${name} entry.`); } return null; } get mediaBox() { return shadow(this, "mediaBox", this._getBoundingBox("MediaBox") || LETTER_SIZE_MEDIABOX); } get cropBox() { return shadow(this, "cropBox", this._getBoundingBox("CropBox") || this.mediaBox); } get userUnit() { let obj = this.pageDict.get("UserUnit"); if (typeof obj !== "number" || obj <= 0) { obj = DEFAULT_USER_UNIT; } return shadow(this, "userUnit", obj); } get view() { const { cropBox, mediaBox } = this; if (cropBox !== mediaBox && !isArrayEqual(cropBox, mediaBox)) { const box = Util.intersect(cropBox, mediaBox); if (box && box[2] - box[0] > 0 && box[3] - box[1] > 0) { return shadow(this, "view", box); } warn("Empty /CropBox and /MediaBox intersection."); } return shadow(this, "view", mediaBox); } get rotate() { let rotate = this._getInheritableProperty("Rotate") || 0; if (rotate % 90 !== 0) { rotate = 0; } else if (rotate >= 360) { rotate %= 360; } else if (rotate < 0) { rotate = (rotate % 360 + 360) % 360; } return shadow(this, "rotate", rotate); } _onSubStreamError(reason, objId) { if (this.evaluatorOptions.ignoreErrors) { warn(`getContentStream - ignoring sub-stream (${objId}): "${reason}".`); return; } throw reason; } getContentStream() { return this.pdfManager.ensure(this, "content").then(content => { if (content instanceof BaseStream) { return content; } if (Array.isArray(content)) { return new StreamsSequenceStream(content, this._onSubStreamError.bind(this)); } return new NullStream(); }); } get xfaData() { return shadow(this, "xfaData", this.xfaFactory ? { bbox: this.xfaFactory.getBoundingBox(this.pageIndex) } : null); } #replaceIdByRef(annotations, deletedAnnotations, existingAnnotations) { for (const annotation of annotations) { if (annotation.id) { const ref = Ref.fromString(annotation.id); if (!ref) { warn(`A non-linked annotation cannot be modified: ${annotation.id}`); continue; } if (annotation.deleted) { deletedAnnotations.put(ref, ref); continue; } existingAnnotations?.put(ref); annotation.ref = ref; delete annotation.id; } } } async saveNewAnnotations(handler, task, annotations, imagePromises) { if (this.xfaFactory) { throw new Error("XFA: Cannot save new annotations."); } const partialEvaluator = new PartialEvaluator({ xref: this.xref, handler, pageIndex: this.pageIndex, idFactory: this._localIdFactory, fontCache: this.fontCache, builtInCMapCache: this.builtInCMapCache, standardFontDataCache: this.standardFontDataCache, globalImageCache: this.globalImageCache, systemFontCache: this.systemFontCache, options: this.evaluatorOptions }); const deletedAnnotations = new RefSetCache(); const existingAnnotations = new RefSet(); this.#replaceIdByRef(annotations, deletedAnnotations, existingAnnotations); const pageDict = this.pageDict; const annotationsArray = this.annotations.filter(a => !(a instanceof Ref && deletedAnnotations.has(a))); const newData = await AnnotationFactory.saveNewAnnotations(partialEvaluator, task, annotations, imagePromises); for (const { ref } of newData.annotations) { if (ref instanceof Ref && !existingAnnotations.has(ref)) { annotationsArray.push(ref); } } const savedDict = pageDict.get("Annots"); pageDict.set("Annots", annotationsArray); const buffer = []; await writeObject(this.ref, pageDict, buffer, this.xref); if (savedDict) { pageDict.set("Annots", savedDict); } const objects = newData.dependencies; objects.push({ ref: this.ref, data: buffer.join("") }, ...newData.annotations); for (const deletedRef of deletedAnnotations) { objects.push({ ref: deletedRef, data: null }); } return objects; } save(handler, task, annotationStorage) { const partialEvaluator = new PartialEvaluator({ xref: this.xref, handler, pageIndex: this.pageIndex, idFactory: this._localIdFactory, fontCache: this.fontCache, builtInCMapCache: this.builtInCMapCache, standardFontDataCache: this.standardFontDataCache, globalImageCache: this.globalImageCache, systemFontCache: this.systemFontCache, options: this.evaluatorOptions }); return this._parsedAnnotations.then(function (annotations) { const newRefsPromises = []; for (const annotation of annotations) { if (!annotation.mustBePrinted(annotationStorage)) { continue; } newRefsPromises.push(annotation.save(partialEvaluator, task, annotationStorage).catch(function (reason) { warn("save - ignoring annotation data during " + `"${task.name}" task: "${reason}".`); return null; })); } return Promise.all(newRefsPromises).then(function (newRefs) { return newRefs.filter(newRef => !!newRef); }); }); } loadResources(keys) { this.resourcesPromise ||= this.pdfManager.ensure(this, "resources"); return this.resourcesPromise.then(() => { const objectLoader = new ObjectLoader(this.resources, keys, this.xref); return objectLoader.load(); }); } getOperatorList({ handler, sink, task, intent, cacheKey, annotationStorage = null }) { const contentStreamPromise = this.getContentStream(); const resourcesPromise = this.loadResources(["ColorSpace", "ExtGState", "Font", "Pattern", "Properties", "Shading", "XObject"]); const partialEvaluator = new PartialEvaluator({ xref: this.xref, handler, pageIndex: this.pageIndex, idFactory: this._localIdFactory, fontCache: this.fontCache, builtInCMapCache: this.builtInCMapCache, standardFontDataCache: this.standardFontDataCache, globalImageCache: this.globalImageCache, systemFontCache: this.systemFontCache, options: this.evaluatorOptions }); const newAnnotsByPage = !this.xfaFactory ? getNewAnnotationsMap(annotationStorage) : null; const newAnnots = newAnnotsByPage?.get(this.pageIndex); let newAnnotationsPromise = Promise.resolve(null); let deletedAnnotations = null; if (newAnnots) { const annotationGlobalsPromise = this.pdfManager.ensureDoc("annotationGlobals"); let imagePromises; const missingBitmaps = new Set(); for (const { bitmapId, bitmap } of newAnnots) { if (bitmapId && !bitmap && !missingBitmaps.has(bitmapId)) { missingBitmaps.add(bitmapId); } } const { isOffscreenCanvasSupported } = this.evaluatorOptions; if (missingBitmaps.size > 0) { const annotationWithBitmaps = newAnnots.slice(); for (const [key, annotation] of annotationStorage) { if (!key.startsWith(AnnotationEditorPrefix)) { continue; } if (annotation.bitmap && missingBitmaps.has(annotation.bitmapId)) { annotationWithBitmaps.push(annotation); } } imagePromises = AnnotationFactory.generateImages(annotationWithBitmaps, this.xref, isOffscreenCanvasSupported); } else { imagePromises = AnnotationFactory.generateImages(newAnnots, this.xref, isOffscreenCanvasSupported); } deletedAnnotations = new RefSet(); this.#replaceIdByRef(newAnnots, deletedAnnotations, null); newAnnotationsPromise = annotationGlobalsPromise.then(annotationGlobals => { if (!annotationGlobals) { return null; } return AnnotationFactory.printNewAnnotations(annotationGlobals, partialEvaluator, task, newAnnots, imagePromises); }); } const pageListPromise = Promise.all([contentStreamPromise, resourcesPromise]).then(([contentStream]) => { const opList = new OperatorList(intent, sink); handler.send("StartRenderPage", { transparency: partialEvaluator.hasBlendModes(this.resources, this.nonBlendModesSet), pageIndex: this.pageIndex, cacheKey }); return partialEvaluator.getOperatorList({ stream: contentStream, task, resources: this.resources, operatorList: opList }).then(function () { return opList; }); }); return Promise.all([pageListPromise, this._parsedAnnotations, newAnnotationsPromise]).then(function ([pageOpList, annotations, newAnnotations]) { if (newAnnotations) { annotations = annotations.filter(a => !(a.ref && deletedAnnotations.has(a.ref))); for (let i = 0, ii = newAnnotations.length; i < ii; i++) { const newAnnotation = newAnnotations[i]; if (newAnnotation.refToReplace) { const j = annotations.findIndex(a => a.ref && isRefsEqual(a.ref, newAnnotation.refToReplace)); if (j >= 0) { annotations.splice(j, 1, newAnnotation); newAnnotations.splice(i--, 1); ii--; } } } annotations = annotations.concat(newAnnotations); } if (annotations.length === 0 || intent & RenderingIntentFlag.ANNOTATIONS_DISABLE) { pageOpList.flush(true); return { length: pageOpList.totalLength }; } const renderForms = !!(intent & RenderingIntentFlag.ANNOTATIONS_FORMS), intentAny = !!(intent & RenderingIntentFlag.ANY), intentDisplay = !!(intent & RenderingIntentFlag.DISPLAY), intentPrint = !!(intent & RenderingIntentFlag.PRINT); const opListPromises = []; for (const annotation of annotations) { if (intentAny || intentDisplay && annotation.mustBeViewed(annotationStorage, renderForms) || intentPrint && annotation.mustBePrinted(annotationStorage)) { opListPromises.push(annotation.getOperatorList(partialEvaluator, task, intent, renderForms, annotationStorage).catch(function (reason) { warn("getOperatorList - ignoring annotation data during " + `"${task.name}" task: "${reason}".`); return { opList: null, separateForm: false, separateCanvas: false }; })); } } return Promise.all(opListPromises).then(function (opLists) { let form = false, canvas = false; for (const { opList, separateForm, separateCanvas } of opLists) { pageOpList.addOpList(opList); form ||= separateForm; canvas ||= separateCanvas; } pageOpList.flush(true, { form, canvas }); return { length: pageOpList.totalLength }; }); }); } async extractTextContent({ handler, task, includeMarkedContent, disableNormalization, sink }) { const contentStreamPromise = this.getContentStream(); const resourcesPromise = this.loadResources(["ExtGState", "Font", "Properties", "XObject"]); const langPromise = this.pdfManager.ensureCatalog("lang"); const [contentStream,, lang] = await Promise.all([contentStreamPromise, resourcesPromise, langPromise]); const partialEvaluator = new PartialEvaluator({ xref: this.xref, handler, pageIndex: this.pageIndex, idFactory: this._localIdFactory, fontCache: this.fontCache, builtInCMapCache: this.builtInCMapCache, standardFontDataCache: this.standardFontDataCache, globalImageCache: this.globalImageCache, systemFontCache: this.systemFontCache, options: this.evaluatorOptions }); return partialEvaluator.getTextContent({ stream: contentStream, task, resources: this.resources, includeMarkedContent, disableNormalization, sink, viewBox: this.view, lang }); } async getStructTree() { const structTreeRoot = await this.pdfManager.ensureCatalog("structTreeRoot"); if (!structTreeRoot) { return null; } await this._parsedAnnotations; const structTree = await this.pdfManager.ensure(this, "_parseStructTree", [structTreeRoot]); return structTree.serializable; } _parseStructTree(structTreeRoot) { const tree = new StructTreePage(structTreeRoot, this.pageDict); tree.parse(this.ref); return tree; } async getAnnotationsData(handler, task, intent) { const annotations = await this._parsedAnnotations; if (annotations.length === 0) { return annotations; } const annotationsData = [], textContentPromises = []; let partialEvaluator; const intentAny = !!(intent & RenderingIntentFlag.ANY), intentDisplay = !!(intent & RenderingIntentFlag.DISPLAY), intentPrint = !!(intent & RenderingIntentFlag.PRINT); for (const annotation of annotations) { const isVisible = intentAny || intentDisplay && annotation.viewable; if (isVisible || intentPrint && annotation.printable) { annotationsData.push(annotation.data); } if (annotation.hasTextContent && isVisible) { partialEvaluator ||= new PartialEvaluator({ xref: this.xref, handler, pageIndex: this.pageIndex, idFactory: this._localIdFactory, fontCache: this.fontCache, builtInCMapCache: this.builtInCMapCache, standardFontDataCache: this.standardFontDataCache, globalImageCache: this.globalImageCache, systemFontCache: this.systemFontCache, options: this.evaluatorOptions }); textContentPromises.push(annotation.extractTextContent(partialEvaluator, task, [-Infinity, -Infinity, Infinity, Infinity]).catch(function (reason) { warn(`getAnnotationsData - ignoring textContent during "${task.name}" task: "${reason}".`); })); } } await Promise.all(textContentPromises); return annotationsData; } get annotations() { const annots = this._getInheritableProperty("Annots"); return shadow(this, "annotations", Array.isArray(annots) ? annots : []); } get _parsedAnnotations() { const promise = this.pdfManager.ensure(this, "annotations").then(async annots => { if (annots.length === 0) { return annots; } const annotationGlobals = await this.pdfManager.ensureDoc("annotationGlobals"); if (!annotationGlobals) { return []; } const annotationPromises = []; for (const annotationRef of annots) { annotationPromises.push(AnnotationFactory.create(this.xref, annotationRef, annotationGlobals, this._localIdFactory, false, this.ref).catch(function (reason) { warn(`_parsedAnnotations: "${reason}".`); return null; })); } const sortedAnnotations = []; let popupAnnotations, widgetAnnotations; for (const annotation of await Promise.all(annotationPromises)) { if (!annotation) { continue; } if (annotation instanceof WidgetAnnotation) { (widgetAnnotations ||= []).push(annotation); continue; } if (annotation instanceof PopupAnnotation) { (popupAnnotations ||= []).push(annotation); continue; } sortedAnnotations.push(annotation); } if (widgetAnnotations) { sortedAnnotations.push(...widgetAnnotations); } if (popupAnnotations) { sortedAnnotations.push(...popupAnnotations); } return sortedAnnotations; }); return shadow(this, "_parsedAnnotations", promise); } get jsActions() { const actions = collectActions(this.xref, this.pageDict, PageActionEventType); return shadow(this, "jsActions", actions); } } const PDF_HEADER_SIGNATURE = new Uint8Array([0x25, 0x50, 0x44, 0x46, 0x2d]); const STARTXREF_SIGNATURE = new Uint8Array([0x73, 0x74, 0x61, 0x72, 0x74, 0x78, 0x72, 0x65, 0x66]); const ENDOBJ_SIGNATURE = new Uint8Array([0x65, 0x6e, 0x64, 0x6f, 0x62, 0x6a]); const FINGERPRINT_FIRST_BYTES = 1024; const EMPTY_FINGERPRINT = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; function find(stream, signature, limit = 1024, backwards = false) { const signatureLength = signature.length; const scanBytes = stream.peekBytes(limit); const scanLength = scanBytes.length - signatureLength; if (scanLength <= 0) { return false; } if (backwards) { const signatureEnd = signatureLength - 1; let pos = scanBytes.length - 1; while (pos >= signatureEnd) { let j = 0; while (j < signatureLength && scanBytes[pos - j] === signature[signatureEnd - j]) { j++; } if (j >= signatureLength) { stream.pos += pos - signatureEnd; return true; } pos--; } } else { let pos = 0; while (pos <= scanLength) { let j = 0; while (j < signatureLength && scanBytes[pos + j] === signature[j]) { j++; } if (j >= signatureLength) { stream.pos += pos; return true; } pos++; } } return false; } class PDFDocument { constructor(pdfManager, stream) { if (stream.length <= 0) { throw new InvalidPDFException("The PDF file is empty, i.e. its size is zero bytes."); } this.pdfManager = pdfManager; this.stream = stream; this.xref = new XRef(stream, pdfManager); this._pagePromises = new Map(); this._version = null; const idCounters = { font: 0 }; this._globalIdFactory = class { static getDocId() { return `g_${pdfManager.docId}`; } static createFontId() { return `f${++idCounters.font}`; } static createObjId() { unreachable("Abstract method `createObjId` called."); } static getPageObjId() { unreachable("Abstract method `getPageObjId` called."); } }; } parse(recoveryMode) { this.xref.parse(recoveryMode); this.catalog = new Catalog(this.pdfManager, this.xref); } get linearization() { let linearization = null; try { linearization = Linearization.create(this.stream); } catch (err) { if (err instanceof MissingDataException) { throw err; } info(err); } return shadow(this, "linearization", linearization); } get startXRef() { const stream = this.stream; let startXRef = 0; if (this.linearization) { stream.reset(); if (find(stream, ENDOBJ_SIGNATURE)) { stream.skip(6); let ch = stream.peekByte(); while (isWhiteSpace(ch)) { stream.pos++; ch = stream.peekByte(); } startXRef = stream.pos - stream.start; } } else { const step = 1024; const startXRefLength = STARTXREF_SIGNATURE.length; let found = false, pos = stream.end; while (!found && pos > 0) { pos -= step - startXRefLength; if (pos < 0) { pos = 0; } stream.pos = pos; found = find(stream, STARTXREF_SIGNATURE, step, true); } if (found) { stream.skip(9); let ch; do { ch = stream.getByte(); } while (isWhiteSpace(ch)); let str = ""; while (ch >= 0x20 && ch <= 0x39) { str += String.fromCharCode(ch); ch = stream.getByte(); } startXRef = parseInt(str, 10); if (isNaN(startXRef)) { startXRef = 0; } } } return shadow(this, "startXRef", startXRef); } checkHeader() { const stream = this.stream; stream.reset(); if (!find(stream, PDF_HEADER_SIGNATURE)) { return; } stream.moveStart(); stream.skip(PDF_HEADER_SIGNATURE.length); let version = "", ch; while ((ch = stream.getByte()) > 0x20 && version.length < 7) { version += String.fromCharCode(ch); } if (PDF_VERSION_REGEXP.test(version)) { this._version = version; } else { warn(`Invalid PDF header version: ${version}`); } } parseStartXRef() { this.xref.setStartXRef(this.startXRef); } get numPages() { let num = 0; if (this.catalog.hasActualNumPages) { num = this.catalog.numPages; } else if (this.xfaFactory) { num = this.xfaFactory.getNumPages(); } else if (this.linearization) { num = this.linearization.numPages; } else { num = this.catalog.numPages; } return shadow(this, "numPages", num); } _hasOnlyDocumentSignatures(fields, recursionDepth = 0) { const RECURSION_LIMIT = 10; if (!Array.isArray(fields)) { return false; } return fields.every(field => { field = this.xref.fetchIfRef(field); if (!(field instanceof Dict)) { return false; } if (field.has("Kids")) { if (++recursionDepth > RECURSION_LIMIT) { warn("_hasOnlyDocumentSignatures: maximum recursion depth reached"); return false; } return this._hasOnlyDocumentSignatures(field.get("Kids"), recursionDepth); } const isSignature = isName(field.get("FT"), "Sig"); const rectangle = field.get("Rect"); const isInvisible = Array.isArray(rectangle) && rectangle.every(value => value === 0); return isSignature && isInvisible; }); } get _xfaStreams() { const acroForm = this.catalog.acroForm; if (!acroForm) { return null; } const xfa = acroForm.get("XFA"); const entries = { "xdp:xdp": "", template: "", datasets: "", config: "", connectionSet: "", localeSet: "", stylesheet: "", "/xdp:xdp": "" }; if (xfa instanceof BaseStream && !xfa.isEmpty) { entries["xdp:xdp"] = xfa; return entries; } if (!Array.isArray(xfa) || xfa.length === 0) { return null; } for (let i = 0, ii = xfa.length; i < ii; i += 2) { let name; if (i === 0) { name = "xdp:xdp"; } else if (i === ii - 2) { name = "/xdp:xdp"; } else { name = xfa[i]; } if (!entries.hasOwnProperty(name)) { continue; } const data = this.xref.fetchIfRef(xfa[i + 1]); if (!(data instanceof BaseStream) || data.isEmpty) { continue; } entries[name] = data; } return entries; } get xfaDatasets() { const streams = this._xfaStreams; if (!streams) { return shadow(this, "xfaDatasets", null); } for (const key of ["datasets", "xdp:xdp"]) { const stream = streams[key]; if (!stream) { continue; } try { const str = stringToUTF8String(stream.getString()); const data = { [key]: str }; return shadow(this, "xfaDatasets", new DatasetReader(data)); } catch { warn("XFA - Invalid utf-8 string."); break; } } return shadow(this, "xfaDatasets", null); } get xfaData() { const streams = this._xfaStreams; if (!streams) { return null; } const data = Object.create(null); for (const [key, stream] of Object.entries(streams)) { if (!stream) { continue; } try { data[key] = stringToUTF8String(stream.getString()); } catch { warn("XFA - Invalid utf-8 string."); return null; } } return data; } get xfaFactory() { let data; if (this.pdfManager.enableXfa && this.catalog.needsRendering && this.formInfo.hasXfa && !this.formInfo.hasAcroForm) { data = this.xfaData; } return shadow(this, "xfaFactory", data ? new XFAFactory(data) : null); } get isPureXfa() { return this.xfaFactory ? this.xfaFactory.isValid() : false; } get htmlForXfa() { return this.xfaFactory ? this.xfaFactory.getPages() : null; } async loadXfaImages() { const xfaImagesDict = await this.pdfManager.ensureCatalog("xfaImages"); if (!xfaImagesDict) { return; } const keys = xfaImagesDict.getKeys(); const objectLoader = new ObjectLoader(xfaImagesDict, keys, this.xref); await objectLoader.load(); const xfaImages = new Map(); for (const key of keys) { const stream = xfaImagesDict.get(key); if (stream instanceof BaseStream) { xfaImages.set(key, stream.getBytes()); } } this.xfaFactory.setImages(xfaImages); } async loadXfaFonts(handler, task) { const acroForm = await this.pdfManager.ensureCatalog("acroForm"); if (!acroForm) { return; } const resources = await acroForm.getAsync("DR"); if (!(resources instanceof Dict)) { return; } const objectLoader = new ObjectLoader(resources, ["Font"], this.xref); await objectLoader.load(); const fontRes = resources.get("Font"); if (!(fontRes instanceof Dict)) { return; } const options = Object.assign(Object.create(null), this.pdfManager.evaluatorOptions); options.useSystemFonts = false; const partialEvaluator = new PartialEvaluator({ xref: this.xref, handler, pageIndex: -1, idFactory: this._globalIdFactory, fontCache: this.catalog.fontCache, builtInCMapCache: this.catalog.builtInCMapCache, standardFontDataCache: this.catalog.standardFontDataCache, options }); const operatorList = new OperatorList(); const pdfFonts = []; const initialState = { get font() { return pdfFonts.at(-1); }, set font(font) { pdfFonts.push(font); }, clone() { return this; } }; const fonts = new Map(); fontRes.forEach((fontName, font) => { fonts.set(fontName, font); }); const promises = []; for (const [fontName, font] of fonts) { const descriptor = font.get("FontDescriptor"); if (!(descriptor instanceof Dict)) { continue; } let fontFamily = descriptor.get("FontFamily"); fontFamily = fontFamily.replaceAll(/[ ]+(\d)/g, "$1"); const fontWeight = descriptor.get("FontWeight"); const italicAngle = -descriptor.get("ItalicAngle"); const cssFontInfo = { fontFamily, fontWeight, italicAngle }; if (!validateCSSFont(cssFontInfo)) { continue; } promises.push(partialEvaluator.handleSetFont(resources, [Name.get(fontName), 1], null, operatorList, task, initialState, null, cssFontInfo).catch(function (reason) { warn(`loadXfaFonts: "${reason}".`); return null; })); } await Promise.all(promises); const missingFonts = this.xfaFactory.setFonts(pdfFonts); if (!missingFonts) { return; } options.ignoreErrors = true; promises.length = 0; pdfFonts.length = 0; const reallyMissingFonts = new Set(); for (const missing of missingFonts) { if (!getXfaFontName(`${missing}-Regular`)) { reallyMissingFonts.add(missing); } } if (reallyMissingFonts.size) { missingFonts.push("PdfJS-Fallback"); } for (const missing of missingFonts) { if (reallyMissingFonts.has(missing)) { continue; } for (const fontInfo of [{ name: "Regular", fontWeight: 400, italicAngle: 0 }, { name: "Bold", fontWeight: 700, italicAngle: 0 }, { name: "Italic", fontWeight: 400, italicAngle: 12 }, { name: "BoldItalic", fontWeight: 700, italicAngle: 12 }]) { const name = `${missing}-${fontInfo.name}`; const dict = getXfaFontDict(name); promises.push(partialEvaluator.handleSetFont(resources, [Name.get(name), 1], null, operatorList, task, initialState, dict, { fontFamily: missing, fontWeight: fontInfo.fontWeight, italicAngle: fontInfo.italicAngle }).catch(function (reason) { warn(`loadXfaFonts: "${reason}".`); return null; })); } } await Promise.all(promises); this.xfaFactory.appendFonts(pdfFonts, reallyMissingFonts); } async serializeXfaData(annotationStorage) { return this.xfaFactory ? this.xfaFactory.serializeData(annotationStorage) : null; } get version() { return this.catalog.version || this._version; } get formInfo() { const formInfo = { hasFields: false, hasAcroForm: false, hasXfa: false, hasSignatures: false }; const acroForm = this.catalog.acroForm; if (!acroForm) { return shadow(this, "formInfo", formInfo); } try { const fields = acroForm.get("Fields"); const hasFields = Array.isArray(fields) && fields.length > 0; formInfo.hasFields = hasFields; const xfa = acroForm.get("XFA"); formInfo.hasXfa = Array.isArray(xfa) && xfa.length > 0 || xfa instanceof BaseStream && !xfa.isEmpty; const sigFlags = acroForm.get("SigFlags"); const hasSignatures = !!(sigFlags & 0x1); const hasOnlyDocumentSignatures = hasSignatures && this._hasOnlyDocumentSignatures(fields); formInfo.hasAcroForm = hasFields && !hasOnlyDocumentSignatures; formInfo.hasSignatures = hasSignatures; } catch (ex) { if (ex instanceof MissingDataException) { throw ex; } warn(`Cannot fetch form information: "${ex}".`); } return shadow(this, "formInfo", formInfo); } get documentInfo() { const docInfo = { PDFFormatVersion: this.version, Language: this.catalog.lang, EncryptFilterName: this.xref.encrypt ? this.xref.encrypt.filterName : null, IsLinearized: !!this.linearization, IsAcroFormPresent: this.formInfo.hasAcroForm, IsXFAPresent: this.formInfo.hasXfa, IsCollectionPresent: !!this.catalog.collection, IsSignaturesPresent: this.formInfo.hasSignatures }; let infoDict; try { infoDict = this.xref.trailer.get("Info"); } catch (err) { if (err instanceof MissingDataException) { throw err; } info("The document information dictionary is invalid."); } if (!(infoDict instanceof Dict)) { return shadow(this, "documentInfo", docInfo); } for (const key of infoDict.getKeys()) { const value = infoDict.get(key); switch (key) { case "Title": case "Author": case "Subject": case "Keywords": case "Creator": case "Producer": case "CreationDate": case "ModDate": if (typeof value === "string") { docInfo[key] = stringToPDFString(value); continue; } break; case "Trapped": if (value instanceof Name) { docInfo[key] = value; continue; } break; default: let customValue; switch (typeof value) { case "string": customValue = stringToPDFString(value); break; case "number": case "boolean": customValue = value; break; default: if (value instanceof Name) { customValue = value; } break; } if (customValue === undefined) { warn(`Bad value, for custom key "${key}", in Info: ${value}.`); continue; } if (!docInfo.Custom) { docInfo.Custom = Object.create(null); } docInfo.Custom[key] = customValue; continue; } warn(`Bad value, for key "${key}", in Info: ${value}.`); } return shadow(this, "documentInfo", docInfo); } get fingerprints() { function validate(data) { return typeof data === "string" && data.length > 0 && data !== EMPTY_FINGERPRINT; } function hexString(hash) { const buf = []; for (const num of hash) { const hex = num.toString(16); buf.push(hex.padStart(2, "0")); } return buf.join(""); } const idArray = this.xref.trailer.get("ID"); let hashOriginal, hashModified; if (Array.isArray(idArray) && validate(idArray[0])) { hashOriginal = stringToBytes(idArray[0]); if (idArray[1] !== idArray[0] && validate(idArray[1])) { hashModified = stringToBytes(idArray[1]); } } else { hashOriginal = calculateMD5(this.stream.getByteRange(0, FINGERPRINT_FIRST_BYTES), 0, FINGERPRINT_FIRST_BYTES); } return shadow(this, "fingerprints", [hexString(hashOriginal), hashModified ? hexString(hashModified) : null]); } async _getLinearizationPage(pageIndex) { const { catalog, linearization, xref } = this; const ref = Ref.get(linearization.objectNumberFirst, 0); try { const obj = await xref.fetchAsync(ref); if (obj instanceof Dict) { let type = obj.getRaw("Type"); if (type instanceof Ref) { type = await xref.fetchAsync(type); } if (isName(type, "Page") || !obj.has("Type") && !obj.has("Kids") && obj.has("Contents")) { if (!catalog.pageKidsCountCache.has(ref)) { catalog.pageKidsCountCache.put(ref, 1); } if (!catalog.pageIndexCache.has(ref)) { catalog.pageIndexCache.put(ref, 0); } return [obj, ref]; } } throw new FormatError("The Linearization dictionary doesn't point to a valid Page dictionary."); } catch (reason) { warn(`_getLinearizationPage: "${reason.message}".`); return catalog.getPageDict(pageIndex); } } getPage(pageIndex) { const cachedPromise = this._pagePromises.get(pageIndex); if (cachedPromise) { return cachedPromise; } const { catalog, linearization, xfaFactory } = this; let promise; if (xfaFactory) { promise = Promise.resolve([Dict.empty, null]); } else if (linearization?.pageFirst === pageIndex) { promise = this._getLinearizationPage(pageIndex); } else { promise = catalog.getPageDict(pageIndex); } promise = promise.then(([pageDict, ref]) => { return new Page({ pdfManager: this.pdfManager, xref: this.xref, pageIndex, pageDict, ref, globalIdFactory: this._globalIdFactory, fontCache: catalog.fontCache, builtInCMapCache: catalog.builtInCMapCache, standardFontDataCache: catalog.standardFontDataCache, globalImageCache: catalog.globalImageCache, systemFontCache: catalog.systemFontCache, nonBlendModesSet: catalog.nonBlendModesSet, xfaFactory }); }); this._pagePromises.set(pageIndex, promise); return promise; } async checkFirstPage(recoveryMode = false) { if (recoveryMode) { return; } try { await this.getPage(0); } catch (reason) { if (reason instanceof XRefEntryException) { this._pagePromises.delete(0); await this.cleanup(); throw new XRefParseException(); } } } async checkLastPage(recoveryMode = false) { const { catalog, pdfManager } = this; catalog.setActualNumPages(); let numPages; try { await Promise.all([pdfManager.ensureDoc("xfaFactory"), pdfManager.ensureDoc("linearization"), pdfManager.ensureCatalog("numPages")]); if (this.xfaFactory) { return; } else if (this.linearization) { numPages = this.linearization.numPages; } else { numPages = catalog.numPages; } if (!Number.isInteger(numPages)) { throw new FormatError("Page count is not an integer."); } else if (numPages <= 1) { return; } await this.getPage(numPages - 1); } catch (reason) { this._pagePromises.delete(numPages - 1); await this.cleanup(); if (reason instanceof XRefEntryException && !recoveryMode) { throw new XRefParseException(); } warn(`checkLastPage - invalid /Pages tree /Count: ${numPages}.`); let pagesTree; try { pagesTree = await catalog.getAllPageDicts(recoveryMode); } catch (reasonAll) { if (reasonAll instanceof XRefEntryException && !recoveryMode) { throw new XRefParseException(); } catalog.setActualNumPages(1); return; } for (const [pageIndex, [pageDict, ref]] of pagesTree) { let promise; if (pageDict instanceof Error) { promise = Promise.reject(pageDict); promise.catch(() => {}); } else { promise = Promise.resolve(new Page({ pdfManager, xref: this.xref, pageIndex, pageDict, ref, globalIdFactory: this._globalIdFactory, fontCache: catalog.fontCache, builtInCMapCache: catalog.builtInCMapCache, standardFontDataCache: catalog.standardFontDataCache, globalImageCache: catalog.globalImageCache, systemFontCache: catalog.systemFontCache, nonBlendModesSet: catalog.nonBlendModesSet, xfaFactory: null })); } this._pagePromises.set(pageIndex, promise); } catalog.setActualNumPages(pagesTree.size); } } fontFallback(id, handler) { return this.catalog.fontFallback(id, handler); } async cleanup(manuallyTriggered = false) { return this.catalog ? this.catalog.cleanup(manuallyTriggered) : clearGlobalCaches(); } async #collectFieldObjects(name, fieldRef, promises, annotationGlobals, visitedRefs) { const { xref } = this; if (!(fieldRef instanceof Ref) || visitedRefs.has(fieldRef)) { return; } visitedRefs.put(fieldRef); const field = await xref.fetchAsync(fieldRef); if (!(field instanceof Dict)) { return; } if (field.has("T")) { const partName = stringToPDFString(await field.getAsync("T")); name = name === "" ? partName : `${name}.${partName}`; } else { let obj = field; while (true) { obj = obj.getRaw("Parent"); if (obj instanceof Ref) { if (visitedRefs.has(obj)) { break; } obj = await xref.fetchAsync(obj); } if (!(obj instanceof Dict)) { break; } if (obj.has("T")) { const partName = stringToPDFString(await obj.getAsync("T")); name = name === "" ? partName : `${name}.${partName}`; break; } } } if (!promises.has(name)) { promises.set(name, []); } promises.get(name).push(AnnotationFactory.create(xref, fieldRef, annotationGlobals, null, true, null).then(annotation => annotation?.getFieldObject()).catch(function (reason) { warn(`#collectFieldObjects: "${reason}".`); return null; })); if (!field.has("Kids")) { return; } const kids = await field.getAsync("Kids"); if (Array.isArray(kids)) { for (const kid of kids) { await this.#collectFieldObjects(name, kid, promises, annotationGlobals, visitedRefs); } } } get fieldObjects() { if (!this.formInfo.hasFields) { return shadow(this, "fieldObjects", Promise.resolve(null)); } const promise = Promise.all([this.pdfManager.ensureDoc("annotationGlobals"), this.pdfManager.ensureCatalog("acroForm")]).then(async ([annotationGlobals, acroForm]) => { if (!annotationGlobals) { return null; } const visitedRefs = new RefSet(); const allFields = Object.create(null); const fieldPromises = new Map(); for (const fieldRef of await acroForm.getAsync("Fields")) { await this.#collectFieldObjects("", fieldRef, fieldPromises, annotationGlobals, visitedRefs); } const allPromises = []; for (const [name, promises] of fieldPromises) { allPromises.push(Promise.all(promises).then(fields => { fields = fields.filter(field => !!field); if (fields.length > 0) { allFields[name] = fields; } })); } await Promise.all(allPromises); return allFields; }); return shadow(this, "fieldObjects", promise); } get hasJSActions() { const promise = this.pdfManager.ensureDoc("_parseHasJSActions"); return shadow(this, "hasJSActions", promise); } async _parseHasJSActions() { const [catalogJsActions, fieldObjects] = await Promise.all([this.pdfManager.ensureCatalog("jsActions"), this.pdfManager.ensureDoc("fieldObjects")]); if (catalogJsActions) { return true; } if (fieldObjects) { return Object.values(fieldObjects).some(fieldObject => fieldObject.some(object => object.actions !== null)); } return false; } get calculationOrderIds() { const acroForm = this.catalog.acroForm; if (!acroForm?.has("CO")) { return shadow(this, "calculationOrderIds", null); } const calculationOrder = acroForm.get("CO"); if (!Array.isArray(calculationOrder) || calculationOrder.length === 0) { return shadow(this, "calculationOrderIds", null); } const ids = []; for (const id of calculationOrder) { if (id instanceof Ref) { ids.push(id.toString()); } } if (ids.length === 0) { return shadow(this, "calculationOrderIds", null); } return shadow(this, "calculationOrderIds", ids); } get annotationGlobals() { return shadow(this, "annotationGlobals", AnnotationFactory.createGlobals(this.pdfManager)); } } ;// CONCATENATED MODULE: ./src/core/pdf_manager.js function parseDocBaseUrl(url) { if (url) { const absoluteUrl = createValidAbsoluteUrl(url); if (absoluteUrl) { return absoluteUrl.href; } warn(`Invalid absolute docBaseUrl: "${url}".`); } return null; } class BasePdfManager { constructor(args) { if (this.constructor === BasePdfManager) { unreachable("Cannot initialize BasePdfManager."); } this._docBaseUrl = parseDocBaseUrl(args.docBaseUrl); this._docId = args.docId; this._password = args.password; this.enableXfa = args.enableXfa; args.evaluatorOptions.isOffscreenCanvasSupported &&= FeatureTest.isOffscreenCanvasSupported; this.evaluatorOptions = Object.freeze(args.evaluatorOptions); } get docId() { return this._docId; } get password() { return this._password; } get docBaseUrl() { return this._docBaseUrl; } get catalog() { return this.pdfDocument.catalog; } ensureDoc(prop, args) { return this.ensure(this.pdfDocument, prop, args); } ensureXRef(prop, args) { return this.ensure(this.pdfDocument.xref, prop, args); } ensureCatalog(prop, args) { return this.ensure(this.pdfDocument.catalog, prop, args); } getPage(pageIndex) { return this.pdfDocument.getPage(pageIndex); } fontFallback(id, handler) { return this.pdfDocument.fontFallback(id, handler); } loadXfaFonts(handler, task) { return this.pdfDocument.loadXfaFonts(handler, task); } loadXfaImages() { return this.pdfDocument.loadXfaImages(); } serializeXfaData(annotationStorage) { return this.pdfDocument.serializeXfaData(annotationStorage); } cleanup(manuallyTriggered = false) { return this.pdfDocument.cleanup(manuallyTriggered); } async ensure(obj, prop, args) { unreachable("Abstract method `ensure` called"); } requestRange(begin, end) { unreachable("Abstract method `requestRange` called"); } requestLoadedStream(noFetch = false) { unreachable("Abstract method `requestLoadedStream` called"); } sendProgressiveData(chunk) { unreachable("Abstract method `sendProgressiveData` called"); } updatePassword(password) { this._password = password; } terminate(reason) { unreachable("Abstract method `terminate` called"); } } class LocalPdfManager extends BasePdfManager { constructor(args) { super(args); const stream = new Stream(args.source); this.pdfDocument = new PDFDocument(this, stream); this._loadedStreamPromise = Promise.resolve(stream); } async ensure(obj, prop, args) { const value = obj[prop]; if (typeof value === "function") { return value.apply(obj, args); } return value; } requestRange(begin, end) { return Promise.resolve(); } requestLoadedStream(noFetch = false) { return this._loadedStreamPromise; } terminate(reason) {} } class NetworkPdfManager extends BasePdfManager { constructor(args) { super(args); this.streamManager = new ChunkedStreamManager(args.source, { msgHandler: args.handler, length: args.length, disableAutoFetch: args.disableAutoFetch, rangeChunkSize: args.rangeChunkSize }); this.pdfDocument = new PDFDocument(this, this.streamManager.getStream()); } async ensure(obj, prop, args) { try { const value = obj[prop]; if (typeof value === "function") { return value.apply(obj, args); } return value; } catch (ex) { if (!(ex instanceof MissingDataException)) { throw ex; } await this.requestRange(ex.begin, ex.end); return this.ensure(obj, prop, args); } } requestRange(begin, end) { return this.streamManager.requestRange(begin, end);
•
Search:
•
Replace:
1
2
3
4
5
6
7
Function
Edit by line
Download
Information
Rename
Copy
Move
Delete
Chmod
List