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

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

Issue 347763007: Improve scrolling performance in OOP PDF (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « chrome/browser/resources/pdf/pdf.js ('k') | chrome/test/data/pdf/basic_plugin_test.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 area of the intersection of two rectangles. 6 * Returns the area 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 area of the intersection of the rects 9 * @return {number} the area of the intersection of the rects
10 */ 10 */
11 function getIntersectionArea(rect1, rect2) { 11 function getIntersectionArea(rect1, rect2) {
12 var xOverlap = Math.max(0, 12 var xOverlap = Math.max(0,
13 Math.min(rect1.x + rect1.width, rect2.x + rect2.width) - 13 Math.min(rect1.x + rect1.width, rect2.x + rect2.width) -
14 Math.max(rect1.x, rect2.x)); 14 Math.max(rect1.x, rect2.x));
15 var yOverlap = Math.max(0, 15 var yOverlap = Math.max(0,
16 Math.min(rect1.y + rect1.height, rect2.y + rect2.height) - 16 Math.min(rect1.y + rect1.height, rect2.y + rect2.height) -
17 Math.max(rect1.y, rect2.y)); 17 Math.max(rect1.y, rect2.y));
18 return xOverlap * yOverlap; 18 return xOverlap * yOverlap;
19 } 19 }
20 20
21 /** 21 /**
22 * Create a new viewport. 22 * Create a new viewport.
23 * @param {Window} window the window 23 * @param {Window} window the window
24 * @param {Object} sizer is the element which represents the size of the 24 * @param {Object} sizer is the element which represents the size of the
25 * document in the viewport 25 * document in the viewport
26 * @param {Function} viewportChangedCallback is run when the viewport changes 26 * @param {Function} viewportChangedCallback is run when the viewport changes
27 * @param {Function} beforeZoomCallback is run before a change in zoom
28 * @param {Function} afterZoomCallback is run after a change in zoom
27 * @param {number} scrollbarWidth the width of scrollbars on the page 29 * @param {number} scrollbarWidth the width of scrollbars on the page
28 */ 30 */
29 function Viewport(window, 31 function Viewport(window,
30 sizer, 32 sizer,
31 viewportChangedCallback, 33 viewportChangedCallback,
34 beforeZoomCallback,
35 afterZoomCallback,
32 scrollbarWidth) { 36 scrollbarWidth) {
33 this.window_ = window; 37 this.window_ = window;
34 this.sizer_ = sizer; 38 this.sizer_ = sizer;
35 this.viewportChangedCallback_ = viewportChangedCallback; 39 this.viewportChangedCallback_ = viewportChangedCallback;
40 this.beforeZoomCallback_ = beforeZoomCallback;
41 this.afterZoomCallback_ = afterZoomCallback;
42 this.allowedToChangeZoom_ = false;
36 this.zoom_ = 1; 43 this.zoom_ = 1;
37 this.documentDimensions_ = null; 44 this.documentDimensions_ = null;
38 this.pageDimensions_ = []; 45 this.pageDimensions_ = [];
39 this.scrollbarWidth_ = scrollbarWidth; 46 this.scrollbarWidth_ = scrollbarWidth;
40 this.fittingType_ = Viewport.FittingType.NONE; 47 this.fittingType_ = Viewport.FittingType.NONE;
41 48
42 window.addEventListener('scroll', this.updateViewport_.bind(this)); 49 window.addEventListener('scroll', this.updateViewport_.bind(this));
43 window.addEventListener('resize', this.resize_.bind(this)); 50 window.addEventListener('resize', this.resize_.bind(this));
44 } 51 }
45 52
(...skipping 30 matching lines...) Expand all
76 Viewport.prototype = { 83 Viewport.prototype = {
77 /** 84 /**
78 * @private 85 * @private
79 * Returns true if the document needs scrollbars at the given zoom level. 86 * Returns true if the document needs scrollbars at the given zoom level.
80 * @param {number} zoom compute whether scrollbars are needed at this zoom 87 * @param {number} zoom compute whether scrollbars are needed at this zoom
81 * @return {Object} with 'horizontal' and 'vertical' keys which map to bool 88 * @return {Object} with 'horizontal' and 'vertical' keys which map to bool
82 * values indicating if the horizontal and vertical scrollbars are needed 89 * values indicating if the horizontal and vertical scrollbars are needed
83 * respectively. 90 * respectively.
84 */ 91 */
85 documentNeedsScrollbars_: function(zoom) { 92 documentNeedsScrollbars_: function(zoom) {
93 if (!this.documentDimensions_) {
94 return {
95 horizontal: false,
96 vertical: false
97 };
98 }
86 var documentWidth = this.documentDimensions_.width * zoom; 99 var documentWidth = this.documentDimensions_.width * zoom;
87 var documentHeight = this.documentDimensions_.height * zoom; 100 var documentHeight = this.documentDimensions_.height * zoom;
88 return { 101 return {
89 horizontal: documentWidth > this.window_.innerWidth, 102 horizontal: documentWidth > this.window_.innerWidth,
90 vertical: documentHeight > this.window_.innerHeight 103 vertical: documentHeight > this.window_.innerHeight
91 }; 104 };
92 }, 105 },
93 106
94 /** 107 /**
95 * Returns true if the document needs scrollbars at the current zoom level. 108 * Returns true if the document needs scrollbars at the current zoom level.
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 181
169 /** 182 /**
170 * @type {number} the zoom level of the viewport. 183 * @type {number} the zoom level of the viewport.
171 */ 184 */
172 get zoom() { 185 get zoom() {
173 return this.zoom_; 186 return this.zoom_;
174 }, 187 },
175 188
176 /** 189 /**
177 * @private 190 * @private
191 * Used to wrap a function that might perform zooming on the viewport. This is
192 * required so that we can notify the plugin that zooming is in progress
193 * so that while zooming is taking place it can stop reacting to scroll events
194 * from the viewport. This is to avoid flickering.
195 */
196 mightZoom_: function(f) {
197 this.beforeZoomCallback_();
198 this.allowedToChangeZoom_ = true;
199 f();
200 this.allowedToChangeZoom_ = false;
201 this.afterZoomCallback_();
202 },
203
204 /**
205 * @private
178 * Sets the zoom of the viewport. 206 * Sets the zoom of the viewport.
179 * @param {number} newZoom the zoom level to zoom to. 207 * @param {number} newZoom the zoom level to zoom to.
180 */ 208 */
181 setZoom_: function(newZoom) { 209 setZoom_: function(newZoom) {
210 if (!this.allowedToChangeZoom_)
211 throw 'Called Viewport.setZoom_ without calling Viewport.mightZoom_.';
182 var oldZoom = this.zoom_; 212 var oldZoom = this.zoom_;
183 this.zoom_ = newZoom; 213 this.zoom_ = newZoom;
184 // Record the scroll position (relative to the middle of the window). 214 // Record the scroll position (relative to the middle of the window).
185 var currentScrollPos = [ 215 var currentScrollPos = [
186 (this.window_.pageXOffset + this.window_.innerWidth / 2) / oldZoom, 216 (this.window_.pageXOffset + this.window_.innerWidth / 2) / oldZoom,
187 (this.window_.pageYOffset + this.window_.innerHeight / 2) / oldZoom 217 (this.window_.pageYOffset + this.window_.innerHeight / 2) / oldZoom
188 ]; 218 ];
189 this.contentSizeChanged_(); 219 this.contentSizeChanged_();
190 // Scroll to the scaled scroll position. 220 // Scroll to the scaled scroll position.
191 this.window_.scrollTo( 221 this.window_.scrollTo(
192 currentScrollPos[0] * newZoom - this.window_.innerWidth / 2, 222 currentScrollPos[0] * newZoom - this.window_.innerWidth / 2,
193 currentScrollPos[1] * newZoom - this.window_.innerHeight / 2); 223 currentScrollPos[1] * newZoom - this.window_.innerHeight / 2);
194 }, 224 },
195 225
196 /** 226 /**
227 * @private
228 * Sets the zoom for testing purposes.
229 */
230 setZoomForTest_: function(newZoom) {
231 this.mightZoom_(function() {
232 this.setZoom_(newZoom);
233 }.bind(this));
234 },
235
236 /**
197 * @type {number} the width of scrollbars in the viewport in pixels. 237 * @type {number} the width of scrollbars in the viewport in pixels.
198 */ 238 */
199 get scrollbarWidth() { 239 get scrollbarWidth() {
200 return this.scrollbarWidth_; 240 return this.scrollbarWidth_;
201 }, 241 },
202 242
203 /** 243 /**
204 * @type {Viewport.FittingType} the fitting type the viewport is currently in. 244 * @type {Viewport.FittingType} the fitting type the viewport is currently in.
205 */ 245 */
206 get fittingType() { 246 get fittingType() {
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 var zoomHeight = windowWithScrollbars.height / pageDimensions.height; 366 var zoomHeight = windowWithScrollbars.height / pageDimensions.height;
327 zoom = Math.min(zoomWidth, zoomHeight); 367 zoom = Math.min(zoomWidth, zoomHeight);
328 } 368 }
329 return zoom; 369 return zoom;
330 }, 370 },
331 371
332 /** 372 /**
333 * Zoom the viewport so that the page-width consumes the entire viewport. 373 * Zoom the viewport so that the page-width consumes the entire viewport.
334 */ 374 */
335 fitToWidth: function() { 375 fitToWidth: function() {
336 this.fittingType_ = Viewport.FittingType.FIT_TO_WIDTH; 376 this.mightZoom_(function() {
337 if (!this.documentDimensions_) 377 this.fittingType_ = Viewport.FittingType.FIT_TO_WIDTH;
338 return; 378 if (!this.documentDimensions_)
339 // Track the last y-position so we stay at the same position after zooming. 379 return;
340 var oldY = this.window_.pageYOffset / this.zoom_; 380 // Track the last y-position to stay at the same position after zooming.
341 // When computing fit-to-width, the maximum width of a page in the document 381 var oldY = this.window_.pageYOffset / this.zoom_;
342 // is used, which is equal to the size of the document width. 382 // When computing fit-to-width, the maximum width of a page in the
343 this.setZoom_(this.computeFittingZoom_(this.documentDimensions_, true)); 383 // document is used, which is equal to the size of the document width.
344 var page = this.getMostVisiblePage(); 384 this.setZoom_(this.computeFittingZoom_(this.documentDimensions_, true));
345 this.window_.scrollTo(0, oldY * this.zoom_); 385 var page = this.getMostVisiblePage();
346 this.updateViewport_(); 386 this.window_.scrollTo(0, oldY * this.zoom_);
387 this.updateViewport_();
388 }.bind(this));
347 }, 389 },
348 390
349 /** 391 /**
350 * Zoom the viewport so that a page consumes the entire viewport. Also scrolls 392 * Zoom the viewport so that a page consumes the entire viewport. Also scrolls
351 * to the top of the most visible page. 393 * to the top of the most visible page.
352 */ 394 */
353 fitToPage: function() { 395 fitToPage: function() {
354 this.fittingType_ = Viewport.FittingType.FIT_TO_PAGE; 396 this.mightZoom_(function() {
355 if (!this.documentDimensions_) 397 this.fittingType_ = Viewport.FittingType.FIT_TO_PAGE;
356 return; 398 if (!this.documentDimensions_)
357 var page = this.getMostVisiblePage(); 399 return;
358 this.setZoom_(this.computeFittingZoom_(this.pageDimensions_[page], false)); 400 var page = this.getMostVisiblePage();
359 // Center the document in the page by scrolling by the amount of empty 401 this.setZoom_(this.computeFittingZoom_(
360 // space to the left of the document. 402 this.pageDimensions_[page], false));
361 var xOffset = 403 // Center the document in the page by scrolling by the amount of empty
362 (this.documentDimensions_.width - this.pageDimensions_[page].width) * 404 // space to the left of the document.
363 this.zoom_ / 2; 405 var xOffset =
364 this.window_.scrollTo(xOffset, 406 (this.documentDimensions_.width - this.pageDimensions_[page].width) *
365 this.pageDimensions_[page].y * this.zoom_); 407 this.zoom_ / 2;
366 this.updateViewport_(); 408 this.window_.scrollTo(xOffset,
409 this.pageDimensions_[page].y * this.zoom_);
410 this.updateViewport_();
411 }.bind(this));
367 }, 412 },
368 413
369 /** 414 /**
370 * Zoom out to the next predefined zoom level. 415 * Zoom out to the next predefined zoom level.
371 */ 416 */
372 zoomOut: function() { 417 zoomOut: function() {
373 this.fittingType_ = Viewport.FittingType.NONE; 418 this.mightZoom_(function() {
374 var nextZoom = Viewport.ZOOM_FACTORS[0]; 419 this.fittingType_ = Viewport.FittingType.NONE;
375 for (var i = 0; i < Viewport.ZOOM_FACTORS.length; i++) { 420 var nextZoom = Viewport.ZOOM_FACTORS[0];
376 if (Viewport.ZOOM_FACTORS[i] < this.zoom_) 421 for (var i = 0; i < Viewport.ZOOM_FACTORS.length; i++) {
377 nextZoom = Viewport.ZOOM_FACTORS[i]; 422 if (Viewport.ZOOM_FACTORS[i] < this.zoom_)
378 } 423 nextZoom = Viewport.ZOOM_FACTORS[i];
379 this.setZoom_(nextZoom); 424 }
380 this.updateViewport_(); 425 this.setZoom_(nextZoom);
426 this.updateViewport_();
427 }.bind(this));
381 }, 428 },
382 429
383 /** 430 /**
384 * Zoom in to the next predefined zoom level. 431 * Zoom in to the next predefined zoom level.
385 */ 432 */
386 zoomIn: function() { 433 zoomIn: function() {
387 this.fittingType_ = Viewport.FittingType.NONE; 434 this.mightZoom_(function() {
388 var nextZoom = Viewport.ZOOM_FACTORS[Viewport.ZOOM_FACTORS.length - 1]; 435 this.fittingType_ = Viewport.FittingType.NONE;
389 for (var i = Viewport.ZOOM_FACTORS.length - 1; i >= 0; i--) { 436 var nextZoom = Viewport.ZOOM_FACTORS[Viewport.ZOOM_FACTORS.length - 1];
390 if (Viewport.ZOOM_FACTORS[i] > this.zoom_) 437 for (var i = Viewport.ZOOM_FACTORS.length - 1; i >= 0; i--) {
391 nextZoom = Viewport.ZOOM_FACTORS[i]; 438 if (Viewport.ZOOM_FACTORS[i] > this.zoom_)
392 } 439 nextZoom = Viewport.ZOOM_FACTORS[i];
393 this.setZoom_(nextZoom); 440 }
394 this.updateViewport_(); 441 this.setZoom_(nextZoom);
442 this.updateViewport_();
443 }.bind(this));
395 }, 444 },
396 445
397 /** 446 /**
398 * Go to the given page index. 447 * Go to the given page index.
399 * @param {number} page the index of the page to go to. 448 * @param {number} page the index of the page to go to.
400 */ 449 */
401 goToPage: function(page) { 450 goToPage: function(page) {
402 if (this.pageDimensions_.length == 0) 451 this.mightZoom_(function() {
403 return; 452 if (this.pageDimensions_.length == 0)
404 if (page < 0) 453 return;
405 page = 0; 454 if (page < 0)
406 if (page >= this.pageDimensions_.length) 455 page = 0;
407 page = this.pageDimensions_.length - 1; 456 if (page >= this.pageDimensions_.length)
408 var dimensions = this.pageDimensions_[page]; 457 page = this.pageDimensions_.length - 1;
409 this.window_.scrollTo(dimensions.x * this.zoom_, dimensions.y * this.zoom_); 458 var dimensions = this.pageDimensions_[page];
459 this.window_.scrollTo(dimensions.x * this.zoom_,
460 dimensions.y * this.zoom_);
461 this.updateViewport_();
462 }.bind(this));
410 }, 463 },
411 464
412 /** 465 /**
413 * Set the dimensions of the document. 466 * Set the dimensions of the document.
414 * @param {Object} documentDimensions the dimensions of the document 467 * @param {Object} documentDimensions the dimensions of the document
415 */ 468 */
416 setDocumentDimensions: function(documentDimensions) { 469 setDocumentDimensions: function(documentDimensions) {
417 var initialDimensions = !this.documentDimensions_; 470 this.mightZoom_(function() {
418 this.documentDimensions_ = documentDimensions; 471 var initialDimensions = !this.documentDimensions_;
419 this.pageDimensions_ = this.documentDimensions_.pageDimensions; 472 this.documentDimensions_ = documentDimensions;
420 if (initialDimensions) { 473 this.pageDimensions_ = this.documentDimensions_.pageDimensions;
421 this.setZoom_(this.computeFittingZoom_(this.documentDimensions_, true)); 474 if (initialDimensions) {
422 if (this.zoom_ > 1) 475 this.setZoom_(this.computeFittingZoom_(this.documentDimensions_, true));
423 this.setZoom_(1); 476 if (this.zoom_ > 1)
424 this.window_.scrollTo(0, 0); 477 this.setZoom_(1);
425 } 478 this.window_.scrollTo(0, 0);
426 this.contentSizeChanged_(); 479 }
427 this.resize_(); 480 this.contentSizeChanged_();
481 this.resize_();
482 }.bind(this));
428 }, 483 },
429 484
430 /** 485 /**
431 * Get the coordinates of the page contents (excluding the page shadow) 486 * Get the coordinates of the page contents (excluding the page shadow)
432 * relative to the screen. 487 * relative to the screen.
433 * @param {number} page the index of the page to get the rect for. 488 * @param {number} page the index of the page to get the rect for.
434 * @return {Object} a rect representing the page in screen coordinates. 489 * @return {Object} a rect representing the page in screen coordinates.
435 */ 490 */
436 getPageScreenRect: function(page) { 491 getPageScreenRect: function(page) {
492 if (!this.documentDimensions_) {
493 return {
494 x: 0,
495 y: 0,
496 width: 0,
497 height: 0
498 };
499 }
437 if (page >= this.pageDimensions_.length) 500 if (page >= this.pageDimensions_.length)
438 page = this.pageDimensions_.length - 1; 501 page = this.pageDimensions_.length - 1;
439 502
440 var pageDimensions = this.pageDimensions_[page]; 503 var pageDimensions = this.pageDimensions_[page];
441 504
442 // Compute the page dimensions minus the shadows. 505 // Compute the page dimensions minus the shadows.
443 var insetDimensions = { 506 var insetDimensions = {
444 x: pageDimensions.x + Viewport.PAGE_SHADOW.left, 507 x: pageDimensions.x + Viewport.PAGE_SHADOW.left,
445 y: pageDimensions.y + Viewport.PAGE_SHADOW.top, 508 y: pageDimensions.y + Viewport.PAGE_SHADOW.top,
446 width: pageDimensions.width - Viewport.PAGE_SHADOW.left - 509 width: pageDimensions.width - Viewport.PAGE_SHADOW.left -
(...skipping 14 matching lines...) Expand all
461 spaceOnLeft = Math.max(spaceOnLeft, 0); 524 spaceOnLeft = Math.max(spaceOnLeft, 0);
462 525
463 return { 526 return {
464 x: x * this.zoom_ + spaceOnLeft - this.window_.pageXOffset, 527 x: x * this.zoom_ + spaceOnLeft - this.window_.pageXOffset,
465 y: insetDimensions.y * this.zoom_ - this.window_.pageYOffset, 528 y: insetDimensions.y * this.zoom_ - this.window_.pageYOffset,
466 width: insetDimensions.width * this.zoom_, 529 width: insetDimensions.width * this.zoom_,
467 height: insetDimensions.height * this.zoom_ 530 height: insetDimensions.height * this.zoom_
468 }; 531 };
469 } 532 }
470 }; 533 };
OLDNEW
« no previous file with comments | « chrome/browser/resources/pdf/pdf.js ('k') | chrome/test/data/pdf/basic_plugin_test.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698