1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-29 07:37:57 +02:00

Merge pull request #13644 from calixteman/xfa_missing_fonts

XFA - Support non-embedded fonts without a Widths entry
This commit is contained in:
calixteman 2021-06-28 23:46:09 +02:00 committed by GitHub
commit 04dc902933
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 464 additions and 59 deletions

View file

@ -17,6 +17,7 @@ import { $globalData, $toHTML } from "./xfa_object.js";
import { Binder } from "./bind.js";
import { DataHandler } from "./data.js";
import { FontFinder } from "./fonts.js";
import { stripQuotes } from "./utils.js";
import { warn } from "../../shared/util.js";
import { XFAParser } from "./parser.js";
@ -62,6 +63,24 @@ class XFAFactory {
setFonts(fonts) {
this.form[$globalData].fontFinder = new FontFinder(fonts);
const missingFonts = [];
for (let typeface of this.form[$globalData].usedTypefaces) {
typeface = stripQuotes(typeface);
const font = this.form[$globalData].fontFinder.find(typeface);
if (!font) {
missingFonts.push(typeface);
}
}
if (missingFonts.length > 0) {
return missingFonts;
}
return null;
}
appendFonts(fonts) {
this.form[$globalData].fontFinder.add(fonts);
}
getPages() {

View file

@ -21,53 +21,13 @@ class FontFinder {
this.cache = new Map();
this.warned = new Set();
this.defaultFont = null;
this.add(pdfFonts);
}
add(pdfFonts) {
for (const pdfFont of pdfFonts) {
const cssFontInfo = pdfFont.cssFontInfo;
const name = cssFontInfo.fontFamily;
let font = this.fonts.get(name);
if (!font) {
font = Object.create(null);
this.fonts.set(name, font);
if (!this.defaultFont) {
this.defaultFont = font;
}
}
let property = "";
if (cssFontInfo.italicAngle !== "0") {
if (parseFloat(cssFontInfo.fontWeight) >= 700) {
property = "bolditalic";
} else {
property = "italic";
}
} else if (parseFloat(cssFontInfo.fontWeight) >= 700) {
property = "bold";
}
if (!property) {
if (
pdfFont.name.includes("Bold") ||
(pdfFont.psName && pdfFont.psName.includes("Bold"))
) {
property = "bold";
}
if (
pdfFont.name.includes("Italic") ||
pdfFont.name.endsWith("It") ||
(pdfFont.psName &&
(pdfFont.psName.includes("Italic") ||
pdfFont.psName.endsWith("It")))
) {
property += "italic";
}
}
if (!property) {
property = "regular";
}
font[property] = pdfFont;
this.addPdfFont(pdfFont);
}
for (const pdfFont of this.fonts.values()) {
if (!pdfFont.regular) {
pdfFont.regular = pdfFont.italic || pdfFont.bold || pdfFont.bolditalic;
@ -75,6 +35,52 @@ class FontFinder {
}
}
addPdfFont(pdfFont) {
const cssFontInfo = pdfFont.cssFontInfo;
const name = cssFontInfo.fontFamily;
let font = this.fonts.get(name);
if (!font) {
font = Object.create(null);
this.fonts.set(name, font);
if (!this.defaultFont) {
this.defaultFont = font;
}
}
let property = "";
if (cssFontInfo.italicAngle !== "0") {
if (parseFloat(cssFontInfo.fontWeight) >= 700) {
property = "bolditalic";
} else {
property = "italic";
}
} else if (parseFloat(cssFontInfo.fontWeight) >= 700) {
property = "bold";
}
if (!property) {
if (
pdfFont.name.includes("Bold") ||
(pdfFont.psName && pdfFont.psName.includes("Bold"))
) {
property = "bold";
}
if (
pdfFont.name.includes("Italic") ||
pdfFont.name.endsWith("It") ||
(pdfFont.psName &&
(pdfFont.psName.includes("Italic") || pdfFont.psName.endsWith("It")))
) {
property += "italic";
}
}
if (!property) {
property = "regular";
}
font[property] = pdfFont;
}
getDefault() {
return this.defaultFont;
}

View file

@ -34,7 +34,9 @@ class XFAParser extends XMLParserBase {
super();
this._builder = new Builder();
this._stack = [];
this._globalData = Object.create(null);
this._globalData = {
usedTypefaces: new Set(),
};
this._ids = new Map();
this._current = this._builder.buildRoot(this._ids);
this._errorCode = XMLParserErrorCode.NoError;

View file

@ -2665,6 +2665,11 @@ class Font extends XFAObject {
this.fill = null;
}
[$clean](builder) {
super[$clean](builder);
this[$globalData].usedTypefaces.add(this.typeface);
}
[$toStyle]() {
const style = toStyle(this, "fill");
const color = style.color;

View file

@ -16,6 +16,7 @@
import {
$acceptWhitespace,
$childrenToHTML,
$clean,
$content,
$extra,
$getChildren,
@ -144,18 +145,23 @@ function mapStyle(styleStr, fontFinder) {
return style;
}
function checkStyle(style) {
if (!style) {
function checkStyle(node) {
if (!node.style) {
return "";
}
// Remove any non-allowed keys.
return style
return node.style
.trim()
.split(/\s*;\s*/)
.filter(s => !!s)
.map(s => s.split(/\s*:\s*/, 2))
.filter(([key]) => VALID_STYLES.has(key))
.filter(([key, value]) => {
if (key === "font-family") {
node[$globalData].usedTypefaces.add(value);
}
return VALID_STYLES.has(key);
})
.map(kv => kv.join(":"))
.join(";");
}
@ -165,7 +171,12 @@ const NoWhites = new Set(["body", "html"]);
class XhtmlObject extends XmlObject {
constructor(attributes, name) {
super(XHTML_NS_ID, name);
this.style = checkStyle(attributes.style);
this.style = attributes.style || "";
}
[$clean](builder) {
super[$clean](builder);
this.style = checkStyle(this);
}
[$acceptWhitespace]() {