[api-minor] Add intent
support to the PDFPageProxy.getOperatorList
method (issue 13704)
With this patch, the `PDFPageProxy.getOperatorList` method will now return `PDFOperatorList`-instances that also include Annotation-operatorLists (when those exist). Hence this closes a small, but potentially confusing, gap between the `render` and `getOperatorList` methods. Previously we've been somewhat reluctant to do this, as explained below, but given that there's actual use-cases where it's required probably means that we'll *have* to implement it now. Since we still need the ability to separate "normal" rendering operations from direct `getOperatorList` calls in the worker-thread, this API-change unfortunately causes the *internal* renderingIntent to become a bit "messy" which is indeed unfortunate (note the `"oplist-"` strings in various spots). As-is I suppose that it's not all that bad, but we may want to consider changing the *internal* renderingIntent to e.g. a bitfield in the future. Besides fixing issue 13704, this patch would also be necessary if someone ever tries to implement e.g. issue 10165 (since currently `PDFPageProxy.getOperatorList` doesn't include Annotation-operatorLists). *Please note:* This patch is *also* tagged "api-minor" for a second reason, which is that we're now including the Annotation-id in the `beginAnnotation` argument. The reason for this is to allow correlating the Annotation-data returned by `PDFPageProxy.getAnnotations`, with its corresponding operatorList-data (for those Annotations that have it).
This commit is contained in:
parent
f1ae7d7b0e
commit
03cf28bf17
@ -702,7 +702,13 @@ class Annotation {
|
|||||||
|
|
||||||
return resourcesPromise.then(resources => {
|
return resourcesPromise.then(resources => {
|
||||||
const opList = new OperatorList();
|
const opList = new OperatorList();
|
||||||
opList.addOp(OPS.beginAnnotation, [data.rect, transform, matrix]);
|
opList.addOp(OPS.beginAnnotation, [
|
||||||
|
data.id,
|
||||||
|
data.rect,
|
||||||
|
transform,
|
||||||
|
matrix,
|
||||||
|
]);
|
||||||
|
|
||||||
return evaluator
|
return evaluator
|
||||||
.getOperatorList({
|
.getOperatorList({
|
||||||
stream: appearance,
|
stream: appearance,
|
||||||
@ -1307,6 +1313,7 @@ class WidgetAnnotation extends Annotation {
|
|||||||
|
|
||||||
const transform = getTransformMatrix(this.data.rect, bbox, matrix);
|
const transform = getTransformMatrix(this.data.rect, bbox, matrix);
|
||||||
operatorList.addOp(OPS.beginAnnotation, [
|
operatorList.addOp(OPS.beginAnnotation, [
|
||||||
|
this.data.id,
|
||||||
this.data.rect,
|
this.data.rect,
|
||||||
transform,
|
transform,
|
||||||
matrix,
|
matrix,
|
||||||
|
@ -366,12 +366,16 @@ class Page {
|
|||||||
|
|
||||||
// Collect the operator list promises for the annotations. Each promise
|
// Collect the operator list promises for the annotations. Each promise
|
||||||
// is resolved with the complete operator list for a single annotation.
|
// is resolved with the complete operator list for a single annotation.
|
||||||
|
const annotationIntent = intent.startsWith("oplist-")
|
||||||
|
? intent.split("-")[1]
|
||||||
|
: intent;
|
||||||
const opListPromises = [];
|
const opListPromises = [];
|
||||||
for (const annotation of annotations) {
|
for (const annotation of annotations) {
|
||||||
if (
|
if (
|
||||||
(intent === "display" &&
|
(annotationIntent === "display" &&
|
||||||
annotation.mustBeViewed(annotationStorage)) ||
|
annotation.mustBeViewed(annotationStorage)) ||
|
||||||
(intent === "print" && annotation.mustBePrinted(annotationStorage))
|
(annotationIntent === "print" &&
|
||||||
|
annotation.mustBePrinted(annotationStorage))
|
||||||
) {
|
) {
|
||||||
opListPromises.push(
|
opListPromises.push(
|
||||||
annotation
|
annotation
|
||||||
|
@ -594,14 +594,14 @@ class OperatorList {
|
|||||||
|
|
||||||
// Close to chunk size.
|
// Close to chunk size.
|
||||||
static get CHUNK_SIZE_ABOUT() {
|
static get CHUNK_SIZE_ABOUT() {
|
||||||
return shadow(this, "CHUNK_SIZE_ABOUT", OperatorList.CHUNK_SIZE - 5);
|
return shadow(this, "CHUNK_SIZE_ABOUT", this.CHUNK_SIZE - 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(intent, streamSink) {
|
constructor(intent, streamSink) {
|
||||||
this._streamSink = streamSink;
|
this._streamSink = streamSink;
|
||||||
this.fnArray = [];
|
this.fnArray = [];
|
||||||
this.argsArray = [];
|
this.argsArray = [];
|
||||||
if (streamSink && intent !== "oplist") {
|
if (streamSink && !(intent && intent.startsWith("oplist-"))) {
|
||||||
this.optimizer = new QueueOptimizer(this);
|
this.optimizer = new QueueOptimizer(this);
|
||||||
} else {
|
} else {
|
||||||
this.optimizer = new NullOptimizer(this);
|
this.optimizer = new NullOptimizer(this);
|
||||||
|
@ -1149,7 +1149,7 @@ class PDFDocumentProxy {
|
|||||||
* Page annotation parameters.
|
* Page annotation parameters.
|
||||||
*
|
*
|
||||||
* @typedef {Object} GetAnnotationsParameters
|
* @typedef {Object} GetAnnotationsParameters
|
||||||
* @property {string} intent - Determines the annotations that will be fetched,
|
* @property {string} [intent] - Determines the annotations that are fetched,
|
||||||
* can be either 'display' (viewable annotations) or 'print' (printable
|
* can be either 'display' (viewable annotations) or 'print' (printable
|
||||||
* annotations). If the parameter is omitted, all annotations are fetched.
|
* annotations). If the parameter is omitted, all annotations are fetched.
|
||||||
*/
|
*/
|
||||||
@ -1187,6 +1187,14 @@ class PDFDocumentProxy {
|
|||||||
* states set.
|
* states set.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page getOperatorList parameters.
|
||||||
|
*
|
||||||
|
* @typedef {Object} GetOperatorListParameters
|
||||||
|
* @property {string} [intent] - Rendering intent, can be 'display' or 'print'.
|
||||||
|
* The default value is 'display'.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Structure tree node. The root node will have a role "Root".
|
* Structure tree node. The root node will have a role "Root".
|
||||||
*
|
*
|
||||||
@ -1299,12 +1307,18 @@ class PDFPageProxy {
|
|||||||
* {Array} of the annotation objects.
|
* {Array} of the annotation objects.
|
||||||
*/
|
*/
|
||||||
getAnnotations({ intent = null } = {}) {
|
getAnnotations({ intent = null } = {}) {
|
||||||
if (!this._annotationsPromise || this._annotationsIntent !== intent) {
|
const renderingIntent =
|
||||||
|
intent === "display" || intent === "print" ? intent : null;
|
||||||
|
|
||||||
|
if (
|
||||||
|
!this._annotationsPromise ||
|
||||||
|
this._annotationsIntent !== renderingIntent
|
||||||
|
) {
|
||||||
this._annotationsPromise = this._transport.getAnnotations(
|
this._annotationsPromise = this._transport.getAnnotations(
|
||||||
this._pageIndex,
|
this._pageIndex,
|
||||||
intent
|
renderingIntent
|
||||||
);
|
);
|
||||||
this._annotationsIntent = intent;
|
this._annotationsIntent = renderingIntent;
|
||||||
}
|
}
|
||||||
return this._annotationsPromise;
|
return this._annotationsPromise;
|
||||||
}
|
}
|
||||||
@ -1332,7 +1346,7 @@ class PDFPageProxy {
|
|||||||
/**
|
/**
|
||||||
* Begins the process of rendering a page to the desired context.
|
* Begins the process of rendering a page to the desired context.
|
||||||
*
|
*
|
||||||
* @param {RenderParameters} params Page render parameters.
|
* @param {RenderParameters} params - Page render parameters.
|
||||||
* @returns {RenderTask} An object that contains a promise that is
|
* @returns {RenderTask} An object that contains a promise that is
|
||||||
* resolved when the page finishes rendering.
|
* resolved when the page finishes rendering.
|
||||||
*/
|
*/
|
||||||
@ -1473,10 +1487,12 @@ class PDFPageProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param {GetOperatorListParameters} params - Page getOperatorList
|
||||||
|
* parameters.
|
||||||
* @returns {Promise<PDFOperatorList>} A promise resolved with an
|
* @returns {Promise<PDFOperatorList>} A promise resolved with an
|
||||||
* {@link PDFOperatorList} object that represents page's operator list.
|
* {@link PDFOperatorList} object that represents the page's operator list.
|
||||||
*/
|
*/
|
||||||
getOperatorList() {
|
getOperatorList({ intent = "display" } = {}) {
|
||||||
function operatorListChanged() {
|
function operatorListChanged() {
|
||||||
if (intentState.operatorList.lastChunk) {
|
if (intentState.operatorList.lastChunk) {
|
||||||
intentState.opListReadCapability.resolve(intentState.operatorList);
|
intentState.opListReadCapability.resolve(intentState.operatorList);
|
||||||
@ -1485,7 +1501,9 @@ class PDFPageProxy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderingIntent = "oplist";
|
const renderingIntent = `oplist-${
|
||||||
|
intent === "print" ? "print" : "display"
|
||||||
|
}`;
|
||||||
let intentState = this._intentStates.get(renderingIntent);
|
let intentState = this._intentStates.get(renderingIntent);
|
||||||
if (!intentState) {
|
if (!intentState) {
|
||||||
intentState = Object.create(null);
|
intentState = Object.create(null);
|
||||||
@ -1600,7 +1618,7 @@ class PDFPageProxy {
|
|||||||
force: true,
|
force: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (intent === "oplist") {
|
if (intent.startsWith("oplist-")) {
|
||||||
// Avoid errors below, since the renderTasks are just stubs.
|
// Avoid errors below, since the renderTasks are just stubs.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2401,7 +2401,7 @@ const CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
this.restore();
|
this.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
beginAnnotation(rect, transform, matrix) {
|
beginAnnotation(id, rect, transform, matrix) {
|
||||||
this.save();
|
this.save();
|
||||||
resetCtxToDefault(this.ctx);
|
resetCtxToDefault(this.ctx);
|
||||||
this.current = new CanvasExtraState();
|
this.current = new CanvasExtraState();
|
||||||
|
@ -1689,6 +1689,12 @@ describe("annotation", function () {
|
|||||||
OPS.setFillRGBColor,
|
OPS.setFillRGBColor,
|
||||||
OPS.endAnnotation,
|
OPS.endAnnotation,
|
||||||
]);
|
]);
|
||||||
|
expect(operatorList.argsArray[0]).toEqual([
|
||||||
|
"271R",
|
||||||
|
[0, 0, 32, 10],
|
||||||
|
[32, 0, 0, 10, 0, 0],
|
||||||
|
[1, 0, 0, 1, 0, 0],
|
||||||
|
]);
|
||||||
expect(operatorList.argsArray[1]).toEqual(
|
expect(operatorList.argsArray[1]).toEqual(
|
||||||
new Uint8ClampedArray([26, 51, 76])
|
new Uint8ClampedArray([26, 51, 76])
|
||||||
);
|
);
|
||||||
@ -2324,6 +2330,12 @@ describe("annotation", function () {
|
|||||||
OPS.showText,
|
OPS.showText,
|
||||||
OPS.endAnnotation,
|
OPS.endAnnotation,
|
||||||
]);
|
]);
|
||||||
|
expect(operatorList.argsArray[0]).toEqual([
|
||||||
|
"124R",
|
||||||
|
[0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0],
|
||||||
|
[1, 0, 0, 1, 0, 0],
|
||||||
|
]);
|
||||||
expect(operatorList.argsArray[3][0][0].unicode).toEqual("4");
|
expect(operatorList.argsArray[3][0][0].unicode).toEqual("4");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -2375,6 +2387,12 @@ describe("annotation", function () {
|
|||||||
OPS.setFillRGBColor,
|
OPS.setFillRGBColor,
|
||||||
OPS.endAnnotation,
|
OPS.endAnnotation,
|
||||||
]);
|
]);
|
||||||
|
expect(operatorList.argsArray[0]).toEqual([
|
||||||
|
"124R",
|
||||||
|
[0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0],
|
||||||
|
[1, 0, 0, 1, 0, 0],
|
||||||
|
]);
|
||||||
expect(operatorList.argsArray[1]).toEqual(
|
expect(operatorList.argsArray[1]).toEqual(
|
||||||
new Uint8ClampedArray([26, 51, 76])
|
new Uint8ClampedArray([26, 51, 76])
|
||||||
);
|
);
|
||||||
@ -2393,6 +2411,12 @@ describe("annotation", function () {
|
|||||||
OPS.setFillRGBColor,
|
OPS.setFillRGBColor,
|
||||||
OPS.endAnnotation,
|
OPS.endAnnotation,
|
||||||
]);
|
]);
|
||||||
|
expect(operatorList.argsArray[0]).toEqual([
|
||||||
|
"124R",
|
||||||
|
[0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0],
|
||||||
|
[1, 0, 0, 1, 0, 0],
|
||||||
|
]);
|
||||||
expect(operatorList.argsArray[1]).toEqual(
|
expect(operatorList.argsArray[1]).toEqual(
|
||||||
new Uint8ClampedArray([76, 51, 26])
|
new Uint8ClampedArray([76, 51, 26])
|
||||||
);
|
);
|
||||||
@ -2449,6 +2473,12 @@ describe("annotation", function () {
|
|||||||
OPS.setFillRGBColor,
|
OPS.setFillRGBColor,
|
||||||
OPS.endAnnotation,
|
OPS.endAnnotation,
|
||||||
]);
|
]);
|
||||||
|
expect(operatorList.argsArray[0]).toEqual([
|
||||||
|
"1249R",
|
||||||
|
[0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0],
|
||||||
|
[1, 0, 0, 1, 0, 0],
|
||||||
|
]);
|
||||||
expect(operatorList.argsArray[1]).toEqual(
|
expect(operatorList.argsArray[1]).toEqual(
|
||||||
new Uint8ClampedArray([26, 51, 76])
|
new Uint8ClampedArray([26, 51, 76])
|
||||||
);
|
);
|
||||||
@ -2503,6 +2533,12 @@ describe("annotation", function () {
|
|||||||
OPS.setFillRGBColor,
|
OPS.setFillRGBColor,
|
||||||
OPS.endAnnotation,
|
OPS.endAnnotation,
|
||||||
]);
|
]);
|
||||||
|
expect(operatorList.argsArray[0]).toEqual([
|
||||||
|
"124R",
|
||||||
|
[0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0],
|
||||||
|
[1, 0, 0, 1, 0, 0],
|
||||||
|
]);
|
||||||
expect(operatorList.argsArray[1]).toEqual(
|
expect(operatorList.argsArray[1]).toEqual(
|
||||||
new Uint8ClampedArray([26, 51, 76])
|
new Uint8ClampedArray([26, 51, 76])
|
||||||
);
|
);
|
||||||
@ -2700,6 +2736,12 @@ describe("annotation", function () {
|
|||||||
OPS.setFillRGBColor,
|
OPS.setFillRGBColor,
|
||||||
OPS.endAnnotation,
|
OPS.endAnnotation,
|
||||||
]);
|
]);
|
||||||
|
expect(operatorList.argsArray[0]).toEqual([
|
||||||
|
"124R",
|
||||||
|
[0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0],
|
||||||
|
[1, 0, 0, 1, 0, 0],
|
||||||
|
]);
|
||||||
expect(operatorList.argsArray[1]).toEqual(
|
expect(operatorList.argsArray[1]).toEqual(
|
||||||
new Uint8ClampedArray([26, 51, 76])
|
new Uint8ClampedArray([26, 51, 76])
|
||||||
);
|
);
|
||||||
@ -2718,6 +2760,12 @@ describe("annotation", function () {
|
|||||||
OPS.setFillRGBColor,
|
OPS.setFillRGBColor,
|
||||||
OPS.endAnnotation,
|
OPS.endAnnotation,
|
||||||
]);
|
]);
|
||||||
|
expect(operatorList.argsArray[0]).toEqual([
|
||||||
|
"124R",
|
||||||
|
[0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0],
|
||||||
|
[1, 0, 0, 1, 0, 0],
|
||||||
|
]);
|
||||||
expect(operatorList.argsArray[1]).toEqual(
|
expect(operatorList.argsArray[1]).toEqual(
|
||||||
new Uint8ClampedArray([76, 51, 26])
|
new Uint8ClampedArray([76, 51, 26])
|
||||||
);
|
);
|
||||||
@ -2772,6 +2820,12 @@ describe("annotation", function () {
|
|||||||
OPS.setFillRGBColor,
|
OPS.setFillRGBColor,
|
||||||
OPS.endAnnotation,
|
OPS.endAnnotation,
|
||||||
]);
|
]);
|
||||||
|
expect(operatorList.argsArray[0]).toEqual([
|
||||||
|
"124R",
|
||||||
|
[0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0],
|
||||||
|
[1, 0, 0, 1, 0, 0],
|
||||||
|
]);
|
||||||
expect(operatorList.argsArray[1]).toEqual(
|
expect(operatorList.argsArray[1]).toEqual(
|
||||||
new Uint8ClampedArray([76, 51, 26])
|
new Uint8ClampedArray([76, 51, 26])
|
||||||
);
|
);
|
||||||
|
@ -1622,8 +1622,9 @@ describe("api", function () {
|
|||||||
|
|
||||||
it("gets operator list", async function () {
|
it("gets operator list", async function () {
|
||||||
const operatorList = await page.getOperatorList();
|
const operatorList = await page.getOperatorList();
|
||||||
expect(!!operatorList.fnArray).toEqual(true);
|
|
||||||
expect(!!operatorList.argsArray).toEqual(true);
|
expect(operatorList.fnArray.length).toBeGreaterThan(100);
|
||||||
|
expect(operatorList.argsArray.length).toBeGreaterThan(100);
|
||||||
expect(operatorList.lastChunk).toEqual(true);
|
expect(operatorList.lastChunk).toEqual(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1687,6 +1688,26 @@ describe("api", function () {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
it("gets operator list, containing Annotation-operatorLists", async function () {
|
||||||
|
const loadingTask = getDocument(
|
||||||
|
buildGetDocumentParams("annotation-line.pdf")
|
||||||
|
);
|
||||||
|
const pdfDoc = await loadingTask.promise;
|
||||||
|
const pdfPage = await pdfDoc.getPage(1);
|
||||||
|
const operatorList = await pdfPage.getOperatorList();
|
||||||
|
|
||||||
|
expect(operatorList.fnArray.length).toBeGreaterThan(20);
|
||||||
|
expect(operatorList.argsArray.length).toBeGreaterThan(20);
|
||||||
|
expect(operatorList.lastChunk).toEqual(true);
|
||||||
|
|
||||||
|
// The `getOperatorList` method, similar to the `render` method,
|
||||||
|
// is supposed to include any existing Annotation-operatorLists.
|
||||||
|
expect(operatorList.fnArray.includes(OPS.beginAnnotation)).toEqual(true);
|
||||||
|
expect(operatorList.fnArray.includes(OPS.endAnnotation)).toEqual(true);
|
||||||
|
|
||||||
|
await loadingTask.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
it("gets document stats after parsing page", async function () {
|
it("gets document stats after parsing page", async function () {
|
||||||
const stats = await page.getOperatorList().then(function () {
|
const stats = await page.getOperatorList().then(function () {
|
||||||
return pdfDocument.getStats();
|
return pdfDocument.getStats();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user