123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358 |
- import { createPromiseCapability, PDFDateString } from "pdfjs-lib";
- import { getPageSizeInches, isPortraitOrientation } from "./ui_utils.js";
- const DEFAULT_FIELD_CONTENT = "-";
- const NON_METRIC_LOCALES = ["en-us", "en-lr", "my"];
- const US_PAGE_NAMES = {
- "8.5x11": "Letter",
- "8.5x14": "Legal",
- };
- const METRIC_PAGE_NAMES = {
- "297x420": "A3",
- "210x297": "A4",
- };
- function getPageName(size, isPortrait, pageNames) {
- const width = isPortrait ? size.width : size.height;
- const height = isPortrait ? size.height : size.width;
- return pageNames[`${width}x${height}`];
- }
- class PDFDocumentProperties {
- #fieldData = null;
-
- constructor(
- { dialog, fields, closeButton },
- overlayManager,
- eventBus,
- l10n,
- fileNameLookup
- ) {
- this.dialog = dialog;
- this.fields = fields;
- this.overlayManager = overlayManager;
- this.l10n = l10n;
- this._fileNameLookup = fileNameLookup;
- this.#reset();
-
- closeButton.addEventListener("click", this.close.bind(this));
- this.overlayManager.register(this.dialog);
- eventBus._on("pagechanging", evt => {
- this._currentPageNumber = evt.pageNumber;
- });
- eventBus._on("rotationchanging", evt => {
- this._pagesRotation = evt.pagesRotation;
- });
- this._isNonMetricLocale = true;
- l10n.getLanguage().then(locale => {
- this._isNonMetricLocale = NON_METRIC_LOCALES.includes(locale);
- });
- }
-
- async open() {
- await Promise.all([
- this.overlayManager.open(this.dialog),
- this._dataAvailableCapability.promise,
- ]);
- const currentPageNumber = this._currentPageNumber;
- const pagesRotation = this._pagesRotation;
-
-
- if (
- this.#fieldData &&
- currentPageNumber === this.#fieldData._currentPageNumber &&
- pagesRotation === this.#fieldData._pagesRotation
- ) {
- this.#updateUI();
- return;
- }
-
- const {
- info,
-
-
- contentLength,
- } = await this.pdfDocument.getMetadata();
- const [
- fileName,
- fileSize,
- creationDate,
- modificationDate,
- pageSize,
- isLinearized,
- ] = await Promise.all([
- this._fileNameLookup(),
- this.#parseFileSize(contentLength),
- this.#parseDate(info.CreationDate),
- this.#parseDate(info.ModDate),
- this.pdfDocument.getPage(currentPageNumber).then(pdfPage => {
- return this.#parsePageSize(getPageSizeInches(pdfPage), pagesRotation);
- }),
- this.#parseLinearization(info.IsLinearized),
- ]);
- this.#fieldData = Object.freeze({
- fileName,
- fileSize,
- title: info.Title,
- author: info.Author,
- subject: info.Subject,
- keywords: info.Keywords,
- creationDate,
- modificationDate,
- creator: info.Creator,
- producer: info.Producer,
- version: info.PDFFormatVersion,
- pageCount: this.pdfDocument.numPages,
- pageSize,
- linearized: isLinearized,
- _currentPageNumber: currentPageNumber,
- _pagesRotation: pagesRotation,
- });
- this.#updateUI();
-
-
- const { length } = await this.pdfDocument.getDownloadInfo();
- if (contentLength === length) {
- return;
- }
- const data = Object.assign(Object.create(null), this.#fieldData);
- data.fileSize = await this.#parseFileSize(length);
- this.#fieldData = Object.freeze(data);
- this.#updateUI();
- }
-
- async close() {
- this.overlayManager.close(this.dialog);
- }
-
- setDocument(pdfDocument) {
- if (this.pdfDocument) {
- this.#reset();
- this.#updateUI(true);
- }
- if (!pdfDocument) {
- return;
- }
- this.pdfDocument = pdfDocument;
- this._dataAvailableCapability.resolve();
- }
- #reset() {
- this.pdfDocument = null;
- this.#fieldData = null;
- this._dataAvailableCapability = createPromiseCapability();
- this._currentPageNumber = 1;
- this._pagesRotation = 0;
- }
-
- #updateUI(reset = false) {
- if (reset || !this.#fieldData) {
- for (const id in this.fields) {
- this.fields[id].textContent = DEFAULT_FIELD_CONTENT;
- }
- return;
- }
- if (this.overlayManager.active !== this.dialog) {
-
-
- return;
- }
- for (const id in this.fields) {
- const content = this.#fieldData[id];
- this.fields[id].textContent =
- content || content === 0 ? content : DEFAULT_FIELD_CONTENT;
- }
- }
- async #parseFileSize(fileSize = 0) {
- const kb = fileSize / 1024,
- mb = kb / 1024;
- if (!kb) {
- return undefined;
- }
- return this.l10n.get(`document_properties_${mb >= 1 ? "mb" : "kb"}`, {
- size_mb: mb >= 1 && (+mb.toPrecision(3)).toLocaleString(),
- size_kb: mb < 1 && (+kb.toPrecision(3)).toLocaleString(),
- size_b: fileSize.toLocaleString(),
- });
- }
- async #parsePageSize(pageSizeInches, pagesRotation) {
- if (!pageSizeInches) {
- return undefined;
- }
-
- if (pagesRotation % 180 !== 0) {
- pageSizeInches = {
- width: pageSizeInches.height,
- height: pageSizeInches.width,
- };
- }
- const isPortrait = isPortraitOrientation(pageSizeInches);
- let sizeInches = {
- width: Math.round(pageSizeInches.width * 100) / 100,
- height: Math.round(pageSizeInches.height * 100) / 100,
- };
-
- let sizeMillimeters = {
- width: Math.round(pageSizeInches.width * 25.4 * 10) / 10,
- height: Math.round(pageSizeInches.height * 25.4 * 10) / 10,
- };
- let rawName =
- getPageName(sizeInches, isPortrait, US_PAGE_NAMES) ||
- getPageName(sizeMillimeters, isPortrait, METRIC_PAGE_NAMES);
- if (
- !rawName &&
- !(
- Number.isInteger(sizeMillimeters.width) &&
- Number.isInteger(sizeMillimeters.height)
- )
- ) {
-
-
-
- const exactMillimeters = {
- width: pageSizeInches.width * 25.4,
- height: pageSizeInches.height * 25.4,
- };
- const intMillimeters = {
- width: Math.round(sizeMillimeters.width),
- height: Math.round(sizeMillimeters.height),
- };
-
- if (
- Math.abs(exactMillimeters.width - intMillimeters.width) < 0.1 &&
- Math.abs(exactMillimeters.height - intMillimeters.height) < 0.1
- ) {
- rawName = getPageName(intMillimeters, isPortrait, METRIC_PAGE_NAMES);
- if (rawName) {
-
-
- sizeInches = {
- width: Math.round((intMillimeters.width / 25.4) * 100) / 100,
- height: Math.round((intMillimeters.height / 25.4) * 100) / 100,
- };
- sizeMillimeters = intMillimeters;
- }
- }
- }
- const [{ width, height }, unit, name, orientation] = await Promise.all([
- this._isNonMetricLocale ? sizeInches : sizeMillimeters,
- this.l10n.get(
- `document_properties_page_size_unit_${
- this._isNonMetricLocale ? "inches" : "millimeters"
- }`
- ),
- rawName &&
- this.l10n.get(
- `document_properties_page_size_name_${rawName.toLowerCase()}`
- ),
- this.l10n.get(
- `document_properties_page_size_orientation_${
- isPortrait ? "portrait" : "landscape"
- }`
- ),
- ]);
- return this.l10n.get(
- `document_properties_page_size_dimension_${name ? "name_" : ""}string`,
- {
- width: width.toLocaleString(),
- height: height.toLocaleString(),
- unit,
- name,
- orientation,
- }
- );
- }
- async #parseDate(inputDate) {
- const dateObject = PDFDateString.toDateObject(inputDate);
- if (!dateObject) {
- return undefined;
- }
- return this.l10n.get("document_properties_date_string", {
- date: dateObject.toLocaleDateString(),
- time: dateObject.toLocaleTimeString(),
- });
- }
- #parseLinearization(isLinearized) {
- return this.l10n.get(
- `document_properties_linearized_${isLinearized ? "yes" : "no"}`
- );
- }
- }
- export { PDFDocumentProperties };
|