Chromium Code Reviews| Index: ui/file_manager/gallery/js/image_editor/image_util.js |
| diff --git a/ui/file_manager/gallery/js/image_editor/image_util.js b/ui/file_manager/gallery/js/image_editor/image_util.js |
| index a074e1e769d831613643c0f39506f3881a543554..aa40c8c23989064379e4a9f37ad3bf624034598b 100644 |
| --- a/ui/file_manager/gallery/js/image_editor/image_util.js |
| +++ b/ui/file_manager/gallery/js/image_editor/image_util.js |
| @@ -3,12 +3,17 @@ |
| // found in the LICENSE file. |
| // Namespace object for the utilities. |
| -function ImageUtil() {} |
| +var ImageUtil = {}; |
| /** |
| * Performance trace. |
| */ |
| ImageUtil.trace = (function() { |
| + /** |
| + * Performance trace. |
| + * @constructor |
| + * @struct |
| + */ |
| function PerformanceTrace() { |
| this.lines_ = {}; |
| this.timers_ = {}; |
| @@ -74,75 +79,50 @@ ImageUtil.between = function(min, value, max) { |
| /** |
| * Rectangle class. |
| - */ |
| - |
| -/** |
| - * Rectangle constructor takes 0, 1, 2 or 4 arguments. |
| - * Supports following variants: |
| - * new ImageRect(left, top, width, height) |
| - * new ImageRect(width, height) |
| - * new ImageRect(rect) // anything with left, top, width, height. |
| - * new ImageRect(bounds) // anything with left, top, right, bottom. |
| - * new ImageRect(canvas|image) // anything with width and height. |
| - * new ImageRect() // empty rectangle. |
| + * |
| + * @param {number} left Left. |
| + * @param {number} top Top. |
| + * @param {number} width Width. |
| + * @param {number} height Height. |
| * @constructor |
| + * @struct |
| */ |
| -function ImageRect() { |
| - switch (arguments.length) { |
| - case 4: |
| - this.left = arguments[0]; |
| - this.top = arguments[1]; |
| - this.width = arguments[2]; |
| - this.height = arguments[3]; |
| - return; |
| - |
| - case 2: |
| - this.left = 0; |
| - this.top = 0; |
| - this.width = arguments[0]; |
| - this.height = arguments[1]; |
| - return; |
| - |
| - case 1: { |
| - var source = arguments[0]; |
| - if ('left' in source && 'top' in source) { |
| - this.left = source.left; |
| - this.top = source.top; |
| - if ('right' in source && 'bottom' in source) { |
| - this.width = source.right - source.left; |
| - this.height = source.bottom - source.top; |
| - return; |
| - } |
| - } else { |
| - this.left = 0; |
| - this.top = 0; |
| - } |
| - if ('width' in source && 'height' in source) { |
| - this.width = source.width; |
| - this.height = source.height; |
| - return; |
| - } |
| - break; // Fall through to the error message. |
| - } |
| - |
| - case 0: |
| - this.left = 0; |
| - this.top = 0; |
| - this.width = 0; |
| - this.height = 0; |
| - return; |
| - } |
| - console.error('Invalid ImageRect constructor arguments:', |
| - Array.apply(null, arguments)); |
| +function ImageRect(left, top, width, height) { |
| + this.left = left; |
| + this.top = top; |
| + this.width = width; |
| + this.height = height; |
| } |
| /** |
| * Creates an image rect with a canvas. |
| * @param {!HTMLCanvasElement} canvas A canvas. |
| * @return {!ImageRect} |
| + * |
| + * TODO(yawano): Since createFromImage accepts HTMLCanvasElement, delete this |
| + * method later. |
| */ |
| ImageRect.createFromCanvas = function(canvas) { |
| - return new ImageRect(canvas); |
| + return ImageRect.createFromImage(canvas); |
| +}; |
| + |
| +/** |
| + * Creates an image rect with an image or a canvas. |
| + * @param {!(HTMLImageElement|HTMLCanvasElement)} image An image or a canvas. |
| + * @return {!ImageRect} |
| + */ |
| +ImageRect.createFromImage = function(image) { |
| + return new ImageRect(0, 0, image.width, image.height); |
| +}; |
| + |
| +/** |
| + * Clone an image rect. |
| + * @param {!ImageRect} imageRect An image rect. |
| + * @return {!ImageRect} |
| + */ |
| +ImageRect.clone = function(imageRect) { |
| + return new ImageRect(imageRect.left, imageRect.top, imageRect.width, |
| + imageRect.height); |
| }; |
| /** |
| @@ -152,7 +132,8 @@ ImageRect.createFromCanvas = function(canvas) { |
| * @return {!ImageRect} |
| */ |
| ImageRect.createFromBounds = function(bound) { |
| - return new ImageRect(bound); |
| + return new ImageRect(bound.left, bound.top, |
| + bound.right - bound.left, bound.bottom - bound.top); |
| }; |
| /** |
| @@ -162,7 +143,7 @@ ImageRect.createFromBounds = function(bound) { |
| * @return {!ImageRect} |
| */ |
| ImageRect.createFromWidthAndHeight = function(width, height) { |
| - return new ImageRect(width, height); |
| + return new ImageRect(0, 0, width, height); |
| }; |
| /** |
| @@ -172,12 +153,16 @@ ImageRect.createFromWidthAndHeight = function(width, height) { |
| * @param {number} width Width. |
| * @param {number} height Height. |
| * @return {!ImageRect} |
| + * |
| + * TODO(yawano): Remove createWith calls and call constructor directly. |
| */ |
| ImageRect.createWith = function(left, top, width, height) { |
| return new ImageRect(left, top, width, height); |
| }; |
| -ImageRect.prototype = { |
| +ImageRect.prototype = /** @struct */ ({ |
| + // TODO(yawano): Change getters to methods (e.g. getRight()). |
| + |
| /** |
| * Obtains the x coordinate of right edge. The most right pixels in the |
| * rectangle are (x = right - 1) and the pixels (x = right) are not included |
| @@ -197,11 +182,11 @@ ImageRect.prototype = { |
| get bottom() { |
| return this.top + this.height; |
| } |
| -}; |
| +}); |
| /** |
| * @param {number} factor Factor to scale. |
| - * @return {ImageRect} A rectangle with every dimension scaled. |
| + * @return {!ImageRect} A rectangle with every dimension scaled. |
| */ |
| ImageRect.prototype.scale = function(factor) { |
| return new ImageRect( |
| @@ -214,7 +199,7 @@ ImageRect.prototype.scale = function(factor) { |
| /** |
| * @param {number} dx Difference in X. |
| * @param {number} dy Difference in Y. |
| - * @return {ImageRect} A rectangle shifted by (dx,dy), same size. |
| + * @return {!ImageRect} A rectangle shifted by (dx,dy), same size. |
| */ |
| ImageRect.prototype.shift = function(dx, dy) { |
| return new ImageRect(this.left + dx, this.top + dy, this.width, this.height); |
| @@ -223,7 +208,7 @@ ImageRect.prototype.shift = function(dx, dy) { |
| /** |
| * @param {number} x Coordinate of the left top corner. |
| * @param {number} y Coordinate of the left top corner. |
| - * @return {ImageRect} A rectangle with left==x and top==y, same size. |
| + * @return {!ImageRect} A rectangle with left==x and top==y, same size. |
| */ |
| ImageRect.prototype.moveTo = function(x, y) { |
| return new ImageRect(x, y, this.width, this.height); |
| @@ -250,7 +235,7 @@ ImageRect.prototype.inside = function(x, y) { |
| }; |
| /** |
| - * @param {ImageRect} rect Rectangle to check. |
| + * @param {!ImageRect} rect Rectangle to check. |
| * @return {boolean} True if this rectangle intersects with the |rect|. |
| */ |
| ImageRect.prototype.intersects = function(rect) { |
| @@ -261,7 +246,7 @@ ImageRect.prototype.intersects = function(rect) { |
| }; |
| /** |
| - * @param {ImageRect} rect Rectangle to check. |
| + * @param {!ImageRect} rect Rectangle to check. |
| * @return {boolean} True if this rectangle containing the |rect|. |
| */ |
| ImageRect.prototype.contains = function(rect) { |
| @@ -281,11 +266,11 @@ ImageRect.prototype.isEmpty = function() { |
| /** |
| * Clamp the rectangle to the bounds by moving it. |
| * Decrease the size only if necessary. |
| - * @param {ImageRect} bounds Bounds. |
| - * @return {ImageRect} Calculated rectangle. |
| + * @param {!ImageRect} bounds Bounds. |
| + * @return {!ImageRect} Calculated rectangle. |
| */ |
| ImageRect.prototype.clamp = function(bounds) { |
| - var rect = new ImageRect(this); |
| + var rect = ImageRect.clone(this); |
| if (rect.width > bounds.width) { |
| rect.left = bounds.left; |
| @@ -323,7 +308,7 @@ ImageRect.prototype.toString = function() { |
| /** |
| * Draw the image in context with appropriate scaling. |
| - * @param {CanvasRenderingContext2D} context Context to draw. |
| + * @param {!CanvasRenderingContext2D} context Context to draw. |
| * @param {!(HTMLCanvasElement|HTMLImageElement)} image Image to draw. |
| * @param {ImageRect=} opt_dstRect Rectangle in the canvas (whole canvas by |
| * default). |
| @@ -331,8 +316,9 @@ ImageRect.prototype.toString = function() { |
| * default). |
| */ |
| ImageRect.drawImage = function(context, image, opt_dstRect, opt_srcRect) { |
| - opt_dstRect = opt_dstRect || new ImageRect(context.canvas); |
| - opt_srcRect = opt_srcRect || new ImageRect(image); |
| + opt_dstRect = opt_dstRect || |
| + ImageRect.createFromImage(assert(context.canvas)); |
| + opt_srcRect = opt_srcRect || ImageRect.createFromImage(image); |
| if (opt_dstRect.isEmpty() || opt_srcRect.isEmpty()) |
| return; |
| context.drawImage(image, |
| @@ -342,8 +328,8 @@ ImageRect.drawImage = function(context, image, opt_dstRect, opt_srcRect) { |
| /** |
| * Draw a box around the rectangle. |
| - * @param {CanvasRenderingContext2D} context Context to draw. |
| - * @param {ImageRect} rect Rectangle. |
| + * @param {!CanvasRenderingContext2D} context Context to draw. |
| + * @param {!ImageRect} rect Rectangle. |
| */ |
| ImageRect.outline = function(context, rect) { |
| context.strokeRect( |
| @@ -352,8 +338,8 @@ ImageRect.outline = function(context, rect) { |
| /** |
| * Fill the rectangle. |
| - * @param {CanvasRenderingContext2D} context Context to draw. |
| - * @param {ImageRect} rect Rectangle. |
| + * @param {!CanvasRenderingContext2D} context Context to draw. |
| + * @param {!ImageRect} rect Rectangle. |
| */ |
| ImageRect.fill = function(context, rect) { |
| context.fillRect(rect.left, rect.top, rect.width, rect.height); |
| @@ -361,9 +347,9 @@ ImageRect.fill = function(context, rect) { |
| /** |
| * Fills the space between the two rectangles. |
| - * @param {CanvasRenderingContext2D} context Context to draw. |
| - * @param {ImageRect} inner Inner rectangle. |
| - * @param {ImageRect} outer Outer rectangle. |
| + * @param {!CanvasRenderingContext2D} context Context to draw. |
| + * @param {!ImageRect} inner Inner rectangle. |
| + * @param {!ImageRect} outer Outer rectangle. |
| */ |
| ImageRect.fillBetween = function(context, inner, outer) { |
| var innerRight = inner.left + inner.width; |
| @@ -416,8 +402,8 @@ Circle.prototype.inside = function(x, y) { |
| /** |
| * Copy an image applying scaling and rotation. |
| * |
| - * @param {HTMLCanvasElement} dst Destination. |
| - * @param {HTMLCanvasElement|HTMLImageElement} src Source. |
| + * @param {!HTMLCanvasElement} dst Destination. |
| + * @param {!(HTMLCanvasElement|HTMLImageElement)} src Source. |
| * @param {number} scaleX Y scale transformation. |
| * @param {number} scaleY X scale transformation. |
| * @param {number} angle (in radians). |
| @@ -434,7 +420,7 @@ ImageUtil.drawImageTransformed = function(dst, src, scaleX, scaleY, angle) { |
| /** |
| * Adds or removes an attribute to/from an HTML element. |
| - * @param {HTMLElement} element To be applied to. |
| + * @param {!HTMLElement} element To be applied to. |
| * @param {string} attribute Name of attribute. |
| * @param {boolean} on True if add, false if remove. |
| */ |
| @@ -447,7 +433,7 @@ ImageUtil.setAttribute = function(element, attribute, on) { |
| /** |
| * Adds or removes CSS class to/from an HTML element. |
| - * @param {HTMLElement} element To be applied to. |
| + * @param {!HTMLElement} element To be applied to. |
| * @param {string} className Name of CSS class. |
| * @param {boolean} on True if add, false if remove. |
| */ |
| @@ -466,13 +452,32 @@ ImageUtil.setClass = function(element, className, on) { |
| * stripe-by-stripe to avoid freezing up the UI. The transform is taken into |
| * account. |
| * |
| - * @param {HTMLDocument} document Owner document. |
| + * @param {!HTMLDocument} document Owner document. |
| * @constructor |
| + * @struct |
| */ |
| ImageUtil.ImageLoader = function(document) { |
| this.document_ = document; |
| this.image_ = new Image(); |
| this.generation_ = 0; |
| + |
| + /** |
| + * @type {number} |
| + * @private |
| + */ |
| + this.timeout_ = 0; |
| + |
| + /** |
| + * @type {?function(!HTMLCanvasElement, string=)} |
| + * @private |
| + */ |
| + this.callback_ = null; |
| + |
| + /** |
| + * @type {FileEntry} |
| + * @private |
| + */ |
| + this.entry_ = null; |
| }; |
| /** |
| @@ -480,7 +485,7 @@ ImageUtil.ImageLoader = function(document) { |
| * TODO(mtomasz): Simplify, or even get rid of this class and merge with the |
| * ThumbnaiLoader class. |
| * |
| - * @param {Gallery.Item} item Item representing the image to be loaded. |
| + * @param {!Gallery.Item} item Item representing the image to be loaded. |
| * @param {function(!HTMLCanvasElement, string=)} callback Callback to be |
| * called when loaded. The second optional argument is an error identifier. |
| * @param {number=} opt_delay Load delay in milliseconds, useful to let the |
| @@ -495,23 +500,34 @@ ImageUtil.ImageLoader.prototype.load = function(item, callback, opt_delay) { |
| // The transform fetcher is not cancellable so we need a generation counter. |
| var generation = ++this.generation_; |
| - var onTransform = function(image, transform) { |
| + |
| + /** |
| + * @param {!HTMLImageElement} image Image to be transformed. |
| + * @param {Object=} opt_transform Transformation. |
| + */ |
| + var onTransform = function(image, opt_transform) { |
| if (generation === this.generation_) { |
| this.convertImage_( |
| - image, transform || { scaleX: 1, scaleY: 1, rotate90: 0}); |
| + image, opt_transform || { scaleX: 1, scaleY: 1, rotate90: 0}); |
| } |
| - }.bind(this); |
| + }; |
| + onTransform = onTransform.bind(this); |
| + /** |
| + * @param {string=} opt_error Error. |
| + */ |
| var onError = function(opt_error) { |
| this.image_.onerror = null; |
| this.image_.onload = null; |
| var tmpCallback = this.callback_; |
| this.callback_ = null; |
| - var emptyCanvas = this.document_.createElement('canvas'); |
| + var emptyCanvas = assertInstanceof(this.document_.createElement('canvas'), |
| + HTMLCanvasElement); |
| emptyCanvas.width = 0; |
| emptyCanvas.height = 0; |
| tmpCallback(emptyCanvas, opt_error); |
| - }.bind(this); |
| + }; |
| + onError = onError.bind(this); |
| var loadImage = function() { |
| ImageUtil.metrics.startInterval(ImageUtil.getMetricName('LoadTime')); |
| @@ -521,7 +537,10 @@ ImageUtil.ImageLoader.prototype.load = function(item, callback, opt_delay) { |
| this.image_.onerror = null; |
| this.image_.onload = null; |
| item.getFetchedMedia().then(function(fetchedMediaMetadata) { |
| - onTransform(this.image_, fetchedMediaMetadata.imageTransform); |
| + if (fetchedMediaMetadata.imageTransform) |
|
fukino
2014/12/12 02:21:03
Do we need this if statement? That is, did onTrans
yawano
2014/12/12 03:17:45
If we write it as onTransform(this.image_, fetched
fukino
2014/12/12 05:03:44
Got it.
|
| + onTransform(this.image_, fetchedMediaMetadata.imageTransform); |
| + else |
| + onTransform(this.image_); |
| }.bind(this)).catch(function(error) { |
| console.error(error.stack || error); |
| }); |
| @@ -609,7 +628,7 @@ ImageUtil.ImageLoader.prototype.cancel = function() { |
| this.callback_ = null; |
| if (this.timeout_) { |
| clearTimeout(this.timeout_); |
| - this.timeout_ = null; |
| + this.timeout_ = 0; |
| } |
| if (this.image_) { |
| this.image_.onload = function() {}; |
| @@ -620,8 +639,8 @@ ImageUtil.ImageLoader.prototype.cancel = function() { |
| }; |
| /** |
| - * @param {HTMLImageElement} image Image to be transformed. |
| - * @param {Object} transform transformation description to apply to the image. |
| + * @param {!HTMLImageElement} image Image to be transformed. |
| + * @param {!Object} transform transformation description to apply to the image. |
| * @private |
| */ |
| ImageUtil.ImageLoader.prototype.convertImage_ = function(image, transform) { |
| @@ -648,8 +667,8 @@ ImageUtil.ImageLoader.prototype.convertImage_ = function(image, transform) { |
| }; |
| /** |
| - * @param {CanvasRenderingContext2D} context Context to draw. |
| - * @param {HTMLImageElement} image Image to draw. |
| + * @param {!CanvasRenderingContext2D} context Context to draw. |
| + * @param {!HTMLImageElement} image Image to draw. |
| * @param {number} firstRow Number of the first pixel row to draw. |
| * @param {number} rowCount Count of pixel rows to draw. |
| * @private |
| @@ -678,14 +697,14 @@ ImageUtil.ImageLoader.prototype.copyStrip_ = function( |
| var self = this; |
| this.timeout_ = setTimeout( |
| function() { |
| - self.timeout_ = null; |
| + self.timeout_ = 0; |
| self.copyStrip_(context, image, lastRow, rowCount); |
| }, 0); |
| } |
| }; |
| /** |
| - * @param {HTMLElement} element To remove children from. |
| + * @param {!HTMLElement} element To remove children from. |
| */ |
| ImageUtil.removeChildren = function(element) { |
| element.textContent = ''; |
| @@ -717,7 +736,7 @@ ImageUtil.getExtensionFromFullName = function(name) { |
| /** |
| * Metrics (from metrics.js) itnitialized by the File Manager from owner frame. |
| - * @type {Object?} |
| + * @type {Object} |
| */ |
| ImageUtil.metrics = null; |
| @@ -731,5 +750,7 @@ ImageUtil.getMetricName = function(name) { |
| /** |
| * Used for metrics reporting, keep in sync with the histogram description. |
| + * @type {Array.<string>} |
| + * @const |
| */ |
| ImageUtil.FILE_TYPES = ['jpg', 'png', 'gif', 'bmp', 'webp']; |