Index: ui/file_manager/gallery/js/image_editor/image_view.js |
diff --git a/ui/file_manager/gallery/js/image_editor/image_view.js b/ui/file_manager/gallery/js/image_editor/image_view.js |
index 5e8bffc3e88123597e85c35682cf43ef73a071ca..191ef24772f32757705bf836735fa4a3a50dd810 100644 |
--- a/ui/file_manager/gallery/js/image_editor/image_view.js |
+++ b/ui/file_manager/gallery/js/image_editor/image_view.js |
@@ -38,18 +38,11 @@ function ImageView(container, viewport, metadataModel) { |
this.contentCallbacks_ = []; |
/** |
- * The element displaying the current content. |
- * @type {HTMLCanvasElement} |
- * @private |
- */ |
- this.screenImage_ = null; |
- |
- /** |
- * The content canvas element. |
+ * The content image or canvas element. |
* @type {(HTMLCanvasElement|HTMLImageElement)} |
* @private |
*/ |
- this.contentCanvas_ = null; |
+ this.contentImage_ = null; |
/** |
* True if the image is a preview (not full res). |
@@ -179,21 +172,13 @@ ImageView.prototype.getZIndex = function() { return -1; }; |
* @override |
*/ |
ImageView.prototype.draw = function() { |
- if (!this.contentCanvas_) // Do nothing if the image content is not set. |
+ if (!this.contentImage_) // Do nothing if the image content is not set. |
return; |
this.setTransform_( |
- this.contentCanvas_, |
+ this.contentImage_, |
this.viewport_, |
new ImageView.Effect.None(), |
- ImageView.Effect.DEFAULT_DURATION); |
- if ((this.screenImage_ && this.setupDeviceBuffer(this.screenImage_)) || |
- this.displayedContentGeneration_ !== this.contentGeneration_) { |
- this.displayedContentGeneration_ = this.contentGeneration_; |
- ImageUtil.trace.resetTimer('paint'); |
- this.paintDeviceRect( |
- this.contentCanvas_, ImageRect.createFromImage(this.contentCanvas_)); |
- ImageUtil.trace.reportTimer('paint'); |
- } |
+ 0); |
}; |
/** |
@@ -201,23 +186,13 @@ ImageView.prototype.draw = function() { |
* change or offset change) with animation. |
*/ |
ImageView.prototype.applyViewportChange = function() { |
- var zooming = this.viewport_.getZoom() > 1; |
- if (this.contentCanvas_) { |
- // Show full resolution image only for zooming. |
- this.contentCanvas_.style.opacity = zooming ? '1' : '0'; |
+ if (this.contentImage_) { |
this.setTransform_( |
- this.contentCanvas_, |
+ this.contentImage_, |
this.viewport_, |
new ImageView.Effect.None(), |
ImageView.Effect.DEFAULT_DURATION); |
} |
- if (this.screenImage_) { |
- this.setTransform_( |
- this.screenImage_, |
- this.viewport_, |
- new ImageView.Effect.None(), |
- ImageView.Effect.DEFAULT_DURATION); |
- } |
}; |
/** |
@@ -235,15 +210,17 @@ ImageView.prototype.invalidateCaches = function() { |
}; |
/** |
- * @return {HTMLCanvasElement} The content canvas element. |
+ * @return {!HTMLCanvasElement|!HTMLImageElement} The content image(or canvas). |
*/ |
-ImageView.prototype.getCanvas = function() { return this.contentCanvas_; }; |
+ImageView.prototype.getImage = function() { |
+ return assert(this.contentImage_); |
+}; |
/** |
* @return {boolean} True if the a valid image is currently loaded. |
*/ |
ImageView.prototype.hasValidImage = function() { |
- return !!(!this.preview_ && this.contentCanvas_ && this.contentCanvas_.width); |
+ return !!(!this.preview_ && this.contentImage_ && this.contentImage_.width); |
}; |
/** |
@@ -262,8 +239,7 @@ ImageView.prototype.getContentRevision = function() { |
}; |
/** |
- * Copies an image fragment from a full resolution canvas to a device resolution |
- * canvas. |
+ * Copies an image fragment to a content image. |
* |
* @param {!HTMLCanvasElement} canvas Canvas containing whole image. The canvas |
* may not be full resolution (scaled). |
@@ -272,6 +248,7 @@ ImageView.prototype.getContentRevision = function() { |
ImageView.prototype.paintDeviceRect = function(canvas, imageRect) { |
// Map the rectangle in full resolution image to the rectangle in the device |
// canvas. |
+ // TODO(ryoh): Shold we prepare a device-res canvas to show? |
var deviceBounds = this.viewport_.getDeviceBounds(); |
var scaleX = deviceBounds.width / canvas.width; |
var scaleY = deviceBounds.height / canvas.height; |
@@ -281,8 +258,12 @@ ImageView.prototype.paintDeviceRect = function(canvas, imageRect) { |
imageRect.width * scaleX, |
imageRect.height * scaleY); |
+ var canvas = ImageUtil.ensureCanvas(assert(this.contentImage_)); |
+ if (canvas !== this.contentImage_) { |
+ this.replaceContent_(canvas); |
+ } |
ImageRect.drawImage( |
- this.screenImage_.getContext('2d'), canvas, deviceRect, imageRect); |
+ this.contentImage_.getContext('2d'), canvas, deviceRect, imageRect); |
}; |
/** |
@@ -322,29 +303,23 @@ ImageView.prototype.setupDeviceBuffer = function(canvas) { |
}; |
/** |
- * Gets screen image data with specified size. |
+ * Gets screen image canvas with specified size. |
* @param {number} width |
* @param {number} height |
- * @return {!ImageData} A new ImageData object. |
+ * @return {!HTMLCanvasElement} A scaled canvas. |
*/ |
-ImageView.prototype.getScreenImageDataWith = function(width, height) { |
- // If specified size is same with current screen image size, just return it. |
- if (width === this.screenImage_.width && |
- height === this.screenImage_.height) { |
- return this.screenImage_.getContext('2d').getImageData( |
- 0, 0, this.screenImage_.width, this.screenImage_.height); |
- } |
- |
+ImageView.prototype.getImageCanvasWith = function(width, height) { |
// Resize if these sizes are different. |
- var resizeCanvas = document.createElement('canvas'); |
+ var resizeCanvas = assertInstanceof(document.createElement('canvas'), |
+ HTMLCanvasElement); |
resizeCanvas.width = width; |
resizeCanvas.height = height; |
var context = resizeCanvas.getContext('2d'); |
- context.drawImage(this.screenImage_, |
- 0, 0, this.screenImage_.width, this.screenImage_.height, |
+ context.drawImage(this.contentImage_, |
+ 0, 0, this.contentImage_.width, this.contentImage_.height, |
0, 0, resizeCanvas.width, resizeCanvas.height); |
- return context.getImageData(0, 0, resizeCanvas.width, resizeCanvas.height); |
+ return resizeCanvas; |
}; |
/** |
@@ -541,10 +516,10 @@ ImageView.prototype.unload = function(opt_zoomToRect) { |
clearTimeout(this.unloadTimer_); |
this.unloadTimer_ = null; |
} |
- if (opt_zoomToRect && this.screenImage_) { |
+ if (opt_zoomToRect && this.contentImage_) { |
var effect = this.createZoomEffect(opt_zoomToRect); |
- this.setTransform_(this.screenImage_, this.viewport_, effect); |
- this.screenImage_.setAttribute('fade', true); |
+ this.setTransform_(this.contentImage_, this.viewport_, effect); |
+ this.contentImage_.setAttribute('fade', true); |
this.unloadTimer_ = setTimeout(function() { |
this.unloadTimer_ = null; |
this.unload(null /* force unload */); |
@@ -552,8 +527,7 @@ ImageView.prototype.unload = function(opt_zoomToRect) { |
return; |
} |
this.container_.textContent = ''; |
- this.contentCanvas_ = null; |
- this.screenImage_ = null; |
+ this.contentImage_ = null; |
}; |
/** |
@@ -566,38 +540,28 @@ ImageView.prototype.unload = function(opt_zoomToRect) { |
ImageView.prototype.replaceContent_ = function( |
content, opt_width, opt_height, opt_preview) { |
- if (this.contentCanvas_ && this.contentCanvas_.parentNode === this.container_) |
- this.container_.removeChild(this.contentCanvas_); |
- |
- this.screenImage_ = assertInstanceof(this.document_.createElement('canvas'), |
- HTMLCanvasElement); |
- this.screenImage_.className = 'image'; |
+ if (this.contentImage_ && this.contentImage_.parentNode === this.container_) |
+ this.container_.removeChild(this.contentImage_); |
- this.contentCanvas_ = content; |
+ this.contentImage_ = content; |
+ this.container_.appendChild(content); |
+ ImageUtil.setAttribute(this.contentImage_, 'fade', false); |
this.invalidateCaches(); |
this.viewport_.setImageSize( |
- opt_width || this.contentCanvas_.width, |
- opt_height || this.contentCanvas_.height); |
+ opt_width || this.contentImage_.width, |
+ opt_height || this.contentImage_.height); |
this.draw(); |
- this.container_.appendChild(this.screenImage_); |
- |
this.preview_ = opt_preview || false; |
// If this is not a thumbnail, cache the content and the screen-scale image. |
if (this.hasValidImage()) { |
// Insert the full resolution canvas into DOM so that it can be printed. |
- this.container_.appendChild(this.contentCanvas_); |
- this.contentCanvas_.classList.add('fullres'); |
- this.setTransform_( |
- this.contentCanvas_, this.viewport_, null, 0); |
+ this.contentImage_.classList.add('image'); |
+ this.setTransform_(this.contentImage_, this.viewport_, null, 0); |
- this.contentItem_.contentImage = this.contentCanvas_; |
- this.contentItem_.screenImage = this.screenImage_; |
+ this.contentItem_.contentImage = this.contentImage_; |
- // TODO(kaznacheev): It is better to pass screenImage_ as it is usually |
- // much smaller than contentCanvas_ and still contains the entire image. |
- // Once we implement zoom/pan we should pass contentCanvas_ instead. |
- this.updateThumbnail_(this.screenImage_); |
+ this.updateThumbnail_(this.contentImage_); |
this.contentRevision_++; |
for (var i = 0; i !== this.contentCallbacks_.length; i++) { |
@@ -621,52 +585,52 @@ ImageView.prototype.addContentCallback = function(callback) { |
/** |
* Updates the cached thumbnail image. |
* |
- * @param {!HTMLCanvasElement} canvas The source canvas. |
+ * @param {!HTMLCanvasElement|!HTMLImageElement} image The source image or |
+ * canvas. |
* @private |
*/ |
-ImageView.prototype.updateThumbnail_ = function(canvas) { |
+ImageView.prototype.updateThumbnail_ = function(image) { |
ImageUtil.trace.resetTimer('thumb'); |
var pixelCount = 10000; |
var downScale = |
- Math.max(1, Math.sqrt(canvas.width * canvas.height / pixelCount)); |
+ Math.max(1, Math.sqrt(image.width * image.height / pixelCount)); |
- this.thumbnailCanvas_ = canvas.ownerDocument.createElement('canvas'); |
- this.thumbnailCanvas_.width = Math.round(canvas.width / downScale); |
- this.thumbnailCanvas_.height = Math.round(canvas.height / downScale); |
- ImageRect.drawImage(this.thumbnailCanvas_.getContext('2d'), canvas); |
+ this.thumbnailCanvas_ = image.ownerDocument.createElement('canvas'); |
+ this.thumbnailCanvas_.width = Math.round(image.width / downScale); |
+ this.thumbnailCanvas_.height = Math.round(image.height / downScale); |
+ ImageRect.drawImage(this.thumbnailCanvas_.getContext('2d'), image); |
ImageUtil.trace.reportTimer('thumb'); |
}; |
/** |
* Replaces the displayed image, possibly with slide-in animation. |
* |
- * @param {!(HTMLCanvasElement|HTMLImageElement)} content The image element. |
+ * @param {!(HTMLCanvasElement|HTMLImageElement)} newContentImage |
+ * The image element. |
* @param {ImageView.Effect=} opt_effect Transition effect object. |
* @param {number=} opt_width Image width. |
* @param {number=} opt_height Image height. |
* @param {boolean=} opt_preview True if the image is a preview (not full res). |
*/ |
ImageView.prototype.replace = function( |
- content, opt_effect, opt_width, opt_height, opt_preview) { |
- var oldScreenImage = this.screenImage_; |
+ newContentImage, opt_effect, opt_width, opt_height, opt_preview) { |
+ var oldContentImage = this.contentImage_; |
var oldViewport = this.viewport_.clone(); |
- this.replaceContent_(content, opt_width, opt_height, opt_preview); |
+ this.replaceContent_(newContentImage, opt_width, opt_height, opt_preview); |
if (!opt_effect) { |
- if (oldScreenImage) |
- oldScreenImage.parentNode.removeChild(oldScreenImage); |
return; |
} |
- assert(this.screenImage_); |
- var newScreenImage = this.screenImage_; |
+ assert(this.contentImage_); |
this.viewport_.resetView(); |
- if (oldScreenImage) |
- ImageUtil.setAttribute(newScreenImage, 'fade', true); |
- this.setTransform_( |
- newScreenImage, this.viewport_, opt_effect, 0 /* instant */); |
+ if (oldContentImage) { |
+ this.container_.insertBefore(oldContentImage, this.container_.firstChild); |
+ ImageUtil.setAttribute(newContentImage, 'fade', true); |
+ } |
+ |
this.setTransform_( |
- content, this.viewport_, opt_effect, 0 /* instant */); |
+ newContentImage, this.viewport_, opt_effect, 0 /* instant */); |
// We need to call requestAnimationFrame twice here. The first call is for |
// commiting the styles of beggining of transition that are assigned above. |
@@ -675,28 +639,23 @@ ImageView.prototype.replace = function( |
requestAnimationFrame(function() { |
requestAnimationFrame(function() { |
this.setTransform_( |
- newScreenImage, |
- this.viewport_, |
- null, |
- opt_effect ? opt_effect.getDuration() : undefined); |
- this.setTransform_( |
- content, |
+ newContentImage, |
this.viewport_, |
null, |
opt_effect ? opt_effect.getDuration() : undefined); |
- if (oldScreenImage) { |
- ImageUtil.setAttribute(newScreenImage, 'fade', false); |
- ImageUtil.setAttribute(oldScreenImage, 'fade', true); |
+ if (oldContentImage) { |
+ ImageUtil.setAttribute(newContentImage, 'fade', false); |
+ ImageUtil.setAttribute(oldContentImage, 'fade', true); |
var reverse = opt_effect.getReverse(); |
if (reverse) { |
- this.setTransform_(oldScreenImage, oldViewport, reverse); |
+ this.setTransform_(oldContentImage, oldViewport, reverse); |
setTimeout(function() { |
- if (oldScreenImage.parentNode) |
- oldScreenImage.parentNode.removeChild(oldScreenImage); |
+ if (oldContentImage.parentNode) |
+ oldContentImage.parentNode.removeChild(oldContentImage); |
}, reverse.getSafeInterval()); |
} else { |
- if (oldScreenImage.parentNode) |
- oldScreenImage.parentNode.removeChild(oldScreenImage); |
+ if (oldContentImage.parentNode) |
+ oldContentImage.parentNode.removeChild(oldContentImage); |
} |
} |
}.bind(this)); |
@@ -746,15 +705,15 @@ ImageView.prototype.createZoomEffect = function(screenRect) { |
*/ |
ImageView.prototype.replaceAndAnimate = function( |
canvas, imageCropRect, rotate90) { |
- assert(this.screenImage_); |
+ assert(this.contentImage_); |
var oldImageBounds = { |
width: this.viewport_.getImageBounds().width, |
height: this.viewport_.getImageBounds().height |
}; |
- var oldScreenImage = this.screenImage_; |
+ var oldScreenImage = this.contentImage_; |
this.replaceContent_(canvas); |
- var newScreenImage = this.screenImage_; |
+ var newScreenImage = this.contentImage_; |
var effect = rotate90 ? |
new ImageView.Effect.Rotate(rotate90 > 0) : |
new ImageView.Effect.Zoom( |
@@ -762,9 +721,6 @@ ImageView.prototype.replaceAndAnimate = function( |
this.setTransform_(newScreenImage, this.viewport_, effect, 0 /* instant */); |
- oldScreenImage.parentNode.appendChild(newScreenImage); |
- oldScreenImage.parentNode.removeChild(oldScreenImage); |
- |
// Let the layout fire, then animate back to non-transformed state. |
setTimeout( |
this.setTransform_.bind( |
@@ -783,24 +739,28 @@ ImageView.prototype.replaceAndAnimate = function( |
* @return {number} Animation duration. |
*/ |
ImageView.prototype.animateAndReplace = function(canvas, imageCropRect) { |
- var oldScreenImage = this.screenImage_; |
+ var oldScreenImage = assert(this.contentImage_); |
+ oldScreenImage.style.zIndex = 1000; |
this.replaceContent_(canvas); |
- var newScreenImage = this.screenImage_; |
- var setFade = ImageUtil.setAttribute.bind(null, assert(newScreenImage), |
- 'fade'); |
- setFade(true); |
- oldScreenImage.parentNode.insertBefore(newScreenImage, oldScreenImage); |
+ this.container_.appendChild(oldScreenImage); |
+ var newScreenImage = this.contentImage_; |
+ ImageUtil.setAttribute(newScreenImage, 'fade', true); |
var effect = new ImageView.Effect.Zoom( |
this.viewport_.getImageBounds().width, |
this.viewport_.getImageBounds().height, |
imageCropRect); |
- |
// Animate to the transformed state. |
- this.setTransform_(oldScreenImage, this.viewport_, effect); |
- setTimeout(setFade.bind(null, false), 0); |
+ requestAnimationFrame(function() { |
+ requestAnimationFrame(function() { |
+ this.setTransform_(oldScreenImage, this.viewport_, effect); |
+ ImageUtil.setAttribute(newScreenImage, 'fade', false); |
+ }.bind(this)); |
+ }.bind(this)); |
+ |
setTimeout(function() { |
- if (oldScreenImage.parentNode) |
+ if (oldScreenImage.parentNode) |
oldScreenImage.parentNode.removeChild(oldScreenImage); |
+ oldScreenImage.style.zIndex = ''; |
}, effect.getSafeInterval()); |
return effect.getSafeInterval(); |