| Index: chrome/browser/resources/pdf/viewport.js
|
| diff --git a/chrome/browser/resources/pdf/viewport.js b/chrome/browser/resources/pdf/viewport.js
|
| index 18fb6c2ad403f4c8a49956f43a37bc776eaece6e..80a5a06ac646bb69e61dcda69a07bfb53a2ea208 100644
|
| --- a/chrome/browser/resources/pdf/viewport.js
|
| +++ b/chrome/browser/resources/pdf/viewport.js
|
| @@ -15,6 +15,36 @@ function getIntersectionHeight(rect1, rect2) {
|
| }
|
|
|
| /**
|
| + * 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 within the limits.
|
| + */
|
| +function clampScale(scale) {
|
| + return Math.min(5, Math.max(0.25, scale));
|
| +}
|
| +
|
| +/**
|
| + * Computes vector between two points.
|
| + * @param {!Object} p1 The first point.
|
| + * @param {!Object} p2 The second point.
|
| + * @return {!Object} The vector.
|
| + */
|
| +function vectorDelta(p1, p2) {
|
| + return {
|
| + x: p2.x - p1.x,
|
| + y: p2.y - p1.y
|
| + };
|
| +}
|
| +
|
| +function frameToPluginCoordinate(coordinateInFrame) {
|
| + var container = $('plugin');
|
| + return {
|
| + x: coordinateInFrame.x - container.getBoundingClientRect().left,
|
| + y: coordinateInFrame.y - container.getBoundingClientRect().top
|
| + };
|
| +}
|
| +
|
| +/**
|
| * Create a new viewport.
|
| * @constructor
|
| * @param {Window} window the window
|
| @@ -49,6 +79,11 @@ function Viewport(window,
|
| this.fittingType_ = Viewport.FittingType.NONE;
|
| this.defaultZoom_ = defaultZoom;
|
| this.topToolbarHeight_ = topToolbarHeight;
|
| + this.prevScale_ = 1;
|
| + this.pinchPhase_ = Viewport.PinchPhase.PINCH_NONE;
|
| + this.pinchPanVector_ = null;
|
| + this.pinchCenter_ = null;
|
| + this.firstPinchCenterInFrame_ = null;
|
|
|
| window.addEventListener('scroll', this.updateViewport_.bind(this));
|
| window.addEventListener('resize', this.resize_.bind(this));
|
| @@ -65,6 +100,19 @@ Viewport.FittingType = {
|
| };
|
|
|
| /**
|
| + * Enumeration of pinch states.
|
| + * This should match PinchPhase enum in pdf/out_of_process_instance.h
|
| + * @enum {number}
|
| + */
|
| +Viewport.PinchPhase = {
|
| + PINCH_NONE: 0,
|
| + PINCH_START: 1,
|
| + PINCH_UPDATE_ZOOM_OUT: 2,
|
| + PINCH_UPDATE_ZOOM_IN: 3,
|
| + PINCH_END: 4
|
| +};
|
| +
|
| +/**
|
| * The increment to scroll a page by in pixels when up/down/left/right arrow
|
| * keys are pressed. Usually we just let the browser handle scrolling on the
|
| * window when these keys are pressed but in certain cases we need to simulate
|
| @@ -227,6 +275,29 @@ Viewport.prototype = {
|
| },
|
|
|
| /**
|
| + * @type {Viewport.PinchPhase} The phase of the current pinch gesture for
|
| + * the viewport.
|
| + */
|
| + get pinchPhase() {
|
| + return this.pinchPhase_;
|
| + },
|
| +
|
| + /**
|
| + * @type {Object} The panning caused by the current pinch gesture (as
|
| + * the deltas of the x and y coordinates).
|
| + */
|
| + get pinchPanVector() {
|
| + return this.pinchPanVector_;
|
| + },
|
| +
|
| + /**
|
| + * @type {Object} The coordinates of the center of the current pinch gesture.
|
| + */
|
| + get pinchCenter() {
|
| + return this.pinchCenter_;
|
| + },
|
| +
|
| + /**
|
| * @private
|
| * Used to wrap a function that might perform zooming on the viewport. This is
|
| * required so that we can notify the plugin that zooming is in progress
|
| @@ -266,6 +337,54 @@ Viewport.prototype = {
|
| },
|
|
|
| /**
|
| + * @private
|
| + * Sets the zoom of the viewport.
|
| + * Same as setZoomInternal_ 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) {
|
| + assert(this.allowedToChangeZoom_,
|
| + 'Called Viewport.setPinchZoomInternal_ without calling ' +
|
| + 'Viewport.mightZoom_.');
|
| + this.zoom_ = 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
|
| + * Converts a point from frame to content coordinates.
|
| + * @param {!Object} framePoint The frame coordinates.
|
| + * @return {!Object} The content coordinates.
|
| + */
|
| + frameToContent: function(framePoint) {
|
| + // TODO(mcnee) Add a helper Point class to avoid duplicating operations
|
| + // on plain {x,y} objects.
|
| + 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.
|
| */
|
| @@ -499,6 +618,79 @@ Viewport.prototype = {
|
| },
|
|
|
| /**
|
| + * Pinch zoom event handler.
|
| + * @param {!Object} e The pinch event.
|
| + */
|
| + pinchZoom: function(e) {
|
| + this.mightZoom_(function() {
|
| + this.pinchPhase_ = e.direction == 'out' ?
|
| + Viewport.PinchPhase.PINCH_UPDATE_ZOOM_OUT :
|
| + Viewport.PinchPhase.PINCH_UPDATE_ZOOM_IN;
|
| +
|
| + var scaleDelta = e.startScaleRatio / this.prevScale_;
|
| + this.pinchPanVector_ =
|
| + vectorDelta(e.center, this.firstPinchCenterInFrame_);
|
| +
|
| + var needsScrollbars = this.documentNeedsScrollbars_(
|
| + clampScale(this.zoom_ * scaleDelta));
|
| +
|
| + this.pinchCenter_ = e.center;
|
| +
|
| + // If there's no horizontal scrolling, keep the content centered so the
|
| + // user can't zoom in on the non-content area.
|
| + // TODO(mcnee) Investigate other ways of scaling when we don't have
|
| + // horizontal scrolling. We want to keep the document centered,
|
| + // but this causes a potentially awkward transition when we start
|
| + // using the gesture center.
|
| + if (!needsScrollbars.horizontal) {
|
| + this.pinchCenter_ = {
|
| + x: this.window_.innerWidth / 2,
|
| + y: this.window_.innerHeight / 2
|
| + };
|
| + } else if (this.keepContentCentered_) {
|
| + this.oldCenterInContent =
|
| + this.frameToContent(frameToPluginCoordinate(e.center));
|
| + this.keepContentCentered_ = false;
|
| + }
|
| +
|
| + this.setPinchZoomInternal_(
|
| + scaleDelta, frameToPluginCoordinate(e.center));
|
| + this.updateViewport_();
|
| + this.prevScale_ = e.startScaleRatio;
|
| + }.bind(this));
|
| + },
|
| +
|
| + pinchZoomStart: function(e) {
|
| + this.pinchPhase_ = Viewport.PinchPhase.PINCH_START;
|
| + this.prevScale_ = 1;
|
| + this.oldCenterInContent =
|
| + this.frameToContent(frameToPluginCoordinate(e.center));
|
| +
|
| + var needsScrollbars = this.documentNeedsScrollbars_(this.zoom_);
|
| + this.keepContentCentered_ = !needsScrollbars.horizontal;
|
| + // We keep track of begining of the pinch.
|
| + // By doing so we will be able to compute the pan distance.
|
| + this.firstPinchCenterInFrame_ = e.center;
|
| + },
|
| +
|
| + pinchZoomEnd: function(e) {
|
| + this.mightZoom_(function() {
|
| + this.pinchPhase_ = Viewport.PinchPhase.PINCH_END;
|
| + var scaleDelta = e.startScaleRatio / this.prevScale_;
|
| + this.pinchCenter_ = e.center;
|
| +
|
| + this.setPinchZoomInternal_(
|
| + scaleDelta, frameToPluginCoordinate(e.center));
|
| + this.updateViewport_();
|
| + }.bind(this));
|
| +
|
| + this.pinchPhase_ = Viewport.PinchPhase.PINCH_NONE;
|
| + this.pinchPanVector_ = null;
|
| + this.pinchCenter_ = null;
|
| + this.firstPinchCenterInFrame_ = null;
|
| + },
|
| +
|
| + /**
|
| * Go to the given page index.
|
| * @param {number} page the index of the page to go to. zero-based.
|
| */
|
|
|