From 10ca73335cade8e0a9f5bbe23cb24cd3fb5bbbff Mon Sep 17 00:00:00 2001 From: Calixte Date: Thu, 25 Jan 2024 15:35:38 +0000 Subject: [PATCH] Bug 1876508 - Update PDF.js to new version bf9236009521621891d73dd77acc68215cb2cadb r=pdfjs-reviewers,fluent-reviewers,marco,flod Differential Revision: https://phabricator.services.mozilla.com/D199621 --- .../content/PdfJsDefaultPreferences.sys.mjs | 56 +- .../components/pdfjs/content/build/pdf.mjs | 1411 ++++++++++++----- .../build/pdf.sandbox.external.sys.mjs | 228 ++- .../pdfjs/content/build/pdf.scripting.mjs | 99 +- .../pdfjs/content/build/pdf.worker.mjs | 510 +++--- .../pdfjs/content/web/viewer-geckoview.css | 31 +- .../pdfjs/content/web/viewer-geckoview.mjs | 99 +- .../components/pdfjs/content/web/viewer.css | 122 +- .../components/pdfjs/content/web/viewer.html | 6 + .../components/pdfjs/content/web/viewer.mjs | 111 +- toolkit/components/pdfjs/moz.yaml | 4 +- .../en-US/toolkit/pdfviewer/viewer.ftl | 2 + 12 files changed, 1667 insertions(+), 1012 deletions(-) diff --git a/toolkit/components/pdfjs/content/PdfJsDefaultPreferences.sys.mjs b/toolkit/components/pdfjs/content/PdfJsDefaultPreferences.sys.mjs index a8041003dbda..35059477b1a5 100644 --- a/toolkit/components/pdfjs/content/PdfJsDefaultPreferences.sys.mjs +++ b/toolkit/components/pdfjs/content/PdfJsDefaultPreferences.sys.mjs @@ -18,32 +18,32 @@ // export const PdfJsDefaultPreferences = Object.freeze({ - "annotationEditorMode": 0, - "annotationMode": 2, - "cursorToolOnLoad": 0, - "defaultZoomDelay": 400, - "defaultZoomValue": "", - "disablePageLabels": false, - "enableHighlightEditor": false, - "enablePermissions": false, - "enablePrintAutoRotate": true, - "enableScripting": true, - "externalLinkTarget": 0, - "highlightEditorColors": "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F", - "historyUpdateUrl": false, - "ignoreDestinationZoom": false, - "forcePageColors": false, - "pageColorsBackground": "Canvas", - "pageColorsForeground": "CanvasText", - "pdfBugEnabled": false, - "sidebarViewOnLoad": -1, - "scrollModeOnLoad": -1, - "spreadModeOnLoad": -1, - "textLayerMode": 1, - "viewOnLoad": 0, - "disableAutoFetch": false, - "disableFontFace": false, - "disableRange": false, - "disableStream": false, - "enableXfa": true + annotationEditorMode: 0, + annotationMode: 2, + cursorToolOnLoad: 0, + defaultZoomDelay: 400, + defaultZoomValue: "", + disablePageLabels: false, + enableHighlightEditor: false, + enablePermissions: false, + enablePrintAutoRotate: true, + enableScripting: true, + externalLinkTarget: 0, + highlightEditorColors: "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F", + historyUpdateUrl: false, + ignoreDestinationZoom: false, + forcePageColors: false, + pageColorsBackground: "Canvas", + pageColorsForeground: "CanvasText", + pdfBugEnabled: false, + sidebarViewOnLoad: -1, + scrollModeOnLoad: -1, + spreadModeOnLoad: -1, + textLayerMode: 1, + viewOnLoad: 0, + disableAutoFetch: false, + disableFontFace: false, + disableRange: false, + disableStream: false, + enableXfa: true }); diff --git a/toolkit/components/pdfjs/content/build/pdf.mjs b/toolkit/components/pdfjs/content/build/pdf.mjs index 2faa7f2888a4..d6f8b5230d3b 100644 --- a/toolkit/components/pdfjs/content/build/pdf.mjs +++ b/toolkit/components/pdfjs/content/build/pdf.mjs @@ -137,7 +137,8 @@ const AnnotationEditorParamsType = { INK_THICKNESS: 22, INK_OPACITY: 23, HIGHLIGHT_COLOR: 31, - HIGHLIGHT_DEFAULT_COLOR: 32 + HIGHLIGHT_DEFAULT_COLOR: 32, + HIGHLIGHT_THICKNESS: 33 }; const PermissionFlag = { PRINT: 0x04, @@ -575,43 +576,43 @@ class Util { if (transform[0]) { if (transform[0] < 0) { temp = minMax[0]; - minMax[0] = minMax[1]; - minMax[1] = temp; + minMax[0] = minMax[2]; + minMax[2] = temp; } minMax[0] *= transform[0]; - minMax[1] *= transform[0]; + minMax[2] *= transform[0]; if (transform[3] < 0) { - temp = minMax[2]; - minMax[2] = minMax[3]; + temp = minMax[1]; + minMax[1] = minMax[3]; minMax[3] = temp; } - minMax[2] *= transform[3]; + minMax[1] *= transform[3]; minMax[3] *= transform[3]; } else { temp = minMax[0]; - minMax[0] = minMax[2]; - minMax[2] = temp; - temp = minMax[1]; - minMax[1] = minMax[3]; + minMax[0] = minMax[1]; + minMax[1] = temp; + temp = minMax[2]; + minMax[2] = minMax[3]; minMax[3] = temp; if (transform[1] < 0) { - temp = minMax[2]; - minMax[2] = minMax[3]; + temp = minMax[1]; + minMax[1] = minMax[3]; minMax[3] = temp; } - minMax[2] *= transform[1]; + minMax[1] *= transform[1]; minMax[3] *= transform[1]; if (transform[2] < 0) { temp = minMax[0]; - minMax[0] = minMax[1]; - minMax[1] = temp; + minMax[0] = minMax[2]; + minMax[2] = temp; } minMax[0] *= transform[2]; - minMax[1] *= transform[2]; + minMax[2] *= transform[2]; } minMax[0] += transform[4]; - minMax[1] += transform[4]; - minMax[2] += transform[5]; + minMax[1] += transform[5]; + minMax[2] += transform[4]; minMax[3] += transform[5]; } static transform(m1, m2) { @@ -676,59 +677,48 @@ class Util { } return [xLow, yLow, xHigh, yHigh]; } - static bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3) { - const tvalues = [], - bounds = [[], []]; - let a, b, c, t, t1, t2, b2ac, sqrtb2ac; - for (let i = 0; i < 2; ++i) { - if (i === 0) { - b = 6 * x0 - 12 * x1 + 6 * x2; - a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3; - c = 3 * x1 - 3 * x0; - } else { - b = 6 * y0 - 12 * y1 + 6 * y2; - a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3; - c = 3 * y1 - 3 * y0; - } - if (Math.abs(a) < 1e-12) { - if (Math.abs(b) < 1e-12) { - continue; - } - t = -c / b; - if (0 < t && t < 1) { - tvalues.push(t); - } - continue; - } - b2ac = b * b - 4 * c * a; - sqrtb2ac = Math.sqrt(b2ac); - if (b2ac < 0) { - continue; - } - t1 = (-b + sqrtb2ac) / (2 * a); - if (0 < t1 && t1 < 1) { - tvalues.push(t1); - } - t2 = (-b - sqrtb2ac) / (2 * a); - if (0 < t2 && t2 < 1) { - tvalues.push(t2); - } + static #getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, t, minMax) { + if (t <= 0 || t >= 1) { + return; } - let j = tvalues.length, - mt; - const jlen = j; - while (j--) { - t = tvalues[j]; - mt = 1 - t; - bounds[0][j] = mt * mt * mt * x0 + 3 * mt * mt * t * x1 + 3 * mt * t * t * x2 + t * t * t * x3; - bounds[1][j] = mt * mt * mt * y0 + 3 * mt * mt * t * y1 + 3 * mt * t * t * y2 + t * t * t * y3; + const mt = 1 - t; + const tt = t * t; + const ttt = tt * t; + const x = mt * (mt * (mt * x0 + 3 * t * x1) + 3 * tt * x2) + ttt * x3; + const y = mt * (mt * (mt * y0 + 3 * t * y1) + 3 * tt * y2) + ttt * y3; + minMax[0] = Math.min(minMax[0], x); + minMax[1] = Math.min(minMax[1], y); + minMax[2] = Math.max(minMax[2], x); + minMax[3] = Math.max(minMax[3], y); + } + static #getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, a, b, c, minMax) { + if (Math.abs(a) < 1e-12) { + if (Math.abs(b) >= 1e-12) { + this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, -c / b, minMax); + } + return; } - bounds[0][jlen] = x0; - bounds[1][jlen] = y0; - bounds[0][jlen + 1] = x3; - bounds[1][jlen + 1] = y3; - bounds[0].length = bounds[1].length = jlen + 2; - return [Math.min(...bounds[0]), Math.min(...bounds[1]), Math.max(...bounds[0]), Math.max(...bounds[1])]; + const delta = b ** 2 - 4 * c * a; + if (delta < 0) { + return; + } + const sqrtDelta = Math.sqrt(delta); + const a2 = 2 * a; + this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, (-b + sqrtDelta) / a2, minMax); + this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, (-b - sqrtDelta) / a2, minMax); + } + static bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3, minMax) { + if (minMax) { + minMax[0] = Math.min(minMax[0], x0, x3); + minMax[1] = Math.min(minMax[1], y0, y3); + minMax[2] = Math.max(minMax[2], x0, x3); + minMax[3] = Math.max(minMax[3], y0, y3); + } else { + minMax = [Math.min(x0, x3), Math.min(y0, y3), Math.max(x0, x3), Math.max(y0, y3)]; + } + this.#getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, 3 * (-x0 + 3 * (x1 - x2) + x3), 6 * (x0 - 2 * x1 + x2), 3 * (x1 - x0), minMax); + this.#getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, 3 * (-y0 + 3 * (y1 - y2) + y3), 6 * (y0 - 2 * y1 + y2), 3 * (y1 - y0), minMax); + return minMax; } } const PDFStringTranslateTable = (/* unused pure expression or super */ null && ([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2d8, 0x2c7, 0x2c6, 0x2d9, 0x2dd, 0x2db, 0x2da, 0x2dc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x192, 0x2044, 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018, 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x141, 0x152, 0x160, 0x178, 0x17d, 0x131, 0x142, 0x153, 0x161, 0x17e, 0, 0x20ac])); @@ -782,9 +772,6 @@ function stringToUTF8String(str) { function utf8StringToString(str) { return unescape(encodeURIComponent(str)); } -function isArrayBuffer(v) { - return typeof v === "object" && v?.byteLength !== undefined; -} function isArrayEqual(arr1, arr2) { if (arr1.length !== arr2.length) { return false; @@ -825,9 +812,7 @@ function normalizeUnicode(str) { NormalizeRegex = /([\u00a0\u00b5\u037e\u0eb3\u2000-\u200a\u202f\u2126\ufb00-\ufb04\ufb06\ufb20-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufba1\ufba4-\ufba9\ufbae-\ufbb1\ufbd3-\ufbdc\ufbde-\ufbe7\ufbea-\ufbf8\ufbfc-\ufbfd\ufc00-\ufc5d\ufc64-\ufcf1\ufcf5-\ufd3d\ufd88\ufdf4\ufdfa-\ufdfb\ufe71\ufe77\ufe79\ufe7b\ufe7d]+)|(\ufb05+)/gu; NormalizationMap = new Map([["ſt", "ſt"]]); } - return str.replaceAll(NormalizeRegex, (_, p1, p2) => { - return p1 ? p1.normalize("NFKC") : NormalizationMap.get(p2); - }); + return str.replaceAll(NormalizeRegex, (_, p1, p2) => p1 ? p1.normalize("NFKC") : NormalizationMap.get(p2)); } function getUuid() { return crypto.randomUUID(); @@ -848,7 +833,7 @@ class BaseFilterFactory { addHCMFilter(fgColor, bgColor) { return "none"; } - addHighlightHCMFilter(fgColor, bgColor, newFgColor, newBgColor) { + addHighlightHCMFilter(filterName, fgColor, bgColor, newFgColor, newBgColor) { return "none"; } destroy(keepHCM = false) {} @@ -994,12 +979,7 @@ class DOMFilterFactory extends BaseFilterFactory { #_defs; #docId; #document; - #hcmFilter; - #hcmKey; - #hcmUrl; - #hcmHighlightFilter; - #hcmHighlightKey; - #hcmHighlightUrl; + #_hcmCache; #id = 0; constructor({ docId, @@ -1012,6 +992,9 @@ class DOMFilterFactory extends BaseFilterFactory { get #cache() { return this.#_cache ||= new Map(); } + get #hcmCache() { + return this.#_hcmCache ||= new Map(); + } get #defs() { if (!this.#_defs) { const div = this.#document.createElement("div"); @@ -1080,14 +1063,26 @@ class DOMFilterFactory extends BaseFilterFactory { } addHCMFilter(fgColor, bgColor) { const key = `${fgColor}-${bgColor}`; - if (this.#hcmKey === key) { - return this.#hcmUrl; + const filterName = "base"; + let info = this.#hcmCache.get(filterName); + if (info?.key === key) { + return info.url; + } + if (info) { + info.filter?.remove(); + info.key = key; + info.url = "none"; + info.filter = null; + } else { + info = { + key, + url: "none", + filter: null + }; + this.#hcmCache.set(filterName, info); } - this.#hcmKey = key; - this.#hcmUrl = "none"; - this.#hcmFilter?.remove(); if (!fgColor || !bgColor) { - return this.#hcmUrl; + return info.url; } const fgRGB = this.#getRGB(fgColor); fgColor = Util.makeHexColor(...fgRGB); @@ -1095,7 +1090,7 @@ class DOMFilterFactory extends BaseFilterFactory { bgColor = Util.makeHexColor(...bgRGB); this.#defs.style.color = ""; if (fgColor === "#000000" && bgColor === "#ffffff" || fgColor === bgColor) { - return this.#hcmUrl; + return info.url; } const map = new Array(256); for (let i = 0; i <= 255; i++) { @@ -1104,7 +1099,7 @@ class DOMFilterFactory extends BaseFilterFactory { } const table = map.join(","); const id = `g_${this.#docId}_hcm_filter`; - const filter = this.#hcmHighlightFilter = this.#createFilter(id); + const filter = info.filter = this.#createFilter(id); this.#addTransferMapConversion(table, table, table, filter); this.#addGrayConversion(filter); const getSteps = (c, n) => { @@ -1117,19 +1112,30 @@ class DOMFilterFactory extends BaseFilterFactory { return arr.join(","); }; this.#addTransferMapConversion(getSteps(0, 5), getSteps(1, 5), getSteps(2, 5), filter); - this.#hcmUrl = `url(#${id})`; - return this.#hcmUrl; + info.url = `url(#${id})`; + return info.url; } - addHighlightHCMFilter(fgColor, bgColor, newFgColor, newBgColor) { + addHighlightHCMFilter(filterName, fgColor, bgColor, newFgColor, newBgColor) { const key = `${fgColor}-${bgColor}-${newFgColor}-${newBgColor}`; - if (this.#hcmHighlightKey === key) { - return this.#hcmHighlightUrl; + let info = this.#hcmCache.get(filterName); + if (info?.key === key) { + return info.url; + } + if (info) { + info.filter?.remove(); + info.key = key; + info.url = "none"; + info.filter = null; + } else { + info = { + key, + url: "none", + filter: null + }; + this.#hcmCache.set(filterName, info); } - this.#hcmHighlightKey = key; - this.#hcmHighlightUrl = "none"; - this.#hcmHighlightFilter?.remove(); if (!fgColor || !bgColor) { - return this.#hcmHighlightUrl; + return info.url; } const [fgRGB, bgRGB] = [fgColor, bgColor].map(this.#getRGB.bind(this)); let fgGray = Math.round(0.2126 * fgRGB[0] + 0.7152 * fgRGB[1] + 0.0722 * fgRGB[2]); @@ -1158,15 +1164,15 @@ class DOMFilterFactory extends BaseFilterFactory { } return arr.join(","); }; - const id = `g_${this.#docId}_hcm_highlight_filter`; - const filter = this.#hcmHighlightFilter = this.#createFilter(id); + const id = `g_${this.#docId}_hcm_${filterName}_filter`; + const filter = info.filter = this.#createFilter(id); this.#addGrayConversion(filter); this.#addTransferMapConversion(getSteps(newFgRGB[0], newBgRGB[0], 5), getSteps(newFgRGB[1], newBgRGB[1], 5), getSteps(newFgRGB[2], newBgRGB[2], 5), filter); - this.#hcmHighlightUrl = `url(#${id})`; - return this.#hcmHighlightUrl; + info.url = `url(#${id})`; + return info.url; } destroy(keepHCM = false) { - if (keepHCM && (this.#hcmUrl || this.#hcmHighlightUrl)) { + if (keepHCM && this.#hcmCache.size !== 0) { return; } if (this.#_defs) { @@ -1241,19 +1247,15 @@ async function fetchData(url, type = "text") { } class DOMCMapReaderFactory extends BaseCMapReaderFactory { _fetchData(url, compressionType) { - return fetchData(url, this.isCompressed ? "arraybuffer" : "text").then(data => { - return { - cMapData: data instanceof ArrayBuffer ? new Uint8Array(data) : stringToBytes(data), - compressionType - }; - }); + return fetchData(url, this.isCompressed ? "arraybuffer" : "text").then(data => ({ + cMapData: data instanceof ArrayBuffer ? new Uint8Array(data) : stringToBytes(data), + compressionType + })); } } class DOMStandardFontDataFactory extends BaseStandardFontDataFactory { _fetchData(url) { - return fetchData(url, "arraybuffer").then(data => { - return new Uint8Array(data); - }); + return fetchData(url, "arraybuffer").then(data => new Uint8Array(data)); } } class DOMSVGFactory extends BaseSVGFactory { @@ -1738,6 +1740,7 @@ class CommandManager { add({ cmd, undo, + post, mustExec, type = NaN, overwriteIfSameType = false, @@ -1752,6 +1755,7 @@ class CommandManager { const save = { cmd, undo, + post, type }; if (this.#position === -1) { @@ -1785,7 +1789,12 @@ class CommandManager { return; } this.#locked = true; - this.#commands[this.#position].undo(); + const { + undo, + post + } = this.#commands[this.#position]; + undo(); + post?.(); this.#locked = false; this.#position -= 1; } @@ -1793,7 +1802,12 @@ class CommandManager { if (this.#position < this.#commands.length - 1) { this.#position += 1; this.#locked = true; - this.#commands[this.#position].cmd(); + const { + cmd, + post + } = this.#commands[this.#position]; + cmd(); + post?.(); this.#locked = false; } } @@ -1953,9 +1967,7 @@ class AnnotationEditorUIManager { static TRANSLATE_BIG = 10; static get _keyboardManager() { const proto = AnnotationEditorUIManager.prototype; - const arrowChecker = self => { - return self.#container.contains(document.activeElement) && document.activeElement.tagName !== "BUTTON" && self.hasSomethingToControl(); - }; + const arrowChecker = self => self.#container.contains(document.activeElement) && document.activeElement.tagName !== "BUTTON" && self.hasSomethingToControl(); const textInputChecker = (_self, { target: el }) => { @@ -2491,6 +2503,16 @@ class AnnotationEditorUIManager { this.#dispatchUpdateUI(editor.propertiesToUpdate); } } + get #lastSelectedEditor() { + let ed = null; + for (ed of this.#selectedEditors) {} + return ed; + } + updateUI(editor) { + if (this.#lastSelectedEditor === editor) { + this.#dispatchUpdateUI(editor.propertiesToUpdate); + } + } toggleSelected(editor) { if (this.#selectedEditors.has(editor)) { this.#selectedEditors.delete(editor); @@ -2604,6 +2626,9 @@ class AnnotationEditorUIManager { return this.#activeEditor || this.hasSelection; } #selectEditors(editors) { + for (const editor of this.#selectedEditors) { + editor.unselect(); + } this.#selectedEditors.clear(); for (const editor of editors) { if (editor.isEmpty()) { @@ -2613,7 +2638,7 @@ class AnnotationEditorUIManager { editor.select(); } this.#dispatchUpdateStates({ - hasSelectedEditor: true + hasSelectedEditor: this.hasSelection }); } selectAll() { @@ -3285,7 +3310,7 @@ class AnnotationEditor { x, y } = this; - const [bx, by] = this.#getBaseTranslation(); + const [bx, by] = this.getBaseTranslation(); x += bx; y += by; this.div.style.left = `${(100 * x).toFixed(2)}%`; @@ -3294,7 +3319,7 @@ class AnnotationEditor { block: "nearest" }); } - #getBaseTranslation() { + getBaseTranslation() { const [parentWidth, parentHeight] = this.parentDimensions; const { _borderLineWidth @@ -3344,7 +3369,7 @@ class AnnotationEditor { } this.x = x /= pageWidth; this.y = y /= pageHeight; - const [bx, by] = this.#getBaseTranslation(); + const [bx, by] = this.getBaseTranslation(); x += bx; y += by; const { @@ -4045,7 +4070,6 @@ class FakeEditor extends AnnotationEditor { } ;// CONCATENATED MODULE: ./src/shared/murmurhash3.js - const SEED = 0xc3d2e1f0; const MASK_HIGH = 0xffff0000; const MASK_LOW = 0xffff; @@ -4068,11 +4092,11 @@ class MurmurHash3_64 { data[length++] = code & 0xff; } } - } else if (isArrayBuffer(input)) { + } else if (ArrayBuffer.isView(input)) { data = input.slice(); length = data.byteLength; } else { - throw new Error("Wrong data format in MurmurHash3_64_update. " + "Input must be a string or array."); + throw new Error("Invalid data format, must be a string or TypedArray."); } const blockCounts = length >> 2; const tailLength = length - blockCounts * 4; @@ -5399,17 +5423,13 @@ class CanvasExtraState { updateScalingPathMinMax(transform, minMax) { Util.scaleMinMax(transform, minMax); this.minX = Math.min(this.minX, minMax[0]); - this.maxX = Math.max(this.maxX, minMax[1]); - this.minY = Math.min(this.minY, minMax[2]); + this.minY = Math.min(this.minY, minMax[1]); + this.maxX = Math.max(this.maxX, minMax[2]); this.maxY = Math.max(this.maxY, minMax[3]); } updateCurvePathMinMax(transform, x0, y0, x1, y1, x2, y2, x3, y3, minMax) { - const box = Util.bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3); + const box = Util.bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3, minMax); if (minMax) { - minMax[0] = Math.min(minMax[0], box[0], box[2]); - minMax[1] = Math.max(minMax[1], box[0], box[2]); - minMax[2] = Math.min(minMax[2], box[1], box[3]); - minMax[3] = Math.max(minMax[3], box[1], box[3]); return; } this.updateRectMinMax(transform, box); @@ -6635,12 +6655,10 @@ class CanvasGraphics { const color = IR[1]; const baseTransform = this.baseTransform || getCurrentTransform(this.ctx); const canvasGraphicsFactory = { - createCanvasGraphics: ctx => { - return new CanvasGraphics(ctx, this.commonObjs, this.objs, this.canvasFactory, this.filterFactory, { - optionalContentConfig: this.optionalContentConfig, - markedContentStack: this.markedContentStack - }); - } + createCanvasGraphics: ctx => new CanvasGraphics(ctx, this.commonObjs, this.objs, this.canvasFactory, this.filterFactory, { + optionalContentConfig: this.optionalContentConfig, + markedContentStack: this.markedContentStack + }) }; pattern = new TilingPattern(IR, color, this.ctx, canvasGraphicsFactory, baseTransform); } else { @@ -8647,7 +8665,7 @@ function getDocument(src) { } const fetchDocParams = { docId, - apiVersion: '4.1.30', + apiVersion: "4.1.86", data, password, disableAutoFetch, @@ -8732,7 +8750,7 @@ function getDataProp(val) { if (typeof val === "string") { return stringToBytes(val); } - if (typeof val === "object" && !isNaN(val?.length) || isArrayBuffer(val)) { + if (val instanceof ArrayBuffer || ArrayBuffer.isView(val) || typeof val === "object" && !isNaN(val?.length)) { return new Uint8Array(val); } throw new Error("Invalid PDF binary data: either TypedArray, " + "string, or array-like object is expected in the data property."); @@ -9113,9 +9131,7 @@ class PDFPageProxy { } getTextContent(params = {}) { if (this._transport._htmlForXfa) { - return this.getXfa().then(xfa => { - return XfaText.textContent(xfa); - }); + return this.getXfa().then(xfa => XfaText.textContent(xfa)); } const readableStream = this.streamTextContent(params); return new Promise(function (resolve, reject) { @@ -9820,11 +9836,9 @@ class WorkerTransport { ignoreErrors: params.ignoreErrors, inspectFont }); - this.fontLoader.bind(font).catch(reason => { - return messageHandler.sendWithPromise("FontFallback", { - id - }); - }).finally(() => { + this.fontLoader.bind(font).catch(() => messageHandler.sendWithPromise("FontFallback", { + id + })).finally(() => { if (!params.fontExtraProperties && font.data) { font.data = null; } @@ -10025,9 +10039,7 @@ class WorkerTransport { return this.messageHandler.sendWithPromise("GetOutline", null); } getOptionalContentConfig() { - return this.messageHandler.sendWithPromise("GetOptionalContentConfig", null).then(results => { - return new OptionalContentConfig(results); - }); + return this.messageHandler.sendWithPromise("GetOptionalContentConfig", null).then(results => new OptionalContentConfig(results)); } getPermissions() { return this.messageHandler.sendWithPromise("GetPermissions", null); @@ -10038,14 +10050,12 @@ class WorkerTransport { if (cachedPromise) { return cachedPromise; } - const promise = this.messageHandler.sendWithPromise(name, null).then(results => { - return { - info: results[0], - metadata: results[1] ? new Metadata(results[1]) : null, - contentDispositionFilename: this._fullReader?.filename ?? null, - contentLength: this._fullReader?.contentLength ?? null - }; - }); + const promise = this.messageHandler.sendWithPromise(name, null).then(results => ({ + info: results[0], + metadata: results[1] ? new Metadata(results[1]) : null, + contentDispositionFilename: this._fullReader?.filename ?? null, + contentLength: this._fullReader?.contentLength ?? null + })); this.#methodPromises.set(name, promise); return promise; } @@ -10292,8 +10302,8 @@ class InternalRenderTask { } } } -const version = '4.1.30'; -const build = 'a22b5a4f0'; +const version = "4.1.86"; +const build = "bf9236009"; ;// CONCATENATED MODULE: ./src/shared/scripting_utils.js function makeColorComp(n) { @@ -12029,12 +12039,10 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement { let selectedValues = getValue(false); const getItems = event => { const options = event.target.options; - return Array.prototype.map.call(options, option => { - return { - displayValue: option.textContent, - exportValue: option.value - }; - }); + return Array.prototype.map.call(options, option => ({ + displayValue: option.textContent, + exportValue: option.value + })); }; if (this.enableScripting && this.hasJSActions) { selectElement.addEventListener("updatefromsandbox", jsEvent => { @@ -13062,12 +13070,9 @@ class FreeTextEditor extends AnnotationEditor { }; const savedFontsize = this.#fontSize; this.addCommands({ - cmd: () => { - setFontsize(fontSize); - }, - undo: () => { - setFontsize(savedFontsize); - }, + cmd: setFontsize.bind(this, fontSize), + undo: setFontsize.bind(this, savedFontsize), + post: this._uiManager.updateUI.bind(this._uiManager, this), mustExec: true, type: AnnotationEditorParamsType.FREETEXT_SIZE, overwriteIfSameType: true, @@ -13075,14 +13080,14 @@ class FreeTextEditor extends AnnotationEditor { }); } #updateColor(color) { + const setColor = col => { + this.#color = this.editorDiv.style.color = col; + }; const savedColor = this.#color; this.addCommands({ - cmd: () => { - this.#color = this.editorDiv.style.color = color; - }, - undo: () => { - this.#color = this.editorDiv.style.color = savedColor; - }, + cmd: setColor.bind(this, color), + undo: setColor.bind(this, savedColor), + post: this._uiManager.updateUI.bind(this._uiManager, this), mustExec: true, type: AnnotationEditorParamsType.FREETEXT_COLOR, overwriteIfSameType: true, @@ -13474,168 +13479,8 @@ class FreeTextEditor extends AnnotationEditor { } } -;// CONCATENATED MODULE: ./src/display/editor/color_picker.js - - - -class ColorPicker { - #boundKeyDown = this.#keyDown.bind(this); - #button = null; - #buttonSwatch = null; - #defaultColor; - #dropdown = null; - #dropdownWasFromKeyboard = false; - #isMainColorPicker = false; - #eventBus; - #uiManager = null; - #type; - static get _keyboardManager() { - return shadow(this, "_keyboardManager", new KeyboardManager([[["Escape", "mac+Escape"], ColorPicker.prototype._hideDropdownFromKeyboard], [[" ", "mac+ "], ColorPicker.prototype._colorSelectFromKeyboard], [["ArrowDown", "ArrowRight", "mac+ArrowDown", "mac+ArrowRight"], ColorPicker.prototype._moveToNext], [["ArrowUp", "ArrowLeft", "mac+ArrowUp", "mac+ArrowLeft"], ColorPicker.prototype._moveToPrevious], [["Home", "mac+Home"], ColorPicker.prototype._moveToBeginning], [["End", "mac+End"], ColorPicker.prototype._moveToEnd]])); - } - constructor({ - editor = null, - uiManager = null - }) { - if (editor) { - this.#isMainColorPicker = false; - this.#type = AnnotationEditorParamsType.HIGHLIGHT_COLOR; - } else { - this.#isMainColorPicker = true; - this.#type = AnnotationEditorParamsType.HIGHLIGHT_DEFAULT_COLOR; - } - this.#uiManager = editor?._uiManager || uiManager; - this.#eventBus = this.#uiManager._eventBus; - this.#defaultColor = editor?.color || this.#uiManager?.highlightColors.values().next().value || "#FFFF98"; - } - renderButton() { - const button = this.#button = document.createElement("button"); - button.className = "colorPicker"; - button.tabIndex = "0"; - button.setAttribute("data-l10n-id", "pdfjs-editor-colorpicker-button"); - button.setAttribute("aria-haspopup", true); - button.addEventListener("click", this.#openDropdown.bind(this)); - const swatch = this.#buttonSwatch = document.createElement("span"); - swatch.className = "swatch"; - swatch.style.backgroundColor = this.#defaultColor; - button.append(swatch); - return button; - } - renderMainDropdown() { - const dropdown = this.#dropdown = this.#getDropdownRoot(); - dropdown.setAttribute("aria-orientation", "horizontal"); - dropdown.setAttribute("aria-labelledby", "highlightColorPickerLabel"); - return dropdown; - } - #getDropdownRoot() { - const div = document.createElement("div"); - div.addEventListener("contextmenu", noContextMenu); - div.className = "dropdown"; - div.role = "listbox"; - div.setAttribute("aria-multiselectable", false); - div.setAttribute("aria-orientation", "vertical"); - div.setAttribute("data-l10n-id", "pdfjs-editor-colorpicker-dropdown"); - for (const [name, color] of this.#uiManager.highlightColors) { - const button = document.createElement("button"); - button.tabIndex = "0"; - button.role = "option"; - button.setAttribute("data-color", color); - button.title = name; - button.setAttribute("data-l10n-id", `pdfjs-editor-colorpicker-${name}`); - const swatch = document.createElement("span"); - button.append(swatch); - swatch.className = "swatch"; - swatch.style.backgroundColor = color; - button.setAttribute("aria-selected", color === this.#defaultColor); - button.addEventListener("click", this.#colorSelect.bind(this, color)); - div.append(button); - } - div.addEventListener("keydown", this.#boundKeyDown); - return div; - } - #colorSelect(color, event) { - event.stopPropagation(); - this.#eventBus.dispatch("switchannotationeditorparams", { - source: this, - type: this.#type, - value: color - }); - } - _colorSelectFromKeyboard(event) { - const color = event.target.getAttribute("data-color"); - if (!color) { - return; - } - this.#colorSelect(color, event); - } - _moveToNext(event) { - if (event.target === this.#button) { - this.#dropdown.firstChild?.focus(); - return; - } - event.target.nextSibling?.focus(); - } - _moveToPrevious(event) { - event.target.previousSibling?.focus(); - } - _moveToBeginning() { - this.#dropdown.firstChild?.focus(); - } - _moveToEnd() { - this.#dropdown.lastChild?.focus(); - } - #keyDown(event) { - ColorPicker._keyboardManager.exec(this, event); - } - #openDropdown(event) { - if (this.#dropdown && !this.#dropdown.classList.contains("hidden")) { - this.hideDropdown(); - return; - } - this.#button.addEventListener("keydown", this.#boundKeyDown); - this.#dropdownWasFromKeyboard = event.detail === 0; - if (this.#dropdown) { - this.#dropdown.classList.remove("hidden"); - return; - } - const root = this.#dropdown = this.#getDropdownRoot(AnnotationEditorParamsType.HIGHLIGHT_COLOR); - this.#button.append(root); - } - hideDropdown() { - this.#dropdown?.classList.add("hidden"); - } - _hideDropdownFromKeyboard() { - if (this.#isMainColorPicker || !this.#dropdown || this.#dropdown.classList.contains("hidden")) { - return; - } - this.hideDropdown(); - this.#button.removeEventListener("keydown", this.#boundKeyDown); - this.#button.focus({ - preventScroll: true, - focusVisible: this.#dropdownWasFromKeyboard - }); - } - updateColor(color) { - if (this.#buttonSwatch) { - this.#buttonSwatch.style.backgroundColor = color; - } - if (!this.#dropdown) { - return; - } - const i = this.#uiManager.highlightColors.values(); - for (const child of this.#dropdown.children) { - child.setAttribute("aria-selected", i.next().value === color); - } - } - destroy() { - this.#button?.remove(); - this.#button = null; - this.#buttonSwatch = null; - this.#dropdown?.remove(); - this.#dropdown = null; - } -} - ;// CONCATENATED MODULE: ./src/display/editor/outliner.js + class Outliner { #box; #verticalEdges = []; @@ -13834,6 +13679,9 @@ class Outline { serialize(_bbox, _rotation) { throw new Error("Abstract method `serialize` must be implemented."); } + get free() { + return this instanceof FreeHighlightOutline; + } } class HighlightOutline extends Outline { #box; @@ -13881,6 +13729,540 @@ class HighlightOutline extends Outline { return this.#box; } } +class FreeOutliner { + #box; + #bottom = []; + #innerMargin; + #isLTR; + #top = []; + #last = new Float64Array(18); + #min; + #min_dist; + #scaleFactor; + #thickness; + #points = []; + static #MIN_DIST = 8; + static #MIN_DIFF = 2; + static #MIN = FreeOutliner.#MIN_DIST + FreeOutliner.#MIN_DIFF; + constructor({ + x, + y + }, box, scaleFactor, thickness, isLTR, innerMargin = 0) { + this.#box = box; + this.#thickness = thickness * scaleFactor; + this.#isLTR = isLTR; + this.#last.set([NaN, NaN, NaN, NaN, x, y], 6); + this.#innerMargin = innerMargin; + this.#min_dist = FreeOutliner.#MIN_DIST * scaleFactor; + this.#min = FreeOutliner.#MIN * scaleFactor; + this.#scaleFactor = scaleFactor; + this.#points.push(x, y); + } + get free() { + return true; + } + isEmpty() { + return isNaN(this.#last[8]); + } + add({ + x, + y + }) { + const [layerX, layerY, layerWidth, layerHeight] = this.#box; + let [x1, y1, x2, y2] = this.#last.subarray(8, 12); + const diffX = x - x2; + const diffY = y - y2; + const d = Math.hypot(diffX, diffY); + if (d < this.#min) { + return false; + } + const diffD = d - this.#min_dist; + const K = diffD / d; + const shiftX = K * diffX; + const shiftY = K * diffY; + let x0 = x1; + let y0 = y1; + x1 = x2; + y1 = y2; + x2 += shiftX; + y2 += shiftY; + this.#points?.push(x, y); + const nX = -shiftY / diffD; + const nY = shiftX / diffD; + const thX = nX * this.#thickness; + const thY = nY * this.#thickness; + this.#last.set(this.#last.subarray(2, 8), 0); + this.#last.set([x2 + thX, y2 + thY], 4); + this.#last.set(this.#last.subarray(14, 18), 12); + this.#last.set([x2 - thX, y2 - thY], 16); + if (isNaN(this.#last[6])) { + if (this.#top.length === 0) { + this.#last.set([x1 + thX, y1 + thY], 2); + this.#top.push(NaN, NaN, NaN, NaN, (x1 + thX - layerX) / layerWidth, (y1 + thY - layerY) / layerHeight); + this.#last.set([x1 - thX, y1 - thY], 14); + this.#bottom.push(NaN, NaN, NaN, NaN, (x1 - thX - layerX) / layerWidth, (y1 - thY - layerY) / layerHeight); + } + this.#last.set([x0, y0, x1, y1, x2, y2], 6); + return !this.isEmpty(); + } + this.#last.set([x0, y0, x1, y1, x2, y2], 6); + const angle = Math.abs(Math.atan2(y0 - y1, x0 - x1) - Math.atan2(shiftY, shiftX)); + if (angle < Math.PI / 2) { + [x1, y1, x2, y2] = this.#last.subarray(2, 6); + this.#top.push(NaN, NaN, NaN, NaN, ((x1 + x2) / 2 - layerX) / layerWidth, ((y1 + y2) / 2 - layerY) / layerHeight); + [x1, y1, x0, y0] = this.#last.subarray(14, 18); + this.#bottom.push(NaN, NaN, NaN, NaN, ((x0 + x1) / 2 - layerX) / layerWidth, ((y0 + y1) / 2 - layerY) / layerHeight); + return true; + } + [x0, y0, x1, y1, x2, y2] = this.#last.subarray(0, 6); + this.#top.push(((x0 + 5 * x1) / 6 - layerX) / layerWidth, ((y0 + 5 * y1) / 6 - layerY) / layerHeight, ((5 * x1 + x2) / 6 - layerX) / layerWidth, ((5 * y1 + y2) / 6 - layerY) / layerHeight, ((x1 + x2) / 2 - layerX) / layerWidth, ((y1 + y2) / 2 - layerY) / layerHeight); + [x2, y2, x1, y1, x0, y0] = this.#last.subarray(12, 18); + this.#bottom.push(((x0 + 5 * x1) / 6 - layerX) / layerWidth, ((y0 + 5 * y1) / 6 - layerY) / layerHeight, ((5 * x1 + x2) / 6 - layerX) / layerWidth, ((5 * y1 + y2) / 6 - layerY) / layerHeight, ((x1 + x2) / 2 - layerX) / layerWidth, ((y1 + y2) / 2 - layerY) / layerHeight); + return true; + } + toSVGPath() { + if (this.isEmpty()) { + return ""; + } + const top = this.#top; + const bottom = this.#bottom; + const lastTop = this.#last.subarray(4, 6); + const lastBottom = this.#last.subarray(16, 18); + const [x, y, width, height] = this.#box; + if (isNaN(this.#last[6]) && !this.isEmpty()) { + return `M${(this.#last[2] - x) / width} ${(this.#last[3] - y) / height} L${(this.#last[4] - x) / width} ${(this.#last[5] - y) / height} L${(this.#last[16] - x) / width} ${(this.#last[17] - y) / height} L${(this.#last[14] - x) / width} ${(this.#last[15] - y) / height} Z`; + } + const buffer = []; + buffer.push(`M${top[4]} ${top[5]}`); + for (let i = 6; i < top.length; i += 6) { + if (isNaN(top[i])) { + buffer.push(`L${top[i + 4]} ${top[i + 5]}`); + } else { + buffer.push(`C${top[i]} ${top[i + 1]} ${top[i + 2]} ${top[i + 3]} ${top[i + 4]} ${top[i + 5]}`); + } + } + buffer.push(`L${(lastTop[0] - x) / width} ${(lastTop[1] - y) / height} L${(lastBottom[0] - x) / width} ${(lastBottom[1] - y) / height}`); + for (let i = bottom.length - 6; i >= 6; i -= 6) { + if (isNaN(bottom[i])) { + buffer.push(`L${bottom[i + 4]} ${bottom[i + 5]}`); + } else { + buffer.push(`C${bottom[i]} ${bottom[i + 1]} ${bottom[i + 2]} ${bottom[i + 3]} ${bottom[i + 4]} ${bottom[i + 5]}`); + } + } + buffer.push(`L${bottom[4]} ${bottom[5]} Z`); + return buffer.join(" "); + } + getOutlines() { + const top = this.#top; + const bottom = this.#bottom; + const last = this.#last; + const lastTop = last.subarray(4, 6); + const lastBottom = last.subarray(16, 18); + const [layerX, layerY, layerWidth, layerHeight] = this.#box; + const points = new Float64Array(this.#points?.length ?? 0); + for (let i = 0, ii = points.length; i < ii; i += 2) { + points[i] = (this.#points[i] - layerX) / layerWidth; + points[i + 1] = (this.#points[i + 1] - layerY) / layerHeight; + } + if (isNaN(last[6]) && !this.isEmpty()) { + const outline = new Float64Array(24); + outline.set([NaN, NaN, NaN, NaN, (last[2] - layerX) / layerWidth, (last[3] - layerY) / layerHeight, NaN, NaN, NaN, NaN, (last[4] - layerX) / layerWidth, (last[5] - layerY) / layerHeight, NaN, NaN, NaN, NaN, (last[16] - layerX) / layerWidth, (last[17] - layerY) / layerHeight, NaN, NaN, NaN, NaN, (last[14] - layerX) / layerWidth, (last[15] - layerY) / layerHeight], 0); + return new FreeHighlightOutline(outline, points, this.#box, this.#scaleFactor, this.#innerMargin, this.#isLTR); + } + const outline = new Float64Array(this.#top.length + 12 + this.#bottom.length); + let N = top.length; + for (let i = 0; i < N; i += 2) { + if (isNaN(top[i])) { + outline[i] = outline[i + 1] = NaN; + continue; + } + outline[i] = top[i]; + outline[i + 1] = top[i + 1]; + } + outline.set([NaN, NaN, NaN, NaN, (lastTop[0] - layerX) / layerWidth, (lastTop[1] - layerY) / layerHeight, NaN, NaN, NaN, NaN, (lastBottom[0] - layerX) / layerWidth, (lastBottom[1] - layerY) / layerHeight], N); + N += 12; + for (let i = bottom.length - 6; i >= 6; i -= 6) { + for (let j = 0; j < 6; j += 2) { + if (isNaN(bottom[i + j])) { + outline[N] = outline[N + 1] = NaN; + N += 2; + continue; + } + outline[N] = bottom[i + j]; + outline[N + 1] = bottom[i + j + 1]; + N += 2; + } + } + outline.set([NaN, NaN, NaN, NaN, bottom[4], bottom[5]], N); + return new FreeHighlightOutline(outline, points, this.#box, this.#scaleFactor, this.#innerMargin, this.#isLTR); + } +} +class FreeHighlightOutline extends Outline { + #box; + #bbox = null; + #innerMargin; + #isLTR; + #points; + #scaleFactor; + #outline; + constructor(outline, points, box, scaleFactor, innerMargin, isLTR) { + super(); + this.#outline = outline; + this.#points = points; + this.#box = box; + this.#scaleFactor = scaleFactor; + this.#innerMargin = innerMargin; + this.#isLTR = isLTR; + this.#computeMinMax(isLTR); + const { + x, + y, + width, + height + } = this.#bbox; + for (let i = 0, ii = outline.length; i < ii; i += 2) { + outline[i] = (outline[i] - x) / width; + outline[i + 1] = (outline[i + 1] - y) / height; + } + for (let i = 0, ii = points.length; i < ii; i += 2) { + points[i] = (points[i] - x) / width; + points[i + 1] = (points[i + 1] - y) / height; + } + } + toSVGPath() { + const buffer = [`M${this.#outline[4]} ${this.#outline[5]}`]; + for (let i = 6, ii = this.#outline.length; i < ii; i += 6) { + if (isNaN(this.#outline[i])) { + buffer.push(`L${this.#outline[i + 4]} ${this.#outline[i + 5]}`); + continue; + } + buffer.push(`C${this.#outline[i]} ${this.#outline[i + 1]} ${this.#outline[i + 2]} ${this.#outline[i + 3]} ${this.#outline[i + 4]} ${this.#outline[i + 5]}`); + } + buffer.push("Z"); + return buffer.join(" "); + } + serialize([blX, blY, trX, trY], rotation) { + const width = trX - blX; + const height = trY - blY; + let outline; + let points; + switch (rotation) { + case 0: + outline = this.#rescale(this.#outline, blX, trY, width, -height); + points = this.#rescale(this.#points, blX, trY, width, -height); + break; + case 90: + outline = this.#rescaleAndSwap(this.#outline, blX, blY, width, height); + points = this.#rescaleAndSwap(this.#points, blX, blY, width, height); + break; + case 180: + outline = this.#rescale(this.#outline, trX, blY, -width, height); + points = this.#rescale(this.#points, trX, blY, -width, height); + break; + case 270: + outline = this.#rescaleAndSwap(this.#outline, trX, trY, -width, -height); + points = this.#rescaleAndSwap(this.#points, trX, trY, -width, -height); + break; + } + return { + outline: Array.from(outline), + points: [Array.from(points)] + }; + } + #rescale(src, tx, ty, sx, sy) { + const dest = new Float64Array(src.length); + for (let i = 0, ii = src.length; i < ii; i += 2) { + dest[i] = tx + src[i] * sx; + dest[i + 1] = ty + src[i + 1] * sy; + } + return dest; + } + #rescaleAndSwap(src, tx, ty, sx, sy) { + const dest = new Float64Array(src.length); + for (let i = 0, ii = src.length; i < ii; i += 2) { + dest[i] = tx + src[i + 1] * sx; + dest[i + 1] = ty + src[i] * sy; + } + return dest; + } + #computeMinMax(isLTR) { + const outline = this.#outline; + let lastX = outline[4]; + let lastY = outline[5]; + let minX = lastX; + let minY = lastY; + let maxX = lastX; + let maxY = lastY; + let lastPointX = lastX; + let lastPointY = lastY; + const ltrCallback = isLTR ? Math.max : Math.min; + for (let i = 6, ii = outline.length; i < ii; i += 6) { + if (isNaN(outline[i])) { + minX = Math.min(minX, outline[i + 4]); + minY = Math.min(minY, outline[i + 5]); + maxX = Math.max(maxX, outline[i + 4]); + maxY = Math.max(maxY, outline[i + 5]); + if (lastPointY < outline[i + 5]) { + lastPointX = outline[i + 4]; + lastPointY = outline[i + 5]; + } else if (lastPointY === outline[i + 5]) { + lastPointX = ltrCallback(lastPointX, outline[i + 4]); + } + } else { + const bbox = Util.bezierBoundingBox(lastX, lastY, ...outline.slice(i, i + 6)); + minX = Math.min(minX, bbox[0]); + minY = Math.min(minY, bbox[1]); + maxX = Math.max(maxX, bbox[2]); + maxY = Math.max(maxY, bbox[3]); + if (lastPointY < bbox[3]) { + lastPointX = bbox[2]; + lastPointY = bbox[3]; + } else if (lastPointY === bbox[3]) { + lastPointX = ltrCallback(lastPointX, bbox[2]); + } + } + lastX = outline[i + 4]; + lastY = outline[i + 5]; + } + const x = minX - this.#innerMargin, + y = minY - this.#innerMargin, + width = maxX - minX + 2 * this.#innerMargin, + height = maxY - minY + 2 * this.#innerMargin; + lastPointX = (lastPointX - x) / width; + lastPointY = (lastPointY - y) / height; + this.#bbox = { + x, + y, + width, + height, + lastPoint: [lastPointX, lastPointY] + }; + } + get box() { + return this.#bbox; + } + getNewOutline(thickness, innerMargin) { + const { + x, + y, + width, + height + } = this.#bbox; + const [layerX, layerY, layerWidth, layerHeight] = this.#box; + const sx = width * layerWidth; + const sy = height * layerHeight; + const tx = x * layerWidth + layerX; + const ty = y * layerHeight + layerY; + const outliner = new FreeOutliner({ + x: this.#points[0] * sx + tx, + y: this.#points[1] * sy + ty + }, this.#box, this.#scaleFactor, thickness, this.#isLTR, innerMargin ?? this.#innerMargin); + for (let i = 2; i < this.#points.length; i += 2) { + outliner.add({ + x: this.#points[i] * sx + tx, + y: this.#points[i + 1] * sy + ty + }); + } + return outliner.getOutlines(); + } +} + +;// CONCATENATED MODULE: ./src/display/editor/color_picker.js + + + +class ColorPicker { + #boundKeyDown = this.#keyDown.bind(this); + #boundPointerDown = this.#pointerDown.bind(this); + #button = null; + #buttonSwatch = null; + #defaultColor; + #dropdown = null; + #dropdownWasFromKeyboard = false; + #isMainColorPicker = false; + #eventBus; + #uiManager = null; + #type; + static get _keyboardManager() { + return shadow(this, "_keyboardManager", new KeyboardManager([[["Escape", "mac+Escape"], ColorPicker.prototype._hideDropdownFromKeyboard], [[" ", "mac+ "], ColorPicker.prototype._colorSelectFromKeyboard], [["ArrowDown", "ArrowRight", "mac+ArrowDown", "mac+ArrowRight"], ColorPicker.prototype._moveToNext], [["ArrowUp", "ArrowLeft", "mac+ArrowUp", "mac+ArrowLeft"], ColorPicker.prototype._moveToPrevious], [["Home", "mac+Home"], ColorPicker.prototype._moveToBeginning], [["End", "mac+End"], ColorPicker.prototype._moveToEnd]])); + } + constructor({ + editor = null, + uiManager = null + }) { + if (editor) { + this.#isMainColorPicker = false; + this.#type = AnnotationEditorParamsType.HIGHLIGHT_COLOR; + } else { + this.#isMainColorPicker = true; + this.#type = AnnotationEditorParamsType.HIGHLIGHT_DEFAULT_COLOR; + } + this.#uiManager = editor?._uiManager || uiManager; + this.#eventBus = this.#uiManager._eventBus; + this.#defaultColor = editor?.color || this.#uiManager?.highlightColors.values().next().value || "#FFFF98"; + } + renderButton() { + const button = this.#button = document.createElement("button"); + button.className = "colorPicker"; + button.tabIndex = "0"; + button.setAttribute("data-l10n-id", "pdfjs-editor-colorpicker-button"); + button.setAttribute("aria-haspopup", true); + button.addEventListener("click", this.#openDropdown.bind(this)); + button.addEventListener("keydown", this.#boundKeyDown); + const swatch = this.#buttonSwatch = document.createElement("span"); + swatch.className = "swatch"; + swatch.style.backgroundColor = this.#defaultColor; + button.append(swatch); + return button; + } + renderMainDropdown() { + const dropdown = this.#dropdown = this.#getDropdownRoot(); + dropdown.setAttribute("aria-orientation", "horizontal"); + dropdown.setAttribute("aria-labelledby", "highlightColorPickerLabel"); + return dropdown; + } + #getDropdownRoot() { + const div = document.createElement("div"); + div.addEventListener("contextmenu", noContextMenu); + div.className = "dropdown"; + div.role = "listbox"; + div.setAttribute("aria-multiselectable", false); + div.setAttribute("aria-orientation", "vertical"); + div.setAttribute("data-l10n-id", "pdfjs-editor-colorpicker-dropdown"); + for (const [name, color] of this.#uiManager.highlightColors) { + const button = document.createElement("button"); + button.tabIndex = "0"; + button.role = "option"; + button.setAttribute("data-color", color); + button.title = name; + button.setAttribute("data-l10n-id", `pdfjs-editor-colorpicker-${name}`); + const swatch = document.createElement("span"); + button.append(swatch); + swatch.className = "swatch"; + swatch.style.backgroundColor = color; + button.setAttribute("aria-selected", color === this.#defaultColor); + button.addEventListener("click", this.#colorSelect.bind(this, color)); + div.append(button); + } + div.addEventListener("keydown", this.#boundKeyDown); + return div; + } + #colorSelect(color, event) { + event.stopPropagation(); + this.#eventBus.dispatch("switchannotationeditorparams", { + source: this, + type: this.#type, + value: color + }); + } + _colorSelectFromKeyboard(event) { + if (event.target === this.#button) { + this.#openDropdown(event); + return; + } + const color = event.target.getAttribute("data-color"); + if (!color) { + return; + } + this.#colorSelect(color, event); + } + _moveToNext(event) { + if (!this.#isDropdownVisible) { + this.#openDropdown(event); + return; + } + if (event.target === this.#button) { + this.#dropdown.firstChild?.focus(); + return; + } + event.target.nextSibling?.focus(); + } + _moveToPrevious(event) { + if (event.target === this.#dropdown?.firstChild || event.target === this.#button) { + if (this.#isDropdownVisible) { + this._hideDropdownFromKeyboard(); + } + return; + } + if (!this.#isDropdownVisible) { + this.#openDropdown(event); + } + event.target.previousSibling?.focus(); + } + _moveToBeginning(event) { + if (!this.#isDropdownVisible) { + this.#openDropdown(event); + return; + } + this.#dropdown.firstChild?.focus(); + } + _moveToEnd(event) { + if (!this.#isDropdownVisible) { + this.#openDropdown(event); + return; + } + this.#dropdown.lastChild?.focus(); + } + #keyDown(event) { + ColorPicker._keyboardManager.exec(this, event); + } + #openDropdown(event) { + if (this.#isDropdownVisible) { + this.hideDropdown(); + return; + } + this.#dropdownWasFromKeyboard = event.detail === 0; + window.addEventListener("pointerdown", this.#boundPointerDown); + if (this.#dropdown) { + this.#dropdown.classList.remove("hidden"); + return; + } + const root = this.#dropdown = this.#getDropdownRoot(); + this.#button.append(root); + } + #pointerDown(event) { + if (this.#dropdown?.contains(event.target)) { + return; + } + this.hideDropdown(); + } + hideDropdown() { + this.#dropdown?.classList.add("hidden"); + window.removeEventListener("pointerdown", this.#boundPointerDown); + } + get #isDropdownVisible() { + return this.#dropdown && !this.#dropdown.classList.contains("hidden"); + } + _hideDropdownFromKeyboard() { + if (this.#isMainColorPicker || !this.#isDropdownVisible) { + return; + } + this.hideDropdown(); + this.#button.focus({ + preventScroll: true, + focusVisible: this.#dropdownWasFromKeyboard + }); + } + updateColor(color) { + if (this.#buttonSwatch) { + this.#buttonSwatch.style.backgroundColor = color; + } + if (!this.#dropdown) { + return; + } + const i = this.#uiManager.highlightColors.values(); + for (const child of this.#dropdown.children) { + child.setAttribute("aria-selected", i.next().value === color); + } + } + destroy() { + this.#button?.remove(); + this.#button = null; + this.#buttonSwatch = null; + this.#dropdown?.remove(); + this.#dropdown = null; + } +} ;// CONCATENATED MODULE: ./src/display/editor/highlight.js @@ -13888,6 +14270,7 @@ class HighlightOutline extends Outline { + class HighlightEditor extends AnnotationEditor { #boxes; #clipPathId = null; @@ -13896,26 +14279,39 @@ class HighlightEditor extends AnnotationEditor { #highlightDiv = null; #highlightOutlines = null; #id = null; + #isFreeHighlight = false; #lastPoint = null; #opacity; #outlineId = null; + #thickness; static _defaultColor = null; static _defaultOpacity = 1; + static _defaultThickness = 12; static _l10nPromise; static _type = "highlight"; static _editorType = AnnotationEditorType.HIGHLIGHT; + static _freeHighlightId = -1; + static _freeHighlight = null; + static _freeHighlightClipId = ""; constructor(params) { super({ ...params, name: "highlightEditor" }); this.color = params.color || HighlightEditor._defaultColor; + this.#thickness = params.thickness || HighlightEditor._defaultThickness; this.#opacity = params.opacity || HighlightEditor._defaultOpacity; this.#boxes = params.boxes || null; this._isDraggable = false; - this.#createOutlines(); - this.#addToDrawLayer(); - this.rotate(this.rotation); + if (params.highlightId > -1) { + this.#isFreeHighlight = true; + this.#createFreeOutlines(params); + this.#addToDrawLayer(); + } else { + this.#createOutlines(); + this.#addToDrawLayer(); + this.rotate(this.rotation); + } } #createOutlines() { const outliner = new Outliner(this.#boxes, 0.001); @@ -13933,6 +14329,64 @@ class HighlightEditor extends AnnotationEditor { } = this.#focusOutlines.box; this.#lastPoint = [(lastPoint[0] - this.x) / this.width, (lastPoint[1] - this.y) / this.height]; } + #createFreeOutlines({ + highlightOutlines, + highlightId, + clipPathId + }) { + this.#highlightOutlines = highlightOutlines; + const extraThickness = 1.5; + this.#focusOutlines = highlightOutlines.getNewOutline(this.#thickness / 2 + extraThickness, 0.0025); + if (highlightId >= 0) { + this.#id = highlightId; + this.#clipPathId = clipPathId; + this.parent.drawLayer.finalizeLine(highlightId, highlightOutlines); + this.#outlineId = this.parent.drawLayer.highlightOutline(this.#focusOutlines); + } else if (this.parent) { + this.parent.drawLayer.updateLine(this.#id, highlightOutlines); + this.parent.drawLayer.updateLine(this.#outlineId, this.#focusOutlines); + } + const { + x, + y, + width, + height, + lastPoint + } = highlightOutlines.box; + this.#lastPoint = lastPoint; + switch (this.rotation) { + case 0: + this.x = x; + this.y = y; + this.width = width; + this.height = height; + break; + case 90: + { + const [pageWidth, pageHeight] = this.parentDimensions; + this.x = y; + this.y = 1 - x; + this.width = width * pageHeight / pageWidth; + this.height = height * pageWidth / pageHeight; + break; + } + case 180: + this.x = 1 - x; + this.y = 1 - y; + this.width = width; + this.height = height; + break; + case 270: + { + const [pageWidth, pageHeight] = this.parentDimensions; + this.x = 1 - y; + this.y = x; + this.width = width * pageHeight / pageWidth; + this.height = height * pageWidth / pageHeight; + break; + } + } + } static initialize(l10n, uiManager) { AnnotationEditor.initialize(l10n, uiManager); HighlightEditor._defaultColor ||= uiManager.highlightColors?.values().next().value || "#fff066"; @@ -13942,6 +14396,9 @@ class HighlightEditor extends AnnotationEditor { case AnnotationEditorParamsType.HIGHLIGHT_DEFAULT_COLOR: HighlightEditor._defaultColor = value; break; + case AnnotationEditorParamsType.HIGHLIGHT_THICKNESS: + HighlightEditor._defaultThickness = value; + break; } } translateInPage(x, y) {} @@ -13953,33 +14410,50 @@ class HighlightEditor extends AnnotationEditor { case AnnotationEditorParamsType.HIGHLIGHT_COLOR: this.#updateColor(value); break; + case AnnotationEditorParamsType.HIGHLIGHT_THICKNESS: + this.#updateThickness(value); + break; } } static get defaultPropertiesToUpdate() { - return [[AnnotationEditorParamsType.HIGHLIGHT_DEFAULT_COLOR, HighlightEditor._defaultColor]]; + return [[AnnotationEditorParamsType.HIGHLIGHT_DEFAULT_COLOR, HighlightEditor._defaultColor], [AnnotationEditorParamsType.HIGHLIGHT_THICKNESS, HighlightEditor._defaultThickness]]; } get propertiesToUpdate() { - return [[AnnotationEditorParamsType.HIGHLIGHT_COLOR, this.color || HighlightEditor._defaultColor]]; + return [[AnnotationEditorParamsType.HIGHLIGHT_COLOR, this.color || HighlightEditor._defaultColor], [AnnotationEditorParamsType.HIGHLIGHT_THICKNESS, this.#thickness || HighlightEditor._defaultThickness]]; } #updateColor(color) { + const setColor = col => { + this.color = col; + this.parent?.drawLayer.changeColor(this.#id, col); + this.#colorPicker?.updateColor(col); + }; const savedColor = this.color; this.addCommands({ - cmd: () => { - this.color = color; - this.parent?.drawLayer.changeColor(this.#id, color); - this.#colorPicker?.updateColor(color); - }, - undo: () => { - this.color = savedColor; - this.parent?.drawLayer.changeColor(this.#id, savedColor); - this.#colorPicker?.updateColor(savedColor); - }, + cmd: setColor.bind(this, color), + undo: setColor.bind(this, savedColor), + post: this._uiManager.updateUI.bind(this._uiManager, this), mustExec: true, type: AnnotationEditorParamsType.HIGHLIGHT_COLOR, overwriteIfSameType: true, keepUndo: true }); } + #updateThickness(thickness) { + const savedThickness = this.#thickness; + const setThickness = th => { + this.#thickness = th; + this.#changeThickness(th); + }; + this.addCommands({ + cmd: setThickness.bind(this, thickness), + undo: setThickness.bind(this, savedThickness), + post: this._uiManager.updateUI.bind(this._uiManager, this), + mustExec: true, + type: AnnotationEditorParamsType.INK_THICKNESS, + overwriteIfSameType: true, + keepUndo: true + }); + } async addEditToolbar() { const toolbar = await super.addEditToolbar(); if (!toolbar) { @@ -14002,10 +14476,13 @@ class HighlightEditor extends AnnotationEditor { this.div.classList.toggle("disabled", false); } fixAndSetPosition() { - return super.fixAndSetPosition(0); + return super.fixAndSetPosition(this.#getRotation()); + } + getBaseTranslation() { + return [0, 0]; } getRect(tx, ty) { - return super.getRect(tx, ty, 0); + return super.getRect(tx, ty, this.#getRotation()); } onceAdded() { this.parent.addUndoableEditor(this); @@ -14041,6 +14518,17 @@ class HighlightEditor extends AnnotationEditor { this.select(); } } + #changeThickness(thickness) { + if (!this.#isFreeHighlight) { + return; + } + this.#createFreeOutlines({ + highlightOutlines: this.#highlightOutlines.getNewOutline(thickness / 2) + }); + this.fixAndSetPosition(); + const [parentWidth, parentHeight] = this.parentDimensions; + this.setDims(this.width * parentWidth, this.height * parentHeight); + } #cleanDrawLayer() { if (this.#id === null || !this.parent) { return; @@ -14058,10 +14546,10 @@ class HighlightEditor extends AnnotationEditor { id: this.#id, clipPathId: this.#clipPathId } = parent.drawLayer.highlight(this.#highlightOutlines, this.color, this.#opacity)); + this.#outlineId = parent.drawLayer.highlightOutline(this.#focusOutlines); if (this.#highlightDiv) { this.#highlightDiv.style.clipPath = this.#clipPathId; } - this.#outlineId = parent.drawLayer.highlightOutline(this.#focusOutlines); } static #rotateBbox({ x, @@ -14103,9 +14591,16 @@ class HighlightEditor extends AnnotationEditor { const { drawLayer } = this.parent; + let box; + if (this.#isFreeHighlight) { + angle = (angle - this.rotation + 360) % 360; + box = HighlightEditor.#rotateBbox(this.#highlightOutlines.box, angle); + } else { + box = HighlightEditor.#rotateBbox(this, angle); + } drawLayer.rotate(this.#id, angle); drawLayer.rotate(this.#outlineId, angle); - drawLayer.updateBox(this.#id, HighlightEditor.#rotateBbox(this, angle)); + drawLayer.updateBox(this.#id, box); drawLayer.updateBox(this.#outlineId, HighlightEditor.#rotateBbox(this.#focusOutlines.box, angle)); } render() { @@ -14113,6 +14608,9 @@ class HighlightEditor extends AnnotationEditor { return this.div; } const div = super.render(); + if (this.#isFreeHighlight) { + div.classList.add("free"); + } const highlightDiv = this.#highlightDiv = document.createElement("div"); div.append(highlightDiv); highlightDiv.className = "internal"; @@ -14138,7 +14636,13 @@ class HighlightEditor extends AnnotationEditor { super.unselect(); this.parent?.drawLayer.removeClass(this.#outlineId, "selected"); } + #getRotation() { + return this.#isFreeHighlight ? this.rotation : 0; + } #serializeBoxes(rect) { + if (this.#isFreeHighlight) { + return null; + } const [pageWidth, pageHeight] = this.pageDimensions; const boxes = this.#boxes; const quadPoints = new Array(boxes.length * 8); @@ -14161,7 +14665,70 @@ class HighlightEditor extends AnnotationEditor { return quadPoints; } #serializeOutlines(rect) { - return this.#highlightOutlines.serialize(rect, 0); + return this.#highlightOutlines.serialize(rect, this.#getRotation()); + } + static startHighlighting(parent, isLTR, { + target: textLayer, + x, + y + }) { + const { + x: layerX, + y: layerY, + width: parentWidth, + height: parentHeight + } = textLayer.getBoundingClientRect(); + const pointerMove = e => { + this.#highlightMove(parent, e); + }; + const pointerDownOptions = { + capture: true, + passive: false + }; + const pointerDown = e => { + e.preventDefault(); + e.stopPropagation(); + }; + const pointerUpCallback = e => { + textLayer.removeEventListener("pointermove", pointerMove); + window.removeEventListener("blur", pointerUpCallback); + window.removeEventListener("pointerup", pointerUpCallback); + window.removeEventListener("pointerdown", pointerDown, pointerDownOptions); + window.removeEventListener("contextmenu", noContextMenu); + this.#endHighlight(parent, e); + }; + window.addEventListener("blur", pointerUpCallback); + window.addEventListener("pointerup", pointerUpCallback); + window.addEventListener("pointerdown", pointerDown, pointerDownOptions); + window.addEventListener("contextmenu", noContextMenu); + textLayer.addEventListener("pointermove", pointerMove); + this._freeHighlight = new FreeOutliner({ + x, + y + }, [layerX, layerY, parentWidth, parentHeight], parent.scale, this._defaultThickness / 2, isLTR, 0.001); + ({ + id: this._freeHighlightId, + clipPathId: this._freeHighlightClipId + } = parent.drawLayer.highlight(this._freeHighlight, this._defaultColor, this._defaultOpacity, true)); + } + static #highlightMove(parent, event) { + if (this._freeHighlight.add(event)) { + parent.drawLayer.updatePath(this._freeHighlightId, this._freeHighlight); + } + } + static #endHighlight(parent, event) { + if (!this._freeHighlight.isEmpty()) { + parent.createAndAddNewEditor(event, false, { + highlightId: this._freeHighlightId, + highlightOutlines: this._freeHighlight.getOutlines(), + clipPathId: this._freeHighlightClipId + }); + } else { + parent.drawLayer.removeFreeHighlight(this._freeHighlightId); + } + this._freeHighlightId = -1; + this._freeHighlight = null; + this._freeHighlightClipId = ""; } static deserialize(data, parent, uiManager) { const editor = super.deserialize(data, parent, uiManager); @@ -14197,11 +14764,12 @@ class HighlightEditor extends AnnotationEditor { annotationType: AnnotationEditorType.HIGHLIGHT, color, opacity: this.#opacity, + thickness: this.#thickness, quadPoints: this.#serializeBoxes(rect), outlines: this.#serializeOutlines(rect), pageIndex: this.pageIndex, rect, - rotation: 0, + rotation: this.#getRotation(), structTreeParentId: this._structTreeParentId }; } @@ -14291,16 +14859,15 @@ class InkEditor extends AnnotationEditor { return [[AnnotationEditorParamsType.INK_THICKNESS, this.thickness || InkEditor._defaultThickness], [AnnotationEditorParamsType.INK_COLOR, this.color || InkEditor._defaultColor || AnnotationEditor._defaultLineColor], [AnnotationEditorParamsType.INK_OPACITY, Math.round(100 * (this.opacity ?? InkEditor._defaultOpacity))]]; } #updateThickness(thickness) { + const setThickness = th => { + this.thickness = th; + this.#fitToContent(); + }; const savedThickness = this.thickness; this.addCommands({ - cmd: () => { - this.thickness = thickness; - this.#fitToContent(); - }, - undo: () => { - this.thickness = savedThickness; - this.#fitToContent(); - }, + cmd: setThickness.bind(this, thickness), + undo: setThickness.bind(this, savedThickness), + post: this._uiManager.updateUI.bind(this._uiManager, this), mustExec: true, type: AnnotationEditorParamsType.INK_THICKNESS, overwriteIfSameType: true, @@ -14308,16 +14875,15 @@ class InkEditor extends AnnotationEditor { }); } #updateColor(color) { + const setColor = col => { + this.color = col; + this.#redraw(); + }; const savedColor = this.color; this.addCommands({ - cmd: () => { - this.color = color; - this.#redraw(); - }, - undo: () => { - this.color = savedColor; - this.#redraw(); - }, + cmd: setColor.bind(this, color), + undo: setColor.bind(this, savedColor), + post: this._uiManager.updateUI.bind(this._uiManager, this), mustExec: true, type: AnnotationEditorParamsType.INK_COLOR, overwriteIfSameType: true, @@ -14325,17 +14891,16 @@ class InkEditor extends AnnotationEditor { }); } #updateOpacity(opacity) { + const setOpacity = op => { + this.opacity = op; + this.#redraw(); + }; opacity /= 100; const savedOpacity = this.opacity; this.addCommands({ - cmd: () => { - this.opacity = opacity; - this.#redraw(); - }, - undo: () => { - this.opacity = savedOpacity; - this.#redraw(); - }, + cmd: setOpacity.bind(this, opacity), + undo: setOpacity.bind(this, savedOpacity), + post: this._uiManager.updateUI.bind(this._uiManager, this), mustExec: true, type: AnnotationEditorParamsType.INK_OPACITY, overwriteIfSameType: true, @@ -15420,6 +15985,7 @@ class AnnotationEditorLayer { #boundPointerup = this.pointerup.bind(this); #boundPointerUpAfterSelection = this.pointerUpAfterSelection.bind(this); #boundPointerdown = this.pointerdown.bind(this); + #boundTextLayerPointerDown = this.#textLayerPointerDown.bind(this); #editorFocusTimeoutId = null; #boundSelectionStart = this.selectionStart.bind(this); #editors = new Map(); @@ -15511,7 +16077,7 @@ class AnnotationEditorLayer { } } } - const editor = this.#createAndAddNewEditor({ + const editor = this.createAndAddNewEditor({ offsetX: 0, offsetY: 0 }, false); @@ -15606,11 +16172,28 @@ class AnnotationEditorLayer { enableTextSelection() { if (this.#textLayer?.div) { document.addEventListener("selectstart", this.#boundSelectionStart); + this.#textLayer.div.addEventListener("pointerdown", this.#boundTextLayerPointerDown); + this.#textLayer.div.classList.add("drawing"); } } disableTextSelection() { if (this.#textLayer?.div) { document.removeEventListener("selectstart", this.#boundSelectionStart); + this.#textLayer.div.removeEventListener("pointerdown", this.#boundTextLayerPointerDown); + this.#textLayer.div.classList.remove("drawing"); + } + } + #textLayerPointerDown(event) { + this.#uiManager.unselectAll(); + if (event.target === this.#textLayer.div) { + const { + isMac + } = util_FeatureTest.platform; + if (event.button !== 0 || event.ctrlKey && isMac) { + return; + } + HighlightEditor.startHighlighting(this, this.#uiManager.direction === "ltr", event); + event.preventDefault(); } } enableClick() { @@ -15757,7 +16340,7 @@ class AnnotationEditorLayer { deserialize(data) { return AnnotationEditorLayer.#editorTypes.get(data.annotationType ?? data.annotationEditorType)?.deserialize(data, this, this.#uiManager) || null; } - #createAndAddNewEditor(event, isCentered, data = {}) { + createAndAddNewEditor(event, isCentered, data = {}) { const id = this.getNextId(); const editor = this.#createNewEditor({ parent: this, @@ -15793,7 +16376,7 @@ class AnnotationEditorLayer { }; } addNewEditor() { - this.#createAndAddNewEditor(this.#getCenterPoint(), true); + this.createAndAddNewEditor(this.#getCenterPoint(), true); } setSelected(editor) { this.#uiManager.setSelected(editor); @@ -15879,7 +16462,7 @@ class AnnotationEditorLayer { boxes.push(rotator(x, y, width, height)); } if (boxes.length !== 0) { - this.#createAndAddNewEditor(event, false, { + this.createAndAddNewEditor(event, false, { boxes }); } @@ -15907,7 +16490,7 @@ class AnnotationEditorLayer { this.#uiManager.unselectAll(); return; } - this.#createAndAddNewEditor(event, false); + this.createAndAddNewEditor(event, false); } pointerdown(event) { if (this.#uiManager.getMode() === AnnotationEditorType.HIGHLIGHT) { @@ -16000,6 +16583,9 @@ class AnnotationEditorLayer { } = this.viewport.rawDims; return [pageWidth, pageHeight]; } + get scale() { + return this.#uiManager.viewParameters.realScale; + } } ;// CONCATENATED MODULE: ./src/display/draw_layer.js @@ -16009,6 +16595,7 @@ class DrawLayer { #parent = null; #id = 0; #mapping = new Map(); + #toUpdate = new Map(); constructor({ pageIndex }) { @@ -16033,11 +16620,11 @@ class DrawLayer { return shadow(this, "_svgFactory", new DOMSVGFactory()); } static #setBox(element, { - x, - y, - width, - height - }) { + x = 0, + y = 0, + width = 1, + height = 1 + } = {}) { const { style } = element; @@ -16064,10 +16651,13 @@ class DrawLayer { clipPathUse.classList.add("clip"); return clipPathId; } - highlight(outlines, color, opacity) { + highlight(outlines, color, opacity, isPathUpdatable = false) { const id = this.#id++; const root = this.#createSVG(outlines.box); root.classList.add("highlight"); + if (outlines.free) { + root.classList.add("free"); + } const defs = DrawLayer._svgFactory.createElement("defs"); root.append(defs); const path = DrawLayer._svgFactory.createElement("path"); @@ -16075,6 +16665,9 @@ class DrawLayer { const pathId = `path_p${this.pageIndex}_${id}`; path.setAttribute("id", pathId); path.setAttribute("d", outlines.toSVGPath()); + if (isPathUpdatable) { + this.#toUpdate.set(id, path); + } const clipPathId = this.#createClipPath(defs, pathId); const use = DrawLayer._svgFactory.createElement("use"); root.append(use); @@ -16109,6 +16702,26 @@ class DrawLayer { this.#mapping.set(id, root); return id; } + finalizeLine(id, line) { + const path = this.#toUpdate.get(id); + this.#toUpdate.delete(id); + this.updateBox(id, line.box); + path.setAttribute("d", line.toSVGPath()); + } + updateLine(id, line) { + const root = this.#mapping.get(id); + const defs = root.firstChild; + const path = defs.firstChild; + this.updateBox(id, line.box); + path.setAttribute("d", line.toSVGPath()); + } + removeFreeHighlight(id) { + this.remove(id); + this.#toUpdate.delete(id); + } + updatePath(id, line) { + this.#toUpdate.get(id).setAttribute("d", line.toSVGPath()); + } updateBox(id, box) { DrawLayer.#setBox(this.#mapping.get(id), box); } @@ -16156,8 +16769,8 @@ class DrawLayer { -const pdfjsVersion = '4.1.30'; -const pdfjsBuild = 'a22b5a4f0'; +const pdfjsVersion = "4.1.86"; +const pdfjsBuild = "bf9236009"; var __webpack_exports__AbortException = __webpack_exports__.AbortException; var __webpack_exports__AnnotationEditorLayer = __webpack_exports__.AnnotationEditorLayer; diff --git a/toolkit/components/pdfjs/content/build/pdf.sandbox.external.sys.mjs b/toolkit/components/pdfjs/content/build/pdf.sandbox.external.sys.mjs index 37647adcdae3..3dfe4eb2e1ca 100644 --- a/toolkit/components/pdfjs/content/build/pdf.sandbox.external.sys.mjs +++ b/toolkit/components/pdfjs/content/build/pdf.sandbox.external.sys.mjs @@ -14,128 +14,114 @@ */ export class SandboxSupportBase { - constructor(win) { - this.win = win; - this.timeoutIds = new Map(); - this.commFun = null; - } - destroy() { - this.commFun = null; - for (const id of this.timeoutIds.values()) { - this.win.clearTimeout(id); + constructor(win) { + this.win = win; + this.timeoutIds = new Map(); + this.commFun = null; } - this.timeoutIds = null; - } - exportValueToSandbox(val) { - throw new Error("Not implemented"); - } - importValueFromSandbox(val) { - throw new Error("Not implemented"); - } - createErrorForSandbox(errorMessage) { - throw new Error("Not implemented"); - } - callSandboxFunction(name, args) { - try { - args = this.exportValueToSandbox(args); - this.commFun(name, args); - } catch (e) { - this.win.console.error(e); + destroy() { + this.commFun = null; + for (const id of this.timeoutIds.values()) { + this.win.clearTimeout(id); + } + this.timeoutIds = null; } - } - createSandboxExternals() { - const externals = { - setTimeout: (callbackId, nMilliseconds) => { - if (typeof callbackId !== "number" || typeof nMilliseconds !== "number") { - return; + exportValueToSandbox(val) { + throw new Error("Not implemented"); + } + importValueFromSandbox(val) { + throw new Error("Not implemented"); + } + createErrorForSandbox(errorMessage) { + throw new Error("Not implemented"); + } + callSandboxFunction(name, args) { + try { + args = this.exportValueToSandbox(args); + this.commFun(name, args); + } catch (e) { + this.win.console.error(e); } - if (callbackId === 0) { - this.win.clearTimeout(this.timeoutIds.get(callbackId)); - } - const id = this.win.setTimeout(() => { - this.timeoutIds.delete(callbackId); - this.callSandboxFunction("timeoutCb", { - callbackId, - interval: false - }); - }, nMilliseconds); - this.timeoutIds.set(callbackId, id); - }, - clearTimeout: callbackId => { - this.win.clearTimeout(this.timeoutIds.get(callbackId)); - this.timeoutIds.delete(callbackId); - }, - setInterval: (callbackId, nMilliseconds) => { - if (typeof callbackId !== "number" || typeof nMilliseconds !== "number") { - return; - } - const id = this.win.setInterval(() => { - this.callSandboxFunction("timeoutCb", { - callbackId, - interval: true - }); - }, nMilliseconds); - this.timeoutIds.set(callbackId, id); - }, - clearInterval: callbackId => { - this.win.clearInterval(this.timeoutIds.get(callbackId)); - this.timeoutIds.delete(callbackId); - }, - alert: cMsg => { - if (typeof cMsg !== "string") { - return; - } - this.win.alert(cMsg); - }, - confirm: cMsg => { - if (typeof cMsg !== "string") { - return false; - } - return this.win.confirm(cMsg); - }, - prompt: (cQuestion, cDefault) => { - if (typeof cQuestion !== "string" || typeof cDefault !== "string") { - return null; - } - return this.win.prompt(cQuestion, cDefault); - }, - parseURL: cUrl => { - const url = new this.win.URL(cUrl); - const props = [ - "hash", - "host", - "hostname", - "href", - "origin", - "password", - "pathname", - "port", - "protocol", - "search", - "searchParams", - "username" - ]; - return Object.fromEntries(props.map(name => [ - name, - url[name].toString() - ])); - }, - send: data => { - if (!data) { - return; - } - const event = new this.win.CustomEvent("updatefromsandbox", { detail: this.importValueFromSandbox(data) }); - this.win.dispatchEvent(event); - } - }; - Object.setPrototypeOf(externals, null); - return (name, args) => { - try { - const result = externals[name](...args); - return this.exportValueToSandbox(result); - } catch (error) { - throw this.createErrorForSandbox(error?.toString() ?? ""); - } - }; - } + } + createSandboxExternals() { + const externals = { + setTimeout: (callbackId, nMilliseconds) => { + if (typeof callbackId !== "number" || typeof nMilliseconds !== "number") { + return; + } + if (callbackId === 0) { + this.win.clearTimeout(this.timeoutIds.get(callbackId)); + } + const id = this.win.setTimeout(() => { + this.timeoutIds.delete(callbackId); + this.callSandboxFunction("timeoutCb", { + callbackId, + interval: false + }); + }, nMilliseconds); + this.timeoutIds.set(callbackId, id); + }, + clearTimeout: callbackId => { + this.win.clearTimeout(this.timeoutIds.get(callbackId)); + this.timeoutIds.delete(callbackId); + }, + setInterval: (callbackId, nMilliseconds) => { + if (typeof callbackId !== "number" || typeof nMilliseconds !== "number") { + return; + } + const id = this.win.setInterval(() => { + this.callSandboxFunction("timeoutCb", { + callbackId, + interval: true + }); + }, nMilliseconds); + this.timeoutIds.set(callbackId, id); + }, + clearInterval: callbackId => { + this.win.clearInterval(this.timeoutIds.get(callbackId)); + this.timeoutIds.delete(callbackId); + }, + alert: cMsg => { + if (typeof cMsg !== "string") { + return; + } + this.win.alert(cMsg); + }, + confirm: cMsg => { + if (typeof cMsg !== "string") { + return false; + } + return this.win.confirm(cMsg); + }, + prompt: (cQuestion, cDefault) => { + if (typeof cQuestion !== "string" || typeof cDefault !== "string") { + return null; + } + return this.win.prompt(cQuestion, cDefault); + }, + parseURL: cUrl => { + const url = new this.win.URL(cUrl); + const props = ["hash", "host", "hostname", "href", "origin", "password", "pathname", "port", "protocol", "search", "searchParams", "username"]; + return Object.fromEntries(props.map(name => [name, url[name].toString()])); + }, + send: data => { + if (!data) { + return; + } + const event = new this.win.CustomEvent("updatefromsandbox", { + detail: this.importValueFromSandbox(data) + }); + this.win.dispatchEvent(event); + } + }; + Object.setPrototypeOf(externals, null); + return (name, args) => { + try { + const result = externals[name](...args); + return this.exportValueToSandbox(result); + } catch (error) { + throw this.createErrorForSandbox(error?.toString() ?? ""); + } + }; + } } \ No newline at end of file diff --git a/toolkit/components/pdfjs/content/build/pdf.scripting.mjs b/toolkit/components/pdfjs/content/build/pdf.scripting.mjs index a891466706e9..a5e2a4f79ecd 100644 --- a/toolkit/components/pdfjs/content/build/pdf.scripting.mjs +++ b/toolkit/components/pdfjs/content/build/pdf.scripting.mjs @@ -1074,9 +1074,6 @@ class AForm { } AFNumber_Format(nDec, sepStyle, negStyle, currStyle, strCurrency, bCurrencyPrepend) { const event = globalThis.event; - if (!event.value) { - return; - } let value = this.AFMakeNumber(event.value); if (value === null) { event.value = ""; @@ -1686,23 +1683,27 @@ class EventDispatcher { } event.value = null; const target = this._objects[targetId]; - let savedValue = target.obj.value; + let savedValue = target.obj._getValue(); this.runActions(source, target, event, "Calculate"); if (!event.rc) { continue; } if (event.value !== null) { target.obj.value = event.value; + } else { + event.value = target.obj._getValue(); } - event.value = target.obj.value; this.runActions(target, target, event, "Validate"); if (!event.rc) { - if (target.obj.value !== savedValue) { + if (target.obj._getValue() !== savedValue) { target.wrapped.value = savedValue; } continue; } - savedValue = event.value = target.obj.value; + if (event.value === null) { + event.value = target.obj._getValue(); + } + savedValue = target.obj._getValue(); let formattedValue = null; if (this.runActions(target, target, event, "Format")) { formattedValue = event.value?.toString?.(); @@ -3486,66 +3487,26 @@ class Util extends PDFObject { return this.printd("m/d/yy h:MM:ss tt", oDate); } const handlers = { - mmmm: data => { - return this._months[data.month]; - }, - mmm: data => { - return this._months[data.month].substring(0, 3); - }, - mm: data => { - return (data.month + 1).toString().padStart(2, "0"); - }, - m: data => { - return (data.month + 1).toString(); - }, - dddd: data => { - return this._days[data.dayOfWeek]; - }, - ddd: data => { - return this._days[data.dayOfWeek].substring(0, 3); - }, - dd: data => { - return data.day.toString().padStart(2, "0"); - }, - d: data => { - return data.day.toString(); - }, - yyyy: data => { - return data.year.toString(); - }, - yy: data => { - return (data.year % 100).toString().padStart(2, "0"); - }, - HH: data => { - return data.hours.toString().padStart(2, "0"); - }, - H: data => { - return data.hours.toString(); - }, - hh: data => { - return (1 + (data.hours + 11) % 12).toString().padStart(2, "0"); - }, - h: data => { - return (1 + (data.hours + 11) % 12).toString(); - }, - MM: data => { - return data.minutes.toString().padStart(2, "0"); - }, - M: data => { - return data.minutes.toString(); - }, - ss: data => { - return data.seconds.toString().padStart(2, "0"); - }, - s: data => { - return data.seconds.toString(); - }, - tt: data => { - return data.hours < 12 ? "am" : "pm"; - }, - t: data => { - return data.hours < 12 ? "a" : "p"; - } + mmmm: data => this._months[data.month], + mmm: data => this._months[data.month].substring(0, 3), + mm: data => (data.month + 1).toString().padStart(2, "0"), + m: data => (data.month + 1).toString(), + dddd: data => this._days[data.dayOfWeek], + ddd: data => this._days[data.dayOfWeek].substring(0, 3), + dd: data => data.day.toString().padStart(2, "0"), + d: data => data.day.toString(), + yyyy: data => data.year.toString(), + yy: data => (data.year % 100).toString().padStart(2, "0"), + HH: data => data.hours.toString().padStart(2, "0"), + H: data => data.hours.toString(), + hh: data => (1 + (data.hours + 11) % 12).toString().padStart(2, "0"), + h: data => (1 + (data.hours + 11) % 12).toString(), + MM: data => data.minutes.toString().padStart(2, "0"), + M: data => data.minutes.toString(), + ss: data => data.seconds.toString().padStart(2, "0"), + s: data => data.seconds.toString(), + tt: data => data.hours < 12 ? "am" : "pm", + t: data => data.hours < 12 ? "a" : "p" }; const data = { year: oDate.getFullYear(), @@ -3996,8 +3957,8 @@ function initSandbox(params) { ;// CONCATENATED MODULE: ./src/pdf.scripting.js -const pdfjsVersion = '4.1.30'; -const pdfjsBuild = 'a22b5a4f0'; +const pdfjsVersion = "4.1.86"; +const pdfjsBuild = "bf9236009"; globalThis.pdfjsScripting = { initSandbox: initSandbox }; diff --git a/toolkit/components/pdfjs/content/build/pdf.worker.mjs b/toolkit/components/pdfjs/content/build/pdf.worker.mjs index 40d4b2d8b056..ffd9e9d873ad 100644 --- a/toolkit/components/pdfjs/content/build/pdf.worker.mjs +++ b/toolkit/components/pdfjs/content/build/pdf.worker.mjs @@ -92,7 +92,8 @@ const AnnotationEditorParamsType = { INK_THICKNESS: 22, INK_OPACITY: 23, HIGHLIGHT_COLOR: 31, - HIGHLIGHT_DEFAULT_COLOR: 32 + HIGHLIGHT_DEFAULT_COLOR: 32, + HIGHLIGHT_THICKNESS: 33 }; const PermissionFlag = { PRINT: 0x04, @@ -530,43 +531,43 @@ class Util { if (transform[0]) { if (transform[0] < 0) { temp = minMax[0]; - minMax[0] = minMax[1]; - minMax[1] = temp; + minMax[0] = minMax[2]; + minMax[2] = temp; } minMax[0] *= transform[0]; - minMax[1] *= transform[0]; + minMax[2] *= transform[0]; if (transform[3] < 0) { - temp = minMax[2]; - minMax[2] = minMax[3]; + temp = minMax[1]; + minMax[1] = minMax[3]; minMax[3] = temp; } - minMax[2] *= transform[3]; + minMax[1] *= transform[3]; minMax[3] *= transform[3]; } else { temp = minMax[0]; - minMax[0] = minMax[2]; - minMax[2] = temp; - temp = minMax[1]; - minMax[1] = minMax[3]; + minMax[0] = minMax[1]; + minMax[1] = temp; + temp = minMax[2]; + minMax[2] = minMax[3]; minMax[3] = temp; if (transform[1] < 0) { - temp = minMax[2]; - minMax[2] = minMax[3]; + temp = minMax[1]; + minMax[1] = minMax[3]; minMax[3] = temp; } - minMax[2] *= transform[1]; + minMax[1] *= transform[1]; minMax[3] *= transform[1]; if (transform[2] < 0) { temp = minMax[0]; - minMax[0] = minMax[1]; - minMax[1] = temp; + minMax[0] = minMax[2]; + minMax[2] = temp; } minMax[0] *= transform[2]; - minMax[1] *= transform[2]; + minMax[2] *= transform[2]; } minMax[0] += transform[4]; - minMax[1] += transform[4]; - minMax[2] += transform[5]; + minMax[1] += transform[5]; + minMax[2] += transform[4]; minMax[3] += transform[5]; } static transform(m1, m2) { @@ -631,59 +632,48 @@ class Util { } return [xLow, yLow, xHigh, yHigh]; } - static bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3) { - const tvalues = [], - bounds = [[], []]; - let a, b, c, t, t1, t2, b2ac, sqrtb2ac; - for (let i = 0; i < 2; ++i) { - if (i === 0) { - b = 6 * x0 - 12 * x1 + 6 * x2; - a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3; - c = 3 * x1 - 3 * x0; - } else { - b = 6 * y0 - 12 * y1 + 6 * y2; - a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3; - c = 3 * y1 - 3 * y0; - } - if (Math.abs(a) < 1e-12) { - if (Math.abs(b) < 1e-12) { - continue; - } - t = -c / b; - if (0 < t && t < 1) { - tvalues.push(t); - } - continue; - } - b2ac = b * b - 4 * c * a; - sqrtb2ac = Math.sqrt(b2ac); - if (b2ac < 0) { - continue; - } - t1 = (-b + sqrtb2ac) / (2 * a); - if (0 < t1 && t1 < 1) { - tvalues.push(t1); - } - t2 = (-b - sqrtb2ac) / (2 * a); - if (0 < t2 && t2 < 1) { - tvalues.push(t2); - } + static #getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, t, minMax) { + if (t <= 0 || t >= 1) { + return; } - let j = tvalues.length, - mt; - const jlen = j; - while (j--) { - t = tvalues[j]; - mt = 1 - t; - bounds[0][j] = mt * mt * mt * x0 + 3 * mt * mt * t * x1 + 3 * mt * t * t * x2 + t * t * t * x3; - bounds[1][j] = mt * mt * mt * y0 + 3 * mt * mt * t * y1 + 3 * mt * t * t * y2 + t * t * t * y3; + const mt = 1 - t; + const tt = t * t; + const ttt = tt * t; + const x = mt * (mt * (mt * x0 + 3 * t * x1) + 3 * tt * x2) + ttt * x3; + const y = mt * (mt * (mt * y0 + 3 * t * y1) + 3 * tt * y2) + ttt * y3; + minMax[0] = Math.min(minMax[0], x); + minMax[1] = Math.min(minMax[1], y); + minMax[2] = Math.max(minMax[2], x); + minMax[3] = Math.max(minMax[3], y); + } + static #getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, a, b, c, minMax) { + if (Math.abs(a) < 1e-12) { + if (Math.abs(b) >= 1e-12) { + this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, -c / b, minMax); + } + return; } - bounds[0][jlen] = x0; - bounds[1][jlen] = y0; - bounds[0][jlen + 1] = x3; - bounds[1][jlen + 1] = y3; - bounds[0].length = bounds[1].length = jlen + 2; - return [Math.min(...bounds[0]), Math.min(...bounds[1]), Math.max(...bounds[0]), Math.max(...bounds[1])]; + const delta = b ** 2 - 4 * c * a; + if (delta < 0) { + return; + } + const sqrtDelta = Math.sqrt(delta); + const a2 = 2 * a; + this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, (-b + sqrtDelta) / a2, minMax); + this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, (-b - sqrtDelta) / a2, minMax); + } + static bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3, minMax) { + if (minMax) { + minMax[0] = Math.min(minMax[0], x0, x3); + minMax[1] = Math.min(minMax[1], y0, y3); + minMax[2] = Math.max(minMax[2], x0, x3); + minMax[3] = Math.max(minMax[3], y0, y3); + } else { + minMax = [Math.min(x0, x3), Math.min(y0, y3), Math.max(x0, x3), Math.max(y0, y3)]; + } + this.#getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, 3 * (-x0 + 3 * (x1 - x2) + x3), 6 * (x0 - 2 * x1 + x2), 3 * (x1 - x0), minMax); + this.#getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, 3 * (-y0 + 3 * (y1 - y2) + y3), 6 * (y0 - 2 * y1 + y2), 3 * (y1 - y0), minMax); + return minMax; } } const PDFStringTranslateTable = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2d8, 0x2c7, 0x2c6, 0x2d9, 0x2dd, 0x2db, 0x2da, 0x2dc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x192, 0x2044, 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018, 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x141, 0x152, 0x160, 0x178, 0x17d, 0x131, 0x142, 0x153, 0x161, 0x17e, 0, 0x20ac]; @@ -737,9 +727,6 @@ function stringToUTF8String(str) { function utf8StringToString(str) { return unescape(encodeURIComponent(str)); } -function isArrayBuffer(v) { - return typeof v === "object" && v?.byteLength !== undefined; -} function isArrayEqual(arr1, arr2) { if (arr1.length !== arr2.length) { return false; @@ -780,9 +767,7 @@ function normalizeUnicode(str) { NormalizeRegex = /([\u00a0\u00b5\u037e\u0eb3\u2000-\u200a\u202f\u2126\ufb00-\ufb04\ufb06\ufb20-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufba1\ufba4-\ufba9\ufbae-\ufbb1\ufbd3-\ufbdc\ufbde-\ufbe7\ufbea-\ufbf8\ufbfc-\ufbfd\ufc00-\ufc5d\ufc64-\ufcf1\ufcf5-\ufd3d\ufd88\ufdf4\ufdfa-\ufdfb\ufe71\ufe77\ufe79\ufe7b\ufe7d]+)|(\ufb05+)/gu; NormalizationMap = new Map([["ſt", "ſt"]]); } - return str.replaceAll(NormalizeRegex, (_, p1, p2) => { - return p1 ? p1.normalize("NFKC") : NormalizationMap.get(p2); - }); + return str.replaceAll(NormalizeRegex, (_, p1, p2) => p1 ? p1.normalize("NFKC") : NormalizationMap.get(p2)); } function getUuid() { return crypto.randomUUID(); @@ -1366,6 +1351,15 @@ const XMLEntities = { 0x22: """, 0x27: "'" }; +function* codePointIter(str) { + for (let i = 0, ii = str.length; i < ii; i++) { + const char = str.codePointAt(i); + if (char > 0xd7ff && (char < 0xe000 || char > 0xfffd)) { + i++; + } + yield char; + } +} function encodeToXmlString(str) { const buffer = []; let start = 0; @@ -11290,9 +11284,7 @@ async function createBuiltInCMap(name, fetchBuiltInCMap) { } = await fetchBuiltInCMap(name); const cMap = new CMap(true); if (compressionType === CMapCompressionType.BINARY) { - return new BinaryCMapReader().process(cMapData, cMap, useCMap => { - return extendCMap(cMap, fetchBuiltInCMap, useCMap); - }); + return new BinaryCMapReader().process(cMapData, cMap, useCMap => extendCMap(cMap, fetchBuiltInCMap, useCMap)); } if (compressionType === CMapCompressionType.NONE) { const lexer = new Lexer(new Stream(cMapData)); @@ -25279,15 +25271,11 @@ class Font { endOffset: 0 }); } - locaEntries.sort((a, b) => { - return a.offset - b.offset; - }); + locaEntries.sort((a, b) => a.offset - b.offset); for (i = 0; i < numGlyphs; i++) { locaEntries[i].endOffset = locaEntries[i + 1].offset; } - locaEntries.sort((a, b) => { - return a.index - b.index; - }); + locaEntries.sort((a, b) => a.index - b.index); for (i = 0; i < numGlyphs; i++) { const { offset, @@ -29590,7 +29578,6 @@ class ImageResizer { ImageResizer._goodSquareLength = MIN_IMAGE_DIM; ;// CONCATENATED MODULE: ./src/shared/murmurhash3.js - const SEED = 0xc3d2e1f0; const MASK_HIGH = 0xffff0000; const MASK_LOW = 0xffff; @@ -29613,11 +29600,11 @@ class MurmurHash3_64 { data[length++] = code & 0xff; } } - } else if (isArrayBuffer(input)) { + } else if (ArrayBuffer.isView(input)) { data = input.slice(); length = data.byteLength; } else { - throw new Error("Wrong data format in MurmurHash3_64_update. " + "Input must be a string or array."); + throw new Error("Invalid data format, must be a string or TypedArray."); } const blockCounts = length >> 2; const tailLength = length - blockCounts * 4; @@ -31312,21 +31299,20 @@ class PartialEvaluator { } const args = group ? [matrix, null] : [matrix, bbox]; operatorList.addOp(OPS.paintFormXObjectBegin, args); - return this.getOperatorList({ + await this.getOperatorList({ stream: xobj, task, resources: dict.get("Resources") || resources, operatorList, initialState - }).then(function () { - operatorList.addOp(OPS.paintFormXObjectEnd, []); - if (group) { - operatorList.addOp(OPS.endGroup, [groupOptions]); - } - if (optionalContent !== undefined) { - operatorList.addOp(OPS.endMarkedContent, []); - } }); + operatorList.addOp(OPS.paintFormXObjectEnd, []); + if (group) { + operatorList.addOp(OPS.endGroup, [groupOptions]); + } + if (optionalContent !== undefined) { + operatorList.addOp(OPS.endMarkedContent, []); + } } _sendImgData(objId, imgData, cacheGlobally = false) { const transfers = imgData ? [imgData.bitmap || imgData.data.buffer] : null; @@ -31624,28 +31610,25 @@ class PartialEvaluator { throw reason; }); } - handleSetFont(resources, fontArgs, fontRef, operatorList, task, state, fallbackFontDict = null, cssFontInfo = null) { + async handleSetFont(resources, fontArgs, fontRef, operatorList, task, state, fallbackFontDict = null, cssFontInfo = null) { const fontName = fontArgs?.[0] instanceof Name ? fontArgs[0].name : null; - return this.loadFont(fontName, fontRef, resources, fallbackFontDict, cssFontInfo).then(translated => { - if (!translated.font.isType3Font) { - return translated; - } - return translated.loadType3Data(this, resources, task).then(function () { + let translated = await this.loadFont(fontName, fontRef, resources, fallbackFontDict, cssFontInfo); + if (translated.font.isType3Font) { + try { + await translated.loadType3Data(this, resources, task); operatorList.addDependencies(translated.type3Dependencies); - return translated; - }).catch(reason => { - return new TranslatedFont({ + } catch (reason) { + translated = new TranslatedFont({ loadedName: "g_font_error", font: new ErrorFont(`Type3 font load error: ${reason}`), dict: translated.font, evaluatorOptions: this.options }); - }); - }).then(translated => { - state.font = translated.font; - translated.send(this.handler); - return translated.loadedName; - }); + } + } + state.font = translated.font; + translated.send(this.handler); + return translated.loadedName; } handleText(chars, state) { const font = state.font; @@ -31701,12 +31684,10 @@ class PartialEvaluator { break; case "Font": isSimpleGState = false; - promise = promise.then(() => { - return this.handleSetFont(resources, null, value[0], operatorList, task, stateManager.state).then(function (loadedName) { - operatorList.addDependency(loadedName); - gStateObj.push([key, [loadedName, value[1]]]); - }); - }); + promise = promise.then(() => this.handleSetFont(resources, null, value[0], operatorList, task, stateManager.state).then(function (loadedName) { + operatorList.addDependency(loadedName); + gStateObj.push([key, [loadedName, value[1]]]); + })); break; case "BM": gStateObj.push([key, normalizeBlendMode(value)]); @@ -31718,9 +31699,7 @@ class PartialEvaluator { } if (value instanceof Dict) { isSimpleGState = false; - promise = promise.then(() => { - return this.handleSMask(value, resources, operatorList, task, stateManager, localColorSpaceCache); - }); + promise = promise.then(() => this.handleSMask(value, resources, operatorList, task, stateManager, localColorSpaceCache)); gStateObj.push([key, true]); } else { warn("Unsupported SMask type"); @@ -31750,14 +31729,13 @@ class PartialEvaluator { break; } } - return promise.then(function () { - if (gStateObj.length > 0) { - operatorList.addOp(OPS.setGState, [gStateObj]); - } - if (isSimpleGState) { - localGStateCache.set(cacheKey, gStateRef, gStateObj); - } - }); + await promise; + if (gStateObj.length > 0) { + operatorList.addOp(OPS.setGState, [gStateObj]); + } + if (isSimpleGState) { + localGStateCache.set(cacheKey, gStateRef, gStateObj); + } } loadFont(fontName, font, resources, fallbackFontDict = null, cssFontInfo = null) { const errorFont = async () => { @@ -31875,14 +31853,14 @@ class PartialEvaluator { case OPS.rectangle: const x = args[0] + args[2]; const y = args[1] + args[3]; - minMax = [Math.min(args[0], x), Math.max(args[0], x), Math.min(args[1], y), Math.max(args[1], y)]; + minMax = [Math.min(args[0], x), Math.min(args[1], y), Math.max(args[0], x), Math.max(args[1], y)]; break; case OPS.moveTo: case OPS.lineTo: - minMax = [args[0], args[0], args[1], args[1]]; + minMax = [args[0], args[1], args[0], args[1]]; break; default: - minMax = [Infinity, -Infinity, Infinity, -Infinity]; + minMax = [Infinity, Infinity, -Infinity, -Infinity]; break; } operatorList.addOp(OPS.constructPath, [[fn], args, minMax]); @@ -31899,15 +31877,15 @@ class PartialEvaluator { const x = args[0] + args[2]; const y = args[1] + args[3]; minMax[0] = Math.min(minMax[0], args[0], x); - minMax[1] = Math.max(minMax[1], args[0], x); - minMax[2] = Math.min(minMax[2], args[1], y); + minMax[1] = Math.min(minMax[1], args[1], y); + minMax[2] = Math.max(minMax[2], args[0], x); minMax[3] = Math.max(minMax[3], args[1], y); break; case OPS.moveTo: case OPS.lineTo: minMax[0] = Math.min(minMax[0], args[0]); - minMax[1] = Math.max(minMax[1], args[0]); - minMax[2] = Math.min(minMax[2], args[1]); + minMax[1] = Math.min(minMax[1], args[1]); + minMax[2] = Math.max(minMax[2], args[0]); minMax[3] = Math.max(minMax[3], args[1]); break; } @@ -32701,19 +32679,16 @@ class PartialEvaluator { hasEOL: textChunk.hasEOL }; } - function handleSetFont(fontName, fontRef) { - return self.loadFont(fontName, fontRef, resources).then(function (translated) { - if (!translated.font.isType3Font) { - return translated; - } - return translated.loadType3Data(self, resources, task).catch(function () {}).then(function () { - return translated; - }); - }).then(function (translated) { - textState.loadedName = translated.loadedName; - textState.font = translated.font; - textState.fontMatrix = translated.font.fontMatrix || FONT_IDENTITY_MATRIX; - }); + async function handleSetFont(fontName, fontRef) { + const translated = await self.loadFont(fontName, fontRef, resources); + if (translated.font.isType3Font) { + try { + await translated.loadType3Data(self, resources, task); + } catch {} + } + textState.loadedName = translated.loadedName; + textState.font = translated.font; + textState.fontMatrix = translated.font.fontMatrix || FONT_IDENTITY_MATRIX; } function applyInverseRotation(x, y, matrix) { const scale = Math.hypot(matrix[0], matrix[1]); @@ -33334,10 +33309,10 @@ class PartialEvaluator { throw reason; }); } - extractDataStructures(dict, baseDict, properties) { + async extractDataStructures(dict, properties) { const xref = this.xref; let cidToGidBytes; - const toUnicodePromise = this.readToUnicode(properties.toUnicode || dict.get("ToUnicode") || baseDict.get("ToUnicode")); + const toUnicodePromise = this.readToUnicode(properties.toUnicode); if (properties.composite) { const cidSystemInfo = dict.get("CIDSystemInfo"); if (cidSystemInfo instanceof Dict) { @@ -33426,16 +33401,13 @@ class PartialEvaluator { properties.baseEncodingName = baseEncodingName; properties.hasEncoding = !!baseEncodingName || differences.length > 0; properties.dict = dict; - return toUnicodePromise.then(readToUnicode => { - properties.toUnicode = readToUnicode; - return this.buildToUnicode(properties); - }).then(builtToUnicode => { - properties.toUnicode = builtToUnicode; - if (cidToGidBytes) { - properties.cidToGidMap = this.readCidToGidMap(cidToGidBytes, builtToUnicode); - } - return properties; - }); + properties.toUnicode = await toUnicodePromise; + const builtToUnicode = await this.buildToUnicode(properties); + properties.toUnicode = builtToUnicode; + if (cidToGidBytes) { + properties.cidToGidMap = this.readCidToGidMap(cidToGidBytes, builtToUnicode); + } + return properties; } _simpleFontToUnicode(properties, forceGlyphs = false) { assert(!properties.composite, "Must be a simple font."); @@ -33557,27 +33529,28 @@ class PartialEvaluator { } return new IdentityToUnicodeMap(properties.firstChar, properties.lastChar); } - readToUnicode(cmapObj) { + async readToUnicode(cmapObj) { if (!cmapObj) { - return Promise.resolve(null); + return null; } if (cmapObj instanceof Name) { - return CMapFactory.create({ + const cmap = await CMapFactory.create({ encoding: cmapObj, fetchBuiltInCMap: this._fetchBuiltInCMapBound, useCMap: null - }).then(function (cmap) { - if (cmap instanceof IdentityCMap) { - return new IdentityToUnicodeMap(0, 0xffff); - } - return new ToUnicodeMap(cmap.getMap()); }); - } else if (cmapObj instanceof BaseStream) { - return CMapFactory.create({ - encoding: cmapObj, - fetchBuiltInCMap: this._fetchBuiltInCMapBound, - useCMap: null - }).then(function (cmap) { + if (cmap instanceof IdentityCMap) { + return new IdentityToUnicodeMap(0, 0xffff); + } + return new ToUnicodeMap(cmap.getMap()); + } + if (cmapObj instanceof BaseStream) { + try { + const cmap = await CMapFactory.create({ + encoding: cmapObj, + fetchBuiltInCMap: this._fetchBuiltInCMapBound, + useCMap: null + }); if (cmap instanceof IdentityCMap) { return new IdentityToUnicodeMap(0, 0xffff); } @@ -33601,7 +33574,7 @@ class PartialEvaluator { map[charCode] = String.fromCodePoint(...str); }); return new ToUnicodeMap(map); - }, reason => { + } catch (reason) { if (reason instanceof AbortException) { return null; } @@ -33610,9 +33583,9 @@ class PartialEvaluator { return null; } throw reason; - }); + } } - return Promise.resolve(null); + return null; } readCidToGidMap(glyphsData, toUnicode) { const result = []; @@ -33767,7 +33740,7 @@ class PartialEvaluator { throw new FormatError("invalid font Subtype"); } let composite = false; - let hash, toUnicode; + let hash; if (type.name === "Type0") { const df = dict.get("DescendantFonts"); if (!df) { @@ -33786,6 +33759,7 @@ class PartialEvaluator { const firstChar = dict.get("FirstChar") || 0, lastChar = dict.get("LastChar") || (composite ? 0xffff : 0xff); const descriptor = dict.get("FontDescriptor"); + const toUnicode = dict.get("ToUnicode") || baseDict.get("ToUnicode"); if (descriptor) { hash = new MurmurHash3_64(); const encoding = baseDict.getRaw("Encoding"); @@ -33815,7 +33789,6 @@ class PartialEvaluator { } } hash.update(`${firstChar}-${lastChar}`); - toUnicode = dict.get("ToUnicode") || baseDict.get("ToUnicode"); if (toUnicode instanceof BaseStream) { const stream = toUnicode.str || toUnicode; const uint8array = stream.buffer ? new Uint8Array(stream.buffer.buffer, 0, stream.bufferLength) : new Uint8Array(stream.bytes.buffer, stream.start, stream.end - stream.start); @@ -33887,7 +33860,6 @@ class PartialEvaluator { cssFontInfo }) { const isType3Font = type === "Type3"; - let properties; if (!descriptor) { if (isType3Font) { descriptor = new Dict(null); @@ -33902,7 +33874,7 @@ class PartialEvaluator { const metrics = this.getBaseFontMetrics(baseFontName); const fontNameWoStyle = baseFontName.split("-")[0]; const flags = (this.isSerifFont(fontNameWoStyle) ? FontFlags.Serif : 0) | (metrics.monospace ? FontFlags.FixedPitch : 0) | (getSymbolsFonts()[fontNameWoStyle] ? FontFlags.Symbolic : FontFlags.Nonsymbolic); - properties = { + const properties = { type, name: baseFontName, loadedName: baseDict.loadedName, @@ -33929,19 +33901,18 @@ class PartialEvaluator { if (!properties.isInternalFont && this.options.useSystemFonts) { properties.systemFontInfo = getFontSubstitution(this.systemFontCache, this.idFactory, this.options.standardFontDataUrl, baseFontName, standardFontName); } - return this.extractDataStructures(dict, dict, properties).then(newProperties => { - if (widths) { - const glyphWidths = []; - let j = firstChar; - for (const width of widths) { - glyphWidths[j++] = this.xref.fetchIfRef(width); - } - newProperties.widths = glyphWidths; - } else { - newProperties.widths = this.buildCharCodeToWidth(metrics.widths, newProperties); + const newProperties = await this.extractDataStructures(dict, properties); + if (widths) { + const glyphWidths = []; + let j = firstChar; + for (const width of widths) { + glyphWidths[j++] = this.xref.fetchIfRef(width); } - return new Font(baseFontName, file, newProperties); - }); + newProperties.widths = glyphWidths; + } else { + newProperties.widths = this.buildCharCodeToWidth(metrics.widths, newProperties); + } + return new Font(baseFontName, file, newProperties); } } let fontName = descriptor.get("FontName"); @@ -34008,7 +33979,7 @@ class PartialEvaluator { systemFontInfo = getFontSubstitution(this.systemFontCache, this.idFactory, this.options.standardFontDataUrl, fontName.name, standardFontName); } } - properties = { + const properties = { type, name: fontName.name, subtype, @@ -34049,10 +34020,9 @@ class PartialEvaluator { properties.cMap = cMap; properties.vertical = properties.cMap.vertical; } - return this.extractDataStructures(dict, baseDict, properties).then(newProperties => { - this.extractWidths(dict, descriptor, newProperties); - return new Font(fontName.name, fontFile, newProperties); - }); + const newProperties = await this.extractDataStructures(dict, properties); + this.extractWidths(dict, descriptor, newProperties); + return new Font(fontName.name, fontFile, newProperties); } static buildFontPaths(font, glyphs, handler, evaluatorOptions) { function buildPath(fontChar) { @@ -34332,7 +34302,7 @@ class EvalState { } class EvaluatorPreprocessor { static get opMap() { - return shadow(this, "opMap", { + return shadow(this, "opMap", Object.assign(Object.create(null), { w: { id: OPS.setLineWidth, numArgs: 1, @@ -34708,7 +34678,7 @@ class EvaluatorPreprocessor { nu: null, nul: null, null: null - }); + })); } static MAX_INVALID_PATH_OPS = 10; constructor(stream, xref, stateManager = new StateManager()) { @@ -35008,31 +34978,6 @@ class FakeUnicodeFont { } this.fontName = Name.get(`InvalidPDFjsFont_${fontFamily}_${FakeUnicodeFont._fontNameId++}`); } - get toUnicodeRef() { - if (!FakeUnicodeFont._toUnicodeRef) { - const toUnicode = `/CIDInit /ProcSet findresource begin -12 dict begin -begincmap -/CIDSystemInfo -<< /Registry (Adobe) -/Ordering (UCS) /Supplement 0 >> def -/CMapName /Adobe-Identity-UCS def -/CMapType 2 def -1 begincodespacerange -<0000> -endcodespacerange -1 beginbfrange -<0000> <0000> -endbfrange -endcmap CMapName currentdict /CMap defineresource pop end end`; - const toUnicodeStream = FakeUnicodeFont.toUnicodeStream = new StringStream(toUnicode); - const toUnicodeDict = new Dict(this.xref); - toUnicodeStream.dict = toUnicodeDict; - toUnicodeDict.set("Length", toUnicode.length); - FakeUnicodeFont._toUnicodeRef = this.xref.getNewPersistentRef(toUnicodeStream); - } - return FakeUnicodeFont._toUnicodeRef; - } get fontDescriptorRef() { if (!FakeUnicodeFont._fontDescriptorRef) { const fontDescriptor = new Dict(this.xref); @@ -35093,7 +35038,7 @@ endcmap CMapName currentdict /CMap defineresource pop end end`; baseFont.set("Subtype", Name.get("Type0")); baseFont.set("Encoding", Name.get("Identity-H")); baseFont.set("DescendantFonts", [this.descendantFontRef]); - baseFont.set("ToUnicode", this.toUnicodeRef); + baseFont.set("ToUnicode", Name.get("Identity-H")); return this.xref.getNewPersistentRef(baseFont); } get resources() { @@ -35148,8 +35093,8 @@ endcmap CMapName currentdict /CMap defineresource pop end end`; lines.push(line); const lineWidth = ctx.measureText(line).width; maxWidth = Math.max(maxWidth, lineWidth); - for (const char of line.split("")) { - const code = char.charCodeAt(0); + for (const code of codePointIter(line)) { + const char = String.fromCodePoint(code); let width = this.widths.get(code); if (width === undefined) { const metrics = ctx.measureText(char); @@ -37255,7 +37200,7 @@ async function writeObject(ref, obj, buffer, { await writeDict(obj, buffer, transform); } else if (obj instanceof BaseStream) { await writeStream(obj, buffer, transform); - } else if (Array.isArray(obj)) { + } else if (Array.isArray(obj) || ArrayBuffer.isView(obj)) { await writeArray(obj, buffer, transform); } buffer.push("\nendobj\n"); @@ -37330,7 +37275,7 @@ async function writeValue(value, buffer, transform) { buffer.push(`/${escapePDFName(value.name)}`); } else if (value instanceof Ref) { buffer.push(`${value.num} ${value.gen} R`); - } else if (Array.isArray(value)) { + } else if (Array.isArray(value) || ArrayBuffer.isView(value)) { await writeArray(value, buffer, transform); } else if (typeof value === "string") { if (transform) { @@ -37524,9 +37469,7 @@ async function incrementalUpdate({ ref: refForXrefTable, data: "" }); - newRefs = newRefs.sort((a, b) => { - return a.ref.num - b.ref.num; - }); + newRefs = newRefs.sort((a, b) => a.ref.num - b.ref.num); const xrefTableData = [[0, 1, 0xffff]]; const indexes = [0, 1]; let maxOffset = 0; @@ -39036,9 +38979,7 @@ class Catalog { break; case "PrintPageRange": if (Array.isArray(value) && value.length % 2 === 0) { - const isValid = value.every((page, i, arr) => { - return Number.isInteger(page) && page > 0 && (i === 0 || page >= arr[i - 1]) && page <= this.numPages; - }); + const isValid = value.every((page, i, arr) => Number.isInteger(page) && page > 0 && (i === 0 || page >= arr[i - 1]) && page <= this.numPages); if (isValid) { prefValue = value; } @@ -40010,12 +39951,10 @@ function getRelevant(data) { if (!data) { return []; } - return data.trim().split(/\s+/).map(e => { - return { - excluded: e[0] === "-", - viewname: e.substring(1) - }; - }); + return data.trim().split(/\s+/).map(e => ({ + excluded: e[0] === "-", + viewname: e.substring(1) + })); } function getColor(data, def = [0, 0, 0]) { let [r, g, b] = def; @@ -50653,7 +50592,11 @@ class AnnotationFactory { })); break; case AnnotationEditorType.HIGHLIGHT: - promises.push(HighlightAnnotation.createNewAnnotation(xref, annotation, dependencies)); + 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)); @@ -50720,9 +50663,15 @@ class AnnotationFactory { })); break; case AnnotationEditorType.HIGHLIGHT: - promises.push(HighlightAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, { - evaluatorOptions: options - })); + 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, { @@ -51740,9 +51689,7 @@ class WidgetAnnotation extends Annotation { path: this.data.fieldName, value }; - const encoder = val => { - return isAscii(val) ? val : stringToUTF16String(val, true); - }; + 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); @@ -52880,7 +52827,7 @@ class FreeTextAnnotation extends MarkupAnnotation { 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, FakeUnicodeFont.toUnicodeStream); + this._streams.push(this.appearance); } else { warn("FreeTextAnnotation: OffscreenCanvas is not supported, annotation may not render correctly."); } @@ -53296,6 +53243,7 @@ class InkAnnotation extends MarkupAnnotation { color, opacity, paths, + outlines, rect, rotation, thickness @@ -53305,9 +53253,12 @@ class InkAnnotation extends MarkupAnnotation { ink.set("Subtype", Name.get("Ink")); ink.set("CreationDate", `D:${getModificationDate()}`); ink.set("Rect", rect); - ink.set("InkList", paths.map(p => p.points)); + 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); @@ -53323,6 +53274,9 @@ class InkAnnotation extends MarkupAnnotation { return ink; } static async createNewAppearanceStream(annotation, xref, params) { + if (annotation.outlines) { + return this.createNewAppearanceStreamForHighlight(annotation, xref, params); + } const { color, rect, @@ -53372,6 +53326,48 @@ class InkAnnotation extends MarkupAnnotation { 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) { @@ -53606,9 +53602,7 @@ class StampAnnotation extends MarkupAnnotation { const jpegBufferPromise = canvas.convertToBlob({ type: "image/jpeg", quality: 1 - }).then(blob => { - return blob.arrayBuffer(); - }); + }).then(blob => blob.arrayBuffer()); const xobjectName = Name.get("XObject"); const imageName = Name.get("Image"); const image = new Dict(xref); @@ -56594,7 +56588,7 @@ class WorkerMessageHandler { docId, apiVersion } = docParams; - const workerVersion = '4.1.30'; + const workerVersion = "4.1.86"; if (apiVersion !== workerVersion) { throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`); } @@ -57155,8 +57149,8 @@ if (typeof window === "undefined" && !isNodeJS && typeof self !== "undefined" && ;// CONCATENATED MODULE: ./src/pdf.worker.js -const pdfjsVersion = '4.1.30'; -const pdfjsBuild = 'a22b5a4f0'; +const pdfjsVersion = "4.1.86"; +const pdfjsBuild = "bf9236009"; var __webpack_exports__WorkerMessageHandler = __webpack_exports__.WorkerMessageHandler; export { __webpack_exports__WorkerMessageHandler as WorkerMessageHandler }; diff --git a/toolkit/components/pdfjs/content/web/viewer-geckoview.css b/toolkit/components/pdfjs/content/web/viewer-geckoview.css index 584ff62b417f..177c005df077 100644 --- a/toolkit/components/pdfjs/content/web/viewer-geckoview.css +++ b/toolkit/components/pdfjs/content/web/viewer-geckoview.css @@ -18,12 +18,17 @@ text-align:initial; inset:0; overflow:hidden; - opacity:0.25; + opacity:1; line-height:1; text-size-adjust:none; forced-color-adjust:none; transform-origin:0 0; z-index:2; + caret-color:CanvasText; + + &.drawing{ + touch-action:none; + } :is(span, br){ color:transparent; @@ -34,17 +39,22 @@ } .highlight{ - --highlight-bg-color:rgb(180 0 170); - --highlight-selected-bg-color:rgb(0 100 0); + --highlight-bg-color:rgb(180 0 170 / 0.25); + --highlight-selected-bg-color:rgb(0 100 0 / 0.25); + --highlight-backdrop-filter:none; + --highlight-selected-backdrop-filter:none; @media screen and (forced-colors: active){ - --highlight-bg-color:Highlight; - --highlight-selected-bg-color:ButtonText; + --highlight-bg-color:transparent; + --highlight-selected-bg-color:transparent; + --highlight-backdrop-filter:var(--hcm-highlight-filter); + --highlight-selected-backdrop-filter:var(--hcm-highlight-selected-filter); } margin:-1px; padding:1px; background-color:var(--highlight-bg-color); + backdrop-filter:var(--highlight-backdrop-filter); border-radius:4px; &.appended{ @@ -65,11 +75,12 @@ &.selected{ background-color:var(--highlight-selected-bg-color); + backdrop-filter:var(--highlight-selected-backdrop-filter); } } ::selection{ - background:AccentColor; + background:color-mix(in srgb, AccentColor, transparent 75%); } .endOfContent{ @@ -101,7 +112,6 @@ --input-disabled-border-color:GrayText; --input-hover-border-color:Highlight; --link-outline:1.5px solid LinkText; - --hcm-highlight-filter:invert(100%); .textWidgetAnnotation :is(input, textarea):required, .choiceWidgetAnnotation select:required, @@ -785,6 +795,13 @@ --scale-factor:1; padding-bottom:var(--pdfViewer-padding-bottom); + + --hcm-highlight-filter:none; + --hcm-highlight-selected-filter:none; + + @media screen and (forced-colors: active){ + --hcm-highlight-filter:invert(100%); + } } .pdfViewer .canvasWrapper{ diff --git a/toolkit/components/pdfjs/content/web/viewer-geckoview.mjs b/toolkit/components/pdfjs/content/web/viewer-geckoview.mjs index fe525a3bcb5f..d1199ccd70dc 100644 --- a/toolkit/components/pdfjs/content/web/viewer-geckoview.mjs +++ b/toolkit/components/pdfjs/content/web/viewer-geckoview.mjs @@ -182,15 +182,13 @@ function parseQueryString(query) { } return params; } -const InvisibleCharactersRegExp = /[\x00-\x1F]/g; +const InvisibleCharsRegExp = /[\x00-\x1F]/g; function removeNullCharacters(str, replaceInvisible = false) { - if (!InvisibleCharactersRegExp.test(str)) { + if (!InvisibleCharsRegExp.test(str)) { return str; } if (replaceInvisible) { - return str.replaceAll(InvisibleCharactersRegExp, m => { - return m === "\x00" ? "" : " "; - }); + return str.replaceAll(InvisibleCharsRegExp, m => m === "\x00" ? "" : " "); } return str.replaceAll("\x00", ""); } @@ -992,9 +990,7 @@ function addLinkAttributes(link, { } else { link.href = ""; link.title = `Disabled: ${url}`; - link.onclick = () => { - return false; - }; + link.onclick = () => false; } let targetStr = ""; switch (target) { @@ -2128,9 +2124,7 @@ class PDFFindController { const extractTextCapability = new PromiseCapability(); this._extractTextPromises[i] = extractTextCapability.promise; promise = promise.then(() => { - return this._pdfDocument.getPage(i + 1).then(pdfPage => { - return pdfPage.getTextContent(textOptions); - }).then(textContent => { + return this._pdfDocument.getPage(i + 1).then(pdfPage => pdfPage.getTextContent(textOptions)).then(textContent => { const strBuf = []; for (const textItem of textContent.items) { strBuf.push(textItem.str); @@ -5036,7 +5030,7 @@ class PDFViewer { #scaleTimeoutId = null; #textLayerMode = TextLayerMode.ENABLE; constructor(options) { - const viewerVersion = '4.1.30'; + const viewerVersion = "4.1.86"; if (version !== viewerVersion) { throw new Error(`The API version "${version}" does not match the Viewer version "${viewerVersion}".`); } @@ -5440,7 +5434,8 @@ class PDFViewer { }); this.viewer.style.setProperty("--scale-factor", viewport.scale); if (this.pageColors?.foreground === "CanvasText" || this.pageColors?.background === "Canvas") { - this.viewer.style.setProperty("--hcm-highlight-filter", pdfDocument.filterFactory.addHighlightHCMFilter("CanvasText", "Canvas", "HighlightText", "Highlight")); + this.viewer.style.setProperty("--hcm-highlight-filter", pdfDocument.filterFactory.addHighlightHCMFilter("highlight", "CanvasText", "Canvas", "HighlightText", "Highlight")); + this.viewer.style.setProperty("--hcm-highlight-selected-filter", pdfDocument.filterFactory.addHighlightHCMFilter("highlight_selected", "CanvasText", "Canvas", "HighlightText", "ButtonText")); } for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) { const pageView = new PDFPageView({ @@ -7636,9 +7631,7 @@ const PDFViewerApplication = { this.pdfRenderingQueue.renderHighestPriority(); }, beforePrint() { - this._printAnnotationStoragePromise = this.pdfScriptingManager.dispatchWillPrint().catch(() => {}).then(() => { - return this.pdfDocument?.annotationStorage.print; - }); + this._printAnnotationStoragePromise = this.pdfScriptingManager.dispatchWillPrint().catch(() => {}).then(() => this.pdfDocument?.annotationStorage.print); if (this.printService) { return; } @@ -8617,34 +8610,34 @@ const PDFPrintServiceFactory = { class BasePreferences { #defaults = Object.freeze({ - "annotationEditorMode": 0, - "annotationMode": 2, - "cursorToolOnLoad": 0, - "defaultZoomDelay": 400, - "defaultZoomValue": "", - "disablePageLabels": false, - "enableHighlightEditor": false, - "enablePermissions": false, - "enablePrintAutoRotate": true, - "enableScripting": true, - "externalLinkTarget": 0, - "highlightEditorColors": "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F", - "historyUpdateUrl": false, - "ignoreDestinationZoom": false, - "forcePageColors": false, - "pageColorsBackground": "Canvas", - "pageColorsForeground": "CanvasText", - "pdfBugEnabled": false, - "sidebarViewOnLoad": -1, - "scrollModeOnLoad": -1, - "spreadModeOnLoad": -1, - "textLayerMode": 1, - "viewOnLoad": 0, - "disableAutoFetch": false, - "disableFontFace": false, - "disableRange": false, - "disableStream": false, - "enableXfa": true + annotationEditorMode: 0, + annotationMode: 2, + cursorToolOnLoad: 0, + defaultZoomDelay: 400, + defaultZoomValue: "", + disablePageLabels: false, + enableHighlightEditor: false, + enablePermissions: false, + enablePrintAutoRotate: true, + enableScripting: true, + externalLinkTarget: 0, + highlightEditorColors: "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F", + historyUpdateUrl: false, + ignoreDestinationZoom: false, + forcePageColors: false, + pageColorsBackground: "Canvas", + pageColorsForeground: "CanvasText", + pdfBugEnabled: false, + sidebarViewOnLoad: -1, + scrollModeOnLoad: -1, + spreadModeOnLoad: -1, + textLayerMode: 1, + viewOnLoad: 0, + disableAutoFetch: false, + disableFontFace: false, + disableRange: false, + disableStream: false, + enableXfa: true }); #prefs = Object.create(null); #initializedPromise = null; @@ -8657,13 +8650,13 @@ class BasePreferences { prefs }) => { const BROWSER_PREFS = { - "canvasMaxAreaInBytes": -1, - "isInAutomation": false, - "supportsDocumentFonts": true, - "supportsIntegratedFind": false, - "supportsMouseWheelZoomCtrlKey": true, - "supportsMouseWheelZoomMetaKey": true, - "supportsPinchToZoom": true + canvasMaxAreaInBytes: -1, + isInAutomation: false, + supportsDocumentFonts: true, + supportsIntegratedFind: false, + supportsMouseWheelZoomCtrlKey: true, + supportsMouseWheelZoomMetaKey: true, + supportsPinchToZoom: true }; const options = Object.create(null); for (const [name, defaultVal] of Object.entries(BROWSER_PREFS)) { @@ -9249,8 +9242,8 @@ PDFPrintServiceFactory.instance = { -const pdfjsVersion = '4.1.30'; -const pdfjsBuild = 'a22b5a4f0'; +const pdfjsVersion = "4.1.86"; +const pdfjsBuild = "bf9236009"; const AppConstants = null; window.PDFViewerApplication = PDFViewerApplication; window.PDFViewerApplicationConstants = AppConstants; diff --git a/toolkit/components/pdfjs/content/web/viewer.css b/toolkit/components/pdfjs/content/web/viewer.css index 4ee9a5cd328d..466831b12c25 100644 --- a/toolkit/components/pdfjs/content/web/viewer.css +++ b/toolkit/components/pdfjs/content/web/viewer.css @@ -18,12 +18,17 @@ text-align:initial; inset:0; overflow:hidden; - opacity:0.25; + opacity:1; line-height:1; text-size-adjust:none; forced-color-adjust:none; transform-origin:0 0; z-index:2; + caret-color:CanvasText; + + &.drawing{ + touch-action:none; + } :is(span, br){ color:transparent; @@ -34,17 +39,22 @@ } .highlight{ - --highlight-bg-color:rgb(180 0 170); - --highlight-selected-bg-color:rgb(0 100 0); + --highlight-bg-color:rgb(180 0 170 / 0.25); + --highlight-selected-bg-color:rgb(0 100 0 / 0.25); + --highlight-backdrop-filter:none; + --highlight-selected-backdrop-filter:none; @media screen and (forced-colors: active){ - --highlight-bg-color:Highlight; - --highlight-selected-bg-color:ButtonText; + --highlight-bg-color:transparent; + --highlight-selected-bg-color:transparent; + --highlight-backdrop-filter:var(--hcm-highlight-filter); + --highlight-selected-backdrop-filter:var(--hcm-highlight-selected-filter); } margin:-1px; padding:1px; background-color:var(--highlight-bg-color); + backdrop-filter:var(--highlight-backdrop-filter); border-radius:4px; &.appended{ @@ -65,11 +75,12 @@ &.selected{ background-color:var(--highlight-selected-bg-color); + backdrop-filter:var(--highlight-selected-backdrop-filter); } } ::selection{ - background:AccentColor; + background:color-mix(in srgb, AccentColor, transparent 75%); } .endOfContent{ @@ -101,7 +112,6 @@ --input-disabled-border-color:GrayText; --input-hover-border-color:Highlight; --link-outline:1.5px solid LinkText; - --hcm-highlight-filter:invert(100%); .textWidgetAnnotation :is(input, textarea):required, .choiceWidgetAnnotation select:required, @@ -774,7 +784,10 @@ position:absolute; mix-blend-mode:var(--blend-mode); - fill-rule:evenodd; + + &:not(.free){ + fill-rule:evenodd; + } } &.highlightOutline{ @@ -1706,25 +1719,25 @@ .annotationEditorLayer{ &[data-main-rotation="0"]{ - .highlightEditor > .editToolbar{ + .highlightEditor:not(.free) > .editToolbar{ rotate:0deg; } } &[data-main-rotation="90"]{ - .highlightEditor > .editToolbar{ + .highlightEditor:not(.free) > .editToolbar{ rotate:270deg; } } &[data-main-rotation="180"]{ - .highlightEditor > .editToolbar{ + .highlightEditor:not(.free) > .editToolbar{ rotate:180deg; } } &[data-main-rotation="270"]{ - .highlightEditor > .editToolbar{ + .highlightEditor:not(.free) > .editToolbar{ rotate:90deg; } } @@ -1733,14 +1746,17 @@ position:absolute; background:transparent; z-index:1; - transform-origin:0 0; cursor:auto; max-width:100%; max-height:100%; border:none; outline:none; pointer-events:none; - transform:none; + transform-origin:0 0; + + &:not(.free){ + transform:none; + } .internal{ position:absolute; @@ -1793,6 +1809,10 @@ &:has(.dropdown:not(.hidden)){ background-color:var(--editor-toolbar-hover-bg-color); + + &::after{ + scale:-1; + } } .dropdown{ @@ -1851,21 +1871,22 @@ height:auto; padding-inline:10px; padding-block:10px 16px; + gap:16px; display:flex; flex-direction:column; box-sizing:border-box; + .editorParamsLabel{ + width:-moz-fit-content; + width:fit-content; + inset-inline-start:0; + } + .colorPicker{ display:flex; flex-direction:column; gap:8px; - #highlightColorPickerLabel{ - width:-moz-fit-content; - width:fit-content; - inset-inline-start:0; - } - .dropdown{ display:flex; justify-content:space-between; @@ -1903,6 +1924,60 @@ } } } + + #editorHighlightThickness{ + display:flex; + flex-direction:column; + align-items:center; + gap:4px; + align-self:stretch; + + .editorParamsLabel{ + width:100%; + height:auto; + align-self:stretch; + } + + .thicknessPicker{ + display:flex; + justify-content:space-between; + align-items:center; + align-self:stretch; + + --example-color:#bfbfc9; + + @media (prefers-color-scheme: dark){ + --example-color:#80808e; + } + + @media screen and (forced-colors: active){ + --example-color:HighlightText; + } + + &::before{ + content:""; + width:8px; + aspect-ratio:1; + display:block; + border-radius:100%; + background-color:var(--example-color); + } + + .editorParamsSlider{ + width:unset; + height:14px; + } + + &::after{ + content:""; + width:24px; + aspect-ratio:1; + display:block; + border-radius:100%; + background-color:var(--example-color); + } + } + } } :root{ @@ -1947,6 +2022,13 @@ --scale-factor:1; padding-bottom:var(--pdfViewer-padding-bottom); + + --hcm-highlight-filter:none; + --hcm-highlight-selected-filter:none; + + @media screen and (forced-colors: active){ + --hcm-highlight-filter:invert(100%); + } } .pdfViewer .canvasWrapper{ diff --git a/toolkit/components/pdfjs/content/web/viewer.html b/toolkit/components/pdfjs/content/web/viewer.html index b687a7238fd7..4951f1811e67 100644 --- a/toolkit/components/pdfjs/content/web/viewer.html +++ b/toolkit/components/pdfjs/content/web/viewer.html @@ -121,6 +121,12 @@ See https://github.com/adobe-type-tools/cmap-resources
Highlight color
+
+ +
+ +
+
diff --git a/toolkit/components/pdfjs/content/web/viewer.mjs b/toolkit/components/pdfjs/content/web/viewer.mjs index c918567ca972..4484b880727f 100644 --- a/toolkit/components/pdfjs/content/web/viewer.mjs +++ b/toolkit/components/pdfjs/content/web/viewer.mjs @@ -182,15 +182,13 @@ function parseQueryString(query) { } return params; } -const InvisibleCharactersRegExp = /[\x00-\x1F]/g; +const InvisibleCharsRegExp = /[\x00-\x1F]/g; function removeNullCharacters(str, replaceInvisible = false) { - if (!InvisibleCharactersRegExp.test(str)) { + if (!InvisibleCharsRegExp.test(str)) { return str; } if (replaceInvisible) { - return str.replaceAll(InvisibleCharactersRegExp, m => { - return m === "\x00" ? "" : " "; - }); + return str.replaceAll(InvisibleCharsRegExp, m => m === "\x00" ? "" : " "); } return str.replaceAll("\x00", ""); } @@ -992,9 +990,7 @@ function addLinkAttributes(link, { } else { link.href = ""; link.title = `Disabled: ${url}`; - link.onclick = () => { - return false; - }; + link.onclick = () => false; } let targetStr = ""; switch (target) { @@ -1673,7 +1669,8 @@ class AnnotationEditorParams { editorInkColor, editorInkThickness, editorInkOpacity, - editorStampAddImage + editorStampAddImage, + editorFreeHighlightThickness }) { const dispatchEvent = (typeStr, value) => { this.eventBus.dispatch("switchannotationeditorparams", { @@ -1700,6 +1697,9 @@ class AnnotationEditorParams { editorStampAddImage.addEventListener("click", () => { dispatchEvent("CREATE"); }); + editorFreeHighlightThickness.addEventListener("input", function () { + dispatchEvent("HIGHLIGHT_THICKNESS", this.valueAsNumber); + }); this.eventBus._on("annotationeditorparamschanged", evt => { for (const [type, value] of evt.details) { switch (type) { @@ -1718,6 +1718,9 @@ class AnnotationEditorParams { case AnnotationEditorParamsType.INK_OPACITY: editorInkOpacity.value = value; break; + case AnnotationEditorParamsType.HIGHLIGHT_THICKNESS: + editorFreeHighlightThickness.value = value; + break; } } }); @@ -3040,9 +3043,7 @@ class PDFFindController { const extractTextCapability = new PromiseCapability(); this._extractTextPromises[i] = extractTextCapability.promise; promise = promise.then(() => { - return this._pdfDocument.getPage(i + 1).then(pdfPage => { - return pdfPage.getTextContent(textOptions); - }).then(textContent => { + return this._pdfDocument.getPage(i + 1).then(pdfPage => pdfPage.getTextContent(textOptions)).then(textContent => { const strBuf = []; for (const textItem of textContent.items) { strBuf.push(textItem.str); @@ -7634,7 +7635,7 @@ class PDFViewer { #scaleTimeoutId = null; #textLayerMode = TextLayerMode.ENABLE; constructor(options) { - const viewerVersion = '4.1.30'; + const viewerVersion = "4.1.86"; if (version !== viewerVersion) { throw new Error(`The API version "${version}" does not match the Viewer version "${viewerVersion}".`); } @@ -8038,7 +8039,8 @@ class PDFViewer { }); this.viewer.style.setProperty("--scale-factor", viewport.scale); if (this.pageColors?.foreground === "CanvasText" || this.pageColors?.background === "Canvas") { - this.viewer.style.setProperty("--hcm-highlight-filter", pdfDocument.filterFactory.addHighlightHCMFilter("CanvasText", "Canvas", "HighlightText", "Highlight")); + this.viewer.style.setProperty("--hcm-highlight-filter", pdfDocument.filterFactory.addHighlightHCMFilter("highlight", "CanvasText", "Canvas", "HighlightText", "Highlight")); + this.viewer.style.setProperty("--hcm-highlight-selected-filter", pdfDocument.filterFactory.addHighlightHCMFilter("highlight_selected", "CanvasText", "Canvas", "HighlightText", "ButtonText")); } for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) { const pageView = new PDFPageView({ @@ -10743,9 +10745,7 @@ const PDFViewerApplication = { this.pdfRenderingQueue.renderHighestPriority(); }, beforePrint() { - this._printAnnotationStoragePromise = this.pdfScriptingManager.dispatchWillPrint().catch(() => {}).then(() => { - return this.pdfDocument?.annotationStorage.print; - }); + this._printAnnotationStoragePromise = this.pdfScriptingManager.dispatchWillPrint().catch(() => {}).then(() => this.pdfDocument?.annotationStorage.print); if (this.printService) { return; } @@ -11724,34 +11724,34 @@ const PDFPrintServiceFactory = { class BasePreferences { #defaults = Object.freeze({ - "annotationEditorMode": 0, - "annotationMode": 2, - "cursorToolOnLoad": 0, - "defaultZoomDelay": 400, - "defaultZoomValue": "", - "disablePageLabels": false, - "enableHighlightEditor": false, - "enablePermissions": false, - "enablePrintAutoRotate": true, - "enableScripting": true, - "externalLinkTarget": 0, - "highlightEditorColors": "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F", - "historyUpdateUrl": false, - "ignoreDestinationZoom": false, - "forcePageColors": false, - "pageColorsBackground": "Canvas", - "pageColorsForeground": "CanvasText", - "pdfBugEnabled": false, - "sidebarViewOnLoad": -1, - "scrollModeOnLoad": -1, - "spreadModeOnLoad": -1, - "textLayerMode": 1, - "viewOnLoad": 0, - "disableAutoFetch": false, - "disableFontFace": false, - "disableRange": false, - "disableStream": false, - "enableXfa": true + annotationEditorMode: 0, + annotationMode: 2, + cursorToolOnLoad: 0, + defaultZoomDelay: 400, + defaultZoomValue: "", + disablePageLabels: false, + enableHighlightEditor: false, + enablePermissions: false, + enablePrintAutoRotate: true, + enableScripting: true, + externalLinkTarget: 0, + highlightEditorColors: "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F", + historyUpdateUrl: false, + ignoreDestinationZoom: false, + forcePageColors: false, + pageColorsBackground: "Canvas", + pageColorsForeground: "CanvasText", + pdfBugEnabled: false, + sidebarViewOnLoad: -1, + scrollModeOnLoad: -1, + spreadModeOnLoad: -1, + textLayerMode: 1, + viewOnLoad: 0, + disableAutoFetch: false, + disableFontFace: false, + disableRange: false, + disableStream: false, + enableXfa: true }); #prefs = Object.create(null); #initializedPromise = null; @@ -11764,13 +11764,13 @@ class BasePreferences { prefs }) => { const BROWSER_PREFS = { - "canvasMaxAreaInBytes": -1, - "isInAutomation": false, - "supportsDocumentFonts": true, - "supportsIntegratedFind": false, - "supportsMouseWheelZoomCtrlKey": true, - "supportsMouseWheelZoomMetaKey": true, - "supportsPinchToZoom": true + canvasMaxAreaInBytes: -1, + isInAutomation: false, + supportsDocumentFonts: true, + supportsIntegratedFind: false, + supportsMouseWheelZoomCtrlKey: true, + supportsMouseWheelZoomMetaKey: true, + supportsPinchToZoom: true }; const options = Object.create(null); for (const [name, defaultVal] of Object.entries(BROWSER_PREFS)) { @@ -12321,8 +12321,8 @@ PDFPrintServiceFactory.instance = { -const pdfjsVersion = '4.1.30'; -const pdfjsBuild = 'a22b5a4f0'; +const pdfjsVersion = "4.1.86"; +const pdfjsBuild = "bf9236009"; const AppConstants = null; window.PDFViewerApplication = PDFViewerApplication; window.PDFViewerApplicationConstants = AppConstants; @@ -12447,7 +12447,8 @@ function getViewerConfiguration() { editorInkColor: document.getElementById("editorInkColor"), editorInkThickness: document.getElementById("editorInkThickness"), editorInkOpacity: document.getElementById("editorInkOpacity"), - editorStampAddImage: document.getElementById("editorStampAddImage") + editorStampAddImage: document.getElementById("editorStampAddImage"), + editorFreeHighlightThickness: document.getElementById("editorFreeHighlightThickness") }, printContainer: document.getElementById("printContainer"), openFileInput: null, diff --git a/toolkit/components/pdfjs/moz.yaml b/toolkit/components/pdfjs/moz.yaml index 54beab3ef352..111fa6d7eba3 100644 --- a/toolkit/components/pdfjs/moz.yaml +++ b/toolkit/components/pdfjs/moz.yaml @@ -20,8 +20,8 @@ origin: # Human-readable identifier for this version/release # Generally "version NNN", "tag SSS", "bookmark SSS" - release: a22b5a4f02d046b5113630b1c333281841cbe309 (2024-01-16T21:27:14Z). - revision: a22b5a4f02d046b5113630b1c333281841cbe309 + release: bf9236009521621891d73dd77acc68215cb2cadb (2024-01-25T09:07:48Z). + revision: bf9236009521621891d73dd77acc68215cb2cadb # The package's license, where possible using the mnemonic from # https://spdx.org/licenses/ diff --git a/toolkit/locales/en-US/toolkit/pdfviewer/viewer.ftl b/toolkit/locales/en-US/toolkit/pdfviewer/viewer.ftl index a40842a65fbe..d0efeec892cb 100644 --- a/toolkit/locales/en-US/toolkit/pdfviewer/viewer.ftl +++ b/toolkit/locales/en-US/toolkit/pdfviewer/viewer.ftl @@ -349,6 +349,8 @@ pdfjs-editor-ink-opacity-input = Opacity pdfjs-editor-stamp-add-image-button = .title = Add image pdfjs-editor-stamp-add-image-button-label = Add image +# This refers to the thickness of the line used for free highlighting (not bound to text) +pdfjs-editor-free-highlight-thickness-input = Thickness pdfjs-free-text = .aria-label = Text Editor