Browse Source

Refactors PDFPageView_draw.

Yury Delendik 9 years ago
parent
commit
c9a0955c9c
  1. 276
      web/pdf_page_view.js

276
web/pdf_page_view.js

@ -93,9 +93,11 @@ var PDFPageView = (function PDFPageViewClosure() {
this.textLayerFactory = textLayerFactory; this.textLayerFactory = textLayerFactory;
this.annotationLayerFactory = annotationLayerFactory; this.annotationLayerFactory = annotationLayerFactory;
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 +173,9 @@ var PDFPageView = (function PDFPageViewClosure() {
this.canvas.height = 0; this.canvas.height = 0;
delete this.canvas; delete this.canvas;
} }
if (!currentZoomLayerNode) {
this.paintedViewport = null;
}
this.loadingIconDiv = document.createElement('div'); this.loadingIconDiv = document.createElement('div');
this.loadingIconDiv.className = 'loadingIcon'; this.loadingIconDiv.className = 'loadingIcon';
@ -224,9 +229,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;
@ -258,7 +263,8 @@ var PDFPageView = (function PDFPageViewClosure() {
canvas.style.height = canvas.parentNode.style.height = div.style.height = canvas.style.height = canvas.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) {
@ -337,6 +343,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,62 +354,12 @@ 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);
} }
this.canvas = canvas;
if (typeof PDFJSDev === 'undefined' ||
PDFJSDev.test('MOZCENTRAL || FIREFOX || GENERIC')) {
canvas.mozOpaque = true;
}
var ctx = canvas.getContext('2d', {alpha: false});
var outputScale = getOutputScale(ctx);
this.outputScale = outputScale;
if (pdfjsLib.PDFJS.useOnlyCssZoom) {
var actualSizeViewport = viewport.clone({scale: CSS_UNITS});
// Use a scale that will make the canvas be the original intended size
// of the page.
outputScale.sx *= actualSizeViewport.width / viewport.width;
outputScale.sy *= actualSizeViewport.height / viewport.height;
outputScale.scaled = true;
}
if (pdfjsLib.PDFJS.maxCanvasPixels > 0) {
var pixelsInViewport = viewport.width * viewport.height;
var maxScale =
Math.sqrt(pdfjsLib.PDFJS.maxCanvasPixels / pixelsInViewport);
if (outputScale.sx > maxScale || outputScale.sy > maxScale) {
outputScale.sx = maxScale;
outputScale.sy = maxScale;
outputScale.scaled = true;
this.hasRestrictedScaling = true;
} else {
this.hasRestrictedScaling = false;
}
}
var sfx = approximateFraction(outputScale.sx);
var sfy = approximateFraction(outputScale.sy);
canvas.width = roundToDivide(viewport.width * outputScale.sx, sfx[0]);
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.
canvas._viewport = viewport;
var textLayerDiv = null; var textLayerDiv = null;
var textLayer = null; var textLayer = null;
@ -424,35 +381,36 @@ var PDFPageView = (function PDFPageViewClosure() {
} }
this.textLayer = textLayer; this.textLayer = textLayer;
var resolveRenderPromise, rejectRenderPromise; var renderContinueCallback = null;
var promise = new Promise(function (resolve, reject) { if (this.renderingQueue) {
resolveRenderPromise = resolve; renderContinueCallback = function renderContinueCallback(cont) {
rejectRenderPromise = reject; if (!self.renderingQueue.isHighestPriority(self)) {
}); self.renderingState = RenderingStates.PAUSED;
self.resume = function resumeCallback() {
// Rendering area self.renderingState = RenderingStates.RUNNING;
cont();
};
return;
}
cont();
};
}
var self = this; var finishPaintTask = function finishPaintTask(error) {
function pageViewDrawCallback(error) { // The paintTask may have been replaced by a new one, so only remove
// The renderTask may have been replaced by a new one, so only remove // the reference to the paintTask if it matches the one that is
// the reference to the renderTask if it matches the one that is
// triggering this callback. // triggering this callback.
if (renderTask === self.renderTask) { if (paintTask === self.paintTask) {
self.renderTask = null; self.paintTask = null;
} }
if (error === 'cancelled') { if (error === 'cancelled') {
rejectRenderPromise(error); self.error = null;
return; return;
} }
self.renderingState = RenderingStates.FINISHED; self.renderingState = RenderingStates.FINISHED;
if (isCanvasHidden) {
self.canvas.removeAttribute('hidden');
isCanvasHidden = false;
}
if (self.loadingIconDiv) { if (self.loadingIconDiv) {
div.removeChild(self.loadingIconDiv); div.removeChild(self.loadingIconDiv);
delete self.loadingIconDiv; delete self.loadingIconDiv;
@ -484,33 +442,121 @@ var PDFPageView = (function PDFPageViewClosure() {
pageNumber: self.id, pageNumber: self.id,
cssTransform: false, cssTransform: false,
}); });
};
if (!error) { var paintTask = this.paintOnCanvas(canvasWrapper);
resolveRenderPromise(undefined); paintTask.onRenderContinue = renderContinueCallback;
} else { this.paintTask = paintTask;
rejectRenderPromise(error);
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);
var renderContinueCallback = null; if (this.onBeforeDraw) {
if (this.renderingQueue) { this.onBeforeDraw();
renderContinueCallback = function renderContinueCallback(cont) { }
if (!self.renderingQueue.isHighestPriority(self)) { return resultPromise;
self.renderingState = RenderingStates.PAUSED; },
self.resume = function resumeCallback() {
self.renderingState = RenderingStates.RUNNING; paintOnCanvas: function (canvasWrapper) {
cont(); var resolveRenderPromise, rejectRenderPromise;
}; var promise = new Promise(function (resolve, reject) {
return; resolveRenderPromise = resolve;
} rejectRenderPromise = reject;
if (isCanvasHidden) { });
self.canvas.removeAttribute('hidden');
isCanvasHidden = false; var result = {
} promise: promise,
onRenderContinue: function (cont) {
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;
if (typeof PDFJSDev === 'undefined' ||
PDFJSDev.test('MOZCENTRAL || FIREFOX || GENERIC')) {
canvas.mozOpaque = true;
} }
var ctx = canvas.getContext('2d', {alpha: false});
var outputScale = getOutputScale(ctx);
this.outputScale = outputScale;
if (pdfjsLib.PDFJS.useOnlyCssZoom) {
var actualSizeViewport = viewport.clone({scale: CSS_UNITS});
// Use a scale that will make the canvas be the original intended size
// of the page.
outputScale.sx *= actualSizeViewport.width / viewport.width;
outputScale.sy *= actualSizeViewport.height / viewport.height;
outputScale.scaled = true;
}
if (pdfjsLib.PDFJS.maxCanvasPixels > 0) {
var pixelsInViewport = viewport.width * viewport.height;
var maxScale =
Math.sqrt(pdfjsLib.PDFJS.maxCanvasPixels / pixelsInViewport);
if (outputScale.sx > maxScale || outputScale.sy > maxScale) {
outputScale.sx = maxScale;
outputScale.sy = maxScale;
outputScale.scaled = true;
this.hasRestrictedScaling = true;
} else {
this.hasRestrictedScaling = false;
}
}
var sfx = approximateFraction(outputScale.sx);
var sfy = approximateFraction(outputScale.sy);
canvas.width = roundToDivide(viewport.width * outputScale.sx, sfx[0]);
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.paintedViewport = viewport;
// Rendering area
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 +566,28 @@ 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) {
self.onBeforeDraw();
}
return promise;
}, },
/** /**

Loading…
Cancel
Save