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

Side by Side Diff: ui/file_manager/gallery/js/image_editor/image_view.js

Issue 792733002: Add type annotations to gallery/js/image_editor/image_view.js. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 6 years 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
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 * The overlay displaying the image. 6 * The overlay displaying the image.
7 * 7 *
8 * @param {HTMLElement} container The container element. 8 * @param {!HTMLElement} container The container element.
9 * @param {Viewport} viewport The viewport. 9 * @param {!Viewport} viewport The viewport.
10 * @constructor 10 * @constructor
11 * @extends {ImageBuffer.Overlay} 11 * @extends {ImageBuffer.Overlay}
12 * @struct
12 */ 13 */
13 function ImageView(container, viewport) { 14 function ImageView(container, viewport) {
14 ImageBuffer.Overlay.call(this); 15 ImageBuffer.Overlay.call(this);
15 16
16 this.container_ = container; 17 this.container_ = container;
18
19 /**
20 * The viewport.
21 * @type {!Viewport}
22 * @private
23 */
17 this.viewport_ = viewport; 24 this.viewport_ = viewport;
18 this.document_ = container.ownerDocument; 25
26 this.document_ = assertInstanceof(container.ownerDocument, HTMLDocument);
19 this.contentGeneration_ = 0; 27 this.contentGeneration_ = 0;
20 this.displayedContentGeneration_ = 0; 28 this.displayedContentGeneration_ = 0;
21 29
22 this.imageLoader_ = new ImageUtil.ImageLoader(this.document_); 30 this.imageLoader_ = new ImageUtil.ImageLoader(this.document_);
23 // We have a separate image loader for prefetch which does not get cancelled 31 // We have a separate image loader for prefetch which does not get cancelled
24 // when the selection changes. 32 // when the selection changes.
25 this.prefetchLoader_ = new ImageUtil.ImageLoader(this.document_); 33 this.prefetchLoader_ = new ImageUtil.ImageLoader(this.document_);
26 34
27 this.contentCallbacks_ = []; 35 this.contentCallbacks_ = [];
28 36
29 /** 37 /**
30 * The element displaying the current content. 38 * The element displaying the current content.
31 *
32 * @type {HTMLCanvasElement} 39 * @type {HTMLCanvasElement}
33 * @private 40 * @private
34 */ 41 */
35 this.screenImage_ = null; 42 this.screenImage_ = null;
43
44 /**
45 * The content canvas element.
46 * @type {(HTMLCanvasElement|HTMLImageElement)}
47 * @private
48 */
49 this.contentCanvas_ = null;
50
51 /**
52 * True if the image is a preview (not full res).
53 * @type {boolean}
54 * @private
55 */
56 this.preview_ = false;
57
58 /**
59 * Cached thumbnail image.
60 * @type {HTMLCanvasElement}
61 * @private
62 */
63 this.thumbnailCanvas_ = null;
64
65 /**
66 * The content revision number.
67 * @type {number}
68 * @private
69 */
70 this.contentRevision_ = -1;
71
72 /**
73 * The last load time.
74 * @type {?number}
75 * @private
76 */
77 this.lastLoadTime_ = null;
78
79 /**
80 * Gallery item which is loaded.
81 * @type {Gallery.Item}
82 * @private
83 */
84 this.contentItem_ = null;
85
86 /**
87 * Timer to unload.
88 * @type {?number}
89 * @private
90 */
91 this.unloadTimer_ = null;
36 } 92 }
37 93
38 /** 94 /**
39 * Duration of transition between modes in ms. 95 * Duration of transition between modes in ms.
96 * @type {number}
97 * @const
40 */ 98 */
41 ImageView.MODE_TRANSITION_DURATION = 350; 99 ImageView.MODE_TRANSITION_DURATION = 350;
42 100
43 /** 101 /**
44 * If the user flips though images faster than this interval we do not apply 102 * If the user flips though images faster than this interval we do not apply
45 * the slide-in/slide-out transition. 103 * the slide-in/slide-out transition.
104 * @type {number}
105 * @const
46 */ 106 */
47 ImageView.FAST_SCROLL_INTERVAL = 300; 107 ImageView.FAST_SCROLL_INTERVAL = 300;
48 108
49 /**
50 * Image load type: full resolution image loaded from cache.
51 */
52 ImageView.LOAD_TYPE_CACHED_FULL = 0;
53 109
54 /** 110 /**
55 * Image load type: screen resolution preview loaded from cache. 111 * Image load types.
112 * @enum {number}
56 */ 113 */
57 ImageView.LOAD_TYPE_CACHED_SCREEN = 1; 114 ImageView.LoadType = {
58 115 // Full resolution image loaded from cache.
59 /** 116 CACHED_FULL: 0,
60 * Image load type: image read from file. 117 // Screen resolution preview loaded from cache.
61 */ 118 CACHED_SCREEN: 1,
62 ImageView.LOAD_TYPE_IMAGE_FILE = 2; 119 // Image read from file.
63 120 IMAGE_FILE: 2,
64 /** 121 // Error occurred.
65 * Image load type: error occurred. 122 ERROR: 3,
66 */ 123 // The file contents is not available offline.
67 ImageView.LOAD_TYPE_ERROR = 3; 124 OFFLINE: 4
68 125 };
69 /**
70 * Image load type: the file contents is not available offline.
71 */
72 ImageView.LOAD_TYPE_OFFLINE = 4;
73
74 /**
75 * The total number of load types.
76 */
77 ImageView.LOAD_TYPE_TOTAL = 5;
78 126
79 /** 127 /**
80 * Target of image load. 128 * Target of image load.
81 * @enum {string} 129 * @enum {string}
82 */ 130 */
83 ImageView.LoadTarget = { 131 ImageView.LoadTarget = {
84 CACHED_MAIN_IMAGE: 'cachedMainImage', 132 CACHED_MAIN_IMAGE: 'cachedMainImage',
85 CACHED_THUMBNAIL: 'cachedThumbnail', 133 CACHED_THUMBNAIL: 'cachedThumbnail',
86 THUMBNAIL: 'thumbnail', 134 THUMBNAIL: 'thumbnail',
87 MAIN_IMAGE: 'mainImage' 135 MAIN_IMAGE: 'mainImage'
(...skipping 29 matching lines...) Expand all
117 * @override 165 * @override
118 */ 166 */
119 ImageView.prototype.getZIndex = function() { return -1; }; 167 ImageView.prototype.getZIndex = function() { return -1; };
120 168
121 /** 169 /**
122 * @override 170 * @override
123 */ 171 */
124 ImageView.prototype.draw = function() { 172 ImageView.prototype.draw = function() {
125 if (!this.contentCanvas_) // Do nothing if the image content is not set. 173 if (!this.contentCanvas_) // Do nothing if the image content is not set.
126 return; 174 return;
127 if (this.setupDeviceBuffer(this.screenImage_) || 175 if ((this.screenImage_ && this.setupDeviceBuffer(this.screenImage_)) ||
128 this.displayedContentGeneration_ !== this.contentGeneration_) { 176 this.displayedContentGeneration_ !== this.contentGeneration_) {
129 this.displayedContentGeneration_ = this.contentGeneration_; 177 this.displayedContentGeneration_ = this.contentGeneration_;
130 ImageUtil.trace.resetTimer('paint'); 178 ImageUtil.trace.resetTimer('paint');
131 this.paintDeviceRect( 179 this.paintDeviceRect(
132 this.contentCanvas_, new ImageRect(this.contentCanvas_)); 180 this.contentCanvas_, ImageRect.createFromCanvas(this.contentCanvas_));
133 ImageUtil.trace.reportTimer('paint'); 181 ImageUtil.trace.reportTimer('paint');
134 } 182 }
135 }; 183 };
136 184
137 /** 185 /**
138 * Applies the viewport change that does not affect the screen cache size (zoom 186 * Applies the viewport change that does not affect the screen cache size (zoom
139 * change or offset change) with animation. 187 * change or offset change) with animation.
140 */ 188 */
141 ImageView.prototype.applyViewportChange = function() { 189 ImageView.prototype.applyViewportChange = function() {
142 if (this.screenImage_) { 190 if (this.screenImage_) {
(...skipping 21 matching lines...) Expand all
164 212
165 /** 213 /**
166 * @return {HTMLCanvasElement} The content canvas element. 214 * @return {HTMLCanvasElement} The content canvas element.
167 */ 215 */
168 ImageView.prototype.getCanvas = function() { return this.contentCanvas_; }; 216 ImageView.prototype.getCanvas = function() { return this.contentCanvas_; };
169 217
170 /** 218 /**
171 * @return {boolean} True if the a valid image is currently loaded. 219 * @return {boolean} True if the a valid image is currently loaded.
172 */ 220 */
173 ImageView.prototype.hasValidImage = function() { 221 ImageView.prototype.hasValidImage = function() {
174 return !this.preview_ && this.contentCanvas_ && this.contentCanvas_.width; 222 return !!(!this.preview_ && this.contentCanvas_ && this.contentCanvas_.width);
175 }; 223 };
176 224
177 /** 225 /**
178 * @return {!HTMLCanvasElement} The cached thumbnail image. 226 * @return {!HTMLCanvasElement} The cached thumbnail image.
179 */ 227 */
180 ImageView.prototype.getThumbnail = function() { 228 ImageView.prototype.getThumbnail = function() {
181 assert(this.thumbnailCanvas_); 229 assert(this.thumbnailCanvas_);
182 return this.thumbnailCanvas_; 230 return this.thumbnailCanvas_;
183 }; 231 };
184 232
185 /** 233 /**
186 * @return {number} The content revision number. 234 * @return {number} The content revision number.
187 */ 235 */
188 ImageView.prototype.getContentRevision = function() { 236 ImageView.prototype.getContentRevision = function() {
189 return this.contentRevision_; 237 return this.contentRevision_;
190 }; 238 };
191 239
192 /** 240 /**
193 * Copies an image fragment from a full resolution canvas to a device resolution 241 * Copies an image fragment from a full resolution canvas to a device resolution
194 * canvas. 242 * canvas.
195 * 243 *
196 * @param {HTMLCanvasElement} canvas Canvas containing whole image. The canvas 244 * @param {!HTMLCanvasElement} canvas Canvas containing whole image. The canvas
197 * may not be full resolution (scaled). 245 * may not be full resolution (scaled).
198 * @param {ImageRect} imageRect Rectangle region of the canvas to be rendered. 246 * @param {!ImageRect} imageRect Rectangle region of the canvas to be rendered.
199 */ 247 */
200 ImageView.prototype.paintDeviceRect = function(canvas, imageRect) { 248 ImageView.prototype.paintDeviceRect = function(canvas, imageRect) {
201 // Map the rectangle in full resolution image to the rectangle in the device 249 // Map the rectangle in full resolution image to the rectangle in the device
202 // canvas. 250 // canvas.
203 var deviceBounds = this.viewport_.getDeviceBounds(); 251 var deviceBounds = this.viewport_.getDeviceBounds();
204 var scaleX = deviceBounds.width / canvas.width; 252 var scaleX = deviceBounds.width / canvas.width;
205 var scaleY = deviceBounds.height / canvas.height; 253 var scaleY = deviceBounds.height / canvas.height;
206 var deviceRect = new ImageRect( 254 var deviceRect = ImageRect.createWith(
207 imageRect.left * scaleX, 255 imageRect.left * scaleX,
208 imageRect.top * scaleY, 256 imageRect.top * scaleY,
209 imageRect.width * scaleX, 257 imageRect.width * scaleX,
210 imageRect.height * scaleY); 258 imageRect.height * scaleY);
211 259
212 ImageRect.drawImage( 260 ImageRect.drawImage(
213 this.screenImage_.getContext('2d'), canvas, deviceRect, imageRect); 261 this.screenImage_.getContext('2d'), canvas, deviceRect, imageRect);
214 }; 262 };
215 263
216 /** 264 /**
217 * Creates an overlay canvas with properties similar to the screen canvas. 265 * Creates an overlay canvas with properties similar to the screen canvas.
218 * Useful for showing quick feedback when editing. 266 * Useful for showing quick feedback when editing.
219 * 267 *
220 * @return {HTMLCanvasElement} Overlay canvas. 268 * @return {!HTMLCanvasElement} Overlay canvas.
221 */ 269 */
222 ImageView.prototype.createOverlayCanvas = function() { 270 ImageView.prototype.createOverlayCanvas = function() {
223 var canvas = this.document_.createElement('canvas'); 271 var canvas = assertInstanceof(this.document_.createElement('canvas'),
272 HTMLCanvasElement);
224 canvas.className = 'image'; 273 canvas.className = 'image';
225 this.container_.appendChild(canvas); 274 this.container_.appendChild(canvas);
226 return canvas; 275 return canvas;
227 }; 276 };
228 277
229 /** 278 /**
230 * Sets up the canvas as a buffer in the device resolution. 279 * Sets up the canvas as a buffer in the device resolution.
231 * 280 *
232 * @param {HTMLCanvasElement} canvas The buffer canvas. 281 * @param {!HTMLCanvasElement} canvas The buffer canvas.
233 * @return {boolean} True if the canvas needs to be rendered. 282 * @return {boolean} True if the canvas needs to be rendered.
234 */ 283 */
235 ImageView.prototype.setupDeviceBuffer = function(canvas) { 284 ImageView.prototype.setupDeviceBuffer = function(canvas) {
236 // Set the canvas position and size in device pixels. 285 // Set the canvas position and size in device pixels.
237 var deviceRect = this.viewport_.getDeviceBounds(); 286 var deviceRect = this.viewport_.getDeviceBounds();
238 var needRepaint = false; 287 var needRepaint = false;
239 if (canvas.width !== deviceRect.width) { 288 if (canvas.width !== deviceRect.width) {
240 canvas.width = deviceRect.width; 289 canvas.width = deviceRect.width;
241 needRepaint = true; 290 needRepaint = true;
242 } 291 }
243 if (canvas.height !== deviceRect.height) { 292 if (canvas.height !== deviceRect.height) {
244 canvas.height = deviceRect.height; 293 canvas.height = deviceRect.height;
245 needRepaint = true; 294 needRepaint = true;
246 } 295 }
247 296
248 // Center the image. 297 // Center the image.
249 var imageBounds = this.viewport_.getImageElementBoundsOnScreen(); 298 var imageBounds = this.viewport_.getImageElementBoundsOnScreen();
250 canvas.style.left = imageBounds.left + 'px'; 299 canvas.style.left = imageBounds.left + 'px';
251 canvas.style.top = imageBounds.top + 'px'; 300 canvas.style.top = imageBounds.top + 'px';
252 canvas.style.width = imageBounds.width + 'px'; 301 canvas.style.width = imageBounds.width + 'px';
253 canvas.style.height = imageBounds.height + 'px'; 302 canvas.style.height = imageBounds.height + 'px';
254 303
255 this.setTransform_(canvas, this.viewport_); 304 this.setTransform_(canvas, this.viewport_);
256 305
257 return needRepaint; 306 return needRepaint;
258 }; 307 };
259 308
260 /** 309 /**
261 * @return {ImageData} A new ImageData object with a copy of the content. 310 * @return {!ImageData} A new ImageData object with a copy of the content.
262 */ 311 */
263 ImageView.prototype.copyScreenImageData = function() { 312 ImageView.prototype.copyScreenImageData = function() {
264 return this.screenImage_.getContext('2d').getImageData( 313 return this.screenImage_.getContext('2d').getImageData(
265 0, 0, this.screenImage_.width, this.screenImage_.height); 314 0, 0, this.screenImage_.width, this.screenImage_.height);
266 }; 315 };
267 316
268 /** 317 /**
269 * @return {boolean} True if the image is currently being loaded. 318 * @return {boolean} True if the image is currently being loaded.
270 */ 319 */
271 ImageView.prototype.isLoading = function() { 320 ImageView.prototype.isLoading = function() {
272 return this.imageLoader_.isBusy(); 321 return this.imageLoader_.isBusy();
273 }; 322 };
274 323
275 /** 324 /**
276 * Cancels the current image loading operation. The callbacks will be ignored. 325 * Cancels the current image loading operation. The callbacks will be ignored.
277 */ 326 */
278 ImageView.prototype.cancelLoad = function() { 327 ImageView.prototype.cancelLoad = function() {
279 this.imageLoader_.cancel(); 328 this.imageLoader_.cancel();
280 }; 329 };
281 330
282 /** 331 /**
283 * Loads and display a new image. 332 * Loads and display a new image.
284 * 333 *
285 * Loads the thumbnail first, then replaces it with the main image. 334 * Loads the thumbnail first, then replaces it with the main image.
286 * Takes into account the image orientation encoded in the metadata. 335 * Takes into account the image orientation encoded in the metadata.
287 * 336 *
288 * @param {Gallery.Item} item Gallery item to be loaded. 337 * @param {!Gallery.Item} item Gallery item to be loaded.
289 * @param {!ImageView.Effect} effect Transition effect object. 338 * @param {!ImageView.Effect} effect Transition effect object.
290 * @param {function()} displayCallback Called when the image is displayed 339 * @param {function()} displayCallback Called when the image is displayed
291 * (possibly as a preview). 340 * (possibly as a preview).
292 * @param {function(number, number, *=)} loadCallback Called when the image is 341 * @param {function(ImageView.LoadType, number, *=)} loadCallback Called when
293 * fully loaded. The first parameter is the load type. 342 * the image is fully loaded. The first parameter is the load type.
294 */ 343 */
295 ImageView.prototype.load = 344 ImageView.prototype.load =
296 function(item, effect, displayCallback, loadCallback) { 345 function(item, effect, displayCallback, loadCallback) {
297 var entry = item.getEntry(); 346 var entry = item.getEntry();
298 var metadata = item.getMetadata() || {}; 347 var metadata = item.getMetadata() || {};
299 348
300 if (effect) { 349 if (!(effect instanceof ImageView.Effect.None)) {
301 // Skip effects when reloading repeatedly very quickly. 350 // Skip effects when reloading repeatedly very quickly.
302 var time = Date.now(); 351 var time = Date.now();
303 if (this.lastLoadTime_ && 352 if (this.lastLoadTime_ &&
304 (time - this.lastLoadTime_) < ImageView.FAST_SCROLL_INTERVAL) { 353 (time - this.lastLoadTime_) < ImageView.FAST_SCROLL_INTERVAL) {
305 effect = new ImageView.Effect.None(); 354 effect = new ImageView.Effect.None();
306 } 355 }
307 this.lastLoadTime_ = time; 356 this.lastLoadTime_ = time;
308 } 357 }
309 358
310 ImageUtil.metrics.startInterval(ImageUtil.getMetricName('DisplayTime')); 359 ImageUtil.metrics.startInterval(ImageUtil.getMetricName('DisplayTime'));
311 360
312 var self = this; 361 var self = this;
313 362
314 this.contentItem_ = item; 363 this.contentItem_ = item;
315 this.contentRevision_ = -1; 364 this.contentRevision_ = -1;
316 365
317 switch (ImageView.getLoadTarget(item, effect)) { 366 switch (ImageView.getLoadTarget(item, effect)) {
318 case ImageView.LoadTarget.CACHED_MAIN_IMAGE: 367 case ImageView.LoadTarget.CACHED_MAIN_IMAGE:
319 displayMainImage( 368 displayMainImage(
320 ImageView.LOAD_TYPE_CACHED_FULL, 369 ImageView.LoadType.CACHED_FULL,
321 false /* no preview */, 370 false /* no preview */,
322 assert(item.contentImage)); 371 assert(item.contentImage));
323 break; 372 break;
324 373
325 case ImageView.LoadTarget.CACHED_THUMBNAIL: 374 case ImageView.LoadTarget.CACHED_THUMBNAIL:
326 // We have a cached screen-scale canvas, use it instead of a thumbnail. 375 // We have a cached screen-scale canvas, use it instead of a thumbnail.
327 displayThumbnail(ImageView.LOAD_TYPE_CACHED_SCREEN, item.screenImage); 376 displayThumbnail(ImageView.LoadType.CACHED_SCREEN, item.screenImage);
328 // As far as the user can tell the image is loaded. We still need to load 377 // As far as the user can tell the image is loaded. We still need to load
329 // the full res image to make editing possible, but we can report now. 378 // the full res image to make editing possible, but we can report now.
330 ImageUtil.metrics.recordInterval(ImageUtil.getMetricName('DisplayTime')); 379 ImageUtil.metrics.recordInterval(ImageUtil.getMetricName('DisplayTime'));
331 break; 380 break;
332 381
333 case ImageView.LoadTarget.THUMBNAIL: 382 case ImageView.LoadTarget.THUMBNAIL:
334 var thumbnailLoader = new ThumbnailLoader( 383 var thumbnailLoader = new ThumbnailLoader(
335 entry, 384 entry,
336 ThumbnailLoader.LoaderType.CANVAS, 385 ThumbnailLoader.LoaderType.CANVAS,
337 metadata); 386 metadata);
338 thumbnailLoader.loadDetachedImage(function(success) { 387 thumbnailLoader.loadDetachedImage(function(success) {
339 displayThumbnail( 388 displayThumbnail(
340 ImageView.LOAD_TYPE_IMAGE_FILE, 389 ImageView.LoadType.IMAGE_FILE,
341 success ? thumbnailLoader.getImage() : null); 390 success ? thumbnailLoader.getImage() : null);
342 }); 391 });
343 break; 392 break;
344 393
345 case ImageView.LoadTarget.MAIN_IMAGE: 394 case ImageView.LoadTarget.MAIN_IMAGE:
346 loadMainImage( 395 loadMainImage(
347 ImageView.LOAD_TYPE_IMAGE_FILE, 396 ImageView.LoadType.IMAGE_FILE,
348 entry, 397 entry,
349 false /* no preview*/, 398 false /* no preview*/,
350 0 /* delay */); 399 0 /* delay */);
351 break; 400 break;
352 401
353 default: 402 default:
354 assertNotReached(); 403 assertNotReached();
355 } 404 }
356 405
406 /**
407 * @param {ImageView.LoadType} loadType A load type.
408 * @param {(HTMLCanvasElement|HTMLImageElement)} canvas A canvas.
409 */
357 function displayThumbnail(loadType, canvas) { 410 function displayThumbnail(loadType, canvas) {
358 if (canvas) { 411 if (canvas) {
359 var width = null; 412 var width = null;
360 var height = null; 413 var height = null;
361 if (metadata.media) { 414 if (metadata.media) {
362 width = metadata.media.width; 415 width = metadata.media.width;
363 height = metadata.media.height; 416 height = metadata.media.height;
364 } 417 }
365 // If metadata.external.present is true, the image data is loaded directly 418 // If metadata.external.present is true, the image data is loaded directly
366 // from local cache, whose size may be out of sync with the drive 419 // from local cache, whose size may be out of sync with the drive
367 // metadata. 420 // metadata.
368 if (metadata.external && !metadata.external.present) { 421 if (metadata.external && !metadata.external.present) {
369 width = metadata.external.imageWidth; 422 width = metadata.external.imageWidth;
370 height = metadata.external.imageHeight; 423 height = metadata.external.imageHeight;
371 } 424 }
372 self.replace( 425 self.replace(
373 canvas, 426 canvas,
374 effect, 427 effect,
375 width, 428 width,
376 height, 429 height,
377 true /* preview */); 430 true /* preview */);
378 if (displayCallback) displayCallback(); 431 if (displayCallback) displayCallback();
379 } 432 }
380 loadMainImage(loadType, entry, !!canvas, 433 loadMainImage(loadType, entry, !!canvas,
381 (effect && canvas) ? effect.getSafeInterval() : 0); 434 (effect && canvas) ? effect.getSafeInterval() : 0);
382 } 435 }
383 436
437 /**
438 * @param {ImageView.LoadType} loadType Load type.
439 * @param {Entry} contentEntry A content entry.
440 * @param {boolean} previewShown A preview is shown or not.
441 * @param {number} delay Load delay.
442 */
384 function loadMainImage(loadType, contentEntry, previewShown, delay) { 443 function loadMainImage(loadType, contentEntry, previewShown, delay) {
385 if (self.prefetchLoader_.isLoading(contentEntry)) { 444 if (self.prefetchLoader_.isLoading(contentEntry)) {
386 // The image we need is already being prefetched. Initiating another load 445 // The image we need is already being prefetched. Initiating another load
387 // would be a waste. Hijack the load instead by overriding the callback. 446 // would be a waste. Hijack the load instead by overriding the callback.
388 self.prefetchLoader_.setCallback( 447 self.prefetchLoader_.setCallback(
389 displayMainImage.bind(null, loadType, previewShown)); 448 displayMainImage.bind(null, loadType, previewShown));
390 449
391 // Swap the loaders so that the self.isLoading works correctly. 450 // Swap the loaders so that the self.isLoading works correctly.
392 var temp = self.prefetchLoader_; 451 var temp = self.prefetchLoader_;
393 self.prefetchLoader_ = self.imageLoader_; 452 self.prefetchLoader_ = self.imageLoader_;
394 self.imageLoader_ = temp; 453 self.imageLoader_ = temp;
395 return; 454 return;
396 } 455 }
397 self.prefetchLoader_.cancel(); // The prefetch was doing something useless. 456 self.prefetchLoader_.cancel(); // The prefetch was doing something useless.
398 457
399 self.imageLoader_.load( 458 self.imageLoader_.load(
400 item, 459 item,
401 displayMainImage.bind(null, loadType, previewShown), 460 displayMainImage.bind(null, loadType, previewShown),
402 delay); 461 delay);
403 } 462 }
404 463
405 /** 464 /**
406 * @param {number} loadType 465 * @param {ImageView.LoadType} loadType Load type.
407 * @param {boolean} previewShown 466 * @param {boolean} previewShown A preview is shown or not.
408 * @param {!HTMLCanvasElement} content 467 * @param {!(HTMLCanvasElement|HTMLImageElement)} content A content.
409 * @param {*=} opt_error 468 * @param {string=} opt_error Error message.
410 */ 469 */
411 function displayMainImage(loadType, previewShown, content, opt_error) { 470 function displayMainImage(loadType, previewShown, content, opt_error) {
412 if (opt_error) 471 if (opt_error)
413 loadType = ImageView.LOAD_TYPE_ERROR; 472 loadType = ImageView.LoadType.ERROR;
414 473
415 // If we already displayed the preview we should not replace the content if 474 // If we already displayed the preview we should not replace the content if
416 // the full content failed to load. 475 // the full content failed to load.
417 var animationDuration = 0; 476 var animationDuration = 0;
418 if (!(previewShown && loadType === ImageView.LOAD_TYPE_ERROR)) { 477 if (!(previewShown && loadType === ImageView.LoadType.ERROR)) {
419 var replaceEffect = previewShown ? null : effect; 478 var replaceEffect = previewShown ? null : effect;
420 animationDuration = replaceEffect ? replaceEffect.getSafeInterval() : 0; 479 animationDuration = replaceEffect ? replaceEffect.getSafeInterval() : 0;
421 self.replace(content, replaceEffect); 480 self.replace(content, replaceEffect);
422 if (!previewShown && displayCallback) displayCallback(); 481 if (!previewShown && displayCallback) displayCallback();
423 } 482 }
424 483
425 if (loadType !== ImageView.LOAD_TYPE_ERROR && 484 if (loadType !== ImageView.LoadType.ERROR &&
426 loadType !== ImageView.LOAD_TYPE_CACHED_SCREEN) { 485 loadType !== ImageView.LoadType.CACHED_SCREEN) {
427 ImageUtil.metrics.recordInterval(ImageUtil.getMetricName('DisplayTime')); 486 ImageUtil.metrics.recordInterval(ImageUtil.getMetricName('DisplayTime'));
428 } 487 }
429 ImageUtil.metrics.recordEnum(ImageUtil.getMetricName('LoadMode'), 488 ImageUtil.metrics.recordEnum(ImageUtil.getMetricName('LoadMode'),
430 loadType, ImageView.LOAD_TYPE_TOTAL); 489 loadType, Object.keys(ImageView.LoadType).length);
431 490
432 if (loadType === ImageView.LOAD_TYPE_ERROR && 491 if (loadType === ImageView.LoadType.ERROR &&
433 !navigator.onLine && !metadata.external.present) { 492 !navigator.onLine && !metadata.external.present) {
434 loadType = ImageView.LOAD_TYPE_OFFLINE; 493 loadType = ImageView.LoadType.OFFLINE;
435 } 494 }
436 if (loadCallback) loadCallback(loadType, animationDuration, opt_error); 495 if (loadCallback) loadCallback(loadType, animationDuration, opt_error);
437 } 496 }
438 }; 497 };
439 498
440 /** 499 /**
441 * Prefetches an image. 500 * Prefetches an image.
442 * @param {Gallery.Item} item The image item. 501 * @param {!Gallery.Item} item The image item.
443 * @param {number=} opt_delay Image load delay in ms. 502 * @param {number=} opt_delay Image load delay in ms.
444 */ 503 */
445 ImageView.prototype.prefetch = function(item, opt_delay) { 504 ImageView.prototype.prefetch = function(item, opt_delay) {
446 if (item.contentImage) 505 if (item.contentImage)
447 return; 506 return;
448 this.prefetchLoader_.load(item, function(canvas) { 507 this.prefetchLoader_.load(item, function(canvas) {
449 if (canvas.width && canvas.height && !item.contentImage) 508 if (canvas.width && canvas.height && !item.contentImage)
450 item.contentImage = canvas; 509 item.contentImage = canvas;
451 }, opt_delay); 510 }, opt_delay);
452 }; 511 };
(...skipping 16 matching lines...) Expand all
469 this.unload(null /* force unload */); 528 this.unload(null /* force unload */);
470 }.bind(this), effect.getSafeInterval()); 529 }.bind(this), effect.getSafeInterval());
471 return; 530 return;
472 } 531 }
473 this.container_.textContent = ''; 532 this.container_.textContent = '';
474 this.contentCanvas_ = null; 533 this.contentCanvas_ = null;
475 this.screenImage_ = null; 534 this.screenImage_ = null;
476 }; 535 };
477 536
478 /** 537 /**
479 * @param {HTMLCanvasElement} content The image element. 538 * @param {!(HTMLCanvasElement|HTMLImageElement)} content The image element.
480 * @param {number=} opt_width Image width. 539 * @param {number=} opt_width Image width.
481 * @param {number=} opt_height Image height. 540 * @param {number=} opt_height Image height.
482 * @param {boolean=} opt_preview True if the image is a preview (not full res). 541 * @param {boolean=} opt_preview True if the image is a preview (not full res).
483 * @private 542 * @private
484 */ 543 */
485 ImageView.prototype.replaceContent_ = function( 544 ImageView.prototype.replaceContent_ = function(
486 content, opt_width, opt_height, opt_preview) { 545 content, opt_width, opt_height, opt_preview) {
487 546
488 if (this.contentCanvas_ && this.contentCanvas_.parentNode === this.container_) 547 if (this.contentCanvas_ && this.contentCanvas_.parentNode === this.container_)
489 this.container_.removeChild(this.contentCanvas_); 548 this.container_.removeChild(this.contentCanvas_);
490 549
491 this.screenImage_ = this.document_.createElement('canvas'); 550 this.screenImage_ = assertInstanceof(this.document_.createElement('canvas'),
551 HTMLCanvasElement);
492 this.screenImage_.className = 'image'; 552 this.screenImage_.className = 'image';
493 553
494 this.contentCanvas_ = content; 554 this.contentCanvas_ = content;
495 this.invalidateCaches(); 555 this.invalidateCaches();
496 this.viewport_.setImageSize( 556 this.viewport_.setImageSize(
497 opt_width || this.contentCanvas_.width, 557 opt_width || this.contentCanvas_.width,
498 opt_height || this.contentCanvas_.height); 558 opt_height || this.contentCanvas_.height);
499 this.draw(); 559 this.draw();
500 560
501 this.container_.appendChild(this.screenImage_); 561 this.container_.appendChild(this.screenImage_);
502 562
503 this.preview_ = opt_preview; 563 this.preview_ = opt_preview || false;
504 // If this is not a thumbnail, cache the content and the screen-scale image. 564 // If this is not a thumbnail, cache the content and the screen-scale image.
505 if (this.hasValidImage()) { 565 if (this.hasValidImage()) {
506 // Insert the full resolution canvas into DOM so that it can be printed. 566 // Insert the full resolution canvas into DOM so that it can be printed.
507 this.container_.appendChild(this.contentCanvas_); 567 this.container_.appendChild(this.contentCanvas_);
508 this.contentCanvas_.classList.add('fullres'); 568 this.contentCanvas_.classList.add('fullres');
509 569
510 this.contentItem_.contentImage = this.contentCanvas_; 570 this.contentItem_.contentImage = this.contentCanvas_;
511 this.contentItem_.screenImage = this.screenImage_; 571 this.contentItem_.screenImage = this.screenImage_;
512 572
513 // TODO(kaznacheev): It is better to pass screenImage_ as it is usually 573 // TODO(kaznacheev): It is better to pass screenImage_ as it is usually
(...skipping 16 matching lines...) Expand all
530 * Adds a listener for content changes. 590 * Adds a listener for content changes.
531 * @param {function()} callback Callback. 591 * @param {function()} callback Callback.
532 */ 592 */
533 ImageView.prototype.addContentCallback = function(callback) { 593 ImageView.prototype.addContentCallback = function(callback) {
534 this.contentCallbacks_.push(callback); 594 this.contentCallbacks_.push(callback);
535 }; 595 };
536 596
537 /** 597 /**
538 * Updates the cached thumbnail image. 598 * Updates the cached thumbnail image.
539 * 599 *
540 * @param {HTMLCanvasElement} canvas The source canvas. 600 * @param {!HTMLCanvasElement} canvas The source canvas.
541 * @private 601 * @private
542 */ 602 */
543 ImageView.prototype.updateThumbnail_ = function(canvas) { 603 ImageView.prototype.updateThumbnail_ = function(canvas) {
544 ImageUtil.trace.resetTimer('thumb'); 604 ImageUtil.trace.resetTimer('thumb');
545 var pixelCount = 10000; 605 var pixelCount = 10000;
546 var downScale = 606 var downScale =
547 Math.max(1, Math.sqrt(canvas.width * canvas.height / pixelCount)); 607 Math.max(1, Math.sqrt(canvas.width * canvas.height / pixelCount));
548 608
549 this.thumbnailCanvas_ = canvas.ownerDocument.createElement('canvas'); 609 this.thumbnailCanvas_ = canvas.ownerDocument.createElement('canvas');
550 this.thumbnailCanvas_.width = Math.round(canvas.width / downScale); 610 this.thumbnailCanvas_.width = Math.round(canvas.width / downScale);
551 this.thumbnailCanvas_.height = Math.round(canvas.height / downScale); 611 this.thumbnailCanvas_.height = Math.round(canvas.height / downScale);
552 ImageRect.drawImage(this.thumbnailCanvas_.getContext('2d'), canvas); 612 ImageRect.drawImage(this.thumbnailCanvas_.getContext('2d'), canvas);
553 ImageUtil.trace.reportTimer('thumb'); 613 ImageUtil.trace.reportTimer('thumb');
554 }; 614 };
555 615
556 /** 616 /**
557 * Replaces the displayed image, possibly with slide-in animation. 617 * Replaces the displayed image, possibly with slide-in animation.
558 * 618 *
559 * @param {HTMLCanvasElement} content The image element. 619 * @param {!(HTMLCanvasElement|HTMLImageElement)} content The image element.
560 * @param {Object=} opt_effect Transition effect object. 620 * @param {ImageView.Effect=} opt_effect Transition effect object.
561 * @param {number=} opt_width Image width. 621 * @param {number=} opt_width Image width.
562 * @param {number=} opt_height Image height. 622 * @param {number=} opt_height Image height.
563 * @param {boolean=} opt_preview True if the image is a preview (not full res). 623 * @param {boolean=} opt_preview True if the image is a preview (not full res).
564 */ 624 */
565 ImageView.prototype.replace = function( 625 ImageView.prototype.replace = function(
566 content, opt_effect, opt_width, opt_height, opt_preview) { 626 content, opt_effect, opt_width, opt_height, opt_preview) {
567 var oldScreenImage = this.screenImage_; 627 var oldScreenImage = this.screenImage_;
568 var oldViewport = this.viewport_.clone(); 628 var oldViewport = this.viewport_.clone();
569 629
570 this.replaceContent_(content, opt_width, opt_height, opt_preview); 630 this.replaceContent_(content, opt_width, opt_height, opt_preview);
571 if (!opt_effect) { 631 if (!opt_effect) {
572 if (oldScreenImage) 632 if (oldScreenImage)
573 oldScreenImage.parentNode.removeChild(oldScreenImage); 633 oldScreenImage.parentNode.removeChild(oldScreenImage);
574 return; 634 return;
575 } 635 }
576 636
637 assert(this.screenImage_);
577 var newScreenImage = this.screenImage_; 638 var newScreenImage = this.screenImage_;
578 this.viewport_.resetView(); 639 this.viewport_.resetView();
579 640
580 if (oldScreenImage) 641 if (oldScreenImage)
581 ImageUtil.setAttribute(newScreenImage, 'fade', true); 642 ImageUtil.setAttribute(newScreenImage, 'fade', true);
582 this.setTransform_( 643 this.setTransform_(
583 newScreenImage, this.viewport_, opt_effect, 0 /* instant */); 644 newScreenImage, this.viewport_, opt_effect, 0 /* instant */);
584 645
585 setTimeout(function() { 646 setTimeout(function() {
586 this.setTransform_( 647 this.setTransform_(
587 newScreenImage, 648 newScreenImage,
588 this.viewport_, 649 this.viewport_,
589 null, 650 null,
590 opt_effect && opt_effect.getDuration()); 651 opt_effect && opt_effect.getDuration());
591 if (oldScreenImage) { 652 if (oldScreenImage) {
592 ImageUtil.setAttribute(newScreenImage, 'fade', false); 653 ImageUtil.setAttribute(newScreenImage, 'fade', false);
593 ImageUtil.setAttribute(oldScreenImage, 'fade', true); 654 ImageUtil.setAttribute(oldScreenImage, 'fade', true);
594 console.assert(opt_effect.getReverse, 'Cannot revert an effect.');
595 var reverse = opt_effect.getReverse(); 655 var reverse = opt_effect.getReverse();
656 assert(reverse);
596 this.setTransform_(oldScreenImage, oldViewport, reverse); 657 this.setTransform_(oldScreenImage, oldViewport, reverse);
597 setTimeout(function() { 658 setTimeout(function() {
598 if (oldScreenImage.parentNode) 659 if (oldScreenImage.parentNode)
599 oldScreenImage.parentNode.removeChild(oldScreenImage); 660 oldScreenImage.parentNode.removeChild(oldScreenImage);
600 }, reverse.getSafeInterval()); 661 }, reverse.getSafeInterval());
601 } 662 }
602 }.bind(this)); 663 }.bind(this), 0);
603 }; 664 };
604 665
605 /** 666 /**
606 * @param {HTMLCanvasElement} element The element to transform. 667 * @param {!HTMLCanvasElement} element The element to transform.
607 * @param {Viewport} viewport Viewport to be used for calculating 668 * @param {!Viewport} viewport Viewport to be used for calculating
608 * transformation. 669 * transformation.
609 * @param {ImageView.Effect=} opt_effect The effect to apply. 670 * @param {ImageView.Effect=} opt_effect The effect to apply.
610 * @param {number=} opt_duration Transition duration. 671 * @param {number=} opt_duration Transition duration.
611 * @private 672 * @private
612 */ 673 */
613 ImageView.prototype.setTransform_ = function( 674 ImageView.prototype.setTransform_ = function(
614 element, viewport, opt_effect, opt_duration) { 675 element, viewport, opt_effect, opt_duration) {
615 if (!opt_effect) 676 if (!opt_effect)
616 opt_effect = new ImageView.Effect.None(); 677 opt_effect = new ImageView.Effect.None();
617 if (typeof opt_duration !== 'number') 678 if (typeof opt_duration !== 'number')
618 opt_duration = opt_effect.getDuration(); 679 opt_duration = opt_effect.getDuration();
619 element.style.webkitTransitionDuration = opt_duration + 'ms'; 680 element.style.webkitTransitionDuration = opt_duration + 'ms';
620 element.style.webkitTransitionTimingFunction = opt_effect.getTiming(); 681 element.style.webkitTransitionTimingFunction = opt_effect.getTiming();
621 element.style.webkitTransform = opt_effect.transform(element, viewport); 682 element.style.webkitTransform = opt_effect.transform(element, viewport);
622 }; 683 };
623 684
624 /** 685 /**
625 * @param {ImageRect} screenRect Target rectangle in screen coordinates. 686 * Creates zoom effect object.
687 * @param {!ImageRect} screenRect Target rectangle in screen coordinates.
626 * @return {!ImageView.Effect} Zoom effect object. 688 * @return {!ImageView.Effect} Zoom effect object.
627 */ 689 */
628 ImageView.prototype.createZoomEffect = function(screenRect) { 690 ImageView.prototype.createZoomEffect = function(screenRect) {
629 return new ImageView.Effect.ZoomToScreen( 691 return new ImageView.Effect.ZoomToScreen(
630 screenRect, 692 screenRect,
631 ImageView.MODE_TRANSITION_DURATION); 693 ImageView.MODE_TRANSITION_DURATION);
632 }; 694 };
633 695
634 /** 696 /**
635 * Visualizes crop or rotate operation. Hide the old image instantly, animate 697 * Visualizes crop or rotate operation. Hide the old image instantly, animate
636 * the new image to visualize the operation. 698 * the new image to visualize the operation.
637 * 699 *
638 * @param {HTMLCanvasElement} canvas New content canvas. 700 * @param {!HTMLCanvasElement} canvas New content canvas.
639 * @param {ImageRect} imageCropRect The crop rectangle in image coordinates. 701 * @param {!ImageRect} imageCropRect The crop rectangle in image coordinates.
640 * Null for rotation operations. 702 * Null for rotation operations.
641 * @param {number} rotate90 Rotation angle in 90 degree increments. 703 * @param {number} rotate90 Rotation angle in 90 degree increments.
642 * @return {number} Animation duration. 704 * @return {number} Animation duration.
643 */ 705 */
644 ImageView.prototype.replaceAndAnimate = function( 706 ImageView.prototype.replaceAndAnimate = function(
645 canvas, imageCropRect, rotate90) { 707 canvas, imageCropRect, rotate90) {
708 assert(this.screenImage_);
709
646 var oldImageBounds = { 710 var oldImageBounds = {
647 width: this.viewport_.getImageBounds().width, 711 width: this.viewport_.getImageBounds().width,
648 height: this.viewport_.getImageBounds().height 712 height: this.viewport_.getImageBounds().height
649 }; 713 };
650 var oldScreenImage = this.screenImage_; 714 var oldScreenImage = this.screenImage_;
651 this.replaceContent_(canvas); 715 this.replaceContent_(canvas);
652 var newScreenImage = this.screenImage_; 716 var newScreenImage = this.screenImage_;
653 var effect = rotate90 ? 717 var effect = rotate90 ?
654 new ImageView.Effect.Rotate(rotate90 > 0) : 718 new ImageView.Effect.Rotate(rotate90 > 0) :
655 new ImageView.Effect.Zoom( 719 new ImageView.Effect.Zoom(
(...skipping 10 matching lines...) Expand all
666 this, newScreenImage, this.viewport_, null, effect.getDuration()), 730 this, newScreenImage, this.viewport_, null, effect.getDuration()),
667 0); 731 0);
668 732
669 return effect.getSafeInterval(); 733 return effect.getSafeInterval();
670 }; 734 };
671 735
672 /** 736 /**
673 * Visualizes "undo crop". Shrink the current image to the given crop rectangle 737 * Visualizes "undo crop". Shrink the current image to the given crop rectangle
674 * while fading in the new image. 738 * while fading in the new image.
675 * 739 *
676 * @param {HTMLCanvasElement} canvas New content canvas. 740 * @param {!HTMLCanvasElement} canvas New content canvas.
677 * @param {ImageRect} imageCropRect The crop rectangle in image coordinates. 741 * @param {!ImageRect} imageCropRect The crop rectangle in image coordinates.
678 * @return {number} Animation duration. 742 * @return {number} Animation duration.
679 */ 743 */
680 ImageView.prototype.animateAndReplace = function(canvas, imageCropRect) { 744 ImageView.prototype.animateAndReplace = function(canvas, imageCropRect) {
681 var oldScreenImage = this.screenImage_; 745 var oldScreenImage = this.screenImage_;
682 this.replaceContent_(canvas); 746 this.replaceContent_(canvas);
683 var newScreenImage = this.screenImage_; 747 var newScreenImage = this.screenImage_;
684 var setFade = ImageUtil.setAttribute.bind(null, newScreenImage, 'fade'); 748 var setFade = ImageUtil.setAttribute.bind(null, newScreenImage, 'fade');
685 setFade(true); 749 setFade(true);
686 oldScreenImage.parentNode.insertBefore(newScreenImage, oldScreenImage); 750 oldScreenImage.parentNode.insertBefore(newScreenImage, oldScreenImage);
687 var effect = new ImageView.Effect.Zoom( 751 var effect = new ImageView.Effect.Zoom(
(...skipping 13 matching lines...) Expand all
701 }; 765 };
702 766
703 /* Transition effects */ 767 /* Transition effects */
704 768
705 /** 769 /**
706 * Base class for effects. 770 * Base class for effects.
707 * 771 *
708 * @param {number} duration Duration in ms. 772 * @param {number} duration Duration in ms.
709 * @param {string=} opt_timing CSS transition timing function name. 773 * @param {string=} opt_timing CSS transition timing function name.
710 * @constructor 774 * @constructor
775 * @struct
711 */ 776 */
712 ImageView.Effect = function(duration, opt_timing) { 777 ImageView.Effect = function(duration, opt_timing) {
713 this.duration_ = duration; 778 this.duration_ = duration;
714 this.timing_ = opt_timing || 'linear'; 779 this.timing_ = opt_timing || 'linear';
715 }; 780 };
716 781
717 /** 782 /**
718 * 783 * Default duration of an effect.
784 * @type {number}
785 * @const
719 */ 786 */
720 ImageView.Effect.DEFAULT_DURATION = 180; 787 ImageView.Effect.DEFAULT_DURATION = 180;
721 788
722 /** 789 /**
723 * 790 * Effect margin.
791 * @type {number}
792 * @const
724 */ 793 */
725 ImageView.Effect.MARGIN = 100; 794 ImageView.Effect.MARGIN = 100;
726 795
727 /** 796 /**
728 * @return {number} Effect duration in ms. 797 * @return {number} Effect duration in ms.
729 */ 798 */
730 ImageView.Effect.prototype.getDuration = function() { return this.duration_; }; 799 ImageView.Effect.prototype.getDuration = function() { return this.duration_; };
731 800
732 /** 801 /**
733 * @return {number} Delay in ms since the beginning of the animation after which 802 * @return {number} Delay in ms since the beginning of the animation after which
734 * it is safe to perform CPU-heavy operations without disrupting the animation. 803 * it is safe to perform CPU-heavy operations without disrupting the animation.
735 */ 804 */
736 ImageView.Effect.prototype.getSafeInterval = function() { 805 ImageView.Effect.prototype.getSafeInterval = function() {
737 return this.getDuration() + ImageView.Effect.MARGIN; 806 return this.getDuration() + ImageView.Effect.MARGIN;
738 }; 807 };
739 808
740 /** 809 /**
810 * Reverses the effect.
811 * @return {ImageView.Effect} Reversed effect. Null is returned if this
812 * is not supported in the effect.
813 */
814 ImageView.Effect.prototype.getReverse = function() {
815 return null;
816 };
817
818 /**
741 * @return {string} CSS transition timing function name. 819 * @return {string} CSS transition timing function name.
742 */ 820 */
743 ImageView.Effect.prototype.getTiming = function() { return this.timing_; }; 821 ImageView.Effect.prototype.getTiming = function() { return this.timing_; };
744 822
745 /** 823 /**
746 * Obtains the CSS transformation string of the effect. 824 * Obtains the CSS transformation string of the effect.
747 * @param {HTMLCanvasElement} element Canvas element to be applied the 825 * @param {!HTMLCanvasElement} element Canvas element to be applied the
748 * transformation. 826 * transformation.
749 * @param {Viewport} viewport Current viewport. 827 * @param {!Viewport} viewport Current viewport.
750 * @return {string} CSS transformation description. 828 * @return {string} CSS transformation description.
751 */ 829 */
752 ImageView.Effect.prototype.transform = function(element, viewport) { 830 ImageView.Effect.prototype.transform = function(element, viewport) {
753 throw new Error('Not implemented.'); 831 throw new Error('Not implemented.');
754 return '';
755 }; 832 };
756 833
757 /** 834 /**
758 * Default effect. 835 * Default effect.
759 * 836 *
760 * @constructor 837 * @constructor
761 * @extends {ImageView.Effect} 838 * @extends {ImageView.Effect}
839 * @struct
762 */ 840 */
763 ImageView.Effect.None = function() { 841 ImageView.Effect.None = function() {
764 ImageView.Effect.call(this, 0, 'easy-out'); 842 ImageView.Effect.call(this, 0, 'easy-out');
765 }; 843 };
766 844
767 /** 845 /**
768 * Inherits from ImageView.Effect. 846 * Inherits from ImageView.Effect.
769 */ 847 */
770 ImageView.Effect.None.prototype = { __proto__: ImageView.Effect.prototype }; 848 ImageView.Effect.None.prototype = { __proto__: ImageView.Effect.prototype };
771 849
772 /** 850 /**
773 * @param {HTMLCanvasElement} element Element. 851 * @param {!HTMLCanvasElement} element Element.
774 * @param {Viewport} viewport Current viewport. 852 * @param {!Viewport} viewport Current viewport.
775 * @return {string} Transform string. 853 * @return {string} Transform string.
776 */ 854 */
777 ImageView.Effect.None.prototype.transform = function(element, viewport) { 855 ImageView.Effect.None.prototype.transform = function(element, viewport) {
778 return viewport.getTransformation(); 856 return viewport.getTransformation();
779 }; 857 };
780 858
781 /** 859 /**
782 * Slide effect. 860 * Slide effect.
783 * 861 *
784 * @param {number} direction -1 for left, 1 for right. 862 * @param {number} direction -1 for left, 1 for right.
785 * @param {boolean=} opt_slow True if slow (as in slideshow). 863 * @param {boolean=} opt_slow True if slow (as in slideshow).
786 * @constructor 864 * @constructor
787 * @extends {ImageView.Effect} 865 * @extends {ImageView.Effect}
866 * @struct
788 */ 867 */
789 ImageView.Effect.Slide = function Slide(direction, opt_slow) { 868 ImageView.Effect.Slide = function Slide(direction, opt_slow) {
790 ImageView.Effect.call(this, 869 ImageView.Effect.call(this,
791 opt_slow ? 800 : ImageView.Effect.DEFAULT_DURATION, 'ease-out'); 870 opt_slow ? 800 : ImageView.Effect.DEFAULT_DURATION, 'ease-out');
792 this.direction_ = direction; 871 this.direction_ = direction;
793 this.slow_ = opt_slow; 872 this.slow_ = opt_slow;
794 this.shift_ = opt_slow ? 100 : 40; 873 this.shift_ = opt_slow ? 100 : 40;
795 if (this.direction_ < 0) this.shift_ = -this.shift_; 874 if (this.direction_ < 0) this.shift_ = -this.shift_;
796 }; 875 };
797 876
798 ImageView.Effect.Slide.prototype = { __proto__: ImageView.Effect.prototype }; 877 ImageView.Effect.Slide.prototype = { __proto__: ImageView.Effect.prototype };
799 878
800 /** 879 /**
801 * Reverses the slide effect. 880 * @override
802 * @return {ImageView.Effect.Slide} Reversed effect.
803 */ 881 */
804 ImageView.Effect.Slide.prototype.getReverse = function() { 882 ImageView.Effect.Slide.prototype.getReverse = function() {
805 return new ImageView.Effect.Slide(-this.direction_, this.slow_); 883 return new ImageView.Effect.Slide(-this.direction_, this.slow_);
806 }; 884 };
807 885
808 /** 886 /**
809 * @override 887 * @override
810 */ 888 */
811 ImageView.Effect.Slide.prototype.transform = function(element, viewport) { 889 ImageView.Effect.Slide.prototype.transform = function(element, viewport) {
812 return viewport.getShiftTransformation(this.shift_); 890 return viewport.getShiftTransformation(this.shift_);
813 }; 891 };
814 892
815 /** 893 /**
816 * Zoom effect. 894 * Zoom effect.
817 * 895 *
818 * Animates the original rectangle to the target rectangle. 896 * Animates the original rectangle to the target rectangle.
819 * 897 *
820 * @param {number} previousImageWidth Width of the full resolution image. 898 * @param {number} previousImageWidth Width of the full resolution image.
821 * @param {number} previousImageHeight Height of the full resolution image. 899 * @param {number} previousImageHeight Height of the full resolution image.
822 * @param {ImageRect} imageCropRect Crop rectangle in the full resolution image. 900 * @param {!ImageRect} imageCropRect Crop rectangle in the full resolution
901 * image.
823 * @param {number=} opt_duration Duration of the effect. 902 * @param {number=} opt_duration Duration of the effect.
824 * @constructor 903 * @constructor
825 * @extends {ImageView.Effect} 904 * @extends {ImageView.Effect}
905 * @struct
826 */ 906 */
827 ImageView.Effect.Zoom = function( 907 ImageView.Effect.Zoom = function(
828 previousImageWidth, previousImageHeight, imageCropRect, opt_duration) { 908 previousImageWidth, previousImageHeight, imageCropRect, opt_duration) {
829 ImageView.Effect.call(this, 909 ImageView.Effect.call(this,
830 opt_duration || ImageView.Effect.DEFAULT_DURATION, 'ease-out'); 910 opt_duration || ImageView.Effect.DEFAULT_DURATION, 'ease-out');
831 this.previousImageWidth_ = previousImageWidth; 911 this.previousImageWidth_ = previousImageWidth;
832 this.previousImageHeight_ = previousImageHeight; 912 this.previousImageHeight_ = previousImageHeight;
833 this.imageCropRect_ = imageCropRect; 913 this.imageCropRect_ = imageCropRect;
834 }; 914 };
835 915
836 ImageView.Effect.Zoom.prototype = { __proto__: ImageView.Effect.prototype }; 916 ImageView.Effect.Zoom.prototype = { __proto__: ImageView.Effect.prototype };
837 917
838 /** 918 /**
839 * @override 919 * @override
840 */ 920 */
841 ImageView.Effect.Zoom.prototype.transform = function(element, viewport) { 921 ImageView.Effect.Zoom.prototype.transform = function(element, viewport) {
842 return viewport.getInverseTransformForCroppedImage( 922 return viewport.getInverseTransformForCroppedImage(
843 this.previousImageWidth_, this.previousImageHeight_, this.imageCropRect_); 923 this.previousImageWidth_, this.previousImageHeight_, this.imageCropRect_);
844 }; 924 };
845 925
846 /** 926 /**
847 * Effect to zoom to a screen rectangle. 927 * Effect to zoom to a screen rectangle.
848 * 928 *
849 * @param {ImageRect} screenRect Rectangle in the application window's 929 * @param {!ImageRect} screenRect Rectangle in the application window's
850 * coordinate. 930 * coordinate.
851 * @param {number=} opt_duration Duration of effect. 931 * @param {number=} opt_duration Duration of effect.
852 * @constructor 932 * @constructor
853 * @extends {ImageView.Effect} 933 * @extends {ImageView.Effect}
934 * @struct
854 */ 935 */
855 ImageView.Effect.ZoomToScreen = function(screenRect, opt_duration) { 936 ImageView.Effect.ZoomToScreen = function(screenRect, opt_duration) {
856 ImageView.Effect.call(this, opt_duration); 937 ImageView.Effect.call(this, opt_duration ||
938 ImageView.Effect.DEFAULT_DURATION);
857 this.screenRect_ = screenRect; 939 this.screenRect_ = screenRect;
858 }; 940 };
859 941
860 ImageView.Effect.ZoomToScreen.prototype = { 942 ImageView.Effect.ZoomToScreen.prototype = {
861 __proto__: ImageView.Effect.prototype 943 __proto__: ImageView.Effect.prototype
862 }; 944 };
863 945
864 /** 946 /**
865 * @override 947 * @override
866 */ 948 */
867 ImageView.Effect.ZoomToScreen.prototype.transform = function( 949 ImageView.Effect.ZoomToScreen.prototype.transform = function(
868 element, viewport) { 950 element, viewport) {
869 return viewport.getScreenRectTransformForImage(this.screenRect_); 951 return viewport.getScreenRectTransformForImage(this.screenRect_);
870 }; 952 };
871 953
872 /** 954 /**
873 * Rotation effect. 955 * Rotation effect.
874 * 956 *
875 * @param {boolean} orientation Orientation of rotation. True is for clockwise 957 * @param {boolean} orientation Orientation of rotation. True is for clockwise
876 * and false is for counterclockwise. 958 * and false is for counterclockwise.
877 * @constructor 959 * @constructor
878 * @extends {ImageView.Effect} 960 * @extends {ImageView.Effect}
961 * @struct
879 */ 962 */
880 ImageView.Effect.Rotate = function(orientation) { 963 ImageView.Effect.Rotate = function(orientation) {
881 ImageView.Effect.call(this, ImageView.Effect.DEFAULT_DURATION); 964 ImageView.Effect.call(this, ImageView.Effect.DEFAULT_DURATION);
882 this.orientation_ = orientation; 965 this.orientation_ = orientation;
883 }; 966 };
884 967
885 ImageView.Effect.Rotate.prototype = { __proto__: ImageView.Effect.prototype }; 968 ImageView.Effect.Rotate.prototype = { __proto__: ImageView.Effect.prototype };
886 969
887 /** 970 /**
888 * @override 971 * @override
889 */ 972 */
890 ImageView.Effect.Rotate.prototype.transform = function(element, viewport) { 973 ImageView.Effect.Rotate.prototype.transform = function(element, viewport) {
891 return viewport.getInverseTransformForRotatedImage(this.orientation_); 974 return viewport.getInverseTransformForRotatedImage(this.orientation_);
892 }; 975 };
OLDNEW
« no previous file with comments | « ui/file_manager/gallery/js/image_editor/image_util.js ('k') | ui/file_manager/gallery/js/slide_mode.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698