diff options
author | serya@google.com <serya@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-24 12:18:13 +0000 |
---|---|---|
committer | serya@google.com <serya@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-24 12:18:13 +0000 |
commit | 8bb9d51cc9eb0e39f2862085eccceed52b2705a1 (patch) | |
tree | ea98a774d7a6d26ae489498b6861d2010660fd5d | |
parent | 7263a7de49e02a258d56970c58a96494c2c00489 (diff) | |
download | chromium_src-8bb9d51cc9eb0e39f2862085eccceed52b2705a1.zip chromium_src-8bb9d51cc9eb0e39f2862085eccceed52b2705a1.tar.gz chromium_src-8bb9d51cc9eb0e39f2862085eccceed52b2705a1.tar.bz2 |
Refactoring.
Fixes presubmit warnings in image_utlis.js.
ImageEditor.Ribbon employs closure UI elemets subclassing idiom.
BUG=
TEST=
Review URL: https://chromiumcodereview.appspot.com/10444007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@138784 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/resources/file_manager/js/image_editor/gallery.js | 164 | ||||
-rw-r--r-- | chrome/browser/resources/file_manager/js/image_editor/image_util.js | 221 |
2 files changed, 271 insertions, 114 deletions
diff --git a/chrome/browser/resources/file_manager/js/image_editor/gallery.js b/chrome/browser/resources/file_manager/js/image_editor/gallery.js index ac3a526..19a22e7 100644 --- a/chrome/browser/resources/file_manager/js/image_editor/gallery.js +++ b/chrome/browser/resources/file_manager/js/image_editor/gallery.js @@ -224,8 +224,9 @@ Gallery.prototype.initDom_ = function() { this.errorBanner_.className = 'error-banner'; this.errorWrapper_.appendChild(this.errorBanner_); - this.ribbon_ = new Ribbon(this.ribbonSpacer_, + this.ribbon_ = new Ribbon(this.document_, this, this.context_.metadataProvider, this.arrowLeft_, this.arrowRight_); + this.ribbonSpacer_.appendChild(this.ribbon_); this.editBar_ = doc.createElement('div'); this.editBar_.className = 'edit-bar'; @@ -816,43 +817,60 @@ Gallery.prototype.cancelFading_ = function() { }; /** - * @param {HTMLElement} container + * @param {HTMLDocument} document * @param {RibbonClient} client * @param {MetadataProvider} metadataProvider * @param {HTMLElement} arrowLeft * @param {HTMLElement} arrowRight + * @constructor */ -function Ribbon(container, client, metadataProvider, arrowLeft, arrowRight) { - this.container_ = container; - this.document_ = container.ownerDocument; - this.client_ = client; - this.metadataProvider_ = metadataProvider; +function Ribbon(document, client, metadataProvider, arrowLeft, arrowRight) { + var self = document.createElement('div'); + Ribbon.decorate(self, client, metadataProvider, arrowLeft, arrowRight); + return self; +} - this.items_ = []; - this.selectedIndex_ = -1; +Ribbon.prototype.__proto__ = HTMLDivElement.prototype; + +/** + * @param {HTMLDivElement} self Element to decorate. + * @param {RibbonClient} client + * @param {MetadataProvider} metadataProvider + * @param {HTMLElement} arrowLeft + * @param {HTMLElement} arrowRight + */ +Ribbon.decorate = function( + self, client, metadataProvider, arrowLeft, arrowRight) { + self.__proto__ = Ribbon.prototype; + self.client_ = client; + self.metadataProvider_ = metadataProvider; - this.arrowLeft_ = arrowLeft; - this.arrowLeft_. - addEventListener('click', this.selectNext.bind(this, -1, null)); + self.items_ = []; + self.selectedIndex_ = -1; - this.arrowRight_ = arrowRight; - this.arrowRight_. - addEventListener('click', this.selectNext.bind(this, 1, null)); + self.arrowLeft_ = arrowLeft; + self.arrowLeft_. + addEventListener('click', self.selectNext.bind(self, -1, null)); - this.bar_ = this.document_.createElement('div'); - this.bar_.className = 'ribbon'; - this.container_.appendChild(this.bar_); + self.arrowRight_ = arrowRight; + self.arrowRight_. + addEventListener('click', self.selectNext.bind(self, 1, null)); + + self.className = 'ribbon'; } Ribbon.PAGING_SINGLE_ITEM_DELAY = 20; Ribbon.PAGING_ANIMATION_DURATION = 200; +/** + * @return {Ribbon.Item?} The selected item. + */ Ribbon.prototype.getSelectedItem = function () { return this.items_[this.selectedIndex_]; }; Ribbon.prototype.clear = function() { - this.bar_.textContent = ''; + this.textContent = ''; this.items_ = []; this.selectedIndex_ = -1; this.firstVisibleIndex_ = 0; @@ -863,8 +881,8 @@ Ribbon.prototype.clear = function() { Ribbon.prototype.add = function(url) { var index = this.items_.length; - var selectClosure = this.select.bind(this, index, 0, null); - var item = new Ribbon.Item(index, url, this.document_, selectClosure); + var item = new Ribbon.Item(this.ownerDocument, index, url); + item.addEventListener('click', this.select.bind(this, index, 0, null)); this.items_.push(item); }; @@ -990,13 +1008,13 @@ Ribbon.prototype.redraw = function() { }.bind(this); // TODO(dgozman): use margin instead of 2 here. - var itemWidth = this.bar_.clientHeight - 2; + var itemWidth = this.clientHeight - 2; var fullItems = Ribbon.ITEMS_COUNT; fullItems = Math.min(fullItems, this.items_.length); var right = Math.floor((fullItems - 1) / 2); var fullWidth = fullItems * itemWidth; - this.bar_.style.width = fullWidth + 'px'; + this.style.width = fullWidth + 'px'; var lastIndex = this.selectedIndex_ + right; lastIndex = Math.max(lastIndex, fullItems - 1); @@ -1013,7 +1031,7 @@ Ribbon.prototype.redraw = function() { this.lastVisibleIndex_ = lastIndex; } - this.bar_.textContent = ''; + this.textContent = ''; var startIndex = Math.min(firstIndex, this.firstVisibleIndex_); var toRemove = []; // All the items except the first one treated equally. @@ -1021,9 +1039,9 @@ Ribbon.prototype.redraw = function() { index <= Math.max(lastIndex, this.lastVisibleIndex_); ++index) { initThumbnail(index); - var box = this.items_[index].getBox(); + var box = this.items_[index]; box.style.marginLeft = '0'; - this.bar_.appendChild(box); + this.appendChild(box); if (index < firstIndex || index > lastIndex) { toRemove.push(index); } @@ -1031,14 +1049,14 @@ Ribbon.prototype.redraw = function() { var margin = itemWidth * Math.abs(firstIndex - this.firstVisibleIndex_); initThumbnail(startIndex); - var startBox = this.items_[startIndex].getBox(); + var startBox = this.items_[startIndex]; if (startIndex == firstIndex) { // Sliding to the right. startBox.style.marginLeft = -margin + 'px'; - if (this.bar_.firstChild) - this.bar_.insertBefore(startBox, this.bar_.firstChild); + if (this.firstChild) + this.insertBefore(startBox, this.firstChild); else - this.bar_.appendChild(startBox); + this.appendChild(startBox); setTimeout(function() { startBox.style.marginLeft = '0'; }, 0); @@ -1047,26 +1065,20 @@ Ribbon.prototype.redraw = function() { // removed afterwards. toRemove.push(startIndex); startBox.style.marginLeft = '0'; - if (this.bar_.firstChild) - this.bar_.insertBefore(startBox, this.bar_.firstChild); + if (this.firstChild) + this.insertBefore(startBox, this.firstChild); else - this.bar_.appendChild(startBox); + this.appendChild(startBox); setTimeout(function() { startBox.style.marginLeft = -margin + 'px'; }, 0); } - if (firstIndex > 0 && this.selectedIndex_ != firstIndex) { - this.bar_.classList.add('fade-left'); - } else { - this.bar_.classList.remove('fade-left'); - } + ImageUtil.setClass(this, 'fade-left', + firstIndex > 0 && this.selectedIndex_ != firstIndex); - if (lastIndex < this.items_.length - 1 && this.selectedIndex_ != lastIndex) { - this.bar_.classList.add('fade-right'); - } else { - this.bar_.classList.remove('fade-right'); - } + ImageUtil.setClass(this, 'fade-right', + lastIndex < this.items_.length - 1 && this.selectedIndex_ != lastIndex); this.firstVisibleIndex_ = firstIndex; this.lastVisibleIndex_ = lastIndex; @@ -1075,9 +1087,9 @@ Ribbon.prototype.redraw = function() { for (var i = 0; i < toRemove.length; i++) { var index = toRemove[i]; if (index < this.firstVisibleIndex_ || index > this.lastVisibleIndex_) { - var box = this.items_[index].getBox(); - if (box.parentNode == this.bar_) - this.bar_.removeChild(box); + var box = this.items_[index]; + if (box.parentNode == this) + this.removeChild(box); } } }.bind(this), 200); @@ -1120,29 +1132,34 @@ Ribbon.prototype.toggleDebugSlideshow = function() { } }; -Ribbon.Item = function(index, url, document, selectClosure) { - this.index_ = index; - this.url_ = url; +Ribbon.Item = function(document, index, url) { + var self = document.createElement('div'); + Ribbon.Item.decorate(self, index, url); + return self; +}; + +Ribbon.Item.prototype.__proto__ = HTMLDivElement.prototype; - this.box_ = document.createElement('div'); - this.box_.className = 'ribbon-image'; - this.box_.addEventListener('click', selectClosure); +Ribbon.Item.decorate = function(self, index, url, selectClosure) { + self.__proto__ = Ribbon.Item.prototype; + self.index_ = index; + self.url_ = url; - this.wrapper_ = document.createElement('div'); - this.wrapper_.className = 'image-wrapper'; - this.box_.appendChild(this.wrapper_); + self.className = 'ribbon-image'; - this.img_ = document.createElement('img'); - this.wrapper_.appendChild(this.img_); + var wrapper = self.ownerDocument.createElement('div'); + wrapper.className = 'image-wrapper'; + self.appendChild(wrapper); - this.original_ = true; - this.nameForSaving_ = null; + var img = document.createElement('img'); + wrapper.appendChild(img); + + self.original_ = true; + self.nameForSaving_ = null; }; Ribbon.Item.prototype.getIndex = function () { return this.index_ }; -Ribbon.Item.prototype.getBox = function () { return this.box_ }; - Ribbon.Item.prototype.isOriginal = function () { return this.original_ }; Ribbon.Item.prototype.getUrl = function () { return this.url_ }; @@ -1157,11 +1174,11 @@ Ribbon.Item.prototype.hasNameForSaving = function() { }; Ribbon.Item.prototype.isSelected = function() { - return this.box_.hasAttribute('selected'); + return this.hasAttribute('selected'); }; Ribbon.Item.prototype.select = function(on) { - ImageUtil.setAttribute(this.box_, 'selected', on); + ImageUtil.setAttribute(this, 'selected', on); }; Ribbon.Item.prototype.saveToFile = function( @@ -1295,7 +1312,7 @@ Ribbon.Item.prototype.setNameForSaving = function(newName) { }; Ribbon.Item.prototype.hasThumbnail = function() { - return this.img_.hasAttribute('src'); + return !!this.querySelector('img[src]'); }; Ribbon.Item.prototype.setThumbnail = function(metadata) { @@ -1332,9 +1349,10 @@ Ribbon.Item.prototype.setThumbnail = function(metadata) { } } - util.applyTransform(this.wrapper_, transform); + var wrapper = this.querySelector('.image-wrapper'); + util.applyTransform(wrapper, transform); - var img = this.img_; + var img = this.querySelector('img'); if (metadata.width && metadata.height) { var aspect = metadata.width / metadata.height; @@ -1357,13 +1375,17 @@ Ribbon.Item.prototype.setThumbnail = function(metadata) { img.onerror = function() { // Use the default icon if we could not fetch the correct one. - util.applyTransform(this.wrapper_, null); + util.applyTransform(wrapper, null); img.src = FileType.getPreviewArt(mediaType); - }.bind(this); + }; img.src = url; }; +/** + * @constructor + * @extends {ImageEditor.Mode} + */ function ShareMode(editor, container, toolbar, shareActions, onClick, actionCallback, displayStringFunction) { ImageEditor.Mode.call(this, 'share'); @@ -1400,12 +1422,18 @@ function ShareMode(editor, container, toolbar, shareActions, ShareMode.prototype = { __proto__: ImageEditor.Mode.prototype }; +/** + * Shows share mode UI. + */ ShareMode.prototype.setUp = function() { ImageEditor.Mode.prototype.setUp.apply(this, arguments); ImageUtil.setAttribute(this.menu_, 'hidden', false); ImageUtil.setAttribute(this.button_, 'pressed', false); }; +/** + * Hides share mode UI. + */ ShareMode.prototype.cleanUpUI = function() { ImageEditor.Mode.prototype.cleanUpUI.apply(this, arguments); ImageUtil.setAttribute(this.menu_, 'hidden', true); diff --git a/chrome/browser/resources/file_manager/js/image_editor/image_util.js b/chrome/browser/resources/file_manager/js/image_editor/image_util.js index 4190879..a02a9e9 100644 --- a/chrome/browser/resources/file_manager/js/image_editor/image_util.js +++ b/chrome/browser/resources/file_manager/js/image_editor/image_util.js @@ -6,7 +6,9 @@ // Namespace object for the utilities. function ImageUtil() {} -// Performance trace. +/** + * Performance trace. + */ ImageUtil.trace = (function() { function PerformanceTrace() { this.lines_ = {}; @@ -51,11 +53,22 @@ ImageUtil.trace = (function() { return new PerformanceTrace(); })(); - +/** + * @param {number} min Minimum value. + * @param {number} value Value to adjust. + * @param {number} max Maximum value. + * @return {number} The closest to the |value| number in span [min, max]. + */ ImageUtil.clamp = function(min, value, max) { return Math.max(min, Math.min(max, value)); }; +/** + * @param {number} min Minimum value. + * @param {number} value Value to check. + * @param {number} max Maximum value. + * @return {boolean} True if value is between + */ ImageUtil.between = function(min, value, max) { return (value - min) * (value - max) <= 0; }; @@ -75,7 +88,7 @@ ImageUtil.between = function(min, value, max) { * new Rect() // empty rectangle. * @constructor */ -function Rect(args) { +function Rect() { switch (arguments.length) { case 4: this.left = arguments[0]; @@ -125,6 +138,7 @@ function Rect(args) { } /** + * @param {number} factor Factor to scale. * @return {Rect} A rectangle with every dimension scaled. */ Rect.prototype.scale = function(factor) { @@ -136,6 +150,8 @@ Rect.prototype.scale = function(factor) { }; /** + * @param {number} dx Difference in X. + * @param {number} dy Difference in Y. * @return {Rect} A rectangle shifted by (dx,dy), same size. */ Rect.prototype.shift = function(dx, dy) { @@ -143,6 +159,8 @@ Rect.prototype.shift = function(dx, dy) { }; /** + * @param {number} x Coordinate of the left top corner. + * @param {number} y Coordinate of the left top corner. * @return {Rect} A rectangle with left==x and top==y, same size. */ Rect.prototype.moveTo = function(x, y) { @@ -150,6 +168,8 @@ Rect.prototype.moveTo = function(x, y) { }; /** + * @param {number} dx Difference in X. + * @param {number} dy Difference in Y. * @return {Rect} A rectangle inflated by (dx, dy), same center. */ Rect.prototype.inflate = function(dx, dy) { @@ -158,13 +178,19 @@ Rect.prototype.inflate = function(dx, dy) { }; /** - * @return {Boolean} True if the point lies inside the rectange. + * @param {number} x Coordinate of the point. + * @param {number} y Coordinate of the point. + * @return {boolean} True if the point lies inside the rectange. */ Rect.prototype.inside = function(x, y) { return this.left <= x && x < this.left + this.width && this.top <= y && y < this.top + this.height; }; +/** + * @param {Rect} rect Rectangle to check. + * @return {boolean} True if this recangle intersects with the |rect|. + */ Rect.prototype.intersects = function(rect) { return (this.left + this.width) > rect.left && (rect.left + rect.width) > this.left && @@ -172,6 +198,10 @@ Rect.prototype.intersects = function(rect) { (rect.top + rect.height) > this.top; }; +/** + * @param {Rect} rect Rectangle to check. + * @return {boolean} True if this recangle containg the |rect|. + */ Rect.prototype.contains = function(rect) { return (this.left <= rect.left) && (rect.left + rect.width) <= (this.left + this.width) && @@ -179,6 +209,9 @@ Rect.prototype.contains = function(rect) { (rect.top + rect.height) <= (this.top + this.height); }; +/** + * @return {boolean} True if rectangle is empty. + */ Rect.prototype.isEmpty = function() { return this.width == 0 || this.height == 0; }; @@ -186,6 +219,8 @@ Rect.prototype.isEmpty = function() { /** * Clamp the rectangle to the bounds by moving it. * Decrease the size only if necessary. + * @param {Rect} bounds Bounds. + * @return {Rect} Caclulated rectangle. */ Rect.prototype.clamp = function(bounds) { var rect = new Rect(this); @@ -193,7 +228,7 @@ Rect.prototype.clamp = function(bounds) { if (rect.width > bounds.width) { rect.left = bounds.left; rect.width = bounds.width; - } else if (rect.left < bounds.left){ + } else if (rect.left < bounds.left) { rect.left = bounds.left; } else if (rect.left + rect.width > bounds.left + bounds.width) { @@ -203,7 +238,7 @@ Rect.prototype.clamp = function(bounds) { if (rect.height > bounds.height) { rect.top = bounds.top; rect.height = bounds.height; - } else if (rect.top < bounds.top){ + } else if (rect.top < bounds.top) { rect.top = bounds.top; } else if (rect.top + rect.height > bounds.top + bounds.height) { @@ -213,6 +248,9 @@ Rect.prototype.clamp = function(bounds) { return rect; }; +/** + * @return {string} String representation. + */ Rect.prototype.toString = function() { return '(' + this.left + ',' + this.top + '):' + '(' + (this.left + this.width) + ',' + (this.top + this.height) + ')'; @@ -223,6 +261,12 @@ Rect.prototype.toString = function() { /** * Draw the image in context with appropriate scaling. + * @param {CanvasRenderingContext2D} context Context to draw. + * @param {Image} image Image to draw. + * @param {Rect=} opt_dstRect Rectangle in the canvas + * (whole canvas by default). + * @param {Rect=} opt_srcRect Rectangle in the imsge + * (whole image by default). */ Rect.drawImage = function(context, image, opt_dstRect, opt_srcRect) { opt_dstRect = opt_dstRect || new Rect(context.canvas); @@ -236,6 +280,8 @@ Rect.drawImage = function(context, image, opt_dstRect, opt_srcRect) { /** * Draw a box around the rectangle. + * @param {CanvasRenderingContext2D} context Context to draw. + * @param {Rect} rect Rectangle. */ Rect.outline = function(context, rect) { context.strokeRect( @@ -244,6 +290,8 @@ Rect.outline = function(context, rect) { /** * Fill the rectangle. + * @param {CanvasRenderingContext2D} context Context to draw. + * @param {Rect} rect Rectangle. */ Rect.fill = function(context, rect) { context.fillRect(rect.left, rect.top, rect.width, rect.height); @@ -251,8 +299,11 @@ Rect.fill = function(context, rect) { /** * Fills the space between the two rectangles. + * @param {CanvasRenderingContext2D} context Context to draw. + * @param {Rect} inner Inner rectangle. + * @param {Rect} outer Outer rectangle. */ -Rect.fillBetween= function(context, inner, outer) { +Rect.fillBetween = function(context, inner, outer) { var inner_right = inner.left + inner.width; var inner_bottom = inner.top + inner.height; var outer_right = outer.left + outer.width; @@ -277,14 +328,23 @@ Rect.fillBetween= function(context, inner, outer) { /** * Circle class. + * @param {number} x X coordinate of circle center. + * @param {number} y Y coordinate of circle center. + * @param {number} r Radius. + * @constructor */ - -function Circle(x, y, R) { +function Circle(x, y, r) { this.x = x; this.y = y; - this.squaredR = R * R; + this.squaredR = r * r; } +/** + * Check if the point is inside the circle. + * @param {number} x X coordinate of the point. + * @param {number} y Y coordinate of the point. + * @return {boolean} True if the point is inside. + */ Circle.prototype.inside = function(x, y) { x -= this.x; y -= this.y; @@ -294,10 +354,10 @@ Circle.prototype.inside = function(x, y) { /** * Copy an image applying scaling and rotation. * - * @param {HTMLCanvasElement} dst destination - * @param {HTMLCanvasElement|HTMLImageElement} src source - * @param {number} scaleX - * @param {number} scaleY + * @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) */ ImageUtil.drawImageTransformed = function(dst, src, scaleX, scaleY, angle) { @@ -310,43 +370,50 @@ ImageUtil.drawImageTransformed = function(dst, src, scaleX, scaleY, angle) { context.restore(); }; - -ImageUtil.deepCopy = function(obj) { - if (obj == null || typeof obj != 'object') - return obj; // Copy built-in types as is. - - var res; - if (obj.constructor.name == 'Array') { - // obj.constructor == Array would give a false negative if obj came - // from a different context. - res = []; - for (var i = 0; i != obj.length; i++) { - res[i] = ImageUtil.deepCopy(obj[i]); - } - } else { - res = {}; - for (var p in obj) { - res[p] = ImageUtil.deepCopy(obj[p]); - } - } - return res; +/** + * @param {*} value Structure. + * @return {*} Clone of the value. + */ +ImageUtil.deepCopy = function(value) { + return JSON.parse(JSON.stringify(obj)); }; +/** + * Adds or removes an attribute to/from an HTML element. + * @param {HTMLElement} element To be applied to. + * @param {string} attribute Name of attribute. + * @param {boolean} on True if add, false if remove. + */ ImageUtil.setAttribute = function(element, attribute, on) { if (on) - element.setAttribute(attribute, attribute); + element.setAttribute(attribute, ''); else element.removeAttribute(attribute); }; -/* +/** + * Adds or removes CSS class to/from an HTML element. + * @param {HTMLElement} element To be applied to. + * @param {string} className Name of CSS class. + * @param {boolean} on True if add, false if remove. + */ +ImageUtil.setClass = function(element, className, on) { + var cl = element.classList; + if (on) + cl.add(className); + else + cl.remove(className); +}; + +/** * ImageLoader loads an image from a given URL into a canvas in two steps: * 1. Loads the image into an HTMLImageElement. * 2. Copies pixels from HTMLImageElement to HTMLCanvasElement. This is done * stripe-by-stripe to avoid freezing up the UI. The transform is taken into * account. + * @param {HTMLDocument} document Owner document. + * @constructor */ - ImageUtil.ImageLoader = function(document) { this.document_ = document; this.image_ = null; @@ -354,10 +421,10 @@ ImageUtil.ImageLoader = function(document) { }; /** - * @param {string} url + * @param {string} url Image URL. * @param {function(function(object))} transformFetcher function to get * the image transform (which we need for the image orientation) - * @param {function(HTMLCanvasElement} callback + * @param {function(HTMLCanvasElement)} callback To be called when loaded. * @param {number} opt_delay Load delay in milliseconds, useful to let the * animations play out before the computation heavy image loading starts. */ @@ -405,18 +472,31 @@ ImageUtil.ImageLoader.prototype.load = function( } }; +/** + * @return {boolean} True if an image is loading. + */ ImageUtil.ImageLoader.prototype.isBusy = function() { return !!this.callback_; }; +/** + * @param {string} url Image url. + * @return {boolean} True if loader loads this image. + */ ImageUtil.ImageLoader.prototype.isLoading = function(url) { return this.isBusy() && (this.url_ == url); }; +/** + * @param {Function} callback To be called when the image loaded. + */ ImageUtil.ImageLoader.prototype.setCallback = function(callback) { this.callback_ = callback; }; +/** + * Stops loading image. + */ ImageUtil.ImageLoader.prototype.cancel = function() { if (!this.callback_) return; this.callback_ = null; @@ -425,19 +505,24 @@ ImageUtil.ImageLoader.prototype.cancel = function() { this.timeout_ = null; } if (this.image_) { - this.image_.onload = function(){}; + this.image_.onload = function() {}; this.image_ = null; } this.generation_++; // Silence the transform fetcher if it is in progress. }; +/** + * @param {HTMLImageElement} image Image to be transformed. + * @param {object} transform rransformation description to applay to the image. + * @private + */ ImageUtil.ImageLoader.prototype.convertImage_ = function(image, transform) { var canvas = this.document_.createElement('canvas'); if (transform.rotate90 & 1) { // Rotated +/-90deg, swap the dimensions. canvas.width = image.height; canvas.height = image.width; - } else { + } else { canvas.width = image.width; canvas.height = image.height; } @@ -445,18 +530,25 @@ ImageUtil.ImageLoader.prototype.convertImage_ = function(image, transform) { var context = canvas.getContext('2d'); context.save(); context.translate(canvas.width / 2, canvas.height / 2); - context.rotate(transform.rotate90 * Math.PI/2); + context.rotate(transform.rotate90 * Math.PI / 2); context.scale(transform.scaleX, transform.scaleY); - var stripCount = Math.ceil(image.width * image.height / ( 1 << 21)); + var stripCount = Math.ceil(image.width * image.height / (1 << 21)); var step = Math.max(16, Math.ceil(image.height / stripCount)) & 0xFFFFF0; this.copyStrip_(context, image, 0, step); }; +/** + * @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 + */ ImageUtil.ImageLoader.prototype.copyStrip_ = function( context, image, firstRow, rowCount) { - var lastRow = Math.min (firstRow + rowCount, image.height); + var lastRow = Math.min(firstRow + rowCount, image.height); context.drawImage( image, 0, firstRow, image.width, lastRow - firstRow, @@ -480,10 +572,17 @@ ImageUtil.ImageLoader.prototype.copyStrip_ = function( } }; +/** + * @param {HTMLElement} element To remove children from. + */ ImageUtil.removeChildren = function(element) { element.textContent = ''; }; +/** + * @param {string} url "filesystem:" URL. + * @return {string} File name. + */ ImageUtil.getFullNameFromUrl = function(url) { url = decodeURIComponent(url); if (url.indexOf('/') != -1) @@ -492,6 +591,10 @@ ImageUtil.getFullNameFromUrl = function(url) { return url; }; +/** + * @param {string} name File name (with extension). + * @return {string} File name without extension. + */ ImageUtil.getFileNameFromFullName = function(name) { var index = name.lastIndexOf('.'); if (index != -1) @@ -500,10 +603,20 @@ ImageUtil.getFileNameFromFullName = function(name) { return name; }; +/** + * @param {string} url "filesystem:" URL. + * @return {string} File name. + */ ImageUtil.getFileNameFromUrl = function(url) { return ImageUtil.getFileNameFromFullName(ImageUtil.getFullNameFromUrl(url)); }; +/** + * @param {string} fullName Original file name. + * @param {string} name New file name without extension. + * @return {string} New file name with base of |name| and extension of + * |fullName|. + */ ImageUtil.replaceFileNameInFullName = function(fullName, name) { var index = fullName.lastIndexOf('.'); if (index != -1) @@ -512,6 +625,10 @@ ImageUtil.replaceFileNameInFullName = function(fullName, name) { return name; }; +/** + * @param {string} name File name. + * @return {string} File extension. + */ ImageUtil.getExtensionFromFullName = function(name) { var index = name.lastIndexOf('.'); if (index != -1) @@ -520,10 +637,22 @@ ImageUtil.getExtensionFromFullName = function(name) { return ''; }; +/** + * Metrics (from metrics.js) itnitialized by the File Manager from owner frame. + * @type {Object?} + */ ImageUtil.metrics = null; -ImageUtil.getMetricName = function(name) { return 'PhotoEditor.' + name } +/** + * @param {string} name Local name. + * @return {string} Full name. + */ +ImageUtil.getMetricName = function(name) { + return 'PhotoEditor.' + name; +}; -// Used for metrics reporting, keep in sync with the histogram description. +/** + * Used for metrics reporting, keep in sync with the histogram description. + */ ImageUtil.FILE_TYPES = ['jpg', 'png', 'gif', 'bmp', 'webp']; |