| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 * Viewport class controls the way the image is displayed (scale, offset etc). | 6 * Viewport class controls the way the image is displayed (scale, offset etc). |
| 7 */ | 7 */ |
| 8 function Viewport(repaintCallback) { | 8 function Viewport(repaintCallback) { |
| 9 this.repaintCallback_ = repaintCallback; | 9 this.repaintCallback_ = repaintCallback; |
| 10 | 10 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 Viewport.prototype.setCenter = function(x, y, ignoreClipping) { | 82 Viewport.prototype.setCenter = function(x, y, ignoreClipping) { |
| 83 this.setOffset( | 83 this.setOffset( |
| 84 this.imageBounds_.width / 2 - x, | 84 this.imageBounds_.width / 2 - x, |
| 85 this.imageBounds_.height / 2 - y, | 85 this.imageBounds_.height / 2 - y, |
| 86 ignoreClipping); | 86 ignoreClipping); |
| 87 }; | 87 }; |
| 88 | 88 |
| 89 /** | 89 /** |
| 90 * Return a closure that can be called to pan the image. | 90 * Return a closure that can be called to pan the image. |
| 91 * Useful for implementing non-trivial variants of panning (overview etc). | 91 * Useful for implementing non-trivial variants of panning (overview etc). |
| 92 * @param {Number} originalX The x coordinate on the screen canvas that | 92 * @param {number} originalX The x coordinate on the screen canvas that |
| 93 * corresponds to zero change to offsetX. | 93 * corresponds to zero change to offsetX. |
| 94 * @param {Number} originalY The y coordinate on the screen canvas that | 94 * @param {number} originalY The y coordinate on the screen canvas that |
| 95 * corresponds to zero change to offsetY. | 95 * corresponds to zero change to offsetY. |
| 96 * @param {Function} scaleFunc returns the current image to screen scale. | 96 * @param {function():number} scaleFunc returns the image to screen scale. |
| 97 * @param {Function} hitFunc returns true if (x,y) is in the valid region. | 97 * @param {function(number,number):boolean} hitFunc returns true if (x,y) is |
| 98 * in the valid region. |
| 98 */ | 99 */ |
| 99 Viewport.prototype.createOffsetSetter = function ( | 100 Viewport.prototype.createOffsetSetter = function ( |
| 100 originalX, originalY, scaleFunc, hitFunc) { | 101 originalX, originalY, scaleFunc, hitFunc) { |
| 101 var originalOffsetX = this.offsetX_; | 102 var originalOffsetX = this.offsetX_; |
| 102 var originalOffsetY = this.offsetY_; | 103 var originalOffsetY = this.offsetY_; |
| 103 if (!hitFunc) hitFunc = function() { return true }; | 104 if (!hitFunc) hitFunc = function() { return true }; |
| 104 if (!scaleFunc) scaleFunc = this.getScale.bind(this); | 105 if (!scaleFunc) scaleFunc = this.getScale.bind(this); |
| 105 | 106 |
| 106 var self = this; | 107 var self = this; |
| 107 return function(x, y) { | 108 return function(x, y) { |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 * @return {Boolean} True if some part of the image is clipped by the screen. | 207 * @return {Boolean} True if some part of the image is clipped by the screen. |
| 207 */ | 208 */ |
| 208 Viewport.prototype.isClipped = function () { | 209 Viewport.prototype.isClipped = function () { |
| 209 return this.getMarginX_() < 0 || this.getMarginY_() < 0; | 210 return this.getMarginX_() < 0 || this.getMarginY_() < 0; |
| 210 }; | 211 }; |
| 211 | 212 |
| 212 /** | 213 /** |
| 213 * Horizontal margin. Negative if the image is clipped horizontally. | 214 * Horizontal margin. Negative if the image is clipped horizontally. |
| 214 */ | 215 */ |
| 215 Viewport.prototype.getMarginX_ = function() { | 216 Viewport.prototype.getMarginX_ = function() { |
| 216 return Math.floor( | 217 return Math.round( |
| 217 (this.screenBounds_.width - this.imageBounds_.width * this.scale_) / 2); | 218 (this.screenBounds_.width - this.imageBounds_.width * this.scale_) / 2); |
| 218 }; | 219 }; |
| 219 | 220 |
| 220 /** | 221 /** |
| 221 * Vertical margin. Negative if the image is clipped vertically. | 222 * Vertical margin. Negative if the image is clipped vertically. |
| 222 */ | 223 */ |
| 223 Viewport.prototype.getMarginY_ = function() { | 224 Viewport.prototype.getMarginY_ = function() { |
| 224 return Math.floor( | 225 return Math.round( |
| 225 (this.screenBounds_.height - this.imageBounds_.height * this.scale_) / 2); | 226 (this.screenBounds_.height - this.imageBounds_.height * this.scale_) / 2); |
| 226 }; | 227 }; |
| 227 | 228 |
| 228 Viewport.prototype.clampOffsetX_ = function(x) { | 229 Viewport.prototype.clampOffsetX_ = function(x) { |
| 229 var limit = Math.max(0, -this.getMarginX_() / this.getScale()); | 230 var limit = Math.round(Math.max(0, -this.getMarginX_() / this.getScale())); |
| 230 return ImageUtil.clamp(-limit, x, limit); | 231 return ImageUtil.clamp(-limit, x, limit); |
| 231 }; | 232 }; |
| 232 | 233 |
| 233 Viewport.prototype.clampOffsetY_ = function(y) { | 234 Viewport.prototype.clampOffsetY_ = function(y) { |
| 234 var limit = Math.max(0, -this.getMarginY_() / this.getScale()); | 235 var limit = Math.round(Math.max(0, -this.getMarginY_() / this.getScale())); |
| 235 return ImageUtil.clamp(-limit, y, limit); | 236 return ImageUtil.clamp(-limit, y, limit); |
| 236 }; | 237 }; |
| 237 | 238 |
| 238 /** | 239 /** |
| 239 * Recalculate the viewport parameters. | 240 * Recalculate the viewport parameters. |
| 240 */ | 241 */ |
| 241 Viewport.prototype.update = function() { | 242 Viewport.prototype.update = function() { |
| 242 var scale = this.getScale(); | 243 var scale = this.getScale(); |
| 243 | 244 |
| 244 // Image bounds in screen coordinates. | 245 // Image bounds in screen coordinates. |
| 245 this.imageOnScreen_ = new Rect( | 246 this.imageOnScreen_ = new Rect( |
| 246 this.getMarginX_(), | 247 this.getMarginX_(), |
| 247 this.getMarginY_(), | 248 this.getMarginY_(), |
| 248 Math.floor(this.imageBounds_.width * scale), | 249 Math.round(this.imageBounds_.width * scale), |
| 249 Math.floor(this.imageBounds_.height * scale)); | 250 Math.round(this.imageBounds_.height * scale)); |
| 250 | 251 |
| 251 // A visible part of the image in image coordinates. | 252 // A visible part of the image in image coordinates. |
| 252 this.imageClipped_ = new Rect(this.imageBounds_); | 253 this.imageClipped_ = new Rect(this.imageBounds_); |
| 253 | 254 |
| 254 // A visible part of the image in screen coordinates. | 255 // A visible part of the image in screen coordinates. |
| 255 this.screenClipped_ = new Rect(this.screenBounds_); | 256 this.screenClipped_ = new Rect(this.screenBounds_); |
| 256 | 257 |
| 257 // Adjust for the offset. | 258 // Adjust for the offset. |
| 258 if (this.imageOnScreen_.left < 0) { | 259 if (this.imageOnScreen_.left < 0) { |
| 259 this.imageOnScreen_.left += this.clampOffsetX_(this.offsetX_) * scale; | 260 this.imageOnScreen_.left += |
| 260 this.imageClipped_.left = -this.imageOnScreen_.left / scale; | 261 Math.round(this.clampOffsetX_(this.offsetX_) * scale); |
| 261 this.imageClipped_.width = this.screenBounds_.width / scale; | 262 this.imageClipped_.left = Math.round(-this.imageOnScreen_.left / scale); |
| 263 this.imageClipped_.width = Math.round(this.screenBounds_.width / scale); |
| 262 } else { | 264 } else { |
| 263 this.screenClipped_.left = this.imageOnScreen_.left; | 265 this.screenClipped_.left = this.imageOnScreen_.left; |
| 264 this.screenClipped_.width = this.imageOnScreen_.width; | 266 this.screenClipped_.width = this.imageOnScreen_.width; |
| 265 } | 267 } |
| 266 | 268 |
| 267 if (this.imageOnScreen_.top < 0) { | 269 if (this.imageOnScreen_.top < 0) { |
| 268 this.imageOnScreen_.top += this.clampOffsetY_(this.offsetY_) * scale; | 270 this.imageOnScreen_.top += |
| 269 this.imageClipped_.top = -this.imageOnScreen_.top / scale; | 271 Math.round(this.clampOffsetY_(this.offsetY_) * scale); |
| 270 this.imageClipped_.height = this.screenBounds_.height / scale; | 272 this.imageClipped_.top = Math.round(-this.imageOnScreen_.top / scale); |
| 273 this.imageClipped_.height = Math.round(this.screenBounds_.height / scale); |
| 271 } else { | 274 } else { |
| 272 this.screenClipped_.top = this.imageOnScreen_.top; | 275 this.screenClipped_.top = this.imageOnScreen_.top; |
| 273 this.screenClipped_.height = this.imageOnScreen_.height; | 276 this.screenClipped_.height = this.imageOnScreen_.height; |
| 274 } | 277 } |
| 275 }; | 278 }; |
| 276 | 279 |
| 277 Viewport.prototype.repaint = function () { | 280 Viewport.prototype.repaint = function () { |
| 278 if (this.repaintCallback_) this.repaintCallback_(); | 281 if (this.repaintCallback_) this.repaintCallback_(); |
| 279 }; | 282 }; |
| OLD | NEW |