From 7851c0da8d93cfa9cbce32ba547d3f9c45b6347e Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Thu, 5 Oct 2023 10:19:07 +0200 Subject: [PATCH] [Debugger] Add some info about substitution font When pdfBug is true, the substitution font is used in the text layer in order to be able to know what is the font really used thanks to the devtools. And to be sure that fonts are loaded, the font cache isn't cleaned up when the debugger is active. --- src/core/evaluator.js | 6 +++++- src/display/font_loader.js | 5 +++-- src/display/text_layer.js | 10 +++++++--- web/app.js | 4 +++- web/debugger.mjs | 34 +++++++++++++++++++++++----------- 5 files changed, 41 insertions(+), 18 deletions(-) diff --git a/src/core/evaluator.js b/src/core/evaluator.js index bcfe4827d..5e86ea5e2 100644 --- a/src/core/evaluator.js +++ b/src/core/evaluator.js @@ -2427,13 +2427,17 @@ class PartialEvaluator { const { font, loadedName } = textState; if (!seenStyles.has(loadedName)) { seenStyles.add(loadedName); - textContent.styles[loadedName] = { fontFamily: font.fallbackName, ascent: font.ascent, descent: font.descent, vertical: font.vertical, }; + if (self.options.fontExtraProperties && font.systemFontInfo) { + const style = textContent.styles[loadedName]; + style.fontSubstitution = font.systemFontInfo.css; + style.fontSubstitutionLoadedName = font.systemFontInfo.loadedName; + } } textContentItem.fontName = loadedName; diff --git a/src/display/font_loader.js b/src/display/font_loader.js index 2beead5be..23f4a6a1c 100644 --- a/src/display/font_loader.js +++ b/src/display/font_loader.js @@ -80,7 +80,7 @@ class FontLoader { } } - async loadSystemFont(info) { + async loadSystemFont({ systemFontInfo: info, _inspectFont }) { if (!info || this.#systemFonts.has(info.loadedName)) { return; } @@ -96,6 +96,7 @@ class FontLoader { try { await fontFace.load(); this.#systemFonts.add(loadedName); + _inspectFont?.(info); } catch { warn( `Cannot load system font: ${info.baseFontName}, installing it could help to improve PDF rendering.` @@ -119,7 +120,7 @@ class FontLoader { font.attached = true; if (font.systemFontInfo) { - await this.loadSystemFont(font.systemFontInfo); + await this.loadSystemFont(font); return; } diff --git a/src/display/text_layer.js b/src/display/text_layer.js index ccf3eed31..d974ba8b6 100644 --- a/src/display/text_layer.js +++ b/src/display/text_layer.js @@ -172,9 +172,12 @@ function appendText(task, geom, styles) { if (style.vertical) { angle += Math.PI / 2; } + + const fontFamily = + (task._fontInspectorEnabled && style.fontSubstitution) || style.fontFamily; const fontHeight = Math.hypot(tx[2], tx[3]); const fontAscent = - fontHeight * getAscent(style.fontFamily, task._isOffscreenCanvasSupported); + fontHeight * getAscent(fontFamily, task._isOffscreenCanvasSupported); let left, top; if (angle === 0) { @@ -198,7 +201,7 @@ function appendText(task, geom, styles) { divStyle.top = `${scaleFactorStr}${top.toFixed(2)}px)`; } divStyle.fontSize = `${scaleFactorStr}${fontHeight.toFixed(2)}px)`; - divStyle.fontFamily = style.fontFamily; + divStyle.fontFamily = fontFamily; textDivProperties.fontSize = fontHeight; @@ -212,7 +215,8 @@ function appendText(task, geom, styles) { // `fontName` is only used by the FontInspector, and we only use `dataset` // here to make the font name available in the debugger. if (task._fontInspectorEnabled) { - textDiv.dataset.fontName = geom.fontName; + textDiv.dataset.fontName = + style.fontSubstitutionLoadedName || geom.fontName; } if (angle !== 0) { textDivProperties.angle = angle * (180 / Math.PI); diff --git a/web/app.js b/web/app.js index d5675e578..876e23490 100644 --- a/web/app.js +++ b/web/app.js @@ -1816,7 +1816,9 @@ const PDFViewerApplication = { this.pdfViewer.cleanup(); this.pdfThumbnailViewer?.cleanup(); - this.pdfDocument.cleanup(); + this.pdfDocument.cleanup( + /* keepLoadedFonts = */ AppOptions.get("fontExtraProperties") + ); }, forceRendering() { diff --git a/web/debugger.mjs b/web/debugger.mjs index 9fe79d8c1..59c1871b3 100644 --- a/web/debugger.mjs +++ b/web/debugger.mjs @@ -111,21 +111,29 @@ const FontInspector = (function FontInspectorClosure() { } return moreInfo; } - const moreInfo = properties(fontObj, ["name", "type"]); + + const moreInfo = fontObj.css + ? properties(fontObj, ["baseFontName"]) + : properties(fontObj, ["name", "type"]); + const fontName = fontObj.loadedName; const font = document.createElement("div"); const name = document.createElement("span"); name.textContent = fontName; - const download = document.createElement("a"); - if (url) { - url = /url\(['"]?([^)"']+)/.exec(url); - download.href = url[1]; - } else if (fontObj.data) { - download.href = URL.createObjectURL( - new Blob([fontObj.data], { type: fontObj.mimetype }) - ); + let download; + if (!fontObj.css) { + download = document.createElement("a"); + if (url) { + url = /url\(['"]?([^)"']+)/.exec(url); + download.href = url[1]; + } else if (fontObj.data) { + download.href = URL.createObjectURL( + new Blob([fontObj.data], { type: fontObj.mimetype }) + ); + } + download.textContent = "Download"; } - download.textContent = "Download"; + const logIt = document.createElement("a"); logIt.href = ""; logIt.textContent = "Log"; @@ -139,7 +147,11 @@ const FontInspector = (function FontInspectorClosure() { select.addEventListener("click", function () { selectFont(fontName, select.checked); }); - font.append(select, name, " ", download, " ", logIt, moreInfo); + if (download) { + font.append(select, name, " ", download, " ", logIt, moreInfo); + } else { + font.append(select, name, " ", logIt, moreInfo); + } fonts.append(font); // Somewhat of a hack, should probably add a hook for when the text layer // is done rendering.