Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 'use strict'; | 5 'use strict'; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * Viewport class controls the way the image is displayed (scale, offset etc). | 8 * Viewport class controls the way the image is displayed (scale, offset etc). |
| 9 * @constructor | 9 * @constructor |
| 10 */ | 10 */ |
| 11 function Viewport() { | 11 function Viewport() { |
|
mtomasz
2014/07/10 07:26:52
IIUC, you want to add "zooming by user" and "offse
hirono
2014/07/10 08:16:06
Yes, that is my plan.
| |
| 12 /** | |
| 13 * Size of the full resolution image. | |
| 14 * @type {Rect} | |
| 15 * @private | |
| 16 */ | |
| 12 this.imageBounds_ = new Rect(); | 17 this.imageBounds_ = new Rect(); |
| 18 | |
| 19 /** | |
| 20 * Size of the application window. | |
| 21 * @type {Rect} | |
| 22 * @private | |
| 23 */ | |
| 13 this.screenBounds_ = new Rect(); | 24 this.screenBounds_ = new Rect(); |
| 14 | 25 |
| 26 /** | |
| 27 * Scale from the full resolution image to the screen displayed image. This is | |
| 28 * not zoom operated by users. | |
| 29 */ | |
| 15 this.scale_ = 1; | 30 this.scale_ = 1; |
|
mtomasz
2014/07/10 07:26:52
nit: Is scale_, setScale and getFittingScale used?
hirono
2014/07/10 08:16:06
setScale uses it. getFittingScale actually does no
| |
| 16 this.offsetX_ = 0; | 31 this.offsetX_ = 0; |
|
mtomasz
2014/07/10 07:26:52
nit: Seems that offsetX and offsetY are not used?
hirono
2014/07/10 08:16:06
This is not used so far. But will start to use soo
| |
| 17 this.offsetY_ = 0; | 32 this.offsetY_ = 0; |
| 18 | 33 |
| 19 this.generation_ = 0; | 34 this.generation_ = 0; |
| 20 | 35 |
| 21 this.repaintCallbacks_ = []; | 36 this.repaintCallbacks_ = []; |
| 22 this.update(); | 37 this.update(); |
| 23 } | 38 } |
| 24 | 39 |
| 25 /* | |
| 26 * Viewport modification. | |
| 27 */ | |
| 28 | |
| 29 /** | 40 /** |
| 30 * @param {number} width Image width. | 41 * @param {number} width Image width. |
| 31 * @param {number} height Image height. | 42 * @param {number} height Image height. |
| 32 */ | 43 */ |
| 33 Viewport.prototype.setImageSize = function(width, height) { | 44 Viewport.prototype.setImageSize = function(width, height) { |
| 34 this.imageBounds_ = new Rect(width, height); | 45 this.imageBounds_ = new Rect(width, height); |
| 35 this.invalidateCaches(); | 46 this.invalidateCaches(); |
| 36 }; | 47 }; |
| 37 | 48 |
| 38 /** | 49 /** |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 79 Viewport.prototype.setScale = function(scale, notify) { | 90 Viewport.prototype.setScale = function(scale, notify) { |
| 80 if (this.scale_ == scale) return; | 91 if (this.scale_ == scale) return; |
| 81 this.scale_ = scale; | 92 this.scale_ = scale; |
| 82 this.invalidateCaches(); | 93 this.invalidateCaches(); |
| 83 }; | 94 }; |
| 84 | 95 |
| 85 /** | 96 /** |
| 86 * @return {number} Best scale to fit the current image into the current screen. | 97 * @return {number} Best scale to fit the current image into the current screen. |
| 87 */ | 98 */ |
| 88 Viewport.prototype.getFittingScale = function() { | 99 Viewport.prototype.getFittingScale = function() { |
| 89 var scaleX = this.screenBounds_.width / this.imageBounds_.width; | 100 return this.getFittingScaleForImageSize_( |
| 90 var scaleY = this.screenBounds_.height / this.imageBounds_.height; | 101 this.imageBounds_.width, this.imageBounds_.height); |
| 102 }; | |
| 103 | |
| 104 Viewport.prototype.getFittingScaleForImageSize_ = function(width, height) { | |
| 105 var scaleX = this.screenBounds_.width / width; | |
| 106 var scaleY = this.screenBounds_.height / height; | |
| 91 // Scales > (1 / this.getDevicePixelRatio()) do not look good. Also they are | 107 // Scales > (1 / this.getDevicePixelRatio()) do not look good. Also they are |
| 92 // not really useful as we do not have any pixel-level operations. | 108 // not really useful as we do not have any pixel-level operations. |
| 93 return Math.min(1 / Viewport.getDevicePixelRatio(), scaleX, scaleY); | 109 return Math.min(1 / devicePixelRatio, scaleX, scaleY); |
| 94 }; | 110 } |
| 95 | 111 |
| 96 /** | 112 /** |
| 97 * Set the scale to fit the image into the screen. | 113 * Set the scale to fit the image into the screen. |
| 98 */ | 114 */ |
| 99 Viewport.prototype.fitImage = function() { | 115 Viewport.prototype.fitImage = function() { |
| 100 var scale = this.getFittingScale(); | 116 var scale = this.getFittingScale(); |
| 101 this.setScale(scale, true); | 117 this.setScale(scale, true); |
| 102 }; | 118 }; |
| 103 | 119 |
| 104 /** | 120 /** |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 275 */ | 291 */ |
| 276 Viewport.prototype.imageToScreenRect = function(rect) { | 292 Viewport.prototype.imageToScreenRect = function(rect) { |
| 277 return new Rect( | 293 return new Rect( |
| 278 this.imageToScreenX(rect.left), | 294 this.imageToScreenX(rect.left), |
| 279 this.imageToScreenY(rect.top), | 295 this.imageToScreenY(rect.top), |
| 280 Math.round(this.imageToScreenSize(rect.width)), | 296 Math.round(this.imageToScreenSize(rect.width)), |
| 281 Math.round(this.imageToScreenSize(rect.height))); | 297 Math.round(this.imageToScreenSize(rect.height))); |
| 282 }; | 298 }; |
| 283 | 299 |
| 284 /** | 300 /** |
| 285 * @return {number} The number of physical pixels in one CSS pixel. | |
| 286 */ | |
| 287 Viewport.getDevicePixelRatio = function() { return window.devicePixelRatio; }; | |
| 288 | |
| 289 /** | |
| 290 * Convert a rectangle from screen coordinates to 'device' coordinates. | 301 * Convert a rectangle from screen coordinates to 'device' coordinates. |
| 291 * | 302 * |
| 292 * This conversion enlarges the original rectangle devicePixelRatio times | 303 * This conversion enlarges the original rectangle devicePixelRatio times |
| 293 * with the screen center as a fixed point. | 304 * with the screen center as a fixed point. |
| 294 * | 305 * |
| 295 * @param {Rect} rect Rectangle in screen coordinates. | 306 * @param {Rect} rect Rectangle in screen coordinates. |
| 296 * @return {Rect} Rectangle in device coordinates. | 307 * @return {Rect} Rectangle in device coordinates. |
| 297 */ | 308 */ |
| 298 Viewport.prototype.screenToDeviceRect = function(rect) { | 309 Viewport.prototype.screenToDeviceRect = function(rect) { |
| 299 var ratio = Viewport.getDevicePixelRatio(); | 310 var ratio = devicePixelRatio; |
| 300 var screenCenterX = Math.round( | 311 var screenCenterX = Math.round( |
| 301 this.screenBounds_.left + this.screenBounds_.width / 2); | 312 this.screenBounds_.left + this.screenBounds_.width / 2); |
| 302 var screenCenterY = Math.round( | 313 var screenCenterY = Math.round( |
| 303 this.screenBounds_.top + this.screenBounds_.height / 2); | 314 this.screenBounds_.top + this.screenBounds_.height / 2); |
| 304 return new Rect(screenCenterX + (rect.left - screenCenterX) * ratio, | 315 return new Rect(screenCenterX + (rect.left - screenCenterX) * ratio, |
| 305 screenCenterY + (rect.top - screenCenterY) * ratio, | 316 screenCenterY + (rect.top - screenCenterY) * ratio, |
| 306 rect.width * ratio, | 317 rect.width * ratio, |
| 307 rect.height * ratio); | 318 rect.height * ratio); |
| 308 }; | 319 }; |
| 309 | 320 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 410 }; | 421 }; |
| 411 | 422 |
| 412 /** | 423 /** |
| 413 * Repaint all clients. | 424 * Repaint all clients. |
| 414 */ | 425 */ |
| 415 Viewport.prototype.repaint = function() { | 426 Viewport.prototype.repaint = function() { |
| 416 this.update(); | 427 this.update(); |
| 417 for (var i = 0; i != this.repaintCallbacks_.length; i++) | 428 for (var i = 0; i != this.repaintCallbacks_.length; i++) |
| 418 this.repaintCallbacks_[i](); | 429 this.repaintCallbacks_[i](); |
| 419 }; | 430 }; |
| 431 | |
| 432 /** | |
| 433 * Obtains CSS transformation for the screen image. | |
| 434 * @return {string} Transformation description. | |
| 435 */ | |
| 436 Viewport.prototype.getTransformation = function() { | |
| 437 return 'scale(' + (1 / devicePixelRatio) + ')'; | |
| 438 }; | |
| 439 | |
| 440 /** | |
| 441 * Obtains shift CSS transformation for the screen image. | |
| 442 * @param {number} dx Amount of shift. | |
| 443 * @return {string} Transformation description. | |
| 444 */ | |
| 445 Viewport.prototype.getShiftTransformation = function(dx) { | |
| 446 return 'translateX(' + dx + 'px) ' + this.getTransformation(); | |
| 447 }; | |
| 448 | |
| 449 /** | |
| 450 * Obtains CSS transformation that makes the rotated image fit the original | |
| 451 * image. The new rotated image that the transformation is applied to looks the | |
| 452 * same with original image. | |
| 453 * | |
| 454 * @param {boolean} orientation Orientation of the rotation from the original | |
| 455 * image to the rotated image. True is for clockwise and false is for | |
| 456 * counterclockwise. | |
| 457 * @return {string} Transformation description. | |
| 458 */ | |
| 459 Viewport.prototype.getInverseTransformForRotatedImage = function(orientation) { | |
| 460 var previousImageWidth = this.imageBounds_.height; | |
| 461 var previousImageHeight = this.imageBounds_.width; | |
| 462 var oldScale = this.getFittingScaleForImageSize_( | |
| 463 previousImageWidth, previousImageHeight); | |
| 464 var scaleRatio = oldScale / this.getScale(); | |
| 465 var degree = orientation ? '-90deg' : '90deg'; | |
| 466 return [ | |
| 467 'scale(' + (scaleRatio) + ')', | |
| 468 'rotate(' + degree + ')', | |
| 469 this.getTransformation() | |
| 470 ].join(' '); | |
| 471 }; | |
| 472 | |
| 473 /** | |
| 474 * Obtains CSS transformation that makes the cropped image fit the original | |
| 475 * image. The new cropped image that the transformaton is applied to fits to the | |
| 476 * the cropped rectangle in the original image. | |
| 477 * | |
| 478 * @param {number} imageWidth Width of the original image. | |
| 479 * @param {number} imageHeight Height of the origianl image. | |
| 480 * @param {Rect} imageCropRect Crop rectangle in the image's coordinate system. | |
| 481 * @return {string} Transformation description. | |
| 482 */ | |
| 483 Viewport.prototype.getInverseTransformForCroppedImage = | |
| 484 function(imageWidth, imageHeight, imageCropRect) { | |
| 485 var wholeScale = this.getFittingScaleForImageSize_( | |
| 486 imageWidth, imageHeight); | |
| 487 var croppedScale = this.getFittingScaleForImageSize_( | |
| 488 imageCropRect.width, imageCropRect.height); | |
| 489 var dx = | |
| 490 (imageCropRect.left + imageCropRect.width / 2 - imageWidth / 2) * | |
| 491 wholeScale; | |
| 492 var dy = | |
| 493 (imageCropRect.top + imageCropRect.height / 2 - imageHeight / 2) * | |
| 494 wholeScale; | |
| 495 return [ | |
| 496 'translate(' + dx + 'px,' + dy + 'px)', | |
| 497 'scale(' + wholeScale / croppedScale + ')', | |
| 498 this.getTransformation() | |
| 499 ].join(' '); | |
| 500 }; | |
| 501 | |
| 502 /** | |
| 503 * Obtains CSS transformaton that makes the image fit to the screen rectangle. | |
| 504 * | |
| 505 * @param {Rect} screenRect Screen rectangle. | |
| 506 * @return {string} Transformation description. | |
| 507 */ | |
| 508 Viewport.prototype.getScreenRectTransformForImage = function(screenRect) { | |
| 509 var screenImageWidth = this.imageBounds_.width * this.getScale(); | |
| 510 var screenImageHeight = this.imageBounds_.height * this.getScale(); | |
| 511 var scaleX = screenRect.width / screenImageWidth; | |
| 512 var scaleY = screenRect.height /screenImageHeight; | |
| 513 var screenWidth = this.screenBounds_.width; | |
| 514 var screenHeight = this.screenBounds_.height; | |
| 515 var dx = screenRect.left + screenRect.width / 2 - screenWidth / 2; | |
| 516 var dy = screenRect.top + screenRect.height / 2 - screenHeight / 2; | |
| 517 return [ | |
| 518 'translate(' + dx + 'px,' + dy + 'px)', | |
| 519 'scale(' + scaleX + ',' + scaleY + ')', | |
| 520 this.getTransformation() | |
| 521 ].join(' '); | |
| 522 }; | |
| OLD | NEW |