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

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

Powered by Google App Engine
This is Rietveld 408576698