| 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 */ |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 * not zoom operated by users. | 28 * not zoom operated by users. |
| 29 * @type {number} | 29 * @type {number} |
| 30 * @private | 30 * @private |
| 31 */ | 31 */ |
| 32 this.scale_ = 1; | 32 this.scale_ = 1; |
| 33 this.offsetX_ = 0; | 33 this.offsetX_ = 0; |
| 34 this.offsetY_ = 0; | 34 this.offsetY_ = 0; |
| 35 | 35 |
| 36 this.generation_ = 0; | 36 this.generation_ = 0; |
| 37 | 37 |
| 38 this.repaintCallbacks_ = []; | |
| 39 this.update(); | 38 this.update(); |
| 40 } | 39 } |
| 41 | 40 |
| 42 /** | 41 /** |
| 43 * @param {number} width Image width. | 42 * @param {number} width Image width. |
| 44 * @param {number} height Image height. | 43 * @param {number} height Image height. |
| 45 */ | 44 */ |
| 46 Viewport.prototype.setImageSize = function(width, height) { | 45 Viewport.prototype.setImageSize = function(width, height) { |
| 47 this.imageBounds_ = new Rect(width, height); | 46 this.imageBounds_ = new Rect(width, height); |
| 48 this.invalidateCaches(); | 47 this.invalidateCaches(); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 x = this.clampOffsetX_(x); | 147 x = this.clampOffsetX_(x); |
| 149 y = this.clampOffsetY_(y); | 148 y = this.clampOffsetY_(y); |
| 150 } | 149 } |
| 151 if (this.offsetX_ == x && this.offsetY_ == y) return; | 150 if (this.offsetX_ == x && this.offsetY_ == y) return; |
| 152 this.offsetX_ = x; | 151 this.offsetX_ = x; |
| 153 this.offsetY_ = y; | 152 this.offsetY_ = y; |
| 154 this.invalidateCaches(); | 153 this.invalidateCaches(); |
| 155 }; | 154 }; |
| 156 | 155 |
| 157 /** | 156 /** |
| 158 * Return a closure that can be called to pan the image. | |
| 159 * Useful for implementing non-trivial variants of panning (overview etc). | |
| 160 * @param {number} originalX The x coordinate on the screen canvas that | |
| 161 * corresponds to zero change to offsetX. | |
| 162 * @param {number} originalY The y coordinate on the screen canvas that | |
| 163 * corresponds to zero change to offsetY. | |
| 164 * @param {function():number} scaleFunc returns the image to screen scale. | |
| 165 * @param {function(number,number):boolean} hitFunc returns true if (x,y) is | |
| 166 * in the valid region. | |
| 167 * @return {function} The closure to pan the image. | |
| 168 */ | |
| 169 Viewport.prototype.createOffsetSetter = function( | |
| 170 originalX, originalY, scaleFunc, hitFunc) { | |
| 171 var originalOffsetX = this.offsetX_; | |
| 172 var originalOffsetY = this.offsetY_; | |
| 173 if (!hitFunc) hitFunc = function() { return true; }; | |
| 174 if (!scaleFunc) scaleFunc = this.getScale.bind(this); | |
| 175 | |
| 176 var self = this; | |
| 177 return function(x, y) { | |
| 178 if (hitFunc(x, y)) { | |
| 179 var scale = scaleFunc(); | |
| 180 self.setOffset( | |
| 181 originalOffsetX + (x - originalX) / scale, | |
| 182 originalOffsetY + (y - originalY) / scale); | |
| 183 self.repaint(); | |
| 184 } | |
| 185 }; | |
| 186 }; | |
| 187 | |
| 188 /* | |
| 189 * Access to the current viewport state. | |
| 190 */ | |
| 191 | |
| 192 /** | |
| 193 * @return {Rect} The image bounds in image coordinates. | 157 * @return {Rect} The image bounds in image coordinates. |
| 194 */ | 158 */ |
| 195 Viewport.prototype.getImageBounds = function() { return this.imageBounds_; }; | 159 Viewport.prototype.getImageBounds = function() { return this.imageBounds_; }; |
| 196 | 160 |
| 197 /** | 161 /** |
| 198 * @return {Rect} The screen bounds in screen coordinates. | 162 * @return {Rect} The screen bounds in screen coordinates. |
| 199 */ | 163 */ |
| 200 Viewport.prototype.getScreenBounds = function() { return this.screenBounds_; }; | 164 Viewport.prototype.getScreenBounds = function() { return this.screenBounds_; }; |
| 201 | 165 |
| 202 /** | 166 /** |
| (...skipping 10 matching lines...) Expand all Loading... |
| 213 | 177 |
| 214 /** | 178 /** |
| 215 * A counter that is incremented with each viewport state change. | 179 * A counter that is incremented with each viewport state change. |
| 216 * Clients that cache anything that depends on the viewport state should keep | 180 * Clients that cache anything that depends on the viewport state should keep |
| 217 * track of this counter. | 181 * track of this counter. |
| 218 * @return {number} counter. | 182 * @return {number} counter. |
| 219 */ | 183 */ |
| 220 Viewport.prototype.getCacheGeneration = function() { return this.generation_; }; | 184 Viewport.prototype.getCacheGeneration = function() { return this.generation_; }; |
| 221 | 185 |
| 222 /** | 186 /** |
| 223 * Called on event view port state change (even if repaint has not been called). | 187 * Called on event view port state change. |
| 224 */ | 188 */ |
| 225 Viewport.prototype.invalidateCaches = function() { this.generation_++; }; | 189 Viewport.prototype.invalidateCaches = function() { this.generation_++; }; |
| 226 | 190 |
| 227 /** | 191 /** |
| 228 * @return {Rect} The image bounds in screen coordinates. | 192 * @return {Rect} The image bounds in screen coordinates. |
| 229 */ | 193 */ |
| 230 Viewport.prototype.getImageBoundsOnScreen = function() { | 194 Viewport.prototype.getImageBoundsOnScreen = function() { |
| 231 return this.imageOnScreen_; | 195 return this.imageOnScreen_; |
| 232 }; | 196 }; |
| 233 | 197 |
| 234 /* | |
| 235 * Conversion between the screen and image coordinate spaces. | |
| 236 */ | |
| 237 | |
| 238 /** | 198 /** |
| 239 * @param {number} size Size in screen coordinates. | 199 * @param {number} size Size in screen coordinates. |
| 240 * @return {number} Size in image coordinates. | 200 * @return {number} Size in image coordinates. |
| 241 */ | 201 */ |
| 242 Viewport.prototype.screenToImageSize = function(size) { | 202 Viewport.prototype.screenToImageSize = function(size) { |
| 243 return size / this.getScale(); | 203 return size / this.getScale(); |
| 244 }; | 204 }; |
| 245 | 205 |
| 246 /** | 206 /** |
| 247 * @param {number} x X in screen coordinates. | 207 * @param {number} x X in screen coordinates. |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 Math.round(this.clampOffsetY_(this.offsetY_) * scale); | 377 Math.round(this.clampOffsetY_(this.offsetY_) * scale); |
| 418 this.imageClipped_.top = Math.round(-this.imageOnScreen_.top / scale); | 378 this.imageClipped_.top = Math.round(-this.imageOnScreen_.top / scale); |
| 419 this.imageClipped_.height = Math.round(this.screenBounds_.height / scale); | 379 this.imageClipped_.height = Math.round(this.screenBounds_.height / scale); |
| 420 } else { | 380 } else { |
| 421 this.screenClipped_.top = this.imageOnScreen_.top; | 381 this.screenClipped_.top = this.imageOnScreen_.top; |
| 422 this.screenClipped_.height = this.imageOnScreen_.height; | 382 this.screenClipped_.height = this.imageOnScreen_.height; |
| 423 } | 383 } |
| 424 }; | 384 }; |
| 425 | 385 |
| 426 /** | 386 /** |
| 427 * @param {function} callback Repaint callback. | |
| 428 */ | |
| 429 Viewport.prototype.addRepaintCallback = function(callback) { | |
| 430 this.repaintCallbacks_.push(callback); | |
| 431 }; | |
| 432 | |
| 433 /** | |
| 434 * Repaint all clients. | |
| 435 */ | |
| 436 Viewport.prototype.repaint = function() { | |
| 437 this.update(); | |
| 438 for (var i = 0; i != this.repaintCallbacks_.length; i++) | |
| 439 this.repaintCallbacks_[i](); | |
| 440 }; | |
| 441 | |
| 442 /** | |
| 443 * Obtains CSS transformation for the screen image. | 387 * Obtains CSS transformation for the screen image. |
| 444 * @return {string} Transformation description. | 388 * @return {string} Transformation description. |
| 445 */ | 389 */ |
| 446 Viewport.prototype.getTransformation = function() { | 390 Viewport.prototype.getTransformation = function() { |
| 447 return 'scale(' + (1 / window.devicePixelRatio) + ')'; | 391 return 'scale(' + (1 / window.devicePixelRatio) + ')'; |
| 448 }; | 392 }; |
| 449 | 393 |
| 450 /** | 394 /** |
| 451 * Obtains shift CSS transformation for the screen image. | 395 * Obtains shift CSS transformation for the screen image. |
| 452 * @param {number} dx Amount of shift. | 396 * @param {number} dx Amount of shift. |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 523 var screenWidth = this.screenBounds_.width; | 467 var screenWidth = this.screenBounds_.width; |
| 524 var screenHeight = this.screenBounds_.height; | 468 var screenHeight = this.screenBounds_.height; |
| 525 var dx = screenRect.left + screenRect.width / 2 - screenWidth / 2; | 469 var dx = screenRect.left + screenRect.width / 2 - screenWidth / 2; |
| 526 var dy = screenRect.top + screenRect.height / 2 - screenHeight / 2; | 470 var dy = screenRect.top + screenRect.height / 2 - screenHeight / 2; |
| 527 return [ | 471 return [ |
| 528 'translate(' + dx + 'px,' + dy + 'px)', | 472 'translate(' + dx + 'px,' + dy + 'px)', |
| 529 'scale(' + scaleX + ',' + scaleY + ')', | 473 'scale(' + scaleX + ',' + scaleY + ')', |
| 530 this.getTransformation() | 474 this.getTransformation() |
| 531 ].join(' '); | 475 ].join(' '); |
| 532 }; | 476 }; |
| OLD | NEW |