Merge pull request #7738 from yurydelendik/svg-page
Adds SVG rendering capabilities to the main viewer.
This commit is contained in:
commit
eaf9bff4e4
@ -103,6 +103,14 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": false
|
||||||
},
|
},
|
||||||
|
"renderer": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"canvas",
|
||||||
|
"svg"
|
||||||
|
],
|
||||||
|
"default": "canvas"
|
||||||
|
},
|
||||||
"renderInteractiveForms": {
|
"renderInteractiveForms": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": false
|
||||||
|
@ -1147,6 +1147,7 @@ var SVGGraphics = (function SVGGraphicsClosure() {
|
|||||||
svg.setAttributeNS(null, 'version', '1.1');
|
svg.setAttributeNS(null, 'version', '1.1');
|
||||||
svg.setAttributeNS(null, 'width', viewport.width + 'px');
|
svg.setAttributeNS(null, 'width', viewport.width + 'px');
|
||||||
svg.setAttributeNS(null, 'height', viewport.height + 'px');
|
svg.setAttributeNS(null, 'height', viewport.height + 'px');
|
||||||
|
svg.setAttributeNS(null, 'preserveAspectRatio', 'none');
|
||||||
svg.setAttributeNS(null, 'viewBox', '0 0 ' + viewport.width +
|
svg.setAttributeNS(null, 'viewBox', '0 0 ' + viewport.width +
|
||||||
' ' + viewport.height);
|
' ' + viewport.height);
|
||||||
|
|
||||||
|
13
web/app.js
13
web/app.js
@ -102,6 +102,7 @@ var getGlobalEventBus = domEventsLib.getGlobalEventBus;
|
|||||||
var normalizeWheelEventDelta = uiUtilsLib.normalizeWheelEventDelta;
|
var normalizeWheelEventDelta = uiUtilsLib.normalizeWheelEventDelta;
|
||||||
var animationStarted = uiUtilsLib.animationStarted;
|
var animationStarted = uiUtilsLib.animationStarted;
|
||||||
var localized = uiUtilsLib.localized;
|
var localized = uiUtilsLib.localized;
|
||||||
|
var RendererType = uiUtilsLib.RendererType;
|
||||||
|
|
||||||
var DEFAULT_SCALE_DELTA = 1.1;
|
var DEFAULT_SCALE_DELTA = 1.1;
|
||||||
var DISABLE_AUTO_FETCH_LOADING_BAR_TIMEOUT = 5000;
|
var DISABLE_AUTO_FETCH_LOADING_BAR_TIMEOUT = 5000;
|
||||||
@ -383,6 +384,12 @@ var PDFViewerApplication = {
|
|||||||
}
|
}
|
||||||
PDFJS.externalLinkTarget = value;
|
PDFJS.externalLinkTarget = value;
|
||||||
}),
|
}),
|
||||||
|
Preferences.get('renderer').then(function resolved(value) {
|
||||||
|
// TODO: Like the `enhanceTextSelection` preference, move the
|
||||||
|
// initialization and fetching of `Preferences` to occur
|
||||||
|
// before the various viewer components are initialized.
|
||||||
|
self.pdfViewer.renderer = value;
|
||||||
|
}),
|
||||||
Preferences.get('renderInteractiveForms').then(function resolved(value) {
|
Preferences.get('renderInteractiveForms').then(function resolved(value) {
|
||||||
// TODO: Like the `enhanceTextSelection` preference, move the
|
// TODO: Like the `enhanceTextSelection` preference, move the
|
||||||
// initialization and fetching of `Preferences` to occur
|
// initialization and fetching of `Preferences` to occur
|
||||||
@ -1140,7 +1147,11 @@ var PDFViewerApplication = {
|
|||||||
}
|
}
|
||||||
this.pdfViewer.cleanup();
|
this.pdfViewer.cleanup();
|
||||||
this.pdfThumbnailViewer.cleanup();
|
this.pdfThumbnailViewer.cleanup();
|
||||||
this.pdfDocument.cleanup();
|
|
||||||
|
// We don't want to remove fonts used by active page SVGs.
|
||||||
|
if (this.pdfViewer.renderer !== RendererType.SVG) {
|
||||||
|
this.pdfDocument.cleanup();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
forceRendering: function pdfViewForceRendering() {
|
forceRendering: function pdfViewForceRendering() {
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
"useOnlyCssZoom": false,
|
"useOnlyCssZoom": false,
|
||||||
"externalLinkTarget": 0,
|
"externalLinkTarget": 0,
|
||||||
"enhanceTextSelection": false,
|
"enhanceTextSelection": false,
|
||||||
|
"renderer": "canvas",
|
||||||
"renderInteractiveForms": false,
|
"renderInteractiveForms": false,
|
||||||
"disablePageLabels": false
|
"disablePageLabels": false
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ var DEFAULT_SCALE = uiUtils.DEFAULT_SCALE;
|
|||||||
var getOutputScale = uiUtils.getOutputScale;
|
var getOutputScale = uiUtils.getOutputScale;
|
||||||
var approximateFraction = uiUtils.approximateFraction;
|
var approximateFraction = uiUtils.approximateFraction;
|
||||||
var roundToDivide = uiUtils.roundToDivide;
|
var roundToDivide = uiUtils.roundToDivide;
|
||||||
|
var RendererType = uiUtils.RendererType;
|
||||||
var RenderingStates = pdfRenderingQueue.RenderingStates;
|
var RenderingStates = pdfRenderingQueue.RenderingStates;
|
||||||
|
|
||||||
var TEXT_LAYER_RENDER_DELAY = 200; // ms
|
var TEXT_LAYER_RENDER_DELAY = 200; // ms
|
||||||
@ -54,6 +55,7 @@ var TEXT_LAYER_RENDER_DELAY = 200; // ms
|
|||||||
* enhancement. The default is `false`.
|
* enhancement. The default is `false`.
|
||||||
* @property {boolean} renderInteractiveForms - Turns on rendering of
|
* @property {boolean} renderInteractiveForms - Turns on rendering of
|
||||||
* interactive form elements. The default is `false`.
|
* interactive form elements. The default is `false`.
|
||||||
|
* @property {string} renderer - 'canvas' or 'svg'. The default is 'canvas'.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -92,10 +94,13 @@ var PDFPageView = (function PDFPageViewClosure() {
|
|||||||
this.renderingQueue = renderingQueue;
|
this.renderingQueue = renderingQueue;
|
||||||
this.textLayerFactory = textLayerFactory;
|
this.textLayerFactory = textLayerFactory;
|
||||||
this.annotationLayerFactory = annotationLayerFactory;
|
this.annotationLayerFactory = annotationLayerFactory;
|
||||||
|
this.renderer = options.renderer || RendererType.CANVAS;
|
||||||
|
|
||||||
this.renderTask = null;
|
this.paintTask = null;
|
||||||
|
this.paintedViewport = null;
|
||||||
this.renderingState = RenderingStates.INITIAL;
|
this.renderingState = RenderingStates.INITIAL;
|
||||||
this.resume = null;
|
this.resume = null;
|
||||||
|
this.error = null;
|
||||||
|
|
||||||
this.onBeforeDraw = null;
|
this.onBeforeDraw = null;
|
||||||
this.onAfterDraw = null;
|
this.onAfterDraw = null;
|
||||||
@ -171,6 +176,12 @@ var PDFPageView = (function PDFPageViewClosure() {
|
|||||||
this.canvas.height = 0;
|
this.canvas.height = 0;
|
||||||
delete this.canvas;
|
delete this.canvas;
|
||||||
}
|
}
|
||||||
|
if (this.svg) {
|
||||||
|
delete this.svg;
|
||||||
|
}
|
||||||
|
if (!currentZoomLayerNode) {
|
||||||
|
this.paintedViewport = null;
|
||||||
|
}
|
||||||
|
|
||||||
this.loadingIconDiv = document.createElement('div');
|
this.loadingIconDiv = document.createElement('div');
|
||||||
this.loadingIconDiv.className = 'loadingIcon';
|
this.loadingIconDiv.className = 'loadingIcon';
|
||||||
@ -190,6 +201,17 @@ var PDFPageView = (function PDFPageViewClosure() {
|
|||||||
rotation: totalRotation
|
rotation: totalRotation
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (this.svg) {
|
||||||
|
this.cssTransform(this.svg, true);
|
||||||
|
|
||||||
|
this.eventBus.dispatch('pagerendered', {
|
||||||
|
source: this,
|
||||||
|
pageNumber: this.id,
|
||||||
|
cssTransform: true,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var isScalingRestricted = false;
|
var isScalingRestricted = false;
|
||||||
if (this.canvas && pdfjsLib.PDFJS.maxCanvasPixels > 0) {
|
if (this.canvas && pdfjsLib.PDFJS.maxCanvasPixels > 0) {
|
||||||
var outputScale = this.outputScale;
|
var outputScale = this.outputScale;
|
||||||
@ -224,9 +246,9 @@ var PDFPageView = (function PDFPageViewClosure() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
cancelRendering: function PDFPageView_cancelRendering() {
|
cancelRendering: function PDFPageView_cancelRendering() {
|
||||||
if (this.renderTask) {
|
if (this.paintTask) {
|
||||||
this.renderTask.cancel();
|
this.paintTask.cancel();
|
||||||
this.renderTask = null;
|
this.paintTask = null;
|
||||||
}
|
}
|
||||||
this.renderingState = RenderingStates.INITIAL;
|
this.renderingState = RenderingStates.INITIAL;
|
||||||
this.resume = null;
|
this.resume = null;
|
||||||
@ -246,19 +268,20 @@ var PDFPageView = (function PDFPageViewClosure() {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
cssTransform: function PDFPageView_transform(canvas, redrawAnnotations) {
|
cssTransform: function PDFPageView_transform(target, redrawAnnotations) {
|
||||||
var CustomStyle = pdfjsLib.CustomStyle;
|
var CustomStyle = pdfjsLib.CustomStyle;
|
||||||
|
|
||||||
// Scale canvas, canvas wrapper, and page container.
|
// Scale target (canvas or svg), its wrapper, and page container.
|
||||||
var width = this.viewport.width;
|
var width = this.viewport.width;
|
||||||
var height = this.viewport.height;
|
var height = this.viewport.height;
|
||||||
var div = this.div;
|
var div = this.div;
|
||||||
canvas.style.width = canvas.parentNode.style.width = div.style.width =
|
target.style.width = target.parentNode.style.width = div.style.width =
|
||||||
Math.floor(width) + 'px';
|
Math.floor(width) + 'px';
|
||||||
canvas.style.height = canvas.parentNode.style.height = div.style.height =
|
target.style.height = target.parentNode.style.height = div.style.height =
|
||||||
Math.floor(height) + 'px';
|
Math.floor(height) + 'px';
|
||||||
// The canvas may have been originally rotated, rotate relative to that.
|
// The canvas may have been originally rotated, rotate relative to that.
|
||||||
var relativeRotation = this.viewport.rotation - canvas._viewport.rotation;
|
var relativeRotation = this.viewport.rotation -
|
||||||
|
this.paintedViewport.rotation;
|
||||||
var absRotation = Math.abs(relativeRotation);
|
var absRotation = Math.abs(relativeRotation);
|
||||||
var scaleX = 1, scaleY = 1;
|
var scaleX = 1, scaleY = 1;
|
||||||
if (absRotation === 90 || absRotation === 270) {
|
if (absRotation === 90 || absRotation === 270) {
|
||||||
@ -268,7 +291,7 @@ var PDFPageView = (function PDFPageViewClosure() {
|
|||||||
}
|
}
|
||||||
var cssTransform = 'rotate(' + relativeRotation + 'deg) ' +
|
var cssTransform = 'rotate(' + relativeRotation + 'deg) ' +
|
||||||
'scale(' + scaleX + ',' + scaleY + ')';
|
'scale(' + scaleX + ',' + scaleY + ')';
|
||||||
CustomStyle.setProp('transform', canvas, cssTransform);
|
CustomStyle.setProp('transform', target, cssTransform);
|
||||||
|
|
||||||
if (this.textLayer) {
|
if (this.textLayer) {
|
||||||
// Rotating the text layer is more complicated since the divs inside the
|
// Rotating the text layer is more complicated since the divs inside the
|
||||||
@ -337,6 +360,7 @@ var PDFPageView = (function PDFPageViewClosure() {
|
|||||||
|
|
||||||
this.renderingState = RenderingStates.RUNNING;
|
this.renderingState = RenderingStates.RUNNING;
|
||||||
|
|
||||||
|
var self = this;
|
||||||
var pdfPage = this.pdfPage;
|
var pdfPage = this.pdfPage;
|
||||||
var viewport = this.viewport;
|
var viewport = this.viewport;
|
||||||
var div = this.div;
|
var div = this.div;
|
||||||
@ -347,20 +371,167 @@ var PDFPageView = (function PDFPageViewClosure() {
|
|||||||
canvasWrapper.style.height = div.style.height;
|
canvasWrapper.style.height = div.style.height;
|
||||||
canvasWrapper.classList.add('canvasWrapper');
|
canvasWrapper.classList.add('canvasWrapper');
|
||||||
|
|
||||||
var canvas = document.createElement('canvas');
|
|
||||||
canvas.id = 'page' + this.id;
|
|
||||||
// Keep the canvas hidden until the first draw callback, or until drawing
|
|
||||||
// is complete when `!this.renderingQueue`, to prevent black flickering.
|
|
||||||
canvas.setAttribute('hidden', 'hidden');
|
|
||||||
var isCanvasHidden = true;
|
|
||||||
|
|
||||||
canvasWrapper.appendChild(canvas);
|
|
||||||
if (this.annotationLayer && this.annotationLayer.div) {
|
if (this.annotationLayer && this.annotationLayer.div) {
|
||||||
// annotationLayer needs to stay on top
|
// annotationLayer needs to stay on top
|
||||||
div.insertBefore(canvasWrapper, this.annotationLayer.div);
|
div.insertBefore(canvasWrapper, this.annotationLayer.div);
|
||||||
} else {
|
} else {
|
||||||
div.appendChild(canvasWrapper);
|
div.appendChild(canvasWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var textLayerDiv = null;
|
||||||
|
var textLayer = null;
|
||||||
|
if (this.textLayerFactory) {
|
||||||
|
textLayerDiv = document.createElement('div');
|
||||||
|
textLayerDiv.className = 'textLayer';
|
||||||
|
textLayerDiv.style.width = canvasWrapper.style.width;
|
||||||
|
textLayerDiv.style.height = canvasWrapper.style.height;
|
||||||
|
if (this.annotationLayer && this.annotationLayer.div) {
|
||||||
|
// annotationLayer needs to stay on top
|
||||||
|
div.insertBefore(textLayerDiv, this.annotationLayer.div);
|
||||||
|
} else {
|
||||||
|
div.appendChild(textLayerDiv);
|
||||||
|
}
|
||||||
|
|
||||||
|
textLayer = this.textLayerFactory.
|
||||||
|
createTextLayerBuilder(textLayerDiv, this.id - 1, this.viewport,
|
||||||
|
this.enhanceTextSelection);
|
||||||
|
}
|
||||||
|
this.textLayer = textLayer;
|
||||||
|
|
||||||
|
var renderContinueCallback = null;
|
||||||
|
if (this.renderingQueue) {
|
||||||
|
renderContinueCallback = function renderContinueCallback(cont) {
|
||||||
|
if (!self.renderingQueue.isHighestPriority(self)) {
|
||||||
|
self.renderingState = RenderingStates.PAUSED;
|
||||||
|
self.resume = function resumeCallback() {
|
||||||
|
self.renderingState = RenderingStates.RUNNING;
|
||||||
|
cont();
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cont();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var finishPaintTask = function finishPaintTask(error) {
|
||||||
|
// The paintTask may have been replaced by a new one, so only remove
|
||||||
|
// the reference to the paintTask if it matches the one that is
|
||||||
|
// triggering this callback.
|
||||||
|
if (paintTask === self.paintTask) {
|
||||||
|
self.paintTask = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error === 'cancelled') {
|
||||||
|
self.error = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.renderingState = RenderingStates.FINISHED;
|
||||||
|
|
||||||
|
if (self.loadingIconDiv) {
|
||||||
|
div.removeChild(self.loadingIconDiv);
|
||||||
|
delete self.loadingIconDiv;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.zoomLayer) {
|
||||||
|
// Zeroing the width and height causes Firefox to release graphics
|
||||||
|
// resources immediately, which can greatly reduce memory consumption.
|
||||||
|
var zoomLayerCanvas = self.zoomLayer.firstChild;
|
||||||
|
zoomLayerCanvas.width = 0;
|
||||||
|
zoomLayerCanvas.height = 0;
|
||||||
|
|
||||||
|
if (div.contains(self.zoomLayer)) {
|
||||||
|
// Prevent "Node was not found" errors if the `zoomLayer` was
|
||||||
|
// already removed. This may occur intermittently if the scale
|
||||||
|
// changes many times in very quick succession.
|
||||||
|
div.removeChild(self.zoomLayer);
|
||||||
|
}
|
||||||
|
self.zoomLayer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.error = error;
|
||||||
|
self.stats = pdfPage.stats;
|
||||||
|
if (self.onAfterDraw) {
|
||||||
|
self.onAfterDraw();
|
||||||
|
}
|
||||||
|
self.eventBus.dispatch('pagerendered', {
|
||||||
|
source: self,
|
||||||
|
pageNumber: self.id,
|
||||||
|
cssTransform: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var paintTask = this.renderer === RendererType.SVG ?
|
||||||
|
this.paintOnSvg(canvasWrapper) :
|
||||||
|
this.paintOnCanvas(canvasWrapper);
|
||||||
|
paintTask.onRenderContinue = renderContinueCallback;
|
||||||
|
this.paintTask = paintTask;
|
||||||
|
|
||||||
|
var resultPromise = paintTask.promise.then(function () {
|
||||||
|
finishPaintTask(null);
|
||||||
|
if (textLayer) {
|
||||||
|
pdfPage.getTextContent({
|
||||||
|
normalizeWhitespace: true,
|
||||||
|
}).then(function textContentResolved(textContent) {
|
||||||
|
textLayer.setTextContent(textContent);
|
||||||
|
textLayer.render(TEXT_LAYER_RENDER_DELAY);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, function (reason) {
|
||||||
|
finishPaintTask(reason);
|
||||||
|
throw reason;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.annotationLayerFactory) {
|
||||||
|
if (!this.annotationLayer) {
|
||||||
|
this.annotationLayer = this.annotationLayerFactory.
|
||||||
|
createAnnotationLayerBuilder(div, pdfPage,
|
||||||
|
this.renderInteractiveForms);
|
||||||
|
}
|
||||||
|
this.annotationLayer.render(this.viewport, 'display');
|
||||||
|
}
|
||||||
|
div.setAttribute('data-loaded', true);
|
||||||
|
|
||||||
|
if (this.onBeforeDraw) {
|
||||||
|
this.onBeforeDraw();
|
||||||
|
}
|
||||||
|
return resultPromise;
|
||||||
|
},
|
||||||
|
|
||||||
|
paintOnCanvas: function (canvasWrapper) {
|
||||||
|
var resolveRenderPromise, rejectRenderPromise;
|
||||||
|
var promise = new Promise(function (resolve, reject) {
|
||||||
|
resolveRenderPromise = resolve;
|
||||||
|
rejectRenderPromise = reject;
|
||||||
|
});
|
||||||
|
|
||||||
|
var result = {
|
||||||
|
promise: promise,
|
||||||
|
onRenderContinue: function (cont) {
|
||||||
|
cont();
|
||||||
|
},
|
||||||
|
cancel: function () {
|
||||||
|
renderTask.cancel();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
var pdfPage = this.pdfPage;
|
||||||
|
var viewport = this.viewport;
|
||||||
|
var canvas = document.createElement('canvas');
|
||||||
|
canvas.id = 'page' + this.id;
|
||||||
|
// Keep the canvas hidden until the first draw callback, or until drawing
|
||||||
|
// is complete when `!this.renderingQueue`, to prevent black flickering.
|
||||||
|
canvas.setAttribute('hidden', 'hidden');
|
||||||
|
var isCanvasHidden = true;
|
||||||
|
var showCanvas = function () {
|
||||||
|
if (isCanvasHidden) {
|
||||||
|
canvas.removeAttribute('hidden');
|
||||||
|
isCanvasHidden = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
canvasWrapper.appendChild(canvas);
|
||||||
this.canvas = canvas;
|
this.canvas = canvas;
|
||||||
|
|
||||||
if (typeof PDFJSDev === 'undefined' ||
|
if (typeof PDFJSDev === 'undefined' ||
|
||||||
@ -402,115 +573,9 @@ var PDFPageView = (function PDFPageViewClosure() {
|
|||||||
canvas.style.width = roundToDivide(viewport.width, sfx[1]) + 'px';
|
canvas.style.width = roundToDivide(viewport.width, sfx[1]) + 'px';
|
||||||
canvas.style.height = roundToDivide(viewport.height, sfy[1]) + 'px';
|
canvas.style.height = roundToDivide(viewport.height, sfy[1]) + 'px';
|
||||||
// Add the viewport so it's known what it was originally drawn with.
|
// Add the viewport so it's known what it was originally drawn with.
|
||||||
canvas._viewport = viewport;
|
this.paintedViewport = viewport;
|
||||||
|
|
||||||
var textLayerDiv = null;
|
|
||||||
var textLayer = null;
|
|
||||||
if (this.textLayerFactory) {
|
|
||||||
textLayerDiv = document.createElement('div');
|
|
||||||
textLayerDiv.className = 'textLayer';
|
|
||||||
textLayerDiv.style.width = canvasWrapper.style.width;
|
|
||||||
textLayerDiv.style.height = canvasWrapper.style.height;
|
|
||||||
if (this.annotationLayer && this.annotationLayer.div) {
|
|
||||||
// annotationLayer needs to stay on top
|
|
||||||
div.insertBefore(textLayerDiv, this.annotationLayer.div);
|
|
||||||
} else {
|
|
||||||
div.appendChild(textLayerDiv);
|
|
||||||
}
|
|
||||||
|
|
||||||
textLayer = this.textLayerFactory.
|
|
||||||
createTextLayerBuilder(textLayerDiv, this.id - 1, this.viewport,
|
|
||||||
this.enhanceTextSelection);
|
|
||||||
}
|
|
||||||
this.textLayer = textLayer;
|
|
||||||
|
|
||||||
var resolveRenderPromise, rejectRenderPromise;
|
|
||||||
var promise = new Promise(function (resolve, reject) {
|
|
||||||
resolveRenderPromise = resolve;
|
|
||||||
rejectRenderPromise = reject;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Rendering area
|
// Rendering area
|
||||||
|
|
||||||
var self = this;
|
|
||||||
function pageViewDrawCallback(error) {
|
|
||||||
// The renderTask may have been replaced by a new one, so only remove
|
|
||||||
// the reference to the renderTask if it matches the one that is
|
|
||||||
// triggering this callback.
|
|
||||||
if (renderTask === self.renderTask) {
|
|
||||||
self.renderTask = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error === 'cancelled') {
|
|
||||||
rejectRenderPromise(error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.renderingState = RenderingStates.FINISHED;
|
|
||||||
|
|
||||||
if (isCanvasHidden) {
|
|
||||||
self.canvas.removeAttribute('hidden');
|
|
||||||
isCanvasHidden = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.loadingIconDiv) {
|
|
||||||
div.removeChild(self.loadingIconDiv);
|
|
||||||
delete self.loadingIconDiv;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.zoomLayer) {
|
|
||||||
// Zeroing the width and height causes Firefox to release graphics
|
|
||||||
// resources immediately, which can greatly reduce memory consumption.
|
|
||||||
var zoomLayerCanvas = self.zoomLayer.firstChild;
|
|
||||||
zoomLayerCanvas.width = 0;
|
|
||||||
zoomLayerCanvas.height = 0;
|
|
||||||
|
|
||||||
if (div.contains(self.zoomLayer)) {
|
|
||||||
// Prevent "Node was not found" errors if the `zoomLayer` was
|
|
||||||
// already removed. This may occur intermittently if the scale
|
|
||||||
// changes many times in very quick succession.
|
|
||||||
div.removeChild(self.zoomLayer);
|
|
||||||
}
|
|
||||||
self.zoomLayer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.error = error;
|
|
||||||
self.stats = pdfPage.stats;
|
|
||||||
if (self.onAfterDraw) {
|
|
||||||
self.onAfterDraw();
|
|
||||||
}
|
|
||||||
self.eventBus.dispatch('pagerendered', {
|
|
||||||
source: self,
|
|
||||||
pageNumber: self.id,
|
|
||||||
cssTransform: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!error) {
|
|
||||||
resolveRenderPromise(undefined);
|
|
||||||
} else {
|
|
||||||
rejectRenderPromise(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var renderContinueCallback = null;
|
|
||||||
if (this.renderingQueue) {
|
|
||||||
renderContinueCallback = function renderContinueCallback(cont) {
|
|
||||||
if (!self.renderingQueue.isHighestPriority(self)) {
|
|
||||||
self.renderingState = RenderingStates.PAUSED;
|
|
||||||
self.resume = function resumeCallback() {
|
|
||||||
self.renderingState = RenderingStates.RUNNING;
|
|
||||||
cont();
|
|
||||||
};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (isCanvasHidden) {
|
|
||||||
self.canvas.removeAttribute('hidden');
|
|
||||||
isCanvasHidden = false;
|
|
||||||
}
|
|
||||||
cont();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var transform = !outputScale.scaled ? null :
|
var transform = !outputScale.scaled ? null :
|
||||||
[outputScale.sx, 0, 0, outputScale.sy, 0, 0];
|
[outputScale.sx, 0, 0, outputScale.sy, 0, 0];
|
||||||
var renderContext = {
|
var renderContext = {
|
||||||
@ -520,40 +585,71 @@ var PDFPageView = (function PDFPageViewClosure() {
|
|||||||
renderInteractiveForms: this.renderInteractiveForms,
|
renderInteractiveForms: this.renderInteractiveForms,
|
||||||
// intent: 'default', // === 'display'
|
// intent: 'default', // === 'display'
|
||||||
};
|
};
|
||||||
var renderTask = this.renderTask = this.pdfPage.render(renderContext);
|
var renderTask = this.pdfPage.render(renderContext);
|
||||||
renderTask.onContinue = renderContinueCallback;
|
renderTask.onContinue = function (cont) {
|
||||||
|
showCanvas();
|
||||||
|
if (result.onRenderContinue) {
|
||||||
|
result.onRenderContinue(cont);
|
||||||
|
} else {
|
||||||
|
cont();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
this.renderTask.promise.then(
|
renderTask.promise.then(
|
||||||
function pdfPageRenderCallback() {
|
function pdfPageRenderCallback() {
|
||||||
pageViewDrawCallback(null);
|
showCanvas();
|
||||||
if (textLayer) {
|
resolveRenderPromise(undefined);
|
||||||
self.pdfPage.getTextContent({
|
|
||||||
normalizeWhitespace: true,
|
|
||||||
}).then(function textContentResolved(textContent) {
|
|
||||||
textLayer.setTextContent(textContent);
|
|
||||||
textLayer.render(TEXT_LAYER_RENDER_DELAY);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
function pdfPageRenderError(error) {
|
function pdfPageRenderError(error) {
|
||||||
pageViewDrawCallback(error);
|
showCanvas();
|
||||||
|
rejectRenderPromise(error);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
if (this.annotationLayerFactory) {
|
return result;
|
||||||
if (!this.annotationLayer) {
|
},
|
||||||
this.annotationLayer = this.annotationLayerFactory.
|
|
||||||
createAnnotationLayerBuilder(div, this.pdfPage,
|
|
||||||
this.renderInteractiveForms);
|
|
||||||
}
|
|
||||||
this.annotationLayer.render(this.viewport, 'display');
|
|
||||||
}
|
|
||||||
div.setAttribute('data-loaded', true);
|
|
||||||
|
|
||||||
if (self.onBeforeDraw) {
|
paintOnSvg: function PDFPageView_paintOnSvg(wrapper) {
|
||||||
self.onBeforeDraw();
|
if (typeof PDFJSDev !== 'undefined' &&
|
||||||
|
PDFJSDev.test('FIREFOX || MOZCENTRAL || CHROME')) {
|
||||||
|
return Promise.resolve('SVG rendering is not supported.');
|
||||||
}
|
}
|
||||||
return promise;
|
|
||||||
|
var cancelled = false;
|
||||||
|
var ensureNotCancelled = function () {
|
||||||
|
if (cancelled) {
|
||||||
|
throw 'cancelled';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
var pdfPage = this.pdfPage;
|
||||||
|
var SVGGraphics = pdfjsLib.SVGGraphics;
|
||||||
|
var actualSizeViewport = this.viewport.clone({scale: CSS_UNITS});
|
||||||
|
var promise = pdfPage.getOperatorList().then(function (opList) {
|
||||||
|
ensureNotCancelled();
|
||||||
|
var svgGfx = new SVGGraphics(pdfPage.commonObjs, pdfPage.objs);
|
||||||
|
return svgGfx.getSVG(opList, actualSizeViewport).then(function (svg) {
|
||||||
|
ensureNotCancelled();
|
||||||
|
self.svg = svg;
|
||||||
|
self.paintedViewport = actualSizeViewport;
|
||||||
|
|
||||||
|
svg.style.width = wrapper.style.width;
|
||||||
|
svg.style.height = wrapper.style.height;
|
||||||
|
self.renderingState = RenderingStates.FINISHED;
|
||||||
|
wrapper.appendChild(svg);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
promise: promise,
|
||||||
|
onRenderContinue: function (cont) {
|
||||||
|
cont();
|
||||||
|
},
|
||||||
|
cancel: function () {
|
||||||
|
cancelled = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,6 +45,7 @@ var MAX_AUTO_SCALE = uiUtils.MAX_AUTO_SCALE;
|
|||||||
var CSS_UNITS = uiUtils.CSS_UNITS;
|
var CSS_UNITS = uiUtils.CSS_UNITS;
|
||||||
var DEFAULT_SCALE = uiUtils.DEFAULT_SCALE;
|
var DEFAULT_SCALE = uiUtils.DEFAULT_SCALE;
|
||||||
var DEFAULT_SCALE_VALUE = uiUtils.DEFAULT_SCALE_VALUE;
|
var DEFAULT_SCALE_VALUE = uiUtils.DEFAULT_SCALE_VALUE;
|
||||||
|
var RendererType = uiUtils.RendererType;
|
||||||
var scrollIntoView = uiUtils.scrollIntoView;
|
var scrollIntoView = uiUtils.scrollIntoView;
|
||||||
var watchScroll = uiUtils.watchScroll;
|
var watchScroll = uiUtils.watchScroll;
|
||||||
var getVisibleElements = uiUtils.getVisibleElements;
|
var getVisibleElements = uiUtils.getVisibleElements;
|
||||||
@ -80,6 +81,7 @@ var DEFAULT_CACHE_SIZE = 10;
|
|||||||
* text selection behaviour. The default is `false`.
|
* text selection behaviour. The default is `false`.
|
||||||
* @property {boolean} renderInteractiveForms - (optional) Enables rendering of
|
* @property {boolean} renderInteractiveForms - (optional) Enables rendering of
|
||||||
* interactive form elements. The default is `false`.
|
* interactive form elements. The default is `false`.
|
||||||
|
* @property {string} renderer - 'canvas' or 'svg'. The default is 'canvas'.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -133,6 +135,7 @@ var PDFViewer = (function pdfViewer() {
|
|||||||
this.removePageBorders = options.removePageBorders || false;
|
this.removePageBorders = options.removePageBorders || false;
|
||||||
this.enhanceTextSelection = options.enhanceTextSelection || false;
|
this.enhanceTextSelection = options.enhanceTextSelection || false;
|
||||||
this.renderInteractiveForms = options.renderInteractiveForms || false;
|
this.renderInteractiveForms = options.renderInteractiveForms || false;
|
||||||
|
this.renderer = options.renderer || RendererType.CANVAS;
|
||||||
|
|
||||||
this.defaultRenderingQueue = !options.renderingQueue;
|
this.defaultRenderingQueue = !options.renderingQueue;
|
||||||
if (this.defaultRenderingQueue) {
|
if (this.defaultRenderingQueue) {
|
||||||
@ -393,6 +396,7 @@ var PDFViewer = (function pdfViewer() {
|
|||||||
annotationLayerFactory: this,
|
annotationLayerFactory: this,
|
||||||
enhanceTextSelection: this.enhanceTextSelection,
|
enhanceTextSelection: this.enhanceTextSelection,
|
||||||
renderInteractiveForms: this.renderInteractiveForms,
|
renderInteractiveForms: this.renderInteractiveForms,
|
||||||
|
renderer: this.renderer,
|
||||||
});
|
});
|
||||||
bindOnAfterAndBeforeDraw(pageView);
|
bindOnAfterAndBeforeDraw(pageView);
|
||||||
this._pages.push(pageView);
|
this._pages.push(pageView);
|
||||||
|
@ -35,6 +35,11 @@ var MAX_AUTO_SCALE = 1.25;
|
|||||||
var SCROLLBAR_PADDING = 40;
|
var SCROLLBAR_PADDING = 40;
|
||||||
var VERTICAL_PADDING = 5;
|
var VERTICAL_PADDING = 5;
|
||||||
|
|
||||||
|
var RendererType = {
|
||||||
|
CANVAS: 'canvas',
|
||||||
|
SVG: 'svg',
|
||||||
|
};
|
||||||
|
|
||||||
var mozL10n = document.mozL10n || document.webL10n;
|
var mozL10n = document.mozL10n || document.webL10n;
|
||||||
|
|
||||||
var PDFJS = pdfjsLib.PDFJS;
|
var PDFJS = pdfjsLib.PDFJS;
|
||||||
@ -568,6 +573,7 @@ exports.UNKNOWN_SCALE = UNKNOWN_SCALE;
|
|||||||
exports.MAX_AUTO_SCALE = MAX_AUTO_SCALE;
|
exports.MAX_AUTO_SCALE = MAX_AUTO_SCALE;
|
||||||
exports.SCROLLBAR_PADDING = SCROLLBAR_PADDING;
|
exports.SCROLLBAR_PADDING = SCROLLBAR_PADDING;
|
||||||
exports.VERTICAL_PADDING = VERTICAL_PADDING;
|
exports.VERTICAL_PADDING = VERTICAL_PADDING;
|
||||||
|
exports.RendererType = RendererType;
|
||||||
exports.mozL10n = mozL10n;
|
exports.mozL10n = mozL10n;
|
||||||
exports.EventBus = EventBus;
|
exports.EventBus = EventBus;
|
||||||
exports.ProgressBar = ProgressBar;
|
exports.ProgressBar = ProgressBar;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user