mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-26 19:38:48 +01:00
This commit is contained in:
parent
7ad5cdd067
commit
23f2af3501
57 changed files with 83865 additions and 2979 deletions
|
|
@ -531,7 +531,7 @@ export const getHighlight = (element: HTMLElement) => {
|
|||
const showHighlight = (selected: IPdfAnno, pdf: any, hl?: boolean) => {
|
||||
const pageIndex = selected.index;
|
||||
const page = pdf.pdfViewer.getPageView(pageIndex);
|
||||
let textLayerElement = page.textLayer.textLayerDiv;
|
||||
let textLayerElement = page.textLayer.div;
|
||||
if (!textLayerElement.lastElementChild) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -284,6 +284,8 @@ export class Asset extends Model {
|
|||
<svg><use xlink:href="#iconPlay"></use></svg>
|
||||
</button>
|
||||
<span id="scrollPage" class="fn__none"></span>
|
||||
<span id="print" class="fn__none"></span>
|
||||
<span id="secondaryPrint" class="fn__none"></span>
|
||||
<span id="viewBookmark" class="fn__none"></span>
|
||||
<span id="secondaryViewBookmark" class="fn__none"></span>
|
||||
<button id="secondaryToolbarToggle" class="toolbarButton b3-tooltips b3-tooltips__sw" aria-label="${window.siyuan.languages.more}" tabindex="36" aria-expanded="false" aria-controls="secondaryToolbar">
|
||||
|
|
|
|||
|
|
@ -16,12 +16,9 @@
|
|||
/** @typedef {import("../src/display/api").PDFPageProxy} PDFPageProxy */
|
||||
// eslint-disable-next-line max-len
|
||||
/** @typedef {import("../src/display/display_utils").PageViewport} PageViewport */
|
||||
/** @typedef {import("./interfaces").IPDFLinkService} IPDFLinkService */
|
||||
// eslint-disable-next-line max-len
|
||||
/** @typedef {import("../src/display/editor/tools.js").AnnotationEditorUIManager} AnnotationEditorUIManager */
|
||||
// eslint-disable-next-line max-len
|
||||
/** @typedef {import("../annotation_storage.js").AnnotationStorage} AnnotationStorage */
|
||||
// eslint-disable-next-line max-len
|
||||
/** @typedef {import("./text_accessibility.js").TextAccessibilityManager} TextAccessibilityManager */
|
||||
/** @typedef {import("./interfaces").IL10n} IL10n */
|
||||
|
||||
|
|
@ -30,13 +27,11 @@ import { NullL10n } from "./l10n_utils.js";
|
|||
|
||||
/**
|
||||
* @typedef {Object} AnnotationEditorLayerBuilderOptions
|
||||
* @property {number} mode - Editor mode
|
||||
* @property {AnnotationEditorUIManager} [uiManager]
|
||||
* @property {HTMLDivElement} pageDiv
|
||||
* @property {PDFPageProxy} pdfPage
|
||||
* @property {TextAccessibilityManager} accessibilityManager
|
||||
* @property {AnnotationStorage} annotationStorage
|
||||
* @property {IL10n} l10n - Localization service.
|
||||
* @property {AnnotationEditorUIManager} uiManager
|
||||
* @property {IL10n} [l10n]
|
||||
* @property {TextAccessibilityManager} [accessibilityManager]
|
||||
*/
|
||||
|
||||
class AnnotationEditorLayerBuilder {
|
||||
|
|
@ -48,7 +43,6 @@ class AnnotationEditorLayerBuilder {
|
|||
constructor(options) {
|
||||
this.pageDiv = options.pageDiv;
|
||||
this.pdfPage = options.pdfPage;
|
||||
this.annotationStorage = options.annotationStorage || null;
|
||||
this.accessibilityManager = options.accessibilityManager;
|
||||
this.l10n = options.l10n || NullL10n;
|
||||
this.annotationEditorLayer = null;
|
||||
|
|
@ -78,34 +72,41 @@ class AnnotationEditorLayerBuilder {
|
|||
}
|
||||
|
||||
// Create an AnnotationEditor layer div
|
||||
this.div = document.createElement("div");
|
||||
this.div.className = "annotationEditorLayer";
|
||||
this.div.tabIndex = 0;
|
||||
this.pageDiv.append(this.div);
|
||||
const div = (this.div = document.createElement("div"));
|
||||
div.className = "annotationEditorLayer";
|
||||
div.tabIndex = 0;
|
||||
div.hidden = true;
|
||||
this.pageDiv.append(div);
|
||||
|
||||
this.annotationEditorLayer = new AnnotationEditorLayer({
|
||||
uiManager: this.#uiManager,
|
||||
div: this.div,
|
||||
annotationStorage: this.annotationStorage,
|
||||
div,
|
||||
accessibilityManager: this.accessibilityManager,
|
||||
pageIndex: this.pdfPage._pageIndex,
|
||||
pageIndex: this.pdfPage.pageNumber - 1,
|
||||
l10n: this.l10n,
|
||||
viewport: clonedViewport,
|
||||
});
|
||||
|
||||
const parameters = {
|
||||
viewport: clonedViewport,
|
||||
div: this.div,
|
||||
div,
|
||||
annotations: null,
|
||||
intent,
|
||||
};
|
||||
|
||||
this.annotationEditorLayer.render(parameters);
|
||||
this.show();
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this._cancelled = true;
|
||||
this.destroy();
|
||||
|
||||
if (!this.div) {
|
||||
return;
|
||||
}
|
||||
this.pageDiv = null;
|
||||
this.annotationEditorLayer.destroy();
|
||||
this.div.remove();
|
||||
}
|
||||
|
||||
hide() {
|
||||
|
|
@ -116,20 +117,11 @@ class AnnotationEditorLayerBuilder {
|
|||
}
|
||||
|
||||
show() {
|
||||
if (!this.div) {
|
||||
if (!this.div || this.annotationEditorLayer.isEmpty) {
|
||||
return;
|
||||
}
|
||||
this.div.hidden = false;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
if (!this.div) {
|
||||
return;
|
||||
}
|
||||
this.pageDiv = null;
|
||||
this.annotationEditorLayer.destroy();
|
||||
this.div.remove();
|
||||
}
|
||||
}
|
||||
|
||||
export { AnnotationEditorLayerBuilder };
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
import { AnnotationLayer } from "./pdfjs";
|
||||
import { NullL10n } from "./l10n_utils.js";
|
||||
import { PresentationModeState } from "./ui_utils.js";
|
||||
|
||||
/**
|
||||
* @typedef {Object} AnnotationLayerBuilderOptions
|
||||
|
|
@ -40,12 +41,15 @@ import { NullL10n } from "./l10n_utils.js";
|
|||
* @property {Promise<boolean>} [hasJSActionsPromise]
|
||||
* @property {Promise<Object<string, Array<Object>> | null>}
|
||||
* [fieldObjectsPromise]
|
||||
* @property {Object} [mouseState]
|
||||
* @property {Map<string, HTMLCanvasElement>} [annotationCanvasMap]
|
||||
* @property {TextAccessibilityManager} accessibilityManager
|
||||
* @property {TextAccessibilityManager} [accessibilityManager]
|
||||
*/
|
||||
|
||||
class AnnotationLayerBuilder {
|
||||
#numAnnotations = 0;
|
||||
|
||||
#onPresentationModeChanged = null;
|
||||
|
||||
/**
|
||||
* @param {AnnotationLayerBuilderOptions} options
|
||||
*/
|
||||
|
|
@ -61,7 +65,6 @@ class AnnotationLayerBuilder {
|
|||
enableScripting = false,
|
||||
hasJSActionsPromise = null,
|
||||
fieldObjectsPromise = null,
|
||||
mouseState = null,
|
||||
annotationCanvasMap = null,
|
||||
accessibilityManager = null,
|
||||
}) {
|
||||
|
|
@ -74,14 +77,14 @@ class AnnotationLayerBuilder {
|
|||
this.l10n = l10n;
|
||||
this.annotationStorage = annotationStorage;
|
||||
this.enableScripting = enableScripting;
|
||||
this._hasJSActionsPromise = hasJSActionsPromise;
|
||||
this._fieldObjectsPromise = fieldObjectsPromise;
|
||||
this._mouseState = mouseState;
|
||||
this._hasJSActionsPromise = hasJSActionsPromise || Promise.resolve(false);
|
||||
this._fieldObjectsPromise = fieldObjectsPromise || Promise.resolve(null);
|
||||
this._annotationCanvasMap = annotationCanvasMap;
|
||||
this._accessibilityManager = accessibilityManager;
|
||||
|
||||
this.div = null;
|
||||
this._cancelled = false;
|
||||
this._eventBus = linkService.eventBus;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -91,18 +94,41 @@ class AnnotationLayerBuilder {
|
|||
* annotations is complete.
|
||||
*/
|
||||
async render(viewport, intent = "display") {
|
||||
const [annotations, hasJSActions = false, fieldObjects = null] =
|
||||
await Promise.all([
|
||||
this.pdfPage.getAnnotations({ intent }),
|
||||
this._hasJSActionsPromise,
|
||||
this._fieldObjectsPromise,
|
||||
]);
|
||||
|
||||
if (this._cancelled || annotations.length === 0) {
|
||||
if (this.div) {
|
||||
if (this._cancelled || this.#numAnnotations === 0) {
|
||||
return;
|
||||
}
|
||||
// If an annotationLayer already exists, refresh its children's
|
||||
// transformation matrices.
|
||||
AnnotationLayer.update({
|
||||
viewport: viewport.clone({ dontFlip: true }),
|
||||
div: this.div,
|
||||
annotationCanvasMap: this._annotationCanvasMap,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const parameters = {
|
||||
const [annotations, hasJSActions, fieldObjects] = await Promise.all([
|
||||
this.pdfPage.getAnnotations({ intent }),
|
||||
this._hasJSActionsPromise,
|
||||
this._fieldObjectsPromise,
|
||||
]);
|
||||
if (this._cancelled) {
|
||||
return;
|
||||
}
|
||||
this.#numAnnotations = annotations.length;
|
||||
|
||||
// Create an annotation layer div and render the annotations
|
||||
// if there is at least one annotation.
|
||||
this.div = document.createElement("div");
|
||||
this.div.className = "annotationLayer";
|
||||
this.pageDiv.append(this.div);
|
||||
|
||||
if (this.#numAnnotations === 0) {
|
||||
this.hide();
|
||||
return;
|
||||
}
|
||||
AnnotationLayer.render({
|
||||
viewport: viewport.clone({ dontFlip: true }),
|
||||
div: this.div,
|
||||
annotations,
|
||||
|
|
@ -115,30 +141,37 @@ class AnnotationLayerBuilder {
|
|||
enableScripting: this.enableScripting,
|
||||
hasJSActions,
|
||||
fieldObjects,
|
||||
mouseState: this._mouseState,
|
||||
annotationCanvasMap: this._annotationCanvasMap,
|
||||
accessibilityManager: this._accessibilityManager,
|
||||
};
|
||||
});
|
||||
// NOTE this.l10n.translate(this.div);
|
||||
|
||||
if (this.div) {
|
||||
// If an annotationLayer already exists, refresh its children's
|
||||
// transformation matrices.
|
||||
AnnotationLayer.update(parameters);
|
||||
} else {
|
||||
// Create an annotation layer div and render the annotations
|
||||
// if there is at least one annotation.
|
||||
this.div = document.createElement("div");
|
||||
this.div.className = "annotationLayer";
|
||||
this.pageDiv.append(this.div);
|
||||
parameters.div = this.div;
|
||||
|
||||
AnnotationLayer.render(parameters);
|
||||
this.l10n.translate(this.div);
|
||||
// Ensure that interactive form elements in the annotationLayer are
|
||||
// disabled while PresentationMode is active (see issue 12232).
|
||||
if (this.linkService.isInPresentationMode) {
|
||||
this.#updatePresentationModeState(PresentationModeState.FULLSCREEN);
|
||||
}
|
||||
if (!this.#onPresentationModeChanged) {
|
||||
this.#onPresentationModeChanged = evt => {
|
||||
this.#updatePresentationModeState(evt.state);
|
||||
};
|
||||
this._eventBus?._on(
|
||||
"presentationmodechanged",
|
||||
this.#onPresentationModeChanged
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this._cancelled = true;
|
||||
|
||||
if (this.#onPresentationModeChanged) {
|
||||
this._eventBus?._off(
|
||||
"presentationmodechanged",
|
||||
this.#onPresentationModeChanged
|
||||
);
|
||||
this.#onPresentationModeChanged = null;
|
||||
}
|
||||
}
|
||||
|
||||
hide() {
|
||||
|
|
@ -147,6 +180,29 @@ class AnnotationLayerBuilder {
|
|||
}
|
||||
this.div.hidden = true;
|
||||
}
|
||||
|
||||
#updatePresentationModeState(state) {
|
||||
if (!this.div) {
|
||||
return;
|
||||
}
|
||||
let disableFormElements = false;
|
||||
|
||||
switch (state) {
|
||||
case PresentationModeState.FULLSCREEN:
|
||||
disableFormElements = true;
|
||||
break;
|
||||
case PresentationModeState.NORMAL:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
for (const section of this.div.childNodes) {
|
||||
if (section.hasAttribute("data-internal-link")) {
|
||||
continue;
|
||||
}
|
||||
section.inert = disableFormElements;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { AnnotationLayerBuilder };
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -12,34 +12,33 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Constants } from '../../constants'
|
||||
|
||||
const compatibilityParams = Object.create(null)
|
||||
if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')) {
|
||||
const compatibilityParams = Object.create(null);
|
||||
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
|
||||
if (
|
||||
typeof PDFJSDev !== 'undefined' &&
|
||||
PDFJSDev.test('LIB') &&
|
||||
typeof navigator === 'undefined'
|
||||
typeof PDFJSDev !== "undefined" &&
|
||||
PDFJSDev.test("LIB") &&
|
||||
typeof navigator === "undefined"
|
||||
) {
|
||||
globalThis.navigator = Object.create(null)
|
||||
globalThis.navigator = Object.create(null);
|
||||
}
|
||||
const userAgent = navigator.userAgent || ''
|
||||
const platform = navigator.platform || ''
|
||||
const maxTouchPoints = navigator.maxTouchPoints || 1
|
||||
const userAgent = navigator.userAgent || "";
|
||||
const platform = navigator.platform || "";
|
||||
const maxTouchPoints = navigator.maxTouchPoints || 1;
|
||||
|
||||
const isAndroid = /Android/.test(userAgent)
|
||||
const isAndroid = /Android/.test(userAgent);
|
||||
const isIOS =
|
||||
/\b(iPad|iPhone|iPod)(?=;)/.test(userAgent) ||
|
||||
(platform === 'MacIntel' && maxTouchPoints > 1);
|
||||
(platform === "MacIntel" && maxTouchPoints > 1);
|
||||
|
||||
// Limit canvas size to 5 mega-pixels on mobile.
|
||||
// Support: Android, iOS
|
||||
(function checkCanvasSizeLimitation () {
|
||||
(function checkCanvasSizeLimitation() {
|
||||
if (isIOS || isAndroid) {
|
||||
compatibilityParams.maxCanvasPixels = 5242880
|
||||
compatibilityParams.maxCanvasPixels = 5242880;
|
||||
}
|
||||
})()
|
||||
})();
|
||||
}
|
||||
|
||||
const OptionKind = {
|
||||
|
|
@ -47,7 +46,7 @@ const OptionKind = {
|
|||
API: 0x04,
|
||||
WORKER: 0x08,
|
||||
PREFERENCE: 0x80,
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* NOTE: These options are used to generate the `default_preferences.json` file,
|
||||
|
|
@ -70,9 +69,14 @@ const defaultOptions = {
|
|||
value: 0,
|
||||
kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
|
||||
},
|
||||
defaultZoomDelay: {
|
||||
/** @type {number} */
|
||||
value: 400,
|
||||
kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
|
||||
},
|
||||
defaultZoomValue: {
|
||||
/** @type {string} */
|
||||
value: '',
|
||||
value: "",
|
||||
kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
|
||||
},
|
||||
disableHistory: {
|
||||
|
|
@ -97,12 +101,12 @@ const defaultOptions = {
|
|||
},
|
||||
enableScripting: {
|
||||
/** @type {boolean} */
|
||||
value: typeof PDFJSDev === 'undefined' || !PDFJSDev.test('CHROME'),
|
||||
value: typeof PDFJSDev === "undefined" || !PDFJSDev.test("CHROME"),
|
||||
kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
|
||||
},
|
||||
externalLinkRel: {
|
||||
/** @type {string} */
|
||||
value: 'noopener noreferrer nofollow',
|
||||
value: "noopener noreferrer nofollow",
|
||||
kind: OptionKind.VIEWER,
|
||||
},
|
||||
externalLinkTarget: {
|
||||
|
|
@ -122,7 +126,7 @@ const defaultOptions = {
|
|||
},
|
||||
imageResourcesPath: {
|
||||
/** @type {string} */
|
||||
value: './images/',
|
||||
value: "./images/",
|
||||
kind: OptionKind.VIEWER,
|
||||
},
|
||||
maxCanvasPixels: {
|
||||
|
|
@ -137,17 +141,17 @@ const defaultOptions = {
|
|||
},
|
||||
pageColorsBackground: {
|
||||
/** @type {string} */
|
||||
value: 'Canvas',
|
||||
value: "Canvas",
|
||||
kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
|
||||
},
|
||||
pageColorsForeground: {
|
||||
/** @type {string} */
|
||||
value: 'CanvasText',
|
||||
value: "CanvasText",
|
||||
kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
|
||||
},
|
||||
pdfBugEnabled: {
|
||||
/** @type {boolean} */
|
||||
value: typeof PDFJSDev === 'undefined' || !PDFJSDev.test('PRODUCTION'),
|
||||
value: typeof PDFJSDev === "undefined" || !PDFJSDev.test("PRODUCTION"),
|
||||
kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
|
||||
},
|
||||
printResolution: {
|
||||
|
|
@ -182,7 +186,7 @@ const defaultOptions = {
|
|||
},
|
||||
viewerCssTheme: {
|
||||
/** @type {number} */
|
||||
value: typeof PDFJSDev !== 'undefined' && PDFJSDev.test('CHROME') ? 2 : 0,
|
||||
value: typeof PDFJSDev !== "undefined" && PDFJSDev.test("CHROME") ? 2 : 0,
|
||||
kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
|
||||
},
|
||||
viewOnLoad: {
|
||||
|
|
@ -223,7 +227,7 @@ const defaultOptions = {
|
|||
},
|
||||
docBaseUrl: {
|
||||
/** @type {string} */
|
||||
value: '',
|
||||
value: "",
|
||||
kind: OptionKind.API,
|
||||
},
|
||||
enableXfa: {
|
||||
|
|
@ -241,6 +245,11 @@ const defaultOptions = {
|
|||
value: true,
|
||||
kind: OptionKind.API,
|
||||
},
|
||||
isOffscreenCanvasSupported: {
|
||||
/** @type {boolean} */
|
||||
value: true,
|
||||
kind: OptionKind.API,
|
||||
},
|
||||
maxImageSize: {
|
||||
/** @type {number} */
|
||||
value: -1,
|
||||
|
|
@ -253,10 +262,7 @@ const defaultOptions = {
|
|||
},
|
||||
standardFontDataUrl: {
|
||||
/** @type {string} */
|
||||
value:
|
||||
typeof PDFJSDev === 'undefined' || !PDFJSDev.test('PRODUCTION')
|
||||
? '../external/standard_fonts/'
|
||||
: '../web/standard_fonts/',
|
||||
value: "standard_fonts/", // NOTE
|
||||
kind: OptionKind.API,
|
||||
},
|
||||
verbosity: {
|
||||
|
|
@ -273,131 +279,130 @@ const defaultOptions = {
|
|||
workerSrc: {
|
||||
/** @type {string} */
|
||||
// NOTE
|
||||
value: `${Constants.PROTYLE_CDN}/js/pdf/pdf.worker.js?v=3.0.150`,
|
||||
value: `${Constants.PROTYLE_CDN}/js/pdf/pdf.worker.js?v=3.4.120`,
|
||||
kind: OptionKind.WORKER,
|
||||
},
|
||||
}
|
||||
};
|
||||
if (
|
||||
typeof PDFJSDev === 'undefined' ||
|
||||
PDFJSDev.test('!PRODUCTION || GENERIC')
|
||||
typeof PDFJSDev === "undefined" ||
|
||||
PDFJSDev.test("!PRODUCTION || GENERIC")
|
||||
) {
|
||||
defaultOptions.defaultUrl = {
|
||||
/** @type {string} */
|
||||
value: 'compressed.tracemonkey-pldi-09.pdf',
|
||||
value: "compressed.tracemonkey-pldi-09.pdf",
|
||||
kind: OptionKind.VIEWER,
|
||||
}
|
||||
};
|
||||
defaultOptions.disablePreferences = {
|
||||
/** @type {boolean} */
|
||||
value: typeof PDFJSDev !== 'undefined' && PDFJSDev.test('TESTING'),
|
||||
value: typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING"),
|
||||
kind: OptionKind.VIEWER,
|
||||
}
|
||||
};
|
||||
defaultOptions.locale = {
|
||||
/** @type {string} */
|
||||
value: navigator.language || 'en-US',
|
||||
value: navigator.language || "en-US",
|
||||
kind: OptionKind.VIEWER,
|
||||
}
|
||||
};
|
||||
defaultOptions.renderer = {
|
||||
/** @type {string} */
|
||||
value: 'canvas',
|
||||
value: "canvas",
|
||||
kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
|
||||
}
|
||||
};
|
||||
defaultOptions.sandboxBundleSrc = {
|
||||
/** @type {string} */
|
||||
value:
|
||||
typeof PDFJSDev === 'undefined' || !PDFJSDev.test('PRODUCTION')
|
||||
? '../build/dev-sandbox/pdf.sandbox.js'
|
||||
: '../build/pdf.sandbox.js',
|
||||
typeof PDFJSDev === "undefined" || !PDFJSDev.test("PRODUCTION")
|
||||
? "../build/dev-sandbox/pdf.sandbox.js"
|
||||
: "../build/pdf.sandbox.js",
|
||||
kind: OptionKind.VIEWER,
|
||||
}
|
||||
} else if (PDFJSDev.test('CHROME')) {
|
||||
};
|
||||
} else if (PDFJSDev.test("CHROME")) {
|
||||
defaultOptions.defaultUrl = {
|
||||
/** @type {string} */
|
||||
value: '',
|
||||
value: "",
|
||||
kind: OptionKind.VIEWER,
|
||||
}
|
||||
};
|
||||
defaultOptions.disableTelemetry = {
|
||||
/** @type {boolean} */
|
||||
value: false,
|
||||
kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
|
||||
}
|
||||
};
|
||||
defaultOptions.sandboxBundleSrc = {
|
||||
/** @type {string} */
|
||||
value: '../build/pdf.sandbox.js',
|
||||
value: "../build/pdf.sandbox.js",
|
||||
kind: OptionKind.VIEWER,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const userOptions = Object.create(null)
|
||||
const userOptions = Object.create(null);
|
||||
|
||||
class AppOptions {
|
||||
constructor () {
|
||||
throw new Error('Cannot initialize AppOptions.')
|
||||
constructor() {
|
||||
throw new Error("Cannot initialize AppOptions.");
|
||||
}
|
||||
|
||||
static get (name) {
|
||||
const userOption = userOptions[name]
|
||||
static get(name) {
|
||||
const userOption = userOptions[name];
|
||||
if (userOption !== undefined) {
|
||||
return userOption
|
||||
return userOption;
|
||||
}
|
||||
const defaultOption = defaultOptions[name]
|
||||
const defaultOption = defaultOptions[name];
|
||||
if (defaultOption !== undefined) {
|
||||
return compatibilityParams[name] ?? defaultOption.value
|
||||
return compatibilityParams[name] ?? defaultOption.value;
|
||||
}
|
||||
return undefined
|
||||
return undefined;
|
||||
}
|
||||
|
||||
static getAll (kind = null) {
|
||||
const options = Object.create(null)
|
||||
static getAll(kind = null) {
|
||||
const options = Object.create(null);
|
||||
for (const name in defaultOptions) {
|
||||
const defaultOption = defaultOptions[name]
|
||||
const defaultOption = defaultOptions[name];
|
||||
if (kind) {
|
||||
if ((kind & defaultOption.kind) === 0) {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
if (kind === OptionKind.PREFERENCE) {
|
||||
const value = defaultOption.value,
|
||||
valueType = typeof value
|
||||
valueType = typeof value;
|
||||
|
||||
if (
|
||||
valueType === 'boolean' ||
|
||||
valueType === 'string' ||
|
||||
(valueType === 'number' && Number.isInteger(value))
|
||||
valueType === "boolean" ||
|
||||
valueType === "string" ||
|
||||
(valueType === "number" && Number.isInteger(value))
|
||||
) {
|
||||
options[name] = value
|
||||
continue
|
||||
options[name] = value;
|
||||
continue;
|
||||
}
|
||||
throw new Error(`Invalid type for preference: ${name}`)
|
||||
throw new Error(`Invalid type for preference: ${name}`);
|
||||
}
|
||||
}
|
||||
const userOption = userOptions[name]
|
||||
const userOption = userOptions[name];
|
||||
options[name] =
|
||||
userOption !== undefined
|
||||
? userOption
|
||||
: compatibilityParams[name] ?? defaultOption.value
|
||||
: compatibilityParams[name] ?? defaultOption.value;
|
||||
}
|
||||
return options
|
||||
return options;
|
||||
}
|
||||
|
||||
static set (name, value) {
|
||||
userOptions[name] = value
|
||||
static set(name, value) {
|
||||
userOptions[name] = value;
|
||||
}
|
||||
|
||||
static setAll (options) {
|
||||
static setAll(options) {
|
||||
for (const name in options) {
|
||||
userOptions[name] = options[name]
|
||||
userOptions[name] = options[name];
|
||||
}
|
||||
}
|
||||
|
||||
static remove (name) {
|
||||
delete userOptions[name]
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
static _hasUserOptions () {
|
||||
return Object.keys(userOptions).length > 0
|
||||
static remove(name) {
|
||||
delete userOptions[name];
|
||||
}
|
||||
}
|
||||
|
||||
export { AppOptions, compatibilityParams, OptionKind }
|
||||
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
|
||||
AppOptions._hasUserOptions = function () {
|
||||
return Object.keys(userOptions).length > 0;
|
||||
};
|
||||
}
|
||||
|
||||
export { AppOptions, compatibilityParams, OptionKind };
|
||||
|
|
|
|||
|
|
@ -75,9 +75,7 @@ function waitOnEventOrTimeout({ target, name, delay = 0 }) {
|
|||
* and `off` methods. To raise an event, the `dispatch` method shall be used.
|
||||
*/
|
||||
class EventBus {
|
||||
constructor() {
|
||||
this._listeners = Object.create(null);
|
||||
}
|
||||
#listeners = Object.create(null);
|
||||
|
||||
/**
|
||||
* @param {string} eventName
|
||||
|
|
@ -108,7 +106,7 @@ class EventBus {
|
|||
* @param {Object} data
|
||||
*/
|
||||
dispatch(eventName, data) {
|
||||
const eventListeners = this._listeners[eventName];
|
||||
const eventListeners = this.#listeners[eventName];
|
||||
if (!eventListeners || eventListeners.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -139,7 +137,7 @@ class EventBus {
|
|||
* @ignore
|
||||
*/
|
||||
_on(eventName, listener, options = null) {
|
||||
const eventListeners = (this._listeners[eventName] ||= []);
|
||||
const eventListeners = (this.#listeners[eventName] ||= []);
|
||||
eventListeners.push({
|
||||
listener,
|
||||
external: options?.external === true,
|
||||
|
|
@ -151,7 +149,7 @@ class EventBus {
|
|||
* @ignore
|
||||
*/
|
||||
_off(eventName, listener, options = null) {
|
||||
const eventListeners = this._listeners[eventName];
|
||||
const eventListeners = this.#listeners[eventName];
|
||||
if (!eventListeners) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,10 +14,8 @@
|
|||
*/
|
||||
|
||||
import { BasePreferences } from "./preferences.js";
|
||||
// NOTE
|
||||
// import { DownloadManager } from "./download_manager.js";
|
||||
import { GenericScripting } from "./generic_scripting.js";
|
||||
import { shadow } from './pdfjs'
|
||||
import {shadow} from "./pdfjs";
|
||||
|
||||
if (typeof PDFJSDev !== "undefined" && !PDFJSDev.test("GENERIC")) {
|
||||
throw new Error(
|
||||
|
|
@ -37,44 +35,48 @@ class GenericPreferences extends BasePreferences {
|
|||
}
|
||||
}
|
||||
|
||||
// NOTE
|
||||
class GenericExternalServices {
|
||||
constructor () {
|
||||
throw new Error('Cannot initialize DefaultExternalServices.')
|
||||
class DefaultExternalServices {
|
||||
constructor() {
|
||||
throw new Error("Cannot initialize DefaultExternalServices.");
|
||||
}
|
||||
|
||||
static updateFindControlState (data) {}
|
||||
static updateFindControlState(data) {}
|
||||
|
||||
static updateFindMatchesCount (data) {}
|
||||
static updateFindMatchesCount(data) {}
|
||||
|
||||
static initPassiveLoading (callbacks) {}
|
||||
static initPassiveLoading(callbacks) {}
|
||||
|
||||
static async fallback (data) {}
|
||||
static reportTelemetry(data) {}
|
||||
|
||||
static reportTelemetry (data) {}
|
||||
|
||||
static get supportsIntegratedFind () {
|
||||
return shadow(this, 'supportsIntegratedFind', false)
|
||||
static get supportsPinchToZoom() {
|
||||
return shadow(this, "supportsPinchToZoom", true);
|
||||
}
|
||||
|
||||
static get supportsDocumentFonts () {
|
||||
return shadow(this, 'supportsDocumentFonts', true)
|
||||
static get supportsIntegratedFind() {
|
||||
return shadow(this, "supportsIntegratedFind", false);
|
||||
}
|
||||
|
||||
static get supportedMouseWheelZoomModifierKeys () {
|
||||
return shadow(this, 'supportedMouseWheelZoomModifierKeys', {
|
||||
static get supportsDocumentFonts() {
|
||||
return shadow(this, "supportsDocumentFonts", true);
|
||||
}
|
||||
|
||||
static get supportedMouseWheelZoomModifierKeys() {
|
||||
return shadow(this, "supportedMouseWheelZoomModifierKeys", {
|
||||
ctrlKey: true,
|
||||
metaKey: true,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
static get isInAutomation () {
|
||||
return shadow(this, 'isInAutomation', false)
|
||||
static get isInAutomation() {
|
||||
return shadow(this, "isInAutomation", false);
|
||||
}
|
||||
|
||||
static createDownloadManager(options) {
|
||||
// NOTE
|
||||
// return new DownloadManager();
|
||||
static updateEditorStates(data) {
|
||||
throw new Error("Not implemented: updateEditorStates");
|
||||
}
|
||||
|
||||
static createDownloadManager() {
|
||||
// NOTE return new DownloadManager();
|
||||
}
|
||||
|
||||
static createPreferences() {
|
||||
|
|
@ -82,13 +84,15 @@ class GenericExternalServices {
|
|||
}
|
||||
|
||||
static createL10n({ locale = "en-US" }) {
|
||||
// NOTE
|
||||
// return new GenericL10n(locale);
|
||||
// NOTE return new GenericL10n(locale);
|
||||
}
|
||||
|
||||
static createScripting({ sandboxBundleSrc }) {
|
||||
return new GenericScripting(sandboxBundleSrc);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE
|
||||
export { GenericCom, GenericExternalServices };
|
||||
// PDFViewerApplication.externalServices = GenericExternalServices;
|
||||
|
||||
export { GenericCom, DefaultExternalServices };
|
||||
|
|
|
|||
|
|
@ -38,12 +38,6 @@ const DEFAULT_L10N_STRINGS = {
|
|||
document_properties_linearized_yes: "Yes",
|
||||
document_properties_linearized_no: "No",
|
||||
|
||||
print_progress_percent: "{{progress}}%",
|
||||
|
||||
"toggle_sidebar.title": "Toggle Sidebar",
|
||||
"toggle_sidebar_notification2.title":
|
||||
"Toggle Sidebar (document contains outline/attachments/layers)",
|
||||
|
||||
additional_layers: "Additional Layers",
|
||||
page_landmark: "Page {{page}}",
|
||||
thumb_page_title: "Page {{page}}",
|
||||
|
|
@ -57,24 +51,17 @@ const DEFAULT_L10N_STRINGS = {
|
|||
"find_match_count_limit[other]": "More than {{limit}} matches",
|
||||
find_not_found: "Phrase not found",
|
||||
|
||||
error_version_info: "PDF.js v{{version}} (build: {{build}})",
|
||||
error_message: "Message: {{message}}",
|
||||
error_stack: "Stack: {{stack}}",
|
||||
error_file: "File: {{file}}",
|
||||
error_line: "Line: {{line}}",
|
||||
rendering_error: "An error occurred while rendering the page.",
|
||||
|
||||
page_scale_width: "Page Width",
|
||||
page_scale_fit: "Page Fit",
|
||||
page_scale_auto: "Automatic Zoom",
|
||||
page_scale_actual: "Actual Size",
|
||||
page_scale_percent: "{{scale}}%",
|
||||
|
||||
loading: "Loading…",
|
||||
loading_error: "An error occurred while loading the PDF.",
|
||||
invalid_file_error: "Invalid or corrupted PDF file.",
|
||||
missing_file_error: "Missing PDF file.",
|
||||
unexpected_response_error: "Unexpected server response.",
|
||||
rendering_error: "An error occurred while rendering the page.",
|
||||
|
||||
printing_not_supported:
|
||||
"Warning: Printing is not fully supported by this browser.",
|
||||
|
|
@ -87,6 +74,9 @@ const DEFAULT_L10N_STRINGS = {
|
|||
editor_ink2_aria_label: "Draw Editor",
|
||||
editor_ink_canvas_aria_label: "User-created image",
|
||||
};
|
||||
if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("MOZCENTRAL")) {
|
||||
DEFAULT_L10N_STRINGS.print_progress_percent = "{{progress}}%";
|
||||
}
|
||||
|
||||
function getL10nFallback(key, args) {
|
||||
switch (key) {
|
||||
|
|
|
|||
|
|
@ -85,9 +85,7 @@ class PasswordPrompt {
|
|||
this.input.focus();
|
||||
}
|
||||
// NOTE
|
||||
this.label.textContent = window.siyuan.languages[`password_${passwordIncorrect
|
||||
? 'invalid'
|
||||
: 'label'}`]
|
||||
this.label.textContent = window.siyuan.languages[`password_${passwordIncorrect ? 'invalid' : 'label'}`]
|
||||
}
|
||||
|
||||
async close() {
|
||||
|
|
|
|||
|
|
@ -118,7 +118,10 @@ class PDFAttachmentViewer extends BaseTreeViewer {
|
|||
for (const name of names) {
|
||||
const item = attachments[name];
|
||||
const content = item.content,
|
||||
filename = getFilenameFromUrl(item.filename);
|
||||
filename = getFilenameFromUrl(
|
||||
item.filename,
|
||||
/* onlyStripPath = */ true
|
||||
);
|
||||
|
||||
const div = document.createElement("div");
|
||||
div.className = "treeItem";
|
||||
|
|
|
|||
|
|
@ -13,15 +13,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { CursorTool, PresentationModeState } from "./ui_utils.js";
|
||||
import { AnnotationEditorType } from "./pdfjs";
|
||||
import { GrabToPan } from "./grab_to_pan.js";
|
||||
import { PresentationModeState } from "./ui_utils.js";
|
||||
|
||||
const CursorTool = {
|
||||
SELECT: 0, // The default value.
|
||||
HAND: 1,
|
||||
ZOOM: 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {Object} PDFCursorToolsOptions
|
||||
|
|
@ -175,4 +169,4 @@ class PDFCursorTools {
|
|||
}
|
||||
}
|
||||
|
||||
export { CursorTool, PDFCursorTools };
|
||||
export { PDFCursorTools };
|
||||
|
|
|
|||
|
|
@ -239,11 +239,9 @@ class PDFDocumentProperties {
|
|||
}
|
||||
// NOTE
|
||||
if (mb >= 1) {
|
||||
return `${mb >= 1 && (+mb.toPrecision(
|
||||
3)).toLocaleString()} MB ${fileSize.toLocaleString()} bytes`
|
||||
return `${mb >= 1 && (+mb.toPrecision(3)).toLocaleString()} MB ${fileSize.toLocaleString()} bytes`
|
||||
}
|
||||
return `${mb < 1 && (+kb.toPrecision(
|
||||
3)).toLocaleString()} KB (${fileSize.toLocaleString()} bytes`
|
||||
return `${mb < 1 && (+kb.toPrecision(3)).toLocaleString()} KB (${fileSize.toLocaleString()} bytes`
|
||||
}
|
||||
|
||||
async #parsePageSize(pageSizeInches, pagesRotation) {
|
||||
|
|
@ -313,15 +311,11 @@ class PDFDocumentProperties {
|
|||
// NOTE
|
||||
const [{ width, height }, unit, name, orientation] = await Promise.all([
|
||||
this._isNonMetricLocale ? sizeInches : sizeMillimeters,
|
||||
this._isNonMetricLocale
|
||||
? window.siyuan.languages.unitInches
|
||||
: window.siyuan.languages.unitMillimeters,
|
||||
this._isNonMetricLocale ? window.siyuan.languages.unitInches : window.siyuan.languages.unitMillimeters,
|
||||
rawName &&
|
||||
window.siyuan.languages[`document_properties_page_size_name_${rawName.toLowerCase()}`],
|
||||
window.siyuan.languages[`document_properties_page_size_orientation_${isPortrait
|
||||
? 'portrait'
|
||||
: 'landscape'}`],
|
||||
])
|
||||
window.siyuan.languages[`document_properties_page_size_orientation_${isPortrait ? 'portrait' : 'landscape'}`],
|
||||
]);
|
||||
if (name) {
|
||||
return `${width.toLocaleString()} × ${height.toLocaleString()} ${unit} (${name}, ${orientation})`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,9 +149,8 @@ class PDFFindBar {
|
|||
status = "notFound";
|
||||
break;
|
||||
case FindState.WRAPPED:
|
||||
findMsg = window.siyuan.languages.find_not_found[`find_reached_${previous
|
||||
? 'top'
|
||||
: 'bottom'}`]
|
||||
// NOTE
|
||||
findMsg = window.siyuan.languages.find_not_found[`find_reached_${previous ? 'top' : 'bottom'}`]
|
||||
break;
|
||||
}
|
||||
this.findField.setAttribute("data-status", status);
|
||||
|
|
@ -165,7 +164,7 @@ class PDFFindBar {
|
|||
|
||||
updateResultsCount({ current = 0, total = 0 } = {}) {
|
||||
const limit = MATCHES_COUNT_LIMIT;
|
||||
// // NOTE
|
||||
// NOTE
|
||||
let matchCountMsg = "";
|
||||
|
||||
if (total > 0) {
|
||||
|
|
|
|||
|
|
@ -76,9 +76,7 @@ const DIACRITICS_EXCEPTION = new Set([
|
|||
// https://www.compart.com/fr/unicode/combining/132
|
||||
0x0f74,
|
||||
]);
|
||||
const DIACRITICS_EXCEPTION_STR = [...DIACRITICS_EXCEPTION.values()]
|
||||
.map(x => String.fromCharCode(x))
|
||||
.join("");
|
||||
let DIACRITICS_EXCEPTION_STR; // Lazily initialized, see below.
|
||||
|
||||
const DIACRITICS_REG_EXP = /\p{M}+/gu;
|
||||
const SPECIAL_CHARS_REG_EXP =
|
||||
|
|
@ -95,6 +93,8 @@ const SYLLABLES_LENGTHS = new Map();
|
|||
const FIRST_CHAR_SYLLABLES_REG_EXP =
|
||||
"[\\u1100-\\u1112\\ud7a4-\\ud7af\\ud84a\\ud84c\\ud850\\ud854\\ud857\\ud85f]";
|
||||
|
||||
const NFKC_CHARS_TO_NORMALIZE = new Map();
|
||||
|
||||
let noSyllablesRegExp = null;
|
||||
let withSyllablesRegExp = null;
|
||||
|
||||
|
|
@ -126,7 +126,18 @@ function normalize(text) {
|
|||
} else {
|
||||
// Compile the regular expression for text normalization once.
|
||||
const replace = Object.keys(CHARACTERS_TO_NORMALIZE).join("");
|
||||
const regexp = `([${replace}])|(\\p{M}+(?:-\\n)?)|(\\S-\\n)|(\\p{Ideographic}\\n)|(\\n)`;
|
||||
const toNormalizeWithNFKC =
|
||||
"\u2460-\u2473" + // Circled numbers.
|
||||
"\u24b6-\u24ff" + // Circled letters/numbers.
|
||||
"\u3244-\u32bf" + // Circled ideograms/numbers.
|
||||
"\u32d0-\u32fe" + // Circled ideograms.
|
||||
"\uff00-\uffef"; // Halfwidth, fullwidth forms.
|
||||
|
||||
// 3040-309F: Hiragana
|
||||
// 30A0-30FF: Katakana
|
||||
const CJK = "(?:\\p{Ideographic}|[\u3040-\u30FF])";
|
||||
const HKDiacritics = "(?:\u3099|\u309A)";
|
||||
const regexp = `([${replace}])|([${toNormalizeWithNFKC}])|(${HKDiacritics}\\n)|(\\p{M}+(?:-\\n)?)|(\\S-\\n)|(${CJK}\\n)|(\\n)`;
|
||||
|
||||
if (syllablePositions.length === 0) {
|
||||
// Most of the syllables belong to Hangul so there are no need
|
||||
|
|
@ -188,11 +199,11 @@ function normalize(text) {
|
|||
|
||||
normalized = normalized.replace(
|
||||
normalizationRegex,
|
||||
(match, p1, p2, p3, p4, p5, p6, i) => {
|
||||
(match, p1, p2, p3, p4, p5, p6, p7, p8, i) => {
|
||||
i -= shiftOrigin;
|
||||
if (p1) {
|
||||
// Maybe fractions or quotations mark...
|
||||
const replacement = CHARACTERS_TO_NORMALIZE[match];
|
||||
const replacement = CHARACTERS_TO_NORMALIZE[p1];
|
||||
const jj = replacement.length;
|
||||
for (let j = 1; j < jj; j++) {
|
||||
positions.push([i - shift + j, shift - j]);
|
||||
|
|
@ -202,8 +213,47 @@ function normalize(text) {
|
|||
}
|
||||
|
||||
if (p2) {
|
||||
const hasTrailingDashEOL = p2.endsWith("\n");
|
||||
const len = hasTrailingDashEOL ? p2.length - 2 : p2.length;
|
||||
// Use the NFKC representation to normalize the char.
|
||||
let replacement = NFKC_CHARS_TO_NORMALIZE.get(p2);
|
||||
if (!replacement) {
|
||||
replacement = p2.normalize("NFKC");
|
||||
NFKC_CHARS_TO_NORMALIZE.set(p2, replacement);
|
||||
}
|
||||
const jj = replacement.length;
|
||||
for (let j = 1; j < jj; j++) {
|
||||
positions.push([i - shift + j, shift - j]);
|
||||
}
|
||||
shift -= jj - 1;
|
||||
return replacement;
|
||||
}
|
||||
|
||||
if (p3) {
|
||||
// We've a Katakana-Hiragana diacritic followed by a \n so don't replace
|
||||
// the \n by a whitespace.
|
||||
hasDiacritics = true;
|
||||
|
||||
// Diacritic.
|
||||
if (i + eol === rawDiacriticsPositions[rawDiacriticsIndex]?.[1]) {
|
||||
++rawDiacriticsIndex;
|
||||
} else {
|
||||
// i is the position of the first diacritic
|
||||
// so (i - 1) is the position for the letter before.
|
||||
positions.push([i - 1 - shift + 1, shift - 1]);
|
||||
shift -= 1;
|
||||
shiftOrigin += 1;
|
||||
}
|
||||
|
||||
// End-of-line.
|
||||
positions.push([i - shift + 1, shift]);
|
||||
shiftOrigin += 1;
|
||||
eol += 1;
|
||||
|
||||
return p3.charAt(0);
|
||||
}
|
||||
|
||||
if (p4) {
|
||||
const hasTrailingDashEOL = p4.endsWith("\n");
|
||||
const len = hasTrailingDashEOL ? p4.length - 2 : p4.length;
|
||||
|
||||
// Diacritics.
|
||||
hasDiacritics = true;
|
||||
|
|
@ -223,19 +273,19 @@ function normalize(text) {
|
|||
|
||||
if (hasTrailingDashEOL) {
|
||||
// Diacritics are followed by a -\n.
|
||||
// See comments in `if (p3)` block.
|
||||
// See comments in `if (p5)` block.
|
||||
i += len - 1;
|
||||
positions.push([i - shift + 1, 1 + shift]);
|
||||
shift += 1;
|
||||
shiftOrigin += 1;
|
||||
eol += 1;
|
||||
return p2.slice(0, len);
|
||||
return p4.slice(0, len);
|
||||
}
|
||||
|
||||
return p2;
|
||||
return p4;
|
||||
}
|
||||
|
||||
if (p3) {
|
||||
if (p5) {
|
||||
// "X-\n" is removed because an hyphen at the end of a line
|
||||
// with not a space before is likely here to mark a break
|
||||
// in a word.
|
||||
|
|
@ -244,19 +294,19 @@ function normalize(text) {
|
|||
shift += 1;
|
||||
shiftOrigin += 1;
|
||||
eol += 1;
|
||||
return p3.charAt(0);
|
||||
return p5.charAt(0);
|
||||
}
|
||||
|
||||
if (p4) {
|
||||
if (p6) {
|
||||
// An ideographic at the end of a line doesn't imply adding an extra
|
||||
// white space.
|
||||
positions.push([i - shift + 1, shift]);
|
||||
shiftOrigin += 1;
|
||||
eol += 1;
|
||||
return p4.charAt(0);
|
||||
return p6.charAt(0);
|
||||
}
|
||||
|
||||
if (p5) {
|
||||
if (p7) {
|
||||
// eol is replaced by space: "foo\nbar" is likely equivalent to
|
||||
// "foo bar".
|
||||
positions.push([i - shift + 1, shift - 1]);
|
||||
|
|
@ -266,7 +316,7 @@ function normalize(text) {
|
|||
return " ";
|
||||
}
|
||||
|
||||
// p6
|
||||
// p8
|
||||
if (i + eol === syllablePositions[syllableIndex]?.[1]) {
|
||||
// A syllable (1 char) is replaced with several chars (n) so
|
||||
// newCharsLen = n - 1.
|
||||
|
|
@ -278,7 +328,7 @@ function normalize(text) {
|
|||
shift -= newCharLen;
|
||||
shiftOrigin += newCharLen;
|
||||
}
|
||||
return p6;
|
||||
return p8;
|
||||
}
|
||||
);
|
||||
|
||||
|
|
@ -314,18 +364,26 @@ function getOriginalIndex(diffs, pos, len) {
|
|||
* @typedef {Object} PDFFindControllerOptions
|
||||
* @property {IPDFLinkService} linkService - The navigation/linking service.
|
||||
* @property {EventBus} eventBus - The application event bus.
|
||||
* @property {boolean} updateMatchesCountOnProgress - True if the matches
|
||||
* count must be updated on progress or only when the last page is reached.
|
||||
* The default value is `true`.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides search functionality to find a given string in a PDF document.
|
||||
*/
|
||||
class PDFFindController {
|
||||
#updateMatchesCountOnProgress = true;
|
||||
|
||||
#visitedPagesCount = 0;
|
||||
|
||||
/**
|
||||
* @param {PDFFindControllerOptions} options
|
||||
*/
|
||||
constructor({ linkService, eventBus }) {
|
||||
constructor({ linkService, eventBus, updateMatchesCountOnProgress = true }) {
|
||||
this._linkService = linkService;
|
||||
this._eventBus = eventBus;
|
||||
this.#updateMatchesCountOnProgress = updateMatchesCountOnProgress;
|
||||
|
||||
this.#reset();
|
||||
eventBus._on("find", this.#onFind.bind(this));
|
||||
|
|
@ -464,6 +522,7 @@ class PDFFindController {
|
|||
this._pdfDocument = null;
|
||||
this._pageMatches = [];
|
||||
this._pageMatchesLength = [];
|
||||
this.#visitedPagesCount = 0;
|
||||
this._state = null;
|
||||
// Currently selected match.
|
||||
this._selected = {
|
||||
|
|
@ -566,9 +625,13 @@ class PDFFindController {
|
|||
}
|
||||
|
||||
#calculateRegExpMatch(query, entireWord, pageIndex, pageContent) {
|
||||
const matches = [],
|
||||
matchesLength = [];
|
||||
|
||||
const matches = (this._pageMatches[pageIndex] = []);
|
||||
const matchesLength = (this._pageMatchesLength[pageIndex] = []);
|
||||
if (!query) {
|
||||
// The query can be empty because some chars like diacritics could have
|
||||
// been stripped out.
|
||||
return;
|
||||
}
|
||||
const diffs = this._pageDiffs[pageIndex];
|
||||
let match;
|
||||
while ((match = query.exec(pageContent)) !== null) {
|
||||
|
|
@ -590,8 +653,6 @@ class PDFFindController {
|
|||
matchesLength.push(matchLen);
|
||||
}
|
||||
}
|
||||
this._pageMatches[pageIndex] = matches;
|
||||
this._pageMatchesLength[pageIndex] = matchesLength;
|
||||
}
|
||||
|
||||
#convertToRegExpString(query, hasDiacritics) {
|
||||
|
|
@ -652,6 +713,10 @@ class PDFFindController {
|
|||
if (matchDiacritics) {
|
||||
// aX must not match aXY.
|
||||
if (hasDiacritics) {
|
||||
DIACRITICS_EXCEPTION_STR ||= String.fromCharCode(
|
||||
...DIACRITICS_EXCEPTION
|
||||
);
|
||||
|
||||
isUnicode = true;
|
||||
query = `${query}(?=[${DIACRITICS_EXCEPTION_STR}]|[^\\p{M}]|$)`;
|
||||
}
|
||||
|
|
@ -662,7 +727,7 @@ class PDFFindController {
|
|||
|
||||
#calculateMatch(pageIndex) {
|
||||
let query = this.#query;
|
||||
if (query.length === 0) {
|
||||
if (!query) {
|
||||
// Do nothing: the matches should be wiped out already.
|
||||
return;
|
||||
}
|
||||
|
|
@ -695,7 +760,7 @@ class PDFFindController {
|
|||
}
|
||||
|
||||
const flags = `g${isUnicode ? "u" : ""}${caseSensitive ? "" : "i"}`;
|
||||
query = new RegExp(query, flags);
|
||||
query = query ? new RegExp(query, flags) : null;
|
||||
|
||||
this.#calculateRegExpMatch(query, entireWord, pageIndex, pageContent);
|
||||
|
||||
|
|
@ -711,8 +776,14 @@ class PDFFindController {
|
|||
|
||||
// Update the match count.
|
||||
const pageMatchesCount = this._pageMatches[pageIndex].length;
|
||||
if (pageMatchesCount > 0) {
|
||||
this._matchesCountTotal += pageMatchesCount;
|
||||
this._matchesCountTotal += pageMatchesCount;
|
||||
if (this.#updateMatchesCountOnProgress) {
|
||||
if (pageMatchesCount > 0) {
|
||||
this.#updateUIResultsCount();
|
||||
}
|
||||
} else if (++this.#visitedPagesCount === this._linkService.pagesCount) {
|
||||
// For example, in GeckoView we want to have only the final update because
|
||||
// the Java side provides only one object to update the counts.
|
||||
this.#updateUIResultsCount();
|
||||
}
|
||||
}
|
||||
|
|
@ -807,6 +878,7 @@ class PDFFindController {
|
|||
this._resumePageIdx = null;
|
||||
this._pageMatches.length = 0;
|
||||
this._pageMatchesLength.length = 0;
|
||||
this.#visitedPagesCount = 0;
|
||||
this._matchesCountTotal = 0;
|
||||
|
||||
this.#updateAllPages(); // Wipe out any previously highlighted matches.
|
||||
|
|
@ -825,7 +897,7 @@ class PDFFindController {
|
|||
}
|
||||
|
||||
// If there's no query there's no point in searching.
|
||||
if (this.#query === "") {
|
||||
if (!this.#query) {
|
||||
this.#updateUIState(FindState.FOUND);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1005,6 +1077,16 @@ class PDFFindController {
|
|||
}
|
||||
|
||||
#updateUIState(state, previous = false) {
|
||||
if (
|
||||
!this.#updateMatchesCountOnProgress &&
|
||||
(this.#visitedPagesCount !== this._linkService.pagesCount ||
|
||||
state === FindState.PENDING)
|
||||
) {
|
||||
// When this.#updateMatchesCountOnProgress is false we only send an update
|
||||
// when everything is ready.
|
||||
return;
|
||||
}
|
||||
|
||||
this._eventBus.dispatch("updatefindcontrolstate", {
|
||||
source: this,
|
||||
state,
|
||||
|
|
|
|||
|
|
@ -173,6 +173,13 @@ class PDFLinkService {
|
|||
this.pdfViewer.pagesRotation = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isInPresentationMode() {
|
||||
return this.pdfViewer.isInPresentationMode;
|
||||
}
|
||||
|
||||
#goToDestinationHelper(rawDest, namedDest = null, explicitDest) {
|
||||
// Dest array looks like that: <page-ref> </XYZ|/FitXXX> <args..>
|
||||
const destRef = explicitDest[0];
|
||||
|
|
@ -673,6 +680,13 @@ class SimpleLinkService {
|
|||
*/
|
||||
set rotation(value) {}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isInPresentationMode() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string|Array} dest - The named, or explicit, PDF destination.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -20,8 +20,9 @@ import { SidebarView } from "./ui_utils.js";
|
|||
/**
|
||||
* @typedef {Object} PDFOutlineViewerOptions
|
||||
* @property {HTMLDivElement} container - The viewer element.
|
||||
* @property {IPDFLinkService} linkService - The navigation/linking service.
|
||||
* @property {EventBus} eventBus - The application event bus.
|
||||
* @property {IPDFLinkService} linkService - The navigation/linking service.
|
||||
* @property {DownloadManager} downloadManager - The download manager.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
@ -37,6 +38,7 @@ class PDFOutlineViewer extends BaseTreeViewer {
|
|||
constructor(options) {
|
||||
super(options);
|
||||
this.linkService = options.linkService;
|
||||
this.downloadManager = options.downloadManager;
|
||||
|
||||
this.eventBus._on("toggleoutlinetree", this._toggleAllTreeItems.bind(this));
|
||||
this.eventBus._on(
|
||||
|
|
@ -109,7 +111,10 @@ class PDFOutlineViewer extends BaseTreeViewer {
|
|||
/**
|
||||
* @private
|
||||
*/
|
||||
_bindLink(element, { url, newWindow, action, dest, setOCGState }) {
|
||||
_bindLink(
|
||||
element,
|
||||
{ url, newWindow, action, attachment, dest, setOCGState }
|
||||
) {
|
||||
const { linkService } = this;
|
||||
|
||||
if (url) {
|
||||
|
|
@ -124,6 +129,18 @@ class PDFOutlineViewer extends BaseTreeViewer {
|
|||
};
|
||||
return;
|
||||
}
|
||||
if (attachment) {
|
||||
element.href = linkService.getAnchorUrl("");
|
||||
element.onclick = () => {
|
||||
this.downloadManager.openOrDownloadData(
|
||||
element,
|
||||
attachment.content,
|
||||
attachment.filename
|
||||
);
|
||||
return false;
|
||||
};
|
||||
return;
|
||||
}
|
||||
if (setOCGState) {
|
||||
element.href = linkService.getAnchorUrl("");
|
||||
element.onclick = () => {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -224,21 +224,24 @@ class PDFPresentationMode {
|
|||
evt.preventDefault();
|
||||
return;
|
||||
}
|
||||
if (evt.button === 0) {
|
||||
// Enable clicking of links in presentation mode. Note: only links
|
||||
// pointing to destinations in the current PDF document work.
|
||||
const isInternalLink =
|
||||
evt.target.href && evt.target.classList.contains("internalLink");
|
||||
if (!isInternalLink) {
|
||||
// Unless an internal link was clicked, advance one page.
|
||||
evt.preventDefault();
|
||||
if (evt.button !== 0) {
|
||||
return;
|
||||
}
|
||||
// Enable clicking of links in presentation mode. Note: only links
|
||||
// pointing to destinations in the current PDF document work.
|
||||
if (
|
||||
evt.target.href &&
|
||||
evt.target.parentNode?.hasAttribute("data-internal-link")
|
||||
) {
|
||||
return;
|
||||
}
|
||||
// Unless an internal link was clicked, advance one page.
|
||||
evt.preventDefault();
|
||||
|
||||
if (evt.shiftKey) {
|
||||
this.pdfViewer.previousPage();
|
||||
} else {
|
||||
this.pdfViewer.nextPage();
|
||||
}
|
||||
}
|
||||
if (evt.shiftKey) {
|
||||
this.pdfViewer.previousPage();
|
||||
} else {
|
||||
this.pdfViewer.nextPage();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ class PDFScriptingManager {
|
|||
this._destroyCapability = null;
|
||||
|
||||
this._scripting = null;
|
||||
this._mouseState = Object.create(null);
|
||||
this._ready = false;
|
||||
|
||||
this._eventBus = eventBus;
|
||||
|
|
@ -143,19 +142,9 @@ class PDFScriptingManager {
|
|||
this._closeCapability?.resolve();
|
||||
});
|
||||
|
||||
this._domEvents.set("mousedown", event => {
|
||||
this._mouseState.isDown = true;
|
||||
});
|
||||
this._domEvents.set("mouseup", event => {
|
||||
this._mouseState.isDown = false;
|
||||
});
|
||||
|
||||
for (const [name, listener] of this._internalEvents) {
|
||||
this._eventBus._on(name, listener);
|
||||
}
|
||||
for (const [name, listener] of this._domEvents) {
|
||||
window.addEventListener(name, listener, true);
|
||||
}
|
||||
|
||||
try {
|
||||
const docProperties = await this._getDocProperties();
|
||||
|
|
@ -229,10 +218,6 @@ class PDFScriptingManager {
|
|||
});
|
||||
}
|
||||
|
||||
get mouseState() {
|
||||
return this._mouseState;
|
||||
}
|
||||
|
||||
get destroyPromise() {
|
||||
return this._destroyCapability?.promise || null;
|
||||
}
|
||||
|
|
@ -248,13 +233,6 @@ class PDFScriptingManager {
|
|||
return shadow(this, "_internalEvents", new Map());
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
get _domEvents() {
|
||||
return shadow(this, "_domEvents", new Map());
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
|
|
@ -287,13 +265,21 @@ class PDFScriptingManager {
|
|||
case "error":
|
||||
console.error(value);
|
||||
break;
|
||||
case "layout":
|
||||
if (isInPresentationMode) {
|
||||
case "layout": {
|
||||
// NOTE: Always ignore the pageLayout in GeckoView since there's
|
||||
// no UI available to change Scroll/Spread modes for the user.
|
||||
if (
|
||||
(typeof PDFJSDev === "undefined"
|
||||
? window.isGECKOVIEW
|
||||
: PDFJSDev.test("GECKOVIEW")) ||
|
||||
isInPresentationMode
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const modes = apiPageLayoutToViewerModes(value);
|
||||
this._pdfViewer.spreadMode = modes.spreadMode;
|
||||
break;
|
||||
}
|
||||
case "page-num":
|
||||
this._pdfViewer.currentPageNumber = value + 1;
|
||||
break;
|
||||
|
|
@ -508,16 +494,10 @@ class PDFScriptingManager {
|
|||
}
|
||||
this._internalEvents.clear();
|
||||
|
||||
for (const [name, listener] of this._domEvents) {
|
||||
window.removeEventListener(name, listener, true);
|
||||
}
|
||||
this._domEvents.clear();
|
||||
|
||||
this._pageOpenPending.clear();
|
||||
this._visitedPages.clear();
|
||||
|
||||
this._scripting = null;
|
||||
delete this._mouseState.isDown;
|
||||
this._ready = false;
|
||||
|
||||
this._destroyCapability?.resolve();
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
*/
|
||||
|
||||
/** @typedef {import("../src/display/api").PDFDocumentProxy} PDFDocumentProxy */
|
||||
/** @typedef {import("./event_utils").EventBus} EventBus */
|
||||
/** @typedef {import("./interfaces").IL10n} IL10n */
|
||||
/** @typedef {import("./interfaces").IPDFLinkService} IPDFLinkService */
|
||||
// eslint-disable-next-line max-len
|
||||
|
|
@ -36,7 +35,6 @@ const THUMBNAIL_SELECTED_CLASS = "selected";
|
|||
* @typedef {Object} PDFThumbnailViewerOptions
|
||||
* @property {HTMLDivElement} container - The container for the thumbnail
|
||||
* elements.
|
||||
* @property {EventBus} eventBus - The application event bus.
|
||||
* @property {IPDFLinkService} linkService - The navigation/linking service.
|
||||
* @property {PDFRenderingQueue} renderingQueue - The rendering queue object.
|
||||
* @property {IL10n} l10n - Localization service.
|
||||
|
|
@ -52,14 +50,7 @@ class PDFThumbnailViewer {
|
|||
/**
|
||||
* @param {PDFThumbnailViewerOptions} options
|
||||
*/
|
||||
constructor({
|
||||
container,
|
||||
eventBus,
|
||||
linkService,
|
||||
renderingQueue,
|
||||
l10n,
|
||||
pageColors,
|
||||
}) {
|
||||
constructor({ container, linkService, renderingQueue, l10n, pageColors }) {
|
||||
this.container = container;
|
||||
this.linkService = linkService;
|
||||
this.renderingQueue = renderingQueue;
|
||||
|
|
|
|||
|
|
@ -22,18 +22,7 @@
|
|||
/** @typedef {import("./event_utils").EventBus} EventBus */
|
||||
/** @typedef {import("./interfaces").IDownloadManager} IDownloadManager */
|
||||
/** @typedef {import("./interfaces").IL10n} IL10n */
|
||||
// eslint-disable-next-line max-len
|
||||
/** @typedef {import("./interfaces").IPDFAnnotationLayerFactory} IPDFAnnotationLayerFactory */
|
||||
// eslint-disable-next-line max-len
|
||||
/** @typedef {import("./interfaces").IPDFAnnotationEditorLayerFactory} IPDFAnnotationEditorLayerFactory */
|
||||
/** @typedef {import("./interfaces").IPDFLinkService} IPDFLinkService */
|
||||
// eslint-disable-next-line max-len
|
||||
/** @typedef {import("./interfaces").IPDFStructTreeLayerFactory} IPDFStructTreeLayerFactory */
|
||||
// eslint-disable-next-line max-len
|
||||
/** @typedef {import("./interfaces").IPDFTextLayerFactory} IPDFTextLayerFactory */
|
||||
/** @typedef {import("./interfaces").IPDFXfaLayerFactory} IPDFXfaLayerFactory */
|
||||
// eslint-disable-next-line max-len
|
||||
/** @typedef {import("./text_accessibility.js").TextAccessibilityManager} TextAccessibilityManager */
|
||||
|
||||
import {
|
||||
AnnotationEditorType,
|
||||
|
|
@ -69,16 +58,10 @@ import {
|
|||
VERTICAL_PADDING,
|
||||
watchScroll,
|
||||
} from "./ui_utils.js";
|
||||
import { AnnotationEditorLayerBuilder } from "./annotation_editor_layer_builder.js";
|
||||
import { AnnotationLayerBuilder } from "./annotation_layer_builder.js";
|
||||
import { NullL10n } from "./l10n_utils.js";
|
||||
import { PDFPageView } from "./pdf_page_view.js";
|
||||
import { PDFRenderingQueue } from "./pdf_rendering_queue.js";
|
||||
import { SimpleLinkService } from "./pdf_link_service.js";
|
||||
import { StructTreeLayerBuilder } from "./struct_tree_layer_builder.js";
|
||||
import { TextHighlighter } from "./text_highlighter.js";
|
||||
import { TextLayerBuilder } from "./text_layer_builder.js";
|
||||
import { XfaLayerBuilder } from "./xfa_layer_builder.js";
|
||||
|
||||
const DEFAULT_CACHE_SIZE = 10;
|
||||
const ENABLE_PERMISSIONS_CLASS = "enablePermissions";
|
||||
|
|
@ -128,6 +111,8 @@ function isValidAnnotationEditorMode(mode) {
|
|||
* landscape pages upon printing. The default is `false`.
|
||||
* @property {boolean} [useOnlyCssZoom] - Enables CSS only zooming. The default
|
||||
* value is `false`.
|
||||
* @property {boolean} [isOffscreenCanvasSupported] - Allows to use an
|
||||
* OffscreenCanvas if needed.
|
||||
* @property {number} [maxCanvasPixels] - The maximum supported canvas size in
|
||||
* total pixels, i.e. width * height. Use -1 for no limit. The default value
|
||||
* is 4096 * 4096 (16 mega-pixels).
|
||||
|
|
@ -209,12 +194,6 @@ class PDFPageViewBuffer {
|
|||
|
||||
/**
|
||||
* Simple viewer control to display PDF content/pages.
|
||||
*
|
||||
* @implements {IPDFAnnotationLayerFactory}
|
||||
* @implements {IPDFAnnotationEditorLayerFactory}
|
||||
* @implements {IPDFStructTreeLayerFactory}
|
||||
* @implements {IPDFTextLayerFactory}
|
||||
* @implements {IPDFXfaLayerFactory}
|
||||
*/
|
||||
class PDFViewer {
|
||||
#buffer = null;
|
||||
|
|
@ -225,14 +204,20 @@ class PDFViewer {
|
|||
|
||||
#annotationMode = AnnotationMode.ENABLE_FORMS;
|
||||
|
||||
#containerTopLeft = null;
|
||||
|
||||
#enablePermissions = false;
|
||||
|
||||
#previousContainerHeight = 0;
|
||||
|
||||
#resizeObserver = new ResizeObserver(this.#resizeObserverCallback.bind(this));
|
||||
|
||||
#scrollModePageState = null;
|
||||
|
||||
#onVisibilityChange = null;
|
||||
|
||||
#scaleTimeoutId = null;
|
||||
|
||||
/**
|
||||
* @param {PDFViewerOptions} options
|
||||
*/
|
||||
|
|
@ -252,12 +237,7 @@ class PDFViewer {
|
|||
typeof PDFJSDev === "undefined" ||
|
||||
PDFJSDev.test("!PRODUCTION || GENERIC")
|
||||
) {
|
||||
if (
|
||||
!(
|
||||
this.container?.tagName.toUpperCase() === "DIV" &&
|
||||
this.viewer?.tagName.toUpperCase() === "DIV"
|
||||
)
|
||||
) {
|
||||
if (this.container?.tagName !== "DIV" || this.viewer?.tagName !== "DIV") {
|
||||
throw new Error("Invalid `container` and/or `viewer` option.");
|
||||
}
|
||||
|
||||
|
|
@ -268,12 +248,13 @@ class PDFViewer {
|
|||
throw new Error("The `container` must be absolutely positioned.");
|
||||
}
|
||||
}
|
||||
this.#resizeObserver.observe(this.container);
|
||||
|
||||
this.eventBus = options.eventBus;
|
||||
this.linkService = options.linkService || new SimpleLinkService();
|
||||
this.downloadManager = options.downloadManager || null;
|
||||
this.findController = options.findController || null;
|
||||
this._scriptingManager = options.scriptingManager || null;
|
||||
this.removePageBorders = options.removePageBorders || false;
|
||||
this.textLayerMode = options.textLayerMode ?? TextLayerMode.ENABLE;
|
||||
this.#annotationMode =
|
||||
options.annotationMode ?? AnnotationMode.ENABLE_FORMS;
|
||||
|
|
@ -285,9 +266,12 @@ class PDFViewer {
|
|||
typeof PDFJSDev === "undefined" ||
|
||||
PDFJSDev.test("!PRODUCTION || GENERIC")
|
||||
) {
|
||||
this.removePageBorders = options.removePageBorders || false;
|
||||
this.renderer = options.renderer || RendererType.CANVAS;
|
||||
}
|
||||
this.useOnlyCssZoom = options.useOnlyCssZoom || false;
|
||||
this.isOffscreenCanvasSupported =
|
||||
options.isOffscreenCanvasSupported ?? true;
|
||||
this.maxCanvasPixels = options.maxCanvasPixels;
|
||||
this.l10n = options.l10n || NullL10n;
|
||||
this.#enablePermissions = options.enablePermissions || false;
|
||||
|
|
@ -324,10 +308,14 @@ class PDFViewer {
|
|||
this._onBeforeDraw = this._onAfterDraw = null;
|
||||
this._resetView();
|
||||
|
||||
if (this.removePageBorders) {
|
||||
if (
|
||||
(typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) &&
|
||||
this.removePageBorders
|
||||
) {
|
||||
this.viewer.classList.add("removePageBorders");
|
||||
}
|
||||
this.updateContainerHeightCss();
|
||||
|
||||
this.#updateContainerHeightCss();
|
||||
}
|
||||
|
||||
get pagesCount() {
|
||||
|
|
@ -467,7 +455,7 @@ class PDFViewer {
|
|||
if (!this.pdfDocument) {
|
||||
return;
|
||||
}
|
||||
this._setScale(val, false);
|
||||
this._setScale(val, { noScroll: false });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -484,7 +472,7 @@ class PDFViewer {
|
|||
if (!this.pdfDocument) {
|
||||
return;
|
||||
}
|
||||
this._setScale(val, false);
|
||||
this._setScale(val, { noScroll: false });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -516,14 +504,12 @@ class PDFViewer {
|
|||
|
||||
const pageNumber = this._currentPageNumber;
|
||||
|
||||
const updateArgs = { rotation };
|
||||
for (const pageView of this._pages) {
|
||||
pageView.update(updateArgs);
|
||||
}
|
||||
this.refresh(true, { rotation });
|
||||
|
||||
// Prevent errors in case the rotation changes *before* the scale has been
|
||||
// set to a non-default value.
|
||||
if (this._currentScaleValue) {
|
||||
this._setScale(this._currentScaleValue, true);
|
||||
this._setScale(this._currentScaleValue, { noScroll: true });
|
||||
}
|
||||
|
||||
this.eventBus.dispatch("rotationchanging", {
|
||||
|
|
@ -549,6 +535,36 @@ class PDFViewer {
|
|||
return this.pdfDocument ? this._pagesCapability.promise : null;
|
||||
}
|
||||
|
||||
#layerProperties() {
|
||||
const self = this;
|
||||
return {
|
||||
get annotationEditorUIManager() {
|
||||
return self.#annotationEditorUIManager;
|
||||
},
|
||||
get annotationStorage() {
|
||||
return self.pdfDocument?.annotationStorage;
|
||||
},
|
||||
get downloadManager() {
|
||||
return self.downloadManager;
|
||||
},
|
||||
get enableScripting() {
|
||||
return !!self._scriptingManager;
|
||||
},
|
||||
get fieldObjectsPromise() {
|
||||
return self.pdfDocument?.getFieldObjects();
|
||||
},
|
||||
get findController() {
|
||||
return self.findController;
|
||||
},
|
||||
get hasJSActionsPromise() {
|
||||
return self.pdfDocument?.hasJSActions();
|
||||
},
|
||||
get linkService() {
|
||||
return self.linkService;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Currently only *some* permissions are supported.
|
||||
* @returns {Object}
|
||||
|
|
@ -648,7 +664,6 @@ class PDFViewer {
|
|||
if (!pdfDocument) {
|
||||
return;
|
||||
}
|
||||
const isPureXfa = pdfDocument.isPureXfa;
|
||||
const pagesCount = pdfDocument.numPages;
|
||||
const firstPagePromise = pdfDocument.getPage(1);
|
||||
// Rendering (potentially) depends on this, hence fetching it immediately.
|
||||
|
|
@ -722,12 +737,13 @@ class PDFViewer {
|
|||
if (annotationEditorMode !== AnnotationEditorType.DISABLE) {
|
||||
const mode = annotationEditorMode;
|
||||
|
||||
if (isPureXfa) {
|
||||
if (pdfDocument.isPureXfa) {
|
||||
console.warn("Warning: XFA-editing is not implemented.");
|
||||
} else if (isValidAnnotationEditorMode(mode)) {
|
||||
this.#annotationEditorUIManager = new AnnotationEditorUIManager(
|
||||
this.container,
|
||||
this.eventBus
|
||||
this.eventBus,
|
||||
pdfDocument?.annotationStorage
|
||||
);
|
||||
if (mode !== AnnotationEditorType.NONE) {
|
||||
this.#annotationEditorUIManager.updateMode(mode);
|
||||
|
|
@ -737,20 +753,16 @@ class PDFViewer {
|
|||
}
|
||||
}
|
||||
|
||||
const layerProperties = this.#layerProperties.bind(this);
|
||||
const viewerElement =
|
||||
this._scrollMode === ScrollMode.PAGE ? null : this.viewer;
|
||||
const scale = this.currentScale;
|
||||
const viewport = firstPdfPage.getViewport({
|
||||
scale: scale * PixelsPerInch.PDF_TO_CSS_UNITS,
|
||||
});
|
||||
const textLayerFactory =
|
||||
textLayerMode !== TextLayerMode.DISABLE && !isPureXfa ? this : null;
|
||||
const annotationLayerFactory =
|
||||
annotationMode !== AnnotationMode.DISABLE ? this : null;
|
||||
const xfaLayerFactory = isPureXfa ? this : null;
|
||||
const annotationEditorLayerFactory = this.#annotationEditorUIManager
|
||||
? this
|
||||
: null;
|
||||
// Ensure that the various layers always get the correct initial size,
|
||||
// see issue 15795.
|
||||
this.viewer.style.setProperty("--scale-factor", viewport.scale);
|
||||
|
||||
for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) {
|
||||
const pageView = new PDFPageView({
|
||||
|
|
@ -761,14 +773,8 @@ class PDFViewer {
|
|||
defaultViewport: viewport.clone(),
|
||||
optionalContentConfigPromise,
|
||||
renderingQueue: this.renderingQueue,
|
||||
textLayerFactory,
|
||||
textLayerMode,
|
||||
annotationLayerFactory,
|
||||
annotationMode,
|
||||
xfaLayerFactory,
|
||||
annotationEditorLayerFactory,
|
||||
textHighlighterFactory: this,
|
||||
structTreeLayerFactory: this,
|
||||
imageResourcesPath: this.imageResourcesPath,
|
||||
renderer:
|
||||
typeof PDFJSDev === "undefined" ||
|
||||
|
|
@ -776,9 +782,11 @@ class PDFViewer {
|
|||
? this.renderer
|
||||
: null,
|
||||
useOnlyCssZoom: this.useOnlyCssZoom,
|
||||
isOffscreenCanvasSupported: this.isOffscreenCanvasSupported,
|
||||
maxCanvasPixels: this.maxCanvasPixels,
|
||||
pageColors: this.pageColors,
|
||||
l10n: this.l10n,
|
||||
layerProperties,
|
||||
});
|
||||
this._pages.push(pageView);
|
||||
}
|
||||
|
|
@ -1024,10 +1032,12 @@ class PDFViewer {
|
|||
#scrollIntoView(pageView, pageSpot = null) {
|
||||
const { div, id } = pageView;
|
||||
|
||||
if (this._scrollMode === ScrollMode.PAGE) {
|
||||
// Ensure that `this._currentPageNumber` is correct.
|
||||
// Ensure that `this._currentPageNumber` is correct, when `#scrollIntoView`
|
||||
// is called directly (and not from `#resetCurrentPageView`).
|
||||
if (this._currentPageNumber !== id) {
|
||||
this._setCurrentPageNumber(id);
|
||||
|
||||
}
|
||||
if (this._scrollMode === ScrollMode.PAGE) {
|
||||
this.#ensurePageViewVisible();
|
||||
// Ensure that rendering always occurs, to avoid showing a blank page,
|
||||
// even if the current position doesn't change when the page is scrolled.
|
||||
|
|
@ -1047,6 +1057,15 @@ class PDFViewer {
|
|||
}
|
||||
}
|
||||
scrollIntoView(div, pageSpot);
|
||||
|
||||
// Ensure that the correct *initial* document position is set, when any
|
||||
// OpenParameters are used, for documents with non-default Scroll/Spread
|
||||
// modes (fixes issue 15695). This is necessary since the scroll-handler
|
||||
// invokes the `update`-method asynchronously, and `this._location` could
|
||||
// thus be wrong when the initial zooming occurs in the default viewer.
|
||||
if (!this._currentScaleValue && this._location) {
|
||||
this._location = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1060,7 +1079,11 @@ class PDFViewer {
|
|||
);
|
||||
}
|
||||
|
||||
_setScaleUpdatePages(newScale, newValue, noScroll = false, preset = false) {
|
||||
_setScaleUpdatePages(
|
||||
newScale,
|
||||
newValue,
|
||||
{ noScroll = false, preset = false, drawingDelay = -1 }
|
||||
) {
|
||||
this._currentScaleValue = newValue.toString();
|
||||
|
||||
if (this.#isSameScale(newScale)) {
|
||||
|
|
@ -1074,15 +1097,24 @@ class PDFViewer {
|
|||
return;
|
||||
}
|
||||
|
||||
docStyle.setProperty(
|
||||
this.viewer.style.setProperty(
|
||||
"--scale-factor",
|
||||
newScale * PixelsPerInch.PDF_TO_CSS_UNITS
|
||||
);
|
||||
|
||||
const updateArgs = { scale: newScale };
|
||||
for (const pageView of this._pages) {
|
||||
pageView.update(updateArgs);
|
||||
const postponeDrawing = drawingDelay >= 0 && drawingDelay < 1000;
|
||||
this.refresh(true, {
|
||||
scale: newScale,
|
||||
drawingDelay: postponeDrawing ? drawingDelay : -1,
|
||||
});
|
||||
|
||||
if (postponeDrawing) {
|
||||
this.#scaleTimeoutId = setTimeout(() => {
|
||||
this.#scaleTimeoutId = null;
|
||||
this.refresh();
|
||||
}, drawingDelay);
|
||||
}
|
||||
|
||||
this._currentScale = newScale;
|
||||
|
||||
if (!noScroll) {
|
||||
|
|
@ -1117,7 +1149,6 @@ class PDFViewer {
|
|||
if (this.defaultRenderingQueue) {
|
||||
this.update();
|
||||
}
|
||||
this.updateContainerHeightCss();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1133,11 +1164,12 @@ class PDFViewer {
|
|||
return 1;
|
||||
}
|
||||
|
||||
_setScale(value, noScroll = false) {
|
||||
_setScale(value, options) {
|
||||
let scale = parseFloat(value);
|
||||
|
||||
if (scale > 0) {
|
||||
this._setScaleUpdatePages(scale, value, noScroll, /* preset = */ false);
|
||||
options.preset = false;
|
||||
this._setScaleUpdatePages(scale, value, options);
|
||||
} else {
|
||||
const currentPage = this._pages[this._currentPageNumber - 1];
|
||||
if (!currentPage) {
|
||||
|
|
@ -1147,8 +1179,18 @@ class PDFViewer {
|
|||
vPadding = VERTICAL_PADDING;
|
||||
|
||||
if (this.isInPresentationMode) {
|
||||
hPadding = vPadding = 4;
|
||||
} else if (this.removePageBorders) {
|
||||
// Pages have a 2px (transparent) border in PresentationMode, see
|
||||
// the `web/pdf_viewer.css` file.
|
||||
hPadding = vPadding = 4; // 2 * 2px
|
||||
if (this._spreadMode !== SpreadMode.NONE) {
|
||||
// Account for two pages being visible in PresentationMode, thus
|
||||
// "doubling" the total border width.
|
||||
hPadding *= 2;
|
||||
}
|
||||
} else if (
|
||||
(typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) &&
|
||||
this.removePageBorders
|
||||
) {
|
||||
hPadding = vPadding = 0;
|
||||
} else if (this._scrollMode === ScrollMode.HORIZONTAL) {
|
||||
[hPadding, vPadding] = [vPadding, hPadding]; // Swap the padding values.
|
||||
|
|
@ -1185,7 +1227,8 @@ class PDFViewer {
|
|||
console.error(`_setScale: "${value}" is an unknown zoom value.`);
|
||||
return;
|
||||
}
|
||||
this._setScaleUpdatePages(scale, value, noScroll, /* preset = */ true);
|
||||
options.preset = true;
|
||||
this._setScaleUpdatePages(scale, value, options);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1197,7 +1240,7 @@ class PDFViewer {
|
|||
|
||||
if (this.isInPresentationMode) {
|
||||
// Fixes the case when PDF has different page sizes.
|
||||
this._setScale(this._currentScaleValue, true);
|
||||
this._setScale(this._currentScaleValue, { noScroll: true });
|
||||
}
|
||||
this.#scrollIntoView(pageView);
|
||||
}
|
||||
|
|
@ -1314,9 +1357,15 @@ class PDFViewer {
|
|||
y = destArray[3];
|
||||
width = destArray[4] - x;
|
||||
height = destArray[5] - y;
|
||||
const hPadding = this.removePageBorders ? 0 : SCROLLBAR_PADDING;
|
||||
const vPadding = this.removePageBorders ? 0 : VERTICAL_PADDING;
|
||||
let hPadding = SCROLLBAR_PADDING,
|
||||
vPadding = VERTICAL_PADDING;
|
||||
|
||||
if (
|
||||
(typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) &&
|
||||
this.removePageBorders
|
||||
) {
|
||||
hPadding = vPadding = 0;
|
||||
}
|
||||
widthScale =
|
||||
(this.container.clientWidth - hPadding) /
|
||||
width /
|
||||
|
|
@ -1582,23 +1631,6 @@ class PDFViewer {
|
|||
return this.scroll.down;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only show the `loadingIcon`-spinner on visible pages (see issue 14242).
|
||||
*/
|
||||
#toggleLoadingIconSpinner(visibleIds) {
|
||||
for (const id of visibleIds) {
|
||||
const pageView = this._pages[id - 1];
|
||||
pageView?.toggleLoadingIconSpinner(/* viewVisible = */ true);
|
||||
}
|
||||
for (const pageView of this.#buffer) {
|
||||
if (visibleIds.has(pageView.id)) {
|
||||
// Handled above, since the "buffer" may not contain all visible pages.
|
||||
continue;
|
||||
}
|
||||
pageView.toggleLoadingIconSpinner(/* viewVisible = */ false);
|
||||
}
|
||||
}
|
||||
|
||||
forceRendering(currentlyVisiblePages) {
|
||||
const visiblePages = currentlyVisiblePages || this._getVisiblePages();
|
||||
const scrollAhead = this.#getScrollAhead(visiblePages);
|
||||
|
|
@ -1612,7 +1644,6 @@ class PDFViewer {
|
|||
scrollAhead,
|
||||
preRenderExtra
|
||||
);
|
||||
this.#toggleLoadingIconSpinner(visiblePages.ids);
|
||||
|
||||
if (pageView) {
|
||||
this.#ensurePdfPageLoaded(pageView).then(() => {
|
||||
|
|
@ -1623,185 +1654,6 @@ class PDFViewer {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} CreateTextLayerBuilderParameters
|
||||
* @property {HTMLDivElement} textLayerDiv
|
||||
* @property {number} pageIndex
|
||||
* @property {PageViewport} viewport
|
||||
* @property {EventBus} eventBus
|
||||
* @property {TextHighlighter} highlighter
|
||||
* @property {TextAccessibilityManager} [accessibilityManager]
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {CreateTextLayerBuilderParameters}
|
||||
* @returns {TextLayerBuilder}
|
||||
*/
|
||||
createTextLayerBuilder({
|
||||
textLayerDiv,
|
||||
pageIndex,
|
||||
viewport,
|
||||
eventBus,
|
||||
highlighter,
|
||||
accessibilityManager = null,
|
||||
}) {
|
||||
return new TextLayerBuilder({
|
||||
textLayerDiv,
|
||||
eventBus,
|
||||
pageIndex,
|
||||
viewport,
|
||||
highlighter,
|
||||
accessibilityManager,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} CreateTextHighlighterParameters
|
||||
* @property {number} pageIndex
|
||||
* @property {EventBus} eventBus
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {CreateTextHighlighterParameters}
|
||||
* @returns {TextHighlighter}
|
||||
*/
|
||||
createTextHighlighter({ pageIndex, eventBus }) {
|
||||
return new TextHighlighter({
|
||||
eventBus,
|
||||
pageIndex,
|
||||
findController: this.isInPresentationMode ? null : this.findController,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} CreateAnnotationLayerBuilderParameters
|
||||
* @property {HTMLDivElement} pageDiv
|
||||
* @property {PDFPageProxy} pdfPage
|
||||
* @property {AnnotationStorage} [annotationStorage] - Storage for annotation
|
||||
* data in forms.
|
||||
* @property {string} [imageResourcesPath] - Path for image resources, mainly
|
||||
* for annotation icons. Include trailing slash.
|
||||
* @property {boolean} renderForms
|
||||
* @property {IL10n} l10n
|
||||
* @property {boolean} [enableScripting]
|
||||
* @property {Promise<boolean>} [hasJSActionsPromise]
|
||||
* @property {Object} [mouseState]
|
||||
* @property {Promise<Object<string, Array<Object>> | null>}
|
||||
* [fieldObjectsPromise]
|
||||
* @property {Map<string, HTMLCanvasElement>} [annotationCanvasMap] - Map some
|
||||
* annotation ids with canvases used to render them.
|
||||
* @property {TextAccessibilityManager} [accessibilityManager]
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {CreateAnnotationLayerBuilderParameters}
|
||||
* @returns {AnnotationLayerBuilder}
|
||||
*/
|
||||
createAnnotationLayerBuilder({
|
||||
pageDiv,
|
||||
pdfPage,
|
||||
annotationStorage = this.pdfDocument?.annotationStorage,
|
||||
imageResourcesPath = "",
|
||||
renderForms = true,
|
||||
l10n = NullL10n,
|
||||
enableScripting = this.enableScripting,
|
||||
hasJSActionsPromise = this.pdfDocument?.hasJSActions(),
|
||||
mouseState = this._scriptingManager?.mouseState,
|
||||
fieldObjectsPromise = this.pdfDocument?.getFieldObjects(),
|
||||
annotationCanvasMap = null,
|
||||
accessibilityManager = null,
|
||||
}) {
|
||||
return new AnnotationLayerBuilder({
|
||||
pageDiv,
|
||||
pdfPage,
|
||||
annotationStorage,
|
||||
imageResourcesPath,
|
||||
renderForms,
|
||||
linkService: this.linkService,
|
||||
downloadManager: this.downloadManager,
|
||||
l10n,
|
||||
enableScripting,
|
||||
hasJSActionsPromise,
|
||||
mouseState,
|
||||
fieldObjectsPromise,
|
||||
annotationCanvasMap,
|
||||
accessibilityManager,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} CreateAnnotationEditorLayerBuilderParameters
|
||||
* @property {AnnotationEditorUIManager} [uiManager]
|
||||
* @property {HTMLDivElement} pageDiv
|
||||
* @property {PDFPageProxy} pdfPage
|
||||
* @property {IL10n} l10n
|
||||
* @property {AnnotationStorage} [annotationStorage] - Storage for annotation
|
||||
* @property {TextAccessibilityManager} [accessibilityManager]
|
||||
* data in forms.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {CreateAnnotationEditorLayerBuilderParameters}
|
||||
* @returns {AnnotationEditorLayerBuilder}
|
||||
*/
|
||||
createAnnotationEditorLayerBuilder({
|
||||
uiManager = this.#annotationEditorUIManager,
|
||||
pageDiv,
|
||||
pdfPage,
|
||||
accessibilityManager = null,
|
||||
l10n,
|
||||
annotationStorage = this.pdfDocument?.annotationStorage,
|
||||
}) {
|
||||
return new AnnotationEditorLayerBuilder({
|
||||
uiManager,
|
||||
pageDiv,
|
||||
pdfPage,
|
||||
annotationStorage,
|
||||
accessibilityManager,
|
||||
l10n,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} CreateXfaLayerBuilderParameters
|
||||
* @property {HTMLDivElement} pageDiv
|
||||
* @property {PDFPageProxy} pdfPage
|
||||
* @property {AnnotationStorage} [annotationStorage] - Storage for annotation
|
||||
* data in forms.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {CreateXfaLayerBuilderParameters}
|
||||
* @returns {XfaLayerBuilder}
|
||||
*/
|
||||
createXfaLayerBuilder({
|
||||
pageDiv,
|
||||
pdfPage,
|
||||
annotationStorage = this.pdfDocument?.annotationStorage,
|
||||
}) {
|
||||
return new XfaLayerBuilder({
|
||||
pageDiv,
|
||||
pdfPage,
|
||||
annotationStorage,
|
||||
linkService: this.linkService,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} CreateStructTreeLayerBuilderParameters
|
||||
* @property {PDFPageProxy} pdfPage
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {CreateStructTreeLayerBuilderParameters}
|
||||
* @returns {StructTreeLayerBuilder}
|
||||
*/
|
||||
createStructTreeLayerBuilder({ pdfPage }) {
|
||||
return new StructTreeLayerBuilder({
|
||||
pdfPage,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean} Whether all pages of the PDF document have identical
|
||||
* widths and heights.
|
||||
|
|
@ -1878,11 +1730,7 @@ class PDFViewer {
|
|||
}
|
||||
this._optionalContentConfigPromise = promise;
|
||||
|
||||
const updateArgs = { optionalContentConfigPromise: promise };
|
||||
for (const pageView of this._pages) {
|
||||
pageView.update(updateArgs);
|
||||
}
|
||||
this.update();
|
||||
this.refresh(false, { optionalContentConfigPromise: promise });
|
||||
|
||||
this.eventBus.dispatch("optionalcontentconfigchanged", {
|
||||
source: this,
|
||||
|
|
@ -1945,7 +1793,7 @@ class PDFViewer {
|
|||
// Call this before re-scrolling to the current page, to ensure that any
|
||||
// changes in scale don't move the current page.
|
||||
if (this._currentScaleValue && isNaN(this._currentScaleValue)) {
|
||||
this._setScale(this._currentScaleValue, true);
|
||||
this._setScale(this._currentScaleValue, { noScroll: true });
|
||||
}
|
||||
this._setCurrentPageNumber(pageNumber, /* resetCurrentPageView = */ true);
|
||||
this.update();
|
||||
|
|
@ -2017,7 +1865,7 @@ class PDFViewer {
|
|||
// Call this before re-scrolling to the current page, to ensure that any
|
||||
// changes in scale don't move the current page.
|
||||
if (this._currentScaleValue && isNaN(this._currentScaleValue)) {
|
||||
this._setScale(this._currentScaleValue, true);
|
||||
this._setScale(this._currentScaleValue, { noScroll: true });
|
||||
}
|
||||
this._setCurrentPageNumber(pageNumber, /* resetCurrentPageView = */ true);
|
||||
this.update();
|
||||
|
|
@ -2157,42 +2005,110 @@ class PDFViewer {
|
|||
|
||||
/**
|
||||
* Increase the current zoom level one, or more, times.
|
||||
* @param {number} [steps] - Defaults to zooming once.
|
||||
* @param {Object|null} [options]
|
||||
*/
|
||||
increaseScale(steps = 1) {
|
||||
increaseScale(options = null) {
|
||||
if (
|
||||
(typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) &&
|
||||
typeof options === "number"
|
||||
) {
|
||||
console.error(
|
||||
"The `increaseScale` method-signature was updated, please use an object instead."
|
||||
);
|
||||
options = { steps: options };
|
||||
}
|
||||
|
||||
if (!this.pdfDocument) {
|
||||
return;
|
||||
}
|
||||
|
||||
options ||= Object.create(null);
|
||||
|
||||
let newScale = this._currentScale;
|
||||
do {
|
||||
newScale = (newScale * DEFAULT_SCALE_DELTA).toFixed(2);
|
||||
newScale = Math.ceil(newScale * 10) / 10;
|
||||
newScale = Math.min(MAX_SCALE, newScale);
|
||||
} while (--steps > 0 && newScale < MAX_SCALE);
|
||||
this.currentScaleValue = newScale;
|
||||
if (options.scaleFactor > 1) {
|
||||
newScale = Math.min(
|
||||
MAX_SCALE,
|
||||
Math.round(newScale * options.scaleFactor * 100) / 100
|
||||
);
|
||||
} else {
|
||||
let steps = options.steps ?? 1;
|
||||
do {
|
||||
newScale = (newScale * DEFAULT_SCALE_DELTA).toFixed(2);
|
||||
newScale = Math.ceil(newScale * 10) / 10;
|
||||
newScale = Math.min(MAX_SCALE, newScale);
|
||||
} while (--steps > 0 && newScale < MAX_SCALE);
|
||||
}
|
||||
|
||||
options.noScroll = false;
|
||||
this._setScale(newScale, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrease the current zoom level one, or more, times.
|
||||
* @param {number} [steps] - Defaults to zooming once.
|
||||
* @param {Object|null} [options]
|
||||
*/
|
||||
decreaseScale(steps = 1) {
|
||||
decreaseScale(options = null) {
|
||||
if (
|
||||
(typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) &&
|
||||
typeof options === "number"
|
||||
) {
|
||||
console.error(
|
||||
"The `decreaseScale` method-signature was updated, please use an object instead."
|
||||
);
|
||||
options = { steps: options };
|
||||
}
|
||||
|
||||
if (!this.pdfDocument) {
|
||||
return;
|
||||
}
|
||||
|
||||
options ||= Object.create(null);
|
||||
|
||||
let newScale = this._currentScale;
|
||||
do {
|
||||
newScale = (newScale / DEFAULT_SCALE_DELTA).toFixed(2);
|
||||
newScale = Math.floor(newScale * 10) / 10;
|
||||
newScale = Math.max(MIN_SCALE, newScale);
|
||||
} while (--steps > 0 && newScale > MIN_SCALE);
|
||||
this.currentScaleValue = newScale;
|
||||
if (options.scaleFactor > 0 && options.scaleFactor < 1) {
|
||||
newScale = Math.max(
|
||||
MIN_SCALE,
|
||||
Math.round(newScale * options.scaleFactor * 100) / 100
|
||||
);
|
||||
} else {
|
||||
let steps = options.steps ?? 1;
|
||||
do {
|
||||
newScale = (newScale / DEFAULT_SCALE_DELTA).toFixed(2);
|
||||
newScale = Math.floor(newScale * 10) / 10;
|
||||
newScale = Math.max(MIN_SCALE, newScale);
|
||||
} while (--steps > 0 && newScale > MIN_SCALE);
|
||||
}
|
||||
|
||||
options.noScroll = false;
|
||||
this._setScale(newScale, options);
|
||||
}
|
||||
|
||||
updateContainerHeightCss() {
|
||||
const height = this.container.clientHeight;
|
||||
|
||||
#updateContainerHeightCss(height = this.container.clientHeight) {
|
||||
if (height !== this.#previousContainerHeight) {
|
||||
this.#previousContainerHeight = height;
|
||||
|
||||
docStyle.setProperty("--viewer-container-height", `${height}px`);
|
||||
}
|
||||
}
|
||||
|
||||
#resizeObserverCallback(entries) {
|
||||
for (const entry of entries) {
|
||||
if (entry.target === this.container) {
|
||||
this.#updateContainerHeightCss(
|
||||
Math.floor(entry.borderBoxSize[0].blockSize)
|
||||
);
|
||||
this.#containerTopLeft = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get containerTopLeft() {
|
||||
return (this.#containerTopLeft ||= [
|
||||
this.container.offsetTop,
|
||||
this.container.offsetLeft,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
|
|
@ -2235,15 +2151,20 @@ class PDFViewer {
|
|||
this.#annotationEditorUIManager.updateParams(type, value);
|
||||
}
|
||||
|
||||
refresh() {
|
||||
refresh(noUpdate = false, updateArgs = Object.create(null)) {
|
||||
if (!this.pdfDocument) {
|
||||
return;
|
||||
}
|
||||
const updateArgs = {};
|
||||
for (const pageView of this._pages) {
|
||||
pageView.update(updateArgs);
|
||||
}
|
||||
this.update();
|
||||
if (this.#scaleTimeoutId !== null) {
|
||||
clearTimeout(this.#scaleTimeoutId);
|
||||
this.#scaleTimeoutId = null;
|
||||
}
|
||||
if (!noUpdate) {
|
||||
this.update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,5 +18,5 @@
|
|||
|
||||
const {addScriptSync} = require('../../protyle/util/addScript')
|
||||
const {Constants} = require('../../constants')
|
||||
addScriptSync(`${Constants.PROTYLE_CDN}/js/pdf/pdf.js?v=3.0.150`, 'pdfjsScript')
|
||||
addScriptSync(`${Constants.PROTYLE_CDN}/js/pdf/pdf.js?v=3.4.120`, 'pdfjsScript')
|
||||
module.exports = window["pdfjs-dist/build/pdf"];
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ScrollMode, SpreadMode } from "./ui_utils.js";
|
||||
import { CursorTool } from "./pdf_cursor_tools.js";
|
||||
import { CursorTool, ScrollMode, SpreadMode } from "./ui_utils.js";
|
||||
import { PagesCountLimit } from "./pdf_viewer.js";
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** @typedef {import("../src/display/api").PDFPageProxy} PDFPageProxy */
|
||||
|
||||
const PDF_ROLE_TO_HTML_ROLE = {
|
||||
// Document level structure types
|
||||
Document: null, // There's a "document" role, but it doesn't make sense here.
|
||||
|
|
@ -73,24 +71,35 @@ const PDF_ROLE_TO_HTML_ROLE = {
|
|||
|
||||
const HEADING_PATTERN = /^H(\d+)$/;
|
||||
|
||||
/**
|
||||
* @typedef {Object} StructTreeLayerBuilderOptions
|
||||
* @property {PDFPageProxy} pdfPage
|
||||
*/
|
||||
|
||||
class StructTreeLayerBuilder {
|
||||
/**
|
||||
* @param {StructTreeLayerBuilderOptions} options
|
||||
*/
|
||||
constructor({ pdfPage }) {
|
||||
this.pdfPage = pdfPage;
|
||||
#treeDom = undefined;
|
||||
|
||||
get renderingDone() {
|
||||
return this.#treeDom !== undefined;
|
||||
}
|
||||
|
||||
render(structTree) {
|
||||
return this._walk(structTree);
|
||||
if (this.#treeDom !== undefined) {
|
||||
return this.#treeDom;
|
||||
}
|
||||
const treeDom = this.#walk(structTree);
|
||||
treeDom?.classList.add("structTree");
|
||||
return (this.#treeDom = treeDom);
|
||||
}
|
||||
|
||||
_setAttributes(structElement, htmlElement) {
|
||||
hide() {
|
||||
if (this.#treeDom && !this.#treeDom.hidden) {
|
||||
this.#treeDom.hidden = true;
|
||||
}
|
||||
}
|
||||
|
||||
show() {
|
||||
if (this.#treeDom?.hidden) {
|
||||
this.#treeDom.hidden = false;
|
||||
}
|
||||
}
|
||||
|
||||
#setAttributes(structElement, htmlElement) {
|
||||
if (structElement.alt !== undefined) {
|
||||
htmlElement.setAttribute("aria-label", structElement.alt);
|
||||
}
|
||||
|
|
@ -102,7 +111,7 @@ class StructTreeLayerBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
_walk(node) {
|
||||
#walk(node) {
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -119,16 +128,16 @@ class StructTreeLayerBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
this._setAttributes(node, element);
|
||||
this.#setAttributes(node, element);
|
||||
|
||||
if (node.children) {
|
||||
if (node.children.length === 1 && "id" in node.children[0]) {
|
||||
// Often there is only one content node so just set the values on the
|
||||
// parent node to avoid creating an extra span.
|
||||
this._setAttributes(node.children[0], element);
|
||||
this.#setAttributes(node.children[0], element);
|
||||
} else {
|
||||
for (const kid of node.children) {
|
||||
element.append(this._walk(kid));
|
||||
element.append(this.#walk(kid));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ class TextHighlighter {
|
|||
);
|
||||
this._onUpdateTextLayerMatches = null;
|
||||
}
|
||||
this._updateMatches(/* reset = */ true);
|
||||
}
|
||||
|
||||
_convertMatches(matches, matchesLength) {
|
||||
|
|
@ -264,8 +265,8 @@ class TextHighlighter {
|
|||
}
|
||||
}
|
||||
|
||||
_updateMatches() {
|
||||
if (!this.enabled) {
|
||||
_updateMatches(reset = false) {
|
||||
if (!this.enabled && !reset) {
|
||||
return;
|
||||
}
|
||||
const { findController, matches, pageIdx } = this;
|
||||
|
|
@ -273,8 +274,7 @@ class TextHighlighter {
|
|||
let clearedUntilDivIdx = -1;
|
||||
|
||||
// Clear all current matches.
|
||||
for (let i = 0, ii = matches.length; i < ii; i++) {
|
||||
const match = matches[i];
|
||||
for (const match of matches) {
|
||||
const begin = Math.max(clearedUntilDivIdx, match.begin.divIdx);
|
||||
for (let n = begin, end = match.end.divIdx; n <= end; n++) {
|
||||
const div = textDivs[n];
|
||||
|
|
@ -284,7 +284,7 @@ class TextHighlighter {
|
|||
clearedUntilDivIdx = match.end.divIdx + 1;
|
||||
}
|
||||
|
||||
if (!findController?.highlightMatches) {
|
||||
if (!findController?.highlightMatches || reset) {
|
||||
return;
|
||||
}
|
||||
// Convert the matches on the `findController` into the match format
|
||||
|
|
|
|||
|
|
@ -15,23 +15,21 @@
|
|||
|
||||
// eslint-disable-next-line max-len
|
||||
/** @typedef {import("../src/display/display_utils").PageViewport} PageViewport */
|
||||
/** @typedef {import("./event_utils").EventBus} EventBus */
|
||||
/** @typedef {import("../src/display/api").TextContent} TextContent */
|
||||
/** @typedef {import("./text_highlighter").TextHighlighter} TextHighlighter */
|
||||
// eslint-disable-next-line max-len
|
||||
/** @typedef {import("./text_accessibility.js").TextAccessibilityManager} TextAccessibilityManager */
|
||||
|
||||
import { renderTextLayer } from "./pdfjs";
|
||||
import { getHighlight } from '../anno'
|
||||
import { renderTextLayer, updateTextLayer } from "./pdfjs";
|
||||
import {getHighlight} from "../anno";
|
||||
|
||||
/**
|
||||
* @typedef {Object} TextLayerBuilderOptions
|
||||
* @property {HTMLDivElement} textLayerDiv - The text layer container.
|
||||
* @property {EventBus} eventBus - The application event bus.
|
||||
* @property {number} pageIndex - The page index.
|
||||
* @property {PageViewport} viewport - The viewport of the text layer.
|
||||
* @property {TextHighlighter} highlighter - Optional object that will handle
|
||||
* highlighting text from the find controller.
|
||||
* @property {TextAccessibilityManager} [accessibilityManager]
|
||||
* @property {boolean} [isOffscreenCanvasSupported] - Allows to use an
|
||||
* OffscreenCanvas if needed.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
@ -40,28 +38,29 @@ import { getHighlight } from '../anno'
|
|||
* contain text that matches the PDF text they are overlaying.
|
||||
*/
|
||||
class TextLayerBuilder {
|
||||
#rotation = 0;
|
||||
|
||||
#scale = 0;
|
||||
|
||||
#textContentSource = null;
|
||||
|
||||
constructor({
|
||||
textLayerDiv,
|
||||
eventBus,
|
||||
pageIndex,
|
||||
viewport,
|
||||
highlighter = null,
|
||||
accessibilityManager = null,
|
||||
isOffscreenCanvasSupported = true,
|
||||
}) {
|
||||
this.textLayerDiv = textLayerDiv;
|
||||
this.eventBus = eventBus;
|
||||
this.textContent = null;
|
||||
this.textContentItemsStr = [];
|
||||
this.textContentStream = null;
|
||||
this.renderingDone = false;
|
||||
this.pageNumber = pageIndex + 1;
|
||||
this.viewport = viewport;
|
||||
this.textDivs = [];
|
||||
this.textDivProperties = new WeakMap();
|
||||
this.textLayerRenderTask = null;
|
||||
this.highlighter = highlighter;
|
||||
this.accessibilityManager = accessibilityManager;
|
||||
this.isOffscreenCanvasSupported = isOffscreenCanvasSupported;
|
||||
|
||||
this.#bindMouse();
|
||||
this.div = document.createElement("div");
|
||||
this.div.className = "textLayer";
|
||||
this.hide();
|
||||
}
|
||||
|
||||
#finishRendering() {
|
||||
|
|
@ -69,54 +68,86 @@ class TextLayerBuilder {
|
|||
|
||||
const endOfContent = document.createElement("div");
|
||||
endOfContent.className = "endOfContent";
|
||||
this.textLayerDiv.append(endOfContent);
|
||||
this.div.append(endOfContent);
|
||||
|
||||
this.#bindMouse();
|
||||
|
||||
this.eventBus.dispatch("textlayerrendered", {
|
||||
source: this,
|
||||
pageNumber: this.pageNumber,
|
||||
numTextDivs: this.textDivs.length,
|
||||
});
|
||||
// NOTE
|
||||
getHighlight(this.textLayerDiv)
|
||||
getHighlight(this.div)
|
||||
}
|
||||
|
||||
get numTextDivs() {
|
||||
return this.textDivs.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the text layer.
|
||||
*
|
||||
* @param {number} [timeout] - Wait for a specified amount of milliseconds
|
||||
* before rendering.
|
||||
* @param {PageViewport} viewport
|
||||
*/
|
||||
render(timeout = 0) {
|
||||
if (!(this.textContent || this.textContentStream) || this.renderingDone) {
|
||||
async render(viewport) {
|
||||
if (!this.#textContentSource) {
|
||||
throw new Error('No "textContentSource" parameter specified.');
|
||||
}
|
||||
|
||||
const scale = viewport.scale * (globalThis.devicePixelRatio || 1);
|
||||
const { rotation } = viewport;
|
||||
if (this.renderingDone) {
|
||||
const mustRotate = rotation !== this.#rotation;
|
||||
const mustRescale = scale !== this.#scale;
|
||||
if (mustRotate || mustRescale) {
|
||||
this.hide();
|
||||
updateTextLayer({
|
||||
container: this.div,
|
||||
viewport,
|
||||
textDivs: this.textDivs,
|
||||
textDivProperties: this.textDivProperties,
|
||||
isOffscreenCanvasSupported: this.isOffscreenCanvasSupported,
|
||||
mustRescale,
|
||||
mustRotate,
|
||||
});
|
||||
this.#scale = scale;
|
||||
this.#rotation = rotation;
|
||||
}
|
||||
this.show();
|
||||
return;
|
||||
}
|
||||
this.cancel();
|
||||
|
||||
this.textDivs.length = 0;
|
||||
this.cancel();
|
||||
this.highlighter?.setTextMapping(this.textDivs, this.textContentItemsStr);
|
||||
this.accessibilityManager?.setTextMapping(this.textDivs);
|
||||
|
||||
const textLayerFrag = document.createDocumentFragment();
|
||||
this.textLayerRenderTask = renderTextLayer({
|
||||
textContent: this.textContent,
|
||||
textContentStream: this.textContentStream,
|
||||
container: textLayerFrag,
|
||||
viewport: this.viewport,
|
||||
textContentSource: this.#textContentSource,
|
||||
container: this.div,
|
||||
viewport,
|
||||
textDivs: this.textDivs,
|
||||
textDivProperties: this.textDivProperties,
|
||||
textContentItemsStr: this.textContentItemsStr,
|
||||
timeout,
|
||||
isOffscreenCanvasSupported: this.isOffscreenCanvasSupported,
|
||||
});
|
||||
this.textLayerRenderTask.promise.then(
|
||||
() => {
|
||||
this.textLayerDiv.append(textLayerFrag);
|
||||
this.#finishRendering();
|
||||
this.highlighter?.enable();
|
||||
this.accessibilityManager?.enable();
|
||||
},
|
||||
function (reason) {
|
||||
// Cancelled or failed to render text layer; skipping errors.
|
||||
}
|
||||
);
|
||||
|
||||
await this.textLayerRenderTask.promise;
|
||||
this.#finishRendering();
|
||||
this.#scale = scale;
|
||||
this.#rotation = rotation;
|
||||
this.show();
|
||||
this.accessibilityManager?.enable();
|
||||
}
|
||||
|
||||
hide() {
|
||||
if (!this.div.hidden) {
|
||||
// We turn off the highlighter in order to avoid to scroll into view an
|
||||
// element of the text layer which could be hidden.
|
||||
this.highlighter?.disable();
|
||||
this.div.hidden = true;
|
||||
}
|
||||
}
|
||||
|
||||
show() {
|
||||
if (this.div.hidden && this.renderingDone) {
|
||||
this.div.hidden = false;
|
||||
this.highlighter?.enable();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -129,16 +160,17 @@ class TextLayerBuilder {
|
|||
}
|
||||
this.highlighter?.disable();
|
||||
this.accessibilityManager?.disable();
|
||||
this.textContentItemsStr.length = 0;
|
||||
this.textDivs.length = 0;
|
||||
this.textDivProperties = new WeakMap();
|
||||
}
|
||||
|
||||
setTextContentStream(readableStream) {
|
||||
/**
|
||||
* @param {ReadableStream | TextContent} source
|
||||
*/
|
||||
setTextContentSource(source) {
|
||||
this.cancel();
|
||||
this.textContentStream = readableStream;
|
||||
}
|
||||
|
||||
setTextContent(textContent) {
|
||||
this.cancel();
|
||||
this.textContent = textContent;
|
||||
this.#textContentSource = source;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -147,7 +179,7 @@ class TextLayerBuilder {
|
|||
* dragged up or down.
|
||||
*/
|
||||
#bindMouse() {
|
||||
const div = this.textLayerDiv;
|
||||
const { div } = this;
|
||||
|
||||
div.addEventListener("mousedown", evt => {
|
||||
const end = div.querySelector(".endOfContent");
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ import {
|
|||
animationStarted,
|
||||
DEFAULT_SCALE,
|
||||
DEFAULT_SCALE_VALUE,
|
||||
docStyle,
|
||||
MAX_SCALE,
|
||||
MIN_SCALE,
|
||||
noContextMenuHandler,
|
||||
|
|
@ -262,6 +261,7 @@ class Toolbar {
|
|||
items.pageNumber.type = "text";
|
||||
} else {
|
||||
items.pageNumber.type = "number";
|
||||
// NOTE
|
||||
items.numPages.textContent = "/ " + pagesCount;
|
||||
}
|
||||
items.pageNumber.max = pagesCount;
|
||||
|
|
@ -269,6 +269,7 @@ class Toolbar {
|
|||
|
||||
if (this.hasPageLabels) {
|
||||
items.pageNumber.value = this.pageLabel;
|
||||
// NOTE
|
||||
items.numPages.textContent = `(${pageNumber} / ${pagesCount})`
|
||||
} else {
|
||||
items.pageNumber.value = pageNumber;
|
||||
|
|
@ -318,15 +319,10 @@ class Toolbar {
|
|||
|
||||
await animationStarted;
|
||||
|
||||
const style = getComputedStyle(items.scaleSelect),
|
||||
scaleSelectContainerWidth = parseInt(
|
||||
style.getPropertyValue("--scale-select-container-width"),
|
||||
10
|
||||
),
|
||||
scaleSelectOverflow = parseInt(
|
||||
style.getPropertyValue("--scale-select-overflow"),
|
||||
10
|
||||
);
|
||||
const style = getComputedStyle(items.scaleSelect);
|
||||
const scaleSelectWidth = parseFloat(
|
||||
style.getPropertyValue("--scale-select-width")
|
||||
);
|
||||
|
||||
// The temporary canvas is used to measure text length in the DOM.
|
||||
const canvas = document.createElement("canvas");
|
||||
|
|
@ -334,16 +330,19 @@ class Toolbar {
|
|||
ctx.font = `${style.fontSize} ${style.fontFamily}`;
|
||||
|
||||
let maxWidth = 0;
|
||||
for (const predefinedValue of predefinedValuesPromise) {
|
||||
for (const predefinedValue of await predefinedValuesPromise) {
|
||||
const { width } = ctx.measureText(predefinedValue);
|
||||
if (width > maxWidth) {
|
||||
maxWidth = width;
|
||||
}
|
||||
}
|
||||
maxWidth += 2 * scaleSelectOverflow;
|
||||
// Account for the icon width, and ensure that there's always some spacing
|
||||
// between the text and the icon.
|
||||
maxWidth += 0.3 * scaleSelectWidth;
|
||||
|
||||
if (maxWidth > scaleSelectContainerWidth) {
|
||||
docStyle.setProperty("--scale-select-container-width", `${maxWidth}px`);
|
||||
if (maxWidth > scaleSelectWidth) {
|
||||
const container = items.scaleSelect.parentNode;
|
||||
container.style.setProperty("--scale-select-width", `${maxWidth}px`);
|
||||
}
|
||||
// Zeroing the width and height cause Firefox to release graphics resources
|
||||
// immediately, which can greatly reduce memory consumption.
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {hasClosestByAttribute} from "../../protyle/util/hasClosest";
|
||||
|
||||
const DEFAULT_SCALE_VALUE = "auto";
|
||||
const DEFAULT_SCALE = 1.0;
|
||||
const DEFAULT_SCALE_DELTA = 1.1;
|
||||
|
|
@ -76,6 +74,12 @@ const SpreadMode = {
|
|||
EVEN: 2,
|
||||
};
|
||||
|
||||
const CursorTool = {
|
||||
SELECT: 0, // The default value.
|
||||
HAND: 1,
|
||||
ZOOM: 2,
|
||||
};
|
||||
|
||||
// Used by `PDFViewerApplication`, and by the API unit-tests.
|
||||
const AutoPrintRegExp = /\bprint\s*\(/;
|
||||
|
||||
|
|
@ -624,17 +628,16 @@ function normalizeWheelEventDirection(evt) {
|
|||
}
|
||||
|
||||
function normalizeWheelEventDelta(evt) {
|
||||
const deltaMode = evt.deltaMode; // Avoid being affected by bug 1392460.
|
||||
let delta = normalizeWheelEventDirection(evt);
|
||||
|
||||
const MOUSE_DOM_DELTA_PIXEL_MODE = 0;
|
||||
const MOUSE_DOM_DELTA_LINE_MODE = 1;
|
||||
const MOUSE_PIXELS_PER_LINE = 30;
|
||||
const MOUSE_LINES_PER_PAGE = 30;
|
||||
|
||||
// Converts delta to per-page units
|
||||
if (evt.deltaMode === MOUSE_DOM_DELTA_PIXEL_MODE) {
|
||||
if (deltaMode === WheelEvent.DOM_DELTA_PIXEL) {
|
||||
delta /= MOUSE_PIXELS_PER_LINE * MOUSE_LINES_PER_PAGE;
|
||||
} else if (evt.deltaMode === MOUSE_DOM_DELTA_LINE_MODE) {
|
||||
} else if (deltaMode === WheelEvent.DOM_DELTA_LINE) {
|
||||
delta /= MOUSE_LINES_PER_PAGE;
|
||||
}
|
||||
return delta;
|
||||
|
|
@ -695,13 +698,18 @@ function clamp(v, min, max) {
|
|||
class ProgressBar {
|
||||
#classList = null;
|
||||
|
||||
#disableAutoFetchTimeout = null;
|
||||
|
||||
#percent = 0;
|
||||
|
||||
#style = null;
|
||||
|
||||
#visible = true;
|
||||
|
||||
// NOTE
|
||||
constructor(bar) {
|
||||
this.#classList = bar.classList;
|
||||
this.#style = bar.style;
|
||||
}
|
||||
|
||||
get percent() {
|
||||
|
|
@ -717,7 +725,7 @@ class ProgressBar {
|
|||
}
|
||||
this.#classList.remove("indeterminate");
|
||||
|
||||
docStyle.setProperty("--progressBar-percent", `${this.#percent}%`);
|
||||
this.#style.setProperty("--progressBar-percent", `${this.#percent}%`);
|
||||
}
|
||||
|
||||
setWidth(viewer) {
|
||||
|
|
@ -727,10 +735,28 @@ class ProgressBar {
|
|||
const container = viewer.parentNode;
|
||||
const scrollbarWidth = container.offsetWidth - viewer.offsetWidth;
|
||||
if (scrollbarWidth > 0) {
|
||||
docStyle.setProperty("--progressBar-end-offset", `${scrollbarWidth}px`);
|
||||
this.#style.setProperty(
|
||||
"--progressBar-end-offset",
|
||||
`${scrollbarWidth}px`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
setDisableAutoFetch(delay = /* ms = */ 5000) {
|
||||
if (isNaN(this.#percent)) {
|
||||
return;
|
||||
}
|
||||
if (this.#disableAutoFetchTimeout) {
|
||||
clearTimeout(this.#disableAutoFetchTimeout);
|
||||
}
|
||||
this.show();
|
||||
|
||||
this.#disableAutoFetchTimeout = setTimeout(() => {
|
||||
this.#disableAutoFetchTimeout = null;
|
||||
this.hide();
|
||||
}, delay);
|
||||
}
|
||||
|
||||
hide() {
|
||||
if (!this.#visible) {
|
||||
return;
|
||||
|
|
@ -775,9 +801,6 @@ function getActiveOrFocusedElement() {
|
|||
|
||||
/**
|
||||
* Converts API PageLayout values to the format used by `BaseViewer`.
|
||||
* NOTE: This is supported to the extent that the viewer implements the
|
||||
* necessary Scroll/Spread modes (since SinglePage, TwoPageLeft,
|
||||
* and TwoPageRight all suggests using non-continuous scrolling).
|
||||
* @param {string} mode - The API PageLayout value.
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
|
@ -839,6 +862,7 @@ export {
|
|||
AutoPrintRegExp,
|
||||
backtrackBeforeAllVisibleElements, // only exported for testing
|
||||
binarySearchFirstItem,
|
||||
CursorTool,
|
||||
DEFAULT_SCALE,
|
||||
DEFAULT_SCALE_DELTA,
|
||||
DEFAULT_SCALE_VALUE,
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {setStorageVal} from "../../protyle/util/compatibility";
|
||||
|
||||
const DEFAULT_VIEW_HISTORY_CACHE_SIZE = 20;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -13,237 +13,192 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { RenderingStates, ScrollMode, SpreadMode } from './ui_utils.js'
|
||||
import { AppOptions } from './app_options.js'
|
||||
import { LinkTarget } from './pdf_link_service.js'
|
||||
import { PDFViewerApplication } from './app.js'
|
||||
import { initAnno } from '../anno'
|
||||
import { RenderingStates, ScrollMode, SpreadMode } from "./ui_utils.js";
|
||||
import { AppOptions } from "./app_options.js";
|
||||
import { LinkTarget } from "./pdf_link_service.js";
|
||||
import { PDFViewerApplication } from "./app.js";
|
||||
import { initAnno } from "../anno";
|
||||
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const pdfjsVersion =
|
||||
typeof PDFJSDev !== 'undefined' ? PDFJSDev.eval('BUNDLE_VERSION') : void 0
|
||||
typeof PDFJSDev !== "undefined" ? PDFJSDev.eval("BUNDLE_VERSION") : void 0;
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const pdfjsBuild =
|
||||
typeof PDFJSDev !== 'undefined' ? PDFJSDev.eval('BUNDLE_BUILD') : void 0
|
||||
typeof PDFJSDev !== "undefined" ? PDFJSDev.eval("BUNDLE_BUILD") : void 0;
|
||||
|
||||
const AppConstants =
|
||||
typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')
|
||||
? {LinkTarget, RenderingStates, ScrollMode, SpreadMode}
|
||||
: null
|
||||
|
||||
window.PDFViewerApplication = PDFViewerApplication
|
||||
window.PDFViewerApplicationConstants = AppConstants
|
||||
window.PDFViewerApplicationOptions = AppOptions
|
||||
|
||||
if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('CHROME')) {
|
||||
(function rewriteUrlClosure () {
|
||||
// Run this code outside DOMContentLoaded to make sure that the URL
|
||||
// is rewritten as soon as possible.
|
||||
const queryString = document.location.search.slice(1)
|
||||
const m = /(^|&)file=([^&]*)/.exec(queryString)
|
||||
const defaultUrl = m ? decodeURIComponent(m[2]) : ''
|
||||
|
||||
// Example: chrome-extension://.../http://example.com/file.pdf
|
||||
const humanReadableUrl = '/' + defaultUrl + location.hash
|
||||
history.replaceState(history.state, '', humanReadableUrl)
|
||||
if (top === window) {
|
||||
// eslint-disable-next-line no-undef
|
||||
chrome.runtime.sendMessage('showPageAction')
|
||||
}
|
||||
|
||||
AppOptions.set('defaultUrl', defaultUrl)
|
||||
})()
|
||||
}
|
||||
typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")
|
||||
? { LinkTarget, RenderingStates, ScrollMode, SpreadMode }
|
||||
: null;
|
||||
|
||||
// NOTE
|
||||
// if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('MOZCENTRAL')) {
|
||||
// require('./firefoxcom.js')
|
||||
// require('./firefox_print_service.js')
|
||||
// }
|
||||
// if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('GENERIC')) {
|
||||
// require('./genericcom.js')
|
||||
// }
|
||||
// if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('CHROME')) {
|
||||
// require('./chromecom.js')
|
||||
// }
|
||||
// if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('CHROME || GENERIC')) {
|
||||
// require('./pdf_print_service.js')
|
||||
// }
|
||||
// window.PDFViewerApplication = PDFViewerApplication;
|
||||
// window.PDFViewerApplicationConstants = AppConstants;
|
||||
// window.PDFViewerApplicationOptions = AppOptions;
|
||||
|
||||
// NOTE
|
||||
function getViewerConfiguration (element) {
|
||||
function getViewerConfiguration(element) {
|
||||
return {
|
||||
appContainer: element,
|
||||
mainContainer: element.querySelector('#viewerContainer'),
|
||||
viewerContainer: element.querySelector('#viewer'),
|
||||
mainContainer: element.querySelector("#viewerContainer"),
|
||||
viewerContainer: element.querySelector("#viewer"),
|
||||
toolbar: {
|
||||
// NOTE
|
||||
rectAnno: element.querySelector('#rectAnno'),
|
||||
container: element.querySelector('#toolbarViewer'),
|
||||
numPages: element.querySelector('#numPages'),
|
||||
pageNumber: element.querySelector('#pageNumber'),
|
||||
scaleSelect: element.querySelector('#scaleSelect'),
|
||||
customScaleOption: element.querySelector('#customScaleOption'),
|
||||
previous: element.querySelector('#previous'),
|
||||
next: element.querySelector('#next'),
|
||||
zoomIn: element.querySelector('#zoomIn'),
|
||||
zoomOut: element.querySelector('#zoomOut'),
|
||||
viewFind: element.querySelector('#viewFind'),
|
||||
rectAnno: element.querySelector("#rectAnno"),
|
||||
container: element.querySelector("#toolbarViewer"),
|
||||
numPages: element.querySelector("#numPages"),
|
||||
pageNumber: element.querySelector("#pageNumber"),
|
||||
scaleSelect: element.querySelector("#scaleSelect"),
|
||||
customScaleOption: element.querySelector("#customScaleOption"),
|
||||
previous: element.querySelector("#previous"),
|
||||
next: element.querySelector("#next"),
|
||||
zoomIn: element.querySelector("#zoomIn"),
|
||||
zoomOut: element.querySelector("#zoomOut"),
|
||||
viewFind: element.querySelector("#viewFind"),
|
||||
openFile:
|
||||
typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')
|
||||
? element.querySelector('#openFile')
|
||||
typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")
|
||||
? element.querySelector("#openFile")
|
||||
: null,
|
||||
print: element.querySelector('#print'),
|
||||
editorFreeTextButton: element.querySelector('#editorFreeText'),
|
||||
editorFreeTextParamsToolbar: element.querySelector('#editorFreeTextParamsToolbar'),
|
||||
editorInkButton: element.querySelector('#editorInk'),
|
||||
editorInkParamsToolbar: element.querySelector('#editorInkParamsToolbar'),
|
||||
download: element.querySelector('#download'),
|
||||
print: element.querySelector("#print"),
|
||||
editorFreeTextButton: element.querySelector("#editorFreeText"),
|
||||
editorFreeTextParamsToolbar: element.querySelector(
|
||||
"#editorFreeTextParamsToolbar"
|
||||
),
|
||||
editorInkButton: element.querySelector("#editorInk"),
|
||||
editorInkParamsToolbar: element.querySelector("#editorInkParamsToolbar"),
|
||||
download: element.querySelector("#download"),
|
||||
},
|
||||
secondaryToolbar: {
|
||||
toolbar: element.querySelector('#secondaryToolbar'),
|
||||
toggleButton: element.querySelector('#secondaryToolbarToggle'),
|
||||
presentationModeButton: element.querySelector('#presentationMode'),
|
||||
toolbar: element.querySelector("#secondaryToolbar"),
|
||||
toggleButton: element.querySelector("#secondaryToolbarToggle"),
|
||||
presentationModeButton: element.querySelector("#presentationMode"),
|
||||
openFileButton:
|
||||
typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')
|
||||
? element.querySelector('#secondaryOpenFile')
|
||||
typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")
|
||||
? element.querySelector("#secondaryOpenFile")
|
||||
: null,
|
||||
printButton: element.querySelector('#secondaryPrint'),
|
||||
downloadButton: element.querySelector('#secondaryDownload'),
|
||||
viewBookmarkButton: element.querySelector('#viewBookmark'),
|
||||
firstPageButton: element.querySelector('#firstPage'),
|
||||
lastPageButton: element.querySelector('#lastPage'),
|
||||
pageRotateCwButton: element.querySelector('#pageRotateCw'),
|
||||
pageRotateCcwButton: element.querySelector('#pageRotateCcw'),
|
||||
cursorSelectToolButton: element.querySelector('#cursorSelectTool'),
|
||||
cursorHandToolButton: element.querySelector('#cursorHandTool'),
|
||||
scrollPageButton: element.querySelector('#scrollPage'),
|
||||
scrollVerticalButton: element.querySelector('#scrollVertical'),
|
||||
scrollHorizontalButton: element.querySelector('#scrollHorizontal'),
|
||||
scrollWrappedButton: element.querySelector('#scrollWrapped'),
|
||||
spreadNoneButton: element.querySelector('#spreadNone'),
|
||||
spreadOddButton: element.querySelector('#spreadOdd'),
|
||||
spreadEvenButton: element.querySelector('#spreadEven'),
|
||||
documentPropertiesButton: element.querySelector('#documentProperties'),
|
||||
printButton: element.querySelector("#secondaryPrint"),
|
||||
downloadButton: element.querySelector("#secondaryDownload"),
|
||||
viewBookmarkButton: element.querySelector("#viewBookmark"),
|
||||
firstPageButton: element.querySelector("#firstPage"),
|
||||
lastPageButton: element.querySelector("#lastPage"),
|
||||
pageRotateCwButton: element.querySelector("#pageRotateCw"),
|
||||
pageRotateCcwButton: element.querySelector("#pageRotateCcw"),
|
||||
cursorSelectToolButton: element.querySelector("#cursorSelectTool"),
|
||||
cursorHandToolButton: element.querySelector("#cursorHandTool"),
|
||||
scrollPageButton: element.querySelector("#scrollPage"),
|
||||
scrollVerticalButton: element.querySelector("#scrollVertical"),
|
||||
scrollHorizontalButton: element.querySelector("#scrollHorizontal"),
|
||||
scrollWrappedButton: element.querySelector("#scrollWrapped"),
|
||||
spreadNoneButton: element.querySelector("#spreadNone"),
|
||||
spreadOddButton: element.querySelector("#spreadOdd"),
|
||||
spreadEvenButton: element.querySelector("#spreadEven"),
|
||||
documentPropertiesButton: element.querySelector("#documentProperties"),
|
||||
},
|
||||
sidebar: {
|
||||
// Divs (and sidebar button)
|
||||
outerContainer: element.querySelector('#outerContainer'),
|
||||
sidebarContainer: element.querySelector('#sidebarContainer'),
|
||||
toggleButton: element.querySelector('#sidebarToggle'),
|
||||
outerContainer: element.querySelector("#outerContainer"),
|
||||
sidebarContainer: element.querySelector("#sidebarContainer"),
|
||||
toggleButton: element.querySelector("#sidebarToggle"),
|
||||
// Buttons
|
||||
thumbnailButton: element.querySelector('#viewThumbnail'),
|
||||
outlineButton: element.querySelector('#viewOutline'),
|
||||
attachmentsButton: element.querySelector('#viewAttachments'),
|
||||
layersButton: element.querySelector('#viewLayers'),
|
||||
thumbnailButton: element.querySelector("#viewThumbnail"),
|
||||
outlineButton: element.querySelector("#viewOutline"),
|
||||
attachmentsButton: element.querySelector("#viewAttachments"),
|
||||
layersButton: element.querySelector("#viewLayers"),
|
||||
// Views
|
||||
thumbnailView: element.querySelector('#thumbnailView'),
|
||||
outlineView: element.querySelector('#outlineView'),
|
||||
attachmentsView: element.querySelector('#attachmentsView'),
|
||||
layersView: element.querySelector('#layersView'),
|
||||
thumbnailView: element.querySelector("#thumbnailView"),
|
||||
outlineView: element.querySelector("#outlineView"),
|
||||
attachmentsView: element.querySelector("#attachmentsView"),
|
||||
layersView: element.querySelector("#layersView"),
|
||||
// View-specific options
|
||||
outlineOptionsContainer: element.querySelector('#outlineOptionsContainer'),
|
||||
currentOutlineItemButton: element.querySelector('#currentOutlineItem'),
|
||||
outlineOptionsContainer: element.querySelector("#outlineOptionsContainer"),
|
||||
currentOutlineItemButton: element.querySelector("#currentOutlineItem"),
|
||||
},
|
||||
sidebarResizer: {
|
||||
outerContainer: element.querySelector('#outerContainer'),
|
||||
resizer: element.querySelector('#sidebarResizer'),
|
||||
outerContainer: element.querySelector("#outerContainer"),
|
||||
resizer: element.querySelector("#sidebarResizer"),
|
||||
},
|
||||
findBar: {
|
||||
bar: element.querySelector('#findbar'),
|
||||
toggleButton: element.querySelector('#viewFind'),
|
||||
findField: element.querySelector('#findInput'),
|
||||
highlightAllCheckbox: element.querySelector('#findHighlightAll'),
|
||||
caseSensitiveCheckbox: element.querySelector('#findMatchCase'),
|
||||
matchDiacriticsCheckbox: element.querySelector('#findMatchDiacritics'),
|
||||
entireWordCheckbox: element.querySelector('#findEntireWord'),
|
||||
findMsg: element.querySelector('#findMsg'),
|
||||
findResultsCount: element.querySelector('#findResultsCount'),
|
||||
findPreviousButton: element.querySelector('#findPrevious'),
|
||||
findNextButton: element.querySelector('#findNext'),
|
||||
bar: element.querySelector("#findbar"),
|
||||
toggleButton: element.querySelector("#viewFind"),
|
||||
findField: element.querySelector("#findInput"),
|
||||
highlightAllCheckbox: element.querySelector("#findHighlightAll"),
|
||||
caseSensitiveCheckbox: element.querySelector("#findMatchCase"),
|
||||
matchDiacriticsCheckbox: element.querySelector("#findMatchDiacritics"),
|
||||
entireWordCheckbox: element.querySelector("#findEntireWord"),
|
||||
findMsg: element.querySelector("#findMsg"),
|
||||
findResultsCount: element.querySelector("#findResultsCount"),
|
||||
findPreviousButton: element.querySelector("#findPrevious"),
|
||||
findNextButton: element.querySelector("#findNext"),
|
||||
},
|
||||
passwordOverlay: {
|
||||
dialog: element.querySelector('#passwordDialog'),
|
||||
label: element.querySelector('#passwordText'),
|
||||
input: element.querySelector('#password'),
|
||||
submitButton: element.querySelector('#passwordSubmit'),
|
||||
cancelButton: element.querySelector('#passwordCancel'),
|
||||
dialog: element.querySelector("#passwordDialog"),
|
||||
label: element.querySelector("#passwordText"),
|
||||
input: element.querySelector("#password"),
|
||||
submitButton: element.querySelector("#passwordSubmit"),
|
||||
cancelButton: element.querySelector("#passwordCancel"),
|
||||
},
|
||||
documentProperties: {
|
||||
dialog: element.querySelector('#documentPropertiesDialog'),
|
||||
closeButton: element.querySelector('#documentPropertiesClose'),
|
||||
dialog: element.querySelector("#documentPropertiesDialog"),
|
||||
closeButton: element.querySelector("#documentPropertiesClose"),
|
||||
fields: {
|
||||
fileName: element.querySelector('#fileNameField'),
|
||||
fileSize: element.querySelector('#fileSizeField'),
|
||||
title: element.querySelector('#titleField'),
|
||||
author: element.querySelector('#authorField'),
|
||||
subject: element.querySelector('#subjectField'),
|
||||
keywords: element.querySelector('#keywordsField'),
|
||||
creationDate: element.querySelector('#creationDateField'),
|
||||
modificationDate: element.querySelector('#modificationDateField'),
|
||||
creator: element.querySelector('#creatorField'),
|
||||
producer: element.querySelector('#producerField'),
|
||||
version: element.querySelector('#versionField'),
|
||||
pageCount: element.querySelector('#pageCountField'),
|
||||
pageSize: element.querySelector('#pageSizeField'),
|
||||
linearized: element.querySelector('#linearizedField'),
|
||||
fileName: element.querySelector("#fileNameField"),
|
||||
fileSize: element.querySelector("#fileSizeField"),
|
||||
title: element.querySelector("#titleField"),
|
||||
author: element.querySelector("#authorField"),
|
||||
subject: element.querySelector("#subjectField"),
|
||||
keywords: element.querySelector("#keywordsField"),
|
||||
creationDate: element.querySelector("#creationDateField"),
|
||||
modificationDate: element.querySelector("#modificationDateField"),
|
||||
creator: element.querySelector("#creatorField"),
|
||||
producer: element.querySelector("#producerField"),
|
||||
version: element.querySelector("#versionField"),
|
||||
pageCount: element.querySelector("#pageCountField"),
|
||||
pageSize: element.querySelector("#pageSizeField"),
|
||||
linearized: element.querySelector("#linearizedField"),
|
||||
},
|
||||
},
|
||||
annotationEditorParams: {
|
||||
editorFreeTextFontSize: element.querySelector('#editorFreeTextFontSize'),
|
||||
editorFreeTextColor: element.querySelector('#editorFreeTextColor'),
|
||||
editorInkColor: element.querySelector('#editorInkColor'),
|
||||
editorInkThickness: element.querySelector('#editorInkThickness'),
|
||||
editorInkOpacity: element.querySelector('#editorInkOpacity'),
|
||||
editorFreeTextFontSize: element.querySelector("#editorFreeTextFontSize"),
|
||||
editorFreeTextColor: element.querySelector("#editorFreeTextColor"),
|
||||
editorInkColor: element.querySelector("#editorInkColor"),
|
||||
editorInkThickness: element.querySelector("#editorInkThickness"),
|
||||
editorInkOpacity: element.querySelector("#editorInkOpacity"),
|
||||
},
|
||||
errorWrapper:
|
||||
typeof PDFJSDev === 'undefined' || !PDFJSDev.test('MOZCENTRAL')
|
||||
? {
|
||||
container: element.querySelector('#errorWrapper'),
|
||||
errorMessage: element.querySelector('#errorMessage'),
|
||||
closeButton: element.querySelector('#errorClose'),
|
||||
errorMoreInfo: element.querySelector('#errorMoreInfo'),
|
||||
moreInfoButton: element.querySelector('#errorShowMore'),
|
||||
lessInfoButton: element.querySelector('#errorShowLess'),
|
||||
}
|
||||
: null,
|
||||
printContainer: element.querySelector('#printContainer'),
|
||||
printContainer: element.querySelector("#printContainer"),
|
||||
openFileInput:
|
||||
typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')
|
||||
? element.querySelector('#fileInput')
|
||||
typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")
|
||||
? element.querySelector("#fileInput")
|
||||
: null,
|
||||
debuggerScriptPath: './debugger.js',
|
||||
debuggerScriptPath: "./debugger.js",
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE
|
||||
function webViewerLoad (file, element, pdfPage, annoId) {
|
||||
function webViewerLoad(file, element, pdfPage, annoId) {
|
||||
const pdf = new PDFViewerApplication(pdfPage)
|
||||
pdf.annoId = annoId
|
||||
const config = getViewerConfiguration(element)
|
||||
if (typeof PDFJSDev === 'undefined' || !PDFJSDev.test('PRODUCTION')) {
|
||||
config.file = file
|
||||
} else {
|
||||
if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('GENERIC')) {
|
||||
// Give custom implementations of the default viewer a simpler way to
|
||||
// set various `AppOptions`, by dispatching an event once all viewer
|
||||
// files are loaded but *before* the viewer initialization has run.
|
||||
const event = document.createEvent('CustomEvent')
|
||||
event.initCustomEvent('webviewerloaded', true, true, {
|
||||
source: window,
|
||||
})
|
||||
try {
|
||||
// Attempt to dispatch the event at the embedding `document`,
|
||||
// in order to support cases where the viewer is embedded in
|
||||
// a *dynamically* created <iframe> element.
|
||||
parent.document.dispatchEvent(event)
|
||||
} catch (ex) {
|
||||
// The viewer could be in e.g. a cross-origin <iframe> element,
|
||||
// fallback to dispatching the event at the current `document`.
|
||||
console.error(`webviewerloaded: ${ex}`)
|
||||
document.dispatchEvent(event)
|
||||
}
|
||||
const config = getViewerConfiguration(element);
|
||||
|
||||
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("GENERIC")) {
|
||||
// Give custom implementations of the default viewer a simpler way to
|
||||
// set various `AppOptions`, by dispatching an event once all viewer
|
||||
// files are loaded but *before* the viewer initialization has run.
|
||||
const event = document.createEvent("CustomEvent");
|
||||
event.initCustomEvent("webviewerloaded", true, true, {
|
||||
source: window,
|
||||
});
|
||||
try {
|
||||
// Attempt to dispatch the event at the embedding `document`,
|
||||
// in order to support cases where the viewer is embedded in
|
||||
// a *dynamically* created <iframe> element.
|
||||
parent.document.dispatchEvent(event);
|
||||
} catch (ex) {
|
||||
// The viewer could be in e.g. a cross-origin <iframe> element,
|
||||
// fallback to dispatching the event at the current `document`.
|
||||
console.error(`webviewerloaded: ${ex}`);
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
} else {
|
||||
config.file = file
|
||||
}
|
||||
pdf.run(config)
|
||||
initAnno(file, element, annoId, pdf, config);
|
||||
|
|
@ -252,19 +207,19 @@ function webViewerLoad (file, element, pdfPage, annoId) {
|
|||
|
||||
// Block the "load" event until all pages are loaded, to ensure that printing
|
||||
// works in Firefox; see https://bugzilla.mozilla.org/show_bug.cgi?id=1618553
|
||||
document.blockUnblockOnload?.(true);
|
||||
|
||||
document.blockUnblockOnload?.(true)
|
||||
// NOTE
|
||||
// if (
|
||||
// document.readyState === 'interactive' ||
|
||||
// document.readyState === 'complete'
|
||||
// document.readyState === "interactive" ||
|
||||
// document.readyState === "complete"
|
||||
// ) {
|
||||
// webViewerLoad()
|
||||
// webViewerLoad();
|
||||
// } else {
|
||||
// document.addEventListener('DOMContentLoaded', webViewerLoad, true)
|
||||
// document.addEventListener("DOMContentLoaded", webViewerLoad, true);
|
||||
// }
|
||||
|
||||
// NOTE
|
||||
export {
|
||||
webViewerLoad
|
||||
}
|
||||
webViewerLoad,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -55,9 +55,9 @@ class XfaLayerBuilder {
|
|||
* @param {string} intent (default value is 'display')
|
||||
* @returns {Promise<Object | void>} A promise that is resolved when rendering
|
||||
* of the XFA layer is complete. The first rendering will return an object
|
||||
* with a `textDivs` property that can be used with the TextHighlighter.
|
||||
* with a `textDivs` property that can be used with the TextHighlighter.
|
||||
*/
|
||||
render(viewport, intent = "display") {
|
||||
async render(viewport, intent = "display") {
|
||||
if (intent === "print") {
|
||||
const parameters = {
|
||||
viewport: viewport.clone({ dontFlip: true }),
|
||||
|
|
@ -73,39 +73,33 @@ class XfaLayerBuilder {
|
|||
this.pageDiv.append(div);
|
||||
parameters.div = div;
|
||||
|
||||
const result = XfaLayer.render(parameters);
|
||||
return Promise.resolve(result);
|
||||
return XfaLayer.render(parameters);
|
||||
}
|
||||
|
||||
// intent === "display"
|
||||
return this.pdfPage
|
||||
.getXfa()
|
||||
.then(xfaHtml => {
|
||||
if (this._cancelled || !xfaHtml) {
|
||||
return { textDivs: [] };
|
||||
}
|
||||
const xfaHtml = await this.pdfPage.getXfa();
|
||||
if (this._cancelled || !xfaHtml) {
|
||||
return { textDivs: [] };
|
||||
}
|
||||
|
||||
const parameters = {
|
||||
viewport: viewport.clone({ dontFlip: true }),
|
||||
div: this.div,
|
||||
xfaHtml,
|
||||
annotationStorage: this.annotationStorage,
|
||||
linkService: this.linkService,
|
||||
intent,
|
||||
};
|
||||
const parameters = {
|
||||
viewport: viewport.clone({ dontFlip: true }),
|
||||
div: this.div,
|
||||
xfaHtml,
|
||||
annotationStorage: this.annotationStorage,
|
||||
linkService: this.linkService,
|
||||
intent,
|
||||
};
|
||||
|
||||
if (this.div) {
|
||||
return XfaLayer.update(parameters);
|
||||
}
|
||||
// Create an xfa layer div and render the form
|
||||
this.div = document.createElement("div");
|
||||
this.pageDiv.append(this.div);
|
||||
parameters.div = this.div;
|
||||
return XfaLayer.render(parameters);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
});
|
||||
if (this.div) {
|
||||
return XfaLayer.update(parameters);
|
||||
}
|
||||
// Create an xfa layer div and render the form
|
||||
this.div = document.createElement("div");
|
||||
this.pageDiv.append(this.div);
|
||||
parameters.div = this.div;
|
||||
|
||||
return XfaLayer.render(parameters);
|
||||
}
|
||||
|
||||
cancel() {
|
||||
|
|
|
|||
|
|
@ -398,12 +398,18 @@
|
|||
}
|
||||
}
|
||||
|
||||
.dropdownToolbarButton select {
|
||||
min-width: 124px;
|
||||
height: 24px;
|
||||
margin: 4px 8px 0 0;
|
||||
line-height: 24px;
|
||||
padding: 0 8px;
|
||||
.dropdownToolbarButton {
|
||||
--scale-select-width: 140px;
|
||||
width: var(--scale-select-width);
|
||||
|
||||
select {
|
||||
width: inherit;
|
||||
min-width: auto;
|
||||
height: 24px;
|
||||
margin: 4px 8px 0 0;
|
||||
line-height: 24px;
|
||||
padding: 0 8px;
|
||||
}
|
||||
}
|
||||
|
||||
#customScaleOption {
|
||||
|
|
|
|||
|
|
@ -13,9 +13,65 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
:root {
|
||||
--annotation-unfocused-field-background: url("data:image/svg+xml;charset=UTF-8,<svg width='1px' height='1px' xmlns='http://www.w3.org/2000/svg'><rect width='100%' height='100%' style='fill:rgba(0, 54, 255, 0.13);'/></svg>");
|
||||
--input-focus-border-color: Highlight;
|
||||
--input-focus-outline: 1px solid Canvas;
|
||||
--input-unfocused-border-color: transparent;
|
||||
--input-disabled-border-color: transparent;
|
||||
--input-hover-border-color: black;
|
||||
--link-outline: none;
|
||||
}
|
||||
|
||||
@media screen and (forced-colors: active) {
|
||||
:root {
|
||||
--input-focus-border-color: CanvasText;
|
||||
--input-unfocused-border-color: ActiveText;
|
||||
--input-disabled-border-color: GrayText;
|
||||
--input-hover-border-color: Highlight;
|
||||
--link-outline: 1.5px solid LinkText;
|
||||
}
|
||||
|
||||
.annotationLayer .linkAnnotation:hover {
|
||||
backdrop-filter: invert(100%);
|
||||
}
|
||||
}
|
||||
|
||||
.annotationLayer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
pointer-events: none;
|
||||
transform-origin: 0 0;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.annotationLayer[data-main-rotation="90"] .norotate {
|
||||
transform: rotate(270deg) translateX(-100%);
|
||||
}
|
||||
.annotationLayer[data-main-rotation="180"] .norotate {
|
||||
transform: rotate(180deg) translate(-100%, -100%);
|
||||
}
|
||||
.annotationLayer[data-main-rotation="270"] .norotate {
|
||||
transform: rotate(90deg) translateY(-100%);
|
||||
}
|
||||
|
||||
.annotationLayer canvas {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.annotationLayer section {
|
||||
position: absolute;
|
||||
text-align: initial;
|
||||
pointer-events: auto;
|
||||
box-sizing: border-box;
|
||||
transform-origin: 0 0;
|
||||
}
|
||||
|
||||
.annotationLayer .linkAnnotation {
|
||||
outline: var(--link-outline);
|
||||
}
|
||||
|
||||
.annotationLayer .linkAnnotation > a,
|
||||
|
|
@ -28,13 +84,6 @@
|
|||
height: 100%;
|
||||
}
|
||||
|
||||
.annotationLayer .buttonWidgetAnnotation.pushButton > canvas {
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.annotationLayer .linkAnnotation > a:hover,
|
||||
.annotationLayer .buttonWidgetAnnotation.pushButton > a:hover {
|
||||
opacity: 0.2;
|
||||
|
|
@ -45,6 +94,10 @@
|
|||
.annotationLayer .textAnnotation img {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.annotationLayer .textWidgetAnnotation input,
|
||||
|
|
@ -52,17 +105,24 @@
|
|||
.annotationLayer .choiceWidgetAnnotation select,
|
||||
.annotationLayer .buttonWidgetAnnotation.checkBox input,
|
||||
.annotationLayer .buttonWidgetAnnotation.radioButton input {
|
||||
background-color: rgba(0, 54, 255, 0.13);
|
||||
border: 1px solid transparent;
|
||||
background-color: rgba(0, 54, 255, 0.13); // NOTE
|
||||
border: 2px solid var(--input-unfocused-border-color);
|
||||
box-sizing: border-box;
|
||||
font-size: 9px;
|
||||
font: calc(9px * var(--scale-factor)) sans-serif;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0 3px;
|
||||
vertical-align: top;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.annotationLayer .textWidgetAnnotation input:required,
|
||||
.annotationLayer .textWidgetAnnotation textarea:required,
|
||||
.annotationLayer .choiceWidgetAnnotation select:required,
|
||||
.annotationLayer .buttonWidgetAnnotation.checkBox input:required,
|
||||
.annotationLayer .buttonWidgetAnnotation.radioButton input:required {
|
||||
outline: 1.5px solid red;
|
||||
}
|
||||
|
||||
.annotationLayer .choiceWidgetAnnotation select option {
|
||||
padding: 0;
|
||||
}
|
||||
|
|
@ -72,8 +132,6 @@
|
|||
}
|
||||
|
||||
.annotationLayer .textWidgetAnnotation textarea {
|
||||
font: message-box;
|
||||
font-size: 9px;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
|
|
@ -83,7 +141,7 @@
|
|||
.annotationLayer .buttonWidgetAnnotation.checkBox input[disabled],
|
||||
.annotationLayer .buttonWidgetAnnotation.radioButton input[disabled] {
|
||||
background: none;
|
||||
border: 1px solid transparent;
|
||||
border: 2px solid var(--input-disabled-border-color);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
|
|
@ -92,30 +150,45 @@
|
|||
.annotationLayer .choiceWidgetAnnotation select:hover,
|
||||
.annotationLayer .buttonWidgetAnnotation.checkBox input:hover,
|
||||
.annotationLayer .buttonWidgetAnnotation.radioButton input:hover {
|
||||
border: 1px solid rgba(0, 0, 0, 1);
|
||||
border: 2px solid var(--input-hover-border-color);
|
||||
}
|
||||
.annotationLayer .textWidgetAnnotation input:hover,
|
||||
.annotationLayer .textWidgetAnnotation textarea:hover,
|
||||
.annotationLayer .choiceWidgetAnnotation select:hover,
|
||||
.annotationLayer .buttonWidgetAnnotation.checkBox input:hover {
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.annotationLayer .textWidgetAnnotation input:focus,
|
||||
.annotationLayer .textWidgetAnnotation textarea:focus,
|
||||
.annotationLayer .choiceWidgetAnnotation select:focus {
|
||||
background: none;
|
||||
border: 1px solid transparent;
|
||||
border: 2px solid var(--input-focus-border-color);
|
||||
border-radius: 2px;
|
||||
outline: var(--input-focus-outline);
|
||||
}
|
||||
|
||||
.annotationLayer .textWidgetAnnotation input :focus,
|
||||
.annotationLayer .textWidgetAnnotation textarea :focus,
|
||||
.annotationLayer .choiceWidgetAnnotation select :focus,
|
||||
.annotationLayer .buttonWidgetAnnotation.checkBox :focus,
|
||||
.annotationLayer .buttonWidgetAnnotation.radioButton :focus {
|
||||
background-image: none;
|
||||
background-color: transparent;
|
||||
outline: auto;
|
||||
}
|
||||
|
||||
.annotationLayer .buttonWidgetAnnotation.checkBox :focus {
|
||||
border: 2px solid var(--input-focus-border-color);
|
||||
border-radius: 2px;
|
||||
outline: var(--input-focus-outline);
|
||||
}
|
||||
|
||||
.annotationLayer .buttonWidgetAnnotation.radioButton :focus {
|
||||
border: 2px solid var(--input-focus-border-color);
|
||||
outline: var(--input-focus-outline);
|
||||
}
|
||||
|
||||
.annotationLayer .buttonWidgetAnnotation.checkBox input:checked:before,
|
||||
.annotationLayer .buttonWidgetAnnotation.checkBox input:checked:after,
|
||||
.annotationLayer .buttonWidgetAnnotation.radioButton input:checked:before {
|
||||
background-color: rgba(0, 0, 0, 1);
|
||||
background-color: rgba(0, 0, 0, 1); // NOTE
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
|
|
@ -163,32 +236,43 @@
|
|||
.annotationLayer .buttonWidgetAnnotation.checkBox input,
|
||||
.annotationLayer .buttonWidgetAnnotation.radioButton input {
|
||||
appearance: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.annotationLayer .popupTriggerArea {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.annotationLayer .fileAttachmentAnnotation .popupTriggerArea {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.annotationLayer .popupWrapper {
|
||||
position: absolute;
|
||||
width: 20em;
|
||||
font-size: calc(9px * var(--scale-factor));
|
||||
width: 100%;
|
||||
min-width: calc(180px * var(--scale-factor));
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.annotationLayer .popup {
|
||||
position: absolute;
|
||||
z-index: 200;
|
||||
max-width: 20em;
|
||||
max-width: calc(180px * var(--scale-factor));
|
||||
background-color: rgba(255, 255, 153, 1);
|
||||
box-shadow: 0 2px 5px rgba(136, 136, 136, 1);
|
||||
border-radius: 2px;
|
||||
padding: 6px;
|
||||
margin-left: 5px;
|
||||
box-shadow: 0 calc(2px * var(--scale-factor)) calc(5px * var(--scale-factor))
|
||||
rgba(136, 136, 136, 1);
|
||||
border-radius: calc(2px * var(--scale-factor));
|
||||
padding: calc(6px * var(--scale-factor));
|
||||
margin-left: calc(5px * var(--scale-factor));
|
||||
cursor: pointer;
|
||||
font: message-box;
|
||||
font-size: 9px;
|
||||
white-space: normal;
|
||||
word-wrap: break-word;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.annotationLayer .popup > * {
|
||||
font-size: 9px;
|
||||
font-size: calc(9px * var(--scale-factor));
|
||||
}
|
||||
|
||||
.annotationLayer .popup h1 {
|
||||
|
|
@ -197,17 +281,18 @@
|
|||
|
||||
.annotationLayer .popupDate {
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
margin-left: calc(5px * var(--scale-factor));
|
||||
}
|
||||
|
||||
.annotationLayer .popupContent {
|
||||
border-top: 1px solid rgba(51, 51, 51, 1);
|
||||
margin-top: 2px;
|
||||
padding-top: 2px;
|
||||
margin-top: calc(2px * var(--scale-factor));
|
||||
padding-top: calc(2px * var(--scale-factor));
|
||||
}
|
||||
|
||||
.annotationLayer .richText > * {
|
||||
white-space: pre-wrap;
|
||||
font-size: calc(9px * var(--scale-factor));
|
||||
}
|
||||
|
||||
.annotationLayer .highlightAnnotation,
|
||||
|
|
@ -226,3 +311,26 @@
|
|||
.annotationLayer .fileAttachmentAnnotation {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.annotationLayer section svg {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.annotationLayer .annotationTextContent {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
color: transparent;
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.annotationLayer .annotationTextContent span {
|
||||
width: 100%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,29 +17,46 @@
|
|||
@import "xfa_layer_builder";
|
||||
|
||||
:root {
|
||||
--viewer-container-height: 0;
|
||||
--pdfViewer-padding-bottom: 0;
|
||||
--page-margin: 1px auto -8px;
|
||||
--page-border: 9px solid transparent;
|
||||
--spreadHorizontalWrapped-margin-LR: -3.5px;
|
||||
--zoom-factor: 1;
|
||||
--viewport-scale-factor: 1;
|
||||
--loading-icon-delay: 400ms;
|
||||
}
|
||||
|
||||
@media screen and (forced-colors: active) {
|
||||
:root {
|
||||
--pdfViewer-padding-bottom: 9px;
|
||||
--page-margin: 9px auto 0;
|
||||
--page-margin: 8px auto -1px;
|
||||
--page-border: none;
|
||||
--spreadHorizontalWrapped-margin-LR: 4.5px;
|
||||
--spreadHorizontalWrapped-margin-LR: 3.5px;
|
||||
}
|
||||
}
|
||||
|
||||
[data-main-rotation="90"] {
|
||||
transform: rotate(90deg) translateY(-100%);
|
||||
}
|
||||
[data-main-rotation="180"] {
|
||||
transform: rotate(180deg) translate(-100%, -100%);
|
||||
}
|
||||
[data-main-rotation="270"] {
|
||||
transform: rotate(270deg) translateX(-100%);
|
||||
}
|
||||
|
||||
.pdfViewer {
|
||||
/* Define this variable here and not in :root to avoid to reflow all the UI
|
||||
when scaling (see #15929). */
|
||||
--scale-factor: 1;
|
||||
|
||||
padding-bottom: var(--pdfViewer-padding-bottom);
|
||||
}
|
||||
|
||||
.pdfViewer .canvasWrapper {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.pdfViewer .page {
|
||||
|
|
@ -51,21 +68,23 @@
|
|||
overflow: visible;
|
||||
border: var(--page-border);
|
||||
background-clip: content-box;
|
||||
// border-image: url(images/shadow.png) 9 9 repeat;
|
||||
// background-color: rgba(255, 255, 255, 1);
|
||||
background-color: rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
.pdfViewer .dummyPage {
|
||||
position: relative;
|
||||
width: 0;
|
||||
/* The height is set via JS, see `BaseViewer.#ensurePageViewVisible`. */
|
||||
height: var(--viewer-container-height);
|
||||
}
|
||||
|
||||
/*#if GENERIC*/
|
||||
.pdfViewer.removePageBorders .page {
|
||||
margin: 0 auto 10px;
|
||||
border: none;
|
||||
}
|
||||
/*#endif*/
|
||||
|
||||
/*#if COMPONENTS*/
|
||||
.pdfViewer.singlePageView {
|
||||
display: inline-block;
|
||||
}
|
||||
|
|
@ -74,12 +93,12 @@
|
|||
margin: 0;
|
||||
border: none;
|
||||
}
|
||||
/*#endif*/
|
||||
|
||||
.pdfViewer.scrollHorizontal,
|
||||
.pdfViewer.scrollWrapped,
|
||||
.spread {
|
||||
margin-left: 3.5px;
|
||||
margin-right: 3.5px;
|
||||
margin-inline: 3.5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
|
@ -88,11 +107,12 @@
|
|||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/*#if GENERIC*/
|
||||
.pdfViewer.removePageBorders,
|
||||
/*#endif*/
|
||||
.pdfViewer.scrollHorizontal .spread,
|
||||
.pdfViewer.scrollWrapped .spread {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-inline: 0;
|
||||
}
|
||||
|
||||
.spread .page,
|
||||
|
|
@ -108,37 +128,59 @@
|
|||
.spread .page,
|
||||
.pdfViewer.scrollHorizontal .page,
|
||||
.pdfViewer.scrollWrapped .page {
|
||||
margin-left: var(--spreadHorizontalWrapped-margin-LR);
|
||||
margin-right: var(--spreadHorizontalWrapped-margin-LR);
|
||||
margin-inline: var(--spreadHorizontalWrapped-margin-LR);
|
||||
}
|
||||
|
||||
/*#if GENERIC*/
|
||||
.pdfViewer.removePageBorders .spread .page,
|
||||
.pdfViewer.removePageBorders.scrollHorizontal .page,
|
||||
.pdfViewer.removePageBorders.scrollWrapped .page {
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
margin-inline: 5px;
|
||||
}
|
||||
/*#endif*/
|
||||
|
||||
.pdfViewer .page canvas {
|
||||
margin: 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.pdfViewer .page canvas .structTree {
|
||||
contain: strict;
|
||||
}
|
||||
|
||||
.pdfViewer .page canvas[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.pdfViewer .page .loadingIcon {
|
||||
position: absolute;
|
||||
display: block;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
// background: url("images/loading-icon.gif") center no-repeat;
|
||||
.pdfViewer .page canvas[zooming] {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.pdfViewer .page .loadingIcon.notVisible {
|
||||
background: none;
|
||||
|
||||
.pdfViewer .page.loadingIcon:after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
content: "";
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
// NOTE background: url("images/loading-icon.gif") center no-repeat;
|
||||
display: none;
|
||||
/* Using a delay with background-image doesn't work,
|
||||
consequently we use the display. */
|
||||
transition-property: display;
|
||||
transition-delay: var(--loading-icon-delay);
|
||||
z-index: 5;
|
||||
contain: strict;
|
||||
}
|
||||
|
||||
.pdfViewer .page.loading:after {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.pdfViewer .page:not(.loading):after {
|
||||
transition-property: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.pdfViewer.enablePermissions .textLayer span {
|
||||
|
|
|
|||
15774
app/stage/protyle/js/pdf/pdf.js
vendored
15774
app/stage/protyle/js/pdf/pdf.js
vendored
File diff suppressed because one or more lines are too long
64503
app/stage/protyle/js/pdf/pdf.worker.js
vendored
64503
app/stage/protyle/js/pdf/pdf.worker.js
vendored
File diff suppressed because one or more lines are too long
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitDingbats.pfb
vendored
Normal file
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitDingbats.pfb
vendored
Normal file
Binary file not shown.
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitFixed.pfb
vendored
Normal file
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitFixed.pfb
vendored
Normal file
Binary file not shown.
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitFixedBold.pfb
vendored
Normal file
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitFixedBold.pfb
vendored
Normal file
Binary file not shown.
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitFixedBoldItalic.pfb
vendored
Normal file
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitFixedBoldItalic.pfb
vendored
Normal file
Binary file not shown.
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitFixedItalic.pfb
vendored
Normal file
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitFixedItalic.pfb
vendored
Normal file
Binary file not shown.
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitSans.pfb
vendored
Normal file
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitSans.pfb
vendored
Normal file
Binary file not shown.
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitSansBold.pfb
vendored
Normal file
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitSansBold.pfb
vendored
Normal file
Binary file not shown.
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitSansBoldItalic.pfb
vendored
Normal file
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitSansBoldItalic.pfb
vendored
Normal file
Binary file not shown.
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitSansItalic.pfb
vendored
Normal file
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitSansItalic.pfb
vendored
Normal file
Binary file not shown.
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitSerif.pfb
vendored
Normal file
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitSerif.pfb
vendored
Normal file
Binary file not shown.
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitSerifBold.pfb
vendored
Normal file
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitSerifBold.pfb
vendored
Normal file
Binary file not shown.
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitSerifBoldItalic.pfb
vendored
Normal file
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitSerifBoldItalic.pfb
vendored
Normal file
Binary file not shown.
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitSerifItalic.pfb
vendored
Normal file
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitSerifItalic.pfb
vendored
Normal file
Binary file not shown.
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitSymbol.pfb
vendored
Normal file
BIN
app/stage/protyle/js/pdf/standard_fonts/FoxitSymbol.pfb
vendored
Normal file
Binary file not shown.
27
app/stage/protyle/js/pdf/standard_fonts/LICENSE_FOXIT
vendored
Normal file
27
app/stage/protyle/js/pdf/standard_fonts/LICENSE_FOXIT
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2014 PDFium Authors. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
102
app/stage/protyle/js/pdf/standard_fonts/LICENSE_LIBERATION
vendored
Normal file
102
app/stage/protyle/js/pdf/standard_fonts/LICENSE_LIBERATION
vendored
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
Digitized data copyright (c) 2010 Google Corporation
|
||||
with Reserved Font Arimo, Tinos and Cousine.
|
||||
Copyright (c) 2012 Red Hat, Inc.
|
||||
with Reserved Font Name Liberation.
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License,
|
||||
Version 1.1.
|
||||
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
|
||||
PREAMBLE The goals of the Open Font License (OFL) are to stimulate
|
||||
worldwide development of collaborative font projects, to support the font
|
||||
creation efforts of academic and linguistic communities, and to provide
|
||||
a free and open framework in which fonts may be shared and improved in
|
||||
partnership with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves.
|
||||
The fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply to
|
||||
any document created using the fonts or their derivatives.
|
||||
|
||||
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such.
|
||||
This may include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components
|
||||
as distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting ? in part or in whole ?
|
||||
any of the components of the Original Version, by changing formats or
|
||||
by porting the Font Software to a new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical writer
|
||||
or other person who contributed to the Font Software.
|
||||
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,in
|
||||
Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the
|
||||
corresponding Copyright Holder. This restriction only applies to the
|
||||
primary font name as presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole, must
|
||||
be distributed entirely under this license, and must not be distributed
|
||||
under any other license. The requirement for fonts to remain under
|
||||
this license does not apply to any document created using the Font
|
||||
Software.
|
||||
|
||||
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are not met.
|
||||
|
||||
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER
|
||||
DEALINGS IN THE FONT SOFTWARE.
|
||||
|
||||
BIN
app/stage/protyle/js/pdf/standard_fonts/LiberationSans-Bold.ttf
vendored
Normal file
BIN
app/stage/protyle/js/pdf/standard_fonts/LiberationSans-Bold.ttf
vendored
Normal file
Binary file not shown.
BIN
app/stage/protyle/js/pdf/standard_fonts/LiberationSans-BoldItalic.ttf
vendored
Normal file
BIN
app/stage/protyle/js/pdf/standard_fonts/LiberationSans-BoldItalic.ttf
vendored
Normal file
Binary file not shown.
BIN
app/stage/protyle/js/pdf/standard_fonts/LiberationSans-Italic.ttf
vendored
Normal file
BIN
app/stage/protyle/js/pdf/standard_fonts/LiberationSans-Italic.ttf
vendored
Normal file
Binary file not shown.
BIN
app/stage/protyle/js/pdf/standard_fonts/LiberationSans-Regular.ttf
vendored
Normal file
BIN
app/stage/protyle/js/pdf/standard_fonts/LiberationSans-Regular.ttf
vendored
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue