Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(321)

Side by Side Diff: chrome/browser/resources/pdf/viewport.js

Issue 1901903002: Improved Pinch-Zoom for PDF (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@pepper_add_set_layer_transform
Patch Set: Clean code part 2 Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * Returns the height of the intersection of two rectangles. 6 * Returns the height of the intersection of two rectangles.
7 * @param {Object} rect1 the first rect 7 * @param {Object} rect1 the first rect
8 * @param {Object} rect2 the second rect 8 * @param {Object} rect2 the second rect
9 * @return {number} the height of the intersection of the rects 9 * @return {number} the height of the intersection of the rects
10 */ 10 */
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 this.beforeZoomCallback_ = beforeZoomCallback; 42 this.beforeZoomCallback_ = beforeZoomCallback;
43 this.afterZoomCallback_ = afterZoomCallback; 43 this.afterZoomCallback_ = afterZoomCallback;
44 this.allowedToChangeZoom_ = false; 44 this.allowedToChangeZoom_ = false;
45 this.zoom_ = 1; 45 this.zoom_ = 1;
46 this.documentDimensions_ = null; 46 this.documentDimensions_ = null;
47 this.pageDimensions_ = []; 47 this.pageDimensions_ = [];
48 this.scrollbarWidth_ = scrollbarWidth; 48 this.scrollbarWidth_ = scrollbarWidth;
49 this.fittingType_ = Viewport.FittingType.NONE; 49 this.fittingType_ = Viewport.FittingType.NONE;
50 this.defaultZoom_ = defaultZoom; 50 this.defaultZoom_ = defaultZoom;
51 this.topToolbarHeight_ = topToolbarHeight; 51 this.topToolbarHeight_ = topToolbarHeight;
52 this.prevScale = 1;
53 this.doRender_ = 1;
52 54
53 window.addEventListener('scroll', this.updateViewport_.bind(this)); 55 window.addEventListener('scroll', this.updateViewport_.bind(this));
54 window.addEventListener('resize', this.resize_.bind(this)); 56 window.addEventListener('resize', this.resize_.bind(this));
55 } 57 }
56 58
57 /** 59 /**
58 * Enumeration of page fitting types. 60 * Enumeration of page fitting types.
59 * @enum {string} 61 * @enum {string}
60 */ 62 */
61 Viewport.FittingType = { 63 Viewport.FittingType = {
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 this.sizer_.style.width = zoomedDimensions.width + 'px'; 165 this.sizer_.style.width = zoomedDimensions.width + 'px';
164 this.sizer_.style.height = zoomedDimensions.height + 166 this.sizer_.style.height = zoomedDimensions.height +
165 this.topToolbarHeight_ + 'px'; 167 this.topToolbarHeight_ + 'px';
166 } 168 }
167 }, 169 },
168 170
169 /** 171 /**
170 * @private 172 * @private
171 * Called when the viewport should be updated. 173 * Called when the viewport should be updated.
172 */ 174 */
173 updateViewport_: function() { 175 updateViewport_: function() { this.viewportChangedCallback_(); },
174 this.viewportChangedCallback_();
175 },
176 176
177 /** 177 /**
178 * @private 178 * @private
179 * Called when the viewport size changes. 179 * Called when the viewport size changes.
180 */ 180 */
181 resize_: function() { 181 resize_: function() {
182 if (this.fittingType_ == Viewport.FittingType.FIT_TO_PAGE) 182 if (this.fittingType_ == Viewport.FittingType.FIT_TO_PAGE)
183 this.fitToPageInternal_(false); 183 this.fitToPageInternal_(false);
184 else if (this.fittingType_ == Viewport.FittingType.FIT_TO_WIDTH) 184 else if (this.fittingType_ == Viewport.FittingType.FIT_TO_WIDTH)
185 this.fitToWidth(); 185 this.fitToWidth();
(...skipping 28 matching lines...) Expand all
214 var scrollbarHeight = needsScrollbars.horizontal ? this.scrollbarWidth_ : 0; 214 var scrollbarHeight = needsScrollbars.horizontal ? this.scrollbarWidth_ : 0;
215 return { 215 return {
216 width: this.window_.innerWidth - scrollbarWidth, 216 width: this.window_.innerWidth - scrollbarWidth,
217 height: this.window_.innerHeight - scrollbarHeight 217 height: this.window_.innerHeight - scrollbarHeight
218 }; 218 };
219 }, 219 },
220 220
221 /** 221 /**
222 * @type {number} the zoom level of the viewport. 222 * @type {number} the zoom level of the viewport.
223 */ 223 */
224 get zoom() { 224 get zoom() { return this.zoom_; },
225 return this.zoom_;
226 },
227 225
228 /** 226 /**
229 * @private 227 * @private
230 * Used to wrap a function that might perform zooming on the viewport. This is 228 * Used to wrap a function that might perform zooming on the viewport. This is
231 * required so that we can notify the plugin that zooming is in progress 229 * required so that we can notify the plugin that zooming is in progress
232 * so that while zooming is taking place it can stop reacting to scroll events 230 * so that while zooming is taking place it can stop reacting to scroll events
233 * from the viewport. This is to avoid flickering. 231 * from the viewport. This is to avoid flickering.
234 */ 232 */
235 mightZoom_: function(f) { 233 mightZoom_: function(f) {
236 this.beforeZoomCallback_(); 234 this.beforeZoomCallback_();
237 this.allowedToChangeZoom_ = true; 235 this.allowedToChangeZoom_ = true;
238 f(); 236 f();
237 var needsScrollbars = this.documentNeedsScrollbars_(this.zoom_);
238 if (!needsScrollbars.horizontal) {
239 this.pinchCenter_ = {
wjmaclean 2016/04/21 14:11:01 Perhaps add a TODO here: at present the transition
bokan 2016/04/21 15:27:04 This is the case where we don't have horizontal sc
alessandroa 2016/04/21 20:39:40 I've explained today to David how by having the po
240 x: this.window_.innerWidth / 2,
241 y: this.window_.innerHeight / 2
242 };
243 }
239 this.allowedToChangeZoom_ = false; 244 this.allowedToChangeZoom_ = false;
240 this.afterZoomCallback_(); 245 this.afterZoomCallback_();
241 }, 246 },
242 247
243 /** 248 /**
244 * @private 249 * @private
245 * Sets the zoom of the viewport. 250 * Sets the zoom of the viewport.
246 * @param {number} newZoom the zoom level to zoom to. 251 * @param {number} newZoom the zoom level to zoom to.
247 */ 252 */
248 setZoomInternal_: function(newZoom) { 253 setZoomInternal_: function(newZoom) {
249 if (!this.allowedToChangeZoom_) { 254 if (!this.allowedToChangeZoom_) {
250 throw 'Called Viewport.setZoomInternal_ without calling ' + 255 throw 'Called Viewport.setZoomInternal_ without calling ' +
251 'Viewport.mightZoom_.'; 256 'Viewport.mightZoom_.';
252 } 257 }
253 // Record the scroll position (relative to the top-left of the window). 258 // Record the scroll position (relative to the top-left of the window).
254 var currentScrollPos = { 259 var currentScrollPos = {
255 x: this.position.x / this.zoom_, 260 x: this.position.x / this.zoom_,
256 y: this.position.y / this.zoom_ 261 y: this.position.y / this.zoom_
257 }; 262 };
258 this.zoom_ = newZoom; 263 this.zoom_ = newZoom;
259 this.contentSizeChanged_(); 264 this.contentSizeChanged_();
260 // Scroll to the scaled scroll position. 265 // Scroll to the scaled scroll position.
261 this.position = { 266 this.position = {
262 x: currentScrollPos.x * newZoom, 267 x: currentScrollPos.x * newZoom,
263 y: currentScrollPos.y * newZoom 268 y: currentScrollPos.y * newZoom
264 }; 269 };
265 }, 270 },
266 271
267 /** 272 /**
273 * @private
274 * Sets the cusotm zoom of the viewport.
bokan 2016/04/21 02:24:01 "cusotm" -> "custom"
alessandroa 2016/04/21 20:39:39 Acknowledged.
275 * Same function as below but for pinch zoom we have some more operations.
276 * @param {number} scaleDelta the zoom delta.
277 * @param {Object} center the pinch center
bokan 2016/04/21 18:20:17 Describe the coordinates of the center value. i.e.
alessandroa 2016/04/21 20:39:39 Done.
278 */
279 setPinchZoomInternal_: function(scaleDelta, center) {
280 if (!this.allowedToChangeZoom_) {
281 throw 'Called Viewport.setZoomInternal_ without calling ' +
282 'Viewport.mightZoom_.';
283 }
284 this.zoom_ = this.clampScale(this.zoom_ * scaleDelta);
285
286 var newCenterInContent = this.frameToContent(center, this.zoom_);
287 var delta = {
288 x: (newCenterInContent.x - this.oldCenterInContent.x),
289 y: (newCenterInContent.y - this.oldCenterInContent.y)
290 };
291
292 // Record the scroll position (relative to the pinch center).
293 var currentScrollPos = {
294 x: this.position.x - delta.x * this.zoom_,
295 y: this.position.y - delta.y * this.zoom_
296 };
297
298 this.contentSizeChanged_();
299 // Scroll to the scaled scroll position.
300 this.position = {x: currentScrollPos.x, y: currentScrollPos.y};
301 //Update last scale for the current pinch event
302 this.prevScale *= scaleDelta;
bokan 2016/04/21 15:22:06 prevScale is used entirely in the handlers to calc
303 },
304
305 /**
306 * @private
307 * Makes sure that the scale level doesn't get out of the limits.
308 * @param {number} scale the new scale level
309 * @return {number} the scale clamped in the limit
310 */
311 clampScale: function(scale) { return Math.min(5, Math.max(0.25, scale)); },
312
313 /**
314 * @private
315 * Gets the new center in content.
316 * @param {Object} pinch center
317 * @param {Object} zoom level
318 * @return {Objet} the new center in content
319 */
320 frameToContent: function(framePoint, scale) {
321 return {
322 x: (framePoint.x + this.position.x) / scale,
bokan 2016/04/21 15:22:06 scale is always this.zoom_ so remove the argument
alessandroa 2016/04/21 20:39:40 Done.
323 y: (framePoint.y + this.position.y) / scale
bokan 2016/04/21 15:22:06 This doesn't really get you into the content since
bokan 2016/04/21 15:59:02 You can disregard this comment. While strange, the
324 };
325 },
326
327 /**
268 * Sets the zoom to the given zoom level. 328 * Sets the zoom to the given zoom level.
269 * @param {number} newZoom the zoom level to zoom to. 329 * @param {number} newZoom the zoom level to zoom to.
270 */ 330 */
271 setZoom: function(newZoom) { 331 setZoom: function(newZoom) {
272 this.fittingType_ = Viewport.FittingType.NONE; 332 this.fittingType_ = Viewport.FittingType.NONE;
273 newZoom = Math.max(Viewport.ZOOM_FACTOR_RANGE.min, 333 newZoom = Math.max(Viewport.ZOOM_FACTOR_RANGE.min,
274 Math.min(newZoom, Viewport.ZOOM_FACTOR_RANGE.max)); 334 Math.min(newZoom, Viewport.ZOOM_FACTOR_RANGE.max));
275 this.mightZoom_(function() { 335 this.mightZoom_(function() {
276 this.setZoomInternal_(newZoom); 336 this.setZoomInternal_(newZoom);
277 this.updateViewport_(); 337 this.updateViewport_();
278 }.bind(this)); 338 }.bind(this));
279 }, 339 },
280 340
281 /** 341 /**
282 * @type {number} the width of scrollbars in the viewport in pixels. 342 * @type {number} the width of scrollbars in the viewport in pixels.
283 */ 343 */
284 get scrollbarWidth() { 344 get scrollbarWidth() { return this.scrollbarWidth_; },
285 return this.scrollbarWidth_;
286 },
287 345
288 /** 346 /**
289 * @type {Viewport.FittingType} the fitting type the viewport is currently in. 347 * @type {Viewport.FittingType} the fitting type the viewport is currently in.
290 */ 348 */
291 get fittingType() { 349 get fittingType() { return this.fittingType_; },
292 return this.fittingType_;
293 },
294 350
295 /** 351 /**
296 * @private 352 * @private
297 * @param {integer} y the y-coordinate to get the page at. 353 * @param {integer} y the y-coordinate to get the page at.
298 * @return {integer} the index of a page overlapping the given y-coordinate. 354 * @return {integer} the index of a page overlapping the given y-coordinate.
299 */ 355 */
300 getPageAtY_: function(y) { 356 getPageAtY_: function(y) {
301 var min = 0; 357 var min = 0;
302 var max = this.pageDimensions_.length - 1; 358 var max = this.pageDimensions_.length - 1;
303 while (max >= min) { 359 while (max >= min) {
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
449 this.setZoomInternal_(this.computeFittingZoom_(dimensions, false)); 505 this.setZoomInternal_(this.computeFittingZoom_(dimensions, false));
450 if (scrollToTopOfPage) { 506 if (scrollToTopOfPage) {
451 this.position = { 507 this.position = {
452 x: 0, 508 x: 0,
453 y: this.pageDimensions_[page].y * this.zoom_ 509 y: this.pageDimensions_[page].y * this.zoom_
454 }; 510 };
455 } 511 }
456 this.updateViewport_(); 512 this.updateViewport_();
457 }.bind(this)); 513 }.bind(this));
458 }, 514 },
515 /**
516 * @private
517 * Computes vector between two points.
518 * @param {Object} First Point
519 * @param {Object} Second Point
520 * @return {Object} The vector
521 */
522 vectorDistance: function(p1, p2) {
wjmaclean 2016/04/21 14:11:01 Maybe call the vectorDelta instead of invoking the
alessandroa 2016/04/21 20:39:40 Done.
523 var vector = {
524 x: p2.x - p1.x,
525 y: p2.y - p1.y
526 };
527 return vector;
528 },
459 529
460 /** 530 /**
461 * Zoom the viewport so that a page consumes the entire viewport. Also scrolls 531 * Zoom the viewport so that a page consumes the entire viewport. Also scrolls
462 * the viewport to the top of the current page. 532 * the viewport to the top of the current page.
463 */ 533 */
464 fitToPage: function() { 534 fitToPage: function() { this.fitToPageInternal_(true); },
465 this.fitToPageInternal_(true);
466 },
467 535
468 /** 536 /**
469 * Zoom out to the next predefined zoom level. 537 * Zoom out to the next predefined zoom level.
470 */ 538 */
471 zoomOut: function() { 539 zoomOut: function() {
472 this.mightZoom_(function() { 540 this.mightZoom_(function() {
473 this.fittingType_ = Viewport.FittingType.NONE; 541 this.fittingType_ = Viewport.FittingType.NONE;
474 var nextZoom = Viewport.ZOOM_FACTORS[0]; 542 var nextZoom = Viewport.ZOOM_FACTORS[0];
475 for (var i = 0; i < Viewport.ZOOM_FACTORS.length; i++) { 543 for (var i = 0; i < Viewport.ZOOM_FACTORS.length; i++) {
476 if (Viewport.ZOOM_FACTORS[i] < this.zoom_) 544 if (Viewport.ZOOM_FACTORS[i] < this.zoom_)
(...skipping 14 matching lines...) Expand all
491 for (var i = Viewport.ZOOM_FACTORS.length - 1; i >= 0; i--) { 559 for (var i = Viewport.ZOOM_FACTORS.length - 1; i >= 0; i--) {
492 if (Viewport.ZOOM_FACTORS[i] > this.zoom_) 560 if (Viewport.ZOOM_FACTORS[i] > this.zoom_)
493 nextZoom = Viewport.ZOOM_FACTORS[i]; 561 nextZoom = Viewport.ZOOM_FACTORS[i];
494 } 562 }
495 this.setZoomInternal_(nextZoom); 563 this.setZoomInternal_(nextZoom);
496 this.updateViewport_(); 564 this.updateViewport_();
497 }.bind(this)); 565 }.bind(this));
498 }, 566 },
499 567
500 /** 568 /**
569 * Pinch zoom event handler
570 * @param {ev} the pinch event
571 */
572 pinchZoom: function(ev) {
573 this.mightZoom_(function() {
574 if (ev.additionalEvent == 'pinchin')
bokan 2016/04/21 15:22:06 Add a comment explaining why we render only on pin
575 this.doRender_ = 1;
bokan 2016/04/21 02:24:01 Should doRender be true/false rather than a numeri
wjmaclean 2016/04/21 14:11:01 Agreed, seems like doRender should be a Boolean.
alessandroa 2016/04/21 20:39:40 True :)
576 else
577 this.doRender_ = 0;
578
579 var scaleDelta = ev.scale / this.prevScale;
580 this.pinchPanVector_ = this.vectorDistance(ev.center, this.pinch_start_);
581
582 var needsScrollbars = this.documentNeedsScrollbars_(
583 this.clampScale(this.zoom_ * scaleDelta));
584 // We must change the new content in center because now we have fake
wjmaclean 2016/04/21 14:11:01 I'm never comfortable with this term 'fake scrollb
bokan 2016/04/21 15:27:04 Unrelated to this, but fun anecdote anyway, did yo
alessandroa 2016/04/21 20:39:40 That's pretty much my definition of fake ..
585 // scrollbars
bokan 2016/04/21 15:22:06 This comment should elaborate on what we're doing
alessandroa 2016/04/21 20:39:40 Acknowledged.
586 if (this.changeCenter_ && needsScrollbars.horizontal) {
587 this.oldCenterInContent =
588 this.frameToContent(this.containerCenter(ev.center), this.zoom_);
589 this.changeCenter_ = false;
590 }
591
592 this.pinchCenter_ = ev.center;
593 this.setPinchZoomInternal_(scaleDelta, this.containerCenter(ev.center));
594 this.updateViewport_();
595 }.bind(this));
596 },
597
598 pinchZoomStart: function(ev) {
599 //We render the document once before pinch.
600 //By doing so we ensure the image_data_ in the plugin is the correct one
bokan 2016/04/21 02:24:01 Shouldn't doRender_ be = 1 then? Or I'm misunderst
wjmaclean 2016/04/21 14:11:01 I would have thought that we are continuing to use
bokan 2016/04/21 15:27:04 If so, this comment is misleading.
alessandroa 2016/04/21 20:39:40 Yes. We are using the texture from before the pinc
alessandroa 2016/04/21 20:39:40 Old comment. Sorry!
601 this.doRender_ = 0;
bokan 2016/04/21 18:20:17 This isn't inside a mightZoom though so we won't s
alessandroa 2016/04/21 20:39:40 True. I removed the doRender_ as we don't send the
602 this.prevScale = 1;
603 this.oldCenterInContent =
604 this.frameToContent(this.containerCenter(ev.center), this.zoom_);
605
606 var needsScrollbars = this.documentNeedsScrollbars_(this.zoom_);
607 if (!needsScrollbars.horizontal)
608 this.changeCenter_ = true;
609 else
610 this.changeCenter_ = false;
611 // We keep track of begining of the pinch.
612 // By doing so we will be able to compute the pan distance.
613 this.pinch_start_ = ev.center;
bokan 2016/04/21 15:22:06 More descriptive name please. pinch_start_ -> firs
alessandroa 2016/04/21 20:39:40 Acknowledged.
614 },
615
616 pinchZoomEnd: function(ev) {
617 this.mightZoom_(function() {
618 // We want to render the document on pinch end
619 this.doRender_ = 1;
620 var scaleDelta = ev.scale / this.prevScale;
621 this.pinchCenter_ = ev.center;
622
623 this.setPinchZoomInternal_(scaleDelta, this.containerCenter(ev.center));
624 this.updateViewport_();
625 }.bind(this));
626 },
627
628 containerCenter: function(pageCenter) {
bokan 2016/04/21 15:22:06 This function would be better described as "frameT
alessandroa 2016/04/21 20:39:40 Acknowledged.
629 var container = $('plugin');
630 return {
631 x: pageCenter.x - container.getBoundingClientRect().left,
632 y: pageCenter.y - container.getBoundingClientRect().top
633 };
634 },
635
636 /**
501 * Go to the given page index. 637 * Go to the given page index.
502 * @param {number} page the index of the page to go to. zero-based. 638 * @param {number} page the index of the page to go to. zero-based.
503 */ 639 */
504 goToPage: function(page) { 640 goToPage: function(page) {
505 this.mightZoom_(function() { 641 this.mightZoom_(function() {
506 if (this.pageDimensions_.length === 0) 642 if (this.pageDimensions_.length === 0)
507 return; 643 return;
508 if (page < 0) 644 if (page < 0)
509 page = 0; 645 page = 0;
510 if (page >= this.pageDimensions_.length) 646 if (page >= this.pageDimensions_.length)
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 spaceOnLeft = Math.max(spaceOnLeft, 0); 725 spaceOnLeft = Math.max(spaceOnLeft, 0);
590 726
591 return { 727 return {
592 x: x * this.zoom_ + spaceOnLeft - this.window_.pageXOffset, 728 x: x * this.zoom_ + spaceOnLeft - this.window_.pageXOffset,
593 y: insetDimensions.y * this.zoom_ - this.window_.pageYOffset, 729 y: insetDimensions.y * this.zoom_ - this.window_.pageYOffset,
594 width: insetDimensions.width * this.zoom_, 730 width: insetDimensions.width * this.zoom_,
595 height: insetDimensions.height * this.zoom_ 731 height: insetDimensions.height * this.zoom_
596 }; 732 };
597 } 733 }
598 }; 734 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698