Chromium Code Reviews| 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 * The overlay displaying the image. | 6 * The overlay displaying the image. |
| 7 */ | 7 */ |
| 8 function ImageView(container, viewport) { | 8 function ImageView(container, viewport) { |
| 9 this.container_ = container; | 9 this.container_ = container; |
| 10 this.viewport_ = viewport; | 10 this.viewport_ = viewport; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 28 // the content cache any more. Screen-scale images are small (~1Mpix) | 28 // the content cache any more. Screen-scale images are small (~1Mpix) |
| 29 // so we can afford to cache more of them. | 29 // so we can afford to cache more of them. |
| 30 this.screenCache_ = new ImageView.Cache(5); | 30 this.screenCache_ = new ImageView.Cache(5); |
| 31 this.contentCallbacks_ = []; | 31 this.contentCallbacks_ = []; |
| 32 } | 32 } |
| 33 | 33 |
| 34 ImageView.ANIMATION_DURATION = 180; | 34 ImageView.ANIMATION_DURATION = 180; |
| 35 ImageView.ANIMATION_WAIT_INTERVAL = ImageView.ANIMATION_DURATION * 2; | 35 ImageView.ANIMATION_WAIT_INTERVAL = ImageView.ANIMATION_DURATION * 2; |
| 36 ImageView.FAST_SCROLL_INTERVAL = 300; | 36 ImageView.FAST_SCROLL_INTERVAL = 300; |
| 37 | 37 |
| 38 ImageView.LOAD_TYPE_CACHED_FULL = 0; | |
| 39 ImageView.LOAD_TYPE_CACHED_SCREEN = 1; | |
| 40 ImageView.LOAD_TYPE_FILE = 2; | |
| 41 ImageView.LOAD_TYPE_TOTAL = 3; | |
| 42 | |
| 38 ImageView.prototype = {__proto__: ImageBuffer.Overlay.prototype}; | 43 ImageView.prototype = {__proto__: ImageBuffer.Overlay.prototype}; |
| 39 | 44 |
| 40 // Draw below overlays with the default zIndex. | 45 // Draw below overlays with the default zIndex. |
| 41 ImageView.prototype.getZIndex = function() { return -1 }; | 46 ImageView.prototype.getZIndex = function() { return -1 }; |
| 42 | 47 |
| 43 ImageView.prototype.draw = function() { | 48 ImageView.prototype.draw = function() { |
| 44 var forceRepaint = false; | 49 var forceRepaint = false; |
| 45 | 50 |
| 46 var screenClipped = this.viewport_.getScreenClipped(); | 51 var screenClipped = this.viewport_.getScreenClipped(); |
| 47 | 52 |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 146 * @param {Object} metadata | 151 * @param {Object} metadata |
| 147 * @param {Object} slide Slide-in animation direction. | 152 * @param {Object} slide Slide-in animation direction. |
| 148 * @param {function(boolean} opt_callback The parameter is true if the image | 153 * @param {function(boolean} opt_callback The parameter is true if the image |
| 149 * was loaded instantly (from the cache of the canvas source). | 154 * was loaded instantly (from the cache of the canvas source). |
| 150 */ | 155 */ |
| 151 ImageView.prototype.load = function( | 156 ImageView.prototype.load = function( |
| 152 id, source, metadata, slide, opt_callback) { | 157 id, source, metadata, slide, opt_callback) { |
| 153 | 158 |
| 154 metadata = metadata|| {}; | 159 metadata = metadata|| {}; |
| 155 | 160 |
| 156 ImageUtil.trace.resetTimer('load'); | 161 if (ImageUtil.metrics) { |
| 162 ImageUtil.metrics.startInterval(ImageUtil.getMetricName('DisplayTime')); | |
| 163 } | |
| 157 | 164 |
| 158 var self = this; | 165 var self = this; |
| 159 | 166 |
| 160 this.contentID_ = id; | 167 this.contentID_ = id; |
| 161 | 168 |
| 162 var readyContent = this.getReadyContent(id, source); | 169 var readyContent = this.getReadyContent(id, source); |
| 163 if (readyContent) { | 170 if (readyContent) { |
| 164 displayMainImage(readyContent, true); | 171 displayMainImage(ImageView.LOAD_TYPE_CACHED_FULL, readyContent); |
| 165 } else { | 172 } else { |
| 166 var cachedScreen = this.screenCache_.getItem(id); | 173 var cachedScreen = this.screenCache_.getItem(id); |
| 167 if (cachedScreen) { | 174 if (cachedScreen) { |
| 168 // We have a cached screen-scale canvas, use it as a thumbnail. | 175 // We have a cached screen-scale canvas, use it instead of a thumbnail. |
| 169 displayThumbnail(cachedScreen); | 176 displayThumbnail(ImageView.LOAD_TYPE_CACHED_SCREEN, cachedScreen); |
| 177 // As far as the user can tell the image is loaded. We still need to load | |
| 178 // the full res image to make editing possible, but we can report now. | |
| 179 ImageUtil.metrics.recordInterval(ImageUtil.getMetricName('DisplayTime')); | |
| 170 } else if (metadata.thumbnailURL) { | 180 } else if (metadata.thumbnailURL) { |
| 171 this.imageLoader_.load( | 181 this.imageLoader_.load( |
| 172 metadata.thumbnailURL, | 182 metadata.thumbnailURL, |
| 173 metadata.thumbnailTransform, | 183 metadata.thumbnailTransform, |
| 174 displayThumbnail); | 184 displayThumbnail.bind(null, ImageView.LOAD_TYPE_FILE)); |
| 175 } else { | 185 } else { |
| 176 loadMainImage(0); | 186 loadMainImage(ImageView.LOAD_TYPE_FILE, 0); |
| 177 } | 187 } |
| 178 } | 188 } |
| 179 | 189 |
| 180 function displayThumbnail(canvas) { | 190 function displayThumbnail(loadType, canvas) { |
| 181 // The thumbnail may have different aspect ratio than the main image. | 191 // The thumbnail may have different aspect ratio than the main image. |
| 182 // Force the main image proportions to avoid flicker. | 192 // Force the main image proportions to avoid flicker. |
| 183 var time = Date.now(); | 193 var time = Date.now(); |
| 184 | 194 |
| 185 var mainImageLoadDelay = ImageView.ANIMATION_WAIT_INTERVAL; | 195 var mainImageLoadDelay = ImageView.ANIMATION_WAIT_INTERVAL; |
| 186 | 196 |
| 187 // Do not do slide-in animation when scrolling very fast. | 197 // Do not do slide-in animation when scrolling very fast. |
| 188 if (self.lastLoadTime_ && | 198 if (self.lastLoadTime_ && |
| 189 (time - self.lastLoadTime_) < ImageView.FAST_SCROLL_INTERVAL) { | 199 (time - self.lastLoadTime_) < ImageView.FAST_SCROLL_INTERVAL) { |
| 190 slide = 0; | 200 slide = 0; |
| 191 } | 201 } |
| 192 self.lastLoadTime_ = time; | 202 self.lastLoadTime_ = time; |
| 193 | 203 |
| 194 self.replace(canvas, slide, metadata.width, metadata.height); | 204 self.replace(canvas, slide, metadata.width, metadata.height); |
| 195 if (!slide) mainImageLoadDelay = 0; | 205 if (!slide) mainImageLoadDelay = 0; |
| 196 slide = 0; | 206 slide = 0; |
| 197 loadMainImage(mainImageLoadDelay); | 207 loadMainImage(loadType, mainImageLoadDelay); |
| 198 } | 208 } |
| 199 | 209 |
| 200 function loadMainImage(delay) { | 210 function loadMainImage(loadType, delay) { |
| 201 if (self.prefetchLoader_.isLoading(source)) { | 211 if (self.prefetchLoader_.isLoading(source)) { |
| 202 // The image we need is already being prefetched. Initiating another load | 212 // The image we need is already being prefetched. Initiating another load |
| 203 // would be a waste. Hijack the load instead by overriding the callback. | 213 // would be a waste. Hijack the load instead by overriding the callback. |
| 204 self.prefetchLoader_.setCallback(displayMainImage); | 214 self.prefetchLoader_.setCallback(displayMainImage.bind(null, loadType)); |
| 205 | 215 |
| 206 // Swap the loaders so that the self.isLoading works correctly. | 216 // Swap the loaders so that the self.isLoading works correctly. |
| 207 var temp = self.prefetchLoader_; | 217 var temp = self.prefetchLoader_; |
| 208 self.prefetchLoader_ = self.imageLoader_; | 218 self.prefetchLoader_ = self.imageLoader_; |
| 209 self.imageLoader_ = temp; | 219 self.imageLoader_ = temp; |
| 210 return; | 220 return; |
| 211 } | 221 } |
| 212 self.prefetchLoader_.cancel(); // The prefetch was doing something useless. | 222 self.prefetchLoader_.cancel(); // The prefetch was doing something useless. |
| 213 | 223 |
| 214 self.imageLoader_.load( | 224 self.imageLoader_.load( |
| 215 source, | 225 source, |
| 216 metadata.imageTransform, | 226 metadata.imageTransform, |
| 217 displayMainImage, | 227 displayMainImage.bind(null, loadType), |
| 218 delay); | 228 delay); |
| 219 } | 229 } |
| 220 | 230 |
| 221 function displayMainImage(canvas, opt_fastLoad) { | 231 function displayMainImage(loadType, canvas) { |
| 222 self.replace(canvas, slide); | 232 self.replace(canvas, slide); |
| 223 ImageUtil.trace.reportTimer('load'); | 233 ImageUtil.metrics.recordEnum(ImageUtil.getMetricName('DisplayMode'), |
| 224 ImageUtil.trace.report('load-type', opt_fastLoad ? 'cached' : 'file'); | 234 loadType, ImageView.LOAD_TYPE_TOTAL); |
| 225 if (opt_callback) opt_callback(opt_fastLoad); | 235 if (loadType != ImageView.LOAD_TYPE_CACHED_SCREEN) { |
| 236 ImageUtil.metrics.recordInterval(ImageUtil.getMetricName('DisplayTime')); | |
| 237 } | |
| 238 if (opt_callback) opt_callback(loadType == ImageView.LOAD_TYPE_CACHED_FULL); | |
|
dgozman
2011/12/06 15:45:56
I believe that callback now accepts the loadType i
Vladislav Kaznacheev
2011/12/06 16:07:44
Good catch, thanks!
On 2011/12/06 15:45:56, dgozma
| |
| 226 } | 239 } |
| 227 }; | 240 }; |
| 228 | 241 |
| 229 /** | 242 /** |
| 230 * Try to get the canvas from the content cache or from the source. | 243 * Try to get the canvas from the content cache or from the source. |
| 231 * | 244 * |
| 232 * @param {number} id Unique image id for caching purposes | 245 * @param {number} id Unique image id for caching purposes |
| 233 * @param {string|HTMLCanvasElement} source | 246 * @param {string|HTMLCanvasElement} source |
| 234 */ | 247 */ |
| 235 ImageView.prototype.getReadyContent = function(id, source) { | 248 ImageView.prototype.getReadyContent = function(id, source) { |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 462 if (this.order_.length > this.capacity_) | 475 if (this.order_.length > this.capacity_) |
| 463 throw new Error('Exceeded cache capacity'); | 476 throw new Error('Exceeded cache capacity'); |
| 464 }; | 477 }; |
| 465 | 478 |
| 466 ImageView.Cache.prototype.evictLRU = function() { | 479 ImageView.Cache.prototype.evictLRU = function() { |
| 467 if (this.order_.length == this.capacity_) { | 480 if (this.order_.length == this.capacity_) { |
| 468 var id = this.order_.shift(); | 481 var id = this.order_.shift(); |
| 469 delete this.map_[id]; | 482 delete this.map_[id]; |
| 470 } | 483 } |
| 471 }; | 484 }; |
| OLD | NEW |