15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Copyright 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)'use strict'; 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Namespace object for the utilities. 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function ImageUtil() {} 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Performance trace. 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageUtil.trace = (function() { 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function PerformanceTrace() { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.lines_ = {}; 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.timers_ = {}; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_ = null; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PerformanceTrace.prototype.bindToDOM = function(container) { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_ = container; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PerformanceTrace.prototype.report = function(key, value) { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(key in this.lines_)) { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.container_) { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var div = this.lines_[key] = document.createElement('div'); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_.appendChild(div); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.lines_[key] = {}; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.lines_[key].textContent = key + ': ' + value; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ImageUtil.trace.log) this.dumpLine(key); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PerformanceTrace.prototype.resetTimer = function(key) { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.timers_[key] = Date.now(); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PerformanceTrace.prototype.reportTimer = function(key) { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.report(key, (Date.now() - this.timers_[key]) + 'ms'); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PerformanceTrace.prototype.dump = function() { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var key in this.lines_) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dumpLine(key); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PerformanceTrace.prototype.dumpLine = function(key) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) console.log('trace.' + this.lines_[key].textContent); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new PerformanceTrace(); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)})(); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} min Minimum value. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} value Value to adjust. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} max Maximum value. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The closest to the |value| number in span [min, max]. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageUtil.clamp = function(min, value, max) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Math.max(min, Math.min(max, value)); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} min Minimum value. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} value Value to check. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} max Maximum value. 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @return {boolean} True if value is between. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageUtil.between = function(min, value, max) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (value - min) * (value - max) <= 0; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Rectangle class. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Rectangle constructor takes 0, 1, 2 or 4 arguments. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Supports following variants: 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * new Rect(left, top, width, height) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * new Rect(width, height) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * new Rect(rect) // anything with left, top, width, height properties 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * new Rect(bounds) // anything with left, top, right, bottom properties 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * new Rect(canvas|image) // anything with width and height properties. 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * new Rect() // empty rectangle. 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @constructor 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function Rect() { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (arguments.length) { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 4: 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.left = arguments[0]; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.top = arguments[1]; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.width = arguments[2]; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.height = arguments[3]; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 2: 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.left = 0; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.top = 0; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.width = arguments[0]; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.height = arguments[1]; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 1: { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var source = arguments[0]; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ('left' in source && 'top' in source) { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.left = source.left; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.top = source.top; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ('right' in source && 'bottom' in source) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.width = source.right - source.left; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.height = source.bottom - source.top; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.left = 0; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.top = 0; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ('width' in source && 'height' in source) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.width = source.width; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.height = source.height; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; // Fall through to the error message. 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 0: 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.left = 0; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.top = 0; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.width = 0; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.height = 0; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) console.error('Invalid Rect constructor arguments:', 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Array.apply(null, arguments)); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 142116680a4aac90f2aa7413d9095a592090648e557Ben MurdochRect.prototype = { 143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Obtains the x coordinate of right edge. The most right pixels in the 145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * rectangle are (x = right - 1) and the pixels (x = right) are not included 146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * in the rectangle. 147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * @return {number} 148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch get right() { 150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return this.left + this.width; 151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch }, 152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Obtains the y coordinate of bottom edge. The most bottom pixels in the 1556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) * rectangle are (y = bottom - 1) and the pixels (y = bottom) are not included 156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * in the rectangle. 157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * @return {number} 158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch get bottom() { 160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return this.top + this.height; 161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}; 163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} factor Factor to scale. 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {Rect} A rectangle with every dimension scaled. 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Rect.prototype.scale = function(factor) { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new Rect( 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.left * factor, 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.top * factor, 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.width * factor, 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.height * factor); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} dx Difference in X. 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} dy Difference in Y. 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {Rect} A rectangle shifted by (dx,dy), same size. 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Rect.prototype.shift = function(dx, dy) { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new Rect(this.left + dx, this.top + dy, this.width, this.height); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} x Coordinate of the left top corner. 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} y Coordinate of the left top corner. 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {Rect} A rectangle with left==x and top==y, same size. 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Rect.prototype.moveTo = function(x, y) { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new Rect(x, y, this.width, this.height); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} dx Difference in X. 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} dy Difference in Y. 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {Rect} A rectangle inflated by (dx, dy), same center. 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Rect.prototype.inflate = function(dx, dy) { 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new Rect( 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.left - dx, this.top - dy, this.width + 2 * dx, this.height + 2 * dy); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} x Coordinate of the point. 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} y Coordinate of the point. 2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @return {boolean} True if the point lies inside the rectangle. 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Rect.prototype.inside = function(x, y) { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.left <= x && x < this.left + this.width && 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.top <= y && y < this.top + this.height; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Rect} rect Rectangle to check. 2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @return {boolean} True if this rectangle intersects with the |rect|. 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Rect.prototype.intersects = function(rect) { 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (this.left + this.width) > rect.left && 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (rect.left + rect.width) > this.left && 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (this.top + this.height) > rect.top && 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (rect.top + rect.height) > this.top; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Rect} rect Rectangle to check. 2274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @return {boolean} True if this rectangle containing the |rect|. 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Rect.prototype.contains = function(rect) { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (this.left <= rect.left) && 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (rect.left + rect.width) <= (this.left + this.width) && 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (this.top <= rect.top) && 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (rect.top + rect.height) <= (this.top + this.height); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} True if rectangle is empty. 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Rect.prototype.isEmpty = function() { 240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return this.width === 0 || this.height === 0; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Clamp the rectangle to the bounds by moving it. 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Decrease the size only if necessary. 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Rect} bounds Bounds. 2474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @return {Rect} Calculated rectangle. 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Rect.prototype.clamp = function(bounds) { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var rect = new Rect(this); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rect.width > bounds.width) { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect.left = bounds.left; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect.width = bounds.width; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (rect.left < bounds.left) { 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect.left = bounds.left; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (rect.left + rect.width > 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bounds.left + bounds.width) { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect.left = bounds.left + bounds.width - rect.width; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rect.height > bounds.height) { 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect.top = bounds.top; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect.height = bounds.height; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (rect.top < bounds.top) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect.top = bounds.top; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (rect.top + rect.height > 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bounds.top + bounds.height) { 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect.top = bounds.top + bounds.height - rect.height; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rect; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {string} String representation. 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Rect.prototype.toString = function() { 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '(' + this.left + ',' + this.top + '):' + 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '(' + (this.left + this.width) + ',' + (this.top + this.height) + ')'; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Useful shortcuts for drawing (static functions). 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Draw the image in context with appropriate scaling. 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {CanvasRenderingContext2D} context Context to draw. 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Image} image Image to draw. 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {Rect=} opt_dstRect Rectangle in the canvas (whole canvas by default). 2914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {Rect=} opt_srcRect Rectangle in the image (whole image by default). 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Rect.drawImage = function(context, image, opt_dstRect, opt_srcRect) { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) opt_dstRect = opt_dstRect || new Rect(context.canvas); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) opt_srcRect = opt_srcRect || new Rect(image); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (opt_dstRect.isEmpty() || opt_srcRect.isEmpty()) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context.drawImage(image, 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) opt_srcRect.left, opt_srcRect.top, opt_srcRect.width, opt_srcRect.height, 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) opt_dstRect.left, opt_dstRect.top, opt_dstRect.width, opt_dstRect.height); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Draw a box around the rectangle. 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {CanvasRenderingContext2D} context Context to draw. 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Rect} rect Rectangle. 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Rect.outline = function(context, rect) { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context.strokeRect( 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect.left - 0.5, rect.top - 0.5, rect.width + 1, rect.height + 1); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Fill the rectangle. 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {CanvasRenderingContext2D} context Context to draw. 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Rect} rect Rectangle. 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Rect.fill = function(context, rect) { 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context.fillRect(rect.left, rect.top, rect.width, rect.height); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Fills the space between the two rectangles. 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {CanvasRenderingContext2D} context Context to draw. 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Rect} inner Inner rectangle. 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Rect} outer Outer rectangle. 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Rect.fillBetween = function(context, inner, outer) { 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var innerRight = inner.left + inner.width; 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var innerBottom = inner.top + inner.height; 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var outerRight = outer.left + outer.width; 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var outerBottom = outer.top + outer.height; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (inner.top > outer.top) { 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context.fillRect( 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) outer.left, outer.top, outer.width, inner.top - outer.top); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (inner.left > outer.left) { 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context.fillRect( 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) outer.left, inner.top, inner.left - outer.left, inner.height); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (inner.width < outerRight) { 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context.fillRect( 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) innerRight, inner.top, outerRight - innerRight, inner.height); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (inner.height < outerBottom) { 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context.fillRect( 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) outer.left, innerBottom, outer.width, outerBottom - innerBottom); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Circle class. 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} x X coordinate of circle center. 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} y Y coordinate of circle center. 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} r Radius. 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @constructor 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function Circle(x, y, r) { 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.x = x; 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.y = y; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.squaredR = r * r; 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Check if the point is inside the circle. 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} x X coordinate of the point. 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} y Y coordinate of the point. 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} True if the point is inside. 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Circle.prototype.inside = function(x, y) { 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x -= this.x; 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y -= this.y; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return x * x + y * y <= this.squaredR; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copy an image applying scaling and rotation. 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {HTMLCanvasElement} dst Destination. 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {HTMLCanvasElement|HTMLImageElement} src Source. 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} scaleX Y scale transformation. 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} scaleY X scale transformation. 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {number} angle (in radians). 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageUtil.drawImageTransformed = function(dst, src, scaleX, scaleY, angle) { 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var context = dst.getContext('2d'); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context.save(); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context.translate(context.canvas.width / 2, context.canvas.height / 2); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context.rotate(angle); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context.scale(scaleX, scaleY); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context.drawImage(src, -src.width / 2, -src.height / 2); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context.restore(); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Adds or removes an attribute to/from an HTML element. 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {HTMLElement} element To be applied to. 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} attribute Name of attribute. 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {boolean} on True if add, false if remove. 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageUtil.setAttribute = function(element, attribute, on) { 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (on) 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) element.setAttribute(attribute, ''); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) element.removeAttribute(attribute); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Adds or removes CSS class to/from an HTML element. 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {HTMLElement} element To be applied to. 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} className Name of CSS class. 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {boolean} on True if add, false if remove. 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageUtil.setClass = function(element, className, on) { 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var cl = element.classList; 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (on) 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl.add(className); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl.remove(className); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 423a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * ImageLoader loads an image from a given Entry into a canvas in two steps: 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1. Loads the image into an HTMLImageElement. 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2. Copies pixels from HTMLImageElement to HTMLCanvasElement. This is done 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * stripe-by-stripe to avoid freezing up the UI. The transform is taken into 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * account. 4287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {HTMLDocument} document Owner document. 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @constructor 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 432116680a4aac90f2aa7413d9095a592090648e557Ben MurdochImageUtil.ImageLoader = function(document) { 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.document_ = document; 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.image_ = new Image(); 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.generation_ = 0; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 4397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * Loads an image. 4407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * TODO(mtomasz): Simplify, or even get rid of this class and merge with the 4417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * ThumbnaiLoader class. 4427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * 4431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param {Gallery.Item} item Item representing the image to be loaded. 44490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * @param {function(HTMLCanvasElement, string=)} callback Callback to be 44590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * called when loaded. The second optional argument is an error identifier. 4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {number=} opt_delay Load delay in milliseconds, useful to let the 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * animations play out before the computation heavy image loading starts. 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 449116680a4aac90f2aa7413d9095a592090648e557Ben MurdochImageUtil.ImageLoader.prototype.load = function(item, callback, opt_delay) { 450116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch var entry = item.getEntry(); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 452116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.cancel(); 453a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) this.entry_ = entry; 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.callback_ = callback; 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The transform fetcher is not cancellable so we need a generation counter. 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var generation = ++this.generation_; 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var onTransform = function(image, transform) { 459a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (generation === this.generation_) { 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.convertImage_( 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image, transform || { scaleX: 1, scaleY: 1, rotate90: 0}); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 463116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch }.bind(this); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 46590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) var onError = function(opt_error) { 46690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) this.image_.onerror = null; 46790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) this.image_.onload = null; 46890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) var tmpCallback = this.callback_; 46990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) this.callback_ = null; 47090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) var emptyCanvas = this.document_.createElement('canvas'); 47190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) emptyCanvas.width = 0; 47290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) emptyCanvas.height = 0; 47390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) tmpCallback(emptyCanvas, opt_error); 47490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) }.bind(this); 47590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 476116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch var loadImage = function() { 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageUtil.metrics.startInterval(ImageUtil.getMetricName('LoadTime')); 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.timeout_ = null; 4797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 480116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.image_.onload = function() { 4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.image_.onerror = null; 4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.image_.onload = null; 483116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch item.getFetchedMedia().then(function(fetchedMediaMetadata) { 484116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch onTransform(this.image_, fetchedMediaMetadata.imageTransform); 485116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch }.bind(this)).catch(function(error) { 486116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch console.error(error.stack || error); 487116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch }); 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }.bind(this); 48990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // The error callback has an optional error argument, which in case of a 4917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // general error should not be specified 492a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) this.image_.onerror = onError.bind(this, 'GALLERY_IMAGE_ERROR'); 4937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 49446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Load the image directly. The query parameter is workaround for 49546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // crbug.com/379678, which force to update the contents of the image. 4961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.image_.src = entry.toURL() + '?nocache=' + Date.now(); 49790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) }.bind(this); 49890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Loads the image. If already loaded, then forces a reload. 5007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) var startLoad = this.resetImage_.bind(this, function() { 501116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch loadImage(); 5027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) }.bind(this), onError); 50390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (opt_delay) { 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.timeout_ = setTimeout(startLoad, opt_delay); 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) startLoad(); 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 5127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * Resets the image by forcing the garbage collection and clearing the src 5137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * attribute. 5147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * 5157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * @param {function()} onSuccess Success callback. 5167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * @param {function(opt_string)} onError Failure callback with an optional 5177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * error identifier. 5187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * @private 5197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) */ 5207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)ImageUtil.ImageLoader.prototype.resetImage_ = function(onSuccess, onError) { 5217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) var clearSrc = function() { 5227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) this.image_.onload = onSuccess; 5237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) this.image_.onerror = onSuccess; 5247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) this.image_.src = ''; 5257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) }.bind(this); 5267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 5277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) var emptyImage = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAA' + 5287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 'AAABAAEAAAICTAEAOw=='; 5297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 530a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (this.image_.src !== emptyImage) { 5317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Load an empty image, then clear src. 5327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) this.image_.onload = clearSrc; 533a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) this.image_.onerror = onError.bind(this, 'GALLERY_IMAGE_ERROR'); 5347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) this.image_.src = emptyImage; 5357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } else { 5367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Empty image already loaded, so clear src immediately. 5377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) clearSrc(); 5387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 5397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}; 5407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 5417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)/** 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} True if an image is loading. 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageUtil.ImageLoader.prototype.isBusy = function() { 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !!this.callback_; 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 549a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * @param {Entry} entry Image entry. 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} True if loader loads this image. 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 552a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)ImageUtil.ImageLoader.prototype.isLoading = function(entry) { 553a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return this.isBusy() && util.isSameEntry(this.entry_, entry); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {function} callback To be called when the image loaded. 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageUtil.ImageLoader.prototype.setCallback = function(callback) { 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.callback_ = callback; 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Stops loading image. 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageUtil.ImageLoader.prototype.cancel = function() { 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.callback_) return; 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.callback_ = null; 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.timeout_) { 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clearTimeout(this.timeout_); 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.timeout_ = null; 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.image_) { 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.image_.onload = function() {}; 5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.image_.onerror = function() {}; 5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.image_.src = ''; 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.generation_++; // Silence the transform fetcher if it is in progress. 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {HTMLImageElement} image Image to be transformed. 5834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {Object} transform transformation description to apply to the image. 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageUtil.ImageLoader.prototype.convertImage_ = function(image, transform) { 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var canvas = this.document_.createElement('canvas'); 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transform.rotate90 & 1) { // Rotated +/-90deg, swap the dimensions. 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas.width = image.height; 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas.height = image.width; 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas.width = image.width; 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas.height = image.height; 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var context = canvas.getContext('2d'); 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context.save(); 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context.translate(canvas.width / 2, canvas.height / 2); 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context.rotate(transform.rotate90 * Math.PI / 2); 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context.scale(transform.scaleX, transform.scaleY); 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var stripCount = Math.ceil(image.width * image.height / (1 << 21)); 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var step = Math.max(16, Math.ceil(image.height / stripCount)) & 0xFFFFF0; 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.copyStrip_(context, image, 0, step); 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {CanvasRenderingContext2D} context Context to draw. 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {HTMLImageElement} image Image to draw. 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} firstRow Number of the first pixel row to draw. 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} rowCount Count of pixel rows to draw. 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageUtil.ImageLoader.prototype.copyStrip_ = function( 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context, image, firstRow, rowCount) { 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var lastRow = Math.min(firstRow + rowCount, image.height); 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context.drawImage( 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image, 0, firstRow, image.width, lastRow - firstRow, 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) -image.width / 2, firstRow - image.height / 2, 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image.width, lastRow - firstRow); 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (lastRow === image.height) { 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context.restore(); 627a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (this.entry_.toURL().substr(0, 5) !== 'data:') { // Ignore data urls. 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageUtil.metrics.recordInterval(ImageUtil.getMetricName('LoadTime')); 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try { 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setTimeout(this.callback_, 0, context.canvas); 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } catch (e) { 633c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) console.error(e); 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.callback_ = null; 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var self = this; 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.timeout_ = setTimeout( 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function() { 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.timeout_ = null; 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.copyStrip_(context, image, lastRow, rowCount); 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 0); 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {HTMLElement} element To remove children from. 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageUtil.removeChildren = function(element) { 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) element.textContent = ''; 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} name File name (with extension). 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {string} File name without extension. 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 657a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)ImageUtil.getDisplayNameFromName = function(name) { 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = name.lastIndexOf('.'); 659a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (index !== -1) 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return name.substr(0, index); 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return name; 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} name File name. 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {string} File extension. 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageUtil.getExtensionFromFullName = function(name) { 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = name.lastIndexOf('.'); 671a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (index !== -1) 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return name.substring(index); 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ''; 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Metrics (from metrics.js) itnitialized by the File Manager from owner frame. 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {Object?} 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageUtil.metrics = null; 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} name Local name. 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {string} Full name. 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageUtil.getMetricName = function(name) { 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 'PhotoEditor.' + name; 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Used for metrics reporting, keep in sync with the histogram description. 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageUtil.FILE_TYPES = ['jpg', 'png', 'gif', 'bmp', 'webp']; 695