Merge pull request #14247 from calixteman/button
[api-minor] Render pushbuttons on their own canvas (bug 1737260)
This commit is contained in:
commit
3209c013c4
@ -26,6 +26,7 @@ import {
|
||||
isAscii,
|
||||
isString,
|
||||
OPS,
|
||||
RenderingIntentFlag,
|
||||
shadow,
|
||||
stringToPDFString,
|
||||
stringToUTF16BEString,
|
||||
@ -386,6 +387,7 @@ class Annotation {
|
||||
modificationDate: this.modificationDate,
|
||||
rect: this.rectangle,
|
||||
subtype: params.subtype,
|
||||
hasOwnCanvas: false,
|
||||
};
|
||||
|
||||
if (params.collectFields) {
|
||||
@ -708,8 +710,8 @@ class Annotation {
|
||||
this.appearance = normalAppearanceState.get(as.name);
|
||||
}
|
||||
|
||||
loadResources(keys) {
|
||||
return this.appearance.dict.getAsync("Resources").then(resources => {
|
||||
loadResources(keys, appearance) {
|
||||
return appearance.dict.getAsync("Resources").then(resources => {
|
||||
if (!resources) {
|
||||
return undefined;
|
||||
}
|
||||
@ -721,22 +723,24 @@ class Annotation {
|
||||
});
|
||||
}
|
||||
|
||||
getOperatorList(evaluator, task, renderForms, annotationStorage) {
|
||||
if (!this.appearance) {
|
||||
return Promise.resolve(new OperatorList());
|
||||
getOperatorList(evaluator, task, intent, renderForms, annotationStorage) {
|
||||
const data = this.data;
|
||||
let appearance = this.appearance;
|
||||
const isUsingOwnCanvas =
|
||||
data.hasOwnCanvas && intent & RenderingIntentFlag.DISPLAY;
|
||||
if (!appearance) {
|
||||
if (!isUsingOwnCanvas) {
|
||||
return Promise.resolve(new OperatorList());
|
||||
}
|
||||
appearance = new StringStream("");
|
||||
appearance.dict = new Dict();
|
||||
}
|
||||
|
||||
const appearance = this.appearance;
|
||||
const data = this.data;
|
||||
const appearanceDict = appearance.dict;
|
||||
const resourcesPromise = this.loadResources([
|
||||
"ExtGState",
|
||||
"ColorSpace",
|
||||
"Pattern",
|
||||
"Shading",
|
||||
"XObject",
|
||||
"Font",
|
||||
]);
|
||||
const resourcesPromise = this.loadResources(
|
||||
["ExtGState", "ColorSpace", "Pattern", "Shading", "XObject", "Font"],
|
||||
appearance
|
||||
);
|
||||
const bbox = appearanceDict.getArray("BBox") || [0, 0, 1, 1];
|
||||
const matrix = appearanceDict.getArray("Matrix") || [1, 0, 0, 1, 0, 0];
|
||||
const transform = getTransformMatrix(data.rect, bbox, matrix);
|
||||
@ -748,6 +752,7 @@ class Annotation {
|
||||
data.rect,
|
||||
transform,
|
||||
matrix,
|
||||
isUsingOwnCanvas,
|
||||
]);
|
||||
|
||||
return evaluator
|
||||
@ -1329,7 +1334,7 @@ class WidgetAnnotation extends Annotation {
|
||||
return !!(this.data.fieldFlags & flag);
|
||||
}
|
||||
|
||||
getOperatorList(evaluator, task, renderForms, annotationStorage) {
|
||||
getOperatorList(evaluator, task, intent, renderForms, annotationStorage) {
|
||||
// Do not render form elements on the canvas when interactive forms are
|
||||
// enabled. The display layer is responsible for rendering them instead.
|
||||
if (renderForms && !(this instanceof SignatureWidgetAnnotation)) {
|
||||
@ -1340,6 +1345,7 @@ class WidgetAnnotation extends Annotation {
|
||||
return super.getOperatorList(
|
||||
evaluator,
|
||||
task,
|
||||
intent,
|
||||
renderForms,
|
||||
annotationStorage
|
||||
);
|
||||
@ -1351,6 +1357,7 @@ class WidgetAnnotation extends Annotation {
|
||||
return super.getOperatorList(
|
||||
evaluator,
|
||||
task,
|
||||
intent,
|
||||
renderForms,
|
||||
annotationStorage
|
||||
);
|
||||
@ -1936,17 +1943,25 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
|
||||
} else if (this.data.radioButton) {
|
||||
this._processRadioButton(params);
|
||||
} else if (this.data.pushButton) {
|
||||
this.data.hasOwnCanvas = true;
|
||||
this._processPushButton(params);
|
||||
} else {
|
||||
warn("Invalid field flags for button widget annotation");
|
||||
}
|
||||
}
|
||||
|
||||
async getOperatorList(evaluator, task, renderForms, annotationStorage) {
|
||||
async getOperatorList(
|
||||
evaluator,
|
||||
task,
|
||||
intent,
|
||||
renderForms,
|
||||
annotationStorage
|
||||
) {
|
||||
if (this.data.pushButton) {
|
||||
return super.getOperatorList(
|
||||
evaluator,
|
||||
task,
|
||||
intent,
|
||||
false, // we use normalAppearance to render the button
|
||||
annotationStorage
|
||||
);
|
||||
@ -1965,6 +1980,7 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
|
||||
return super.getOperatorList(
|
||||
evaluator,
|
||||
task,
|
||||
intent,
|
||||
renderForms,
|
||||
annotationStorage
|
||||
);
|
||||
@ -1988,6 +2004,7 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
|
||||
const operatorList = super.getOperatorList(
|
||||
evaluator,
|
||||
task,
|
||||
intent,
|
||||
renderForms,
|
||||
annotationStorage
|
||||
);
|
||||
|
@ -407,6 +407,7 @@ class Page {
|
||||
.getOperatorList(
|
||||
partialEvaluator,
|
||||
task,
|
||||
intent,
|
||||
renderForms,
|
||||
annotationStorage
|
||||
)
|
||||
|
@ -198,7 +198,25 @@ class AnnotationElement {
|
||||
page.view[3] - data.rect[3] + page.view[1],
|
||||
]);
|
||||
|
||||
container.style.transform = `matrix(${viewport.transform.join(",")})`;
|
||||
if (data.hasOwnCanvas) {
|
||||
const transform = viewport.transform.slice();
|
||||
const [scaleX, scaleY] = Util.singularValueDecompose2dScale(transform);
|
||||
width = Math.ceil(width * scaleX);
|
||||
height = Math.ceil(height * scaleY);
|
||||
rect[0] *= scaleX;
|
||||
rect[1] *= scaleY;
|
||||
// Reset the scale part of the transform matrix (which must be diagonal
|
||||
// or anti-diagonal) in order to avoid to rescale the canvas.
|
||||
// The canvas for the annotation is correctly scaled when it is drawn
|
||||
// (see `beginAnnotation` in canvas.js).
|
||||
for (let i = 0; i < 4; i++) {
|
||||
transform[i] = Math.sign(transform[i]);
|
||||
}
|
||||
container.style.transform = `matrix(${transform.join(",")})`;
|
||||
} else {
|
||||
container.style.transform = `matrix(${viewport.transform.join(",")})`;
|
||||
}
|
||||
|
||||
container.style.transformOrigin = `${-rect[0]}px ${-rect[1]}px`;
|
||||
|
||||
if (!ignoreBorder && data.borderStyle.width > 0) {
|
||||
@ -258,8 +276,13 @@ class AnnotationElement {
|
||||
|
||||
container.style.left = `${rect[0]}px`;
|
||||
container.style.top = `${rect[1]}px`;
|
||||
container.style.width = `${width}px`;
|
||||
container.style.height = `${height}px`;
|
||||
|
||||
if (data.hasOwnCanvas) {
|
||||
container.style.width = container.style.height = "auto";
|
||||
} else {
|
||||
container.style.width = `${width}px`;
|
||||
container.style.height = `${height}px`;
|
||||
}
|
||||
return container;
|
||||
}
|
||||
|
||||
@ -2318,10 +2341,12 @@ class AnnotationLayer {
|
||||
sortedAnnotations.push(...popupAnnotations);
|
||||
}
|
||||
|
||||
const div = parameters.div;
|
||||
|
||||
for (const data of sortedAnnotations) {
|
||||
const element = AnnotationElementFactory.create({
|
||||
data,
|
||||
layer: parameters.div,
|
||||
layer: div,
|
||||
page: parameters.page,
|
||||
viewport: parameters.viewport,
|
||||
linkService: parameters.linkService,
|
||||
@ -2343,19 +2368,21 @@ class AnnotationLayer {
|
||||
}
|
||||
if (Array.isArray(rendered)) {
|
||||
for (const renderedElement of rendered) {
|
||||
parameters.div.appendChild(renderedElement);
|
||||
div.appendChild(renderedElement);
|
||||
}
|
||||
} else {
|
||||
if (element instanceof PopupAnnotationElement) {
|
||||
// Popup annotation elements should not be on top of other
|
||||
// annotation elements to prevent interfering with mouse events.
|
||||
parameters.div.prepend(rendered);
|
||||
div.prepend(rendered);
|
||||
} else {
|
||||
parameters.div.appendChild(rendered);
|
||||
div.appendChild(rendered);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.#setAnnotationCanvasMap(div, parameters.annotationCanvasMap);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2366,18 +2393,73 @@ class AnnotationLayer {
|
||||
* @memberof AnnotationLayer
|
||||
*/
|
||||
static update(parameters) {
|
||||
const transform = `matrix(${parameters.viewport.transform.join(",")})`;
|
||||
for (const data of parameters.annotations) {
|
||||
const elements = parameters.div.querySelectorAll(
|
||||
const { page, viewport, annotations, annotationCanvasMap, div } =
|
||||
parameters;
|
||||
const transform = viewport.transform;
|
||||
const matrix = `matrix(${transform.join(",")})`;
|
||||
|
||||
let scale, ownMatrix;
|
||||
for (const data of annotations) {
|
||||
const elements = div.querySelectorAll(
|
||||
`[data-annotation-id="${data.id}"]`
|
||||
);
|
||||
if (elements) {
|
||||
for (const element of elements) {
|
||||
element.style.transform = transform;
|
||||
if (data.hasOwnCanvas) {
|
||||
const rect = Util.normalizeRect([
|
||||
data.rect[0],
|
||||
page.view[3] - data.rect[1] + page.view[1],
|
||||
data.rect[2],
|
||||
page.view[3] - data.rect[3] + page.view[1],
|
||||
]);
|
||||
|
||||
if (!ownMatrix) {
|
||||
// When an annotation has its own canvas, then
|
||||
// the scale has been already applied to the canvas,
|
||||
// so we musn't scale it twice.
|
||||
scale = Math.abs(transform[0] || transform[1]);
|
||||
const ownTransform = transform.slice();
|
||||
for (let i = 0; i < 4; i++) {
|
||||
ownTransform[i] = Math.sign(ownTransform[i]);
|
||||
}
|
||||
ownMatrix = `matrix(${ownTransform.join(",")})`;
|
||||
}
|
||||
|
||||
const left = rect[0] * scale;
|
||||
const top = rect[1] * scale;
|
||||
element.style.left = `${left}px`;
|
||||
element.style.top = `${top}px`;
|
||||
element.style.transformOrigin = `${-left}px ${-top}px`;
|
||||
element.style.transform = ownMatrix;
|
||||
} else {
|
||||
element.style.transform = matrix;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
parameters.div.hidden = false;
|
||||
|
||||
this.#setAnnotationCanvasMap(div, annotationCanvasMap);
|
||||
div.hidden = false;
|
||||
}
|
||||
|
||||
static #setAnnotationCanvasMap(div, annotationCanvasMap) {
|
||||
if (!annotationCanvasMap) {
|
||||
return;
|
||||
}
|
||||
for (const [id, canvas] of annotationCanvasMap) {
|
||||
const element = div.querySelector(`[data-annotation-id="${id}"]`);
|
||||
if (!element) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const { firstChild } = element;
|
||||
if (firstChild.nodeName === "CANVAS") {
|
||||
element.replaceChild(canvas, firstChild);
|
||||
} else {
|
||||
element.insertBefore(canvas, firstChild);
|
||||
}
|
||||
}
|
||||
annotationCanvasMap.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1161,6 +1161,8 @@ class PDFDocumentProxy {
|
||||
* created from `PDFDocumentProxy.getOptionalContentConfig`. If `null`,
|
||||
* the configuration will be fetched automatically with the default visibility
|
||||
* states set.
|
||||
* @property {Map<string, Canvas>} [annotationCanvasMap] - Map some annotation
|
||||
* ids with canvases used to render them.
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -1374,6 +1376,7 @@ class PDFPageProxy {
|
||||
canvasFactory = null,
|
||||
background = null,
|
||||
optionalContentConfigPromise = null,
|
||||
annotationCanvasMap = null,
|
||||
}) {
|
||||
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("GENERIC")) {
|
||||
if (arguments[0]?.renderInteractiveForms !== undefined) {
|
||||
@ -1491,6 +1494,7 @@ class PDFPageProxy {
|
||||
},
|
||||
objs: this.objs,
|
||||
commonObjs: this.commonObjs,
|
||||
annotationCanvasMap,
|
||||
operatorList: intentState.operatorList,
|
||||
pageIndex: this._pageIndex,
|
||||
canvasFactory: canvasFactoryInstance,
|
||||
@ -3216,6 +3220,7 @@ class InternalRenderTask {
|
||||
params,
|
||||
objs,
|
||||
commonObjs,
|
||||
annotationCanvasMap,
|
||||
operatorList,
|
||||
pageIndex,
|
||||
canvasFactory,
|
||||
@ -3226,6 +3231,7 @@ class InternalRenderTask {
|
||||
this.params = params;
|
||||
this.objs = objs;
|
||||
this.commonObjs = commonObjs;
|
||||
this.annotationCanvasMap = annotationCanvasMap;
|
||||
this.operatorListIdx = null;
|
||||
this.operatorList = operatorList;
|
||||
this._pageIndex = pageIndex;
|
||||
@ -3284,7 +3290,8 @@ class InternalRenderTask {
|
||||
this.objs,
|
||||
this.canvasFactory,
|
||||
imageLayer,
|
||||
optionalContentConfig
|
||||
optionalContentConfig,
|
||||
this.annotationCanvasMap
|
||||
);
|
||||
this.gfx.beginDrawing({
|
||||
transform,
|
||||
|
@ -1068,7 +1068,8 @@ class CanvasGraphics {
|
||||
objs,
|
||||
canvasFactory,
|
||||
imageLayer,
|
||||
optionalContentConfig
|
||||
optionalContentConfig,
|
||||
annotationCanvasMap
|
||||
) {
|
||||
this.ctx = canvasCtx;
|
||||
this.current = new CanvasExtraState(
|
||||
@ -1100,6 +1101,10 @@ class CanvasGraphics {
|
||||
this.optionalContentConfig = optionalContentConfig;
|
||||
this.cachedCanvases = new CachedCanvases(this.canvasFactory);
|
||||
this.cachedPatterns = new Map();
|
||||
this.annotationCanvasMap = annotationCanvasMap;
|
||||
this.viewportScale = 1;
|
||||
this.outputScaleX = 1;
|
||||
this.outputScaleY = 1;
|
||||
if (canvasCtx) {
|
||||
// NOTE: if mozCurrentTransform is polyfilled, then the current state of
|
||||
// the transformation must already be set in canvasCtx._transformMatrix.
|
||||
@ -1147,8 +1152,11 @@ class CanvasGraphics {
|
||||
resetCtxToDefault(this.ctx);
|
||||
if (transform) {
|
||||
this.ctx.transform.apply(this.ctx, transform);
|
||||
this.outputScaleX = transform[0];
|
||||
this.outputScaleY = transform[0];
|
||||
}
|
||||
this.ctx.transform.apply(this.ctx, viewport.transform);
|
||||
this.viewportScale = viewport.scale;
|
||||
|
||||
this.baseTransform = this.ctx.mozCurrentTransform.slice();
|
||||
this._combinedScaleFactor = Math.hypot(
|
||||
@ -2691,27 +2699,72 @@ class CanvasGraphics {
|
||||
this.restore();
|
||||
}
|
||||
|
||||
beginAnnotation(id, rect, transform, matrix) {
|
||||
beginAnnotation(id, rect, transform, matrix, hasOwnCanvas) {
|
||||
this.save();
|
||||
resetCtxToDefault(this.ctx);
|
||||
this.current = new CanvasExtraState(
|
||||
this.ctx.canvas.width,
|
||||
this.ctx.canvas.height
|
||||
);
|
||||
|
||||
if (Array.isArray(rect) && rect.length === 4) {
|
||||
const width = rect[2] - rect[0];
|
||||
const height = rect[3] - rect[1];
|
||||
this.ctx.rect(rect[0], rect[1], width, height);
|
||||
this.clip();
|
||||
this.endPath();
|
||||
|
||||
if (hasOwnCanvas && this.annotationCanvasMap) {
|
||||
transform = transform.slice();
|
||||
transform[4] -= rect[0];
|
||||
transform[5] -= rect[1];
|
||||
|
||||
rect = rect.slice();
|
||||
rect[0] = rect[1] = 0;
|
||||
rect[2] = width;
|
||||
rect[3] = height;
|
||||
|
||||
const [scaleX, scaleY] = Util.singularValueDecompose2dScale(
|
||||
this.ctx.mozCurrentTransform
|
||||
);
|
||||
const { viewportScale } = this;
|
||||
const canvasWidth = Math.ceil(
|
||||
width * this.outputScaleX * viewportScale
|
||||
);
|
||||
const canvasHeight = Math.ceil(
|
||||
height * this.outputScaleY * viewportScale
|
||||
);
|
||||
|
||||
this.annotationCanvas = this.canvasFactory.create(
|
||||
canvasWidth,
|
||||
canvasHeight
|
||||
);
|
||||
const { canvas, context } = this.annotationCanvas;
|
||||
canvas.style.width = `calc(${width}px * var(--viewport-scale-factor))`;
|
||||
canvas.style.height = `calc(${height}px * var(--viewport-scale-factor))`;
|
||||
this.annotationCanvasMap.set(id, canvas);
|
||||
this.annotationCanvas.savedCtx = this.ctx;
|
||||
this.ctx = context;
|
||||
this.ctx.setTransform(scaleX, 0, 0, -scaleY, 0, height * scaleY);
|
||||
addContextCurrentTransform(this.ctx);
|
||||
|
||||
resetCtxToDefault(this.ctx);
|
||||
} else {
|
||||
resetCtxToDefault(this.ctx);
|
||||
|
||||
this.ctx.rect(rect[0], rect[1], width, height);
|
||||
this.clip();
|
||||
this.endPath();
|
||||
}
|
||||
}
|
||||
|
||||
this.current = new CanvasExtraState(
|
||||
this.ctx.canvas.width,
|
||||
this.ctx.canvas.height
|
||||
);
|
||||
|
||||
this.transform.apply(this, transform);
|
||||
this.transform.apply(this, matrix);
|
||||
}
|
||||
|
||||
endAnnotation() {
|
||||
if (this.annotationCanvas) {
|
||||
this.ctx = this.annotationCanvas.savedCtx;
|
||||
delete this.annotationCanvas.savedCtx;
|
||||
delete this.annotationCanvas;
|
||||
}
|
||||
this.restore();
|
||||
}
|
||||
|
||||
|
@ -101,6 +101,25 @@ function inlineImages(images) {
|
||||
return Promise.all(imagePromises);
|
||||
}
|
||||
|
||||
async function convertCanvasesToImages(annotationCanvasMap) {
|
||||
const results = new Map();
|
||||
const promises = [];
|
||||
for (const [key, canvas] of annotationCanvasMap) {
|
||||
promises.push(
|
||||
new Promise(resolve => {
|
||||
canvas.toBlob(blob => {
|
||||
const image = document.createElement("img");
|
||||
image.onload = resolve;
|
||||
results.set(key, image);
|
||||
image.src = URL.createObjectURL(blob);
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
await Promise.all(promises);
|
||||
return results;
|
||||
}
|
||||
|
||||
async function resolveImages(node, silentErrors = false) {
|
||||
const images = node.getElementsByTagName("img");
|
||||
const data = await inlineImages(images);
|
||||
@ -227,6 +246,7 @@ var rasterizeAnnotationLayer = (function rasterizeAnnotationLayerClosure() {
|
||||
ctx,
|
||||
viewport,
|
||||
annotations,
|
||||
annotationCanvasMap,
|
||||
page,
|
||||
imageResourcesPath,
|
||||
renderForms = false
|
||||
@ -255,6 +275,10 @@ var rasterizeAnnotationLayer = (function rasterizeAnnotationLayerClosure() {
|
||||
style.textContent = common + "\n" + overrides;
|
||||
|
||||
var annotation_viewport = viewport.clone({ dontFlip: true });
|
||||
const annotationImageMap = await convertCanvasesToImages(
|
||||
annotationCanvasMap
|
||||
);
|
||||
|
||||
var parameters = {
|
||||
viewport: annotation_viewport,
|
||||
div,
|
||||
@ -263,6 +287,7 @@ var rasterizeAnnotationLayer = (function rasterizeAnnotationLayerClosure() {
|
||||
linkService: new SimpleLinkService(),
|
||||
imageResourcesPath,
|
||||
renderForms,
|
||||
annotationCanvasMap: annotationImageMap,
|
||||
};
|
||||
AnnotationLayer.render(parameters);
|
||||
|
||||
@ -665,7 +690,8 @@ var Driver = (function DriverClosure() {
|
||||
var renderAnnotations = false,
|
||||
renderForms = false,
|
||||
renderPrint = false,
|
||||
renderXfa = false;
|
||||
renderXfa = false,
|
||||
annotationCanvasMap = null;
|
||||
|
||||
if (task.annotationStorage) {
|
||||
const entries = Object.entries(task.annotationStorage),
|
||||
@ -739,18 +765,8 @@ var Driver = (function DriverClosure() {
|
||||
if (!renderXfa) {
|
||||
// The annotation builder will draw its content
|
||||
// on the canvas.
|
||||
initPromise = page
|
||||
.getAnnotations({ intent: "display" })
|
||||
.then(function (annotations) {
|
||||
return rasterizeAnnotationLayer(
|
||||
annotationLayerContext,
|
||||
viewport,
|
||||
annotations,
|
||||
page,
|
||||
IMAGE_RESOURCES_PATH,
|
||||
renderForms
|
||||
);
|
||||
});
|
||||
initPromise = page.getAnnotations({ intent: "display" });
|
||||
annotationCanvasMap = new Map();
|
||||
} else {
|
||||
initPromise = page.getXfa().then(function (xfa) {
|
||||
return rasterizeXfaLayer(
|
||||
@ -768,11 +784,11 @@ var Driver = (function DriverClosure() {
|
||||
initPromise = Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
var renderContext = {
|
||||
canvasContext: ctx,
|
||||
viewport,
|
||||
optionalContentConfigPromise: task.optionalContentConfigPromise,
|
||||
annotationCanvasMap,
|
||||
};
|
||||
if (renderForms) {
|
||||
renderContext.annotationMode = AnnotationMode.ENABLE_FORMS;
|
||||
@ -805,7 +821,7 @@ var Driver = (function DriverClosure() {
|
||||
self._snapshot(task, error);
|
||||
};
|
||||
initPromise
|
||||
.then(function () {
|
||||
.then(function (data) {
|
||||
const renderTask = page.render(renderContext);
|
||||
|
||||
if (task.renderTaskOnContinue) {
|
||||
@ -815,7 +831,21 @@ var Driver = (function DriverClosure() {
|
||||
};
|
||||
}
|
||||
return renderTask.promise.then(function () {
|
||||
completeRender(false);
|
||||
if (annotationCanvasMap) {
|
||||
rasterizeAnnotationLayer(
|
||||
annotationLayerContext,
|
||||
viewport,
|
||||
data,
|
||||
annotationCanvasMap,
|
||||
page,
|
||||
IMAGE_RESOURCES_PATH,
|
||||
renderForms
|
||||
).then(() => {
|
||||
completeRender(false);
|
||||
});
|
||||
} else {
|
||||
completeRender(false);
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(function (error) {
|
||||
|
@ -26,6 +26,7 @@ import {
|
||||
AnnotationFlag,
|
||||
AnnotationType,
|
||||
OPS,
|
||||
RenderingIntentFlag,
|
||||
stringToBytes,
|
||||
stringToUTF8String,
|
||||
} from "../../src/shared/util.js";
|
||||
@ -1680,6 +1681,7 @@ describe("annotation", function () {
|
||||
const operatorList = await annotation.getOperatorList(
|
||||
partialEvaluator,
|
||||
task,
|
||||
RenderingIntentFlag.PRINT,
|
||||
false,
|
||||
annotationStorage
|
||||
);
|
||||
@ -1694,6 +1696,7 @@ describe("annotation", function () {
|
||||
[0, 0, 32, 10],
|
||||
[32, 0, 0, 10, 0, 0],
|
||||
[1, 0, 0, 1, 0, 0],
|
||||
false,
|
||||
]);
|
||||
expect(operatorList.argsArray[1]).toEqual(
|
||||
new Uint8ClampedArray([26, 51, 76])
|
||||
@ -2319,6 +2322,7 @@ describe("annotation", function () {
|
||||
const operatorList = await annotation.getOperatorList(
|
||||
checkboxEvaluator,
|
||||
task,
|
||||
RenderingIntentFlag.PRINT,
|
||||
false,
|
||||
annotationStorage
|
||||
);
|
||||
@ -2335,6 +2339,7 @@ describe("annotation", function () {
|
||||
[0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0],
|
||||
[1, 0, 0, 1, 0, 0],
|
||||
false,
|
||||
]);
|
||||
expect(operatorList.argsArray[3][0][0].unicode).toEqual("4");
|
||||
});
|
||||
@ -2378,6 +2383,7 @@ describe("annotation", function () {
|
||||
let operatorList = await annotation.getOperatorList(
|
||||
partialEvaluator,
|
||||
task,
|
||||
RenderingIntentFlag.PRINT,
|
||||
false,
|
||||
annotationStorage
|
||||
);
|
||||
@ -2392,6 +2398,7 @@ describe("annotation", function () {
|
||||
[0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0],
|
||||
[1, 0, 0, 1, 0, 0],
|
||||
false,
|
||||
]);
|
||||
expect(operatorList.argsArray[1]).toEqual(
|
||||
new Uint8ClampedArray([26, 51, 76])
|
||||
@ -2402,6 +2409,7 @@ describe("annotation", function () {
|
||||
operatorList = await annotation.getOperatorList(
|
||||
partialEvaluator,
|
||||
task,
|
||||
RenderingIntentFlag.PRINT,
|
||||
false,
|
||||
annotationStorage
|
||||
);
|
||||
@ -2416,6 +2424,7 @@ describe("annotation", function () {
|
||||
[0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0],
|
||||
[1, 0, 0, 1, 0, 0],
|
||||
false,
|
||||
]);
|
||||
expect(operatorList.argsArray[1]).toEqual(
|
||||
new Uint8ClampedArray([76, 51, 26])
|
||||
@ -2464,6 +2473,7 @@ describe("annotation", function () {
|
||||
const operatorList = await annotation.getOperatorList(
|
||||
partialEvaluator,
|
||||
task,
|
||||
RenderingIntentFlag.PRINT,
|
||||
false,
|
||||
annotationStorage
|
||||
);
|
||||
@ -2478,6 +2488,7 @@ describe("annotation", function () {
|
||||
[0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0],
|
||||
[1, 0, 0, 1, 0, 0],
|
||||
false,
|
||||
]);
|
||||
expect(operatorList.argsArray[1]).toEqual(
|
||||
new Uint8ClampedArray([26, 51, 76])
|
||||
@ -2524,6 +2535,7 @@ describe("annotation", function () {
|
||||
const operatorList = await annotation.getOperatorList(
|
||||
partialEvaluator,
|
||||
task,
|
||||
RenderingIntentFlag.PRINT,
|
||||
false,
|
||||
annotationStorage
|
||||
);
|
||||
@ -2538,6 +2550,7 @@ describe("annotation", function () {
|
||||
[0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0],
|
||||
[1, 0, 0, 1, 0, 0],
|
||||
false,
|
||||
]);
|
||||
expect(operatorList.argsArray[1]).toEqual(
|
||||
new Uint8ClampedArray([26, 51, 76])
|
||||
@ -2727,6 +2740,7 @@ describe("annotation", function () {
|
||||
let operatorList = await annotation.getOperatorList(
|
||||
partialEvaluator,
|
||||
task,
|
||||
RenderingIntentFlag.PRINT,
|
||||
false,
|
||||
annotationStorage
|
||||
);
|
||||
@ -2741,6 +2755,7 @@ describe("annotation", function () {
|
||||
[0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0],
|
||||
[1, 0, 0, 1, 0, 0],
|
||||
false,
|
||||
]);
|
||||
expect(operatorList.argsArray[1]).toEqual(
|
||||
new Uint8ClampedArray([26, 51, 76])
|
||||
@ -2751,6 +2766,7 @@ describe("annotation", function () {
|
||||
operatorList = await annotation.getOperatorList(
|
||||
partialEvaluator,
|
||||
task,
|
||||
RenderingIntentFlag.PRINT,
|
||||
false,
|
||||
annotationStorage
|
||||
);
|
||||
@ -2765,6 +2781,7 @@ describe("annotation", function () {
|
||||
[0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0],
|
||||
[1, 0, 0, 1, 0, 0],
|
||||
false,
|
||||
]);
|
||||
expect(operatorList.argsArray[1]).toEqual(
|
||||
new Uint8ClampedArray([76, 51, 26])
|
||||
@ -2811,6 +2828,7 @@ describe("annotation", function () {
|
||||
const operatorList = await annotation.getOperatorList(
|
||||
partialEvaluator,
|
||||
task,
|
||||
RenderingIntentFlag.PRINT,
|
||||
false,
|
||||
annotationStorage
|
||||
);
|
||||
@ -2825,6 +2843,7 @@ describe("annotation", function () {
|
||||
[0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0],
|
||||
[1, 0, 0, 1, 0, 0],
|
||||
false,
|
||||
]);
|
||||
expect(operatorList.argsArray[1]).toEqual(
|
||||
new Uint8ClampedArray([76, 51, 26])
|
||||
|
@ -32,6 +32,13 @@
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.annotationLayer .buttonWidgetAnnotation.pushButton > canvas {
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.annotationLayer .linkAnnotation > a:hover,
|
||||
.annotationLayer .buttonWidgetAnnotation.pushButton > a:hover {
|
||||
opacity: 0.2;
|
||||
|
@ -36,6 +36,7 @@ import { SimpleLinkService } from "./pdf_link_service.js";
|
||||
* @property {Promise<Object<string, Array<Object>> | null>}
|
||||
* [fieldObjectsPromise]
|
||||
* @property {Object} [mouseState]
|
||||
* @property {Map<string, Canvas>} [annotationCanvasMap]
|
||||
*/
|
||||
|
||||
class AnnotationLayerBuilder {
|
||||
@ -55,6 +56,7 @@ class AnnotationLayerBuilder {
|
||||
hasJSActionsPromise = null,
|
||||
fieldObjectsPromise = null,
|
||||
mouseState = null,
|
||||
annotationCanvasMap = null,
|
||||
}) {
|
||||
this.pageDiv = pageDiv;
|
||||
this.pdfPage = pdfPage;
|
||||
@ -68,6 +70,7 @@ class AnnotationLayerBuilder {
|
||||
this._hasJSActionsPromise = hasJSActionsPromise;
|
||||
this._fieldObjectsPromise = fieldObjectsPromise;
|
||||
this._mouseState = mouseState;
|
||||
this._annotationCanvasMap = annotationCanvasMap;
|
||||
|
||||
this.div = null;
|
||||
this._cancelled = false;
|
||||
@ -105,6 +108,7 @@ class AnnotationLayerBuilder {
|
||||
hasJSActions,
|
||||
fieldObjects,
|
||||
mouseState: this._mouseState,
|
||||
annotationCanvasMap: this._annotationCanvasMap,
|
||||
};
|
||||
|
||||
if (this.div) {
|
||||
@ -153,6 +157,8 @@ class DefaultAnnotationLayerFactory {
|
||||
* @param {Object} [mouseState]
|
||||
* @param {Promise<Object<string, Array<Object>> | null>}
|
||||
* [fieldObjectsPromise]
|
||||
* @param {Map<string, Canvas> | null} [annotationCanvasMap] - Map some
|
||||
* annotation ids with canvases used to render them.
|
||||
* @returns {AnnotationLayerBuilder}
|
||||
*/
|
||||
createAnnotationLayerBuilder(
|
||||
@ -165,7 +171,8 @@ class DefaultAnnotationLayerFactory {
|
||||
enableScripting = false,
|
||||
hasJSActionsPromise = null,
|
||||
mouseState = null,
|
||||
fieldObjectsPromise = null
|
||||
fieldObjectsPromise = null,
|
||||
annotationCanvasMap = null
|
||||
) {
|
||||
return new AnnotationLayerBuilder({
|
||||
pageDiv,
|
||||
@ -179,6 +186,7 @@ class DefaultAnnotationLayerFactory {
|
||||
hasJSActionsPromise,
|
||||
fieldObjectsPromise,
|
||||
mouseState,
|
||||
annotationCanvasMap,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -850,7 +850,12 @@ class BaseViewer {
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this._doc.style.setProperty("--zoom-factor", newScale);
|
||||
this._doc.style.setProperty(
|
||||
"--viewport-scale-factor",
|
||||
newScale * PixelsPerInch.PDF_TO_CSS_UNITS
|
||||
);
|
||||
|
||||
const updateArgs = { scale: newScale };
|
||||
for (const pageView of this._pages) {
|
||||
@ -1480,6 +1485,7 @@ class BaseViewer {
|
||||
* @param {Object} [mouseState]
|
||||
* @param {Promise<Object<string, Array<Object>> | null>}
|
||||
* [fieldObjectsPromise]
|
||||
* @param {Map<string, Canvas>} [annotationCanvasMap]
|
||||
* @returns {AnnotationLayerBuilder}
|
||||
*/
|
||||
createAnnotationLayerBuilder(
|
||||
@ -1492,7 +1498,8 @@ class BaseViewer {
|
||||
enableScripting = null,
|
||||
hasJSActionsPromise = null,
|
||||
mouseState = null,
|
||||
fieldObjectsPromise = null
|
||||
fieldObjectsPromise = null,
|
||||
annotationCanvasMap = null
|
||||
) {
|
||||
return new AnnotationLayerBuilder({
|
||||
pageDiv,
|
||||
@ -1510,6 +1517,7 @@ class BaseViewer {
|
||||
fieldObjectsPromise:
|
||||
fieldObjectsPromise || this.pdfDocument?.getFieldObjects(),
|
||||
mouseState: mouseState || this._scriptingManager?.mouseState,
|
||||
annotationCanvasMap,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -175,6 +175,8 @@ class IPDFAnnotationLayerFactory {
|
||||
* @param {Object} [mouseState]
|
||||
* @param {Promise<Object<string, Array<Object>> | null>}
|
||||
* [fieldObjectsPromise]
|
||||
* @property {Map<string, Canvas> | null} [annotationCanvasMap] - Map some
|
||||
* annotation ids with canvases used to render them.
|
||||
* @returns {AnnotationLayerBuilder}
|
||||
*/
|
||||
createAnnotationLayerBuilder(
|
||||
@ -187,7 +189,8 @@ class IPDFAnnotationLayerFactory {
|
||||
enableScripting = false,
|
||||
hasJSActionsPromise = null,
|
||||
mouseState = null,
|
||||
fieldObjectsPromise = null
|
||||
fieldObjectsPromise = null,
|
||||
annotationCanvasMap = null
|
||||
) {}
|
||||
}
|
||||
|
||||
|
@ -123,6 +123,8 @@ class PDFPageView {
|
||||
this._renderError = null;
|
||||
this._isStandalone = !this.renderingQueue?.hasViewer();
|
||||
|
||||
this._annotationCanvasMap = null;
|
||||
|
||||
this.annotationLayer = null;
|
||||
this.textLayer = null;
|
||||
this.zoomLayer = null;
|
||||
@ -322,17 +324,20 @@ class PDFPageView {
|
||||
if (optionalContentConfigPromise instanceof Promise) {
|
||||
this._optionalContentConfigPromise = optionalContentConfigPromise;
|
||||
}
|
||||
if (this._isStandalone) {
|
||||
const doc = document.documentElement;
|
||||
doc.style.setProperty("--zoom-factor", this.scale);
|
||||
}
|
||||
|
||||
const totalRotation = (this.rotation + this.pdfPageRotate) % 360;
|
||||
const viewportScale = this.scale * PixelsPerInch.PDF_TO_CSS_UNITS;
|
||||
this.viewport = this.viewport.clone({
|
||||
scale: this.scale * PixelsPerInch.PDF_TO_CSS_UNITS,
|
||||
scale: viewportScale,
|
||||
rotation: totalRotation,
|
||||
});
|
||||
|
||||
if (this._isStandalone) {
|
||||
const { style } = document.documentElement;
|
||||
style.setProperty("--zoom-factor", this.scale);
|
||||
style.setProperty("--viewport-scale-factor", viewportScale);
|
||||
}
|
||||
|
||||
if (this.svg) {
|
||||
this.cssTransform({
|
||||
target: this.svg,
|
||||
@ -418,6 +423,7 @@ class PDFPageView {
|
||||
) {
|
||||
this.annotationLayer.cancel();
|
||||
this.annotationLayer = null;
|
||||
this._annotationCanvasMap = null;
|
||||
}
|
||||
if (this.xfaLayer && (!keepXfaLayer || !this.xfaLayer.div)) {
|
||||
this.xfaLayer.cancel();
|
||||
@ -580,6 +586,27 @@ class PDFPageView {
|
||||
}
|
||||
this.textLayer = textLayer;
|
||||
|
||||
if (
|
||||
this._annotationMode !== AnnotationMode.DISABLE &&
|
||||
this.annotationLayerFactory
|
||||
) {
|
||||
this._annotationCanvasMap ||= new Map();
|
||||
this.annotationLayer ||=
|
||||
this.annotationLayerFactory.createAnnotationLayerBuilder(
|
||||
div,
|
||||
pdfPage,
|
||||
/* annotationStorage = */ null,
|
||||
this.imageResourcesPath,
|
||||
this._annotationMode === AnnotationMode.ENABLE_FORMS,
|
||||
this.l10n,
|
||||
/* enableScripting = */ null,
|
||||
/* hasJSActionsPromise = */ null,
|
||||
/* mouseState = */ null,
|
||||
/* fieldObjectsPromise = */ null,
|
||||
/* annotationCanvasMap */ this._annotationCanvasMap
|
||||
);
|
||||
}
|
||||
|
||||
if (this.xfaLayer?.div) {
|
||||
// The xfa layer needs to stay on top.
|
||||
div.appendChild(this.xfaLayer.div);
|
||||
@ -653,6 +680,10 @@ class PDFPageView {
|
||||
textLayer.setTextContentStream(readableStream);
|
||||
textLayer.render();
|
||||
}
|
||||
|
||||
if (this.annotationLayer) {
|
||||
this._renderAnnotationLayer();
|
||||
}
|
||||
});
|
||||
},
|
||||
function (reason) {
|
||||
@ -660,28 +691,6 @@ class PDFPageView {
|
||||
}
|
||||
);
|
||||
|
||||
if (
|
||||
this._annotationMode !== AnnotationMode.DISABLE &&
|
||||
this.annotationLayerFactory
|
||||
) {
|
||||
if (!this.annotationLayer) {
|
||||
this.annotationLayer =
|
||||
this.annotationLayerFactory.createAnnotationLayerBuilder(
|
||||
div,
|
||||
pdfPage,
|
||||
/* annotationStorage = */ null,
|
||||
this.imageResourcesPath,
|
||||
this._annotationMode === AnnotationMode.ENABLE_FORMS,
|
||||
this.l10n,
|
||||
/* enableScripting = */ null,
|
||||
/* hasJSActionsPromise = */ null,
|
||||
/* mouseState = */ null,
|
||||
/* fieldObjectsPromise = */ null
|
||||
);
|
||||
}
|
||||
this._renderAnnotationLayer();
|
||||
}
|
||||
|
||||
if (this.xfaLayerFactory) {
|
||||
if (!this.xfaLayer) {
|
||||
this.xfaLayer = this.xfaLayerFactory.createXfaLayerBuilder(
|
||||
@ -804,6 +813,7 @@ class PDFPageView {
|
||||
canvas.height = roundToDivide(viewport.height * outputScale.sy, sfy[0]);
|
||||
canvas.style.width = roundToDivide(viewport.width, sfx[1]) + "px";
|
||||
canvas.style.height = roundToDivide(viewport.height, sfy[1]) + "px";
|
||||
|
||||
// Add the viewport so it's known what it was originally drawn with.
|
||||
this.paintedViewportMap.set(canvas, viewport);
|
||||
|
||||
@ -817,6 +827,7 @@ class PDFPageView {
|
||||
viewport: this.viewport,
|
||||
annotationMode: this._annotationMode,
|
||||
optionalContentConfigPromise: this._optionalContentConfigPromise,
|
||||
annotationCanvasMap: this._annotationCanvasMap,
|
||||
};
|
||||
const renderTask = this.pdfPage.render(renderContext);
|
||||
renderTask.onContinue = function (cont) {
|
||||
|
@ -22,6 +22,7 @@
|
||||
--page-border: 9px solid transparent;
|
||||
--spreadHorizontalWrapped-margin-LR: -3.5px;
|
||||
--zoom-factor: 1;
|
||||
--viewport-scale-factor: 1;
|
||||
}
|
||||
|
||||
@media screen and (forced-colors: active) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user