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

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

Issue 1608143002: support animated GIF (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: add assert to pass closure compiler Created 4 years, 10 months 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 * @param {!MetadataModel} metadataModel 10 * @param {!MetadataModel} metadataModel
(...skipping 20 matching lines...) Expand all
31 this.imageLoader_ = 31 this.imageLoader_ =
32 new ImageUtil.ImageLoader(this.document_, metadataModel); 32 new ImageUtil.ImageLoader(this.document_, metadataModel);
33 // We have a separate image loader for prefetch which does not get cancelled 33 // We have a separate image loader for prefetch which does not get cancelled
34 // when the selection changes. 34 // when the selection changes.
35 this.prefetchLoader_ = 35 this.prefetchLoader_ =
36 new ImageUtil.ImageLoader(this.document_, metadataModel); 36 new ImageUtil.ImageLoader(this.document_, metadataModel);
37 37
38 this.contentCallbacks_ = []; 38 this.contentCallbacks_ = [];
39 39
40 /** 40 /**
41 * The element displaying the current content. 41 * The content image or canvas element.
42 * @type {HTMLCanvasElement}
43 * @private
44 */
45 this.screenImage_ = null;
46
47 /**
48 * The content canvas element.
49 * @type {(HTMLCanvasElement|HTMLImageElement)} 42 * @type {(HTMLCanvasElement|HTMLImageElement)}
50 * @private 43 * @private
51 */ 44 */
52 this.contentCanvas_ = null; 45 this.contentImage_ = null;
53 46
54 /** 47 /**
55 * True if the image is a preview (not full res). 48 * True if the image is a preview (not full res).
56 * @type {boolean} 49 * @type {boolean}
57 * @private 50 * @private
58 */ 51 */
59 this.preview_ = false; 52 this.preview_ = false;
60 53
61 /** 54 /**
62 * Cached thumbnail image. 55 * Cached thumbnail image.
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 165
173 /** 166 /**
174 * @override 167 * @override
175 */ 168 */
176 ImageView.prototype.getZIndex = function() { return -1; }; 169 ImageView.prototype.getZIndex = function() { return -1; };
177 170
178 /** 171 /**
179 * @override 172 * @override
180 */ 173 */
181 ImageView.prototype.draw = function() { 174 ImageView.prototype.draw = function() {
182 if (!this.contentCanvas_) // Do nothing if the image content is not set. 175 if (!this.contentImage_) // Do nothing if the image content is not set.
183 return; 176 return;
184 this.setTransform_( 177 this.setTransform_(
185 this.contentCanvas_, 178 this.contentImage_,
186 this.viewport_, 179 this.viewport_,
187 new ImageView.Effect.None(), 180 new ImageView.Effect.None(),
188 ImageView.Effect.DEFAULT_DURATION); 181 0);
189 if ((this.screenImage_ && this.setupDeviceBuffer(this.screenImage_)) ||
190 this.displayedContentGeneration_ !== this.contentGeneration_) {
191 this.displayedContentGeneration_ = this.contentGeneration_;
192 ImageUtil.trace.resetTimer('paint');
193 this.paintDeviceRect(
194 this.contentCanvas_, ImageRect.createFromImage(this.contentCanvas_));
195 ImageUtil.trace.reportTimer('paint');
196 }
197 }; 182 };
198 183
199 /** 184 /**
200 * Applies the viewport change that does not affect the screen cache size (zoom 185 * Applies the viewport change that does not affect the screen cache size (zoom
201 * change or offset change) with animation. 186 * change or offset change) with animation.
202 */ 187 */
203 ImageView.prototype.applyViewportChange = function() { 188 ImageView.prototype.applyViewportChange = function() {
204 var zooming = this.viewport_.getZoom() > 1; 189 if (this.contentImage_) {
205 if (this.contentCanvas_) {
206 // Show full resolution image only for zooming.
207 this.contentCanvas_.style.opacity = zooming ? '1' : '0';
208 this.setTransform_( 190 this.setTransform_(
209 this.contentCanvas_, 191 this.contentImage_,
210 this.viewport_, 192 this.viewport_,
211 new ImageView.Effect.None(), 193 new ImageView.Effect.None(),
212 ImageView.Effect.DEFAULT_DURATION); 194 ImageView.Effect.DEFAULT_DURATION);
213 } 195 }
214 if (this.screenImage_) {
215 this.setTransform_(
216 this.screenImage_,
217 this.viewport_,
218 new ImageView.Effect.None(),
219 ImageView.Effect.DEFAULT_DURATION);
220 }
221 }; 196 };
222 197
223 /** 198 /**
224 * @return {number} The cache generation. 199 * @return {number} The cache generation.
225 */ 200 */
226 ImageView.prototype.getCacheGeneration = function() { 201 ImageView.prototype.getCacheGeneration = function() {
227 return this.contentGeneration_; 202 return this.contentGeneration_;
228 }; 203 };
229 204
230 /** 205 /**
231 * Invalidates the caches to force redrawing the screen canvas. 206 * Invalidates the caches to force redrawing the screen canvas.
232 */ 207 */
233 ImageView.prototype.invalidateCaches = function() { 208 ImageView.prototype.invalidateCaches = function() {
234 this.contentGeneration_++; 209 this.contentGeneration_++;
235 }; 210 };
236 211
237 /** 212 /**
238 * @return {HTMLCanvasElement} The content canvas element. 213 * @return {!HTMLCanvasElement|!HTMLImageElement} The content image(or canvas).
239 */ 214 */
240 ImageView.prototype.getCanvas = function() { return this.contentCanvas_; }; 215 ImageView.prototype.getImage = function() {
216 return assert(this.contentImage_);
217 };
241 218
242 /** 219 /**
243 * @return {boolean} True if the a valid image is currently loaded. 220 * @return {boolean} True if the a valid image is currently loaded.
244 */ 221 */
245 ImageView.prototype.hasValidImage = function() { 222 ImageView.prototype.hasValidImage = function() {
246 return !!(!this.preview_ && this.contentCanvas_ && this.contentCanvas_.width); 223 return !!(!this.preview_ && this.contentImage_ && this.contentImage_.width);
247 }; 224 };
248 225
249 /** 226 /**
250 * @return {!HTMLCanvasElement} The cached thumbnail image. 227 * @return {!HTMLCanvasElement} The cached thumbnail image.
251 */ 228 */
252 ImageView.prototype.getThumbnail = function() { 229 ImageView.prototype.getThumbnail = function() {
253 assert(this.thumbnailCanvas_); 230 assert(this.thumbnailCanvas_);
254 return this.thumbnailCanvas_; 231 return this.thumbnailCanvas_;
255 }; 232 };
256 233
257 /** 234 /**
258 * @return {number} The content revision number. 235 * @return {number} The content revision number.
259 */ 236 */
260 ImageView.prototype.getContentRevision = function() { 237 ImageView.prototype.getContentRevision = function() {
261 return this.contentRevision_; 238 return this.contentRevision_;
262 }; 239 };
263 240
264 /** 241 /**
265 * Copies an image fragment from a full resolution canvas to a device resolution 242 * Copies an image fragment to a content image.
266 * canvas.
267 * 243 *
268 * @param {!HTMLCanvasElement} canvas Canvas containing whole image. The canvas 244 * @param {!HTMLCanvasElement} canvas Canvas containing whole image. The canvas
269 * may not be full resolution (scaled). 245 * may not be full resolution (scaled).
270 * @param {!ImageRect} imageRect Rectangle region of the canvas to be rendered. 246 * @param {!ImageRect} imageRect Rectangle region of the canvas to be rendered.
271 */ 247 */
272 ImageView.prototype.paintDeviceRect = function(canvas, imageRect) { 248 ImageView.prototype.paintDeviceRect = function(canvas, imageRect) {
273 // 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
274 // canvas. 250 // canvas.
251 // TODO(ryoh): Shold we prepare a device-res canvas to show?
275 var deviceBounds = this.viewport_.getDeviceBounds(); 252 var deviceBounds = this.viewport_.getDeviceBounds();
276 var scaleX = deviceBounds.width / canvas.width; 253 var scaleX = deviceBounds.width / canvas.width;
277 var scaleY = deviceBounds.height / canvas.height; 254 var scaleY = deviceBounds.height / canvas.height;
278 var deviceRect = new ImageRect( 255 var deviceRect = new ImageRect(
279 imageRect.left * scaleX, 256 imageRect.left * scaleX,
280 imageRect.top * scaleY, 257 imageRect.top * scaleY,
281 imageRect.width * scaleX, 258 imageRect.width * scaleX,
282 imageRect.height * scaleY); 259 imageRect.height * scaleY);
283 260
261 var canvas = ImageUtil.ensureCanvas(assert(this.contentImage_));
262 if (canvas !== this.contentImage_) {
263 this.replaceContent_(canvas);
264 }
284 ImageRect.drawImage( 265 ImageRect.drawImage(
285 this.screenImage_.getContext('2d'), canvas, deviceRect, imageRect); 266 this.contentImage_.getContext('2d'), canvas, deviceRect, imageRect);
286 }; 267 };
287 268
288 /** 269 /**
289 * Creates an overlay canvas with properties similar to the screen canvas. 270 * Creates an overlay canvas with properties similar to the screen canvas.
290 * Useful for showing quick feedback when editing. 271 * Useful for showing quick feedback when editing.
291 * 272 *
292 * @return {!HTMLCanvasElement} Overlay canvas. 273 * @return {!HTMLCanvasElement} Overlay canvas.
293 */ 274 */
294 ImageView.prototype.createOverlayCanvas = function() { 275 ImageView.prototype.createOverlayCanvas = function() {
295 var canvas = assertInstanceof(this.document_.createElement('canvas'), 276 var canvas = assertInstanceof(this.document_.createElement('canvas'),
(...skipping 19 matching lines...) Expand all
315 } 296 }
316 if (canvas.height !== deviceRect.height) { 297 if (canvas.height !== deviceRect.height) {
317 canvas.height = deviceRect.height; 298 canvas.height = deviceRect.height;
318 needRepaint = true; 299 needRepaint = true;
319 } 300 }
320 this.setTransform_(canvas, this.viewport_); 301 this.setTransform_(canvas, this.viewport_);
321 return needRepaint; 302 return needRepaint;
322 }; 303 };
323 304
324 /** 305 /**
325 * Gets screen image data with specified size. 306 * Gets screen image canvas with specified size.
326 * @param {number} width 307 * @param {number} width
327 * @param {number} height 308 * @param {number} height
328 * @return {!ImageData} A new ImageData object. 309 * @return {!HTMLCanvasElement} A scaled canvas.
329 */ 310 */
330 ImageView.prototype.getScreenImageDataWith = function(width, height) { 311 ImageView.prototype.getImageCanvasWith = function(width, height) {
331 // If specified size is same with current screen image size, just return it.
332 if (width === this.screenImage_.width &&
333 height === this.screenImage_.height) {
334 return this.screenImage_.getContext('2d').getImageData(
335 0, 0, this.screenImage_.width, this.screenImage_.height);
336 }
337
338 // Resize if these sizes are different. 312 // Resize if these sizes are different.
339 var resizeCanvas = document.createElement('canvas'); 313 var resizeCanvas = assertInstanceof(document.createElement('canvas'),
314 HTMLCanvasElement);
340 resizeCanvas.width = width; 315 resizeCanvas.width = width;
341 resizeCanvas.height = height; 316 resizeCanvas.height = height;
342 317
343 var context = resizeCanvas.getContext('2d'); 318 var context = resizeCanvas.getContext('2d');
344 context.drawImage(this.screenImage_, 319 context.drawImage(this.contentImage_,
345 0, 0, this.screenImage_.width, this.screenImage_.height, 320 0, 0, this.contentImage_.width, this.contentImage_.height,
346 0, 0, resizeCanvas.width, resizeCanvas.height); 321 0, 0, resizeCanvas.width, resizeCanvas.height);
347 return context.getImageData(0, 0, resizeCanvas.width, resizeCanvas.height); 322 return resizeCanvas;
348 }; 323 };
349 324
350 /** 325 /**
351 * @return {boolean} True if the image is currently being loaded. 326 * @return {boolean} True if the image is currently being loaded.
352 */ 327 */
353 ImageView.prototype.isLoading = function() { 328 ImageView.prototype.isLoading = function() {
354 return this.imageLoader_.isBusy(); 329 return this.imageLoader_.isBusy();
355 }; 330 };
356 331
357 /** 332 /**
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 509
535 /** 510 /**
536 * Unloads content. 511 * Unloads content.
537 * @param {ImageRect=} opt_zoomToRect Target rectangle for zoom-out-effect. 512 * @param {ImageRect=} opt_zoomToRect Target rectangle for zoom-out-effect.
538 */ 513 */
539 ImageView.prototype.unload = function(opt_zoomToRect) { 514 ImageView.prototype.unload = function(opt_zoomToRect) {
540 if (this.unloadTimer_) { 515 if (this.unloadTimer_) {
541 clearTimeout(this.unloadTimer_); 516 clearTimeout(this.unloadTimer_);
542 this.unloadTimer_ = null; 517 this.unloadTimer_ = null;
543 } 518 }
544 if (opt_zoomToRect && this.screenImage_) { 519 if (opt_zoomToRect && this.contentImage_) {
545 var effect = this.createZoomEffect(opt_zoomToRect); 520 var effect = this.createZoomEffect(opt_zoomToRect);
546 this.setTransform_(this.screenImage_, this.viewport_, effect); 521 this.setTransform_(this.contentImage_, this.viewport_, effect);
547 this.screenImage_.setAttribute('fade', true); 522 this.contentImage_.setAttribute('fade', true);
548 this.unloadTimer_ = setTimeout(function() { 523 this.unloadTimer_ = setTimeout(function() {
549 this.unloadTimer_ = null; 524 this.unloadTimer_ = null;
550 this.unload(null /* force unload */); 525 this.unload(null /* force unload */);
551 }.bind(this), effect.getSafeInterval()); 526 }.bind(this), effect.getSafeInterval());
552 return; 527 return;
553 } 528 }
554 this.container_.textContent = ''; 529 this.container_.textContent = '';
555 this.contentCanvas_ = null; 530 this.contentImage_ = null;
556 this.screenImage_ = null;
557 }; 531 };
558 532
559 /** 533 /**
560 * @param {!(HTMLCanvasElement|HTMLImageElement)} content The image element. 534 * @param {!(HTMLCanvasElement|HTMLImageElement)} content The image element.
561 * @param {number=} opt_width Image width. 535 * @param {number=} opt_width Image width.
562 * @param {number=} opt_height Image height. 536 * @param {number=} opt_height Image height.
563 * @param {boolean=} opt_preview True if the image is a preview (not full res). 537 * @param {boolean=} opt_preview True if the image is a preview (not full res).
564 * @private 538 * @private
565 */ 539 */
566 ImageView.prototype.replaceContent_ = function( 540 ImageView.prototype.replaceContent_ = function(
567 content, opt_width, opt_height, opt_preview) { 541 content, opt_width, opt_height, opt_preview) {
568 542
569 if (this.contentCanvas_ && this.contentCanvas_.parentNode === this.container_) 543 if (this.contentImage_ && this.contentImage_.parentNode === this.container_)
570 this.container_.removeChild(this.contentCanvas_); 544 this.container_.removeChild(this.contentImage_);
571 545
572 this.screenImage_ = assertInstanceof(this.document_.createElement('canvas'), 546 this.contentImage_ = content;
573 HTMLCanvasElement); 547 this.container_.appendChild(content);
574 this.screenImage_.className = 'image'; 548 ImageUtil.setAttribute(this.contentImage_, 'fade', false);
575
576 this.contentCanvas_ = content;
577 this.invalidateCaches(); 549 this.invalidateCaches();
578 this.viewport_.setImageSize( 550 this.viewport_.setImageSize(
579 opt_width || this.contentCanvas_.width, 551 opt_width || this.contentImage_.width,
580 opt_height || this.contentCanvas_.height); 552 opt_height || this.contentImage_.height);
581 this.draw(); 553 this.draw();
582 554
583 this.container_.appendChild(this.screenImage_);
584
585 this.preview_ = opt_preview || false; 555 this.preview_ = opt_preview || false;
586 // If this is not a thumbnail, cache the content and the screen-scale image. 556 // If this is not a thumbnail, cache the content and the screen-scale image.
587 if (this.hasValidImage()) { 557 if (this.hasValidImage()) {
588 // Insert the full resolution canvas into DOM so that it can be printed. 558 // Insert the full resolution canvas into DOM so that it can be printed.
589 this.container_.appendChild(this.contentCanvas_); 559 this.contentImage_.classList.add('image');
590 this.contentCanvas_.classList.add('fullres'); 560 this.setTransform_(this.contentImage_, this.viewport_, null, 0);
591 this.setTransform_(
592 this.contentCanvas_, this.viewport_, null, 0);
593 561
594 this.contentItem_.contentImage = this.contentCanvas_; 562 this.contentItem_.contentImage = this.contentImage_;
595 this.contentItem_.screenImage = this.screenImage_;
596 563
597 // TODO(kaznacheev): It is better to pass screenImage_ as it is usually 564 this.updateThumbnail_(this.contentImage_);
598 // much smaller than contentCanvas_ and still contains the entire image.
599 // Once we implement zoom/pan we should pass contentCanvas_ instead.
600 this.updateThumbnail_(this.screenImage_);
601 565
602 this.contentRevision_++; 566 this.contentRevision_++;
603 for (var i = 0; i !== this.contentCallbacks_.length; i++) { 567 for (var i = 0; i !== this.contentCallbacks_.length; i++) {
604 try { 568 try {
605 this.contentCallbacks_[i](); 569 this.contentCallbacks_[i]();
606 } catch (e) { 570 } catch (e) {
607 console.error(e); 571 console.error(e);
608 } 572 }
609 } 573 }
610 } 574 }
611 }; 575 };
612 576
613 /** 577 /**
614 * Adds a listener for content changes. 578 * Adds a listener for content changes.
615 * @param {function()} callback Callback. 579 * @param {function()} callback Callback.
616 */ 580 */
617 ImageView.prototype.addContentCallback = function(callback) { 581 ImageView.prototype.addContentCallback = function(callback) {
618 this.contentCallbacks_.push(callback); 582 this.contentCallbacks_.push(callback);
619 }; 583 };
620 584
621 /** 585 /**
622 * Updates the cached thumbnail image. 586 * Updates the cached thumbnail image.
623 * 587 *
624 * @param {!HTMLCanvasElement} canvas The source canvas. 588 * @param {!HTMLCanvasElement|!HTMLImageElement} image The source image or
589 * canvas.
625 * @private 590 * @private
626 */ 591 */
627 ImageView.prototype.updateThumbnail_ = function(canvas) { 592 ImageView.prototype.updateThumbnail_ = function(image) {
628 ImageUtil.trace.resetTimer('thumb'); 593 ImageUtil.trace.resetTimer('thumb');
629 var pixelCount = 10000; 594 var pixelCount = 10000;
630 var downScale = 595 var downScale =
631 Math.max(1, Math.sqrt(canvas.width * canvas.height / pixelCount)); 596 Math.max(1, Math.sqrt(image.width * image.height / pixelCount));
632 597
633 this.thumbnailCanvas_ = canvas.ownerDocument.createElement('canvas'); 598 this.thumbnailCanvas_ = image.ownerDocument.createElement('canvas');
634 this.thumbnailCanvas_.width = Math.round(canvas.width / downScale); 599 this.thumbnailCanvas_.width = Math.round(image.width / downScale);
635 this.thumbnailCanvas_.height = Math.round(canvas.height / downScale); 600 this.thumbnailCanvas_.height = Math.round(image.height / downScale);
636 ImageRect.drawImage(this.thumbnailCanvas_.getContext('2d'), canvas); 601 ImageRect.drawImage(this.thumbnailCanvas_.getContext('2d'), image);
637 ImageUtil.trace.reportTimer('thumb'); 602 ImageUtil.trace.reportTimer('thumb');
638 }; 603 };
639 604
640 /** 605 /**
641 * Replaces the displayed image, possibly with slide-in animation. 606 * Replaces the displayed image, possibly with slide-in animation.
642 * 607 *
643 * @param {!(HTMLCanvasElement|HTMLImageElement)} content The image element. 608 * @param {!(HTMLCanvasElement|HTMLImageElement)} newContentImage
609 * The image element.
644 * @param {ImageView.Effect=} opt_effect Transition effect object. 610 * @param {ImageView.Effect=} opt_effect Transition effect object.
645 * @param {number=} opt_width Image width. 611 * @param {number=} opt_width Image width.
646 * @param {number=} opt_height Image height. 612 * @param {number=} opt_height Image height.
647 * @param {boolean=} opt_preview True if the image is a preview (not full res). 613 * @param {boolean=} opt_preview True if the image is a preview (not full res).
648 */ 614 */
649 ImageView.prototype.replace = function( 615 ImageView.prototype.replace = function(
650 content, opt_effect, opt_width, opt_height, opt_preview) { 616 newContentImage, opt_effect, opt_width, opt_height, opt_preview) {
651 var oldScreenImage = this.screenImage_; 617 var oldContentImage = this.contentImage_;
652 var oldViewport = this.viewport_.clone(); 618 var oldViewport = this.viewport_.clone();
653 this.replaceContent_(content, opt_width, opt_height, opt_preview); 619 this.replaceContent_(newContentImage, opt_width, opt_height, opt_preview);
654 if (!opt_effect) { 620 if (!opt_effect) {
655 if (oldScreenImage)
656 oldScreenImage.parentNode.removeChild(oldScreenImage);
657 return; 621 return;
658 } 622 }
659 623
660 assert(this.screenImage_); 624 assert(this.contentImage_);
661 var newScreenImage = this.screenImage_;
662 this.viewport_.resetView(); 625 this.viewport_.resetView();
663 626
664 if (oldScreenImage) 627 if (oldContentImage) {
665 ImageUtil.setAttribute(newScreenImage, 'fade', true); 628 this.container_.insertBefore(oldContentImage, this.container_.firstChild);
629 ImageUtil.setAttribute(newContentImage, 'fade', true);
630 }
631
666 this.setTransform_( 632 this.setTransform_(
667 newScreenImage, this.viewport_, opt_effect, 0 /* instant */); 633 newContentImage, this.viewport_, opt_effect, 0 /* instant */);
668 this.setTransform_(
669 content, this.viewport_, opt_effect, 0 /* instant */);
670 634
671 // We need to call requestAnimationFrame twice here. The first call is for 635 // We need to call requestAnimationFrame twice here. The first call is for
672 // commiting the styles of beggining of transition that are assigned above. 636 // commiting the styles of beggining of transition that are assigned above.
673 // The second call is for assigning and commiting the styles of end of 637 // The second call is for assigning and commiting the styles of end of
674 // transition, which triggers transition animation. 638 // transition, which triggers transition animation.
675 requestAnimationFrame(function() { 639 requestAnimationFrame(function() {
676 requestAnimationFrame(function() { 640 requestAnimationFrame(function() {
677 this.setTransform_( 641 this.setTransform_(
678 newScreenImage, 642 newContentImage,
679 this.viewport_, 643 this.viewport_,
680 null, 644 null,
681 opt_effect ? opt_effect.getDuration() : undefined); 645 opt_effect ? opt_effect.getDuration() : undefined);
682 this.setTransform_( 646 if (oldContentImage) {
683 content, 647 ImageUtil.setAttribute(newContentImage, 'fade', false);
684 this.viewport_, 648 ImageUtil.setAttribute(oldContentImage, 'fade', true);
685 null,
686 opt_effect ? opt_effect.getDuration() : undefined);
687 if (oldScreenImage) {
688 ImageUtil.setAttribute(newScreenImage, 'fade', false);
689 ImageUtil.setAttribute(oldScreenImage, 'fade', true);
690 var reverse = opt_effect.getReverse(); 649 var reverse = opt_effect.getReverse();
691 if (reverse) { 650 if (reverse) {
692 this.setTransform_(oldScreenImage, oldViewport, reverse); 651 this.setTransform_(oldContentImage, oldViewport, reverse);
693 setTimeout(function() { 652 setTimeout(function() {
694 if (oldScreenImage.parentNode) 653 if (oldContentImage.parentNode)
695 oldScreenImage.parentNode.removeChild(oldScreenImage); 654 oldContentImage.parentNode.removeChild(oldContentImage);
696 }, reverse.getSafeInterval()); 655 }, reverse.getSafeInterval());
697 } else { 656 } else {
698 if (oldScreenImage.parentNode) 657 if (oldContentImage.parentNode)
699 oldScreenImage.parentNode.removeChild(oldScreenImage); 658 oldContentImage.parentNode.removeChild(oldContentImage);
700 } 659 }
701 } 660 }
702 }.bind(this)); 661 }.bind(this));
703 }.bind(this)); 662 }.bind(this));
704 }; 663 };
705 664
706 /** 665 /**
707 * @param {!HTMLCanvasElement|!HTMLImageElement} element The element to 666 * @param {!HTMLCanvasElement|!HTMLImageElement} element The element to
708 * transform. 667 * transform.
709 * @param {!Viewport} viewport Viewport to be used for calculating 668 * @param {!Viewport} viewport Viewport to be used for calculating
(...skipping 29 matching lines...) Expand all
739 * the new image to visualize the operation. 698 * the new image to visualize the operation.
740 * 699 *
741 * @param {!HTMLCanvasElement} canvas New content canvas. 700 * @param {!HTMLCanvasElement} canvas New content canvas.
742 * @param {ImageRect} imageCropRect The crop rectangle in image coordinates. 701 * @param {ImageRect} imageCropRect The crop rectangle in image coordinates.
743 * Null for rotation operations. 702 * Null for rotation operations.
744 * @param {number} rotate90 Rotation angle in 90 degree increments. 703 * @param {number} rotate90 Rotation angle in 90 degree increments.
745 * @return {number} Animation duration. 704 * @return {number} Animation duration.
746 */ 705 */
747 ImageView.prototype.replaceAndAnimate = function( 706 ImageView.prototype.replaceAndAnimate = function(
748 canvas, imageCropRect, rotate90) { 707 canvas, imageCropRect, rotate90) {
749 assert(this.screenImage_); 708 assert(this.contentImage_);
750 709
751 var oldImageBounds = { 710 var oldImageBounds = {
752 width: this.viewport_.getImageBounds().width, 711 width: this.viewport_.getImageBounds().width,
753 height: this.viewport_.getImageBounds().height 712 height: this.viewport_.getImageBounds().height
754 }; 713 };
755 var oldScreenImage = this.screenImage_; 714 var oldScreenImage = this.contentImage_;
756 this.replaceContent_(canvas); 715 this.replaceContent_(canvas);
757 var newScreenImage = this.screenImage_; 716 var newScreenImage = this.contentImage_;
758 var effect = rotate90 ? 717 var effect = rotate90 ?
759 new ImageView.Effect.Rotate(rotate90 > 0) : 718 new ImageView.Effect.Rotate(rotate90 > 0) :
760 new ImageView.Effect.Zoom( 719 new ImageView.Effect.Zoom(
761 oldImageBounds.width, oldImageBounds.height, assert(imageCropRect)); 720 oldImageBounds.width, oldImageBounds.height, assert(imageCropRect));
762 721
763 this.setTransform_(newScreenImage, this.viewport_, effect, 0 /* instant */); 722 this.setTransform_(newScreenImage, this.viewport_, effect, 0 /* instant */);
764 723
765 oldScreenImage.parentNode.appendChild(newScreenImage);
766 oldScreenImage.parentNode.removeChild(oldScreenImage);
767
768 // Let the layout fire, then animate back to non-transformed state. 724 // Let the layout fire, then animate back to non-transformed state.
769 setTimeout( 725 setTimeout(
770 this.setTransform_.bind( 726 this.setTransform_.bind(
771 this, newScreenImage, this.viewport_, null, effect.getDuration()), 727 this, newScreenImage, this.viewport_, null, effect.getDuration()),
772 0); 728 0);
773 729
774 return effect.getSafeInterval(); 730 return effect.getSafeInterval();
775 }; 731 };
776 732
777 /** 733 /**
778 * Visualizes "undo crop". Shrink the current image to the given crop rectangle 734 * Visualizes "undo crop". Shrink the current image to the given crop rectangle
779 * while fading in the new image. 735 * while fading in the new image.
780 * 736 *
781 * @param {!HTMLCanvasElement} canvas New content canvas. 737 * @param {!HTMLCanvasElement} canvas New content canvas.
782 * @param {!ImageRect} imageCropRect The crop rectangle in image coordinates. 738 * @param {!ImageRect} imageCropRect The crop rectangle in image coordinates.
783 * @return {number} Animation duration. 739 * @return {number} Animation duration.
784 */ 740 */
785 ImageView.prototype.animateAndReplace = function(canvas, imageCropRect) { 741 ImageView.prototype.animateAndReplace = function(canvas, imageCropRect) {
786 var oldScreenImage = this.screenImage_; 742 var oldScreenImage = assert(this.contentImage_);
743 oldScreenImage.style.zIndex = 1000;
787 this.replaceContent_(canvas); 744 this.replaceContent_(canvas);
788 var newScreenImage = this.screenImage_; 745 this.container_.appendChild(oldScreenImage);
789 var setFade = ImageUtil.setAttribute.bind(null, assert(newScreenImage), 746 var newScreenImage = this.contentImage_;
790 'fade'); 747 ImageUtil.setAttribute(newScreenImage, 'fade', true);
791 setFade(true);
792 oldScreenImage.parentNode.insertBefore(newScreenImage, oldScreenImage);
793 var effect = new ImageView.Effect.Zoom( 748 var effect = new ImageView.Effect.Zoom(
794 this.viewport_.getImageBounds().width, 749 this.viewport_.getImageBounds().width,
795 this.viewport_.getImageBounds().height, 750 this.viewport_.getImageBounds().height,
796 imageCropRect); 751 imageCropRect);
752 // Animate to the transformed state.
753 requestAnimationFrame(function() {
754 requestAnimationFrame(function() {
755 this.setTransform_(oldScreenImage, this.viewport_, effect);
756 ImageUtil.setAttribute(newScreenImage, 'fade', false);
757 }.bind(this));
758 }.bind(this));
797 759
798 // Animate to the transformed state.
799 this.setTransform_(oldScreenImage, this.viewport_, effect);
800 setTimeout(setFade.bind(null, false), 0);
801 setTimeout(function() { 760 setTimeout(function() {
802 if (oldScreenImage.parentNode) 761 if (oldScreenImage.parentNode)
803 oldScreenImage.parentNode.removeChild(oldScreenImage); 762 oldScreenImage.parentNode.removeChild(oldScreenImage);
763 oldScreenImage.style.zIndex = '';
804 }, effect.getSafeInterval()); 764 }, effect.getSafeInterval());
805 765
806 return effect.getSafeInterval(); 766 return effect.getSafeInterval();
807 }; 767 };
808 768
809 /* Transition effects */ 769 /* Transition effects */
810 770
811 /** 771 /**
812 * Base class for effects. 772 * Base class for effects.
813 * 773 *
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
1015 975
1016 ImageView.Effect.Rotate.prototype = { __proto__: ImageView.Effect.prototype }; 976 ImageView.Effect.Rotate.prototype = { __proto__: ImageView.Effect.prototype };
1017 977
1018 /** 978 /**
1019 * @override 979 * @override
1020 */ 980 */
1021 ImageView.Effect.Rotate.prototype.transform = function(element, viewport) { 981 ImageView.Effect.Rotate.prototype.transform = function(element, viewport) {
1022 return viewport.getRotatingTransformation( 982 return viewport.getRotatingTransformation(
1023 element.width, element.height, this.orientation_ ? -1 : 1); 983 element.width, element.height, this.orientation_ ? -1 : 1);
1024 }; 984 };
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