From dbea302a6e2245abd4e6dd4ac30043754b09056b Mon Sep 17 00:00:00 2001 From: Tim van der Meij Date: Wed, 14 Sep 2016 22:49:37 +0200 Subject: [PATCH] Text widget annotations: do not render on canvas as well If interactive forms are enabled, then the display layer takes care of rendering the form elements. There is no need to draw them on the canvas as well. This also leads to issues when values are prefilled, because the text fields are transparent, so the contents that have been rendered onto the canvas will be visible too. We address this issue by passing the `renderInteractiveForms` parameter to the render task and handling it when the page is rendered (i.e., when the canvas is rendered). --- src/core/annotation.js | 17 ++++++++++++++--- src/core/document.js | 8 ++++++-- src/core/worker.js | 3 ++- src/display/api.js | 8 +++++++- web/pdf_page_view.js | 1 + 5 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/core/annotation.js b/src/core/annotation.js index 7abd2213f..42f49c2ed 100644 --- a/src/core/annotation.js +++ b/src/core/annotation.js @@ -68,10 +68,12 @@ AnnotationFactory.prototype = /** @lends AnnotationFactory.prototype */ { * @param {Object} ref * @param {string} uniquePrefix * @param {Object} idCounters + * @param {boolean} renderInteractiveForms * @returns {Annotation} */ create: function AnnotationFactory_create(xref, ref, - uniquePrefix, idCounters) { + uniquePrefix, idCounters, + renderInteractiveForms) { var dict = xref.fetchIfRef(ref); if (!isDict(dict)) { return; @@ -90,6 +92,7 @@ AnnotationFactory.prototype = /** @lends AnnotationFactory.prototype */ { ref: isRef(ref) ? ref : null, subtype: subtype, id: id, + renderInteractiveForms: renderInteractiveForms, }; switch (subtype) { @@ -693,6 +696,8 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() { function TextWidgetAnnotation(params) { WidgetAnnotation.call(this, params); + this.renderInteractiveForms = params.renderInteractiveForms; + // Determine the alignment of text in the field. var alignment = Util.getInheritableProperty(params.dict, 'Q'); if (!isInt(alignment) || alignment < 0 || alignment > 2) { @@ -715,12 +720,18 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() { Util.inherit(TextWidgetAnnotation, WidgetAnnotation, { getOperatorList: function TextWidgetAnnotation_getOperatorList(evaluator, task) { + var operatorList = new OperatorList(); + + // Do not render form elements on the canvas when interactive forms are + // enabled. The display layer is responsible for rendering them instead. + if (this.renderInteractiveForms) { + return Promise.resolve(operatorList); + } + if (this.appearance) { return Annotation.prototype.getOperatorList.call(this, evaluator, task); } - var operatorList = new OperatorList(); - // Even if there is an appearance stream, ignore it. This is the // behaviour used by Adobe Reader. if (!this.data.defaultAppearance) { diff --git a/src/core/document.js b/src/core/document.js index 9e414dc90..0d5535385 100644 --- a/src/core/document.js +++ b/src/core/document.js @@ -205,7 +205,8 @@ var Page = (function PageClosure() { }.bind(this)); }, - getOperatorList: function Page_getOperatorList(handler, task, intent) { + getOperatorList: function Page_getOperatorList(handler, task, intent, + renderInteractiveForms) { var self = this; var pdfManager = this.pdfManager; @@ -245,6 +246,8 @@ var Page = (function PageClosure() { }); }); + this.renderInteractiveForms = renderInteractiveForms; + var annotationsPromise = pdfManager.ensure(this, 'annotations'); return Promise.all([pageListPromise, annotationsPromise]).then( function(datas) { @@ -328,7 +331,8 @@ var Page = (function PageClosure() { var annotationRef = annotationRefs[i]; var annotation = annotationFactory.create(this.xref, annotationRef, this.uniquePrefix, - this.idCounters); + this.idCounters, + this.renderInteractiveForms); if (annotation) { annotations.push(annotation); } diff --git a/src/core/worker.js b/src/core/worker.js index 40e5a5a0f..33959e7bd 100644 --- a/src/core/worker.js +++ b/src/core/worker.js @@ -839,7 +839,8 @@ var WorkerMessageHandler = { var pageNum = pageIndex + 1; var start = Date.now(); // Pre compile the pdf page and fetch the fonts/images. - page.getOperatorList(handler, task, data.intent).then( + page.getOperatorList(handler, task, data.intent, + data.renderInteractiveForms).then( function(operatorList) { finishWorkerTask(task); diff --git a/src/display/api.js b/src/display/api.js index 22cabc63c..6ac9e8da5 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -656,6 +656,9 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() { * calling of PDFPage.getViewport method. * @property {string} intent - Rendering intent, can be 'display' or 'print' * (default value is 'display'). + * @property {boolean} renderInteractiveForms - (optional) Whether or not + * interactive form elements are rendered in the display + * layer. If so, we do not render them on canvas as well. * @property {Array} transform - (optional) Additional transform, applied * just before viewport transform. * @property {Object} imageLayer - (optional) An object that has beginLayout, @@ -764,6 +767,8 @@ var PDFPageProxy = (function PDFPageProxyClosure() { this.pendingCleanup = false; var renderingIntent = (params.intent === 'print' ? 'print' : 'display'); + var renderInteractiveForms = (params.renderInteractiveForms === true ? + true : /* Default */ false); if (!this.intentStates[renderingIntent]) { this.intentStates[renderingIntent] = Object.create(null); @@ -784,7 +789,8 @@ var PDFPageProxy = (function PDFPageProxyClosure() { this.stats.time('Page Request'); this.transport.messageHandler.send('RenderPageRequest', { pageIndex: this.pageNumber - 1, - intent: renderingIntent + intent: renderingIntent, + renderInteractiveForms: renderInteractiveForms, }); } diff --git a/web/pdf_page_view.js b/web/pdf_page_view.js index 46ee7495c..bebe9e537 100644 --- a/web/pdf_page_view.js +++ b/web/pdf_page_view.js @@ -498,6 +498,7 @@ var PDFPageView = (function PDFPageViewClosure() { canvasContext: ctx, transform: transform, viewport: this.viewport, + renderInteractiveForms: pdfjsLib.PDFJS.renderInteractiveForms, // intent: 'default', // === 'display' }; var renderTask = this.renderTask = this.pdfPage.render(renderContext);