Browse Source

Adds SVG rendering capabilities to the PDFViewer.

Yury Delendik 9 years ago
parent
commit
f7d6f3a739
  1. 8
      extensions/chromium/preferences_schema.json
  2. 1
      src/display/svg.js
  3. 13
      web/app.js
  4. 1
      web/default_preferences.json
  5. 74
      web/pdf_page_view.js
  6. 4
      web/pdf_viewer.js
  7. 6
      web/ui_utils.js

8
extensions/chromium/preferences_schema.json

@ -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

1
src/display/svg.js

@ -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

@ -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() {

1
web/default_preferences.json

@ -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
} }

74
web/pdf_page_view.js

@ -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,6 +94,7 @@ 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.paintTask = null; this.paintTask = null;
this.paintedViewport = null; this.paintedViewport = null;
@ -173,6 +176,9 @@ 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) { if (!currentZoomLayerNode) {
this.paintedViewport = null; this.paintedViewport = null;
} }
@ -195,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;
@ -251,16 +268,16 @@ 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 - var relativeRotation = this.viewport.rotation -
@ -274,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
@ -444,7 +461,9 @@ var PDFPageView = (function PDFPageViewClosure() {
}); });
}; };
var paintTask = this.paintOnCanvas(canvasWrapper); var paintTask = this.renderer === RendererType.SVG ?
this.paintOnSvg(canvasWrapper) :
this.paintOnCanvas(canvasWrapper);
paintTask.onRenderContinue = renderContinueCallback; paintTask.onRenderContinue = renderContinueCallback;
this.paintTask = paintTask; this.paintTask = paintTask;
@ -590,6 +609,49 @@ var PDFPageView = (function PDFPageViewClosure() {
return result; return result;
}, },
paintOnSvg: function PDFPageView_paintOnSvg(wrapper) {
if (typeof PDFJSDev !== 'undefined' &&
PDFJSDev.test('FIREFOX || MOZCENTRAL || CHROME')) {
return Promise.resolve('SVG rendering is not supported.');
}
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;
}
};
},
/** /**
* @param {string|null} label * @param {string|null} label
*/ */

4
web/pdf_viewer.js

@ -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);

6
web/ui_utils.js

@ -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…
Cancel
Save