Merge pull request #11777 from Snuffleupagus/Font-exportData-2
[api-minor] Change `Font.exportData` to, by default, stop exporting properties which are completely unused on the main-thread and/or in the API (PR 11773 follow-up)
This commit is contained in:
commit
9871ccc69f
@ -94,6 +94,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
nativeImageDecoderSupport: NativeImageDecoding.DECODE,
|
nativeImageDecoderSupport: NativeImageDecoding.DECODE,
|
||||||
ignoreErrors: false,
|
ignoreErrors: false,
|
||||||
isEvalSupported: true,
|
isEvalSupported: true,
|
||||||
|
fontExtraProperties: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line no-shadow
|
// eslint-disable-next-line no-shadow
|
||||||
@ -803,11 +804,12 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
this.handler.send("UnsupportedFeature", {
|
this.handler.send("UnsupportedFeature", {
|
||||||
featureId: UNSUPPORTED_FEATURES.font,
|
featureId: UNSUPPORTED_FEATURES.font,
|
||||||
});
|
});
|
||||||
return new TranslatedFont(
|
return new TranslatedFont({
|
||||||
"g_font_error",
|
loadedName: "g_font_error",
|
||||||
new ErrorFont("Type3 font load error: " + reason),
|
font: new ErrorFont(`Type3 font load error: ${reason}`),
|
||||||
translated.font
|
dict: translated.font,
|
||||||
);
|
extraProperties: this.options.fontExtraProperties,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(translated => {
|
.then(translated => {
|
||||||
@ -956,15 +958,16 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
loadFont: function PartialEvaluator_loadFont(fontName, font, resources) {
|
loadFont: function PartialEvaluator_loadFont(fontName, font, resources) {
|
||||||
function errorFont() {
|
const errorFont = () => {
|
||||||
return Promise.resolve(
|
return Promise.resolve(
|
||||||
new TranslatedFont(
|
new TranslatedFont({
|
||||||
"g_font_error",
|
loadedName: "g_font_error",
|
||||||
new ErrorFont("Font " + fontName + " is not available"),
|
font: new ErrorFont(`Font "${fontName}" is not available.`),
|
||||||
font
|
dict: font,
|
||||||
)
|
extraProperties: this.options.fontExtraProperties,
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
var fontRef,
|
var fontRef,
|
||||||
xref = this.xref;
|
xref = this.xref;
|
||||||
@ -1096,14 +1099,19 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
translatedPromise
|
translatedPromise
|
||||||
.then(function(translatedFont) {
|
.then(translatedFont => {
|
||||||
if (translatedFont.fontType !== undefined) {
|
if (translatedFont.fontType !== undefined) {
|
||||||
var xrefFontStats = xref.stats.fontTypes;
|
var xrefFontStats = xref.stats.fontTypes;
|
||||||
xrefFontStats[translatedFont.fontType] = true;
|
xrefFontStats[translatedFont.fontType] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fontCapability.resolve(
|
fontCapability.resolve(
|
||||||
new TranslatedFont(font.loadedName, translatedFont, font)
|
new TranslatedFont({
|
||||||
|
loadedName: font.loadedName,
|
||||||
|
font: translatedFont,
|
||||||
|
dict: font,
|
||||||
|
extraProperties: this.options.fontExtraProperties,
|
||||||
|
})
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
.catch(reason => {
|
.catch(reason => {
|
||||||
@ -1126,11 +1134,14 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
} catch (ex) {}
|
} catch (ex) {}
|
||||||
|
|
||||||
fontCapability.resolve(
|
fontCapability.resolve(
|
||||||
new TranslatedFont(
|
new TranslatedFont({
|
||||||
font.loadedName,
|
loadedName: font.loadedName,
|
||||||
new ErrorFont(reason instanceof Error ? reason.message : reason),
|
font: new ErrorFont(
|
||||||
font
|
reason instanceof Error ? reason.message : reason
|
||||||
)
|
),
|
||||||
|
dict: font,
|
||||||
|
extraProperties: this.options.fontExtraProperties,
|
||||||
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
return fontCapability.promise;
|
return fontCapability.promise;
|
||||||
@ -3266,107 +3277,105 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
return PartialEvaluator;
|
return PartialEvaluator;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
var TranslatedFont = (function TranslatedFontClosure() {
|
class TranslatedFont {
|
||||||
// eslint-disable-next-line no-shadow
|
constructor({ loadedName, font, dict, extraProperties = false }) {
|
||||||
function TranslatedFont(loadedName, font, dict) {
|
|
||||||
this.loadedName = loadedName;
|
this.loadedName = loadedName;
|
||||||
this.font = font;
|
this.font = font;
|
||||||
this.dict = dict;
|
this.dict = dict;
|
||||||
|
this._extraProperties = extraProperties;
|
||||||
this.type3Loaded = null;
|
this.type3Loaded = null;
|
||||||
this.sent = false;
|
this.sent = false;
|
||||||
}
|
}
|
||||||
TranslatedFont.prototype = {
|
|
||||||
send(handler) {
|
|
||||||
if (this.sent) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.sent = true;
|
|
||||||
|
|
||||||
handler.send("commonobj", [
|
send(handler) {
|
||||||
this.loadedName,
|
if (this.sent) {
|
||||||
"Font",
|
return;
|
||||||
this.font.exportData(),
|
}
|
||||||
]);
|
this.sent = true;
|
||||||
},
|
|
||||||
|
|
||||||
fallback(handler) {
|
handler.send("commonobj", [
|
||||||
if (!this.font.data) {
|
this.loadedName,
|
||||||
return;
|
"Font",
|
||||||
}
|
this.font.exportData(this._extraProperties),
|
||||||
// When font loading failed, fall back to the built-in font renderer.
|
]);
|
||||||
this.font.disableFontFace = true;
|
}
|
||||||
// An arbitrary number of text rendering operators could have been
|
|
||||||
// encountered between the point in time when the 'Font' message was sent
|
|
||||||
// to the main-thread, and the point in time when the 'FontFallback'
|
|
||||||
// message was received on the worker-thread.
|
|
||||||
// To ensure that all 'FontPath's are available on the main-thread, when
|
|
||||||
// font loading failed, attempt to resend *all* previously parsed glyphs.
|
|
||||||
const glyphs = this.font.glyphCacheValues;
|
|
||||||
PartialEvaluator.buildFontPaths(this.font, glyphs, handler);
|
|
||||||
},
|
|
||||||
|
|
||||||
loadType3Data(evaluator, resources, parentOperatorList, task) {
|
fallback(handler) {
|
||||||
if (!this.font.isType3Font) {
|
if (!this.font.data) {
|
||||||
throw new Error("Must be a Type3 font.");
|
return;
|
||||||
}
|
}
|
||||||
|
// When font loading failed, fall back to the built-in font renderer.
|
||||||
|
this.font.disableFontFace = true;
|
||||||
|
// An arbitrary number of text rendering operators could have been
|
||||||
|
// encountered between the point in time when the 'Font' message was sent
|
||||||
|
// to the main-thread, and the point in time when the 'FontFallback'
|
||||||
|
// message was received on the worker-thread.
|
||||||
|
// To ensure that all 'FontPath's are available on the main-thread, when
|
||||||
|
// font loading failed, attempt to resend *all* previously parsed glyphs.
|
||||||
|
const glyphs = this.font.glyphCacheValues;
|
||||||
|
PartialEvaluator.buildFontPaths(this.font, glyphs, handler);
|
||||||
|
}
|
||||||
|
|
||||||
if (this.type3Loaded) {
|
loadType3Data(evaluator, resources, parentOperatorList, task) {
|
||||||
return this.type3Loaded;
|
if (!this.font.isType3Font) {
|
||||||
}
|
throw new Error("Must be a Type3 font.");
|
||||||
// When parsing Type3 glyphs, always ignore them if there are errors.
|
}
|
||||||
// Compared to the parsing of e.g. an entire page, it doesn't really
|
|
||||||
// make sense to only be able to render a Type3 glyph partially.
|
|
||||||
//
|
|
||||||
// Also, ensure that any Type3 image resources (which should be very rare
|
|
||||||
// in practice) are completely decoded on the worker-thread, to simplify
|
|
||||||
// the rendering code on the main-thread (see issue10717.pdf).
|
|
||||||
var type3Options = Object.create(evaluator.options);
|
|
||||||
type3Options.ignoreErrors = false;
|
|
||||||
type3Options.nativeImageDecoderSupport = NativeImageDecoding.NONE;
|
|
||||||
var type3Evaluator = evaluator.clone(type3Options);
|
|
||||||
type3Evaluator.parsingType3Font = true;
|
|
||||||
|
|
||||||
var translatedFont = this.font;
|
if (this.type3Loaded) {
|
||||||
var loadCharProcsPromise = Promise.resolve();
|
|
||||||
var charProcs = this.dict.get("CharProcs");
|
|
||||||
var fontResources = this.dict.get("Resources") || resources;
|
|
||||||
var charProcKeys = charProcs.getKeys();
|
|
||||||
var charProcOperatorList = Object.create(null);
|
|
||||||
|
|
||||||
for (var i = 0, n = charProcKeys.length; i < n; ++i) {
|
|
||||||
const key = charProcKeys[i];
|
|
||||||
loadCharProcsPromise = loadCharProcsPromise.then(function() {
|
|
||||||
var glyphStream = charProcs.get(key);
|
|
||||||
var operatorList = new OperatorList();
|
|
||||||
return type3Evaluator
|
|
||||||
.getOperatorList({
|
|
||||||
stream: glyphStream,
|
|
||||||
task,
|
|
||||||
resources: fontResources,
|
|
||||||
operatorList,
|
|
||||||
})
|
|
||||||
.then(function() {
|
|
||||||
charProcOperatorList[key] = operatorList.getIR();
|
|
||||||
|
|
||||||
// Add the dependencies to the parent operator list so they are
|
|
||||||
// resolved before sub operator list is executed synchronously.
|
|
||||||
parentOperatorList.addDependencies(operatorList.dependencies);
|
|
||||||
})
|
|
||||||
.catch(function(reason) {
|
|
||||||
warn(`Type3 font resource "${key}" is not available.`);
|
|
||||||
const dummyOperatorList = new OperatorList();
|
|
||||||
charProcOperatorList[key] = dummyOperatorList.getIR();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.type3Loaded = loadCharProcsPromise.then(function() {
|
|
||||||
translatedFont.charProcOperatorList = charProcOperatorList;
|
|
||||||
});
|
|
||||||
return this.type3Loaded;
|
return this.type3Loaded;
|
||||||
},
|
}
|
||||||
};
|
// When parsing Type3 glyphs, always ignore them if there are errors.
|
||||||
return TranslatedFont;
|
// Compared to the parsing of e.g. an entire page, it doesn't really
|
||||||
})();
|
// make sense to only be able to render a Type3 glyph partially.
|
||||||
|
//
|
||||||
|
// Also, ensure that any Type3 image resources (which should be very rare
|
||||||
|
// in practice) are completely decoded on the worker-thread, to simplify
|
||||||
|
// the rendering code on the main-thread (see issue10717.pdf).
|
||||||
|
var type3Options = Object.create(evaluator.options);
|
||||||
|
type3Options.ignoreErrors = false;
|
||||||
|
type3Options.nativeImageDecoderSupport = NativeImageDecoding.NONE;
|
||||||
|
var type3Evaluator = evaluator.clone(type3Options);
|
||||||
|
type3Evaluator.parsingType3Font = true;
|
||||||
|
|
||||||
|
var translatedFont = this.font;
|
||||||
|
var loadCharProcsPromise = Promise.resolve();
|
||||||
|
var charProcs = this.dict.get("CharProcs");
|
||||||
|
var fontResources = this.dict.get("Resources") || resources;
|
||||||
|
var charProcKeys = charProcs.getKeys();
|
||||||
|
var charProcOperatorList = Object.create(null);
|
||||||
|
|
||||||
|
for (var i = 0, n = charProcKeys.length; i < n; ++i) {
|
||||||
|
const key = charProcKeys[i];
|
||||||
|
loadCharProcsPromise = loadCharProcsPromise.then(function() {
|
||||||
|
var glyphStream = charProcs.get(key);
|
||||||
|
var operatorList = new OperatorList();
|
||||||
|
return type3Evaluator
|
||||||
|
.getOperatorList({
|
||||||
|
stream: glyphStream,
|
||||||
|
task,
|
||||||
|
resources: fontResources,
|
||||||
|
operatorList,
|
||||||
|
})
|
||||||
|
.then(function() {
|
||||||
|
charProcOperatorList[key] = operatorList.getIR();
|
||||||
|
|
||||||
|
// Add the dependencies to the parent operator list so they are
|
||||||
|
// resolved before sub operator list is executed synchronously.
|
||||||
|
parentOperatorList.addDependencies(operatorList.dependencies);
|
||||||
|
})
|
||||||
|
.catch(function(reason) {
|
||||||
|
warn(`Type3 font resource "${key}" is not available.`);
|
||||||
|
const dummyOperatorList = new OperatorList();
|
||||||
|
charProcOperatorList[key] = dummyOperatorList.getIR();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.type3Loaded = loadCharProcsPromise.then(function() {
|
||||||
|
translatedFont.charProcOperatorList = charProcOperatorList;
|
||||||
|
});
|
||||||
|
return this.type3Loaded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var StateManager = (function StateManagerClosure() {
|
var StateManager = (function StateManagerClosure() {
|
||||||
// eslint-disable-next-line no-shadow
|
// eslint-disable-next-line no-shadow
|
||||||
|
@ -92,21 +92,17 @@ const EXPORT_DATA_PROPERTIES = [
|
|||||||
"bbox",
|
"bbox",
|
||||||
"black",
|
"black",
|
||||||
"bold",
|
"bold",
|
||||||
"cMap",
|
|
||||||
"charProcOperatorList",
|
"charProcOperatorList",
|
||||||
"composite",
|
"composite",
|
||||||
"data",
|
"data",
|
||||||
"defaultEncoding",
|
|
||||||
"defaultVMetrics",
|
"defaultVMetrics",
|
||||||
"defaultWidth",
|
"defaultWidth",
|
||||||
"descent",
|
"descent",
|
||||||
"differences",
|
|
||||||
"fallbackName",
|
"fallbackName",
|
||||||
"fontMatrix",
|
"fontMatrix",
|
||||||
"fontType",
|
"fontType",
|
||||||
"isMonospace",
|
"isMonospace",
|
||||||
"isSerifFont",
|
"isSerifFont",
|
||||||
"isSymbolicFont",
|
|
||||||
"isType3Font",
|
"isType3Font",
|
||||||
"italic",
|
"italic",
|
||||||
"loadedName",
|
"loadedName",
|
||||||
@ -114,12 +110,19 @@ const EXPORT_DATA_PROPERTIES = [
|
|||||||
"missingFile",
|
"missingFile",
|
||||||
"name",
|
"name",
|
||||||
"remeasure",
|
"remeasure",
|
||||||
"seacMap",
|
|
||||||
"subtype",
|
"subtype",
|
||||||
"toFontChar",
|
|
||||||
"toUnicode",
|
|
||||||
"type",
|
"type",
|
||||||
"vertical",
|
"vertical",
|
||||||
|
];
|
||||||
|
|
||||||
|
const EXPORT_DATA_EXTRA_PROPERTIES = [
|
||||||
|
"cMap",
|
||||||
|
"defaultEncoding",
|
||||||
|
"differences",
|
||||||
|
"isSymbolicFont",
|
||||||
|
"seacMap",
|
||||||
|
"toFontChar",
|
||||||
|
"toUnicode",
|
||||||
"vmetrics",
|
"vmetrics",
|
||||||
"widths",
|
"widths",
|
||||||
];
|
];
|
||||||
@ -1295,10 +1298,14 @@ var Font = (function FontClosure() {
|
|||||||
return shadow(this, "renderer", renderer);
|
return shadow(this, "renderer", renderer);
|
||||||
},
|
},
|
||||||
|
|
||||||
exportData() {
|
exportData(extraProperties = false) {
|
||||||
|
const exportDataProperties = extraProperties
|
||||||
|
? [...EXPORT_DATA_PROPERTIES, ...EXPORT_DATA_EXTRA_PROPERTIES]
|
||||||
|
: EXPORT_DATA_PROPERTIES;
|
||||||
|
|
||||||
const data = Object.create(null);
|
const data = Object.create(null);
|
||||||
let property, value;
|
let property, value;
|
||||||
for (property of EXPORT_DATA_PROPERTIES) {
|
for (property of exportDataProperties) {
|
||||||
value = this[property];
|
value = this[property];
|
||||||
// Ignore properties that haven't been explicitly set.
|
// Ignore properties that haven't been explicitly set.
|
||||||
if (value !== undefined) {
|
if (value !== undefined) {
|
||||||
@ -3352,7 +3359,7 @@ var ErrorFont = (function ErrorFontClosure() {
|
|||||||
charsToGlyphs: function ErrorFont_charsToGlyphs() {
|
charsToGlyphs: function ErrorFont_charsToGlyphs() {
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
exportData: function ErrorFont_exportData() {
|
exportData(extraProperties = false) {
|
||||||
return { error: this.error };
|
return { error: this.error };
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -403,6 +403,7 @@ var WorkerMessageHandler = {
|
|||||||
nativeImageDecoderSupport: data.nativeImageDecoderSupport,
|
nativeImageDecoderSupport: data.nativeImageDecoderSupport,
|
||||||
ignoreErrors: data.ignoreErrors,
|
ignoreErrors: data.ignoreErrors,
|
||||||
isEvalSupported: data.isEvalSupported,
|
isEvalSupported: data.isEvalSupported,
|
||||||
|
fontExtraProperties: data.fontExtraProperties,
|
||||||
};
|
};
|
||||||
|
|
||||||
getPdfManager(data, evaluatorOptions)
|
getPdfManager(data, evaluatorOptions)
|
||||||
|
@ -145,6 +145,11 @@ function setPDFNetworkStreamFactory(pdfNetworkStreamFactory) {
|
|||||||
* converted to OpenType fonts and loaded via font face rules. If disabled,
|
* converted to OpenType fonts and loaded via font face rules. If disabled,
|
||||||
* fonts will be rendered using a built-in font renderer that constructs the
|
* fonts will be rendered using a built-in font renderer that constructs the
|
||||||
* glyphs with primitive path commands. The default value is `false`.
|
* glyphs with primitive path commands. The default value is `false`.
|
||||||
|
* @property {boolean} [fontExtraProperties] - Include additional properties,
|
||||||
|
* which are unused during rendering of PDF documents, when exporting the
|
||||||
|
* parsed font data from the worker-thread. This may be useful for debugging
|
||||||
|
* purposes (and backwards compatibility), but note that it will lead to
|
||||||
|
* increased memory usage. The default value is `false`.
|
||||||
* @property {boolean} [disableRange] - Disable range request loading
|
* @property {boolean} [disableRange] - Disable range request loading
|
||||||
* of PDF files. When enabled, and if the server supports partial content
|
* of PDF files. When enabled, and if the server supports partial content
|
||||||
* requests, then the PDF will be fetched in chunks.
|
* requests, then the PDF will be fetched in chunks.
|
||||||
@ -251,6 +256,7 @@ function getDocument(src) {
|
|||||||
params.rangeChunkSize = params.rangeChunkSize || DEFAULT_RANGE_CHUNK_SIZE;
|
params.rangeChunkSize = params.rangeChunkSize || DEFAULT_RANGE_CHUNK_SIZE;
|
||||||
params.CMapReaderFactory = params.CMapReaderFactory || DOMCMapReaderFactory;
|
params.CMapReaderFactory = params.CMapReaderFactory || DOMCMapReaderFactory;
|
||||||
params.ignoreErrors = params.stopAtErrors !== true;
|
params.ignoreErrors = params.stopAtErrors !== true;
|
||||||
|
params.fontExtraProperties = params.fontExtraProperties === true;
|
||||||
params.pdfBug = params.pdfBug === true;
|
params.pdfBug = params.pdfBug === true;
|
||||||
|
|
||||||
const NativeImageDecoderValues = Object.values(NativeImageDecoding);
|
const NativeImageDecoderValues = Object.values(NativeImageDecoding);
|
||||||
@ -403,6 +409,7 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
|
|||||||
nativeImageDecoderSupport: source.nativeImageDecoderSupport,
|
nativeImageDecoderSupport: source.nativeImageDecoderSupport,
|
||||||
ignoreErrors: source.ignoreErrors,
|
ignoreErrors: source.ignoreErrors,
|
||||||
isEvalSupported: source.isEvalSupported,
|
isEvalSupported: source.isEvalSupported,
|
||||||
|
fontExtraProperties: source.fontExtraProperties,
|
||||||
})
|
})
|
||||||
.then(function(workerId) {
|
.then(function(workerId) {
|
||||||
if (worker.destroyed) {
|
if (worker.destroyed) {
|
||||||
|
@ -309,6 +309,8 @@ const PDFViewerApplication = {
|
|||||||
}
|
}
|
||||||
if ("pdfbug" in hashParams) {
|
if ("pdfbug" in hashParams) {
|
||||||
AppOptions.set("pdfBug", true);
|
AppOptions.set("pdfBug", true);
|
||||||
|
AppOptions.set("fontExtraProperties", true);
|
||||||
|
|
||||||
const enabled = hashParams["pdfbug"].split(",");
|
const enabled = hashParams["pdfbug"].split(",");
|
||||||
waitOn.push(loadAndEnablePDFBug(enabled));
|
waitOn.push(loadAndEnablePDFBug(enabled));
|
||||||
}
|
}
|
||||||
|
@ -193,6 +193,11 @@ const defaultOptions = {
|
|||||||
value: "",
|
value: "",
|
||||||
kind: OptionKind.API,
|
kind: OptionKind.API,
|
||||||
},
|
},
|
||||||
|
fontExtraProperties: {
|
||||||
|
/** @type {boolean} */
|
||||||
|
value: false,
|
||||||
|
kind: OptionKind.API,
|
||||||
|
},
|
||||||
isEvalSupported: {
|
isEvalSupported: {
|
||||||
/** @type {boolean} */
|
/** @type {boolean} */
|
||||||
value: true,
|
value: true,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user