Index: chrome/browser/resources/file_manager/js/image_editor/commands.js |
diff --git a/chrome/browser/resources/file_manager/js/image_editor/commands.js b/chrome/browser/resources/file_manager/js/image_editor/commands.js |
deleted file mode 100644 |
index f05f0f227d67d0079a5048a726676c93af755194..0000000000000000000000000000000000000000 |
--- a/chrome/browser/resources/file_manager/js/image_editor/commands.js |
+++ /dev/null |
@@ -1,455 +0,0 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-'use strict'; |
- |
-/** |
- * Command queue is the only way to modify images. |
- * Supports undo/redo. |
- * Command execution is asynchronous (callback-based). |
- * |
- * @param {Document} document Document to create canvases in. |
- * @param {HTMLCanvasElement} canvas The canvas with the original image. |
- * @param {function(callback)} saveFunction Function to save the image. |
- * @constructor |
- */ |
-function CommandQueue(document, canvas, saveFunction) { |
- this.document_ = document; |
- this.undo_ = []; |
- this.redo_ = []; |
- this.subscribers_ = []; |
- this.currentImage_ = canvas; |
- |
- // Current image may be null or not-null but with width = height = 0. |
- // Copying an image with zero dimensions causes js errors. |
- if (this.currentImage_) { |
- this.baselineImage_ = document.createElement('canvas'); |
- this.baselineImage_.width = this.currentImage_.width; |
- this.baselineImage_.height = this.currentImage_.height; |
- if (this.currentImage_.width > 0 && this.currentImage_.height > 0) { |
- var context = this.baselineImage_.getContext('2d'); |
- context.drawImage(this.currentImage_, 0, 0); |
- } |
- } else { |
- this.baselineImage_ = null; |
- } |
- |
- this.previousImage_ = document.createElement('canvas'); |
- this.previousImageAvailable_ = false; |
- |
- this.saveFunction_ = saveFunction; |
- this.busy_ = false; |
- this.UIContext_ = {}; |
-} |
- |
-/** |
- * Attach the UI elements to the command queue. |
- * Once the UI is attached the results of image manipulations are displayed. |
- * |
- * @param {ImageView} imageView The ImageView object to display the results. |
- * @param {ImageEditor.Prompt} prompt Prompt to use with this CommandQueue. |
- * @param {function(boolean)} lock Function to enable/disable buttons etc. |
- */ |
-CommandQueue.prototype.attachUI = function(imageView, prompt, lock) { |
- this.UIContext_ = { |
- imageView: imageView, |
- prompt: prompt, |
- lock: lock |
- }; |
-}; |
- |
-/** |
- * Execute the action when the queue is not busy. |
- * @param {function} callback Callback. |
- */ |
-CommandQueue.prototype.executeWhenReady = function(callback) { |
- if (this.isBusy()) |
- this.subscribers_.push(callback); |
- else |
- setTimeout(callback, 0); |
-}; |
- |
-/** |
- * @return {boolean} True if the command queue is busy. |
- */ |
-CommandQueue.prototype.isBusy = function() { return this.busy_ }; |
- |
-/** |
- * Set the queue state to busy. Lock the UI. |
- * @private |
- */ |
-CommandQueue.prototype.setBusy_ = function() { |
- if (this.busy_) |
- throw new Error('CommandQueue already busy'); |
- |
- this.busy_ = true; |
- |
- if (this.UIContext_.lock) |
- this.UIContext_.lock(true); |
- |
- ImageUtil.trace.resetTimer('command-busy'); |
-}; |
- |
-/** |
- * Set the queue state to not busy. Unlock the UI and execute pending actions. |
- * @private |
- */ |
-CommandQueue.prototype.clearBusy_ = function() { |
- if (!this.busy_) |
- throw new Error('Inconsistent CommandQueue already not busy'); |
- |
- this.busy_ = false; |
- |
- // Execute the actions requested while the queue was busy. |
- while (this.subscribers_.length) |
- this.subscribers_.shift()(); |
- |
- if (this.UIContext_.lock) |
- this.UIContext_.lock(false); |
- |
- ImageUtil.trace.reportTimer('command-busy'); |
-}; |
- |
-/** |
- * Commit the image change: save and unlock the UI. |
- * @param {number=} opt_delay Delay in ms (to avoid disrupting the animation). |
- * @private |
- */ |
-CommandQueue.prototype.commit_ = function(opt_delay) { |
- setTimeout(this.saveFunction_.bind(null, this.clearBusy_.bind(this)), |
- opt_delay || 0); |
-}; |
- |
-/** |
- * Internal function to execute the command in a given context. |
- * |
- * @param {Command} command The command to execute. |
- * @param {Object} uiContext The UI context. |
- * @param {function} callback Completion callback. |
- * @private |
- */ |
-CommandQueue.prototype.doExecute_ = function(command, uiContext, callback) { |
- if (!this.currentImage_) |
- throw new Error('Cannot operate on null image'); |
- |
- // Remember one previous image so that the first undo is as fast as possible. |
- this.previousImage_.width = this.currentImage_.width; |
- this.previousImage_.height = this.currentImage_.height; |
- this.previousImageAvailable_ = true; |
- var context = this.previousImage_.getContext('2d'); |
- context.drawImage(this.currentImage_, 0, 0); |
- |
- command.execute( |
- this.document_, |
- this.currentImage_, |
- function(result, opt_delay) { |
- this.currentImage_ = result; |
- callback(opt_delay); |
- }.bind(this), |
- uiContext); |
-}; |
- |
-/** |
- * Executes the command. |
- * |
- * @param {Command} command Command to execute. |
- * @param {boolean=} opt_keep_redo True if redo stack should not be cleared. |
- */ |
-CommandQueue.prototype.execute = function(command, opt_keep_redo) { |
- this.setBusy_(); |
- |
- if (!opt_keep_redo) |
- this.redo_ = []; |
- |
- this.undo_.push(command); |
- |
- this.doExecute_(command, this.UIContext_, this.commit_.bind(this)); |
-}; |
- |
-/** |
- * @return {boolean} True if Undo is applicable. |
- */ |
-CommandQueue.prototype.canUndo = function() { |
- return this.undo_.length != 0; |
-}; |
- |
-/** |
- * Undo the most recent command. |
- */ |
-CommandQueue.prototype.undo = function() { |
- if (!this.canUndo()) |
- throw new Error('Cannot undo'); |
- |
- this.setBusy_(); |
- |
- var command = this.undo_.pop(); |
- this.redo_.push(command); |
- |
- var self = this; |
- |
- function complete() { |
- var delay = command.revertView( |
- self.currentImage_, self.UIContext_.imageView); |
- self.commit_(delay); |
- } |
- |
- if (this.previousImageAvailable_) { |
- // First undo after an execute call. |
- this.currentImage_.width = this.previousImage_.width; |
- this.currentImage_.height = this.previousImage_.height; |
- var context = this.currentImage_.getContext('2d'); |
- context.drawImage(this.previousImage_, 0, 0); |
- |
- // Free memory. |
- this.previousImage_.width = 0; |
- this.previousImage_.height = 0; |
- this.previousImageAvailable_ = false; |
- |
- complete(); |
- // TODO(kaznacheev) Consider recalculating previousImage_ right here |
- // by replaying the commands in the background. |
- } else { |
- this.currentImage_.width = this.baselineImage_.width; |
- this.currentImage_.height = this.baselineImage_.height; |
- var context = this.currentImage_.getContext('2d'); |
- context.drawImage(this.baselineImage_, 0, 0); |
- |
- var replay = function(index) { |
- if (index < self.undo_.length) |
- self.doExecute_(self.undo_[index], {}, replay.bind(null, index + 1)); |
- else { |
- complete(); |
- } |
- }; |
- |
- replay(0); |
- } |
-}; |
- |
-/** |
- * @return {boolean} True if Redo is applicable. |
- */ |
-CommandQueue.prototype.canRedo = function() { |
- return this.redo_.length != 0; |
-}; |
- |
-/** |
- * Repeat the command that was recently un-done. |
- */ |
-CommandQueue.prototype.redo = function() { |
- if (!this.canRedo()) |
- throw new Error('Cannot redo'); |
- |
- this.execute(this.redo_.pop(), true); |
-}; |
- |
-/** |
- * Closes internal buffers. Call to ensure, that internal buffers are freed |
- * as soon as possible. |
- */ |
-CommandQueue.prototype.close = function() { |
- // Free memory used by the undo buffer. |
- this.previousImage_.width = 0; |
- this.previousImage_.height = 0; |
- this.previousImageAvailable_ = false; |
- |
- if (this.baselineImage_) { |
- this.baselineImage_.width = 0; |
- this.baselineImage_.height = 0; |
- } |
-}; |
- |
-/** |
- * Command object encapsulates an operation on an image and a way to visualize |
- * its result. |
- * |
- * @param {string} name Command name. |
- * @constructor |
- */ |
-function Command(name) { |
- this.name_ = name; |
-} |
- |
-/** |
- * @return {string} String representation of the command. |
- */ |
-Command.prototype.toString = function() { |
- return 'Command ' + this.name_; |
-}; |
- |
-/** |
- * Execute the command and visualize its results. |
- * |
- * The two actions are combined into one method because sometimes it is nice |
- * to be able to show partial results for slower operations. |
- * |
- * @param {Document} document Document on which to execute command. |
- * @param {HTMLCanvasElement} srcCanvas Canvas to execute on. |
- * @param {function(HTMLCanvasElement, number)} callback Callback to call on |
- * completion. |
- * @param {Object} uiContext Context to work in. |
- */ |
-Command.prototype.execute = function(document, srcCanvas, callback, uiContext) { |
- console.error('Command.prototype.execute not implemented'); |
-}; |
- |
-/** |
- * Visualize reversion of the operation. |
- * |
- * @param {HTMLCanvasElement} canvas Image data to use. |
- * @param {ImageView} imageView ImageView to revert. |
- * @return {number} Animation duration in ms. |
- */ |
-Command.prototype.revertView = function(canvas, imageView) { |
- imageView.replace(canvas); |
- return 0; |
-}; |
- |
-/** |
- * Creates canvas to render on. |
- * |
- * @param {Document} document Document to create canvas in. |
- * @param {HTMLCanvasElement} srcCanvas to copy optional dimensions from. |
- * @param {number=} opt_width new canvas width. |
- * @param {number=} opt_height new canvas height. |
- * @return {HTMLCanvasElement} Newly created canvas. |
- * @private |
- */ |
-Command.prototype.createCanvas_ = function( |
- document, srcCanvas, opt_width, opt_height) { |
- var result = document.createElement('canvas'); |
- result.width = opt_width || srcCanvas.width; |
- result.height = opt_height || srcCanvas.height; |
- return result; |
-}; |
- |
- |
-/** |
- * Rotate command |
- * @param {number} rotate90 Rotation angle in 90 degree increments (signed). |
- * @constructor |
- * @extends {Command} |
- */ |
-Command.Rotate = function(rotate90) { |
- Command.call(this, 'rotate(' + rotate90 * 90 + 'deg)'); |
- this.rotate90_ = rotate90; |
-}; |
- |
-Command.Rotate.prototype = { __proto__: Command.prototype }; |
- |
-/** @override */ |
-Command.Rotate.prototype.execute = function( |
- document, srcCanvas, callback, uiContext) { |
- var result = this.createCanvas_( |
- document, |
- srcCanvas, |
- (this.rotate90_ & 1) ? srcCanvas.height : srcCanvas.width, |
- (this.rotate90_ & 1) ? srcCanvas.width : srcCanvas.height); |
- ImageUtil.drawImageTransformed( |
- result, srcCanvas, 1, 1, this.rotate90_ * Math.PI / 2); |
- var delay; |
- if (uiContext.imageView) { |
- delay = uiContext.imageView.replaceAndAnimate(result, null, this.rotate90_); |
- } |
- setTimeout(callback, 0, result, delay); |
-}; |
- |
-/** @override */ |
-Command.Rotate.prototype.revertView = function(canvas, imageView) { |
- return imageView.replaceAndAnimate(canvas, null, -this.rotate90_); |
-}; |
- |
- |
-/** |
- * Crop command. |
- * |
- * @param {Rect} imageRect Crop rectangle in image coordinates. |
- * @constructor |
- * @extends {Command} |
- */ |
-Command.Crop = function(imageRect) { |
- Command.call(this, 'crop' + imageRect.toString()); |
- this.imageRect_ = imageRect; |
-}; |
- |
-Command.Crop.prototype = { __proto__: Command.prototype }; |
- |
-/** @override */ |
-Command.Crop.prototype.execute = function( |
- document, srcCanvas, callback, uiContext) { |
- var result = this.createCanvas_( |
- document, srcCanvas, this.imageRect_.width, this.imageRect_.height); |
- Rect.drawImage(result.getContext('2d'), srcCanvas, null, this.imageRect_); |
- var delay; |
- if (uiContext.imageView) { |
- delay = uiContext.imageView.replaceAndAnimate(result, this.imageRect_, 0); |
- } |
- setTimeout(callback, 0, result, delay); |
-}; |
- |
-/** @override */ |
-Command.Crop.prototype.revertView = function(canvas, imageView) { |
- return imageView.animateAndReplace(canvas, this.imageRect_); |
-}; |
- |
- |
-/** |
- * Filter command. |
- * |
- * @param {string} name Command name. |
- * @param {function(ImageData,ImageData,number,number)} filter Filter function. |
- * @param {string} message Message to display when done. |
- * @constructor |
- * @extends {Command} |
- */ |
-Command.Filter = function(name, filter, message) { |
- Command.call(this, name); |
- this.filter_ = filter; |
- this.message_ = message; |
-}; |
- |
-Command.Filter.prototype = { __proto__: Command.prototype }; |
- |
-/** @override */ |
-Command.Filter.prototype.execute = function( |
- document, srcCanvas, callback, uiContext) { |
- var result = this.createCanvas_(document, srcCanvas); |
- |
- var self = this; |
- |
- var previousRow = 0; |
- |
- function onProgressVisible(updatedRow, rowCount) { |
- if (updatedRow == rowCount) { |
- uiContext.imageView.replace(result); |
- if (self.message_) |
- uiContext.prompt.show(self.message_, 2000); |
- callback(result); |
- } else { |
- var viewport = uiContext.imageView.viewport_; |
- |
- var imageStrip = new Rect(viewport.getImageBounds()); |
- imageStrip.top = previousRow; |
- imageStrip.height = updatedRow - previousRow; |
- |
- var screenStrip = new Rect(viewport.getImageBoundsOnScreen()); |
- screenStrip.top = Math.round(viewport.imageToScreenY(previousRow)); |
- screenStrip.height = |
- Math.round(viewport.imageToScreenY(updatedRow)) - screenStrip.top; |
- |
- uiContext.imageView.paintDeviceRect( |
- viewport.screenToDeviceRect(screenStrip), result, imageStrip); |
- previousRow = updatedRow; |
- } |
- } |
- |
- function onProgressInvisible(updatedRow, rowCount) { |
- if (updatedRow == rowCount) { |
- callback(result); |
- } |
- } |
- |
- filter.applyByStrips(result, srcCanvas, this.filter_, |
- uiContext.imageView ? onProgressVisible : onProgressInvisible); |
-}; |