Slightly refactor the fontRef
handling in PartialEvaluator_loadFont
(issue 7403 and issue 7402)
Originally, I was just going to change this code to use `Ref_toString` in a couple more places. When I started reading the code, I figured that it wouldn't hurt to clean up a couple of comments. While doing this, I noticed that the logic for the (rare) `isDict(fontRef)` case could do with a few improvements. There should be no functional changes with this patch, but given the added reference checks, we will now avoid bogus `Ref`s when resolving font aliases. In practice, as issue 7403 shows, the current code can break certain PDF files even if it's very rare. Note that the only thing that this patch will change, is the `font.loadedName` in the case where a `fontRef` is a reference *and* the font doesn't have a descriptor. Previously for `fontRef = Ref(4, 0)` we'd get `font.loadedName = 'g_d0_f4_0'`, and with this patch `font.loadedName = g_d0_f4R`, which is actually one character shorted in most cases. (Given that `Ref_toString` contains an optimization for the `gen === 0` case, which is by far the most common `gen` value.) In the already existing fallback case, where the `fontName` is used to when creating the `font.loadedName`, we allow any alphanumeric character. Hence I don't see how (as mentioned above) e.g. `font.loadedName = g_d0_f4R` would be an issue here.
This commit is contained in:
parent
10f9f11ec4
commit
2e9cd3ea64
@ -662,8 +662,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
||||
return errorFont();
|
||||
}
|
||||
|
||||
// We are holding font.translated references just for fontRef that are not
|
||||
// dictionaries (Dict). See explanation below.
|
||||
// We are holding `font.translated` references just for `fontRef`s that
|
||||
// are not actually `Ref`s, but rather `Dict`s. See explanation below.
|
||||
if (font.translated) {
|
||||
return font.translated;
|
||||
}
|
||||
@ -672,7 +672,12 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
||||
|
||||
var preEvaluatedFont = this.preEvaluateFont(font, xref);
|
||||
var descriptor = preEvaluatedFont.descriptor;
|
||||
var fontID = fontRef.num + '_' + fontRef.gen;
|
||||
|
||||
var fontRefIsRef = isRef(fontRef), fontID;
|
||||
if (fontRefIsRef) {
|
||||
fontID = fontRef.toString();
|
||||
}
|
||||
|
||||
if (isDict(descriptor)) {
|
||||
if (!descriptor.fontAliases) {
|
||||
descriptor.fontAliases = Object.create(null);
|
||||
@ -682,36 +687,40 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
||||
var hash = preEvaluatedFont.hash;
|
||||
if (fontAliases[hash]) {
|
||||
var aliasFontRef = fontAliases[hash].aliasRef;
|
||||
if (aliasFontRef && this.fontCache.has(aliasFontRef)) {
|
||||
if (fontRefIsRef && aliasFontRef &&
|
||||
this.fontCache.has(aliasFontRef)) {
|
||||
this.fontCache.putAlias(fontRef, aliasFontRef);
|
||||
return this.fontCache.get(fontRef);
|
||||
}
|
||||
}
|
||||
|
||||
if (!fontAliases[hash]) {
|
||||
} else {
|
||||
fontAliases[hash] = {
|
||||
fontID: Font.getFontID()
|
||||
};
|
||||
}
|
||||
|
||||
fontAliases[hash].aliasRef = fontRef;
|
||||
if (fontRefIsRef) {
|
||||
fontAliases[hash].aliasRef = fontRef;
|
||||
}
|
||||
fontID = fontAliases[hash].fontID;
|
||||
}
|
||||
|
||||
// Workaround for bad PDF generators that don't reference fonts
|
||||
// properly, i.e. by not using an object identifier.
|
||||
// Check if the fontRef is a Dict (as opposed to a standard object),
|
||||
// in which case we don't cache the font and instead reference it by
|
||||
// fontName in font.loadedName below.
|
||||
var fontRefIsDict = isDict(fontRef);
|
||||
if (!fontRefIsDict) {
|
||||
// Workaround for bad PDF generators that reference fonts incorrectly,
|
||||
// where `fontRef` is a `Dict` rather than a `Ref` (fixes bug946506.pdf).
|
||||
// In this case we cannot cache the font, since it's not possible to use
|
||||
// a `Dict` as a key in `this.fontCache` (since it's a `RefSetCache`).
|
||||
// Furthermore, if the `fontID` is undefined, we instead reference
|
||||
// the font by `fontName` in `font.loadedName` below.
|
||||
if (fontRefIsRef) {
|
||||
this.fontCache.put(fontRef, fontCapability.promise);
|
||||
} else {
|
||||
if (!fontID) {
|
||||
fontID = (this.uniquePrefix || 'F_') + (++this.idCounters.obj);
|
||||
}
|
||||
}
|
||||
|
||||
// Keep track of each font we translated so the caller can
|
||||
// load them asynchronously before calling display on a page.
|
||||
font.loadedName = 'g_' + this.pdfManager.docId + '_f' + (fontRefIsDict ?
|
||||
fontName.replace(/\W/g, '') : fontID);
|
||||
font.loadedName = 'g_' + this.pdfManager.docId + '_f' + fontID;
|
||||
|
||||
font.translated = fontCapability.promise;
|
||||
|
||||
@ -2115,7 +2124,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
||||
if (isName(encoding)) {
|
||||
hash.update(encoding.name);
|
||||
} else if (isRef(encoding)) {
|
||||
hash.update(encoding.num + '_' + encoding.gen);
|
||||
hash.update(encoding.toString());
|
||||
} else if (isDict(encoding)) {
|
||||
var keys = encoding.getKeys();
|
||||
for (var i = 0, ii = keys.length; i < ii; i++) {
|
||||
@ -2123,7 +2132,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
||||
if (isName(entry)) {
|
||||
hash.update(entry.name);
|
||||
} else if (isRef(entry)) {
|
||||
hash.update(entry.num + '_' + entry.gen);
|
||||
hash.update(entry.toString());
|
||||
} else if (isArray(entry)) { // 'Differences' entry.
|
||||
// Ideally we should check the contents of the array, but to avoid
|
||||
// parsing it here and then again in |extractDataStructures|,
|
||||
|
Loading…
x
Reference in New Issue
Block a user