| Index: chrome/browser/resources/pdf/viewport.js
|
| diff --git a/chrome/browser/resources/pdf/viewport.js b/chrome/browser/resources/pdf/viewport.js
|
| index 4cb8fee0f66a994dd1959295b0ab8483d191890b..dc9f86560db44b653cc3778f52b255aa2383b9e8 100644
|
| --- a/chrome/browser/resources/pdf/viewport.js
|
| +++ b/chrome/browser/resources/pdf/viewport.js
|
| @@ -49,6 +49,10 @@ function Viewport(window,
|
| this.fittingType_ = Viewport.FittingType.NONE;
|
| this.defaultZoom_ = defaultZoom;
|
| this.topToolbarHeight_ = topToolbarHeight;
|
| + this.prevScale = 1;
|
| + this.doRender_ = true;
|
| + this.didPinch_ = false;
|
| + this.didPinchEnd_ = false;
|
|
|
| window.addEventListener('scroll', this.updateViewport_.bind(this));
|
| window.addEventListener('resize', this.resize_.bind(this));
|
| @@ -170,9 +174,7 @@ Viewport.prototype = {
|
| * @private
|
| * Called when the viewport should be updated.
|
| */
|
| - updateViewport_: function() {
|
| - this.viewportChangedCallback_();
|
| - },
|
| + updateViewport_: function() { this.viewportChangedCallback_(); },
|
|
|
| /**
|
| * @private
|
| @@ -221,9 +223,7 @@ Viewport.prototype = {
|
| /**
|
| * @type {number} the zoom level of the viewport.
|
| */
|
| - get zoom() {
|
| - return this.zoom_;
|
| - },
|
| + get zoom() { return this.zoom_; },
|
|
|
| /**
|
| * @private
|
| @@ -236,6 +236,13 @@ Viewport.prototype = {
|
| this.beforeZoomCallback_();
|
| this.allowedToChangeZoom_ = true;
|
| f();
|
| + var needsScrollbars = this.documentNeedsScrollbars_(this.zoom_);
|
| + if (!needsScrollbars.horizontal) {
|
| + this.pinchCenter_ = {
|
| + x: this.window_.innerWidth / 2,
|
| + y: this.window_.innerHeight / 2
|
| + };
|
| + }
|
| this.allowedToChangeZoom_ = false;
|
| this.afterZoomCallback_();
|
| },
|
| @@ -265,6 +272,59 @@ Viewport.prototype = {
|
| },
|
|
|
| /**
|
| + * @private
|
| + * Sets the zoom of the viewport.
|
| + * Same function as below but for pinch zoom we have some more operations.
|
| + * @param {number} scaleDelta the zoom delta.
|
| + * @param {Object} center the pinch center in content coordinates
|
| + */
|
| + setPinchZoomInternal_: function(scaleDelta, center) {
|
| + if (!this.allowedToChangeZoom_) {
|
| + throw 'Called Viewport.setZoomInternal_ without calling ' +
|
| + 'Viewport.mightZoom_.';
|
| + }
|
| + this.zoom_ = this.clampScale(this.zoom_ * scaleDelta);
|
| +
|
| + var newCenterInContent = this.frameToContent(center);
|
| + var delta = {
|
| + x: (newCenterInContent.x - this.oldCenterInContent.x),
|
| + y: (newCenterInContent.y - this.oldCenterInContent.y)
|
| + };
|
| +
|
| + // Record the scroll position (relative to the pinch center).
|
| + var currentScrollPos = {
|
| + x: this.position.x - delta.x * this.zoom_,
|
| + y: this.position.y - delta.y * this.zoom_
|
| + };
|
| +
|
| + this.contentSizeChanged_();
|
| + // Scroll to the scaled scroll position.
|
| + this.position = {x: currentScrollPos.x, y: currentScrollPos.y};
|
| + },
|
| +
|
| + /**
|
| + * @private
|
| + * Makes sure that the scale level doesn't get out of the limits.
|
| + * @param {number} scale the new scale level
|
| + * @return {number} the scale clamped in the limit
|
| + */
|
| + clampScale: function(scale) { return Math.min(5, Math.max(0.25, scale)); },
|
| +
|
| + /**
|
| + * @private
|
| + * Gets the new center in content.
|
| + * @param {Object} pinch center
|
| + * @param {Object} zoom level
|
| + * @return {Objet} the new center in content
|
| + */
|
| + frameToContent: function(framePoint) {
|
| + return {
|
| + x: (framePoint.x + this.position.x) / this.zoom_,
|
| + y: (framePoint.y + this.position.y) / this.zoom_
|
| + };
|
| + },
|
| +
|
| + /**
|
| * Sets the zoom to the given zoom level.
|
| * @param {number} newZoom the zoom level to zoom to.
|
| */
|
| @@ -281,16 +341,12 @@ Viewport.prototype = {
|
| /**
|
| * @type {number} the width of scrollbars in the viewport in pixels.
|
| */
|
| - get scrollbarWidth() {
|
| - return this.scrollbarWidth_;
|
| - },
|
| + get scrollbarWidth() { return this.scrollbarWidth_; },
|
|
|
| /**
|
| * @type {Viewport.FittingType} the fitting type the viewport is currently in.
|
| */
|
| - get fittingType() {
|
| - return this.fittingType_;
|
| - },
|
| + get fittingType() { return this.fittingType_; },
|
|
|
| /**
|
| * @private
|
| @@ -456,14 +512,26 @@ Viewport.prototype = {
|
| this.updateViewport_();
|
| }.bind(this));
|
| },
|
| + /**
|
| + * @private
|
| + * Computes vector between two points.
|
| + * @param {Object} First Point
|
| + * @param {Object} Second Point
|
| + * @return {Object} The vector
|
| + */
|
| + vectorDelta: function(p1, p2) {
|
| + var vector = {
|
| + x: p2.x - p1.x,
|
| + y: p2.y - p1.y
|
| + };
|
| + return vector;
|
| + },
|
|
|
| /**
|
| * Zoom the viewport so that a page consumes the entire viewport. Also scrolls
|
| * the viewport to the top of the current page.
|
| */
|
| - fitToPage: function() {
|
| - this.fitToPageInternal_(true);
|
| - },
|
| + fitToPage: function() { this.fitToPageInternal_(true); },
|
|
|
| /**
|
| * Zoom out to the next predefined zoom level.
|
| @@ -498,6 +566,74 @@ Viewport.prototype = {
|
| },
|
|
|
| /**
|
| + * Pinch zoom event handler
|
| + * @param {ev} the pinch event
|
| + */
|
| + pinchZoom: function(ev) {
|
| + this.mightZoom_(function() {
|
| + // We render on pinchin in order to solve the invalid regions that appear
|
| + // after zooming out.
|
| + if (ev.additionalEvent == 'pinchin')
|
| + this.doRender_ = true;
|
| + else
|
| + this.doRender_ = false;
|
| +
|
| + var scaleDelta = ev.scale / this.prevScale;
|
| + this.pinchPanVector_ = this.vectorDelta(ev.center, this.first_pinch_center_in_frame_);
|
| +
|
| + var needsScrollbars = this.documentNeedsScrollbars_(
|
| + this.clampScale(this.zoom_ * scaleDelta));
|
| + // If there's no horizontal scrolling, keep the content centered so the
|
| + // user can't zoom in on the non-content area.
|
| + if (this.keepContentCentered_ && needsScrollbars.horizontal) {
|
| + this.oldCenterInContent =
|
| + this.frameToContent(this.frameToPluginCoordinate(ev.center));
|
| + this.keepContentCentered_ = false;
|
| + }
|
| +
|
| + this.pinchCenter_ = ev.center;
|
| + this.setPinchZoomInternal_(scaleDelta, this.frameToPluginCoordinate(ev.center));
|
| + this.updateViewport_();
|
| + this.prevScale = ev.scale;
|
| + }.bind(this));
|
| + },
|
| +
|
| + pinchZoomStart: function(ev) {
|
| + this.prevScale = 1;
|
| + this.oldCenterInContent =
|
| + this.frameToContent(this.frameToPluginCoordinate(ev.center));
|
| +
|
| + var needsScrollbars = this.documentNeedsScrollbars_(this.zoom_);
|
| + if (!needsScrollbars.horizontal)
|
| + this.keepContentCentered_ = true;
|
| + else
|
| + this.keepContentCentered_ = false;
|
| + // We keep track of begining of the pinch.
|
| + // By doing so we will be able to compute the pan distance.
|
| + this.first_pinch_center_in_frame_ = ev.center;
|
| + },
|
| +
|
| + pinchZoomEnd: function(ev) {
|
| + this.mightZoom_(function() {
|
| + // We want to render the document on pinch end
|
| + this.doRender_ = true;
|
| + var scaleDelta = ev.scale / this.prevScale;
|
| + this.pinchCenter_ = ev.center;
|
| +
|
| + this.setPinchZoomInternal_(scaleDelta, this.frameToPluginCoordinate(ev.center));
|
| + this.updateViewport_();
|
| + }.bind(this));
|
| + },
|
| +
|
| + frameToPluginCoordinate: function(coordinateInFrame) {
|
| + var container = $('plugin');
|
| + return {
|
| + x: coordinateInFrame.x - container.getBoundingClientRect().left,
|
| + y: coordinateInFrame.y - container.getBoundingClientRect().top
|
| + };
|
| + },
|
| +
|
| + /**
|
| * Go to the given page index.
|
| * @param {number} page the index of the page to go to. zero-based.
|
| */
|
|
|