diff --git a/other-scripts/Steel-Gauges/web_server/script/src/RGraph.common.core.js b/other-scripts/Steel-Gauges/web_server/script/src/RGraph.common.core.js new file mode 100644 index 0000000..d519bdf --- /dev/null +++ b/other-scripts/Steel-Gauges/web_server/script/src/RGraph.common.core.js @@ -0,0 +1,2959 @@ + /** + * o------------------------------------------------------------------------------o + * | This file is part of the RGraph package - you can learn more at: | + * | | + * | http://www.rgraph.net | + * | | + * | This package is licensed under the RGraph license. For all kinds of business | + * | purposes there is a small one-time licensing fee to pay and for non | + * | commercial purposes it is free to use. You can read the full license here: | + * | | + * | http://www.rgraph.net/license | + * o------------------------------------------------------------------------------o + */ + + /** + * Initialise the various objects + */ + if (typeof(RGraph) == 'undefined') RGraph = {isRGraph:true,type:'common'}; + + RGraph.Registry = {}; + RGraph.Registry.store = []; + RGraph.Registry.store['chart.event.handlers'] = []; + RGraph.Registry.store['__rgraph_event_listeners__'] = []; // Used in the new system for tooltips + RGraph.background = {}; + RGraph.objects = []; + RGraph.Resizing = {}; + RGraph.events = []; + RGraph.cursor = []; + RGraph.DOM2Events = {}; + + RGraph.ObjectRegistry = {}; + RGraph.ObjectRegistry.objects = {}; + RGraph.ObjectRegistry.objects.byUID = []; + RGraph.ObjectRegistry.objects.byCanvasID = []; + + + /** + * Some "constants" + */ + HALFPI = (Math.PI / 2); + PI = Math.PI; + TWOPI = PI * 2; + ISOPERA = navigator.userAgent.indexOf('Opera') != -1; + //ISIE is defined below + //ISIE6 is defined below + //ISIE7 is defined below + //ISIE8 is defined below + //ISIE9 is defined below + //ISIE9UP is defined below + //ISIE10 is defined below + //ISIE10UP is defined below + //ISOLD is defined below + + + /** + * Returns five values which are used as a nice scale + * + * @param max int The maximum value of the graph + * @param obj object The graph object + * @return array An appropriate scale + */ + RGraph.getScale = function (max, obj) + { + /** + * Special case for 0 + */ + if (max == 0) { + return ['0.2', '0.4', '0.6', '0.8', '1.0']; + } + + var original_max = max; + + /** + * Manually do decimals + */ + if (max <= 1) { + if (max > 0.5) { + return [0.2,0.4,0.6,0.8, Number(1).toFixed(1)]; + + } else if (max >= 0.1) { + return obj.Get('chart.scale.round') ? [0.2,0.4,0.6,0.8,1] : [0.1,0.2,0.3,0.4,0.5]; + + } else { + + var tmp = max; + var exp = 0; + + while (tmp < 1.01) { + exp += 1; + tmp *= 10; + } + + var ret = ['2e-' + exp, '4e-' + exp, '6e-' + exp, '8e-' + exp, '10e-' + exp]; + + + if (max <= ('5e-' + exp)) { + ret = ['1e-' + exp, '2e-' + exp, '3e-' + exp, '4e-' + exp, '5e-' + exp]; + } + + return ret; + } + } + + // Take off any decimals + if (String(max).indexOf('.') > 0) { + max = String(max).replace(/\.\d+$/, ''); + } + + var interval = Math.pow(10, Number(String(Number(max)).length - 1)); + var topValue = interval; + + while (topValue < max) { + topValue += (interval / 2); + } + + // Handles cases where the max is (for example) 50.5 + if (Number(original_max) > Number(topValue)) { + topValue += (interval / 2); + } + + // Custom if the max is greater than 5 and less than 10 + if (max < 10) { + topValue = (Number(original_max) <= 5 ? 5 : 10); + } + + /** + * Added 02/11/2010 to create "nicer" scales + */ + if (obj && typeof(obj.Get('chart.scale.round')) == 'boolean' && obj.Get('chart.scale.round')) { + topValue = 10 * interval; + } + + return [topValue * 0.2, topValue * 0.4, topValue * 0.6, topValue * 0.8, topValue]; + } + + + /** + * Returns the maximum numeric value which is in an array + * + * @param array arr The array (can also be a number, in which case it's returned as-is) + * @param int Whether to ignore signs (ie negative/positive) + * @return int The maximum value in the array + */ + RGraph.array_max = function (arr) + { + var max = null; + + if (typeof(arr) == 'number') { + return arr; + } + + for (var i=0; i (obj.canvas.height - gutterBottom) ? obj.canvas.height - (gutterBottom + i) : 40); + } + + context.stroke(); + + + // Draw the background grid + if (obj.Get('chart.background.grid')) { + + // If autofit is specified, use the .numhlines and .numvlines along with the width to work + // out the hsize and vsize + if (obj.Get('chart.background.grid.autofit')) { + + /** + * Align the grid to the tickmarks + */ + if (obj.Get('chart.background.grid.autofit.align')) { + // Align the horizontal lines + obj.Set('chart.background.grid.autofit.numhlines', obj.Get('chart.ylabels.count')); + + // Align the vertical lines for the line + if (obj.type == 'line') { + if (obj.Get('chart.labels') && obj.Get('chart.labels').length) { + obj.Set('chart.background.grid.autofit.numvlines', obj.Get('chart.labels').length - 1); + } else { + obj.Set('chart.background.grid.autofit.numvlines', obj.data[0].length - 1); + } + + // Align the vertical lines for the bar + } else if (obj.type == 'bar' && obj.Get('chart.labels') && obj.Get('chart.labels').length) { + obj.Set('chart.background.grid.autofit.numvlines', obj.Get('chart.labels').length); + } + } + + var vsize = ((obj.canvas.width - gutterLeft - gutterRight)) / obj.properties['chart.background.grid.autofit.numvlines']; + var hsize = (obj.canvas.height - gutterTop - gutterBottom) / obj.properties['chart.background.grid.autofit.numhlines']; + + obj.Set('chart.background.grid.vsize', vsize); + obj.Set('chart.background.grid.hsize', hsize); + } + + context.beginPath(); + context.lineWidth = obj.Get('chart.background.grid.width') ? obj.Get('chart.background.grid.width') : 1; + context.strokeStyle = obj.Get('chart.background.grid.color'); + + // Draw the horizontal lines + if (obj.Get('chart.background.grid.hlines')) { + height = (RGraph.GetHeight(obj) - gutterBottom) + for (y=gutterTop; y= 1) days += 31; + if (month >= 2) days += 28; + + // Leap years. Crude, but it functions + if (year >= 2008 && year % 4 == 0) days += 1; + + if (month >= 3) days += 31; + if (month >= 4) days += 30; + if (month >= 5) days += 31; + if (month >= 6) days += 30; + if (month >= 7) days += 31; + if (month >= 8) days += 31; + if (month >= 9) days += 30; + if (month >= 10) days += 31; + if (month >= 11) days += 30; + + return days; + } + + + /** + * Makes a clone of an object + * + * @param obj val The object to clone + */ + RGraph.array_clone = function (obj) + { + if(obj == null || typeof(obj) != 'object') { + return obj; + } + + var temp = []; + + for (var i=0;i 0) { + return String(prepend + String(num) + append); + } + + // We need then number as a string + num = String(num); + + // Take off the decimal part - we re-append it later + if (num.indexOf('.') > 0) { + var tmp = num; + num = num.replace(/\.(.*)/, ''); // The front part of the number + decimal = tmp.replace(/(.*)\.(.*)/, '$2'); // The decimal part of the number + } + + // Thousand seperator + //var seperator = arguments[1] ? String(arguments[1]) : ','; + var seperator = thousand_seperator; + + /** + * Work backwards adding the thousand seperators + */ + var foundPoint; + for (i=(num.length - 1),j=0; i>=0; j++,i--) { + var character = num.charAt(i); + + if ( j % 3 == 0 && j != 0) { + output += seperator; + } + + /** + * Build the output + */ + output += character; + } + + /** + * Now need to reverse the string + */ + var rev = output; + output = ''; + for (i=(rev.length - 1); i>=0; i--) { + output += rev.charAt(i); + } + + // Tidy up + //output = output.replace(/^-,/, '-'); + if (output.indexOf('-' + obj.Get('chart.scale.thousand')) == 0) { + output = '-' + output.substr(('-' + obj.Get('chart.scale.thousand')).length); + } + + // Reappend the decimal + if (decimal.length) { + output = output + decimal_seperator + decimal; + decimal = ''; + RegExp.$1 = ''; + } + + // Minor bugette + if (output.charAt(0) == '-') { + output = output.replace(/-/, ''); + prepend = '-' + prepend; + } + + return prepend + output + append; + } + + + /** + * Draws horizontal coloured bars on something like the bar, line or scatter + */ + RGraph.DrawBars = function (obj) + { + var hbars = obj.Get('chart.background.hbars'); + + /** + * Draws a horizontal bar + */ + obj.context.beginPath(); + + for (i=0; i obj.max) { + hbars[i][1] = obj.max - hbars[i][0]; + } + + + // If height is negative, and the abs() value is greater than .max, use a negative max instead + if (Math.abs(hbars[i][1]) > obj.max) { + hbars[i][1] = -1 * obj.max; + } + + + // If start point is greater than max, change it to max + if (Math.abs(hbars[i][0]) > obj.max) { + hbars[i][0] = obj.max; + } + + // If start point plus height is less than negative max, use the negative max plus the start point + if (hbars[i][0] + hbars[i][1] < (-1 * obj.max) ) { + hbars[i][1] = -1 * (obj.max + hbars[i][0]); + } + + // If the X axis is at the bottom, and a negative max is given, warn the user + if (obj.Get('chart.xaxispos') == 'bottom' && (hbars[i][0] < 0 || (hbars[i][1] + hbars[i][1] < 0)) ) { + alert('[' + obj.type.toUpperCase() + ' (ID: ' + obj.id + ') BACKGROUND HBARS] You have a negative value in one of your background hbars values, whilst the X axis is in the center'); + } + + var ystart = (obj.grapharea - (((hbars[i][0] - obj.min) / (obj.max - obj.min)) * obj.grapharea)); + var height = (Math.min(hbars[i][1], obj.max - hbars[i][0]) / (obj.max - obj.min)) * obj.grapharea; + + // Account for the X axis being in the center + if (obj.Get('chart.xaxispos') == 'center') { + ystart /= 2; + height /= 2; + } + + ystart += obj.Get('chart.gutter.top') + + var x = obj.Get('chart.gutter.left'); + var y = ystart - height; + var w = obj.canvas.width - obj.Get('chart.gutter.left') - obj.Get('chart.gutter.right'); + var h = height; + + // Accommodate Opera :-/ + if (navigator.userAgent.indexOf('Opera') != -1 && obj.Get('chart.xaxispos') == 'center' && h < 0) { + h *= -1; + y = y - h; + } + + /** + * Account for X axis at the top + */ + if (obj.Get('chart.xaxispos') == 'top') { + y = obj.canvas.height - y; + h *= -1; + } + + obj.context.fillStyle = hbars[i][2]; + obj.context.fillRect(x, y, w, h); + } + + obj.context.fill(); + } + + + /** + * Draws in-graph labels. + * + * @param object obj The graph object + */ + RGraph.DrawInGraphLabels = function (obj) + { + var canvas = obj.canvas; + var context = obj.context; + var labels = obj.Get('chart.labels.ingraph'); + var labels_processed = []; + + // Defaults + var fgcolor = 'black'; + var bgcolor = 'white'; + var direction = 1; + + if (!labels) { + return; + } + + /** + * Preprocess the labels array. Numbers are expanded + */ + for (var i=0; i 0) { + + for (var i=0; i 0) { + var x = (obj.type == 'bar' ? coords[0] + (coords[2] / 2) : coords[0]); + var y = (obj.type == 'bar' ? coords[1] + (coords[3] / 2) : coords[1]); + var length = typeof(labels_processed[i][4]) == 'number' ? labels_processed[i][4] : 25; + + context.beginPath(); + context.fillStyle = 'black'; + context.strokeStyle = 'black'; + + + if (obj.type == 'bar') { + + /** + * X axis at the top + */ + if (obj.Get('chart.xaxispos') == 'top') { + length *= -1; + } + + if (obj.Get('chart.variant') == 'dot') { + context.moveTo(Math.round(x), obj.coords[i][1] - 5); + context.lineTo(Math.round(x), obj.coords[i][1] - 5 - length); + + var text_x = Math.round(x); + var text_y = obj.coords[i][1] - 5 - length; + + } else if (obj.Get('chart.variant') == 'arrow') { + context.moveTo(Math.round(x), obj.coords[i][1] - 5); + context.lineTo(Math.round(x), obj.coords[i][1] - 5 - length); + + var text_x = Math.round(x); + var text_y = obj.coords[i][1] - 5 - length; + + } else { + + context.arc(Math.round(x), y, 2.5, 0, 6.28, 0); + context.moveTo(Math.round(x), y); + context.lineTo(Math.round(x), y - length); + + var text_x = Math.round(x); + var text_y = y - length; + } + + context.stroke(); + context.fill(); + + + } else if (obj.type == 'line') { + + if ( + typeof(labels_processed[i]) == 'object' && + typeof(labels_processed[i][3]) == 'number' && + labels_processed[i][3] == -1 + ) { + + context.moveTo(Math.round(x), y + 5); + context.lineTo(Math.round(x), y + 5 + length); + + context.stroke(); + context.beginPath(); + + // This draws the arrow + context.moveTo(Math.round(x), y + 5); + context.lineTo(Math.round(x) - 3, y + 10); + context.lineTo(Math.round(x) + 3, y + 10); + context.closePath(); + + var text_x = x; + var text_y = y + 5 + length; + + } else { + + var text_x = x; + var text_y = y - 5 - length; + + context.moveTo(Math.round(x), y - 5); + context.lineTo(Math.round(x), y - 5 - length); + + context.stroke(); + context.beginPath(); + + // This draws the arrow + context.moveTo(Math.round(x), y - 5); + context.lineTo(Math.round(x) - 3, y - 10); + context.lineTo(Math.round(x) + 3, y - 10); + context.closePath(); + } + + context.fill(); + } + + // Taken out on the 10th Nov 2010 - unnecessary + //var width = context.measureText(labels[i]).width; + + context.beginPath(); + + // Fore ground color + context.fillStyle = (typeof(labels_processed[i]) == 'object' && typeof(labels_processed[i][1]) == 'string') ? labels_processed[i][1] : 'black'; + + RGraph.Text(context, + obj.Get('chart.text.font'), + obj.Get('chart.text.size'), + text_x, + text_y, + (typeof(labels_processed[i]) == 'object' && typeof(labels_processed[i][0]) == 'string') ? labels_processed[i][0] : labels_processed[i], + 'bottom', + 'center', + true, + null, + (typeof(labels_processed[i]) == 'object' && typeof(labels_processed[i][2]) == 'string') ? labels_processed[i][2] : 'white'); + context.fill(); + } + } + } + } + } + + + /** + * This function "fills in" key missing properties that various implementations lack + * + * @param object e The event object + */ + RGraph.FixEventObject = function (e) + { + if (ISOLD) { + var e = event; + + e.pageX = (event.clientX + document.body.scrollLeft); + e.pageY = (event.clientY + document.body.scrollTop); + e.target = event.srcElement; + + if (!document.body.scrollTop && document.documentElement.scrollTop) { + e.pageX += parseInt(document.documentElement.scrollLeft); + e.pageY += parseInt(document.documentElement.scrollTop); + } + } + + // This is mainly for FF which doesn't provide offsetX + if (typeof(e.offsetX) == 'undefined' && typeof(e.offsetY) == 'undefined') { + var coords = RGraph.getMouseXY(e); + e.offsetX = coords[0]; + e.offsetY = coords[1]; + } + + // Any browser that doesn't implement stopPropagation() (MSIE) + if (!e.stopPropagation) { + e.stopPropagation = function () {window.event.cancelBubble = true;} + } + + return e; + } + + /** + * Thisz function hides the crosshairs coordinates + */ + RGraph.HideCrosshairCoords = function () + { + var div = RGraph.Registry.Get('chart.coordinates.coords.div'); + + if ( div + && div.style.opacity == 1 + && div.__object__.Get('chart.crosshairs.coords.fadeout') + ) { + setTimeout(function() {RGraph.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.9;}, 50); + setTimeout(function() {RGraph.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.8;}, 100); + setTimeout(function() {RGraph.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.7;}, 150); + setTimeout(function() {RGraph.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.6;}, 200); + setTimeout(function() {RGraph.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.5;}, 250); + setTimeout(function() {RGraph.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.4;}, 300); + setTimeout(function() {RGraph.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.3;}, 350); + setTimeout(function() {RGraph.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.2;}, 400); + setTimeout(function() {RGraph.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.1;}, 450); + setTimeout(function() {RGraph.Registry.Get('chart.coordinates.coords.div').style.opacity = 0;}, 500); + setTimeout(function() {RGraph.Registry.Get('chart.coordinates.coords.div').style.display = 'none';}, 550); + } + } + + + /** + * Draws the3D axes/background + */ + RGraph.Draw3DAxes = function (obj) + { + var gutterLeft = obj.Get('chart.gutter.left'); + var gutterRight = obj.Get('chart.gutter.right'); + var gutterTop = obj.Get('chart.gutter.top'); + var gutterBottom = obj.Get('chart.gutter.bottom'); + + var context = obj.context; + var canvas = obj.canvas; + + context.strokeStyle = '#aaa'; + context.fillStyle = '#ddd'; + + // Draw the vertical left side + context.beginPath(); + context.moveTo(gutterLeft, gutterTop); + context.lineTo(gutterLeft + 10, gutterTop - 5); + context.lineTo(gutterLeft + 10, canvas.height - gutterBottom - 5); + context.lineTo(gutterLeft, canvas.height - gutterBottom); + context.closePath(); + + context.stroke(); + context.fill(); + + // Draw the bottom floor + context.beginPath(); + context.moveTo(gutterLeft, canvas.height - gutterBottom); + context.lineTo(gutterLeft + 10, canvas.height - gutterBottom - 5); + context.lineTo(canvas.width - gutterRight + 10, canvas.height - gutterBottom - 5); + context.lineTo(canvas.width - gutterRight, canvas.height - gutterBottom); + context.closePath(); + + context.stroke(); + context.fill(); + } + + + + /** + * This function attempts to "fill in" missing functions from the canvas + * context object. Only two at the moment - measureText() nd fillText(). + * + * @param object context The canvas 2D context + */ + RGraph.OldBrowserCompat = function (context) + { + if (!context) { + return; + } + + if (!context.measureText) { + + // This emulates the measureText() function + context.measureText = function (text) + { + var textObj = document.createElement('DIV'); + textObj.innerHTML = text; + textObj.style.position = 'absolute'; + textObj.style.top = '-100px'; + textObj.style.left = 0; + document.body.appendChild(textObj); + + var width = {width: textObj.offsetWidth}; + + textObj.style.display = 'none'; + + return width; + } + } + + if (!context.fillText) { + // This emulates the fillText() method + context.fillText = function (text, targetX, targetY) + { + return false; + } + } + + // If IE8, add addEventListener() + if (!context.canvas.addEventListener) { + window.addEventListener = function (ev, func, bubble) + { + return this.attachEvent('on' + ev, func); + } + + context.canvas.addEventListener = function (ev, func, bubble) + { + return this.attachEvent('on' + ev, func); + } + } + } + + + /** + * Draws a rectangle with curvy corners + * + * @param context object The context + * @param x number The X coordinate (top left of the square) + * @param y number The Y coordinate (top left of the square) + * @param w number The width of the rectangle + * @param h number The height of the rectangle + * @param number The radius of the curved corners + * @param boolean Whether the top left corner is curvy + * @param boolean Whether the top right corner is curvy + * @param boolean Whether the bottom right corner is curvy + * @param boolean Whether the bottom left corner is curvy + */ + RGraph.strokedCurvyRect = function (context, x, y, w, h) + { + // The corner radius + var r = arguments[5] ? arguments[5] : 3; + + // The corners + var corner_tl = (arguments[6] || arguments[6] == null) ? true : false; + var corner_tr = (arguments[7] || arguments[7] == null) ? true : false; + var corner_br = (arguments[8] || arguments[8] == null) ? true : false; + var corner_bl = (arguments[9] || arguments[9] == null) ? true : false; + + context.beginPath(); + + // Top left side + context.moveTo(x + (corner_tl ? r : 0), y); + context.lineTo(x + w - (corner_tr ? r : 0), y); + + // Top right corner + if (corner_tr) { + context.arc(x + w - r, y + r, r, PI + HALFPI, TWOPI, false); + } + + // Top right side + context.lineTo(x + w, y + h - (corner_br ? r : 0) ); + + // Bottom right corner + if (corner_br) { + context.arc(x + w - r, y - r + h, r, TWOPI, HALFPI, false); + } + + // Bottom right side + context.lineTo(x + (corner_bl ? r : 0), y + h); + + // Bottom left corner + if (corner_bl) { + context.arc(x + r, y - r + h, r, HALFPI, PI, false); + } + + // Bottom left side + context.lineTo(x, y + (corner_tl ? r : 0) ); + + // Top left corner + if (corner_tl) { + context.arc(x + r, y + r, r, PI, PI + HALFPI, false); + } + + context.stroke(); + } + + + /** + * Draws a filled rectangle with curvy corners + * + * @param context object The context + * @param x number The X coordinate (top left of the square) + * @param y number The Y coordinate (top left of the square) + * @param w number The width of the rectangle + * @param h number The height of the rectangle + * @param number The radius of the curved corners + * @param boolean Whether the top left corner is curvy + * @param boolean Whether the top right corner is curvy + * @param boolean Whether the bottom right corner is curvy + * @param boolean Whether the bottom left corner is curvy + */ + RGraph.filledCurvyRect = function (context, x, y, w, h) + { + // The corner radius + var r = arguments[5] ? arguments[5] : 3; + + // The corners + var corner_tl = (arguments[6] || arguments[6] == null) ? true : false; + var corner_tr = (arguments[7] || arguments[7] == null) ? true : false; + var corner_br = (arguments[8] || arguments[8] == null) ? true : false; + var corner_bl = (arguments[9] || arguments[9] == null) ? true : false; + + context.beginPath(); + + // First draw the corners + + // Top left corner + if (corner_tl) { + context.moveTo(x + r, y + r); + context.arc(x + r, y + r, r, PI, PI + HALFPI, false); + } else { + context.fillRect(x, y, r, r); + } + + // Top right corner + if (corner_tr) { + context.moveTo(x + w - r, y + r); + context.arc(x + w - r, y + r, r, PI + HALFPI, 0, false); + } else { + context.moveTo(x + w - r, y); + context.fillRect(x + w - r, y, r, r); + } + + + // Bottom right corner + if (corner_br) { + context.moveTo(x + w - r, y + h - r); + context.arc(x + w - r, y - r + h, r, 0, HALFPI, false); + } else { + context.moveTo(x + w - r, y + h - r); + context.fillRect(x + w - r, y + h - r, r, r); + } + + // Bottom left corner + if (corner_bl) { + context.moveTo(x + r, y + h - r); + context.arc(x + r, y - r + h, r, HALFPI, PI, false); + } else { + context.moveTo(x, y + h - r); + context.fillRect(x, y + h - r, r, r); + } + + // Now fill it in + context.fillRect(x + r, y, w - r - r, h); + context.fillRect(x, y + r, r + 1, h - r - r); + context.fillRect(x + w - r - 1, y + r, r + 1, h - r - r); + + context.fill(); + } + + + /** + * Hides the zoomed canvas + */ + RGraph.HideZoomedCanvas = function () + { + var interval = 15; + var frames = 10; + + if (typeof(__zoomedimage__) == 'object') { + obj = __zoomedimage__.obj; + } else { + return; + } + + if (obj.Get('chart.zoom.fade.out')) { + for (var i=frames,j=1; i>=0; --i, ++j) { + if (typeof(__zoomedimage__) == 'object') { + setTimeout("__zoomedimage__.style.opacity = " + String(i / 10), j * interval); + } + } + + if (typeof(__zoomedbackground__) == 'object') { + setTimeout("__zoomedbackground__.style.opacity = " + String(i / frames), j * interval); + } + } + + if (typeof(__zoomedimage__) == 'object') { + setTimeout("__zoomedimage__.style.display = 'none'", obj.Get('chart.zoom.fade.out') ? (frames * interval) + 10 : 0); + } + + if (typeof(__zoomedbackground__) == 'object') { + setTimeout("__zoomedbackground__.style.display = 'none'", obj.Get('chart.zoom.fade.out') ? (frames * interval) + 10 : 0); + } + } + + + /** + * Adds an event handler + * + * @param object obj The graph object + * @param string event The name of the event, eg ontooltip + * @param object func The callback function + */ + RGraph.AddCustomEventListener = function (obj, name, func) + { + if (typeof(RGraph.events[obj.uid]) == 'undefined') { + RGraph.events[obj.uid] = []; + } + + RGraph.events[obj.uid].push([obj, name, func]); + + return RGraph.events[obj.uid].length - 1; + } + + + /** + * Used to fire one of the RGraph custom events + * + * @param object obj The graph object that fires the event + * @param string event The name of the event to fire + */ + RGraph.FireCustomEvent = function (obj, name) + { + if (obj && obj.isRGraph) { + + // New style of adding custom events + if (obj[name]) { + (obj[name])(obj); + } + + var uid = obj.uid; + + if ( typeof(uid) == 'string' + && typeof(RGraph.events) == 'object' + && typeof(RGraph.events[uid]) == 'object' + && RGraph.events[uid].length > 0) { + + for(var j=0; j str.length ? obj.Get('chart.labels')[i] : str); + } + } + + obj.context.font = obj.Get('chart.text.size') + 'pt ' + obj.Get('chart.text.font'); + + len = obj.context.measureText(str).width + 5; + + return (obj.type == 'hbar' ? len / 3 : len); + } + + + /** + * If you prefer, you can use the SetConfig() method to set the configuration information + * for your chart. You may find that setting the configuration this way eases reuse. + * + * @param object obj The graph object + * @param object config The graph configuration information + */ + RGraph.SetConfig = function (obj, c) + { + for (i in c) { + if (typeof(i) == 'string') { + obj.Set(i, c[i]); + } + } + + return obj; + } + + + /** + * Clears all the custom event listeners that have been registered + * + * @param string Limits the clearing to this object ID + */ + RGraph.RemoveAllCustomEventListeners = function () + { + var id = arguments[0]; + + if (id && RGraph.events[id]) { + RGraph.events[id] = []; + } else { + RGraph.events = []; + } + } + + + /** + * Clears a particular custom event listener + * + * @param object obj The graph object + * @param number i This is the index that is return by .AddCustomEventListener() + */ + RGraph.RemoveCustomEventListener = function (obj, i) + { + if ( typeof(RGraph.events) == 'object' + && typeof(RGraph.events[obj.id]) == 'object' + && typeof(RGraph.events[obj.id][i]) == 'object') { + + RGraph.events[obj.id][i] = null; + } + } + + + + /** + * This draws the background + * + * @param object obj The graph object + */ + RGraph.DrawBackgroundImage = function (obj) + { + if (typeof(obj.Get('chart.background.image')) == 'string') { + if (typeof(obj.canvas.__rgraph_background_image__) == 'undefined') { + var img = new Image(); + img.__object__ = obj; + img.__canvas__ = obj.canvas; + img.__context__ = obj.context; + img.src = obj.Get('chart.background.image'); + + obj.canvas.__rgraph_background_image__ = img; + } else { + img = obj.canvas.__rgraph_background_image__; + } + + // When the image has loaded - redraw the canvas + img.onload = function () + { + obj.__rgraph_background_image_loaded__ = true; + RGraph.Clear(obj.canvas); + RGraph.RedrawCanvas(obj.canvas); + } + + var gutterLeft = obj.Get('chart.gutter.left'); + var gutterRight = obj.Get('chart.gutter.right'); + var gutterTop = obj.Get('chart.gutter.top'); + var gutterBottom = obj.Get('chart.gutter.bottom'); + var stretch = obj.Get('chart.background.image.stretch'); + var align = obj.Get('chart.background.image.align'); + + // Handle chart.background.image.align + if (typeof(align) == 'string') { + if (align.indexOf('right') != -1) { + var x = obj.canvas.width - img.width - gutterRight; + } else { + var x = gutterLeft; + } + + if (align.indexOf('bottom') != -1) { + var y = obj.canvas.height - img.height - gutterBottom; + } else { + var y = gutterTop; + } + } else { + var x = gutterLeft; + var y = gutterTop; + } + + // X/Y coords take precedence over the align + var x = typeof(obj.Get('chart.background.image.x')) == 'number' ? obj.Get('chart.background.image.x') : x; + var y = typeof(obj.Get('chart.background.image.y')) == 'number' ? obj.Get('chart.background.image.y') : y; + var w = stretch ? obj.canvas.width - gutterLeft - gutterRight : img.width; + var h = stretch ? obj.canvas.height - gutterTop - gutterBottom : img.height; + + /** + * You can now specify the width and height of the image + */ + if (typeof(obj.Get('chart.background.image.w')) == 'number') w = obj.Get('chart.background.image.w'); + if (typeof(obj.Get('chart.background.image.h')) == 'number') h = obj.Get('chart.background.image.h'); + + obj.context.drawImage(img,x,y,w, h); + } + } + + + + /** + * This function determines wshether an object has tooltips or not + * + * @param object obj The chart object + */ + RGraph.hasTooltips = function (obj) + { + if (typeof(obj.Get('chart.tooltips')) == 'object' && obj.Get('chart.tooltips')) { + for (var i=0; i=0; --i) { + + var obj = objects[i].getObjectByXY(e); + + if (obj) { + return obj; + } + } + } + + + + /** + * Retrieves the relevant objects based on the X/Y position. + * NOTE This function returns an array of objects + * + * @param object e The event object + * @return An array of pertinent objects. Note the there may be only one object + */ + RGraph.ObjectRegistry.getObjectsByXY = function (e) + { + var canvas = e.target; + var ret = []; + var objects = RGraph.ObjectRegistry.getObjectsByCanvasID(canvas.id); + + // Retrieve objects "front to back" + for (var i=(objects.length - 1); i>=0; --i) { + + var obj = objects[i].getObjectByXY(e); + + if (obj) { + ret.push(obj); + } + } + + return ret; + } + + + /** + * Retrieves the object with the corresponding UID + * + * @param string uid The UID to get the relevant object for + */ + RGraph.ObjectRegistry.getObjectByUID = function (uid) + { + var objects = RGraph.ObjectRegistry.objects.byUID; + + for (var i=0; i= cx && y >= cy) { + angle += TWOPI; + + } else if (x >= cx && y < cy) { + angle = (HALFPI - angle) + (PI + HALFPI); + + } else if (x < cx && y < cy) { + angle += PI; + + } else { + angle = PI - angle; + } + + /** + * Upper and lower limit checking + */ + if (angle > TWOPI) { + angle -= TWOPI; + } + + return angle; + } + + + + /** + * This function returns the distance between two points. In effect the + * radius of an imaginary circle that is centered on x1 and y1. The name + * of this function is derived from the word "Hypoteneuse", which in + * trigonmetry is the longest side of a triangle + * + * @param number x1 The original X coordinate + * @param number y1 The original Y coordinate + * @param number x2 The target X coordinate + * @param number y2 The target Y coordinate + */ + RGraph.getHypLength = function (x1, y1, x2, y2) + { + var ret = Math.sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1))); + + return ret; + } + + + + /** + * This function gets the end point (X/Y coordinates) of a given radius. + * You pass it the center X/Y and the radius and this function will return + * the endpoint X/Y coordinates. + * + * @param number cx The center X coord + * @param number cy The center Y coord + * @param number r The lrngth of the radius + */ + RGraph.getRadiusEndPoint = function (cx, cy, angle, radius) + { + var x = cx + (Math.cos(angle) * radius); + var y = cy + (Math.sin(angle) * radius); + + return [x, y]; + } + + + + /** + * This installs all of the event listeners + * + * @param object obj The chart object + */ + RGraph.InstallEventListeners = function (obj) + { + /** + * Don't attempt to install event listeners for older versions of MSIE + */ + if (RGraph.isOld()) { + return; + } + + /** + * If this function exists, then the dynamic file has been included. + */ + if (RGraph.InstallCanvasClickListener) { + + RGraph.InstallWindowMousedownListener(obj); + RGraph.InstallWindowMouseupListener(obj); + RGraph.InstallCanvasMousemoveListener(obj); + RGraph.InstallCanvasMouseupListener(obj); + RGraph.InstallCanvasMousedownListener(obj); + RGraph.InstallCanvasClickListener(obj); + + } else if ( RGraph.hasTooltips(obj) + || obj.Get('chart.adjustable') + || obj.Get('chart.annotatable') + || obj.Get('chart.contextmenu') + || obj.Get('chart.resizable') + || obj.Get('chart.key.interactive') + || obj.Get('chart.events.click') + || obj.Get('chart.events.mousemove') + ) { + alert('[RGRAPH] You appear to have used dynamic features but not included the file: RGraph.common.dynamic.js'); + } + } + + + + /** + * Loosly mimicks the PHP function print_r(); + */ + RGraph.pr = function (obj) + { + var str = ''; + var indent = (arguments[2] ? arguments[2] : ''); + + switch (typeof(obj)) { + case 'number': + if (indent == '') { + str+= 'Number: ' + } + str += String(obj); + break; + + case 'string': + if (indent == '') { + str+= 'String (' + obj.length + '):' + } + str += '"' + String(obj) + '"'; + break; + + case 'object': + // In case of null + if (obj == null) { + str += 'null'; + break; + } + + str += 'Object\n' + indent + '(\n'; + for (var i in obj) { + if (typeof(i) == 'string' || typeof(i) == 'number') { + str += indent + ' ' + i + ' => ' + RGraph.pr(obj[i], true, indent + ' ') + '\n'; + } + } + + var str = str + indent + ')'; + break; + + case 'function': + str += obj; + break; + + case 'boolean': + str += 'Boolean: ' + (obj ? 'true' : 'false'); + break; + } + + /** + * Finished, now either return if we're in a recursed call, or alert() + * if we're not. + */ + if (arguments[1]) { + return str; + } else { + alert(str); + } + } + + + /** + * Produces a dashed line + * + * @param + */ + RGraph.DashedLine = function(context, x1, y1, x2, y2) + { + /** + * This is the size of the dashes + */ + var size = 5; + + /** + * The optional fifth argument can be the size of the dashes + */ + if (typeof(arguments[5]) == 'number') { + size = arguments[5]; + } + + var dx = x2 - x1; + var dy = y2 - y1; + var num = Math.floor(Math.sqrt((dx * dx) + (dy * dy)) / size); + + var xLen = dx / num; + var yLen = dy / num; + + var count = 0; + + do { + (count % 2 == 0 && count > 0) ? context.lineTo(x1, y1) : context.moveTo(x1, y1); + + x1 += xLen; + y1 += yLen; + } while(count++ <= num); + } + + + /** + * Makes an AJAX call. It calls the given callback (a function) when ready + * + * @param string url The URL to retrieve + * @param function callback A function that is called when the response is ready, there's an example below + * called "myCallback". + */ + RGraph.AJAX = function (url, callback) + { + // Mozilla, Safari, ... + if (window.XMLHttpRequest) { + var httpRequest = new XMLHttpRequest(); + + // MSIE + } else if (window.ActiveXObject) { + var httpRequest = new ActiveXObject("Microsoft.XMLHTTP"); + } + + httpRequest.onreadystatechange = function () + { + if (this.readyState == 4 && this.status == 200) { + this.__user_callback__ = callback; + this.__user_callback__(); + } + } + + httpRequest.open('GET', url, true); + httpRequest.send(); + } + + /** + * Rotates the canvas + * + * @param object canvas The canvas to rotate + * @param int x The X coordinate about which to rotate the canvas + * @param int y The Y coordinate about which to rotate the canvas + * @param int angle The angle(in RADIANS) to rotate the canvas by + */ + RGraph.RotateCanvas = function (canvas, x, y, angle) + { + var context = canvas.getContext('2d'); + + context.translate(x, y); + context.rotate(angle); + context.translate(0 - x, 0 - y); + } + + + /** + * This draws an extra set of Y axes + * + * @param object obj The chart object + * @param object prop An assoc array of options - see the API docs for a list of options + */ + RGraph.DrawAxes = + RGraph.DrawYAxis = function (obj, prop) + { + /** + * Allow both axis.xxx and chart.xxx to prevent any confusion that may arise + */ + for (i in prop) { + if (typeof(i) == 'string') { + var key = i.replace(/^chart\./, 'axis.'); + + prop[key] = prop[i]; + } + } + + + var gutterTop = obj.gutterTop; + var gutterBottom = obj.gutterBottom; + var context = prop['axis.context'] ? prop['axis.context'] : obj.context; + var x = prop['axis.x']; + var y = obj.properties['chart.gutter.top']; + var min = prop['axis.min'] ? prop['axis.min'] : 0; + var max = prop['axis.max']; + var color = prop['axis.color'] ? prop['axis.color'] : 'black'; + var title = prop['axis.title'] ? prop['axis.title'] : ''; + var title_color = prop['axis.title.color'] ? prop['axis.title.color'] : color; + var label_color = prop['axis.text.color'] ? prop['axis.color'] : color; + var height = obj.canvas.height - obj.gutterBottom - obj.gutterTop; + var numticks = typeof(prop['axis.numticks']) == 'number' ? prop['axis.numticks'] : 10; + var numlabels = prop['axis.numlabels'] ? prop['axis.numlabels'] : 5; + var font = prop['axis.font'] ? prop['axis.font'] : 'Arial'; + var size = prop['axis.text.size'] ? prop['axis.text.size'] : 10; + var align = typeof(prop['axis.align']) == 'string'? prop['axis.align'] : 'left'; + var formatter = prop['axis.scale.formatter']; + var decimals = prop['axis.scale.decimals']; + var invert = prop['axis.scale.invert']; + var units_pre = prop['axis.units.pre']; + var units_post = prop['axis.units.post']; + var linewidth = prop['axis.linewidth'] ? prop['axis.linewidth'] : 1; + var notopendtick = prop['axis.noendtick.top']; + var nobottomendtick = prop['axis.noendtick.bottom']; + var noyaxis = prop['axis.noyaxis']; + + // This fixes missing corner pixels in Chrome + context.lineWidth = linewidth + 0.001; + + + /** + * Set the color + */ + context.strokeStyle = color; + + if (!noyaxis) { + /** + * Draw the main vertical line + */ + context.beginPath(); + context.moveTo(Math.round(x), y); + context.lineTo(Math.round(x), y + height); + context.stroke(); + + /** + * Draw the axes tickmarks + */ + if (numticks) { + + var gap = height / numticks; + + context.beginPath(); + for (var i=(notopendtick ? 1 : 0); i<=(numticks - (nobottomendtick ? 1 : 0)); ++i) { + context.moveTo(align == 'right' ? x + 3 : x - 3, Math.round(y + (gap *i))); + context.lineTo(x, Math.round(y + (gap *i))); + } + context.stroke(); + } + } + + + /** + * Draw the scale for the axes + */ + context.fillStyle = label_color; + context.beginPath(); + var text_len = 0; + for (var i=0; i<=numlabels; ++i) { + + var original = ((max - min) * ((numlabels-i) / numlabels)) + min; + + var text = RGraph.number_format(obj, original.toFixed(decimals), units_pre, units_post); + var text = String(typeof(formatter) == 'function' ? formatter(obj, original) : text); + var text_len = Math.max(text_len, context.measureText(text).width); + + if (invert) { + var y = gutterTop + (height - ((height / numlabels)*i)); + } else { + var y = gutterTop + ((height / numlabels)*i); + } + + RGraph.Text( + context, + font, + size, + x - (align == 'right' ? -5 : 5), + y, + text, + 'center', + align == 'right' ? 'left' : 'right' + ); + } + context.stroke(); + + /** + * Draw the title for the axes + */ + if (title) { + context.beginPath(); + context.fillStyle = title_color + RGraph.Text(context, font, size + 2, + + align == 'right' ? x + size + text_len + 2 : x - size - text_len - 2, + + height / 2 + gutterTop, title, 'center', 'center', null, align == 'right' ? 90 : -90); + context.stroke(); + } + } + + + /** + * This draws an extra set of X axes + * + * @param object obj The chart object + * @param object prop An assoc array of options - see the API docs for a list of options + */ + RGraph.DrawXAxis = function (obj, prop) + { + /** + * Allow both axis.xxx and chart.xxx to prevent any confusion that may arise + */ + for (i in prop) { + if (typeof(i) == 'string') { + var key = i.replace(/^chart\./, 'axis.'); + + prop[key] = prop[i]; + } + } + + var context = prop['axis.context'] ? prop['axis.context'] : obj.context; + var gutterLeft = obj.gutterLeft; + var gutterRight = obj.gutterRight; + var x = obj.properties['chart.gutter.left']; + var y = prop['axis.y']; + var min = prop['axis.min'] ? prop['axis.min'] : 0; + var max = prop['axis.max'] ? prop['axis.max'] : null; + var labels = prop['axis.labels'] ? prop['axis.labels'] : null; + var labels_position = typeof(prop['axis.labels.position']) == 'string' ? prop['axis.labels.position'] : 'section'; + var color = prop['axis.color'] ? prop['axis.color'] : 'black'; + var title_color = prop['axis.title.color'] ? prop['axis.title.color'] : color; + var label_color = prop['axis.text.color'] ? prop['axis.text.color'] : color; + var width = obj.canvas.width - obj.gutterLeft - obj.gutterRight; + var height = obj.canvas.height - obj.gutterBottom - obj.gutterTop; + var font = prop['axis.text.font'] ? prop['axis.text.font'] : 'Arial'; + var size = prop['axis.text.size'] ? prop['axis.text.size'] : 10; + var align = typeof(prop['axis.align']) == 'string'? prop['axis.align'] : 'bottom'; + var numlabels = prop['axis.numlabels'] ? prop['axis.numlabels'] : 5; + var formatter = prop['axis.scale.formatter']; + var decimals = Number(prop['axis.scale.decimals']); + var invert = prop['axis.scale.invert']; + var units_pre = prop['axis.units.pre'] ? prop['axis.units.pre'] : ''; + var units_post = prop['axis.units.post'] ? prop['axis.units.post'] : ''; + var title = prop['axis.title'] ? prop['axis.title'] : ''; + var numticks = typeof(prop['axis.numticks']) == 'number' ? prop['axis.numticks'] : (labels && labels.length ? labels.length : 10); + var hmargin = prop['axis.hmargin'] ? prop['axis.hmargin'] : 0; + var linewidth = prop['axis.linewidth'] ? prop['axis.linewidth'] : 1; + var noleftendtick = prop['axis.noendtick.left']; + var norightendtick = prop['axis.noendtick.right']; + var noxaxis = prop['axis.noxaxis']; + + /** + * Set the linewidth + */ + context.lineWidth = linewidth + 0.001; + + /** + * Set the color + */ + context.strokeStyle = color; + + if (!noxaxis) { + /** + * Draw the main horizontal line + */ + context.beginPath(); + context.moveTo(x, Math.round(y)); + context.lineTo(x + width, Math.round(y)); + context.stroke(); + + /** + * Draw the axes tickmarks + */ + context.beginPath(); + for (var i=(noleftendtick ? 1 : 0); i<=(numticks - (norightendtick ? 1 : 0)); ++i) { + context.moveTo(Math.round(x + ((width / numticks) * i)), y); + context.lineTo(Math.round(x + ((width / numticks) * i)), y + (align == 'bottom' ? 3 : -3)); + } + context.stroke(); + } + + + + /** + * Draw the labels + */ + context.fillStyle = label_color; + + if (labels) { + /** + * Draw the labels + */ + + numlabels = labels.length; + + context.beginPath(); + for (var i=0; i'); + div.style.fontFamily = font; + div.style.fontWeight = bold ? 'bold' : 'normal'; + div.style.fontSize = size + 'pt'; + + var size = [div.offsetWidth, div.offsetHeight]; + + //document.body.removeChild(div); + __rgraph_measuretext_cache__[str] = size; + + return size; + } + + + + /** + * If the effects library isn't included already this prevents an unknown function error + */ + if (!RGraph.AddEffects) { + RGraph.AddEffects = function (obj) {} + } + + + +// Some other functions. Because they're rarely changed - they're hand minified +RGraph.LinearGradient=function(obj,x1,y1,x2,y2,color1,color2){var gradient=obj.context.createLinearGradient(x1,y1,x2,y2);var numColors=arguments.length-5;for (var i=5;i=0;i--){newarr.push(arr[i]);}return newarr;} +RGraph.Registry.Set=function(name,value){RGraph.Registry.store[name]=value;return value;} +RGraph.Registry.Get=function(name){return RGraph.Registry.store[name];} +RGraph.degrees2Radians=function(degrees){return degrees*(PI/180);} +RGraph.log=(function(n,base){var log=Math.log;return function(n,base){return log(n)/(base?log(base):1);};})(); +RGraph.is_array=function(obj){return obj!=null&&obj.constructor.toString().indexOf('Array')!=-1;} +RGraph.trim=function(str){return RGraph.ltrim(RGraph.rtrim(str));} +RGraph.ltrim=function(str){return str.replace(/^(\s|\0)+/, '');} +RGraph.rtrim=function(str){return str.replace(/(\s|\0)+$/, '');} +RGraph.GetHeight=function(obj){return obj.canvas.height;} +RGraph.GetWidth=function(obj){return obj.canvas.width;} +RGraph.is_null=function(arg){if(arg==null||(typeof(arg))=='object'&&!arg){return true;}return false;} +RGraph.Timer=function(label){var d=new Date();console.log(label+': '+d.getSeconds()+'.'+d.getMilliseconds());} +RGraph.Async=function(func){return setTimeout(func,arguments[1]?arguments[1]:1);} +RGraph.isIE=function(){return navigator.userAgent.indexOf('MSIE')>0;};ISIE=RGraph.isIE(); +RGraph.isIE6=function(){return navigator.userAgent.indexOf('MSIE 6')>0;};ISIE6=RGraph.isIE6(); +RGraph.isIE7=function(){return navigator.userAgent.indexOf('MSIE 7')>0;};ISIE7=RGraph.isIE7(); +RGraph.isIE8=function(){return navigator.userAgent.indexOf('MSIE 8')>0;};ISIE8=RGraph.isIE8(); +RGraph.isIE9=function(){return navigator.userAgent.indexOf('MSIE 9')>0;};ISIE9=RGraph.isIE9(); +RGraph.isIE10=function(){return navigator.userAgent.indexOf('MSIE 10')>0;};ISIE10=RGraph.isIE10(); +RGraph.isIE9up=function(){navigator.userAgent.match(/MSIE (\d+)/);return Number(RegExp.$1)>=9;};ISIE9UP=RGraph.isIE9up(); +RGraph.isIE10up=function(){navigator.userAgent.match(/MSIE (\d+)/);return Number(RegExp.$1)>=10;};ISIE10UP=RGraph.isIE10up(); +RGraph.isOld=function(){return ISIE6||ISIE7||ISIE8;};ISOLD=ISIE6||ISIE7||ISIE8; +RGraph.Reset=function(canvas){canvas.width=canvas.width;RGraph.ObjectRegistry.Clear(canvas);canvas.__rgraph_aa_translated__=false;} +function pd(variable){RGraph.pr(variable);} +function p(variable){RGraph.pr(variable);} +function a(variable){alert(variable);} +function cl(variable){return console.log(variable);} \ No newline at end of file diff --git a/other-scripts/Steel-Gauges/web_server/script/src/RGraph.rose.js b/other-scripts/Steel-Gauges/web_server/script/src/RGraph.rose.js new file mode 100644 index 0000000..2e2c176 --- /dev/null +++ b/other-scripts/Steel-Gauges/web_server/script/src/RGraph.rose.js @@ -0,0 +1,1204 @@ + /** + * o------------------------------------------------------------------------------o + * | This file is part of the RGraph package - you can learn more at: | + * | | + * | http://www.rgraph.net | + * | | + * | This package is licensed under the RGraph license. For all kinds of business | + * | purposes there is a small one-time licensing fee to pay and for non | + * | commercial purposes it is free to use. You can read the full license here: | + * | | + * | http://www.rgraph.net/LICENSE.txt | + * o------------------------------------------------------------------------------o + */ + + if (typeof(RGraph) == 'undefined') RGraph = {}; + + /** + * The rose chart constuctor + * + * @param object canvas + * @param array data + */ + RGraph.Rose = function (id, data) + { + this.id = id; + this.canvas = document.getElementById(id); + this.context = this.canvas.getContext('2d'); + this.data = data; + this.canvas.__object__ = this; + this.type = 'rose'; + this.isRGraph = true; + this.uid = RGraph.CreateUID(); + this.canvas.uid = this.canvas.uid ? this.canvas.uid : RGraph.CreateUID(); + this.colorsParsed = false; + + + /** + * Compatibility with older browsers + */ + RGraph.OldBrowserCompat(this.context); + + + this.centerx = 0; + this.centery = 0; + this.radius = 0; + this.max = 0; + this.angles = []; + + this.properties = { + 'chart.background.axes': true, + 'chart.background.axes.color': 'black', + 'chart.background.grid': true, + 'chart.background.grid.color': '#ccc', + 'chart.background.grid.size': null, + 'chart.background.grid.spokes': null, + 'chart.background.grid.count': 5, + 'chart.centerx': null, + 'chart.centery': null, + 'chart.radius': null, + 'chart.colors': ['rgba(255,0,0,0.5)', 'rgba(255,255,0,0.5)', 'rgba(0,255,255,0.5)', 'rgb(0,255,0)', 'gray', 'blue', 'rgb(255,128,255)','green', 'pink', 'gray', 'aqua'], + 'chart.colors.sequential': false, + 'chart.colors.alpha': null, + 'chart.margin': 0, + 'chart.strokestyle': '#aaa', + 'chart.gutter.left': 25, + 'chart.gutter.right': 25, + 'chart.gutter.top': 25, + 'chart.gutter.bottom': 25, + 'chart.title': '', + 'chart.title.background': null, + 'chart.title.hpos': null, + 'chart.title.vpos': null, + 'chart.title.bold': true, + 'chart.title.font': null, + 'chart.title.x': null, + 'chart.title.y': null, + 'chart.title.halign': null, + 'chart.title.valign': null, + 'chart.labels': null, + 'chart.labels.position': 'center', + 'chart.labels.axes': 'nsew', + 'chart.labels.offset': 0, + 'chart.text.color': 'black', + 'chart.text.font': 'Arial', + 'chart.text.size': 10, + 'chart.key': null, + 'chart.key.background': 'white', + 'chart.key.position': 'graph', + 'chart.key.halign': 'right', + 'chart.key.shadow': false, + 'chart.key.shadow.color': '#666', + 'chart.key.shadow.blur': 3, + 'chart.key.shadow.offsetx': 2, + 'chart.key.shadow.offsety': 2, + 'chart.key.position.gutter.boxed': true, + 'chart.key.position.x': null, + 'chart.key.position.y': null, + 'chart.key.color.shape': 'square', + 'chart.key.rounded': true, + 'chart.key.linewidth': 1, + 'chart.key.colors': null, + 'chart.contextmenu': null, + 'chart.tooltips': null, + 'chart.tooltips.event': 'onclick', + 'chart.tooltips.effect': 'fade', + 'chart.tooltips.css.class': 'RGraph_tooltip', + 'chart.tooltips.highlight': true, + 'chart.highlight.stroke': 'rgba(0,0,0,0)', + 'chart.highlight.fill': 'rgba(255,255,255,0.7)', + 'chart.annotatable': false, + 'chart.annotate.color': 'black', + 'chart.zoom.factor': 1.5, + 'chart.zoom.fade.in': true, + 'chart.zoom.fade.out': true, + 'chart.zoom.hdir': 'right', + 'chart.zoom.vdir': 'down', + 'chart.zoom.frames': 25, + 'chart.zoom.delay': 16.666, + 'chart.zoom.shadow': true, + 'chart.zoom.background': true, + 'chart.zoom.action': 'zoom', + 'chart.resizable': false, + 'chart.resize.handle.adjust': [0,0], + 'chart.resize.handle.background': null, + 'chart.adjustable': false, + 'chart.ymax': null, + 'chart.ymin': 0, + 'chart.scale.decimals': null, + 'chart.scale.point': '.', + 'chart.scale.thousand': ',', + 'chart.variant': 'stacked', + 'chart.exploded': 0, + 'chart.events.mousemove': null, + 'chart.events.click': null, + 'chart.animation.roundrobin.factor': 1, + 'chart.animation.roundrobin.radius': true, + 'chart.animation.grow.multiplier': 1 + } + + + + /** + * Create the $ objects. In the case of non-equi-angular rose charts it actually creates too many $ objects, + * but it doesn't matter. + */ + var linear_data = RGraph.array_linearize(this.data); + for (var i=0; i 0 && this.Get('chart.key').length >= 3) { + this.centerx = this.centerx - this.Get('chart.gutter.right') + 5; + } + + + + // User specified radius, centerx and centery + if (typeof(this.Get('chart.centerx')) == 'number') this.centerx = this.Get('chart.centerx'); + if (typeof(this.Get('chart.centery')) == 'number') this.centery = this.Get('chart.centery'); + if (typeof(this.Get('chart.radius')) == 'number') this.radius = this.Get('chart.radius'); + + /** + * Parse the colors for gradients. Its down here so that the center X/Y can be used + */ + if (!this.colorsParsed) { + + this.parseColors(); + + // Don't want to do this again + this.colorsParsed = true; + } + + this.DrawBackground(); + this.DrawRose(); + this.DrawLabels(); + + /** + * Setup the context menu if required + */ + if (this.Get('chart.contextmenu')) { + RGraph.ShowContext(this); + } + + + /** + * This function enables resizing + */ + if (this.Get('chart.resizable')) { + RGraph.AllowResizing(this); + } + + + /** + * This function enables adjusting + */ + if (this.Get('chart.adjustable')) { + RGraph.AllowAdjusting(this); + } + + + /** + * This installs the event listeners + */ + RGraph.InstallEventListeners(this); + + + /** + * Fire the RGraph ondraw event + */ + RGraph.FireCustomEvent(this, 'ondraw'); + } + + /** + * This method draws the rose charts background + */ + RGraph.Rose.prototype.DrawBackground = function () + { + this.context.lineWidth = 1; + + + + + + // Draw the background grey circles/spokes + if (this.properties['chart.background.grid']) { + if (typeof(this.properties['chart.background.grid.count']) == 'number') { + this.properties['chart.background.grid.size'] = this.radius / this.properties['chart.background.grid.count']; + } + + this.context.beginPath(); + this.context.strokeStyle = this.properties['chart.background.grid.color']; + + // Radius must be greater than 0 for Opera to work + for (var i=this.properties['chart.background.grid.size']; i<=this.radius; i+=this.properties['chart.background.grid.size']) { + + //this.context.moveTo(this.centerx + i, this.centery); + + // Radius must be greater than 0 for Opera to work + this.context.arc(this.centerx, + this.centery, + i, + 0, + TWOPI, + false); + } + this.context.stroke(); + + + + + + + // Draw the background lines that go from the center outwards + this.context.beginPath(); + if (typeof(this.properties['chart.background.grid.spokes']) == 'number') { + + var num = (360 / this.properties['chart.background.grid.spokes']); + + for (var i=num; i<=360; i+=num) { + + // Radius must be greater than 0 for Opera to work + this.context.arc(this.centerx, + this.centery, + this.radius, + (i / (180 / PI)) - HALFPI, + ((i + 0.0001) / (180 / PI)) - HALFPI, + 0); + + this.context.lineTo(this.centerx, this.centery); + } + } else { + for (var i=15; i<=360; i+=15) { + + // Radius must be greater than 0 for Opera to work + this.context.arc(this.centerx, + this.centery, + this.radius, + (i / (180/ PI)) - HALFPI, + ((i + 0.0001) / (180/ PI)) - HALFPI, + false); + + this.context.lineTo(this.centerx, this.centery); + } + } + this.context.stroke(); + } + + + + if (this.Get('chart.background.axes')) { + this.context.beginPath(); + this.context.strokeStyle = this.Get('chart.background.axes.color'); + + // Draw the X axis + this.context.moveTo(this.centerx - this.radius, Math.round(this.centery) ); + this.context.lineTo(this.centerx + this.radius, Math.round(this.centery) ); + + // Draw the X ends + this.context.moveTo(Math.round(this.centerx - this.radius), this.centery - 5); + this.context.lineTo(Math.round(this.centerx - this.radius), this.centery + 5); + this.context.moveTo(Math.round(this.centerx + this.radius), this.centery - 5); + this.context.lineTo(Math.round(this.centerx + this.radius), this.centery + 5); + + // Draw the X check marks + for (var i=(this.centerx - this.radius); i<(this.centerx + this.radius); i+=(this.radius / 5)) { + this.context.moveTo(Math.round(i), this.centery - 3); + this.context.lineTo(Math.round(i), this.centery + 3.5); + } + + // Draw the Y check marks + for (var i=(this.centery - this.radius); i<(this.centery + this.radius); i+=(this.radius / 5)) { + this.context.moveTo(this.centerx - 3, Math.round(i)); + this.context.lineTo(this.centerx + 3, Math.round(i)); + } + + // Draw the Y axis + this.context.moveTo(Math.round(this.centerx), this.centery - this.radius); + this.context.lineTo(Math.round(this.centerx), this.centery + this.radius); + + // Draw the Y ends + this.context.moveTo(this.centerx - 5, Math.round(this.centery - this.radius)); + this.context.lineTo(this.centerx + 5, Math.round(this.centery - this.radius)); + + this.context.moveTo(this.centerx - 5, Math.round(this.centery + this.radius)); + this.context.lineTo(this.centerx + 5, Math.round(this.centery + this.radius)); + + // Stroke it + this.context.closePath(); + this.context.stroke(); + } + } + + + + /** + * This method draws the data on the graph + */ + RGraph.Rose.prototype.DrawRose = function () + { + var max = 0; + var data = this.data; + var margin = RGraph.degrees2Radians(this.Get('chart.margin')); + + // Must be at least two data points + //if (data.length < 2) { + // alert('[ROSE] Must be at least two data points! [' + data + ']'); + // return; + //} + + // Work out the maximum value and the sum + if (!this.Get('chart.ymax')) { + // Work out the max + for (var i=0; i -1) { + RGraph.Text(context, font_face, font_size, this.centerx, this.centery - (r * 0.2), RGraph.number_format(this, Number(this.scale[0]).toFixed(decimals), units_pre, units_post), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery - (r * 0.4), RGraph.number_format(this, Number(this.scale[1]).toFixed(decimals), units_pre, units_post), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery - (r * 0.6), RGraph.number_format(this, Number(this.scale[2]).toFixed(decimals), units_pre, units_post), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery - (r * 0.8), RGraph.number_format(this, Number(this.scale[3]).toFixed(decimals), units_pre, units_post), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery - r, RGraph.number_format(this, Number(this.scale[4]).toFixed(decimals), units_pre, units_post), 'center', 'center', true, false, color); + } + + // The "South" axis labels + if (axes.indexOf('s') > -1) { + RGraph.Text(context, font_face, font_size, this.centerx, this.centery + (r * 0.2), RGraph.number_format(this, Number(this.scale[0]).toFixed(decimals), units_pre, units_post), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery + (r * 0.4), RGraph.number_format(this, Number(this.scale[1]).toFixed(decimals), units_pre, units_post), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery + (r * 0.6), RGraph.number_format(this, Number(this.scale[2]).toFixed(decimals), units_pre, units_post), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery + (r * 0.8), RGraph.number_format(this, Number(this.scale[3]).toFixed(decimals), units_pre, units_post), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery + r, RGraph.number_format(this, Number(this.scale[4]).toFixed(decimals), units_pre, units_post), 'center', 'center', true, false, color); + } + + // The "East" axis labels + if (axes.indexOf('e') > -1) { + RGraph.Text(context, font_face, font_size, this.centerx + (r * 0.2), this.centery, RGraph.number_format(this, Number(this.scale[0]).toFixed(decimals), units_pre, units_post), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx + (r * 0.4), this.centery, RGraph.number_format(this, Number(this.scale[1]).toFixed(decimals), units_pre, units_post), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx + (r * 0.6), this.centery, RGraph.number_format(this, Number(this.scale[2]).toFixed(decimals), units_pre, units_post), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx + (r * 0.8), this.centery, RGraph.number_format(this, Number(this.scale[3]).toFixed(decimals), units_pre, units_post), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx + r, this.centery, RGraph.number_format(this, Number(this.scale[4]).toFixed(decimals), units_pre, units_post), 'center', 'center', true, false, color); + } + + // The "West" axis labels + if (axes.indexOf('w') > -1) { + RGraph.Text(context, font_face, font_size, this.centerx - (r * 0.2), this.centery, RGraph.number_format(this, Number(this.scale[0]).toFixed(decimals), units_pre, units_post), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx - (r * 0.4), this.centery, RGraph.number_format(this, Number(this.scale[1]).toFixed(decimals), units_pre, units_post), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx - (r * 0.6), this.centery, RGraph.number_format(this, Number(this.scale[2]).toFixed(decimals), units_pre, units_post), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx - (r * 0.8), this.centery, RGraph.number_format(this, Number(this.scale[3]).toFixed(decimals), units_pre, units_post), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx - r, this.centery, RGraph.number_format(this, Number(this.scale[4]).toFixed(decimals), units_pre, units_post), 'center', 'center', true, false, color); + } + + if (axes.length > 0) { + RGraph.Text(context, font_face, font_size, this.centerx, this.centery, typeof(this.Get('chart.ymin')) == 'number' ? RGraph.number_format(this, Number(this.Get('chart.ymin')).toFixed(this.Get('chart.scale.decimals')), units_pre, units_post) : '0', 'center', 'center', true, false, color); + } + } + + + /** + * Draws the circular labels that go around the charts + * + * @param labels array The labels that go around the chart + */ + RGraph.Rose.prototype.DrawCircularLabels = function (context, labels, font_face, font_size, r) + { + var variant = this.Get('chart.variant'); + var position = this.Get('chart.labels.position'); + var r = r + 5 + this.Get('chart.labels.offset'); + + for (var i=0; i this.centerx) { + halign = 'left'; + } else if (x == this.centerx) { + halign = 'center'; + } else { + halign = 'right'; + } + + RGraph.Text(context, font_face, font_size, x, y, String(labels[i]), 'center', halign); + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + /** + * This function is for use with circular graph types, eg the Pie or Rose. Pass it your event object + * and it will pass you back the corresponding segment details as an array: + * + * [x, y, r, startAngle, endAngle] + * + * Angles are measured in degrees, and are measured from the "east" axis (just like the canvas). + * + * @param object e Your event object + */ + RGraph.Rose.prototype.getShape = + RGraph.Rose.prototype.getSegment = function (e) + { + RGraph.FixEventObject(e); + + var canvas = this.canvas; + var context = this.context; + var angles = this.angles; + var ret = []; + + /** + * Go through all of the angles checking each one + */ + for (var i=0; i 0) { + this.context.arc(shape['x'], shape['y'], shape['radius.start'], shape['angle.end'], shape['angle.start'], true); + } else { + this.context.lineTo(shape['x'], shape['y']); + } + this.context.closePath(); + + this.context.stroke(); + this.context.fill(); + } + } + + + + /** + * The getObjectByXY() worker method. Don't call this call: + * + * RGraph.ObjectRegistry.getObjectByXY(e) + * + * @param object e The event object + */ + RGraph.Rose.prototype.getObjectByXY = function (e) + { + var mouseXY = RGraph.getMouseXY(e); + + // Work out the radius + var radius = RGraph.getHypLength(this.centerx, this.centery, mouseXY[0], mouseXY[1]); + + if ( + mouseXY[0] > (this.centerx - this.radius) + && mouseXY[0] < (this.centerx + this.radius) + && mouseXY[1] > (this.centery - this.radius) + && mouseXY[1] < (this.centery + this.radius) + && radius <= this.radius + ) { + + return this; + } + } + + + + /** + * This function positions a tooltip when it is displayed + * + * @param obj object The chart object + * @param int x The X coordinate specified for the tooltip + * @param int y The Y coordinate specified for the tooltip + * @param objec tooltip The tooltips DIV element + */ + RGraph.Rose.prototype.positionTooltip = function (obj, x, y, tooltip, idx) + { + + var coordX = obj.angles[idx][4]; + var coordY = obj.angles[idx][5]; + var angleStart = obj.angles[idx][0]; + var angleEnd = obj.angles[idx][1]; + var radius = ((obj.angles[idx][3] - obj.angles[idx][2]) / 2) + obj.angles[idx][2]; + + var angleCenter = ((angleEnd - angleStart) / 2) + angleStart; + var canvasXY = RGraph.getCanvasXY(obj.canvas); + var gutterLeft = obj.Get('chart.gutter.left'); + var gutterTop = obj.Get('chart.gutter.top'); + var width = tooltip.offsetWidth; + var height = tooltip.offsetHeight; + + + // By default any overflow is hidden + tooltip.style.overflow = ''; + + // The arrow + var img = new Image(); + img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAFCAYAAACjKgd3AAAARUlEQVQYV2NkQAN79+797+RkhC4M5+/bd47B2dmZEVkBCgcmgcsgbAaA9GA1BCSBbhAuA/AagmwQPgMIGgIzCD0M0AMMAEFVIAa6UQgcAAAAAElFTkSuQmCC'; + img.style.position = 'absolute'; + img.id = '__rgraph_tooltip_pointer__'; + img.style.top = (tooltip.offsetHeight - 2) + 'px'; + tooltip.appendChild(img); + + // Reposition the tooltip if at the edges: + + // LEFT edge + if ((canvasXY[0] + coordX + (Math.cos(angleCenter) * radius) - (width / 2)) < 10) { + tooltip.style.left = (canvasXY[0] + coordX + (Math.cos(angleCenter) * radius)- (width * 0.1)) + 'px'; + tooltip.style.top = (canvasXY[1] + coordY + (Math.sin(angleCenter) * radius)- height - 5) + 'px'; + img.style.left = ((width * 0.1) - 8.5) + 'px'; + + // RIGHT edge + } else if ((canvasXY[0] + coordX + (Math.cos(angleCenter) * radius) + (width / 2)) > (document.body.offsetWidth - 10) ) { + tooltip.style.left = (canvasXY[0] + coordX + (Math.cos(angleCenter) * radius) - (width * 0.9)) + 'px'; + tooltip.style.top = (canvasXY[1] + coordY + (Math.sin(angleCenter) * radius)- height - 5) + 'px'; + img.style.left = ((width * 0.9) - 8.5) + 'px'; + + // Default positioning - CENTERED + } else { + tooltip.style.left = (canvasXY[0] + coordX + (Math.cos(angleCenter) * radius)- (width / 2)) + 'px'; + tooltip.style.top = (canvasXY[1] + coordY + (Math.sin(angleCenter) * radius)- height - 5) + 'px'; + img.style.left = ((width * 0.5) - 8.5) + 'px'; + } + } + + + + /** + * This method gives you the relevant radius for a particular value + * + * @param number value The relevant value to get the radius for + */ + RGraph.Rose.prototype.getRadius = function (value) + { + // Range checking (the Rose minimum is always 0) + if (value < 0 || value > this.max) { + return null; + } + + var r = (value / this.max) * this.radius; + + return r; + } + + + + /** + * This allows for easy specification of gradients + */ + RGraph.Rose.prototype.parseColors = function () + { + for (var i=0; i maxValue) { + start = maxValue; + } + if (stop < minValue) { + stop = minValue; + } else if (stop > maxValue) { + stop = maxValue; + } + if (start >= stop) { + return; + } + ctx.save(); + ctx.strokeStyle = color; + ctx.fillStyle = color; + ctx.lineWidth = imageWidth * 0.035; + var startAngle = (angleRange / range * start - angleRange / range * minValue); + var stopAngle = startAngle + (stop - start) / (range / angleRange); + ctx.translate(centerX, centerY); + ctx.rotate(rotationOffset); + ctx.beginPath(); + if (filled) { + ctx.moveTo(0, 0); + ctx.arc(0, 0, imageWidth * 0.365 - ctx.lineWidth / 2, startAngle, stopAngle, false); + } else { + ctx.arc(0, 0, imageWidth * 0.365, startAngle, stopAngle, false); + } + if (filled) { + ctx.moveTo(0, 0); + ctx.fill(); + } else { + ctx.stroke(); + } + + ctx.translate(-centerX, -centerY); + ctx.restore(); + }; + + var drawTickmarksImage = function (ctx, labelNumberFormat) { + var fontSize = Math.ceil(imageWidth * 0.04), + alpha = rotationOffset, // Tracks total rotation + rotationStep = angleStep * minorTickSpacing, + textRotationAngle, + valueCounter = minValue, + majorTickCounter = maxNoOfMinorTicks - 1, + OUTER_POINT = imageWidth * 0.38, + MAJOR_INNER_POINT = imageWidth * 0.35, + MED_INNER_POINT = imageWidth * 0.355, + MINOR_INNER_POINT = imageWidth * 0.36, + TEXT_TRANSLATE_X = imageWidth * 0.3, + TEXT_WIDTH = imageWidth * 0.1, + HALF_MAX_NO_OF_MINOR_TICKS = maxNoOfMinorTicks / 2, + MAX_VALUE_ROUNDED = parseFloat(maxValue.toFixed(2)), + i; + + backgroundColor.labelColor.setAlpha(1); + ctx.save(); + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.font = fontSize + 'px ' + stdFontName; + ctx.strokeStyle = backgroundColor.labelColor.getRgbaColor(); + ctx.fillStyle = backgroundColor.labelColor.getRgbaColor(); + ctx.translate(centerX, centerY); + ctx.rotate(rotationOffset); + + if (gaugeType.type === 'type1' || gaugeType.type === 'type2') { + TEXT_WIDTH = imageWidth * 0.04; + } + + for (i = minValue; parseFloat(i.toFixed(2)) <= MAX_VALUE_ROUNDED; i += minorTickSpacing) { + textRotationAngle = rotationStep + HALF_PI; + majorTickCounter++; + // Draw major tickmarks + if (majorTickCounter === maxNoOfMinorTicks) { + ctx.lineWidth = 1.5; + ctx.beginPath(); + ctx.moveTo(OUTER_POINT, 0); + ctx.lineTo(MAJOR_INNER_POINT, 0); + ctx.closePath(); + ctx.stroke(); + ctx.save(); + ctx.translate(TEXT_TRANSLATE_X, 0); + + switch (tickLabelOrientation.type) { + case 'horizontal': + textRotationAngle = -alpha; + break; + + case 'tangent': + textRotationAngle = (alpha <= HALF_PI + PI ? PI : 0); + break; + + case 'normal': + /* falls through */ + default: + textRotationAngle = HALF_PI; + break; + } + ctx.rotate(textRotationAngle); + + switch (labelNumberFormat.format) { + case 'fractional': + ctx.fillText((valueCounter.toFixed(fractionalScaleDecimals)), 0, 0, TEXT_WIDTH); + break; + + case 'scientific': + ctx.fillText((valueCounter.toPrecision(2)), 0, 0, TEXT_WIDTH); + break; + + case 'standard': + /* falls through */ + default: + ctx.fillText((valueCounter.toFixed(0)), 0, 0, TEXT_WIDTH); + break; + } + ctx.translate(-TEXT_TRANSLATE_X, 0); + ctx.restore(); + + valueCounter += majorTickSpacing; + majorTickCounter = 0; + ctx.rotate(rotationStep); + alpha += rotationStep; + continue; + } + + // Draw tickmark every minor tickmark spacing + if (0 === maxNoOfMinorTicks % 2 && majorTickCounter === (HALF_MAX_NO_OF_MINOR_TICKS)) { + ctx.lineWidth = 1; + ctx.beginPath(); + ctx.moveTo(OUTER_POINT, 0); + ctx.lineTo(MED_INNER_POINT, 0); + ctx.closePath(); + ctx.stroke(); + } else { + ctx.lineWidth = 0.5; + ctx.beginPath(); + ctx.moveTo(OUTER_POINT, 0); + ctx.lineTo(MINOR_INNER_POINT, 0); + ctx.closePath(); + ctx.stroke(); + } + ctx.rotate(rotationStep); + alpha += rotationStep; + } + + /* + // Logarithmic scale + var tmp = 0.1; + var minValueLog10 = 0.1; + var maxValueLog10 = parseInt(Math.pow(10, Math.ceil(Math.log10(maxValue)))); + var drawLabel = true; + angleStep = angleRange / (maxValueLog10 - minValueLog10) + for (var scaleFactor = minValueLog10 ; scaleFactor <= maxValueLog10 ; scaleFactor *= 10) + { + for (var i = parseFloat((1 * scaleFactor).toFixed(1)) ; i < parseFloat((10 * scaleFactor).toFixed(1)) ; i += scaleFactor) + { + textRotationAngle =+ rotationStep + HALF_PI; + + if(drawLabel) + { + ctx.lineWidth = 1.5; + ctx.beginPath(); + ctx.moveTo(imageWidth * 0.38,0); + ctx.lineTo(imageWidth * 0.35,0); + ctx.closePath(); + ctx.stroke(); + ctx.save(); + ctx.translate(imageWidth * 0.31, 0); + ctx.rotate(textRotationAngle); + ctx.fillText(parseFloat((i).toFixed(1)), 0, 0, imageWidth * 0.0375); + ctx.translate(-imageWidth * 0.31, 0); + ctx.restore(); + drawLabel = false; + } + else + { + ctx.lineWidth = 0.5; + ctx.beginPath(); + ctx.moveTo(imageWidth * 0.38,0); + ctx.lineTo(imageWidth * 0.36,0); + ctx.closePath(); + ctx.stroke(); + } + //doc.write('log10 scale value: ' + parseFloat((i).toFixed(1)) + '
'); + //Math.log10(parseFloat((i).toFixed(1))); + + ctx.rotate(rotationStep); + } + tmp = 0.1; + drawLabel = true; + } + */ + + ctx.translate(-centerX, -centerY); + ctx.restore(); + }; + + // ************** Initialization ******************** + // Draw all static painting code to background + var init = function (parameters) { + parameters = parameters || {}; + var drawFrame = (undefined === parameters.frame ? false : parameters.frame); + var drawBackground = (undefined === parameters.background ? false : parameters.background); + var drawLed = (undefined === parameters.led ? false : parameters.led); + var drawUserLed = (undefined === parameters.userLed ? false : parameters.userLed); + var drawPointer = (undefined === parameters.pointer ? false : parameters.pointer); + var drawForeground = (undefined === parameters.foreground ? false : parameters.foreground); + var drawTrend = (undefined === parameters.trend ? false : parameters.trend); + var drawOdo = (undefined === parameters.odo ? false : parameters.odo); + + initialized = true; + + // Calculate the current min and max values and the range + calculate(); + + // Create frame in frame buffer (backgroundBuffer) + if (drawFrame && frameVisible) { + drawRadialFrameImage(frameContext, frameDesign, centerX, centerY, imageWidth, imageHeight); + } + + // Create background in background buffer (backgroundBuffer) + if (drawBackground && backgroundVisible) { + drawRadialBackgroundImage(backgroundContext, backgroundColor, centerX, centerY, imageWidth, imageHeight); + + // Create custom layer in background buffer (backgroundBuffer) + drawRadialCustomImage(backgroundContext, customLayer, centerX, centerY, imageWidth, imageHeight); + } + + if (drawLed) { + // Draw LED ON in ledBuffer_ON + ledContextOn.drawImage(createLedImage(Math.ceil(size * 0.093457), 1, ledColor), 0, 0); + + // Draw LED OFF in ledBuffer_OFF + ledContextOff.drawImage(createLedImage(Math.ceil(size * 0.093457), 0, ledColor), 0, 0); + } + + if (drawUserLed) { + // Draw user LED ON in userLedBuffer_ON + userLedContextOn.drawImage(createLedImage(Math.ceil(size * 0.093457), 1, userLedColor), 0, 0); + + // Draw user LED OFF in userLedBuffer_OFF + userLedContextOff.drawImage(createLedImage(Math.ceil(size * 0.093457), 0, userLedColor), 0, 0); + } + + // Draw min measured value indicator in minMeasuredValueBuffer + if (minMeasuredValueVisible) { + minMeasuredValueCtx.drawImage(createMeasuredValueImage(Math.ceil(size * 0.028037), steelseries.ColorDef.BLUE.dark.getRgbaColor(), true, true), 0, 0); + } + + // Draw max measured value indicator in maxMeasuredValueBuffer + if (maxMeasuredValueVisible) { + maxMeasuredValueCtx.drawImage(createMeasuredValueImage(Math.ceil(size * 0.028037), steelseries.ColorDef.RED.medium.getRgbaColor(), true), 0, 0); + } + + // Create alignment posts in background buffer (backgroundBuffer) + if (drawBackground && backgroundVisible) { + drawPostsImage(backgroundContext); + + // Create section in background buffer (backgroundBuffer) + if (null !== section && 0 < section.length) { + var sectionIndex = section.length; + do { + sectionIndex--; + drawAreaSectionImage(backgroundContext, section[sectionIndex].start, section[sectionIndex].stop, section[sectionIndex].color, false); + } + while (0 < sectionIndex); + } + + // Create area in background buffer (backgroundBuffer) + if (null !== area && 0 < area.length) { + var areaIndex = area.length; + do { + areaIndex--; + drawAreaSectionImage(backgroundContext, area[areaIndex].start, area[areaIndex].stop, area[areaIndex].color, true); + } + while (0 < areaIndex); + } + + // Create tickmarks in background buffer (backgroundBuffer) + drawTickmarksImage(backgroundContext, labelNumberFormat); + + // Create title in background buffer (backgroundBuffer) + drawTitleImage(backgroundContext, imageWidth, imageHeight, titleString, unitString, backgroundColor, true, true); + } + + // Draw threshold image to background context + if (drawBackground && thresholdVisible) { + backgroundContext.save(); + backgroundContext.translate(centerX, centerY); + backgroundContext.rotate(rotationOffset + (threshold - minValue) * angleStep + HALF_PI); + backgroundContext.translate(-centerX, -centerY); + backgroundContext.drawImage(createThresholdImage(), imageWidth * 0.475, imageHeight * 0.13); + backgroundContext.translate(centerX, centerY); + backgroundContext.restore(); + } + + // Create lcd background if selected in background buffer (backgroundBuffer) + if (drawBackground && lcdVisible) { + if (useOdometer && drawOdo) { + odoGauge = new steelseries.Odometer('', { + _context: odoContext, + height: size * 0.075, + decimals: odometerParams.decimals, + digits: (odometerParams.digits === undefined ? 5 : odometerParams.digits), + valueForeColor: odometerParams.valueForeColor, + valueBackColor: odometerParams.valueBackColor, + decimalForeColor: odometerParams.decimalForeColor, + decimalBackColor: odometerParams.decimalBackColor, + font: odometerParams.font, + value: value + }); + odoPosX = (imageWidth - odoBuffer.width) / 2; + } else if (!useOdometer) { + lcdBuffer = createLcdBackgroundImage(lcdWidth, lcdHeight, lcdColor); + backgroundContext.drawImage(lcdBuffer, lcdPosX, lcdPosY); + } + } + + // Create pointer image in pointer buffer (contentBuffer) + if (drawPointer) { + drawPointerImage(pointerContext, imageWidth, pointerType, pointerColor, backgroundColor.labelColor); + } + + // Create foreground in foreground buffer (foregroundBuffer) + if (drawForeground && foregroundVisible) { + var knobVisible = (pointerType.type === 'type15' || pointerType.type === 'type16' ? false : true); + drawRadialForegroundImage(foregroundContext, foregroundType, imageWidth, imageHeight, knobVisible, knobType, knobStyle, gaugeType); + } + + // Create the trend indicator buffers + if (drawTrend && trendVisible) { + trendUpBuffer = createTrendIndicator(trendSize, steelseries.TrendState.UP, trendColors); + trendSteadyBuffer = createTrendIndicator(trendSize, steelseries.TrendState.STEADY, trendColors); + trendDownBuffer = createTrendIndicator(trendSize, steelseries.TrendState.DOWN, trendColors); + trendOffBuffer = createTrendIndicator(trendSize, steelseries.TrendState.OFF, trendColors); + } + }; + + var resetBuffers = function (buffers) { + buffers = buffers || {}; + var resetFrame = (undefined === buffers.frame ? false : buffers.frame); + var resetBackground = (undefined === buffers.background ? false : buffers.background); + var resetLed = (undefined === buffers.led ? false : buffers.led); + var resetUserLed = (undefined === buffers.userLed ? false : buffers.userLed); + var resetPointer = (undefined === buffers.pointer ? false : buffers.pointer); + var resetForeground = (undefined === buffers.foreground ? false : buffers.foreground); + + if (resetFrame) { + frameBuffer.width = size; + frameBuffer.height = size; + frameContext = frameBuffer.getContext('2d'); + } + + if (resetBackground) { + backgroundBuffer.width = size; + backgroundBuffer.height = size; + backgroundContext = backgroundBuffer.getContext('2d'); + } + + if (resetLed) { + ledBufferOn.width = Math.ceil(size * 0.093457); + ledBufferOn.height = Math.ceil(size * 0.093457); + ledContextOn = ledBufferOn.getContext('2d'); + + ledBufferOff.width = Math.ceil(size * 0.093457); + ledBufferOff.height = Math.ceil(size * 0.093457); + ledContextOff = ledBufferOff.getContext('2d'); + + // Buffer for current led painting code + ledBuffer = ledBufferOff; + } + + if (resetUserLed) { + userLedBufferOn.width = Math.ceil(size * 0.093457); + userLedBufferOn.height = Math.ceil(size * 0.093457); + userLedContextOn = userLedBufferOn.getContext('2d'); + + userLedBufferOff.width = Math.ceil(size * 0.093457); + userLedBufferOff.height = Math.ceil(size * 0.093457); + userLedContextOff = userLedBufferOff.getContext('2d'); + + // Buffer for current user led painting code + userLedBuffer = userLedBufferOff; + } + + if (resetPointer) { + pointerBuffer.width = size; + pointerBuffer.height = size; + pointerContext = pointerBuffer.getContext('2d'); + } + + if (resetForeground) { + foregroundBuffer.width = size; + foregroundBuffer.height = size; + foregroundContext = foregroundBuffer.getContext('2d'); + } + }; + + var toggleAndRepaintLed = function () { + if (ledVisible) { + if (ledBuffer === ledBufferOn) { + ledBuffer = ledBufferOff; + } else { + ledBuffer = ledBufferOn; + } + if (!repainting) { + repainting = true; + requestAnimFrame(self.repaint); + } + } + }; + + var toggleAndRepaintUserLed = function () { + if (userLedVisible) { + if (userLedBuffer === userLedBufferOn) { + userLedBuffer = userLedBufferOff; + } else { + userLedBuffer = userLedBufferOn; + } + if (!repainting) { + repainting = true; + requestAnimFrame(self.repaint); + } + } + }; + + var blink = function (blinking) { + if (blinking) { + ledTimerId = setInterval(toggleAndRepaintLed, 1000); + } else { + clearInterval(ledTimerId); + ledBuffer = ledBufferOff; + } + }; + + var blinkUser = function (blinking) { + if (blinking) { + userLedTimerId = setInterval(toggleAndRepaintUserLed, 1000); + } else { + clearInterval(userLedTimerId); + userLedBuffer = userLedBufferOff; + } + }; + + //************************************ Public methods ************************************** + this.setValue = function (newValue) { + newValue = parseFloat(newValue); + var targetValue = newValue < minValue ? minValue : (newValue > maxValue ? maxValue : newValue); + if (value !== targetValue) { + value = targetValue; + + if (value > maxMeasuredValue) { + maxMeasuredValue = value; + } + if (value < minMeasuredValue) { + minMeasuredValue = value; + } + + if ((value >= threshold && !ledBlinking && thresholdRising) || + (value <= threshold && !ledBlinking && !thresholdRising)) { + ledBlinking = true; + blink(ledBlinking); + if (playAlarm) { + audioElement.play(); + } + } else if ((value < threshold && ledBlinking && thresholdRising) || + (value > threshold && ledBlinking && !thresholdRising)) { + ledBlinking = false; + blink(ledBlinking); + if (playAlarm) { + audioElement.pause(); + } + } + this.repaint(); + } + return this; + }; + + this.getValue = function () { + return value; + }; + + this.setOdoValue = function (newValue) { + newValue = parseFloat(newValue); + var targetValue = (newValue < 0 ? 0 : newValue); + if (odoValue !== targetValue) { + odoValue = targetValue; + this.repaint(); + } + return this; + }; + + this.getOdoValue = function () { + return odoValue; + }; + + this.setValueAnimated = function (newValue, callback) { + newValue = parseFloat(newValue); + var targetValue = (newValue < minValue ? minValue : (newValue > maxValue ? maxValue : newValue)), + gauge = this, + time; + + if (value !== targetValue) { + if (undefined !== tween && tween.isPlaying) { + tween.stop(); + } + time = fullScaleDeflectionTime * Math.abs(targetValue - value) / (maxValue - minValue); + time = Math.max(time, fullScaleDeflectionTime / 5); + tween = new Tween({}, '', Tween.regularEaseInOut, value, targetValue, time); + //tween = new Tween({}, '', Tween.regularEaseInOut, value, targetValue, 1); + //tween = new Tween(new Object(), '', Tween.strongEaseInOut, value, targetValue, 1); + + tween.onMotionChanged = function (event) { + value = event.target._pos; + + if ((value >= threshold && !ledBlinking && thresholdRising) || + (value <= threshold && !ledBlinking && !thresholdRising)) { + ledBlinking = true; + blink(ledBlinking); + if (playAlarm) { + audioElement.play(); + } + } else if ((value < threshold && ledBlinking && thresholdRising) || + (value > threshold && ledBlinking && !thresholdRising)) { + ledBlinking = false; + blink(ledBlinking); + if (playAlarm) { + audioElement.pause(); + } + } + + if (value > maxMeasuredValue) { + maxMeasuredValue = value; + } + if (value < minMeasuredValue) { + minMeasuredValue = value; + } + if (!repainting) { + repainting = true; + requestAnimFrame(gauge.repaint); + } + }; + + // do we have a callback function to process? + if (callback && typeof(callback) === "function") { + tween.onMotionFinished = callback; + } + + tween.start(); + } + return this; + }; + + this.resetMinMeasuredValue = function () { + minMeasuredValue = value; + this.repaint(); + }; + + this.resetMaxMeasuredValue = function () { + maxMeasuredValue = value; + this.repaint(); + return this; + }; + + this.setMinMeasuredValueVisible = function (visible) { + minMeasuredValueVisible = !!visible; + this.repaint(); + return this; + }; + + this.setMaxMeasuredValueVisible = function (visible) { + maxMeasuredValueVisible = !!visible; + this.repaint(); + return this; + }; + + this.setMaxMeasuredValue = function (newValue) { + newValue = parseFloat(newValue); + var targetValue = newValue < minValue ? minValue : (newValue > maxValue ? maxValue : newValue); + maxMeasuredValue = targetValue; + this.repaint(); + return this; + }; + + this.setMinMeasuredValue = function (newValue) { + newValue = parseFloat(newValue); + var targetValue = newValue < minValue ? minValue : (newValue > maxValue ? maxValue : newValue); + minMeasuredValue = targetValue; + this.repaint(); + return this; + }; + + this.setTitleString = function (title) { + titleString = title; + resetBuffers({background: true}); + init({background: true}); + this.repaint(); + return this; + }; + + this.setUnitString = function (unit) { + unitString = unit; + resetBuffers({background: true}); + init({background: true}); + this.repaint(); + return this; + }; + + this.setMinValue = function (value) { + minValue = parseFloat(value); + resetBuffers({frame: true, + background: true}); + init({frame: true, + background: true}); + this.repaint(); + return this; + }; + + this.getMinValue = function () { + return minValue; + }; + + this.setMaxValue = function (value) { + maxValue = parseFloat(value); + resetBuffers({frame: true, + background: true}); + init({frame: true, + background: true}); + this.repaint(); + return this; + }; + + this.getMaxValue = function () { + return maxValue; + }; + + this.setThreshold = function (newValue) { + newValue = parseFloat(newValue); + var targetValue = newValue < minValue ? minValue : (newValue > maxValue ? maxValue : newValue); + threshold = targetValue; + resetBuffers({background: true}); + init({background: true}); + this.repaint(); + return this; + }; + + this.setArea = function (areaVal) { + area = areaVal; + resetBuffers({background: true, + foreground: true}); + init({background: true, + foreground: true + }); + this.repaint(); + return this; + }; + + this.setSection = function (areaSec) { + section = areaSec; + resetBuffers({background: true, + foreground: true}); + init({background: true, + foreground: true + }); + this.repaint(); + return this; + }; + + this.setThresholdVisible = function (visible) { + thresholdVisible = !!visible; + this.repaint(); + return this; + }; + + this.setThresholdRising = function (rising) { + thresholdRising = !!rising; + // reset existing threshold alerts + ledBlinking = !ledBlinking; + blink(ledBlinking); + this.repaint(); + return this; + }; + + this.setLcdDecimals = function (decimals) { + lcdDecimals = parseInt(decimals, 10); + this.repaint(); + return this; + }; + + this.setFrameDesign = function (newFrameDesign) { + resetBuffers({frame: true}); + frameDesign = newFrameDesign; + init({frame: true}); + this.repaint(); + return this; + }; + + this.setBackgroundColor = function (newBackgroundColor) { + resetBuffers({background: true, + pointer: (pointerType.type === 'type2' || pointerType.type === 'type13' ? true : false) // type2 & 13 depend on background + }); + backgroundColor = newBackgroundColor; + init({background: true, // type2 & 13 depend on background + pointer: (pointerType.type === 'type2' || pointerType.type === 'type13' ? true : false) + }); + this.repaint(); + return this; + }; + + this.setForegroundType = function (newForegroundType) { + resetBuffers({foreground: true}); + foregroundType = newForegroundType; + init({foreground: true}); + this.repaint(); + return this; + }; + + this.setPointerType = function (newPointerType) { + resetBuffers({pointer: true, + foreground: true + }); + pointerType = newPointerType; + init({pointer: true, + foreground: true + }); + this.repaint(); + return this; + }; + + this.setPointerColor = function (newPointerColor) { + resetBuffers({pointer: true}); + pointerColor = newPointerColor; + init({pointer: true}); + this.repaint(); + return this; + }; + + this.setLedColor = function (newLedColor) { + resetBuffers({led: true}); + ledColor = newLedColor; + init({led: true}); + this.repaint(); + return this; + }; + + this.setUserLedColor = function (newLedColor) { + resetBuffers({userLed: true}); + userLedColor = newLedColor; + init({userLed: true}); + this.repaint(); + return this; + }; + + this.toggleUserLed = function () { + if (userLedBuffer === userLedBufferOn) { + userLedBuffer = userLedBufferOff; + } else { + userLedBuffer = userLedBufferOn; + } + this.repaint(); + return this; + }; + + this.setUserLedOnOff = function (on) { + if (true === on) { + userLedBuffer = userLedBufferOn; + } else { + userLedBuffer = userLedBufferOff; + } + this.repaint(); + return this; + }; + + this.blinkUserLed = function (blink) { + if (blink) { + if (!userLedBlinking) { + blinkUser(true); + userLedBlinking = true; + } + } else { + if (userLedBlinking) { + clearInterval(userLedTimerId); + userLedBlinking = false; + } + } + return this; + }; + + this.setLedVisible = function (visible) { + ledVisible = !!visible; + this.repaint(); + return this; + }; + + this.setUserLedVisible = function (visible) { + userLedVisible = !!visible; + this.repaint(); + return this; + }; + + this.setLcdColor = function (newLcdColor) { + lcdColor = newLcdColor; + resetBuffers({background: true}); + init({background: true}); + this.repaint(); + return this; + }; + + this.setTrend = function (newValue) { + trendIndicator = newValue; + this.repaint(); + return this; + }; + + this.setTrendVisible = function (visible) { + trendVisible = !!visible; + this.repaint(); + return this; + }; + + this.setFractionalScaleDecimals = function (decimals) { + fractionalScaleDecimals = parseInt(decimals, 10); + resetBuffers({background: true}); + init({background: true}); + this.repaint(); + return this; + }; + + this.setLabelNumberFormat = function (format) { + labelNumberFormat = format; + resetBuffers({background: true}); + init({background: true}); + this.repaint(); + return this; + }; + + this.repaint = function () { + if (!initialized) { + init({frame: true, + background: true, + led: true, + userLed: true, + pointer: true, + trend: true, + foreground: true, + odo: true}); + } + mainCtx.clearRect(0, 0, size, size); + + // Draw frame + if (frameVisible) { + mainCtx.drawImage(frameBuffer, 0, 0); + } + + // Draw buffered image to visible canvas + mainCtx.drawImage(backgroundBuffer, 0, 0); + + // Draw lcd display + if (lcdVisible) { + if (useOdometer) { + odoGauge.setValue(odometerUseValue ? value : odoValue); + mainCtx.drawImage(odoBuffer, odoPosX, odoPosY); + } else { + drawLcdText(mainCtx, value); + } + } + + // Draw led + if (ledVisible) { + mainCtx.drawImage(ledBuffer, ledPosX, ledPosY); + } + + // Draw user led + if (userLedVisible) { + mainCtx.drawImage(userLedBuffer, userLedPosX, userLedPosY); + } + + // Draw the trend indicator + if (trendVisible) { + switch (trendIndicator.state) { + case 'up': + mainCtx.drawImage(trendUpBuffer, trendPosX, trendPosY); + break; + case 'steady': + mainCtx.drawImage(trendSteadyBuffer, trendPosX, trendPosY); + break; + case 'down': + mainCtx.drawImage(trendDownBuffer, trendPosX, trendPosY); + break; + case 'off': + mainCtx.drawImage(trendOffBuffer, trendPosX, trendPosY); + break; + } + } + + // Draw min measured value indicator + if (minMeasuredValueVisible) { + mainCtx.save(); + mainCtx.translate(centerX, centerY); + mainCtx.rotate(rotationOffset + HALF_PI + (minMeasuredValue - minValue) * angleStep); + mainCtx.translate(-centerX, -centerY); + mainCtx.drawImage(minMeasuredValueBuffer, mainCtx.canvas.width * 0.4865, mainCtx.canvas.height * 0.105); + mainCtx.restore(); + } + + // Draw max measured value indicator + if (maxMeasuredValueVisible) { + mainCtx.save(); + mainCtx.translate(centerX, centerY); + mainCtx.rotate(rotationOffset + HALF_PI + (maxMeasuredValue - minValue) * angleStep); + mainCtx.translate(-centerX, -centerY); + mainCtx.drawImage(maxMeasuredValueBuffer, mainCtx.canvas.width * 0.4865, mainCtx.canvas.height * 0.105); + mainCtx.restore(); + } + + angle = rotationOffset + HALF_PI + (value - minValue) * angleStep; + + // Define rotation center + mainCtx.save(); + mainCtx.translate(centerX, centerY); + mainCtx.rotate(angle); + mainCtx.translate(-centerX, -centerY); + // Set the pointer shadow params + mainCtx.shadowColor = 'rgba(0, 0, 0, 0.8)'; + mainCtx.shadowOffsetX = mainCtx.shadowOffsetY = shadowOffset; + mainCtx.shadowBlur = shadowOffset * 2; + // Draw the pointer + mainCtx.drawImage(pointerBuffer, 0, 0); + // Undo the translations & shadow settings + mainCtx.restore(); + + // Draw foreground + if (foregroundVisible) { + mainCtx.drawImage(foregroundBuffer, 0, 0); + } + + repainting = false; + }; + + // Visualize the component + this.repaint(); + + return this; + }; + + var radialBargraph = function (canvas, parameters) { + parameters = parameters || {}; + var gaugeType = (undefined === parameters.gaugeType ? steelseries.GaugeType.TYPE4 : parameters.gaugeType), + size = (undefined === parameters.size ? 0 : parameters.size), + minValue = (undefined === parameters.minValue ? 0 : parameters.minValue), + maxValue = (undefined === parameters.maxValue ? (minValue + 100) : parameters.maxValue), + niceScale = (undefined === parameters.niceScale ? true : parameters.niceScale), + threshold = (undefined === parameters.threshold ? (maxValue - minValue) / 2 + minValue: parameters.threshold), + thresholdRising = (undefined === parameters.thresholdRising ? true : parameters.thresholdRising), + section = (undefined === parameters.section ? null : parameters.section), + useSectionColors = (undefined === parameters.useSectionColors ? false : parameters.useSectionColors), + titleString = (undefined === parameters.titleString ? '' : parameters.titleString), + unitString = (undefined === parameters.unitString ? '' : parameters.unitString), + frameDesign = (undefined === parameters.frameDesign ? steelseries.FrameDesign.METAL : parameters.frameDesign), + frameVisible = (undefined === parameters.frameVisible ? true : parameters.frameVisible), + backgroundColor = (undefined === parameters.backgroundColor ? steelseries.BackgroundColor.DARK_GRAY : parameters.backgroundColor), + backgroundVisible = (undefined === parameters.backgroundVisible ? true : parameters.backgroundVisible), + valueColor = (undefined === parameters.valueColor ? steelseries.ColorDef.RED : parameters.valueColor), + lcdColor = (undefined === parameters.lcdColor ? steelseries.LcdColor.STANDARD : parameters.lcdColor), + lcdVisible = (undefined === parameters.lcdVisible ? true : parameters.lcdVisible), + lcdDecimals = (undefined === parameters.lcdDecimals ? 2 : parameters.lcdDecimals), + digitalFont = (undefined === parameters.digitalFont ? false : parameters.digitalFont), + fractionalScaleDecimals = (undefined === parameters.fractionalScaleDecimals ? 1 : parameters.fractionalScaleDecimals), + customLayer = (undefined === parameters.customLayer ? null : parameters.customLayer), + ledColor = (undefined === parameters.ledColor ? steelseries.LedColor.RED_LED : parameters.ledColor), + ledVisible = (undefined === parameters.ledVisible ? true : parameters.ledVisible), + userLedColor = (undefined === parameters.userLedColor ? steelseries.LedColor.GREEN_LED : parameters.userLedColor), + userLedVisible = (undefined === parameters.userLedVisible ? false : parameters.userLedVisible), + labelNumberFormat = (undefined === parameters.labelNumberFormat ? steelseries.LabelNumberFormat.STANDARD : parameters.labelNumberFormat), + foregroundType = (undefined === parameters.foregroundType ? steelseries.ForegroundType.TYPE1 : parameters.foregroundType), + foregroundVisible = (undefined === parameters.foregroundVisible ? true : parameters.foregroundVisible), + playAlarm = (undefined === parameters.playAlarm ? false : parameters.playAlarm), + alarmSound = (undefined === parameters.alarmSound ? false : parameters.alarmSound), + valueGradient = (undefined === parameters.valueGradient ? null : parameters.valueGradient), + useValueGradient = (undefined === parameters.useValueGradient ? false : parameters.useValueGradient), + tickLabelOrientation = (undefined === parameters.tickLabelOrientation ? (gaugeType === steelseries.GaugeType.TYPE1 ? steelseries.TickLabelOrientation.TANGENT : steelseries.TickLabelOrientation.NORMAL) : parameters.tickLabelOrientation), + trendVisible = (undefined === parameters.trendVisible ? false : parameters.trendVisible), + trendColors = (undefined === parameters.trendColors ? [steelseries.LedColor.RED_LED, steelseries.LedColor.GREEN_LED, steelseries.LedColor.CYAN_LED] : parameters.trendColors), + fullScaleDeflectionTime = (undefined === parameters.fullScaleDeflectionTime ? 2.5 : parameters.fullScaleDeflectionTime); + + // Get the canvas context and clear it + var mainCtx = getCanvasContext(canvas); + // Has a size been specified? + if (size === 0) { + size = Math.min(mainCtx.canvas.width, mainCtx.canvas.height); + } + + // Set the size - also clears the canvas + mainCtx.canvas.width = size; + mainCtx.canvas.height = size; + + // Create audio tag for alarm sound + if (playAlarm && alarmSound !== false) { + var audioElement = doc.createElement('audio'); + audioElement.setAttribute('src', alarmSound); + audioElement.setAttribute('preload', 'auto'); + } + + var value = minValue; + var range = maxValue - minValue; + var ledBlinking = false; + var ledTimerId = 0; + var userLedBlinking = false; + var userLedTimerId = 0; + var tween; + var self = this; + var repainting = false; + + // GaugeType specific private variables + var freeAreaAngle; + var rotationOffset; + var bargraphOffset; + var tickmarkOffset; + var angleRange; + var degAngleRange; + var angleStep; + var angle; + + var sectionAngles = []; + var isSectionsVisible = false; + var isGradientVisible = false; + + var imageWidth = size; + var imageHeight = size; + + var centerX = imageWidth / 2; + var centerY = imageHeight / 2; + + // Misc + var lcdFontHeight = Math.floor(imageWidth / 10); + var stdFont = lcdFontHeight + 'px ' + stdFontName; + var lcdFont = lcdFontHeight + 'px ' + lcdFontName; + var lcdHeight = imageHeight * 0.13; + var lcdWidth = imageWidth * 0.4; + var lcdPosX = (imageWidth - lcdWidth) / 2; + var lcdPosY = imageHeight / 2 - lcdHeight / 2; + + // Constants + var ACTIVE_LED_POS_X = imageWidth * 0.116822; + var ACTIVE_LED_POS_Y = imageWidth * 0.485981; + var LED_SIZE = Math.ceil(size * 0.093457); + //var LED_POS_X = imageWidth * 0.453271; + var LED_POS_X = imageWidth * 0.53; + var LED_POS_Y = imageHeight * 0.61; + var USER_LED_POS_X = gaugeType === steelseries.GaugeType.TYPE3 ? 0.7 * imageWidth : centerX - LED_SIZE / 2; + var USER_LED_POS_Y = gaugeType === steelseries.GaugeType.TYPE3 ? 0.61 * imageHeight : 0.75 * imageHeight; + + var trendIndicator = steelseries.TrendState.OFF; + var trendSize = size * 0.06; + var trendPosX = size * 0.38; + var trendPosY = size * 0.57; + + switch (gaugeType.type) { + case 'type1': + freeAreaAngle = 0; + rotationOffset = PI; + bargraphOffset = 0; + tickmarkOffset = HALF_PI; + angleRange = HALF_PI; + degAngleRange = angleRange * DEG_FACTOR; + angleStep = angleRange / range; + break; + + case 'type2': + freeAreaAngle = 0; + rotationOffset = PI; + bargraphOffset = 0; + tickmarkOffset = HALF_PI; + angleRange = PI; + degAngleRange = angleRange * DEG_FACTOR; + angleStep = angleRange / range; + break; + + case 'type3': + freeAreaAngle = 0; + rotationOffset = HALF_PI; + bargraphOffset = -HALF_PI; + tickmarkOffset = 0; + angleRange = 1.5 * PI; + degAngleRange = angleRange * DEG_FACTOR; + angleStep = angleRange / range; + break; + + case 'type4': + /* falls through */ + default: + freeAreaAngle = 60 * RAD_FACTOR; + rotationOffset = HALF_PI + (freeAreaAngle / 2); + bargraphOffset = -TWO_PI / 6; + tickmarkOffset = 0; + angleRange = TWO_PI - freeAreaAngle; + degAngleRange = angleRange * DEG_FACTOR; + angleStep = angleRange / range; + break; + } + + // Buffer for the frame + var frameBuffer = createBuffer(size, size); + var frameContext = frameBuffer.getContext('2d'); + + // Buffer for static background painting code + var backgroundBuffer = createBuffer(size, size); + var backgroundContext = backgroundBuffer.getContext('2d'); + + var lcdBuffer; + + // Buffer for active bargraph led + var activeLedBuffer = createBuffer(Math.ceil(size * 0.060747), Math.ceil(size * 0.023364)); + var activeLedContext = activeLedBuffer.getContext('2d'); + + // Buffer for led on painting code + var ledBufferOn = createBuffer(LED_SIZE, LED_SIZE); + var ledContextOn = ledBufferOn.getContext('2d'); + + // Buffer for led off painting code + var ledBufferOff = createBuffer(LED_SIZE, LED_SIZE); + var ledContextOff = ledBufferOff.getContext('2d'); + + // Buffer for current led painting code + var ledBuffer = ledBufferOff; + + // Buffer for user led on painting code + var userLedBufferOn = createBuffer(LED_SIZE, LED_SIZE); + var userLedContextOn = userLedBufferOn.getContext('2d'); + + // Buffer for user led off painting code + var userLedBufferOff = createBuffer(LED_SIZE, LED_SIZE); + var userLedContextOff = userLedBufferOff.getContext('2d'); + + // Buffer for current user led painting code + var userLedBuffer = userLedBufferOff; + // Buffer for the background of the led + var ledBackground; + + // Buffer for static foreground painting code + var foregroundBuffer = createBuffer(size, size); + var foregroundContext = foregroundBuffer.getContext('2d'); + + // Buffers for trend indicators + var trendUpBuffer, trendSteadyBuffer, trendDownBuffer, trendOffBuffer; + + var initialized = false; + + // Tickmark specific private variables + var niceMinValue = minValue; + var niceMaxValue = maxValue; + var niceRange = maxValue - minValue; + range = niceMaxValue - niceMinValue; + var minorTickSpacing = 0; + var majorTickSpacing = 0; + var maxNoOfMinorTicks = 10; + var maxNoOfMajorTicks = 10; + + // Method to calculate nice values for min, max and range for the tickmarks + var calculate = function calculate() { + if (niceScale) { + niceRange = calcNiceNumber(maxValue - minValue, false); + majorTickSpacing = calcNiceNumber(niceRange / (maxNoOfMajorTicks - 1), true); + niceMinValue = Math.floor(minValue / majorTickSpacing) * majorTickSpacing; + niceMaxValue = Math.ceil(maxValue / majorTickSpacing) * majorTickSpacing; + minorTickSpacing = calcNiceNumber(majorTickSpacing / (maxNoOfMinorTicks - 1), true); + minValue = niceMinValue; + maxValue = niceMaxValue; + range = maxValue - minValue; + } else { + niceRange = (maxValue - minValue); + niceMinValue = minValue; + niceMaxValue = maxValue; + range = niceRange; + //minorTickSpacing = 1; + //majorTickSpacing = 10; + majorTickSpacing = calcNiceNumber(niceRange / (maxNoOfMajorTicks - 1), true); + minorTickSpacing = calcNiceNumber(majorTickSpacing / (maxNoOfMinorTicks - 1), true); + } + + switch (gaugeType.type) { + case 'type1': + freeAreaAngle = 0; + rotationOffset = PI; + tickmarkOffset = HALF_PI; + angleRange = HALF_PI; + angleStep = angleRange / range; + break; + + case 'type2': + freeAreaAngle = 0; + rotationOffset = PI; + tickmarkOffset = HALF_PI; + angleRange = PI; + angleStep = angleRange / range; + break; + + case 'type3': + freeAreaAngle = 0; + rotationOffset = HALF_PI; + tickmarkOffset = 0; + angleRange = 1.5 * PI; + angleStep = angleRange / range; + break; + + case 'type4': // fall through + /* falls through */ + default: + freeAreaAngle = 60 * RAD_FACTOR; + rotationOffset = HALF_PI + (freeAreaAngle / 2); + tickmarkOffset = 0; + angleRange = TWO_PI - freeAreaAngle; + angleStep = angleRange / range; + break; + } + angle = rotationOffset + (value - minValue) * angleStep; + }; + + //********************************* Private methods ********************************* + // Draw all static painting code to background + var init = function (parameters) { + parameters = parameters || {}; + var drawFrame = (undefined === parameters.frame ? false : parameters.frame); + var drawBackground = (undefined === parameters.background ? false : parameters.background); + var drawLed = (undefined === parameters.led ? false : parameters.led); + var drawUserLed = (undefined === parameters.userLed ? false : parameters.userLed); + var drawValue = (undefined === parameters.value ? false : parameters.value); + var drawForeground = (undefined === parameters.foreground ? false : parameters.foreground); + var drawTrend = (undefined === parameters.trend ? false : parameters.trend); + + initialized = true; + + calculate(); + + // Create frame in frame buffer (frameBuffer) + if (drawFrame && frameVisible) { + drawRadialFrameImage(frameContext, frameDesign, centerX, centerY, imageWidth, imageHeight); + } + + // Create background in background buffer (backgroundBuffer) + if (drawBackground && backgroundVisible) { + drawRadialBackgroundImage(backgroundContext, backgroundColor, centerX, centerY, imageWidth, imageHeight); + + // Create custom layer in background buffer (backgroundBuffer) + drawRadialCustomImage(backgroundContext, customLayer, centerX, centerY, imageWidth, imageHeight); + } + + if (drawLed) { + // Draw LED ON in ledBuffer_ON + ledContextOn.drawImage(createLedImage(LED_SIZE, 1, ledColor), 0, 0); + + // Draw LED OFF in ledBuffer_OFF + ledContextOff.drawImage(createLedImage(LED_SIZE, 0, ledColor), 0, 0); + + // Buffer the background of the led for blinking + ledBackground = backgroundContext.getImageData(LED_POS_X, LED_POS_Y, LED_SIZE, LED_SIZE); + } + + if (drawUserLed) { + // Draw user LED ON in userLedBuffer_ON + userLedContextOn.drawImage(createLedImage(Math.ceil(LED_SIZE), 1, userLedColor), 0, 0); + + // Draw user LED OFF in userLedBuffer_OFF + userLedContextOff.drawImage(createLedImage(Math.ceil(LED_SIZE), 0, userLedColor), 0, 0); + } + + if (drawBackground) { + // Create bargraphtrack in background buffer (backgroundBuffer) + drawBargraphTrackImage(backgroundContext); + } + + // Create tickmarks in background buffer (backgroundBuffer) + if (drawBackground && backgroundVisible) { + drawTickmarksImage(backgroundContext, labelNumberFormat); + + // Create title in background buffer (backgroundBuffer) + drawTitleImage(backgroundContext, imageWidth, imageHeight, titleString, unitString, backgroundColor, true, true); + } + + // Create lcd background if selected in background buffer (backgroundBuffer) + if (drawBackground && lcdVisible) { + lcdBuffer = createLcdBackgroundImage(lcdWidth, lcdHeight, lcdColor); + backgroundContext.drawImage(lcdBuffer, lcdPosX, lcdPosY); + } + + // Convert Section values into angles + isSectionsVisible = false; + if (useSectionColors && null !== section && 0 < section.length) { + isSectionsVisible = true; + var sectionIndex = section.length; + sectionAngles = []; + do { + sectionIndex--; + sectionAngles.push({start: (((section[sectionIndex].start + Math.abs(minValue)) / (maxValue - minValue)) * degAngleRange), + stop: (((section[sectionIndex].stop + Math.abs(minValue)) / (maxValue - minValue)) * degAngleRange), + color: customColorDef(section[sectionIndex].color)}); + } while (0 < sectionIndex); + } + + // Use a gradient for the valueColor? + isGradientVisible = false; + if (useValueGradient && valueGradient !== null) { + // force section colors off! + isSectionsVisible = false; + isGradientVisible = true; + } + + // Create an image of an active led in active led buffer (activeLedBuffer) + if (drawValue) { + drawActiveLed(activeLedContext, valueColor); + } + + // Create foreground in foreground buffer (foregroundBuffer) + if (drawForeground && foregroundVisible) { + drawRadialForegroundImage(foregroundContext, foregroundType, imageWidth, imageHeight, false); + } + + // Create the trend indicator buffers + if (drawTrend && trendVisible) { + trendUpBuffer = createTrendIndicator(trendSize, steelseries.TrendState.UP, trendColors); + trendSteadyBuffer = createTrendIndicator(trendSize, steelseries.TrendState.STEADY, trendColors); + trendDownBuffer = createTrendIndicator(trendSize, steelseries.TrendState.DOWN, trendColors); + trendOffBuffer = createTrendIndicator(trendSize, steelseries.TrendState.OFF, trendColors); + } + }; + + var resetBuffers = function (buffers) { + buffers = buffers || {}; + var resetFrame = (undefined === buffers.frame ? false : buffers.frame); + var resetBackground = (undefined === buffers.background ? false : buffers.background); + var resetLed = (undefined === buffers.led ? false : buffers.led); + var resetUserLed = (undefined === buffers.userLed ? false : buffers.userLed); + var resetValue = (undefined === buffers.value ? false : buffers.value); + var resetForeground = (undefined === buffers.foreground ? false : buffers.foreground); + + // Buffer for the frame + if (resetFrame) { + frameBuffer.width = size; + frameBuffer.height = size; + frameContext = frameBuffer.getContext('2d'); + } + + // Buffer for static background painting code + if (resetBackground) { + backgroundBuffer.width = size; + backgroundBuffer.height = size; + backgroundContext = backgroundBuffer.getContext('2d'); + } + + // Buffer for active bargraph led + if (resetValue) { + activeLedBuffer.width = Math.ceil(size * 0.060747); + activeLedBuffer.height = Math.ceil(size * 0.023364); + activeLedContext = activeLedBuffer.getContext('2d'); + } + + if (resetLed) { + // Buffer for led on painting code + ledBufferOn.width = Math.ceil(LED_SIZE); + ledBufferOn.height = Math.ceil(LED_SIZE); + ledContextOn = ledBufferOn.getContext('2d'); + + // Buffer for led off painting code + ledBufferOff.width = Math.ceil(LED_SIZE); + ledBufferOff.height = Math.ceil(LED_SIZE); + ledContextOff = ledBufferOff.getContext('2d'); + + // Buffer for current led painting code + ledBuffer = ledBufferOff; + } + + if (resetUserLed) { + userLedBufferOn.width = Math.ceil(LED_SIZE); + userLedBufferOn.height = Math.ceil(LED_SIZE); + userLedContextOn = userLedBufferOn.getContext('2d'); + + userLedBufferOff.width = Math.ceil(LED_SIZE); + userLedBufferOff.height = Math.ceil(LED_SIZE); + userLedContextOff = userLedBufferOff.getContext('2d'); + + // Buffer for current user led painting code + userLedBuffer = userLedBufferOff; + } + + // Buffer for static foreground painting code + if (resetForeground) { + foregroundBuffer.width = size; + foregroundBuffer.height = size; + foregroundContext = foregroundBuffer.getContext('2d'); + } + }; + + var drawBargraphTrackImage = function (ctx) { + + ctx.save(); + + // Bargraphtrack + + // Frame + ctx.save(); + ctx.lineWidth = size * 0.085; + ctx.beginPath(); + ctx.translate(centerX, centerY); + ctx.rotate(rotationOffset - 4 * RAD_FACTOR); + ctx.translate(-centerX, -centerY); + ctx.arc(centerX, centerY, imageWidth * 0.355140, 0, angleRange + 8 * RAD_FACTOR, false); + ctx.rotate(-rotationOffset); + var ledTrackFrameGradient = ctx.createLinearGradient(0, 0.107476 * imageHeight, 0, 0.897195 * imageHeight); + ledTrackFrameGradient.addColorStop(0, '#000000'); + ledTrackFrameGradient.addColorStop(0.22, '#333333'); + ledTrackFrameGradient.addColorStop(0.76, '#333333'); + ledTrackFrameGradient.addColorStop(1, '#cccccc'); + ctx.strokeStyle = ledTrackFrameGradient; + ctx.stroke(); + ctx.restore(); + + // Main + ctx.save(); + ctx.lineWidth = size * 0.075; + ctx.beginPath(); + ctx.translate(centerX, centerY); + ctx.rotate(rotationOffset - 4 * RAD_FACTOR); + ctx.translate(-centerX, -centerY); + ctx.arc(centerX, centerY, imageWidth * 0.355140, 0, angleRange + 8 * RAD_FACTOR, false); + ctx.rotate(-rotationOffset); + var ledTrackMainGradient = ctx.createLinearGradient(0, 0.112149 * imageHeight, 0, 0.892523 * imageHeight); + ledTrackMainGradient.addColorStop(0, '#111111'); + ledTrackMainGradient.addColorStop(1, '#333333'); + ctx.strokeStyle = ledTrackMainGradient; + ctx.stroke(); + ctx.restore(); + + // Draw inactive leds + var ledCenterX = (imageWidth * 0.116822 + imageWidth * 0.060747) / 2; + var ledCenterY = (imageWidth * 0.485981 + imageWidth * 0.023364) / 2; + var ledOffGradient = ctx.createRadialGradient(ledCenterX, ledCenterY, 0, ledCenterX, ledCenterY, 0.030373 * imageWidth); + ledOffGradient.addColorStop(0, '#3c3c3c'); + ledOffGradient.addColorStop(1, '#323232'); + var angle = 0; + for (angle = 0; angle <= degAngleRange; angle += 5) { + ctx.save(); + ctx.translate(centerX, centerY); + ctx.rotate((angle * RAD_FACTOR) + bargraphOffset); + ctx.translate(-centerX, -centerY); + ctx.beginPath(); + ctx.rect(imageWidth * 0.116822, imageWidth * 0.485981, imageWidth * 0.060747, imageWidth * 0.023364); + ctx.closePath(); + ctx.fillStyle = ledOffGradient; + ctx.fill(); + ctx.restore(); + } + + ctx.restore(); + }; + + var drawActiveLed = function (ctx, color) { + ctx.save(); + ctx.beginPath(); + ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height); + ctx.closePath(); + var ledCenterX = (ctx.canvas.width / 2); + var ledCenterY = (ctx.canvas.height / 2); + var ledGradient = mainCtx.createRadialGradient(ledCenterX, ledCenterY, 0, ledCenterX, ledCenterY, ctx.canvas.width / 2); + ledGradient.addColorStop(0, color.light.getRgbaColor()); + ledGradient.addColorStop(1, color.dark.getRgbaColor()); + ctx.fillStyle = ledGradient; + ctx.fill(); + ctx.restore(); + }; + + var drawLcdText = function (ctx, value) { + + ctx.save(); + ctx.textAlign = 'right'; + ctx.strokeStyle = lcdColor.textColor; + ctx.fillStyle = lcdColor.textColor; + + if (lcdColor === steelseries.LcdColor.STANDARD || lcdColor === steelseries.LcdColor.STANDARD_GREEN) { + ctx.shadowColor = 'gray'; + ctx.shadowOffsetX = imageWidth * 0.007; + ctx.shadowOffsetY = imageWidth * 0.007; + ctx.shadowBlur = imageWidth * 0.007; + } + + if (digitalFont) { + ctx.font = lcdFont; + } else { + ctx.font = stdFont; + } + ctx.fillText(value.toFixed(lcdDecimals), lcdPosX + lcdWidth - lcdWidth * 0.05, lcdPosY + lcdHeight * 0.5 + lcdFontHeight * 0.38, lcdWidth * 0.9); + + ctx.restore(); + }; + + var drawTickmarksImage = function (ctx, labelNumberFormat) { + var alpha = rotationOffset, // Tracks total rotation + rotationStep = angleStep * minorTickSpacing, + textRotationAngle, + fontSize = Math.ceil(imageWidth * 0.04), + valueCounter = minValue, + majorTickCounter = maxNoOfMinorTicks - 1, + TEXT_TRANSLATE_X = imageWidth * 0.28, + TEXT_WIDTH = imageWidth * 0.1, + MAX_VALUE_ROUNDED = parseFloat(maxValue.toFixed(2)), + i; + + backgroundColor.labelColor.setAlpha(1); + ctx.save(); + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.font = fontSize + 'px ' + stdFontName; + ctx.strokeStyle = backgroundColor.labelColor.getRgbaColor(); + ctx.fillStyle = backgroundColor.labelColor.getRgbaColor(); + ctx.translate(centerX, centerY); + ctx.rotate(rotationOffset); + + if (gaugeType.type === 'type1' || gaugeType.type === 'type2') { + TEXT_WIDTH = imageWidth * 0.0375; + } + + for (i = minValue; parseFloat(i.toFixed(2)) <= MAX_VALUE_ROUNDED; i += minorTickSpacing) { + textRotationAngle = + rotationStep + HALF_PI; + majorTickCounter++; + // Draw major tickmarks + if (majorTickCounter === maxNoOfMinorTicks) { + ctx.save(); + ctx.translate(TEXT_TRANSLATE_X, 0); + + switch (tickLabelOrientation.type) { + case 'horizontal': + textRotationAngle = -alpha; + break; + + case 'tangent': + textRotationAngle = (alpha <= HALF_PI + PI ? PI : 0); + break; + + case 'normal': + /* falls through */ + default: + textRotationAngle = HALF_PI; + break; + } + ctx.rotate(textRotationAngle); + + switch (labelNumberFormat.format) { + case 'fractional': + ctx.fillText((valueCounter.toFixed(fractionalScaleDecimals)), 0, 0, TEXT_WIDTH); + break; + + case 'scientific': + ctx.fillText((valueCounter.toPrecision(2)), 0, 0, TEXT_WIDTH); + break; + + case 'standard': + /* falls through */ + default: + ctx.fillText((valueCounter.toFixed(0)), 0, 0, TEXT_WIDTH); + break; + } + ctx.translate(-TEXT_TRANSLATE_X, 0); + ctx.restore(); + + valueCounter += majorTickSpacing; + majorTickCounter = 0; + ctx.rotate(rotationStep); + alpha += rotationStep; + continue; + } + ctx.rotate(rotationStep); + alpha += rotationStep; + } + + ctx.translate(-centerX, -centerY); + ctx.restore(); + }; + + var blink = function (blinking) { + if (blinking) { + ledTimerId = setInterval(toggleAndRepaintLed, 1000); + } else { + clearInterval(ledTimerId); + ledBuffer = ledBufferOff; + } + }; + + var blinkUser = function (blinking) { + if (blinking) { + userLedTimerId = setInterval(toggleAndRepaintUserLed, 1000); + } else { + clearInterval(userLedTimerId); + userLedBuffer = userLedBufferOff; + } + }; + + var toggleAndRepaintLed = function () { + if (ledVisible) { + if (ledBuffer === ledBufferOn) { + ledBuffer = ledBufferOff; + } else { + ledBuffer = ledBufferOn; + } + if (!repainting) { + repainting = true; + requestAnimFrame(self.repaint); + } + } + }; + + var toggleAndRepaintUserLed = function () { + if (userLedVisible) { + if (userLedBuffer === userLedBufferOn) { + userLedBuffer = userLedBufferOff; + } else { + userLedBuffer = userLedBufferOn; + } + if (!repainting) { + repainting = true; + requestAnimFrame(self.repaint); + } + } + }; + + //********************************* Public methods ********************************* + this.setValue = function (newValue) { + newValue = parseFloat(newValue); + var targetValue = (newValue < minValue ? minValue : (newValue > maxValue ? maxValue : newValue)); + if (value !== targetValue) { + value = targetValue; + if ((value >= threshold && !ledBlinking && thresholdRising) || + (value <= threshold && !ledBlinking && !thresholdRising)) { + ledBlinking = true; + blink(ledBlinking); + if (playAlarm) { + audioElement.play(); + } + } else if ((value < threshold && ledBlinking && thresholdRising) || + (value > threshold && ledBlinking && !thresholdRising)) { + ledBlinking = false; + blink(ledBlinking); + if (playAlarm) { + audioElement.pause(); + } + } + this.repaint(); + } + return this; + }; + + this.getValue = function () { + return value; + }; + + this.setValueAnimated = function (newValue, callback) { + newValue = parseFloat(newValue); + var targetValue = (newValue < minValue ? minValue : (newValue > maxValue ? maxValue : newValue)), + gauge = this, + time; + + if (value !== targetValue) { + if (undefined !== tween && tween.isPlaying) { + tween.stop(); + } + + time = fullScaleDeflectionTime * Math.abs(targetValue - value) / (maxValue - minValue); + time = Math.max(time, fullScaleDeflectionTime / 5); + tween = new Tween({}, '', Tween.regularEaseInOut, value, targetValue, time); + //tween = new Tween({}, '', Tween.regularEaseInOut, value, targetValue, 1); + //tween = new Tween(new Object(), '', Tween.strongEaseInOut, this.value, targetValue, 1); + tween.onMotionChanged = function (event) { + value = event.target._pos; + + if ((value >= threshold && !ledBlinking && thresholdRising) || + (value <= threshold && !ledBlinking && !thresholdRising)) { + ledBlinking = true; + blink(ledBlinking); + if (playAlarm) { + audioElement.play(); + } + } else if ((value < threshold && ledBlinking && thresholdRising) || + (value > threshold && ledBlinking && !thresholdRising)) { + ledBlinking = false; + blink(ledBlinking); + if (playAlarm) { + audioElement.pause(); + } + } + if (!repainting) { + repainting = true; + requestAnimFrame(gauge.repaint); + } + }; + + // do we have a callback function to process? + if (callback && typeof(callback) === "function") { + tween.onMotionFinished = callback; + } + + tween.start(); + } + return this; + }; + + this.setFrameDesign = function (newFrameDesign) { + resetBuffers({frame: true}); + frameDesign = newFrameDesign; + init({frame: true}); + this.repaint(); + return this; + }; + + this.setBackgroundColor = function (newBackgroundColor) { + resetBuffers({background: true, + led: true}); + backgroundColor = newBackgroundColor; + init({background: true, + led: true}); + this.repaint(); + return this; + }; + + this.setForegroundType = function (newForegroundType) { + resetBuffers({foreground: true}); + foregroundType = newForegroundType; + init({foreground: true}); + this.repaint(); + return this; + }; + + this.setValueColor = function (newValueColor) { + resetBuffers({value: true}); + valueColor = newValueColor; + init({value: true}); + this.repaint(); + return this; + }; + + this.setLedColor = function (newLedColor) { + resetBuffers({led: true}); + ledColor = newLedColor; + init({led: true}); + this.repaint(); + return this; + }; + + this.setUserLedColor = function (newLedColor) { + resetBuffers({userLed: true}); + userLedColor = newLedColor; + init({userLed: true}); + this.repaint(); + return this; + }; + + this.toggleUserLed = function () { + if (userLedBuffer === userLedBufferOn) { + userLedBuffer = userLedBufferOff; + } else { + userLedBuffer = userLedBufferOn; + } + this.repaint(); + return this; + }; + + this.setUserLedOnOff = function (on) { + if (true === on) { + userLedBuffer = userLedBufferOn; + } else { + userLedBuffer = userLedBufferOff; + } + this.repaint(); + return this; + }; + + this.blinkUserLed = function (blink) { + if (blink) { + if (!userLedBlinking) { + blinkUser(true); + userLedBlinking = true; + } + } else { + if (userLedBlinking) { + clearInterval(userLedTimerId); + userLedBlinking = false; + } + } + return this; + }; + + this.setLedVisible = function (visible) { + ledVisible = !!visible; + this.repaint(); + return this; + }; + + this.setUserLedVisible = function (visible) { + userLedVisible = !!visible; + this.repaint(); + return this; + }; + + this.setLcdColor = function (newLcdColor) { + lcdColor = newLcdColor; + resetBuffers({background: true}); + init({background: true}); + this.repaint(); + return this; + }; + + this.setLcdDecimals = function (decimals) { + lcdDecimals = parseInt(decimals, 10); + this.repaint(); + return this; + }; + + this.setSection = function (areaSec) { + section = areaSec; + init(); + this.repaint(); + return this; + }; + + this.setSectionActive = function (value) { + useSectionColors = value; + init(); + this.repaint(); + return this; + }; + + this.setGradient = function (grad) { + valueGradient = grad; + init(); + this.repaint(); + return this; + }; + + this.setGradientActive = function (value) { + useValueGradient = value; + init(); + this.repaint(); + return this; + }; + + this.setMinValue = function (value) { + minValue = value; + resetBuffers({background: true}); + init({background: true}); + this.repaint(); + return this; + }; + + this.getMinValue = function () { + return minValue; + }; + + this.setMaxValue = function (value) { + maxValue = value; + resetBuffers({background: true}); + init({background: true}); + this.repaint(); + return this; + }; + + this.getMaxValue = function () { + return maxValue; + }; + + this.setThreshold = function (newValue) { + newValue = parseFloat(newValue); + var targetValue = newValue < minValue ? minValue : (newValue > maxValue ? maxValue : newValue); + threshold = targetValue; + resetBuffers({background: true}); + init({background: true}); + this.repaint(); + return this; + }; + + this.setThresholdRising = function (rising) { + thresholdRising = !!rising; + // reset existing threshold alerts + ledBlinking = !ledBlinking; + blink(ledBlinking); + this.repaint(); + return this; + }; + + this.setTitleString = function (title) { + titleString = title; + resetBuffers({background: true}); + init({background: true}); + this.repaint(); + return this; + }; + + this.setUnitString = function (unit) { + unitString = unit; + resetBuffers({background: true}); + init({background: true}); + this.repaint(); + return this; + }; + + this.setTrend = function (newValue) { + trendIndicator = newValue; + this.repaint(); + return this; + }; + + this.setTrendVisible = function (visible) { + trendVisible = !!visible; + this.repaint(); + return this; + }; + + this.setFractionalScaleDecimals = function (decimals) { + fractionalScaleDecimals = parseInt(decimals, 10); + resetBuffers({background: true}); + init({background: true}); + this.repaint(); + }; + + this.setLabelNumberFormat = function (format) { + labelNumberFormat = format; + resetBuffers({background: true}); + init({background: true}); + this.repaint(); + return this; + }; + + this.repaint = function () { + var activeLedAngle = ((value - minValue) / (maxValue - minValue)) * degAngleRange, + activeLedColor, + lastActiveLedColor = valueColor, + angle, i, + currentValue, + gradRange, + fraction; + + if (!initialized) { + init({frame: true, + background: true, + led: true, + userLed: true, + value: true, + trend: true, + foreground: true}); + } + + mainCtx.clearRect(0, 0, size, size); + + // Draw frame image + if (frameVisible) { + mainCtx.drawImage(frameBuffer, 0, 0); + } + + // Draw buffered image to visible canvas + mainCtx.drawImage(backgroundBuffer, 0, 0); + + // Draw active leds + for (angle = 0; angle <= activeLedAngle; angle += 5) { + //check for LED color + activeLedColor = valueColor; + // Use a gradient for value colors? + if (isGradientVisible) { + // Convert angle back to value + currentValue = minValue + (angle / degAngleRange) * (maxValue - minValue); + gradRange = valueGradient.getEnd() - valueGradient.getStart(); + fraction = (currentValue - minValue) / gradRange; + fraction = Math.max(Math.min(fraction, 1), 0); + activeLedColor = customColorDef(valueGradient.getColorAt(fraction).getRgbaColor()); + } else if (isSectionsVisible) { + for (i = 0; i < sectionAngles.length; i++) { + if (angle >= sectionAngles[i].start && angle < sectionAngles[i].stop) { + activeLedColor = sectionAngles[i].color; + break; + } + } + } + // Has LED color changed? If so redraw the buffer + if (lastActiveLedColor.medium.getHexColor() !== activeLedColor.medium.getHexColor()) { + drawActiveLed(activeLedContext, activeLedColor); + lastActiveLedColor = activeLedColor; + } + mainCtx.save(); + mainCtx.translate(centerX, centerY); + mainCtx.rotate((angle * RAD_FACTOR) + bargraphOffset); + mainCtx.translate(-centerX, -centerY); + mainCtx.drawImage(activeLedBuffer, ACTIVE_LED_POS_X, ACTIVE_LED_POS_Y); + mainCtx.restore(); + } + + // Draw lcd display + if (lcdVisible) { + drawLcdText(mainCtx, value); + } + + // Draw led + if (ledVisible) { + mainCtx.drawImage(ledBuffer, LED_POS_X, LED_POS_Y); + } + + // Draw user led + if (userLedVisible) { + mainCtx.drawImage(userLedBuffer, USER_LED_POS_X, USER_LED_POS_Y); + } + + // Draw the trend indicator + if (trendVisible) { + switch (trendIndicator.state) { + case 'up': + mainCtx.drawImage(trendUpBuffer, trendPosX, trendPosY); + break; + case 'steady': + mainCtx.drawImage(trendSteadyBuffer, trendPosX, trendPosY); + break; + case 'down': + mainCtx.drawImage(trendDownBuffer, trendPosX, trendPosY); + break; + case 'off': + mainCtx.drawImage(trendOffBuffer, trendPosX, trendPosY); + break; + } + } + + // Draw foreground + if (foregroundVisible) { + mainCtx.drawImage(foregroundBuffer, 0, 0); + } + + repainting = false; + }; + + // Visualize the component + this.repaint(); + + return this; + }; + + var displaySingle = function (canvas, parameters) { + parameters = parameters || {}; + var width = (undefined === parameters.width ? 0 : parameters.width), + height = (undefined === parameters.height ? 0 : parameters.height), + lcdColor = (undefined === parameters.lcdColor ? steelseries.LcdColor.STANDARD : parameters.lcdColor), + lcdDecimals = (undefined === parameters.lcdDecimals ? 2 : parameters.lcdDecimals), + unitString = (undefined === parameters.unitString ? '' : parameters.unitString), + unitStringVisible = (undefined === parameters.unitStringVisible ? false : parameters.unitStringVisible), + headerString = (undefined === parameters.headerString ? '' : parameters.headerString), + headerStringVisible = (undefined === parameters.headerStringVisible ? false : parameters.headerStringVisible), + digitalFont = (undefined === parameters.digitalFont ? false : parameters.digitalFont), + valuesNumeric = (undefined === parameters.valuesNumeric ? true : parameters.valuesNumeric), + value = (undefined === parameters.value ? 0 : parameters.value), + alwaysScroll = (undefined === parameters.alwaysScroll ? false : parameters.alwaysScroll), + autoScroll = (undefined === parameters.autoScroll ? false : parameters.autoScroll), + section = (undefined === parameters.section ? null : parameters.section); + + var scrolling = false; + var scrollX = 0; + var scrollTimer; + var repainting = false; + + var self = this; + + // Get the canvas context and clear it + var mainCtx = getCanvasContext(canvas); + // Has a size been specified? + if (width === 0) { + width = mainCtx.canvas.width; + } + if (height === 0) { + height = mainCtx.canvas.height; + } + + // Set the size - also clears the canvas + mainCtx.canvas.width = width; + mainCtx.canvas.height = height; + + var imageWidth = width; + var imageHeight = height; + var textWidth = 0; + + var fontHeight = Math.floor(imageHeight / 1.5); + var stdFont = fontHeight + 'px ' + stdFontName; + var lcdFont = fontHeight + 'px ' + lcdFontName; + + var initialized = false; + + // ************** Buffer creation ******************** + // Buffer for the lcd + var lcdBuffer; + var sectionBuffer = []; + var sectionForegroundColor = []; + + // ************** Image creation ******************** + var drawLcdText = function (value, color) { + mainCtx.save(); + mainCtx.textAlign = 'right'; + //mainCtx.textBaseline = 'top'; + mainCtx.strokeStyle = color; + mainCtx.fillStyle = color; + + mainCtx.beginPath(); + mainCtx.rect(2, 0, imageWidth - 4, imageHeight); + mainCtx.closePath(); + mainCtx.clip(); + + if ((lcdColor === steelseries.LcdColor.STANDARD || lcdColor === steelseries.LcdColor.STANDARD_GREEN) && + section === null) { + mainCtx.shadowColor = 'gray'; + mainCtx.shadowOffsetX = imageHeight * 0.035; + mainCtx.shadowOffsetY = imageHeight * 0.035; + mainCtx.shadowBlur = imageHeight * 0.055; + } + + mainCtx.font = digitalFont ? lcdFont : stdFont; + + if (valuesNumeric) { + // Numeric value + var unitWidth = 0; + textWidth = 0; + if (unitStringVisible) { + mainCtx.font = Math.floor(imageHeight / 2.5) + 'px ' + stdFontName; + unitWidth = mainCtx.measureText(unitString).width; + } + mainCtx.font = digitalFont ? lcdFont : stdFont; + var lcdText = value.toFixed(lcdDecimals); + textWidth = mainCtx.measureText(lcdText).width; + var vPos = 0.38; + if (headerStringVisible) { + vPos = 0.52; + } + + mainCtx.fillText(lcdText, imageWidth - unitWidth - 4 - scrollX, imageHeight * 0.5 + fontHeight * vPos); + + if (unitStringVisible) { + mainCtx.font = Math.floor(imageHeight / 2.5) + 'px ' + stdFontName; + mainCtx.fillText(unitString, imageWidth - 2 - scrollX, imageHeight * 0.5 + fontHeight * vPos); + } + if (headerStringVisible) { + mainCtx.textAlign = 'center'; + mainCtx.font = Math.floor(imageHeight / 3.5) + 'px ' + stdFontName; + mainCtx.fillText(headerString, imageWidth / 2, imageHeight * 0.3); + } + } else { + // Text value + textWidth = mainCtx.measureText(value).width; + if (alwaysScroll || (autoScroll && textWidth > imageWidth - 4)) { + if (!scrolling) { + if (textWidth > imageWidth * 0.8) { + scrollX = imageWidth - textWidth - imageWidth * 0.2; // leave 20% blank leading space to give time to read start of message + } else { + scrollX = 0; + } + scrolling = true; + clearTimeout(scrollTimer); // kill any pending animate + scrollTimer = setTimeout(animate, 200); + } + } else if (autoScroll && textWidth <= imageWidth - 4) { + scrollX = 0; + scrolling = false; + } + mainCtx.fillText(value, imageWidth - 2 - scrollX, imageHeight * 0.5 + fontHeight * 0.38); + } + mainCtx.restore(); + }; + + var createLcdSectionImage = function (width, height, color, lcdColor) { + var lcdSectionBuffer = createBuffer(width, height); + var lcdCtx = lcdSectionBuffer.getContext('2d'); + + lcdCtx.save(); + var xB = 0; + var yB = 0; + var wB = width; + var hB = height; + var rB = Math.min(width, height) * 0.095; + + var lcdBackground = lcdCtx.createLinearGradient(0, yB, 0, yB + hB); + + lcdBackground.addColorStop(0, '#4c4c4c'); + lcdBackground.addColorStop(0.08, '#666666'); + lcdBackground.addColorStop(0.92, '#666666'); + lcdBackground.addColorStop(1, '#e6e6e6'); + lcdCtx.fillStyle = lcdBackground; + + roundedRectangle(lcdCtx, xB, yB, wB, hB, rB); + + lcdCtx.fill(); + lcdCtx.restore(); + + lcdCtx.save(); + + var rgb = getColorValues(color); + var hsb = rgbToHsb(rgb[0], rgb[1], rgb[2]); + + var rgbStart = getColorValues(lcdColor.gradientStartColor); + var hsbStart = rgbToHsb(rgbStart[0], rgbStart[1], rgbStart[2]); + var rgbFraction1 = getColorValues(lcdColor.gradientFraction1Color); + var hsbFraction1 = rgbToHsb(rgbFraction1[0], rgbFraction1[1], rgbFraction1[2]); + var rgbFraction2 = getColorValues(lcdColor.gradientFraction2Color); + var hsbFraction2 = rgbToHsb(rgbFraction2[0], rgbFraction2[1], rgbFraction2[2]); + var rgbFraction3 = getColorValues(lcdColor.gradientFraction3Color); + var hsbFraction3 = rgbToHsb(rgbFraction3[0], rgbFraction3[1], rgbFraction3[2]); + var rgbStop = getColorValues(lcdColor.gradientStopColor); + var hsbStop = rgbToHsb(rgbStop[0], rgbStop[1], rgbStop[2]); + + var startColor = hsbToRgb(hsb[0], hsb[1], hsbStart[2] - 0.31); + var fraction1Color = hsbToRgb(hsb[0], hsb[1], hsbFraction1[2] - 0.31); + var fraction2Color = hsbToRgb(hsb[0], hsb[1], hsbFraction2[2] - 0.31); + var fraction3Color = hsbToRgb(hsb[0], hsb[1], hsbFraction3[2] - 0.31); + var stopColor = hsbToRgb(hsb[0], hsb[1], hsbStop[2] - 0.31); + + var xF = 1; + var yF = 1; + var wF = width - 2; + var hF = height - 2; + var rF = rB - 1; + var lcdForeground = lcdCtx.createLinearGradient(0, yF, 0, yF + hF); + lcdForeground.addColorStop(0, 'rgb(' + startColor[0] + ', ' + startColor[1] + ', ' + startColor[2] + ')'); + lcdForeground.addColorStop(0.03, 'rgb(' + fraction1Color[0] + ',' + fraction1Color[1] + ',' + fraction1Color[2] + ')'); + lcdForeground.addColorStop(0.49, 'rgb(' + fraction2Color[0] + ',' + fraction2Color[1] + ',' + fraction2Color[2] + ')'); + lcdForeground.addColorStop(0.5, 'rgb(' + fraction3Color[0] + ',' + fraction3Color[1] + ',' + fraction3Color[2] + ')'); + lcdForeground.addColorStop(1, 'rgb(' + stopColor[0] + ',' + stopColor[1] + ',' + stopColor[2] + ')'); + lcdCtx.fillStyle = lcdForeground; + + roundedRectangle(lcdCtx, xF, yF, wF, hF, rF); + + lcdCtx.fill(); + lcdCtx.restore(); + + return lcdSectionBuffer; + }; + + var createSectionForegroundColor = function (sectionColor) { + var rgbSection = getColorValues(sectionColor); + var hsbSection = rgbToHsb(rgbSection[0], rgbSection[1], rgbSection[2]); + var sectionForegroundRgb = hsbToRgb(hsbSection[0], 0.57, 0.83); + return 'rgb(' + sectionForegroundRgb[0] + ', ' + sectionForegroundRgb[1] + ', ' + sectionForegroundRgb[2] + ')'; + }; + + var animate = function () { + if (scrolling) { + if (scrollX > imageWidth) { + scrollX = -textWidth; + } + scrollX += 2; + scrollTimer = setTimeout(animate, 50); + } else { + scrollX = 0; + } + if (!repainting) { + repainting = true; + requestAnimFrame(self.repaint); + } + }; + + // ************** Initialization ******************** + var init = function () { + var sectionIndex; + initialized = true; + + // Create lcd background if selected in background buffer (backgroundBuffer) + lcdBuffer = createLcdBackgroundImage(width, height, lcdColor); + + if (null !== section && 0 < section.length) { + for (sectionIndex = 0 ; sectionIndex < section.length ; sectionIndex++) { + sectionBuffer[sectionIndex] = createLcdSectionImage(width, height, section[sectionIndex].color, lcdColor); + sectionForegroundColor[sectionIndex] = createSectionForegroundColor(section[sectionIndex].color); + } + } + + }; + + // ************** Public methods ******************** + this.setValue = function (newValue) { + if (value !== newValue) { + value = newValue; + this.repaint(); + } + return this; + }; + + this.setLcdColor = function (newLcdColor) { + lcdColor = newLcdColor; + init(); + this.repaint(); + return this; + }; + + this.setSection = function (newSection) { + section = newSection; + init({background: true, foreground: true}); + this.repaint(); + return this; + }; + + this.setScrolling = function (scroll) { + if (scroll) { + if (scrolling) { + return; + } else { + scrolling = scroll; + animate(); + } + } else { //disable scrolling + scrolling = scroll; + } + return this; + }; + + this.repaint = function () { + if (!initialized) { + init(); + } + + //mainCtx.save(); + mainCtx.clearRect(0, 0, mainCtx.canvas.width, mainCtx.canvas.height); + + var lcdBackgroundBuffer = lcdBuffer; + var lcdTextColor = lcdColor.textColor; + var sectionIndex; + // Draw sections + if (null !== section && 0 < section.length) { + for (sectionIndex = 0 ; sectionIndex < section.length ; sectionIndex++) { + if (value >= section[sectionIndex].start && value <= section[sectionIndex].stop) { + lcdBackgroundBuffer = sectionBuffer[sectionIndex]; + lcdTextColor = sectionForegroundColor[sectionIndex]; + break; + } + } + } + + // Draw lcd background + mainCtx.drawImage(lcdBackgroundBuffer, 0, 0); + + // Draw lcd text + drawLcdText(value, lcdTextColor); + + repainting = false; + }; + + // Visualize the component + this.repaint(); + + return this; + }; + + var windDirection = function (canvas, parameters) { + parameters = parameters || {}; + var size = (undefined === parameters.size ? 0 : parameters.size), + frameDesign = (undefined === parameters.frameDesign ? steelseries.FrameDesign.METAL : parameters.frameDesign), + frameVisible = (undefined === parameters.frameVisible ? true : parameters.frameVisible), + backgroundColor = (undefined === parameters.backgroundColor ? steelseries.BackgroundColor.DARK_GRAY : parameters.backgroundColor), + backgroundVisible = (undefined === parameters.backgroundVisible ? true : parameters.backgroundVisible), + pointerTypeLatest = (undefined === parameters.pointerTypeLatest ? steelseries.PointerType.TYPE1 : parameters.pointerTypeLatest), + pointerTypeAverage = (undefined === parameters.pointerTypeAverage ? steelseries.PointerType.TYPE8 : parameters.pointerTypeAverage), + pointerColor = (undefined === parameters.pointerColor ? steelseries.ColorDef.RED : parameters.pointerColor), + pointerColorAverage = (undefined === parameters.pointerColorAverage ? steelseries.ColorDef.BLUE : parameters.pointerColorAverage), + knobType = (undefined === parameters.knobType ? steelseries.KnobType.STANDARD_KNOB : parameters.knobType), + knobStyle = (undefined === parameters.knobStyle ? steelseries.KnobStyle.SILVER : parameters.knobStyle), + foregroundType = (undefined === parameters.foregroundType ? steelseries.ForegroundType.TYPE1 : parameters.foregroundType), + foregroundVisible = (undefined === parameters.foregroundVisible ? true : parameters.foregroundVisible), + pointSymbols = (undefined === parameters.pointSymbols ? ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'] : parameters.pointSymbols), + pointSymbolsVisible = (undefined === parameters.pointSymbolsVisible ? true : parameters.pointSymbolsVisible), + customLayer = (undefined === parameters.customLayer ? null : parameters.customLayer), + degreeScale = (undefined === parameters.degreeScale ? true : parameters.degreeScale), + degreeScaleHalf = (undefined === parameters.degreeScaleHalf ? false : parameters.degreeScaleHalf), + roseVisible = (undefined === parameters.roseVisible ? false : parameters.roseVisible), + lcdColor = (undefined === parameters.lcdColor ? steelseries.LcdColor.STANDARD : parameters.lcdColor), + lcdVisible = (undefined === parameters.lcdVisible ? true : parameters.lcdVisible), + digitalFont = (undefined === parameters.digitalFont ? false : parameters.digitalFont), + section = (undefined === parameters.section ? null : parameters.section), + area = (undefined === parameters.area ? null : parameters.area), + lcdTitleStrings = (undefined === parameters.lcdTitleStrings ? ['Latest', 'Average'] : parameters.lcdTitleStrings), + titleString = (undefined === parameters.titleString ? '' : parameters.titleString), + useColorLabels = (undefined === parameters.useColorLabels ? false : parameters.useColorLabels), + fullScaleDeflectionTime = (undefined === parameters.fullScaleDeflectionTime ? 2.5 : parameters.fullScaleDeflectionTime); + + var tweenLatest; + var tweenAverage; + var valueLatest = 0; + var valueAverage = 0; + var angleStep = RAD_FACTOR; + var angleLatest = this.valueLatest; + var angleAverage = this.valueAverage; + var rotationOffset = -HALF_PI; + var angleRange = TWO_PI; + var range = 360; + var repainting = false; + + // Get the canvas context and clear it + var mainCtx = getCanvasContext(canvas); + // Has a size been specified? + if (size === 0) { + size = Math.min(mainCtx.canvas.width, mainCtx.canvas.height); + } + + // Set the size - also clears the canvas + mainCtx.canvas.width = size; + mainCtx.canvas.height = size; + + var imageWidth = size; + var imageHeight = size; + + var centerX = imageWidth / 2; + var centerY = imageHeight / 2; + + var lcdFontHeight = Math.floor(imageWidth / 10); + var stdFont = lcdFontHeight + 'px ' + stdFontName; + var lcdFont = lcdFontHeight + 'px ' + lcdFontName; + var lcdWidth = imageWidth * 0.3; + var lcdHeight = imageHeight * 0.12; + var lcdPosX = (imageWidth - lcdWidth) / 2; + var lcdPosY1 = imageHeight * 0.32; + var lcdPosY2 = imageHeight * 0.565; + + var initialized = false; + + // ************** Buffer creation ******************** + // Buffer for all static background painting code + var backgroundBuffer = createBuffer(size, size); + var backgroundContext = backgroundBuffer.getContext('2d'); + + // Buffer for LCD displays + var lcdBuffer; + + // Buffer for latest pointer images painting code + var pointerBufferLatest = createBuffer(size, size); + var pointerContextLatest = pointerBufferLatest.getContext('2d'); + + // Buffer for average pointer image + var pointerBufferAverage = createBuffer(size, size); + var pointerContextAverage = pointerBufferAverage.getContext('2d'); + + // Buffer for static foreground painting code + var foregroundBuffer = createBuffer(size, size); + var foregroundContext = foregroundBuffer.getContext('2d'); + + // ************** Image creation ******************** + var drawLcdText = function (value, bLatest) { + mainCtx.save(); + mainCtx.textAlign = 'center'; + mainCtx.strokeStyle = lcdColor.textColor; + mainCtx.fillStyle = lcdColor.textColor; + + //convert value from -180,180 range into 0-360 range + while (value < -180) { + value += 360; + } + if (!degreeScaleHalf && value < 0) { + value += 360; + } + + if (degreeScaleHalf && value > 180) { + value = -(360 - value); + } + + if (value >= 0) { + value = '00' + Math.round(value); + value = value.substring(value.length, value.length - 3); + } else { + value = '00' + Math.abs(Math.round(value)); + value = '-' + value.substring(value.length, value.length - 3); + } + + if (lcdColor === steelseries.LcdColor.STANDARD || lcdColor === steelseries.LcdColor.STANDARD_GREEN) { + mainCtx.shadowColor = 'gray'; + mainCtx.shadowOffsetX = imageWidth * 0.007; + mainCtx.shadowOffsetY = imageWidth * 0.007; + mainCtx.shadowBlur = imageWidth * 0.007; + } + mainCtx.font = (digitalFont ? lcdFont : stdFont); + mainCtx.fillText(value + '\u00B0', imageWidth / 2 + lcdWidth * 0.05, (bLatest ? lcdPosY1 : lcdPosY2) + lcdHeight * 0.5 + lcdFontHeight * 0.38, lcdWidth * 0.9); + + mainCtx.restore(); + }; + + var drawAreaSectionImage = function (ctx, start, stop, color, filled) { + + ctx.save(); + ctx.strokeStyle = color; + ctx.fillStyle = color; + ctx.lineWidth = imageWidth * 0.035; + var startAngle = (angleRange / range * start); + var stopAngle = startAngle + (stop - start) / (range / angleRange); + ctx.translate(centerX, centerY); + ctx.rotate(rotationOffset); + ctx.beginPath(); + if (filled) { + ctx.moveTo(0, 0); + ctx.arc(0, 0, imageWidth * 0.365 - ctx.lineWidth / 2, startAngle, stopAngle, false); + } else { + ctx.arc(0, 0, imageWidth * 0.365, startAngle, stopAngle, false); + } + if (filled) { + ctx.moveTo(0, 0); + ctx.fill(); + } else { + ctx.stroke(); + } + + ctx.translate(-centerX, -centerY); + ctx.restore(); + }; + + var drawTickmarksImage = function (ctx) { + var OUTER_POINT = imageWidth * 0.38, + MAJOR_INNER_POINT = imageWidth * 0.35, + //MED_INNER_POINT = imageWidth * 0.355, + MINOR_INNER_POINT = imageWidth * 0.36, + TEXT_WIDTH = imageWidth * 0.1, + TEXT_TRANSLATE_X = imageWidth * 0.31, + CARDINAL_TRANSLATE_X = imageWidth * 0.36, + stdFont, smlFont, + i, val, to; + + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + + ctx.save(); + ctx.strokeStyle = backgroundColor.labelColor.getRgbaColor(); + ctx.fillStyle = backgroundColor.labelColor.getRgbaColor(); + ctx.translate(centerX, centerY); + + if (!degreeScale) { + + stdFont = 0.12 * imageWidth + 'px serif'; + smlFont = 0.06 * imageWidth + 'px serif'; + + //var angleStep = RAD_FACTOR; + ctx.lineWidth = 1; + ctx.strokeStyle = backgroundColor.symbolColor.getRgbaColor(); + + for (i = 0; 360 > i; i += 2.5) { + + if (0 === i % 5) { + ctx.beginPath(); + ctx.moveTo(imageWidth * 0.38, 0); + ctx.lineTo(imageWidth * 0.36, 0); + ctx.closePath(); + ctx.stroke(); + } + + // Draw the labels + ctx.save(); + switch (i) { + case 0: //E + ctx.translate(imageWidth * 0.35, 0); + ctx.rotate(HALF_PI); + ctx.font = stdFont; + ctx.fillText(pointSymbols[2], 0, 0); + ctx.translate(-imageWidth * 0.35, 0); + break; + case 45: //SE + ctx.translate(imageWidth * 0.29, 0); + ctx.rotate(HALF_PI); + ctx.font = smlFont; + ctx.fillText(pointSymbols[3], 0, 0); + ctx.translate(-imageWidth * 0.29, 0); + break; + case 90: //S + ctx.translate(imageWidth * 0.35, 0); + ctx.rotate(HALF_PI); + ctx.font = stdFont; + ctx.fillText(pointSymbols[4], 0, 0); + ctx.translate(-imageWidth * 0.35, 0); + break; + case 135: //SW + ctx.translate(imageWidth * 0.29, 0); + ctx.rotate(HALF_PI); + ctx.font = smlFont; + ctx.fillText(pointSymbols[5], 0, 0); + ctx.translate(-imageWidth * 0.29, 0); + break; + case 180: //W + ctx.translate(imageWidth * 0.35, 0); + ctx.rotate(HALF_PI); + ctx.font = stdFont; + ctx.fillText(pointSymbols[6], 0, 0); + ctx.translate(-imageWidth * 0.35, 0); + break; + case 225: //NW + ctx.translate(imageWidth * 0.29, 0); + ctx.rotate(HALF_PI); + ctx.font = smlFont; + ctx.fillText(pointSymbols[7], 0, 0); + ctx.translate(-imageWidth * 0.29, 0); + break; + case 270: //N + ctx.translate(imageWidth * 0.35, 0); + ctx.rotate(HALF_PI); + ctx.font = stdFont; + ctx.fillText(pointSymbols[0], 0, 0); + ctx.translate(-imageWidth * 0.35, 0); + break; + case 315: //NE + ctx.translate(imageWidth * 0.29, 0); + ctx.rotate(HALF_PI); + ctx.font = smlFont; + ctx.fillText(pointSymbols[1], 0, 0); + ctx.translate(-imageWidth * 0.29, 0); + break; + } + ctx.restore(); + + if (roseVisible && (0 === i || 22.5 === i || 45 === i || 67.5 === i || 90 === i || 112.5 === i || 135 === i || 157.5 === i || 180 === i || 202.5 === i || 225 === i || 247.5 === i || 270 === i || 292.5 === i || 315 === i || 337.5 === i || 360 === i)) { + // ROSE_LINE + ctx.save(); + ctx.beginPath(); + // indent the 16 half quadrant lines a bit for visual effect + if (i % 45) { + ctx.moveTo(imageWidth * 0.29, 0); + } else { + ctx.moveTo(imageWidth * 0.38, 0); + } + ctx.lineTo(imageWidth * 0.1, 0); + ctx.closePath(); + ctx.restore(); + ctx.stroke(); + } + ctx.rotate(angleStep * 2.5); + } + } else { + stdFont = Math.floor(0.1 * imageWidth) + 'px serif bold'; + smlFont = Math.floor(imageWidth * 0.04) + 'px ' + stdFontName; + + ctx.rotate(angleStep * 5); + for (i = 5; 360 >= i; i += 5) { + // Draw the labels + ctx.save(); + if (pointSymbolsVisible) { + + switch (i) { + case 360: + ctx.translate(CARDINAL_TRANSLATE_X, 0); + ctx.rotate(HALF_PI); + ctx.font = stdFont; + ctx.fillText(pointSymbols[2], 0, 0, TEXT_WIDTH); + ctx.translate(-CARDINAL_TRANSLATE_X, 0); + break; + case 90: + ctx.translate(CARDINAL_TRANSLATE_X, 0); + ctx.rotate(HALF_PI); + ctx.font = stdFont; + ctx.fillText(pointSymbols[4], 0, 0, TEXT_WIDTH); + ctx.translate(-CARDINAL_TRANSLATE_X, 0); + break; + case 180: + ctx.translate(CARDINAL_TRANSLATE_X, 0); + ctx.rotate(HALF_PI); + ctx.font = stdFont; + ctx.fillText(pointSymbols[6], 0, 0, TEXT_WIDTH); + ctx.translate(-CARDINAL_TRANSLATE_X, 0); + break; + case 270: + ctx.translate(CARDINAL_TRANSLATE_X, 0); + ctx.rotate(HALF_PI); + ctx.font = stdFont; + ctx.fillText(pointSymbols[0], 0, 0, TEXT_WIDTH); + ctx.translate(-CARDINAL_TRANSLATE_X, 0); + break; + + case 5: + case 85: + case 95: + case 175: + case 185: + case 265: + case 275: + case 355: + //leave room for ordinal labels + break; + + default: + if ((i + 90) % 20) { + ctx.lineWidth = ((i + 90) % 5) ? 1.5 : 1; + ctx.beginPath(); + ctx.moveTo(OUTER_POINT, 0); + to = (i + 90) % 10 ? MINOR_INNER_POINT : MAJOR_INNER_POINT; + ctx.lineTo(to, 0); + ctx.closePath(); + ctx.stroke(); + } else { + ctx.lineWidth = 1.5; + ctx.beginPath(); + ctx.moveTo(OUTER_POINT, 0); + ctx.lineTo(MAJOR_INNER_POINT, 0); + ctx.closePath(); + ctx.stroke(); + val = (i + 90) % 360; + ctx.translate(TEXT_TRANSLATE_X, 0); + ctx.rotate(HALF_PI); + ctx.font = smlFont; + ctx.fillText(('0'.substring(val >= 100) + val), 0, 0, TEXT_WIDTH); + ctx.translate(-TEXT_TRANSLATE_X, 0); + } + } + } else { + + if ((i + 90) % 20) { + ctx.lineWidth = ((i + 90) % 5) ? 1.5 : 1; + ctx.beginPath(); + ctx.moveTo(OUTER_POINT, 0); + to = (i + 90) % 10 ? MINOR_INNER_POINT : MAJOR_INNER_POINT; + ctx.lineTo(to, 0); + ctx.closePath(); + ctx.stroke(); + } else { + ctx.lineWidth = 1.5; + ctx.beginPath(); + ctx.moveTo(OUTER_POINT, 0); + ctx.lineTo(MAJOR_INNER_POINT, 0); + ctx.closePath(); + ctx.stroke(); + val = (i + 90) % 360; + if (degreeScaleHalf) { + //invert 180-360 + if (val > 180) { + val = -(360 - val); + } + } + ctx.translate(TEXT_TRANSLATE_X, 0); + ctx.rotate(HALF_PI); + ctx.font = smlFont; + ctx.fillText(val, 0, 0, TEXT_WIDTH); + ctx.translate(-TEXT_TRANSLATE_X, 0); + } + } + ctx.restore(); + ctx.rotate(angleStep * 5); + } + + } + ctx.translate(-centerX, -centerY); + ctx.restore(); + }; + + var drawLcdTitles = function (ctx) { + if (lcdTitleStrings.length > 0) { + ctx.save(); + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.fillStyle = (useColorLabels ? pointerColor.medium.getRgbaColor() : backgroundColor.labelColor.getRgbaColor()); + ctx.font = 0.040 * imageWidth + 'px ' + stdFontName; + ctx.fillText(lcdTitleStrings[0], imageWidth / 2, imageHeight * 0.29, imageWidth * 0.3); + ctx.fillStyle = (useColorLabels ? pointerColorAverage.medium.getRgbaColor() : backgroundColor.labelColor.getRgbaColor()); + ctx.fillText(lcdTitleStrings[1], imageWidth / 2, imageHeight * 0.71, imageWidth * 0.3); + if (titleString.length > 0) { + ctx.fillStyle = backgroundColor.labelColor.getRgbaColor(); + ctx.font = 0.0467 * imageWidth + 'px ' + stdFontName; + ctx.fillText(titleString, imageWidth / 2, imageHeight * 0.5, imageWidth * 0.3); + } + } + }; + + // ************** Initialization ******************** + // Draw all static painting code to background + + var init = function (parameters) { + parameters = parameters || {}; + var drawBackground = (undefined === parameters.background ? false : parameters.background); + var drawPointer = (undefined === parameters.pointer ? false : parameters.pointer); + var drawForeground = (undefined === parameters.foreground ? false : parameters.foreground); + + initialized = true; + + if (drawBackground && frameVisible) { + drawRadialFrameImage(backgroundContext, frameDesign, centerX, centerY, imageWidth, imageHeight); + } + + if (drawBackground && backgroundVisible) { + // Create background in background buffer (backgroundBuffer) + drawRadialBackgroundImage(backgroundContext, backgroundColor, centerX, centerY, imageWidth, imageHeight); + + // Create custom layer in background buffer (backgroundBuffer) + drawRadialCustomImage(backgroundContext, customLayer, centerX, centerY, imageWidth, imageHeight); + + // Create section in background buffer (backgroundBuffer) + if (null !== section && 0 < section.length) { + var sectionIndex = section.length; + do { + sectionIndex--; + drawAreaSectionImage(backgroundContext, section[sectionIndex].start, section[sectionIndex].stop, section[sectionIndex].color, false); + } + while (0 < sectionIndex); + } + + // Create area in background buffer (backgroundBuffer) + if (null !== area && 0 < area.length) { + var areaIndex = area.length; + do { + areaIndex--; + drawAreaSectionImage(backgroundContext, area[areaIndex].start, area[areaIndex].stop, area[areaIndex].color, true); + } + while (0 < areaIndex); + } + + drawTickmarksImage(backgroundContext); + } + + if (drawBackground && roseVisible) { + drawRoseImage(backgroundContext, centerX, centerY, imageWidth, imageHeight, backgroundColor); + } + + // Create lcd background if selected in background buffer (backgroundBuffer) + if (drawBackground && lcdVisible) { + lcdBuffer = createLcdBackgroundImage(lcdWidth, lcdHeight, lcdColor); + backgroundContext.drawImage(lcdBuffer, lcdPosX, lcdPosY1); + backgroundContext.drawImage(lcdBuffer, lcdPosX, lcdPosY2); + // Create title in background buffer (backgroundBuffer) + drawLcdTitles(backgroundContext); + } + + if (drawPointer) { + drawPointerImage(pointerContextAverage, imageWidth, pointerTypeAverage, pointerColorAverage, backgroundColor.labelColor); + drawPointerImage(pointerContextLatest, imageWidth, pointerTypeLatest, pointerColor, backgroundColor.labelColor); + } + + if (drawForeground && foregroundVisible) { + var knobVisible = (pointerTypeLatest.type === 'type15' || pointerTypeLatest.type === 'type16' ? false : true); + drawRadialForegroundImage(foregroundContext, foregroundType, imageWidth, imageHeight, knobVisible, knobType, knobStyle); + } + }; + + var resetBuffers = function (buffers) { + buffers = buffers || {}; + var resetBackground = (undefined === buffers.background ? false : buffers.background); + var resetPointer = (undefined === buffers.pointer ? false : buffers.pointer); + var resetForeground = (undefined === buffers.foreground ? false : buffers.foreground); + + // Buffer for all static background painting code + if (resetBackground) { + backgroundBuffer.width = size; + backgroundBuffer.height = size; + backgroundContext = backgroundBuffer.getContext('2d'); + } + // Buffers for pointer image painting code + if (resetPointer) { + pointerBufferLatest.width = size; + pointerBufferLatest.height = size; + pointerContextLatest = pointerBufferLatest.getContext('2d'); + + pointerBufferAverage.width = size; + pointerBufferAverage.height = size; + pointerContextAverage = pointerBufferAverage.getContext('2d'); + } + // Buffer for static foreground painting code + if (resetForeground) { + foregroundBuffer.width = size; + foregroundBuffer.height = size; + foregroundContext = foregroundBuffer.getContext('2d'); + } + }; + + //************************************ Public methods ************************************** + this.setValueLatest = function (newValue) { + // Actually need to handle 0-360 rather than 0-359 + // 1-360 are used for directions + // 0 is used as a special case to indicate 'calm' + newValue = parseFloat(newValue); + newValue = newValue === 360 ? 360 : newValue % 360; + if (valueLatest !== newValue) { + valueLatest = newValue; + this.repaint(); + } + return this; + }; + + this.getValueLatest = function () { + return valueLatest; + }; + + this.setValueAverage = function (newValue) { + // Actually need to handle 0-360 rather than 0-359 + // 1-360 are used for directions + // 0 is used as a special case to indicate 'calm' + newValue = parseFloat(newValue); + newValue = newValue === 360 ? 360 : newValue % 360; + if (valueAverage !== newValue) { + valueAverage = newValue; + this.repaint(); + } + return this; + }; + + this.getValueAverage = function () { + return valueAverage; + }; + + this.setValueAnimatedLatest = function (newValue, callback) { + var targetValue, + gauge = this, + diff, + time; + // Actually need to handle 0-360 rather than 0-359 + // 1-360 are used for directions + // 0 is used as a special case to indicate 'calm' + newValue = parseFloat(newValue); + targetValue = (newValue === 360 ? 360 : newValue % 360); + + if (valueLatest !== targetValue) { + if (undefined !== tweenLatest && tweenLatest.isPlaying) { + tweenLatest.stop(); + } + + diff = getShortestAngle(valueLatest, targetValue); + + if (diff !== 0) { // 360 - 0 is a diff of zero + time = fullScaleDeflectionTime * Math.abs(diff) / 180; + time = Math.max(time, fullScaleDeflectionTime / 5); + tweenLatest = new Tween({}, '', Tween.regularEaseInOut, valueLatest, valueLatest + diff, time); + tweenLatest.onMotionChanged = function (event) { + valueLatest = event.target._pos === 360 ? 360 : event.target._pos % 360; + if (!repainting) { + repainting = true; + requestAnimFrame(gauge.repaint); + } + }; + + tweenLatest.onMotionFinished = function () { + valueLatest = targetValue; + if (!repainting) { + repainting = true; + requestAnimFrame(gauge.repaint); + } + // do we have a callback function to process? + if (callback && typeof(callback) === "function") { + callback(); + } + }; + + tweenLatest.start(); + } else { + // target different from current, but diff is zero (0 -> 360 for instance), so just repaint + valueLatest = targetValue; + if (!repainting) { + repainting = true; + requestAnimFrame(gauge.repaint); + } + } + } + return this; + }; + + this.setValueAnimatedAverage = function (newValue, callback) { + var targetValue, + gauge = this, + diff, time; + // Actually need to handle 0-360 rather than 0-359 + // 1-360 are used for directions + // 0 is used as a special case to indicate 'calm' + newValue = parseFloat(newValue); + targetValue = (newValue === 360 ? 360 : newValue % 360); + if (valueAverage !== newValue) { + if (undefined !== tweenAverage && tweenAverage.isPlaying) { + tweenAverage.stop(); + } + + diff = getShortestAngle(valueAverage, targetValue); + if (diff !== 0) { // 360 - 0 is a diff of zero + time = fullScaleDeflectionTime * Math.abs(diff) / 180; + time = Math.max(time, fullScaleDeflectionTime / 5); + tweenAverage = new Tween({}, '', Tween.regularEaseInOut, valueAverage, valueAverage + diff, time); + tweenAverage.onMotionChanged = function (event) { + valueAverage = event.target._pos === 360 ? 360 : event.target._pos % 360; + if (!repainting) { + repainting = true; + requestAnimFrame(gauge.repaint); + } + }; + + tweenAverage.onMotionFinished = function () { + valueAverage = targetValue; + if (!repainting) { + repainting = true; + requestAnimFrame(gauge.repaint); + } + // do we have a callback function to process? + if (callback && typeof(callback) === "function") { + callback(); + } + }; + + tweenAverage.start(); + } else { + // target different from current, but diff is zero (0 -> 360 for instance), so just repaint + valueAverage = targetValue; + if (!repainting) { + repainting = true; + requestAnimFrame(gauge.repaint); + } + } + } + return this; + }; + + this.setArea = function (areaVal) { + area = areaVal; + resetBuffers({background: true}); + init({background: true}); + this.repaint(); + return this; + }; + + this.setSection = function (areaSec) { + section = areaSec; + resetBuffers({background: true}); + init({background: true}); + this.repaint(); + return this; + }; + + this.setFrameDesign = function (newFrameDesign) { + frameDesign = newFrameDesign; + resetBuffers({background: true}); + init({background: true}); + this.repaint(); + return this; + }; + + this.setBackgroundColor = function (newBackgroundColor) { + backgroundColor = newBackgroundColor; + resetBuffers({background: true}); + init({background: true}); + this.repaint(); + return this; + }; + + this.setForegroundType = function (newForegroundType) { + resetBuffers({foreground: true}); + foregroundType = newForegroundType; + init({foreground: true}); + this.repaint(); + return this; + }; + + this.setPointerColor = function (newPointerColor) { + resetBuffers({pointer: true}); + pointerColor = newPointerColor; + init({pointer: true}); + this.repaint(); + return this; + }; + + this.setPointerColorAverage = function (newPointerColor) { + resetBuffers({pointer: true}); + pointerColorAverage = newPointerColor; + init({pointer: true}); + this.repaint(); + return this; + }; + + this.setPointerType = function (newPointerType) { + pointerTypeLatest = newPointerType; + resetBuffers({pointer: true, + foreground: true + }); + init({pointer: true, + foreground: true + }); + this.repaint(); + return this; + }; + + this.setPointerTypeAverage = function (newPointerType) { + pointerTypeAverage = newPointerType; + resetBuffers({pointer: true, + foreground: true + }); + init({pointer: true, + foreground: true + }); + this.repaint(); + return this; + }; + + this.setPointSymbols = function (newPointSymbols) { + pointSymbols = newPointSymbols; + resetBuffers({background: true}); + init({background: true}); + this.repaint(); + return this; + }; + + this.setLcdColor = function (newLcdColor) { + lcdColor = newLcdColor; + resetBuffers({background: true}); + init({background: true}); + this.repaint(); + return this; + }; + + this.setLcdTitleStrings = function (titles) { + lcdTitleStrings = titles; + resetBuffers({background: true}); + init({background: true}); + this.repaint(); + return this; + }; + + this.repaint = function () { + if (!initialized) { + init({frame: true, + background: true, + led: true, + pointer: true, + foreground: true}); + } + + mainCtx.clearRect(0, 0, mainCtx.canvas.width, mainCtx.canvas.height); + + if (frameVisible || backgroundVisible) { + mainCtx.drawImage(backgroundBuffer, 0, 0); + } + + // Draw lcd display + if (lcdVisible) { + drawLcdText(valueLatest, true); + drawLcdText(valueAverage, false); + } + + // Define rotation angle + angleAverage = valueAverage * angleStep; + + // we have to draw to a rotated temporary image area so we can translate in + // absolute x, y values when drawing to main context + var shadowOffset = imageWidth * 0.006; + + // Define rotation center + mainCtx.save(); + mainCtx.translate(centerX, centerY); + mainCtx.rotate(angleAverage); + mainCtx.translate(-centerX, -centerY); + // Set the pointer shadow params + mainCtx.shadowColor = 'rgba(0, 0, 0, 0.8)'; + mainCtx.shadowOffsetX = mainCtx.shadowOffsetY = shadowOffset; + mainCtx.shadowBlur = shadowOffset * 2; + // Draw the pointer + mainCtx.drawImage(pointerBufferAverage, 0, 0); + // Define rotation angle difference for average pointer + angleLatest = valueLatest * angleStep - angleAverage; + mainCtx.translate(centerX, centerY); + mainCtx.rotate(angleLatest); + mainCtx.translate(-centerX, -centerY); + mainCtx.drawImage(pointerBufferLatest, 0, 0); + mainCtx.restore(); + + if (foregroundVisible) { + mainCtx.drawImage(foregroundBuffer, 0, 0); + } + + repainting = false; + }; + + // Visualize the component + this.repaint(); + + return this; + }; + + var led = function (canvas, parameters) { + parameters = parameters || {}; + var size = (undefined === parameters.size ? 0 : parameters.size), + ledColor = (undefined === parameters.ledColor ? steelseries.LedColor.RED_LED : parameters.ledColor); + + var ledBlinking = false; + var ledTimerId = 0; + + // Get the canvas context and clear it + var mainCtx = getCanvasContext(canvas); + // Has a size been specified? + if (size === 0) { + size = Math.min(mainCtx.canvas.width, mainCtx.canvas.height); + } + + // Set the size - also clears the canvas + mainCtx.canvas.width = size; + mainCtx.canvas.height = size; + + var initialized = false; + + // Buffer for led on painting code + var ledBufferOn = doc.createElement('canvas'); + ledBufferOn.width = size; + ledBufferOn.height = size; + var ledContextOn = ledBufferOn.getContext('2d'); + + // Buffer for led off painting code + var ledBufferOff = doc.createElement('canvas'); + ledBufferOff.width = size; + ledBufferOff.height = size; + var ledContextOff = ledBufferOff.getContext('2d'); + + // Buffer for current led painting code + var ledBuffer = ledBufferOff; + + var init = function () { + initialized = true; + + // Draw LED ON in ledBuffer_ON + ledContextOn.clearRect(0, 0, ledContextOn.canvas.width, ledContextOn.canvas.height); + ledContextOn.drawImage(createLedImage(size, 1, ledColor), 0, 0); + + // Draw LED ON in ledBuffer_OFF + ledContextOff.clearRect(0, 0, ledContextOff.canvas.width, ledContextOff.canvas.height); + ledContextOff.drawImage(createLedImage(size, 0, ledColor), 0, 0); + }; + + this.toggleLed = function () { + if (ledBuffer === ledBufferOn) { + ledBuffer = ledBufferOff; + } else { + ledBuffer = ledBufferOn; + } + repaint(); + return this; + }; + + this.setLedColor = function (newColor) { + ledColor = newColor; + initialized = false; + repaint(); + return this; + }; + + this.setLedOnOff = function (on) { + if (!!on) { + ledBuffer = ledBufferOn; + } else { + ledBuffer = ledBufferOff; + } + repaint(); + return this; + }; + + this.blink = function (blink) { + if (!!blink) { + if (!ledBlinking) { + ledTimerId = setInterval(this.toggleLed, 1000); + ledBlinking = true; + } + } else { + if (ledBlinking) { + clearInterval(ledTimerId); + ledBlinking = false; + ledBuffer = ledBufferOff; + } + } + return this; + }; + + var repaint = function () { + if (!initialized) { + init(); + } + + mainCtx.save(); + mainCtx.clearRect(0, 0, mainCtx.canvas.width, mainCtx.canvas.height); + + mainCtx.drawImage(ledBuffer, 0, 0); + + mainCtx.restore(); + }; + + repaint(); + + return this; + }; + + var odometer = function (canvas, parameters) { + parameters = parameters || {}; + + // parameters + var _context = (undefined === parameters._context ? null : parameters._context), // If component used internally by steelseries + height = (undefined === parameters.height ? 0 : parameters.height), + digits = (undefined === parameters.digits ? 6 : parameters.digits), + decimals = (undefined === parameters.decimals ? 1 : parameters.decimals), + decimalBackColor = (undefined === parameters.decimalBackColor ? '#F0F0F0' : parameters.decimalBackColor), + decimalForeColor = (undefined === parameters.decimalForeColor ? '#F01010' : parameters.decimalForeColor), + font = (undefined === parameters.font ? 'sans-serif' : parameters.font), + value = (undefined === parameters.value ? 0 : parameters.value), + valueBackColor = (undefined === parameters.valueBackColor ? '#050505' : parameters.valueBackColor), + valueForeColor = (undefined === parameters.valueForeColor ? '#F8F8F8' : parameters.valueForeColor), + wobbleFactor = (undefined === parameters.wobbleFactor ? 0.07 : parameters.wobbleFactor), + // + initialized = false, + tween, ctx, + repainting = false, + digitHeight, digitWidth, stdFont, + width, columnHeight, verticalSpace, zeroOffset, + wobble = [], + //buffers + backgroundBuffer, backgroundContext, + foregroundBuffer, foregroundContext, + digitBuffer, digitContext, + decimalBuffer, decimalContext; + // End of variables + + // Get the canvas context and clear it + if (_context) { + ctx = _context; + } else { + ctx = getCanvasContext(canvas); + } + + // Has a height been specified? + if (height === 0) { + height = ctx.canvas.height; + } + + // Cannot display negative values yet + if (value < 0) { + value = 0; + } + + digitHeight = Math.floor(height * 0.85); + stdFont = '600 ' + digitHeight + 'px ' + font; + + digitWidth = Math.floor(height * 0.68); + width = digitWidth * (digits + decimals); + columnHeight = digitHeight * 11; + verticalSpace = columnHeight / 12; + zeroOffset = verticalSpace * 0.81; + + // Resize and clear the main context + ctx.canvas.width = width; + ctx.canvas.height = height; + + // Create buffers + backgroundBuffer = createBuffer(width, height); + backgroundContext = backgroundBuffer.getContext('2d'); + + foregroundBuffer = createBuffer(width, height); + foregroundContext = foregroundBuffer.getContext('2d'); + + digitBuffer = createBuffer(digitWidth, columnHeight * 1.1); + digitContext = digitBuffer.getContext('2d'); + + decimalBuffer = createBuffer(digitWidth, columnHeight * 1.1); + decimalContext = decimalBuffer.getContext('2d'); + + function init() { + var grad, i; + + initialized = true; + + // Create the foreground + foregroundContext.rect(0, 0, width, height); + grad = foregroundContext.createLinearGradient(0, 0, 0, height); + grad.addColorStop(0, 'rgba(0, 0, 0, 1)'); + grad.addColorStop(0.1, 'rgba(0, 0, 0, 0.4)'); + grad.addColorStop(0.33, 'rgba(255, 255, 255, 0.45)'); + grad.addColorStop(0.46, 'rgba(255, 255, 255, 0)'); + grad.addColorStop(0.9, 'rgba(0, 0, 0, 0.4)'); + grad.addColorStop(1, 'rgba(0, 0, 0, 1)'); + foregroundContext.fillStyle = grad; + foregroundContext.fill(); + + // Create a digit column + // background + digitContext.rect(0, 0, digitWidth, columnHeight * 1.1); + digitContext.fillStyle = valueBackColor; + digitContext.fill(); + // edges + digitContext.strokeStyle = '#f0f0f0'; + digitContext.lineWidth = '1px'; //height * 0.1 + 'px'; + digitContext.moveTo(0, 0); + digitContext.lineTo(0, columnHeight * 1.1); + digitContext.stroke(); + digitContext.strokeStyle = '#202020'; + digitContext.moveTo(digitWidth, 0); + digitContext.lineTo(digitWidth, columnHeight * 1.1); + digitContext.stroke(); + // numerals + digitContext.textAlign = 'center'; + digitContext.textBaseline = 'middle'; + digitContext.font = stdFont; + digitContext.fillStyle = valueForeColor; + // put the digits 901234567890 vertically into the buffer + for (i = 9; i < 21; i++) { + digitContext.fillText(i % 10, digitWidth * 0.5, verticalSpace * (i - 9) + verticalSpace / 2); + } + + // Create a decimal column + if (decimals > 0) { + // background + decimalContext.rect(0, 0, digitWidth, columnHeight * 1.1); + decimalContext.fillStyle = decimalBackColor; + decimalContext.fill(); + // edges + decimalContext.strokeStyle = '#f0f0f0'; + decimalContext.lineWidth = '1px'; //height * 0.1 + 'px'; + decimalContext.moveTo(0, 0); + decimalContext.lineTo(0, columnHeight * 1.1); + decimalContext.stroke(); + decimalContext.strokeStyle = '#202020'; + decimalContext.moveTo(digitWidth, 0); + decimalContext.lineTo(digitWidth, columnHeight * 1.1); + decimalContext.stroke(); + // numerals + decimalContext.textAlign = 'center'; + decimalContext.textBaseline = 'middle'; + decimalContext.font = stdFont; + decimalContext.fillStyle = decimalForeColor; + // put the digits 901234567890 vertically into the buffer + for (i = 9; i < 21; i++) { + decimalContext.fillText(i % 10, digitWidth * 0.5, verticalSpace * (i - 9) + verticalSpace / 2); + } + } + // wobble factors + for (i = 0; i < (digits + decimals); i++) { + wobble[i] = Math.random() * wobbleFactor * height - wobbleFactor * height / 2; + } + + } + + function drawDigits() { + var pos = 1, + val = value, i, num, numb, frac, prevNum; + + // do not use Math.pow() - rounding errors! + for (i = 0; i < decimals; i++) { + val *= 10; + } + + numb = Math.floor(val); + frac = val - numb; + numb = String(numb); + prevNum = 9; + + for (i = 0; i < decimals + digits; i++) { + num = +numb.substring(numb.length - i - 1, numb.length - i) || 0; + if (prevNum !== 9) { + frac = 0; + } + if (i < decimals) { + backgroundContext.drawImage(decimalBuffer, width - digitWidth * pos, -(verticalSpace * (num + frac) + zeroOffset + wobble[i])); + } else { + backgroundContext.drawImage(digitBuffer, width - digitWidth * pos, -(verticalSpace * (num + frac) + zeroOffset + wobble[i])); + } + pos++; + prevNum = num; + } + } + + this.setValueAnimated = function (newVal, callback) { + var gauge = this; + newVal = parseFloat(newVal); + + if (newVal < 0) { + newVal = 0; + } + if (value !== newVal) { + if (undefined !== tween && tween.isPlaying) { + tween.stop(); + } + + tween = new Tween({}, '', Tween.strongEaseOut, value, newVal, 2); + tween.onMotionChanged = function (event) { + value = event.target._pos; + if (!repainting) { + repainting = true; + requestAnimFrame(gauge.repaint); + } + }; + + // do we have a callback function to process? + if (callback && typeof(callback) === "function") { + tween.onMotionFinished = callback; + } + + tween.start(); + } + this.repaint(); + return this; + }; + + this.setValue = function (newVal) { + value = parseFloat(newVal); + if (value < 0) { + value = 0; + } + this.repaint(); + return this; + }; + + this.getValue = function () { + return value; + }; + + this.repaint = function () { + if (!initialized) { + init(); + } + + // draw digits + drawDigits(); + + // draw the foreground + backgroundContext.drawImage(foregroundBuffer, 0, 0); + + // paint back to the main context + ctx.drawImage(backgroundBuffer, 0, 0); + + repainting = false; + }; + + this.repaint(); + }; + + //************************************ I M A G E - F U N C T I O N S ***************************************** + + var drawRoseImage = function (ctx, centerX, centerY, imageWidth, imageHeight, backgroundColor) { + var fill = true, + i, grad, + symbolColor = backgroundColor.symbolColor.getRgbaColor(); + + ctx.save(); + ctx.lineWidth = 1; + ctx.fillStyle = symbolColor; + ctx.strokeStyle = symbolColor; + ctx.translate(centerX, centerY); + // broken ring + for (i = 0; i < 360; i += 15) { + fill = !fill; + + ctx.beginPath(); + ctx.arc(0, 0, imageWidth * 0.26, i * RAD_FACTOR, (i + 15) * RAD_FACTOR, false); + ctx.arc(0, 0, imageWidth * 0.23, (i + 15) * RAD_FACTOR, i * RAD_FACTOR, true); + ctx.closePath(); + if (fill) { + ctx.fill(); + } + ctx.stroke(); + } + + ctx.translate(-centerX, -centerY); + +/* + // PATH1_2 + ctx.save(); + ctx.beginPath(); + ctx.moveTo(imageWidth * 0.560747, imageHeight * 0.584112); + ctx.lineTo(imageWidth * 0.640186, imageHeight * 0.644859); + ctx.lineTo(imageWidth * 0.584112, imageHeight * 0.560747); + ctx.lineTo(imageWidth * 0.560747, imageHeight * 0.584112); + ctx.closePath(); + ctx.fillStyle = fillColorPath; + ctx.fill(); + ctx.stroke(); + + // PATH2_2 + ctx.save(); + ctx.beginPath(); + ctx.moveTo(imageWidth * 0.411214, imageHeight * 0.560747); + ctx.lineTo(imageWidth * 0.355140, imageHeight * 0.644859); + ctx.lineTo(imageWidth * 0.439252, imageHeight * 0.588785); + ctx.lineTo(imageWidth * 0.411214, imageHeight * 0.560747); + ctx.closePath(); + ctx.fillStyle = fillColorPath; + ctx.fill(); + ctx.stroke(); + + // PATH3_2 + ctx.save(); + ctx.beginPath(); + ctx.moveTo(imageWidth * 0.584112, imageHeight * 0.443925); + ctx.lineTo(imageWidth * 0.640186, imageHeight * 0.359813); + ctx.lineTo(imageWidth * 0.560747, imageHeight * 0.420560); + ctx.lineTo(imageWidth * 0.584112, imageHeight * 0.443925); + ctx.closePath(); + ctx.fillStyle = fillColorPath; + ctx.fill(); + ctx.stroke(); + + // PATH4_2 + ctx.save(); + ctx.beginPath(); + ctx.moveTo(imageWidth * 0.439252, imageHeight * 0.415887); + ctx.lineTo(imageWidth * 0.355140, imageHeight * 0.359813); + ctx.lineTo(imageWidth * 0.415887, imageHeight * 0.439252); + ctx.lineTo(imageWidth * 0.439252, imageHeight * 0.415887); + ctx.closePath(); + ctx.fillStyle = fillColorPath; + ctx.fill(); + ctx.stroke(); + + // PATH5_2 + ctx.save(); + ctx.beginPath(); + ctx.moveTo(imageWidth * 0.523364, imageHeight * 0.397196); + ctx.lineTo(imageWidth * 0.5, imageHeight * 0.196261); + ctx.lineTo(imageWidth * 0.471962, imageHeight * 0.397196); + ctx.lineTo(imageWidth * 0.523364, imageHeight * 0.397196); + ctx.closePath(); + var PATH5_2_GRADIENT = ctx.createLinearGradient(0.476635 * imageWidth, 0, 0.518691 * imageWidth, 0); + PATH5_2_GRADIENT.addColorStop(0, 'rgb(222, 223, 218)'); + PATH5_2_GRADIENT.addColorStop(0.48, 'rgb(222, 223, 218)'); + PATH5_2_GRADIENT.addColorStop(0.49, backgroundColor.symbolColor.getRgbaColor()); + PATH5_2_GRADIENT.addColorStop(1, backgroundColor.symbolColor.getRgbaColor()); + ctx.fillStyle = PATH5_2_GRADIENT; + ctx.fill(); + ctx.stroke(); + + // PATH6_2 + ctx.save(); + ctx.beginPath(); + ctx.moveTo(imageWidth * 0.471962, imageHeight * 0.607476); + ctx.lineTo(imageWidth * 0.5, imageHeight * 0.813084); + ctx.lineTo(imageWidth * 0.523364, imageHeight * 0.607476); + ctx.lineTo(imageWidth * 0.471962, imageHeight * 0.607476); + ctx.closePath(); + var PATH6_2_GRADIENT = ctx.createLinearGradient(0.518691 * imageWidth, 0, (0.518691 + -0.037383) * imageWidth, 0); + PATH6_2_GRADIENT.addColorStop(0, 'rgb(222, 223, 218)'); + PATH6_2_GRADIENT.addColorStop(0.56, 'rgb(222, 223, 218)'); + PATH6_2_GRADIENT.addColorStop(0.5601, backgroundColor.symbolColor.getRgbaColor()); + PATH6_2_GRADIENT.addColorStop(1, backgroundColor.symbolColor.getRgbaColor()); + ctx.fillStyle = PATH6_2_GRADIENT; + ctx.lineWidth = 1; + ctx.lineCap = 'square'; + ctx.lineJoin = 'miter'; + ctx.strokeStyle = backgroundColor.symbolColor.getRgbaColor(); + ctx.fill(); + ctx.stroke(); + + // PATH7_2 + ctx.save(); + ctx.beginPath(); + ctx.moveTo(imageWidth * 0.602803, imageHeight * 0.528037); + ctx.lineTo(imageWidth * 0.803738, imageHeight * 0.5); + ctx.lineTo(imageWidth * 0.602803, imageHeight * 0.476635); + ctx.lineTo(imageWidth * 0.602803, imageHeight * 0.528037); + ctx.closePath(); + var PATH7_2_GRADIENT = ctx.createLinearGradient(0, 0.485981 * imageHeight, 0, 0.514018 * imageHeight); + PATH7_2_GRADIENT.addColorStop(0, 'rgb(222, 223, 218)'); + PATH7_2_GRADIENT.addColorStop(0.48, 'rgb(222, 223, 218)'); + PATH7_2_GRADIENT.addColorStop(0.49, backgroundColor.symbolColor.getRgbaColor()); + PATH7_2_GRADIENT.addColorStop(1, backgroundColor.symbolColor.getRgbaColor()); + ctx.fillStyle = PATH7_2_GRADIENT; + ctx.fill(); + ctx.stroke(); + + // PATH8_2 + ctx.save(); + ctx.beginPath(); + ctx.moveTo(imageWidth * 0.392523, imageHeight * 0.476635); + ctx.lineTo(imageWidth * 0.191588, imageHeight * 0.5); + ctx.lineTo(imageWidth * 0.392523, imageHeight * 0.528037); + ctx.lineTo(imageWidth * 0.392523, imageHeight * 0.476635); + ctx.closePath(); + var PATH8_2_GRADIENT = ctx.createLinearGradient(0, 0.528037 * imageHeight, 0, 0.485981 * imageHeight); + PATH8_2_GRADIENT.addColorStop(0, 'rgb(222, 223, 218)'); + PATH8_2_GRADIENT.addColorStop(0.52, 'rgb(222, 223, 218)'); + PATH8_2_GRADIENT.addColorStop(0.53, backgroundColor.symbolColor.getRgbaColor()); + PATH8_2_GRADIENT.addColorStop(1, backgroundColor.symbolColor.getRgbaColor()); + ctx.fillStyle = PATH8_2_GRADIENT; + ctx.fill(); + ctx.stroke(); + + // PATH9_2 + ctx.save(); + ctx.beginPath(); + ctx.moveTo(imageWidth * 0.406542, imageHeight * 0.504672); + ctx.bezierCurveTo(imageWidth * 0.406542, imageHeight * 0.453271, imageWidth * 0.448598, imageHeight * 0.411214, imageWidth * 0.5, imageHeight * 0.411214); + ctx.bezierCurveTo(imageWidth * 0.546728, imageHeight * 0.411214, imageWidth * 0.588785, imageHeight * 0.453271, imageWidth * 0.588785, imageHeight * 0.504672); + ctx.bezierCurveTo(imageWidth * 0.588785, imageHeight * 0.551401, imageWidth * 0.546728, imageHeight * 0.593457, imageWidth * 0.5, imageHeight * 0.593457); + ctx.bezierCurveTo(imageWidth * 0.448598, imageHeight * 0.593457, imageWidth * 0.406542, imageHeight * 0.551401, imageWidth * 0.406542, imageHeight * 0.504672); + ctx.closePath(); + ctx.moveTo(imageWidth * 0.387850, imageHeight * 0.504672); + ctx.bezierCurveTo(imageWidth * 0.387850, imageHeight * 0.560747, imageWidth * 0.439252, imageHeight * 0.612149, imageWidth * 0.5, imageHeight * 0.612149); + ctx.bezierCurveTo(imageWidth * 0.556074, imageHeight * 0.612149, imageWidth * 0.607476, imageHeight * 0.560747, imageWidth * 0.607476, imageHeight * 0.504672); + ctx.bezierCurveTo(imageWidth * 0.607476, imageHeight * 0.443925, imageWidth * 0.556074, imageHeight * 0.392523, imageWidth * 0.5, imageHeight * 0.392523); + ctx.bezierCurveTo(imageWidth * 0.439252, imageHeight * 0.392523, imageWidth * 0.387850, imageHeight * 0.443925, imageWidth * 0.387850, imageHeight * 0.504672); + ctx.closePath(); + ctx.fillStyle = fillColorPath; + ctx.lineWidth = 1; + ctx.lineCap = 'square'; + ctx.lineJoin = 'miter'; + ctx.strokeStyle = backgroundColor.symbolColor.getRgbaColor(); + ctx.fill(); + ctx.stroke(); + ctx.restore(); +*/ + // Replacement code, not quite the same but much smaller! + + for (i = 0; 360 >= i; i += 90) { + // Small pointers + ctx.beginPath(); + ctx.moveTo(imageWidth * 0.560747, imageHeight * 0.584112); + ctx.lineTo(imageWidth * 0.640186, imageHeight * 0.644859); + ctx.lineTo(imageWidth * 0.584112, imageHeight * 0.560747); + ctx.lineTo(imageWidth * 0.560747, imageHeight * 0.584112); + ctx.closePath(); + ctx.fillStyle = symbolColor; + ctx.fill(); + ctx.stroke(); + // Large pointers + ctx.beginPath(); + ctx.moveTo(imageWidth * 0.523364, imageHeight * 0.397196); + ctx.lineTo(imageWidth * 0.5, imageHeight * 0.196261); + ctx.lineTo(imageWidth * 0.471962, imageHeight * 0.397196); + ctx.lineTo(imageWidth * 0.523364, imageHeight * 0.397196); + ctx.closePath(); + grad = ctx.createLinearGradient(0.476635 * imageWidth, 0, 0.518691 * imageWidth, 0); + grad.addColorStop(0, 'rgb(222, 223, 218)'); + grad.addColorStop(0.48, 'rgb(222, 223, 218)'); + grad.addColorStop(0.49, symbolColor); + grad.addColorStop(1, symbolColor); + ctx.fillStyle = grad; + ctx.fill(); + ctx.stroke(); + ctx.translate(centerX, centerY); + ctx.rotate(i * RAD_FACTOR); + ctx.translate(-centerX, -centerY); + } + + // Central ring + ctx.beginPath(); + ctx.translate(centerX, centerY); + ctx.arc(0, 0, imageWidth * 0.1, 0, TWO_PI, false); + ctx.lineWidth = imageWidth * 0.022; + ctx.stroke(); + ctx.translate(-centerX, -centerY); + + ctx.restore(); + + }; + + var drawPointerImage = function (ctx, size, ptrType, ptrColor, lblColor) { + var ptrBuffer, ptrCtx, + grad, radius, + cacheKey = size.toString() + ptrType.type + ptrColor.light.getHexColor() + ptrColor.medium.getHexColor(); + + // check if we have already created and cached this buffer, if not create it + if (!drawPointerImage.cache[cacheKey]) { + // create a pointer buffer + ptrBuffer = createBuffer(size, size); + ptrCtx = ptrBuffer.getContext('2d'); + + switch (ptrType.type) { + case 'type2': + grad = ptrCtx.createLinearGradient(0, size * 0.471962, 0, size * 0.130841); + grad.addColorStop(0, lblColor.getRgbaColor()); + grad.addColorStop(0.36, lblColor.getRgbaColor()); + grad.addColorStop(0.361, ptrColor.light.getRgbaColor()); + grad.addColorStop(1, ptrColor.light.getRgbaColor()); + ptrCtx.fillStyle = grad; + ptrCtx.beginPath(); + ptrCtx.moveTo(size * 0.518691, size * 0.471962); + ptrCtx.lineTo(size * 0.509345, size * 0.462616); + ptrCtx.lineTo(size * 0.509345, size * 0.341121); + ptrCtx.lineTo(size * 0.504672, size * 0.130841); + ptrCtx.lineTo(size * 0.495327, size * 0.130841); + ptrCtx.lineTo(size * 0.490654, size * 0.341121); + ptrCtx.lineTo(size * 0.490654, size * 0.462616); + ptrCtx.lineTo(size * 0.481308, size * 0.471962); + ptrCtx.closePath(); + ptrCtx.fill(); + break; + + case 'type3': + ptrCtx.beginPath(); + ptrCtx.rect(size * 0.495327, size * 0.130841, size * 0.009345, size * 0.373831); + ptrCtx.closePath(); + ptrCtx.fillStyle = ptrColor.light.getRgbaColor(); + ptrCtx.fill(); + break; + + case 'type4': + grad = ptrCtx.createLinearGradient(0.467289 * size, 0, 0.528036 * size, 0); + grad.addColorStop(0, ptrColor.dark.getRgbaColor()); + grad.addColorStop(0.51, ptrColor.dark.getRgbaColor()); + grad.addColorStop(0.52, ptrColor.light.getRgbaColor()); + grad.addColorStop(1, ptrColor.light.getRgbaColor()); + ptrCtx.fillStyle = grad; + ptrCtx.beginPath(); + ptrCtx.moveTo(size * 0.5, size * 0.126168); + ptrCtx.lineTo(size * 0.514018, size * 0.135514); + ptrCtx.lineTo(size * 0.532710, size * 0.5); + ptrCtx.lineTo(size * 0.523364, size * 0.602803); + ptrCtx.lineTo(size * 0.476635, size * 0.602803); + ptrCtx.lineTo(size * 0.467289, size * 0.5); + ptrCtx.lineTo(size * 0.485981, size * 0.135514); + ptrCtx.lineTo(size * 0.5, size * 0.126168); + ptrCtx.closePath(); + ptrCtx.fill(); + break; + + case 'type5': + grad = ptrCtx.createLinearGradient(0.471962 * size, 0, 0.528036 * size, 0); + grad.addColorStop(0, ptrColor.light.getRgbaColor()); + grad.addColorStop(0.5, ptrColor.light.getRgbaColor()); + grad.addColorStop(0.5, ptrColor.medium.getRgbaColor()); + grad.addColorStop(1, ptrColor.medium.getRgbaColor()); + ptrCtx.fillStyle = grad; + ptrCtx.beginPath(); + ptrCtx.moveTo(size * 0.5, size * 0.495327); + ptrCtx.lineTo(size * 0.528037, size * 0.495327); + ptrCtx.lineTo(size * 0.5, size * 0.149532); + ptrCtx.lineTo(size * 0.471962, size * 0.495327); + ptrCtx.lineTo(size * 0.5, size * 0.495327); + ptrCtx.closePath(); + ptrCtx.fill(); + + ptrCtx.lineWidth = 1; + ptrCtx.lineCap = 'square'; + ptrCtx.lineJoin = 'miter'; + ptrCtx.strokeStyle = ptrColor.dark.getRgbaColor(); + ptrCtx.stroke(); + break; + + case 'type6': + ptrCtx.fillStyle = ptrColor.medium.getRgbaColor(); + ptrCtx.beginPath(); + ptrCtx.moveTo(size * 0.481308, size * 0.485981); + ptrCtx.lineTo(size * 0.481308, size * 0.392523); + ptrCtx.lineTo(size * 0.485981, size * 0.317757); + ptrCtx.lineTo(size * 0.495327, size * 0.130841); + ptrCtx.lineTo(size * 0.504672, size * 0.130841); + ptrCtx.lineTo(size * 0.514018, size * 0.317757); + ptrCtx.lineTo(size * 0.518691, size * 0.387850); + ptrCtx.lineTo(size * 0.518691, size * 0.485981); + ptrCtx.lineTo(size * 0.504672, size * 0.485981); + ptrCtx.lineTo(size * 0.504672, size * 0.387850); + ptrCtx.lineTo(size * 0.5, size * 0.317757); + ptrCtx.lineTo(size * 0.495327, size * 0.392523); + ptrCtx.lineTo(size * 0.495327, size * 0.485981); + ptrCtx.lineTo(size * 0.481308, size * 0.485981); + ptrCtx.closePath(); + ptrCtx.fill(); + break; + + case 'type7': + grad = ptrCtx.createLinearGradient(0.481308 * size, 0, 0.518691 * size, 0); + grad.addColorStop(0, ptrColor.dark.getRgbaColor()); + grad.addColorStop(1, ptrColor.medium.getRgbaColor()); + ptrCtx.fillStyle = grad; + ptrCtx.beginPath(); + ptrCtx.moveTo(size * 0.490654, size * 0.130841); + ptrCtx.lineTo(size * 0.481308, size * 0.5); + ptrCtx.lineTo(size * 0.518691, size * 0.5); + ptrCtx.lineTo(size * 0.504672, size * 0.130841); + ptrCtx.lineTo(size * 0.490654, size * 0.130841); + ptrCtx.closePath(); + ptrCtx.fill(); + break; + + case 'type8': + grad = ptrCtx.createLinearGradient(0.471962 * size, 0, 0.528036 * size, 0); + grad.addColorStop(0, ptrColor.light.getRgbaColor()); + grad.addColorStop(0.5, ptrColor.light.getRgbaColor()); + grad.addColorStop(0.5, ptrColor.medium.getRgbaColor()); + grad.addColorStop(1, ptrColor.medium.getRgbaColor()); + ptrCtx.fillStyle = grad; + ptrCtx.strokeStyle = ptrColor.dark.getRgbaColor(); + ptrCtx.beginPath(); + ptrCtx.moveTo(size * 0.5, size * 0.532710); + ptrCtx.lineTo(size * 0.532710, size * 0.5); + ptrCtx.bezierCurveTo(size * 0.532710, size * 0.5, size * 0.509345, size * 0.457943, size * 0.5, size * 0.149532); + ptrCtx.bezierCurveTo(size * 0.490654, size * 0.457943, size * 0.467289, size * 0.5, size * 0.467289, size * 0.5); + ptrCtx.lineTo(size * 0.5, size * 0.532710); + ptrCtx.closePath(); + ptrCtx.fill(); + ptrCtx.stroke(); + break; + + case 'type9': + grad = ptrCtx.createLinearGradient(0.471962 * size, 0, 0.528036 * size, 0); + grad.addColorStop(0, 'rgb(50, 50, 50)'); + grad.addColorStop(0.5, '#666666'); + grad.addColorStop(1, 'rgb(50, 50, 50)'); + ptrCtx.fillStyle = grad; + ptrCtx.strokeStyle = '#2E2E2E'; + ptrCtx.beginPath(); + ptrCtx.moveTo(size * 0.495327, size * 0.233644); + ptrCtx.lineTo(size * 0.504672, size * 0.233644); + ptrCtx.lineTo(size * 0.514018, size * 0.439252); + ptrCtx.lineTo(size * 0.485981, size * 0.439252); + ptrCtx.lineTo(size * 0.495327, size * 0.233644); + ptrCtx.closePath(); + ptrCtx.moveTo(size * 0.490654, size * 0.130841); + ptrCtx.lineTo(size * 0.471962, size * 0.471962); + ptrCtx.lineTo(size * 0.471962, size * 0.528037); + ptrCtx.bezierCurveTo(size * 0.471962, size * 0.528037, size * 0.476635, size * 0.602803, size * 0.476635, size * 0.602803); + ptrCtx.bezierCurveTo(size * 0.476635, size * 0.607476, size * 0.481308, size * 0.607476, size * 0.5, size * 0.607476); + ptrCtx.bezierCurveTo(size * 0.518691, size * 0.607476, size * 0.523364, size * 0.607476, size * 0.523364, size * 0.602803); + ptrCtx.bezierCurveTo(size * 0.523364, size * 0.602803, size * 0.528037, size * 0.528037, size * 0.528037, size * 0.528037); + ptrCtx.lineTo(size * 0.528037, size * 0.471962); + ptrCtx.lineTo(size * 0.509345, size * 0.130841); + ptrCtx.lineTo(size * 0.490654, size * 0.130841); + ptrCtx.closePath(); + ptrCtx.fill(); + + ptrCtx.beginPath(); + ptrCtx.moveTo(size * 0.495327, size * 0.219626); + ptrCtx.lineTo(size * 0.504672, size * 0.219626); + ptrCtx.lineTo(size * 0.504672, size * 0.135514); + ptrCtx.lineTo(size * 0.495327, size * 0.135514); + ptrCtx.lineTo(size * 0.495327, size * 0.219626); + ptrCtx.closePath(); + + ptrCtx.fillStyle = ptrColor.medium.getRgbaColor(); + ptrCtx.fill(); + break; + + case 'type10': + // POINTER_TYPE10 + ptrCtx.beginPath(); + ptrCtx.moveTo(size * 0.5, size * 0.149532); + ptrCtx.bezierCurveTo(size * 0.5, size * 0.149532, size * 0.443925, size * 0.490654, size * 0.443925, size * 0.5); + ptrCtx.bezierCurveTo(size * 0.443925, size * 0.532710, size * 0.467289, size * 0.556074, size * 0.5, size * 0.556074); + ptrCtx.bezierCurveTo(size * 0.532710, size * 0.556074, size * 0.556074, size * 0.532710, size * 0.556074, size * 0.5); + ptrCtx.bezierCurveTo(size * 0.556074, size * 0.490654, size * 0.5, size * 0.149532, size * 0.5, size * 0.149532); + ptrCtx.closePath(); + grad = ptrCtx.createLinearGradient(0.471962 * size, 0, 0.528036 * size, 0); + grad.addColorStop(0, ptrColor.light.getRgbaColor()); + grad.addColorStop(0.5, ptrColor.light.getRgbaColor()); + grad.addColorStop(0.5, ptrColor.medium.getRgbaColor()); + grad.addColorStop(1, ptrColor.medium.getRgbaColor()); + ptrCtx.fillStyle = grad; + ptrCtx.strokeStyle = ptrColor.medium.getRgbaColor(); + ptrCtx.lineWidth = 1; + ptrCtx.lineCap = 'square'; + ptrCtx.lineJoin = 'miter'; + ptrCtx.fill(); + ptrCtx.stroke(); + break; + + case 'type11': + // POINTER_TYPE11 + ptrCtx.beginPath(); + ptrCtx.moveTo(0.5 * size, 0.168224 * size); + ptrCtx.lineTo(0.485981 * size, 0.5 * size); + ptrCtx.bezierCurveTo(0.485981 * size, 0.5 * size, 0.481308 * size, 0.584112 * size, 0.5 * size, 0.584112 * size); + ptrCtx.bezierCurveTo(0.514018 * size, 0.584112 * size, 0.509345 * size, 0.5 * size, 0.509345 * size, 0.5 * size); + ptrCtx.lineTo(0.5 * size, 0.168224 * size); + ptrCtx.closePath(); + grad = ptrCtx.createLinearGradient(0, 0.168224 * size, 0, 0.584112 * size); + grad.addColorStop(0, ptrColor.medium.getRgbaColor()); + grad.addColorStop(1, ptrColor.dark.getRgbaColor()); + ptrCtx.fillStyle = grad; + ptrCtx.strokeStyle = ptrColor.dark.getRgbaColor(); + ptrCtx.fill(); + ptrCtx.stroke(); + break; + + case 'type12': + // POINTER_TYPE12 + ptrCtx.beginPath(); + ptrCtx.moveTo(0.5 * size, 0.168224 * size); + ptrCtx.lineTo(0.485981 * size, 0.5 * size); + ptrCtx.lineTo(0.5 * size, 0.504672 * size); + ptrCtx.lineTo(0.509345 * size, 0.5 * size); + ptrCtx.lineTo(0.5 * size, 0.168224 * size); + ptrCtx.closePath(); + grad = ptrCtx.createLinearGradient(0, 0.168224 * size, 0, 0.504672 * size); + grad.addColorStop(0, ptrColor.medium.getRgbaColor()); + grad.addColorStop(1, ptrColor.dark.getRgbaColor()); + ptrCtx.fillStyle = grad; + ptrCtx.strokeStyle = ptrColor.dark.getRgbaColor(); + ptrCtx.fill(); + ptrCtx.stroke(); + break; + + case 'type13': + // POINTER_TYPE13 + case 'type14': + // POINTER_TYPE14 (same shape as 13) + ptrCtx.beginPath(); + ptrCtx.moveTo(0.485981 * size, 0.168224 * size); + ptrCtx.lineTo(0.5 * size, 0.130841 * size); + ptrCtx.lineTo(0.509345 * size, 0.168224 * size); + ptrCtx.lineTo(0.509345 * size, 0.509345 * size); + ptrCtx.lineTo(0.485981 * size, 0.509345 * size); + ptrCtx.lineTo(0.485981 * size, 0.168224 * size); + ptrCtx.closePath(); + if (ptrType.type === 'type13') { + // TYPE13 + grad = ptrCtx.createLinearGradient(0, 0.5 * size, 0, 0.130841 * size); + grad.addColorStop(0, lblColor.getRgbaColor()); + grad.addColorStop(0.85, lblColor.getRgbaColor()); + grad.addColorStop(0.85, ptrColor.medium.getRgbaColor()); + grad.addColorStop(1, ptrColor.medium.getRgbaColor()); + ptrCtx.fillStyle = grad; + } else { + // TYPE14 + grad = ptrCtx.createLinearGradient(0.485981 * size, 0, 0.509345 * size, 0); + grad.addColorStop(0, ptrColor.veryDark.getRgbaColor()); + grad.addColorStop(0.5, ptrColor.light.getRgbaColor()); + grad.addColorStop(1, ptrColor.veryDark.getRgbaColor()); + ptrCtx.fillStyle = grad; + } + ptrCtx.fill(); + break; + + case 'type15': + // POINTER TYPE15 - Classic with crescent + case 'type16': + // POINTER TYPE16 - Classic without crescent + ptrCtx.beginPath(); + ptrCtx.moveTo(size * 0.509345, size * 0.457943); + ptrCtx.lineTo(size * 0.5015, size * 0.13); + ptrCtx.lineTo(size * 0.4985, size * 0.13); + ptrCtx.lineTo(size * 0.490654, size * 0.457943); + ptrCtx.bezierCurveTo(size * 0.490654, size * 0.457943, size * 0.490654, size * 0.457943, size * 0.490654, size * 0.457943); + ptrCtx.bezierCurveTo(size * 0.471962, size * 0.462616, size * 0.457943, size * 0.481308, size * 0.457943, size * 0.5); + ptrCtx.bezierCurveTo(size * 0.457943, size * 0.518691, size * 0.471962, size * 0.537383, size * 0.490654, size * 0.542056); + ptrCtx.bezierCurveTo(size * 0.490654, size * 0.542056, size * 0.490654, size * 0.542056, size * 0.490654, size * 0.542056); + if (ptrType.type === 'type15') { + ptrCtx.lineTo(size * 0.490654, size * 0.57); + ptrCtx.bezierCurveTo(size * 0.46, size * 0.58, size * 0.46, size * 0.62, size * 0.490654, size * 0.63); + ptrCtx.bezierCurveTo(size * 0.47, size * 0.62, size * 0.48, size * 0.59, size * 0.5, size * 0.59); + ptrCtx.bezierCurveTo(size * 0.53, size * 0.59, size * 0.52, size * 0.62, size * 0.509345, size * 0.63); + ptrCtx.bezierCurveTo(size * 0.54, size * 0.62, size * 0.54, size * 0.58, size * 0.509345, size * 0.57); + ptrCtx.lineTo(size * 0.509345, size * 0.57); + } else { + ptrCtx.lineTo(size * 0.490654, size * 0.621495); + ptrCtx.lineTo(size * 0.509345, size * 0.621495); + } + ptrCtx.lineTo(size * 0.509345, size * 0.542056); + ptrCtx.bezierCurveTo(size * 0.509345, size * 0.542056, size * 0.509345, size * 0.542056, size * 0.509345, size * 0.542056); + ptrCtx.bezierCurveTo(size * 0.528037, size * 0.537383, size * 0.542056, size * 0.518691, size * 0.542056, size * 0.5); + ptrCtx.bezierCurveTo(size * 0.542056, size * 0.481308, size * 0.528037, size * 0.462616, size * 0.509345, size * 0.457943); + ptrCtx.bezierCurveTo(size * 0.509345, size * 0.457943, size * 0.509345, size * 0.457943, size * 0.509345, size * 0.457943); + ptrCtx.closePath(); + if (ptrType.type === 'type15') { + grad = ptrCtx.createLinearGradient(0, 0, 0, size * 0.63); + } else { + grad = ptrCtx.createLinearGradient(0, 0, 0, size * 0.621495); + } + grad.addColorStop(0, ptrColor.medium.getRgbaColor()); + grad.addColorStop(0.388888, ptrColor.medium.getRgbaColor()); + grad.addColorStop(0.5, ptrColor.light.getRgbaColor()); + grad.addColorStop(0.611111, ptrColor.medium.getRgbaColor()); + grad.addColorStop(1, ptrColor.medium.getRgbaColor()); + ptrCtx.fillStyle = grad; + ptrCtx.strokeStyle = ptrColor.dark.getRgbaColor(); + ptrCtx.fill(); + ptrCtx.stroke(); + // Draw the rings + ptrCtx.beginPath(); + radius = size * 0.065420 / 2; + ptrCtx.arc(size * 0.5, size * 0.5, radius, 0, TWO_PI); + grad = ptrCtx.createLinearGradient(size * 0.5 - radius, size * 0.5 + radius, 0, size * 0.5 + radius); + grad.addColorStop(0, '#e6b35c'); + grad.addColorStop(0.01, '#e6b35c'); + grad.addColorStop(0.99, '#c48200'); + grad.addColorStop(1, '#c48200'); + ptrCtx.fillStyle = grad; + ptrCtx.closePath(); + ptrCtx.fill(); + ptrCtx.beginPath(); + radius = size * 0.046728 / 2; + ptrCtx.arc(size * 0.5, size * 0.5, radius, 0, TWO_PI); + grad = ptrCtx.createRadialGradient(size * 0.5, size * 0.5, 0, size * 0.5, size * 0.5, radius); + grad.addColorStop(0, '#c5c5c5'); + grad.addColorStop(0.19, '#c5c5c5'); + grad.addColorStop(0.22, '#000000'); + grad.addColorStop(0.8, '#000000'); + grad.addColorStop(0.99, '#707070'); + grad.addColorStop(1, '#707070'); + ptrCtx.fillStyle = grad; + ptrCtx.closePath(); + ptrCtx.fill(); + break; + + case 'type1': + /* falls through */ + default: + grad = ptrCtx.createLinearGradient(0, size * 0.471962, 0, size * 0.130841); + grad.addColorStop(0, ptrColor.veryDark.getRgbaColor()); + grad.addColorStop(0.3, ptrColor.medium.getRgbaColor()); + grad.addColorStop(0.59, ptrColor.medium.getRgbaColor()); + grad.addColorStop(1, ptrColor.veryDark.getRgbaColor()); + ptrCtx.fillStyle = grad; + ptrCtx.beginPath(); + ptrCtx.moveTo(size * 0.518691, size * 0.471962); + ptrCtx.bezierCurveTo(size * 0.514018, size * 0.457943, size * 0.509345, size * 0.415887, size * 0.509345, size * 0.401869); + ptrCtx.bezierCurveTo(size * 0.504672, size * 0.383177, size * 0.5, size * 0.130841, size * 0.5, size * 0.130841); + ptrCtx.bezierCurveTo(size * 0.5, size * 0.130841, size * 0.490654, size * 0.383177, size * 0.490654, size * 0.397196); + ptrCtx.bezierCurveTo(size * 0.490654, size * 0.415887, size * 0.485981, size * 0.457943, size * 0.481308, size * 0.471962); + ptrCtx.bezierCurveTo(size * 0.471962, size * 0.481308, size * 0.467289, size * 0.490654, size * 0.467289, size * 0.5); + ptrCtx.bezierCurveTo(size * 0.467289, size * 0.518691, size * 0.481308, size * 0.532710, size * 0.5, size * 0.532710); + ptrCtx.bezierCurveTo(size * 0.518691, size * 0.532710, size * 0.532710, size * 0.518691, size * 0.532710, size * 0.5); + ptrCtx.bezierCurveTo(size * 0.532710, size * 0.490654, size * 0.528037, size * 0.481308, size * 0.518691, size * 0.471962); + ptrCtx.closePath(); + ptrCtx.fill(); + break; + } + // cache buffer + drawPointerImage.cache[cacheKey] = ptrBuffer; + } + ctx.drawImage(drawPointerImage.cache[cacheKey], 0, 0); + return this; + }; + drawPointerImage.cache = {}; + + var drawRadialFrameImage = function (ctx, frameDesign, centerX, centerY, imageWidth, imageHeight) { + var radFBuffer, radFCtx, + grad, outerX, innerX, fractions, colors, + cacheKey = imageWidth.toString() + imageHeight + frameDesign.design; + + // check if we have already created and cached this buffer, if not create it + if (!drawRadialFrameImage.cache[cacheKey]) { + // Setup buffer + radFBuffer = createBuffer(imageWidth, imageHeight); + radFCtx = radFBuffer.getContext('2d'); + + // outer gray frame + radFCtx.fillStyle = '#848484'; + radFCtx.strokeStyle = 'rgba(132, 132, 132, 0.5)'; + radFCtx.beginPath(); + radFCtx.arc(centerX, centerY, imageWidth / 2, 0, TWO_PI, true); + radFCtx.closePath(); + radFCtx.fill(); + radFCtx.stroke(); + + radFCtx.beginPath(); + radFCtx.arc(centerX, centerY, imageWidth * 0.990654 / 2, 0, TWO_PI, true); + radFCtx.closePath(); + + // main gradient frame + switch (frameDesign.design) { + case 'metal': + grad = radFCtx.createLinearGradient(0, imageWidth * 0.004672, 0, imageHeight * 0.990654); + grad.addColorStop(0, '#fefefe'); + grad.addColorStop(0.07, 'rgb(210, 210, 210)'); + grad.addColorStop(0.12, 'rgb(179, 179, 179)'); + grad.addColorStop(1, 'rgb(213, 213, 213)'); + radFCtx.fillStyle = grad; + radFCtx.fill(); + break; + + case 'brass': + grad = radFCtx.createLinearGradient(0, imageWidth * 0.004672, 0, imageHeight * 0.990654); + grad.addColorStop(0, 'rgb(249, 243, 155)'); + grad.addColorStop(0.05, 'rgb(246, 226, 101)'); + grad.addColorStop(0.10, 'rgb(240, 225, 132)'); + grad.addColorStop(0.50, 'rgb(90, 57, 22)'); + grad.addColorStop(0.90, 'rgb(249, 237, 139)'); + grad.addColorStop(0.95, 'rgb(243, 226, 108)'); + grad.addColorStop(1, 'rgb(202, 182, 113)'); + radFCtx.fillStyle = grad; + radFCtx.fill(); + break; + + case 'steel': + grad = radFCtx.createLinearGradient(0, imageWidth * 0.004672, 0, imageHeight * 0.990654); + grad.addColorStop(0, 'rgb(231, 237, 237)'); + grad.addColorStop(0.05, 'rgb(189, 199, 198)'); + grad.addColorStop(0.10, 'rgb(192, 201, 200)'); + grad.addColorStop(0.50, 'rgb(23, 31, 33)'); + grad.addColorStop(0.90, 'rgb(196, 205, 204)'); + grad.addColorStop(0.95, 'rgb(194, 204, 203)'); + grad.addColorStop(1, 'rgb(189, 201, 199)'); + radFCtx.fillStyle = grad; + radFCtx.fill(); + break; + + case 'gold': + grad = radFCtx.createLinearGradient(0, imageWidth * 0.004672, 0, imageHeight * 0.990654); + grad.addColorStop(0, 'rgb(255, 255, 207)'); + grad.addColorStop(0.15, 'rgb(255, 237, 96)'); + grad.addColorStop(0.22, 'rgb(254, 199, 57)'); + grad.addColorStop(0.3, 'rgb(255, 249, 203)'); + grad.addColorStop(0.38, 'rgb(255, 199, 64)'); + grad.addColorStop(0.44, 'rgb(252, 194, 60)'); + grad.addColorStop(0.51, 'rgb(255, 204, 59)'); + grad.addColorStop(0.6, 'rgb(213, 134, 29)'); + grad.addColorStop(0.68, 'rgb(255, 201, 56)'); + grad.addColorStop(0.75, 'rgb(212, 135, 29)'); + grad.addColorStop(1, 'rgb(247, 238, 101)'); + radFCtx.fillStyle = grad; + radFCtx.fill(); + break; + + case 'anthracite': + grad = radFCtx.createLinearGradient(0, 0.004672 * imageHeight, 0, 0.995326 * imageHeight); + grad.addColorStop(0, 'rgb(118, 117, 135)'); + grad.addColorStop(0.06, 'rgb(74, 74, 82)'); + grad.addColorStop(0.12, 'rgb(50, 50, 54)'); + grad.addColorStop(1, 'rgb(79, 79, 87)'); + radFCtx.fillStyle = grad; + radFCtx.fill(); + break; + + case 'tiltedGray': + grad = radFCtx.createLinearGradient(0.233644 * imageWidth, 0.084112 * imageHeight, 0.81258 * imageWidth, 0.910919 * imageHeight); + grad.addColorStop(0, '#ffffff'); + grad.addColorStop(0.07, 'rgb(210, 210, 210)'); + grad.addColorStop(0.16, 'rgb(179, 179, 179)'); + grad.addColorStop(0.33, '#ffffff'); + grad.addColorStop(0.55, '#c5c5c5'); + grad.addColorStop(0.79, '#ffffff'); + grad.addColorStop(1, '#666666'); + radFCtx.fillStyle = grad; + radFCtx.fill(); + break; + + case 'tiltedBlack': + grad = radFCtx.createLinearGradient(0.228971 * imageWidth, 0.079439 * imageHeight, 0.802547 * imageWidth, 0.898591 * imageHeight); + grad.addColorStop(0, '#666666'); + grad.addColorStop(0.21, '#000000'); + grad.addColorStop(0.47, '#666666'); + grad.addColorStop(0.99, '#000000'); + grad.addColorStop(1, '#000000'); + radFCtx.fillStyle = grad; + radFCtx.fill(); + break; + + case 'glossyMetal': + grad = radFCtx.createRadialGradient(0.5 * imageWidth, 0.5 * imageHeight, 0, 0.5 * imageWidth, 0.5 * imageWidth, 0.5 * imageWidth); + grad.addColorStop(0, 'rgb(207, 207, 207)'); + grad.addColorStop(0.96, 'rgb(205, 204, 205)'); + grad.addColorStop(1, 'rgb(244, 244, 244)'); + radFCtx.fillStyle = grad; + radFCtx.fill(); + radFCtx.beginPath(); + radFCtx.arc(0.5 * imageWidth, 0.5 * imageHeight, 0.973962 * imageWidth / 2, 0, TWO_PI); + radFCtx.closePath(); + grad = radFCtx.createLinearGradient(0, imageHeight - 0.971962 * imageHeight, 0, 0.971962 * imageHeight); + grad.addColorStop(0, 'rgb(249, 249, 249)'); + grad.addColorStop(0.23, 'rgb(200, 195, 191)'); + grad.addColorStop(0.36, '#ffffff'); + grad.addColorStop(0.59, 'rgb(29, 29, 29)'); + grad.addColorStop(0.76, 'rgb(200, 194, 192)'); + grad.addColorStop(1, 'rgb(209, 209, 209)'); + radFCtx.fillStyle = grad; + radFCtx.fill(); + + radFCtx.beginPath(); + radFCtx.arc(0.5 * imageWidth, 0.5 * imageHeight, 0.869158 * imageWidth / 2, 0, TWO_PI); + radFCtx.closePath(); + radFCtx.fillStyle = '#f6f6f6'; + radFCtx.fill(); + + radFCtx.beginPath(); + radFCtx.arc(0.5 * imageWidth, 0.5 * imageHeight, 0.85 * imageWidth / 2, 0, TWO_PI); + radFCtx.closePath(); + radFCtx.fillStyle = '#333333'; + radFCtx.fill(); + break; + + case 'blackMetal': + fractions = [0, + 0.125, + 0.347222, + 0.5, + 0.680555, + 0.875, + 1]; + + colors = [ new RgbaColor(254, 254, 254, 1), + new RgbaColor(0, 0, 0, 1), + new RgbaColor(153, 153, 153, 1), + new RgbaColor(0, 0, 0, 1), + new RgbaColor(153, 153, 153, 1), + new RgbaColor(0, 0, 0, 1), + new RgbaColor(254, 254, 254, 1)]; + + radFCtx.save(); + radFCtx.arc(centerX, centerY, imageWidth * 0.990654 / 2, 0, TWO_PI, true); + radFCtx.clip(); + outerX = imageWidth * 0.495327; + innerX = imageWidth * 0.420560; + grad = new ConicalGradient(fractions, colors); + grad.fillCircle(radFCtx, centerX, centerY, innerX, outerX); + // fade outer edge + radFCtx.strokeStyle = '#848484'; + radFCtx.strokeStyle = 'rgba(132, 132, 132, 0.8)'; + radFCtx.beginPath(); + radFCtx.lineWidth = imageWidth / 90; + radFCtx.arc(centerX, centerY, imageWidth / 2, 0, TWO_PI, true); + radFCtx.closePath(); + radFCtx.stroke(); + radFCtx.restore(); + break; + + case 'shinyMetal': + fractions = [0, + 0.125, + 0.25, + 0.347222, + 0.5, + 0.652777, + 0.75, + 0.875, + 1]; + + colors = [ new RgbaColor(254, 254, 254, 1), + new RgbaColor(210, 210, 210, 1), + new RgbaColor(179, 179, 179, 1), + new RgbaColor(238, 238, 238, 1), + new RgbaColor(160, 160, 160, 1), + new RgbaColor(238, 238, 238, 1), + new RgbaColor(179, 179, 179, 1), + new RgbaColor(210, 210, 210, 1), + new RgbaColor(254, 254, 254, 1)]; + + radFCtx.save(); + radFCtx.arc(centerX, centerY, imageWidth * 0.990654 / 2, 0, TWO_PI, true); + radFCtx.clip(); + outerX = imageWidth * 0.495327; + innerX = imageWidth * 0.420560; + grad = new ConicalGradient(fractions, colors); + grad.fillCircle(radFCtx, centerX, centerY, innerX, outerX); + // fade outer edge + radFCtx.strokeStyle = '#848484'; + radFCtx.strokeStyle = 'rgba(132, 132, 132, 0.8)'; + radFCtx.beginPath(); + radFCtx.lineWidth = imageWidth / 90; + radFCtx.arc(centerX, centerY, imageWidth / 2, 0, TWO_PI, true); + radFCtx.closePath(); + radFCtx.stroke(); + radFCtx.restore(); + break; + + case 'chrome': + fractions = [0, + 0.09, + 0.12, + 0.16, + 0.25, + 0.29, + 0.33, + 0.38, + 0.48, + 0.52, + 0.63, + 0.68, + 0.8, + 0.83, + 0.87, + 0.97, + 1]; + + colors = [ new RgbaColor(255, 255, 255, 1), + new RgbaColor(255, 255, 255, 1), + new RgbaColor(136, 136, 138, 1), + new RgbaColor(164, 185, 190, 1), + new RgbaColor(158, 179, 182, 1), + new RgbaColor(112, 112, 112, 1), + new RgbaColor(221, 227, 227, 1), + new RgbaColor(155, 176, 179, 1), + new RgbaColor(156, 176, 177, 1), + new RgbaColor(254, 255, 255, 1), + new RgbaColor(255, 255, 255, 1), + new RgbaColor(156, 180, 180, 1), + new RgbaColor(198, 209, 211, 1), + new RgbaColor(246, 248, 247, 1), + new RgbaColor(204, 216, 216, 1), + new RgbaColor(164, 188, 190, 1), + new RgbaColor(255, 255, 255, 1)]; + + radFCtx.save(); + radFCtx.arc(centerX, centerY, imageWidth * 0.990654 / 2, 0, TWO_PI, true); + radFCtx.clip(); + outerX = imageWidth * 0.495327; + innerX = imageWidth * 0.420560; + grad = new ConicalGradient(fractions, colors); + grad.fillCircle(radFCtx, centerX, centerY, innerX, outerX); + // fade outer edge + radFCtx.strokeStyle = '#848484'; + radFCtx.strokeStyle = 'rgba(132, 132, 132, 0.8)'; + radFCtx.beginPath(); + radFCtx.lineWidth = imageWidth / 90; + radFCtx.arc(centerX, centerY, imageWidth / 2, 0, TWO_PI, true); + radFCtx.closePath(); + radFCtx.stroke(); + radFCtx.restore(); + + break; + } + + // inner bright frame + radFCtx.fillStyle = 'rgb(191, 191, 191)'; + radFCtx.beginPath(); + radFCtx.arc(centerX, centerY, imageWidth * 0.841121 / 2, 0, TWO_PI, true); + radFCtx.closePath(); + radFCtx.fill(); + + // clip out center so it is transparent if the background is not visible + radFCtx.globalCompositeOperation = 'destination-out'; + // Background ellipse + radFCtx.beginPath(); + radFCtx.arc(centerX, centerY, imageWidth * 0.83 / 2, 0, TWO_PI, true); + radFCtx.closePath(); + radFCtx.fill(); + + // cache the buffer + drawRadialFrameImage.cache[cacheKey] = radFBuffer; + } + ctx.drawImage(drawRadialFrameImage.cache[cacheKey], 0, 0); + return this; + }; + drawRadialFrameImage.cache = {}; + + var drawRadialBackgroundImage = function (ctx, backgroundColor, centerX, centerY, imageWidth, imageHeight) { + var radBBuffer, radBCtx, + grad, fractions, colors, + backgroundOffsetX = imageWidth * 0.831775 / 2, + mono, textureColor, texture, + radius, turnRadius, stepSize, + end, i, + cacheKey = imageWidth.toString() + imageHeight + backgroundColor.name; + + // check if we have already created and cached this buffer, if not create it + if (!drawRadialBackgroundImage.cache[cacheKey]) { + // Setup buffer + radBBuffer = createBuffer(imageWidth, imageHeight); + radBCtx = radBBuffer.getContext('2d'); + + // Background ellipse + radBCtx.beginPath(); + radBCtx.arc(centerX, centerY, backgroundOffsetX, 0, TWO_PI, true); + radBCtx.closePath(); + + // If the backgroundColor is a texture fill it with the texture instead of the gradient + if (backgroundColor.name === 'CARBON' || backgroundColor.name === 'PUNCHED_SHEET' || + backgroundColor.name === 'BRUSHED_METAL' || backgroundColor.name === 'BRUSHED_STAINLESS') { + + if (backgroundColor.name === 'CARBON') { + radBCtx.fillStyle = radBCtx.createPattern(carbonBuffer, 'repeat'); + radBCtx.fill(); + } + + if (backgroundColor.name === 'PUNCHED_SHEET') { + radBCtx.fillStyle = radBCtx.createPattern(punchedSheetBuffer, 'repeat'); + radBCtx.fill(); + } + + // Add another inner shadow to make the look more realistic + grad = radBCtx.createLinearGradient(backgroundOffsetX, 0, imageWidth - backgroundOffsetX, 0); + grad.addColorStop(0, 'rgba(0, 0, 0, 0.25)'); + grad.addColorStop(0.5, 'rgba(0, 0, 0, 0)'); + grad.addColorStop(1, 'rgba(0, 0, 0, 0.25)'); + radBCtx.fillStyle = grad; + radBCtx.beginPath(); + radBCtx.arc(centerX, centerY, backgroundOffsetX, 0, TWO_PI, true); + radBCtx.closePath(); + radBCtx.fill(); + + if (backgroundColor.name === 'BRUSHED_METAL' || backgroundColor.name === 'BRUSHED_STAINLESS') { + mono = (backgroundColor.name === 'BRUSHED_METAL' ? true : false); + textureColor = parseInt(backgroundColor.gradientStop.getHexColor().substr(-6), 16); + texture = brushedMetalTexture(textureColor, 5, 0.1, mono, 0.5); + radBCtx.fillStyle = radBCtx.createPattern(texture.fill(0, 0, imageWidth, imageHeight), 'no-repeat'); + radBCtx.fill(); + } + } else if (backgroundColor.name === 'STAINLESS' || backgroundColor.name === 'TURNED') { + // Define the fractions of the conical gradient paint + fractions = [0, + 0.03, + 0.10, + 0.14, + 0.24, + 0.33, + 0.38, + 0.5, + 0.62, + 0.67, + 0.76, + 0.81, + 0.85, + 0.97, + 1]; + + // Define the colors of the conical gradient paint + colors = [new RgbaColor('#FDFDFD'), + new RgbaColor('#FDFDFD'), + new RgbaColor('#B2B2B4'), + new RgbaColor('#ACACAE'), + new RgbaColor('#FDFDFD'), + new RgbaColor('#8E8E8E'), + new RgbaColor('#8E8E8E'), + new RgbaColor('#FDFDFD'), + new RgbaColor('#8E8E8E'), + new RgbaColor('#8E8E8E'), + new RgbaColor('#FDFDFD'), + new RgbaColor('#ACACAE'), + new RgbaColor('#B2B2B4'), + new RgbaColor('#FDFDFD'), + new RgbaColor('#FDFDFD')]; + + grad = new ConicalGradient(fractions, colors); + grad.fillCircle(radBCtx, centerX, centerY, 0, backgroundOffsetX); + + if (backgroundColor.name === 'TURNED') { + // Define the turning radius + radius = backgroundOffsetX; + turnRadius = radius * 0.55; + // Step size proporational to radius + stepSize = RAD_FACTOR * (500 / radius); + // Save before we start + radBCtx.save(); + // restrict the turnings to the desired area + radBCtx.beginPath(); + radBCtx.arc(centerX, centerY, radius, 0, TWO_PI); + radBCtx.closePath(); + radBCtx.clip(); + // set the style for the turnings + radBCtx.lineWidth = 0.5; + end = TWO_PI - stepSize * 0.3; + // Step the engine round'n'round + for (i = 0 ; i < end; i += stepSize) { + // draw a 'turn' + radBCtx.strokeStyle = 'rgba(240, 240, 255, 0.25)'; + radBCtx.beginPath(); + radBCtx.arc(centerX + turnRadius, centerY, turnRadius, 0, TWO_PI); + radBCtx.stroke(); + // rotate the 'piece' a fraction to draw 'shadow' + radBCtx.translate(centerX, centerY); + radBCtx.rotate(stepSize * 0.3); + radBCtx.translate(-centerX, -centerY); + // draw a 'turn' + radBCtx.strokeStyle = 'rgba(25, 10, 10, 0.1)'; + radBCtx.beginPath(); + radBCtx.arc(centerX + turnRadius, centerY, turnRadius, 0, TWO_PI); + radBCtx.stroke(); + // now rotate on to the next 'scribe' position minus the 'fraction' + radBCtx.translate(centerX, centerY); + radBCtx.rotate(stepSize - stepSize * 0.3); + radBCtx.translate(-centerX, -centerY); + } + // Restore canvas now we are done + radBCtx.restore(); + } + } else { + grad = radBCtx.createLinearGradient(0, imageWidth * 0.084112, 0, backgroundOffsetX * 2); + grad.addColorStop(0, backgroundColor.gradientStart.getRgbaColor()); + grad.addColorStop(0.4, backgroundColor.gradientFraction.getRgbaColor()); + grad.addColorStop(1, backgroundColor.gradientStop.getRgbaColor()); + radBCtx.fillStyle = grad; + radBCtx.fill(); + } + // Inner shadow + grad = radBCtx.createRadialGradient(centerX, centerY, 0, centerX, centerY, backgroundOffsetX); + grad.addColorStop(0, 'rgba(0, 0, 0, 0)'); + grad.addColorStop(0.7, 'rgba(0, 0, 0, 0)'); + grad.addColorStop(0.71, 'rgba(0, 0, 0, 0)'); + grad.addColorStop(0.86, 'rgba(0, 0, 0, 0.03)'); + grad.addColorStop(0.92, 'rgba(0, 0, 0, 0.07)'); + grad.addColorStop(0.97, 'rgba(0, 0, 0, 0.15)'); + grad.addColorStop(1, 'rgba(0, 0, 0, 0.3)'); + radBCtx.fillStyle = grad; + + radBCtx.beginPath(); + radBCtx.arc(centerX, centerY, backgroundOffsetX, 0, TWO_PI, true); + radBCtx.closePath(); + radBCtx.fill(); + + // cache the buffer + drawRadialBackgroundImage.cache[cacheKey] = radBBuffer; + } + ctx.drawImage(drawRadialBackgroundImage.cache[cacheKey], 0, 0); + return this; + }; + drawRadialBackgroundImage.cache = {}; + + var drawRadialCustomImage = function (ctx, img, centerX, centerY, imageWidth, imageHeight) { + var drawWidth = imageWidth * 0.831775, + drawHeight = imageHeight * 0.831775, + x = (imageWidth - drawWidth) / 2, + y = (imageHeight - drawHeight) / 2; + + if (img !== null && img.height > 0 && img.width > 0) { + ctx.save(); + // Set the clipping area + ctx.beginPath(); + ctx.arc(centerX, centerY, imageWidth * 0.831775 / 2, 0, TWO_PI, true); + ctx.clip(); + // Add the image + ctx.drawImage(img, x, y, drawWidth, drawHeight); + ctx.restore(); + } + return this; + }; + + var drawRadialForegroundImage = function (ctx, foregroundType, imageWidth, imageHeight, withCenterKnob, knob, style, gaugeType, orientation) { + var radFgBuffer, radFgCtx, + knobSize = Math.ceil(imageHeight * 0.084112), + knobX = imageWidth * 0.5 - knobSize / 2, + knobY = imageHeight * 0.5 - knobSize / 2, + shadowOffset = imageWidth * 0.008, + gradHighlight, gradHighlight2, + cacheKey = foregroundType.type + imageWidth + imageHeight + withCenterKnob + (knob !== undefined ? knob.type : '-') + + (style !== undefined ? style.style : '-') + (orientation !== undefined ? orientation.type : '-'); + + // check if we have already created and cached this buffer, if so return it and exit + if (!drawRadialForegroundImage.cache[cacheKey]) { + // Setup buffer + radFgBuffer = createBuffer(imageWidth, imageHeight); + radFgCtx = radFgBuffer.getContext('2d'); + + // center post + if (withCenterKnob) { + // Set the pointer shadow params + radFgCtx.shadowColor = 'rgba(0, 0, 0, 0.8)'; + radFgCtx.shadowOffsetX = radFgCtx.shadowOffsetY = shadowOffset; + radFgCtx.shadowBlur = shadowOffset * 2; + + if (gaugeType === steelseries.GaugeType.TYPE5) { + if (steelseries.Orientation.WEST === orientation) { + knobX = imageWidth * 0.733644 - knobSize / 2; + radFgCtx.drawImage(createKnobImage(knobSize, knob, style), knobX, knobY); + } else if (steelseries.Orientation.EAST === orientation) { + knobX = imageWidth * (1 - 0.733644) - knobSize / 2; + radFgCtx.drawImage(createKnobImage(knobSize, knob, style), knobX, knobY); + } else { + knobY = imageHeight * 0.733644 - knobSize / 2; + radFgCtx.drawImage(createKnobImage(knobSize, knob, style), knobX, imageHeight * 0.6857); + } + } else { + radFgCtx.drawImage(createKnobImage(knobSize, knob, style), knobX, knobY); + } + // Undo shadow drawing + radFgCtx.shadowOffsetX = radFgCtx.shadowOffsetY = 0; + radFgCtx.shadowBlur = 0; + } + + // highlight + switch (foregroundType.type) { + case 'type2': + radFgCtx.beginPath(); + radFgCtx.moveTo(imageWidth * 0.135514, imageHeight * 0.696261); + radFgCtx.bezierCurveTo(imageWidth * 0.214953, imageHeight * 0.588785, imageWidth * 0.317757, imageHeight * 0.5, imageWidth * 0.462616, imageHeight * 0.425233); + radFgCtx.bezierCurveTo(imageWidth * 0.612149, imageHeight * 0.345794, imageWidth * 0.733644, imageHeight * 0.317757, imageWidth * 0.873831, imageHeight * 0.322429); + radFgCtx.bezierCurveTo(imageWidth * 0.766355, imageHeight * 0.112149, imageWidth * 0.528037, imageHeight * 0.023364, imageWidth * 0.313084, imageHeight * 0.130841); + radFgCtx.bezierCurveTo(imageWidth * 0.098130, imageHeight * 0.238317, imageWidth * 0.028037, imageHeight * 0.485981, imageWidth * 0.135514, imageHeight * 0.696261); + radFgCtx.closePath(); + gradHighlight = radFgCtx.createLinearGradient(0.313084 * imageWidth, 0.135514 * imageHeight, 0.495528 * imageWidth, 0.493582 * imageHeight); + gradHighlight.addColorStop(0, 'rgba(255, 255, 255, 0.275)'); + gradHighlight.addColorStop(1, 'rgba(255, 255, 255, 0.015)'); + break; + + case 'type3': + radFgCtx.beginPath(); + radFgCtx.moveTo(imageWidth * 0.084112, imageHeight * 0.509345); + radFgCtx.bezierCurveTo(imageWidth * 0.210280, imageHeight * 0.556074, imageWidth * 0.462616, imageHeight * 0.560747, imageWidth * 0.5, imageHeight * 0.560747); + radFgCtx.bezierCurveTo(imageWidth * 0.537383, imageHeight * 0.560747, imageWidth * 0.794392, imageHeight * 0.560747, imageWidth * 0.915887, imageHeight * 0.509345); + radFgCtx.bezierCurveTo(imageWidth * 0.915887, imageHeight * 0.275700, imageWidth * 0.738317, imageHeight * 0.084112, imageWidth * 0.5, imageHeight * 0.084112); + radFgCtx.bezierCurveTo(imageWidth * 0.261682, imageHeight * 0.084112, imageWidth * 0.084112, imageHeight * 0.275700, imageWidth * 0.084112, imageHeight * 0.509345); + radFgCtx.closePath(); + gradHighlight = radFgCtx.createLinearGradient(0, 0.093457 * imageHeight, 0, 0.556073 * imageHeight); + gradHighlight.addColorStop(0, 'rgba(255, 255, 255, 0.275)'); + gradHighlight.addColorStop(1, 'rgba(255, 255, 255, 0.015)'); + break; + + case 'type4': + radFgCtx.beginPath(); + radFgCtx.moveTo(imageWidth * 0.677570, imageHeight * 0.242990); + radFgCtx.bezierCurveTo(imageWidth * 0.771028, imageHeight * 0.308411, imageWidth * 0.822429, imageHeight * 0.411214, imageWidth * 0.813084, imageHeight * 0.528037); + radFgCtx.bezierCurveTo(imageWidth * 0.799065, imageHeight * 0.654205, imageWidth * 0.719626, imageHeight * 0.757009, imageWidth * 0.593457, imageHeight * 0.799065); + radFgCtx.bezierCurveTo(imageWidth * 0.485981, imageHeight * 0.831775, imageWidth * 0.369158, imageHeight * 0.808411, imageWidth * 0.285046, imageHeight * 0.728971); + radFgCtx.bezierCurveTo(imageWidth * 0.275700, imageHeight * 0.719626, imageWidth * 0.252336, imageHeight * 0.714953, imageWidth * 0.233644, imageHeight * 0.728971); + radFgCtx.bezierCurveTo(imageWidth * 0.214953, imageHeight * 0.747663, imageWidth * 0.219626, imageHeight * 0.771028, imageWidth * 0.228971, imageHeight * 0.775700); + radFgCtx.bezierCurveTo(imageWidth * 0.331775, imageHeight * 0.878504, imageWidth * 0.476635, imageHeight * 0.915887, imageWidth * 0.616822, imageHeight * 0.869158); + radFgCtx.bezierCurveTo(imageWidth * 0.771028, imageHeight * 0.822429, imageWidth * 0.873831, imageHeight * 0.691588, imageWidth * 0.887850, imageHeight * 0.532710); + radFgCtx.bezierCurveTo(imageWidth * 0.897196, imageHeight * 0.387850, imageWidth * 0.836448, imageHeight * 0.257009, imageWidth * 0.719626, imageHeight * 0.182242); + radFgCtx.bezierCurveTo(imageWidth * 0.705607, imageHeight * 0.172897, imageWidth * 0.682242, imageHeight * 0.163551, imageWidth * 0.663551, imageHeight * 0.186915); + radFgCtx.bezierCurveTo(imageWidth * 0.654205, imageHeight * 0.205607, imageWidth * 0.668224, imageHeight * 0.238317, imageWidth * 0.677570, imageHeight * 0.242990); + radFgCtx.closePath(); + gradHighlight = radFgCtx.createRadialGradient((0.5) * imageWidth, ((0.5) * imageHeight), 0, ((0.5) * imageWidth), ((0.5) * imageHeight), 0.387850 * imageWidth); + gradHighlight.addColorStop(0, 'rgba(255, 255, 255, 0)'); + gradHighlight.addColorStop(0.82, 'rgba(255, 255, 255, 0)'); + gradHighlight.addColorStop(0.83, 'rgba(255, 255, 255, 0)'); + gradHighlight.addColorStop(1, 'rgba(255, 255, 255, 0.15)'); + + radFgCtx.beginPath(); + radFgCtx.moveTo(imageWidth * 0.261682, imageHeight * 0.224299); + radFgCtx.bezierCurveTo(imageWidth * 0.285046, imageHeight * 0.238317, imageWidth * 0.252336, imageHeight * 0.285046, imageWidth * 0.242990, imageHeight * 0.317757); + radFgCtx.bezierCurveTo(imageWidth * 0.242990, imageHeight * 0.350467, imageWidth * 0.271028, imageHeight * 0.383177, imageWidth * 0.271028, imageHeight * 0.397196); + radFgCtx.bezierCurveTo(imageWidth * 0.275700, imageHeight * 0.415887, imageWidth * 0.261682, imageHeight * 0.457943, imageWidth * 0.238317, imageHeight * 0.509345); + radFgCtx.bezierCurveTo(imageWidth * 0.224299, imageHeight * 0.542056, imageWidth * 0.177570, imageHeight * 0.612149, imageWidth * 0.158878, imageHeight * 0.612149); + radFgCtx.bezierCurveTo(imageWidth * 0.144859, imageHeight * 0.612149, imageWidth * 0.088785, imageHeight * 0.546728, imageWidth * 0.130841, imageHeight * 0.369158); + radFgCtx.bezierCurveTo(imageWidth * 0.140186, imageHeight * 0.336448, imageWidth * 0.214953, imageHeight * 0.200934, imageWidth * 0.261682, imageHeight * 0.224299); + radFgCtx.closePath(); + gradHighlight2 = radFgCtx.createLinearGradient(0.130841 * imageWidth, 0.369158 * imageHeight, 0.273839 * imageWidth, 0.412877 * imageHeight); + gradHighlight2.addColorStop(0, 'rgba(255, 255, 255, 0.275)'); + gradHighlight2.addColorStop(1, 'rgba(255, 255, 255, 0.015)'); + radFgCtx.fillStyle = gradHighlight2; + radFgCtx.fill(); + break; + + case 'type5': + radFgCtx.beginPath(); + radFgCtx.moveTo(imageWidth * 0.084112, imageHeight * 0.5); + radFgCtx.bezierCurveTo(imageWidth * 0.084112, imageHeight * 0.271028, imageWidth * 0.271028, imageHeight * 0.084112, imageWidth * 0.5, imageHeight * 0.084112); + radFgCtx.bezierCurveTo(imageWidth * 0.700934, imageHeight * 0.084112, imageWidth * 0.864485, imageHeight * 0.224299, imageWidth * 0.906542, imageHeight * 0.411214); + radFgCtx.bezierCurveTo(imageWidth * 0.911214, imageHeight * 0.439252, imageWidth * 0.911214, imageHeight * 0.518691, imageWidth * 0.845794, imageHeight * 0.537383); + radFgCtx.bezierCurveTo(imageWidth * 0.794392, imageHeight * 0.546728, imageWidth * 0.551401, imageHeight * 0.411214, imageWidth * 0.392523, imageHeight * 0.457943); + radFgCtx.bezierCurveTo(imageWidth * 0.168224, imageHeight * 0.509345, imageWidth * 0.135514, imageHeight * 0.775700, imageWidth * 0.093457, imageHeight * 0.593457); + radFgCtx.bezierCurveTo(imageWidth * 0.088785, imageHeight * 0.560747, imageWidth * 0.084112, imageHeight * 0.532710, imageWidth * 0.084112, imageHeight * 0.5); + radFgCtx.closePath(); + gradHighlight = radFgCtx.createLinearGradient(0, 0.084112 * imageHeight, 0, 0.644859 * imageHeight); + gradHighlight.addColorStop(0, 'rgba(255, 255, 255, 0.275)'); + gradHighlight.addColorStop(1, 'rgba(255, 255, 255, 0.015)'); + break; + + case 'type1': + /* falls through */ + default: + radFgCtx.beginPath(); + radFgCtx.moveTo(imageWidth * 0.084112, imageHeight * 0.509345); + radFgCtx.bezierCurveTo(imageWidth * 0.205607, imageHeight * 0.448598, imageWidth * 0.336448, imageHeight * 0.415887, imageWidth * 0.5, imageHeight * 0.415887); + radFgCtx.bezierCurveTo(imageWidth * 0.672897, imageHeight * 0.415887, imageWidth * 0.789719, imageHeight * 0.443925, imageWidth * 0.915887, imageHeight * 0.509345); + radFgCtx.bezierCurveTo(imageWidth * 0.915887, imageHeight * 0.275700, imageWidth * 0.738317, imageHeight * 0.084112, imageWidth * 0.5, imageHeight * 0.084112); + radFgCtx.bezierCurveTo(imageWidth * 0.261682, imageHeight * 0.084112, imageWidth * 0.084112, imageHeight * 0.275700, imageWidth * 0.084112, imageHeight * 0.509345); + radFgCtx.closePath(); + gradHighlight = radFgCtx.createLinearGradient(0, 0.088785 * imageHeight, 0, 0.490654 * imageHeight); + gradHighlight.addColorStop(0, 'rgba(255, 255, 255, 0.275)'); + gradHighlight.addColorStop(1, 'rgba(255, 255, 255, 0.015)'); + break; + } + radFgCtx.fillStyle = gradHighlight; + radFgCtx.fill(); + + // cache the buffer + drawRadialForegroundImage.cache[cacheKey] = radFgBuffer; + } + ctx.drawImage(drawRadialForegroundImage.cache[cacheKey], 0, 0); + return this; + }; + drawRadialForegroundImage.cache = {}; + + var createKnobImage = function (size, knob, style) { + var knobBuffer, knobCtx, + maxPostCenterX = size / 2, + maxPostCenterY = size / 2, + grad, + cacheKey = size.toString() + knob.type + style.style; + + // check if we have already created and cached this buffer, if not create it + if (!createKnobImage.cache[cacheKey]) { + knobBuffer = createBuffer(size * 1.18889, size * 1.18889); + knobCtx = knobBuffer.getContext('2d'); + + switch (knob.type) { + case 'metalKnob': + // METALKNOB_FRAME + knobCtx.beginPath(); + knobCtx.moveTo(0, size * 0.5); + knobCtx.bezierCurveTo(0, size * 0.222222, size * 0.222222, 0, size * 0.5, 0); + knobCtx.bezierCurveTo(size * 0.777777, 0, size, size * 0.222222, size, size * 0.5); + knobCtx.bezierCurveTo(size, size * 0.777777, size * 0.777777, size, size * 0.5, size); + knobCtx.bezierCurveTo(size * 0.222222, size, 0, size * 0.777777, 0, size * 0.5); + knobCtx.closePath(); + grad = knobCtx.createLinearGradient(0, 0, 0, size); + grad.addColorStop(0, 'rgb(92, 95, 101)'); + grad.addColorStop(0.47, 'rgb(46, 49, 53)'); + grad.addColorStop(1, 'rgb(22, 23, 26)'); + knobCtx.fillStyle = grad; + knobCtx.fill(); + + // METALKNOB_MAIN + knobCtx.beginPath(); + knobCtx.moveTo(size * 0.055555, size * 0.5); + knobCtx.bezierCurveTo(size * 0.055555, size * 0.277777, size * 0.277777, size * 0.055555, size * 0.5, size * 0.055555); + knobCtx.bezierCurveTo(size * 0.722222, size * 0.055555, size * 0.944444, size * 0.277777, size * 0.944444, size * 0.5); + knobCtx.bezierCurveTo(size * 0.944444, size * 0.722222, size * 0.722222, size * 0.944444, size * 0.5, size * 0.944444); + knobCtx.bezierCurveTo(size * 0.277777, size * 0.944444, size * 0.055555, size * 0.722222, size * 0.055555, size * 0.5); + knobCtx.closePath(); + grad = knobCtx.createLinearGradient(0, 0.055555 * size, 0, 0.944443 * size); + switch (style.style) { + case 'black': + grad.addColorStop(0, 'rgb(43, 42, 47)'); + grad.addColorStop(1, 'rgb(26, 27, 32)'); + break; + + case 'brass': + grad.addColorStop(0, 'rgb(150, 110, 54)'); + grad.addColorStop(1, 'rgb(124, 95, 61)'); + break; + + case 'silver': + /* falls through */ + default: + grad.addColorStop(0, 'rgb(204, 204, 204)'); + grad.addColorStop(1, 'rgb(87, 92, 98)'); + break; + } + knobCtx.fillStyle = grad; + knobCtx.fill(); + + // METALKNOB_LOWERHL + knobCtx.beginPath(); + knobCtx.moveTo(size * 0.777777, size * 0.833333); + knobCtx.bezierCurveTo(size * 0.722222, size * 0.722222, size * 0.611111, size * 0.666666, size * 0.5, size * 0.666666); + knobCtx.bezierCurveTo(size * 0.388888, size * 0.666666, size * 0.277777, size * 0.722222, size * 0.222222, size * 0.833333); + knobCtx.bezierCurveTo(size * 0.277777, size * 0.888888, size * 0.388888, size * 0.944444, size * 0.5, size * 0.944444); + knobCtx.bezierCurveTo(size * 0.611111, size * 0.944444, size * 0.722222, size * 0.888888, size * 0.777777, size * 0.833333); + knobCtx.closePath(); + grad = knobCtx.createRadialGradient((0.555555) * size, ((0.944444) * size), 0, ((0.555555) * size), ((0.944444) * size), 0.388888 * size); + grad.addColorStop(0, 'rgba(255, 255, 255, 0.6)'); + grad.addColorStop(1, 'rgba(255, 255, 255, 0)'); + knobCtx.fillStyle = grad; + knobCtx.fill(); + + // METALKNOB_UPPERHL + knobCtx.beginPath(); + knobCtx.moveTo(size * 0.944444, size * 0.277777); + knobCtx.bezierCurveTo(size * 0.833333, size * 0.111111, size * 0.666666, 0, size * 0.5, 0); + knobCtx.bezierCurveTo(size * 0.333333, 0, size * 0.166666, size * 0.111111, size * 0.055555, size * 0.277777); + knobCtx.bezierCurveTo(size * 0.166666, size * 0.333333, size * 0.333333, size * 0.388888, size * 0.5, size * 0.388888); + knobCtx.bezierCurveTo(size * 0.666666, size * 0.388888, size * 0.833333, size * 0.333333, size * 0.944444, size * 0.277777); + knobCtx.closePath(); + grad = knobCtx.createRadialGradient(0.5 * size, 0, 0, ((0.5) * size), 0, 0.583333 * size); + grad.addColorStop(0, 'rgba(255, 255, 255, 0.749019)'); + grad.addColorStop(1, 'rgba(255, 255, 255, 0)'); + knobCtx.fillStyle = grad; + knobCtx.fill(); + + // METALKNOB_INNERFRAME + knobCtx.beginPath(); + knobCtx.moveTo(size * 0.277777, size * 0.555555); + knobCtx.bezierCurveTo(size * 0.277777, size * 0.388888, size * 0.388888, size * 0.277777, size * 0.5, size * 0.277777); + knobCtx.bezierCurveTo(size * 0.611111, size * 0.277777, size * 0.777777, size * 0.388888, size * 0.777777, size * 0.555555); + knobCtx.bezierCurveTo(size * 0.777777, size * 0.666666, size * 0.611111, size * 0.777777, size * 0.5, size * 0.777777); + knobCtx.bezierCurveTo(size * 0.388888, size * 0.777777, size * 0.277777, size * 0.666666, size * 0.277777, size * 0.555555); + knobCtx.closePath(); + grad = knobCtx.createLinearGradient(0, 0.277777 * size, 0, 0.722221 * size); + grad.addColorStop(0, '#000000'); + grad.addColorStop(1, 'rgb(204, 204, 204)'); + knobCtx.fillStyle = grad; + knobCtx.fill(); + + // METALKNOB_INNERBACKGROUND + knobCtx.beginPath(); + knobCtx.moveTo(size * 0.333333, size * 0.555555); + knobCtx.bezierCurveTo(size * 0.333333, size * 0.444444, size * 0.388888, size * 0.333333, size * 0.5, size * 0.333333); + knobCtx.bezierCurveTo(size * 0.611111, size * 0.333333, size * 0.722222, size * 0.444444, size * 0.722222, size * 0.555555); + knobCtx.bezierCurveTo(size * 0.722222, size * 0.611111, size * 0.611111, size * 0.722222, size * 0.5, size * 0.722222); + knobCtx.bezierCurveTo(size * 0.388888, size * 0.722222, size * 0.333333, size * 0.611111, size * 0.333333, size * 0.555555); + knobCtx.closePath(); + grad = knobCtx.createLinearGradient(0, 0.333333 * size, 0, 0.666666 * size); + grad.addColorStop(0, 'rgb(10, 9, 1)'); + grad.addColorStop(1, 'rgb(42, 41, 37)'); + knobCtx.fillStyle = grad; + knobCtx.fill(); + break; + + case 'standardKnob': + grad = knobCtx.createLinearGradient(0, 0, 0, size); + grad.addColorStop(0, 'rgb(180, 180, 180)'); + grad.addColorStop(0.46, 'rgb(63, 63, 63)'); + grad.addColorStop(1, 'rgb(40, 40, 40)'); + knobCtx.fillStyle = grad; + knobCtx.beginPath(); + knobCtx.arc(maxPostCenterX, maxPostCenterY, size / 2, 0, TWO_PI, true); + knobCtx.closePath(); + knobCtx.fill(); + grad = knobCtx.createLinearGradient(0, size - size * 0.77, 0, size - size * 0.77 + size * 0.77); + switch (style.style) { + case 'black': + grad.addColorStop(0, 'rgb(191, 191, 191)'); + grad.addColorStop(0.5, 'rgb(45, 44, 49)'); + grad.addColorStop(1, 'rgb(125, 126, 128)'); + break; + + case 'brass': + grad.addColorStop(0, 'rgb(223, 208, 174)'); + grad.addColorStop(0.5, 'rgb(123, 95, 63)'); + grad.addColorStop(1, 'rgb(207, 190, 157)'); + break; + + case 'silver': + /* falls through */ + default: + grad.addColorStop(0, 'rgb(215, 215, 215)'); + grad.addColorStop(0.5, 'rgb(116, 116, 116)'); + grad.addColorStop(1, 'rgb(215, 215, 215)'); + break; + } + knobCtx.fillStyle = grad; + knobCtx.beginPath(); + knobCtx.arc(maxPostCenterX, maxPostCenterY, size * 0.77 / 2, 0, TWO_PI, true); + knobCtx.closePath(); + knobCtx.fill(); + + grad = knobCtx.createRadialGradient(maxPostCenterX, maxPostCenterY, 0, maxPostCenterX, maxPostCenterY, size * 0.77 / 2); + grad.addColorStop(0, 'rgba(0, 0, 0, 0)'); + grad.addColorStop(0.75, 'rgba(0, 0, 0, 0)'); + grad.addColorStop(0.76, 'rgba(0, 0, 0, 0.01)'); + grad.addColorStop(1, 'rgba(0, 0, 0, 0.2)'); + knobCtx.fillStyle = grad; + knobCtx.beginPath(); + knobCtx.arc(maxPostCenterX, maxPostCenterY, size * 0.77 / 2, 0, TWO_PI, true); + knobCtx.closePath(); + knobCtx.fill(); + break; + } + + // cache the buffer + createKnobImage.cache[cacheKey] = knobBuffer; + } + return createKnobImage.cache[cacheKey]; + }; + createKnobImage.cache = {}; + + var createLedImage = function (size, state, ledColor) { + var ledBuffer, ledCtx, + // Bug in Chrome browser, radialGradients do not draw correctly if the center is not an integer value + ledCenterX = 2 * Math.round(size / 4), + ledCenterY = 2 * Math.round(size / 4), + grad, + cacheKey = size.toString() + state + ledColor.outerColor_ON; + + // check if we have already created and cached this buffer, if not create it + if (!createLedImage.cache[cacheKey]) { + ledBuffer = createBuffer(size, size); + ledCtx = ledBuffer.getContext('2d'); + + switch (state) { + case 0: // LED OFF + // OFF Gradient + grad = ledCtx.createRadialGradient(ledCenterX, ledCenterY, 0, ledCenterX, ledCenterY, size * 0.5 / 2); + grad.addColorStop(0, ledColor.innerColor1_OFF); + grad.addColorStop(0.2, ledColor.innerColor2_OFF); + grad.addColorStop(1, ledColor.outerColor_OFF); + ledCtx.fillStyle = grad; + + ledCtx.beginPath(); + ledCtx.arc(ledCenterX, ledCenterY, size * 0.5 / 2, 0, TWO_PI, true); + ledCtx.closePath(); + ledCtx.fill(); + + // InnerShadow + grad = ledCtx.createRadialGradient(ledCenterX, ledCenterY, 0, ledCenterX, ledCenterY, size * 0.5 / 2); + grad.addColorStop(0, 'rgba(0, 0, 0, 0)'); + grad.addColorStop(0.8, 'rgba(0, 0, 0, 0)'); + grad.addColorStop(1, 'rgba(0, 0, 0, 0.4)'); + ledCtx.fillStyle = grad; + + ledCtx.beginPath(); + ledCtx.arc(ledCenterX, ledCenterY, size * 0.5 / 2, 0, TWO_PI, true); + ledCtx.closePath(); + ledCtx.fill(); + + // LightReflex + grad = ledCtx.createLinearGradient(0, 0.35 * size, 0, 0.35 * size + 0.15 * size); + grad.addColorStop(0, 'rgba(255, 255, 255, 0.4)'); + grad.addColorStop(1, 'rgba(255, 255, 255, 0)'); + ledCtx.fillStyle = grad; + + ledCtx.beginPath(); + ledCtx.arc(ledCenterX, 0.35 * size + 0.2 * size / 2, size * 0.2, 0, TWO_PI, true); + ledCtx.closePath(); + ledCtx.fill(); + break; + + case 1: // LED ON + // ON Gradient + grad = ledCtx.createRadialGradient(ledCenterX, ledCenterY, 0, ledCenterX, ledCenterY, size * 0.5 / 2); + grad.addColorStop(0, ledColor.innerColor1_ON); + grad.addColorStop(0.2, ledColor.innerColor2_ON); + grad.addColorStop(1, ledColor.outerColor_ON); + ledCtx.fillStyle = grad; + + ledCtx.beginPath(); + ledCtx.arc(ledCenterX, ledCenterY, size * 0.5 / 2, 0, TWO_PI, true); + ledCtx.closePath(); + ledCtx.fill(); + + // InnerShadow + grad = ledCtx.createRadialGradient(ledCenterX, ledCenterY, 0, ledCenterX, ledCenterY, size * 0.5 / 2); + grad.addColorStop(0, 'rgba(0, 0, 0, 0)'); + grad.addColorStop(0.8, 'rgba(0, 0, 0, 0)'); + grad.addColorStop(1, 'rgba(0, 0, 0, 0.4)'); + ledCtx.fillStyle = grad; + + ledCtx.beginPath(); + ledCtx.arc(ledCenterX, ledCenterY, size * 0.5 / 2, 0, TWO_PI, true); + ledCtx.closePath(); + ledCtx.fill(); + + // LightReflex + grad = ledCtx.createLinearGradient(0, 0.35 * size, 0, 0.35 * size + 0.15 * size); + grad.addColorStop(0, 'rgba(255, 255, 255, 0.4)'); + grad.addColorStop(1, 'rgba(255, 255, 255, 0)'); + ledCtx.fillStyle = grad; + + ledCtx.beginPath(); + ledCtx.arc(ledCenterX, 0.35 * size + 0.2 * size / 2, size * 0.2, 0, TWO_PI, true); + ledCtx.closePath(); + ledCtx.fill(); + + // Corona + grad = ledCtx.createRadialGradient(ledCenterX, ledCenterY, 0, ledCenterX, ledCenterY, size / 2); + grad.addColorStop(0, setAlpha(ledColor.coronaColor, 0)); + grad.addColorStop(0.6, setAlpha(ledColor.coronaColor, 0.4)); + grad.addColorStop(0.7, setAlpha(ledColor.coronaColor, 0.25)); + grad.addColorStop(0.8, setAlpha(ledColor.coronaColor, 0.15)); + grad.addColorStop(0.85, setAlpha(ledColor.coronaColor, 0.05)); + grad.addColorStop(1, setAlpha(ledColor.coronaColor, 0)); + ledCtx.fillStyle = grad; + + ledCtx.beginPath(); + ledCtx.arc(ledCenterX, ledCenterY, size / 2, 0, TWO_PI, true); + ledCtx.closePath(); + ledCtx.fill(); + break; + } + // cache the buffer + createLedImage.cache[cacheKey] = ledBuffer; + } + return createLedImage.cache[cacheKey]; + }; + createLedImage.cache = {}; + + var createLcdBackgroundImage = function (width, height, lcdColor) { + var lcdBuffer, lcdCtx, + xB = 0, + yB = 0, + wB = width, + hB = height, + rB = Math.min(width, height) * 0.095, + grad, + xF = 1, + yF = 1, + wF = width - 2, + hF = height - 2, + rF = rB - 1, + cacheKey = width.toString() + height + JSON.stringify(lcdColor); + + // check if we have already created and cached this buffer, if not create it + if (!createLcdBackgroundImage.cache[cacheKey]) { + lcdBuffer = createBuffer(width, height); + lcdCtx = lcdBuffer.getContext('2d'); + // background + grad = lcdCtx.createLinearGradient(0, yB, 0, yB + hB); + grad.addColorStop(0, '#4c4c4c'); + grad.addColorStop(0.08, '#666666'); + grad.addColorStop(0.92, '#666666'); + grad.addColorStop(1, '#e6e6e6'); + lcdCtx.fillStyle = grad; + roundedRectangle(lcdCtx, xB, yB, wB, hB, rB); + lcdCtx.fill(); + + // foreground + grad = lcdCtx.createLinearGradient(0, yF, 0, yF + hF); + grad.addColorStop(0, lcdColor.gradientStartColor); + grad.addColorStop(0.03, lcdColor.gradientFraction1Color); + grad.addColorStop(0.49, lcdColor.gradientFraction2Color); + grad.addColorStop(0.5, lcdColor.gradientFraction3Color); + grad.addColorStop(1, lcdColor.gradientStopColor); + lcdCtx.fillStyle = grad; + roundedRectangle(lcdCtx, xF, yF, wF, hF, rF); + lcdCtx.fill(); + // cache the buffer + createLcdBackgroundImage.cache[cacheKey] = lcdBuffer; + } + return createLcdBackgroundImage.cache[cacheKey]; + }; + createLcdBackgroundImage.cache = {}; + + var createMeasuredValueImage = function (size, indicatorColor, radial, vertical) { + var indicatorBuffer, indicatorCtx, + cacheKey = size.toString() + indicatorColor + radial + vertical; + + // check if we have already created and cached this buffer, if so return it and exit + if (!createMeasuredValueImage.cache[cacheKey]) { + indicatorBuffer = doc.createElement('canvas'); + indicatorCtx = indicatorBuffer.getContext('2d'); + indicatorBuffer.width = size; + indicatorBuffer.height = size; + indicatorCtx.fillStyle = indicatorColor; + if (radial) { + indicatorCtx.beginPath(); + indicatorCtx.moveTo(size * 0.5, size); + indicatorCtx.lineTo(0, 0); + indicatorCtx.lineTo(size, 0); + indicatorCtx.closePath(); + indicatorCtx.fill(); + } else { + if (vertical) { + indicatorCtx.beginPath(); + indicatorCtx.moveTo(size, size * 0.5); + indicatorCtx.lineTo(0, 0); + indicatorCtx.lineTo(0, size); + indicatorCtx.closePath(); + indicatorCtx.fill(); + } else { + indicatorCtx.beginPath(); + indicatorCtx.moveTo(size * 0.5, 0); + indicatorCtx.lineTo(size, size); + indicatorCtx.lineTo(0, size); + indicatorCtx.closePath(); + indicatorCtx.fill(); + } + } + // cache the buffer + createMeasuredValueImage.cache[cacheKey] = indicatorBuffer; + } + return createMeasuredValueImage.cache[cacheKey]; + }; + createMeasuredValueImage.cache = {}; + + var createTrendIndicator = function (width, onSection, colors) { + var height = width * 2, + trendBuffer, trendCtx, + fill, + cacheKey = onSection.state + width + JSON.stringify(colors), + + drawUpArrow = function () { + // draw up arrow (red) + var ledColor = colors[0]; + + if (onSection.state === 'up') { + fill = trendCtx.createRadialGradient(0.5 * width, 0.2 * height, 0, 0.5 * width, 0.2 * height, 0.5 * width); + fill.addColorStop(0, ledColor.innerColor1_ON); + fill.addColorStop(0.2, ledColor.innerColor2_ON); + fill.addColorStop(1, ledColor.outerColor_ON); + } else { + fill = trendCtx.createLinearGradient(0, 0, 0, 0.5 * height); + fill.addColorStop(0, '#323232'); + fill.addColorStop(1, '#5c5c5c'); + } + trendCtx.fillStyle = fill; + trendCtx.beginPath(); + trendCtx.moveTo(0.5 * width, 0); + trendCtx.lineTo(width, 0.2 * height); + trendCtx.lineTo(0.752 * width, 0.2 * height); + trendCtx.lineTo(0.752 * width, 0.37 * height); + trendCtx.lineTo(0.252 * width, 0.37 * height); + trendCtx.lineTo(0.252 * width, 0.2 * height); + trendCtx.lineTo(0, 0.2 * height); + trendCtx.closePath(); + trendCtx.fill(); + if (onSection.state !== 'up') { + // Inner shadow + trendCtx.strokeStyle = 'rgba(0, 0, 0, 0.4)'; + trendCtx.beginPath(); + trendCtx.moveTo(0, 0.2 * height); + trendCtx.lineTo(0.5 * width, 0); + trendCtx.lineTo(width, 0.2 * height); + trendCtx.moveTo(0.252 * width, 0.2 * height); + trendCtx.lineTo(0.252 * width, 0.37 * height); + trendCtx.stroke(); + // Inner highlight + trendCtx.strokeStyle = 'rgba(255, 255, 255, 0.3)'; + trendCtx.beginPath(); + trendCtx.moveTo(0.252 * width, 0.37 * height); + trendCtx.lineTo(0.752 * width, 0.37 * height); + trendCtx.lineTo(0.752 * width, 0.2 * height); + trendCtx.lineTo(width, 0.2 * height); + trendCtx.stroke(); + } else { + // draw halo + fill = trendCtx.createRadialGradient(0.5 * width, 0.2 * height, 0, 0.5 * width, 0.2 * height, 0.7 * width); + fill.addColorStop(0, setAlpha(ledColor.coronaColor, 0)); + fill.addColorStop(0.5, setAlpha(ledColor.coronaColor, 0.3)); + fill.addColorStop(0.7, setAlpha(ledColor.coronaColor, 0.2)); + fill.addColorStop(0.8, setAlpha(ledColor.coronaColor, 0.1)); + fill.addColorStop(0.85, setAlpha(ledColor.coronaColor, 0.05)); + fill.addColorStop(1, setAlpha(ledColor.coronaColor, 0)); + trendCtx.fillStyle = fill; + + trendCtx.beginPath(); + trendCtx.arc(0.5 * width, 0.2 * height, 0.7 * width, 0, TWO_PI, true); + trendCtx.closePath(); + trendCtx.fill(); + } + }, + + drawEquals = function () { + // draw equal symbol + var ledColor = colors[1]; + + trendCtx.beginPath(); + if (onSection.state === 'steady') { + fill = ledColor.outerColor_ON; + trendCtx.fillStyle = fill; + trendCtx.rect(0.128 * width, 0.41 * height, 0.744 * width, 0.074 * height); + trendCtx.rect(0.128 * width, 0.516 * height, 0.744 * width, 0.074 * height); + trendCtx.closePath(); + trendCtx.fill(); + } else { + fill = trendCtx.createLinearGradient(0, 0.41 * height, 0, 0.41 * height + 0.074 * height); + fill.addColorStop(0, '#323232'); + fill.addColorStop(1, '#5c5c5c'); + trendCtx.fillStyle = fill; + trendCtx.rect(0.128 * width, 0.41 * height, 0.744 * width, 0.074 * height); + trendCtx.closePath(); + trendCtx.fill(); + fill = trendCtx.createLinearGradient(0, 0.516 * height, 0, 0.516 * height + 0.074 * height); + fill.addColorStop(0, '#323232'); + fill.addColorStop(1, '#5c5c5c'); + trendCtx.fillStyle = fill; + trendCtx.rect(0.128 * width, 0.516 * height, 0.744 * width, 0.074 * height); + trendCtx.closePath(); + trendCtx.fill(); + } + if (onSection.state !== 'steady') { + // inner shadow + trendCtx.strokeStyle = 'rgba(0, 0, 0, 0.4)'; + trendCtx.beginPath(); + trendCtx.moveTo(0.128 * width, 0.41 * height + 0.074 * height); + trendCtx.lineTo(0.128 * width, 0.41 * height); + trendCtx.lineTo(0.128 * width + 0.744 * width, 0.41 * height); + trendCtx.stroke(); + trendCtx.beginPath(); + trendCtx.moveTo(0.128 * width, 0.516 * height + 0.074 * height); + trendCtx.lineTo(0.128 * width, 0.516 * height); + trendCtx.lineTo(0.128 * width + 0.744 * width, 0.516 * height); + trendCtx.stroke(); + // inner highlight + trendCtx.strokeStyle = 'rgba(255, 255, 255, 0.3)'; + trendCtx.beginPath(); + trendCtx.moveTo(0.128 * width + 0.744 * width, 0.41 * height); + trendCtx.lineTo(0.128 * width + 0.744 * width, 0.41 * height + 0.074 * height); + trendCtx.lineTo(0.128 * width, 0.41 * height + 0.074 * height); + trendCtx.stroke(); + trendCtx.beginPath(); + trendCtx.moveTo(0.128 * width + 0.744 * width, 0.516 * height); + trendCtx.lineTo(0.128 * width + 0.744 * width, 0.516 * height + 0.074 * height); + trendCtx.lineTo(0.128 * width, 0.516 * height + 0.074 * height); + trendCtx.stroke(); + } else { + // draw halo + fill = trendCtx.createRadialGradient(0.5 * width, 0.5 * height, 0, 0.5 * width, 0.5 * height, 0.7 * width); + fill.addColorStop(0, setAlpha(ledColor.coronaColor, 0)); + fill.addColorStop(0.5, setAlpha(ledColor.coronaColor, 0.3)); + fill.addColorStop(0.7, setAlpha(ledColor.coronaColor, 0.2)); + fill.addColorStop(0.8, setAlpha(ledColor.coronaColor, 0.1)); + fill.addColorStop(0.85, setAlpha(ledColor.coronaColor, 0.05)); + fill.addColorStop(1, setAlpha(ledColor.coronaColor, 0)); + trendCtx.fillStyle = fill; + trendCtx.beginPath(); + trendCtx.arc(0.5 * width, 0.5 * height, 0.7 * width, 0, TWO_PI, true); + trendCtx.closePath(); + trendCtx.fill(); + } + }, + + drawDownArrow = function () { + // draw down arrow + var ledColor = colors[2]; + if (onSection.state === 'down') { + fill = trendCtx.createRadialGradient(0.5 * width, 0.8 * height, 0, 0.5 * width, 0.8 * height, 0.5 * width); + fill.addColorStop(0, ledColor.innerColor1_ON); + fill.addColorStop(0.2, ledColor.innerColor2_ON); + fill.addColorStop(1, ledColor.outerColor_ON); + } else { + fill = trendCtx.createLinearGradient(0, 0.63 * height, 0, height); + fill.addColorStop(0, '#323232'); + fill.addColorStop(1, '#5c5c5c'); + } + trendCtx.beginPath(); + trendCtx.fillStyle = fill; + trendCtx.moveTo(0.5 * width, height); + trendCtx.lineTo(width, 0.8 * height); + trendCtx.lineTo(0.725 * width, 0.8 * height); + trendCtx.lineTo(0.725 * width, 0.63 * height); + trendCtx.lineTo(0.252 * width, 0.63 * height); + trendCtx.lineTo(0.252 * width, 0.8 * height); + trendCtx.lineTo(0, 0.8 * height); + trendCtx.closePath(); + trendCtx.fill(); + if (onSection.state !== 'down') { + // Inner shadow + trendCtx.strokeStyle = 'rgba(0, 0, 0, 0.4)'; + trendCtx.beginPath(); + trendCtx.moveTo(0, 0.8 * height); + trendCtx.lineTo(0.252 * width, 0.8 * height); + trendCtx.moveTo(0.252 * width, 0.63 * height); + trendCtx.lineTo(0.752 * width, 0.63 * height); + trendCtx.stroke(); + trendCtx.beginPath(); + trendCtx.moveTo(0.752 * width, 0.8 * height); + trendCtx.lineTo(width, 0.8 * height); + trendCtx.stroke(); + // Inner highlight + trendCtx.strokeStyle = 'rgba(255, 255, 255, 0.3)'; + trendCtx.beginPath(); + trendCtx.moveTo(0, 0.8 * height); + trendCtx.lineTo(0.5 * width, height); + trendCtx.lineTo(width, 0.8 * height); + trendCtx.stroke(); + trendCtx.beginPath(); + trendCtx.moveTo(0.752 * width, 0.8 * height); + trendCtx.lineTo(0.752 * width, 0.63 * height); + trendCtx.stroke(); + } else { + // draw halo + fill = trendCtx.createRadialGradient(0.5 * width, 0.8 * height, 0, 0.5 * width, 0.8 * height, 0.7 * width); + fill.addColorStop(0, setAlpha(ledColor.coronaColor, 0)); + fill.addColorStop(0.5, setAlpha(ledColor.coronaColor, 0.3)); + fill.addColorStop(0.7, setAlpha(ledColor.coronaColor, 0.2)); + fill.addColorStop(0.8, setAlpha(ledColor.coronaColor, 0.1)); + fill.addColorStop(0.85, setAlpha(ledColor.coronaColor, 0.05)); + fill.addColorStop(1, setAlpha(ledColor.coronaColor, 0)); + trendCtx.fillStyle = fill; + trendCtx.beginPath(); + trendCtx.arc(0.5 * width, 0.8 * height, 0.7 * width, 0, TWO_PI, true); + trendCtx.closePath(); + trendCtx.fill(); + } + }; + + // Check if we have already cached this indicator, if not create it + if (!createTrendIndicator.cache[cacheKey]) { + // create oversized buffer for the glow + trendBuffer = createBuffer(width * 2, width * 4); + trendCtx = trendBuffer.getContext('2d'); + trendCtx.translate(width * 0.5, width * 0.5); + // Must draw the active section last so the 'glow' is on top + switch (onSection.state) { + case 'up': + drawDownArrow(); + drawEquals(); + drawUpArrow(); + break; + case 'steady': + drawDownArrow(); + drawUpArrow(); + drawEquals(); + break; + case 'down': + /* falls through */ + default: + drawUpArrow(); + drawEquals(); + drawDownArrow(); + break; + } + // cache the buffer + createTrendIndicator.cache[cacheKey] = trendBuffer; + } + return createTrendIndicator.cache[cacheKey]; + }; + createTrendIndicator.cache = {}; + + var drawTitleImage = function (ctx, imageWidth, imageHeight, titleString, unitString, backgroundColor, vertical, radial, altPos, gaugeType) { + gaugeType = (undefined === gaugeType ? gaugeType = steelseries.GaugeType.TYPE1 : gaugeType); + ctx.save(); + ctx.textAlign = (radial ? 'center' : 'left'); + ctx.textBaseline = 'middle'; + ctx.strokeStyle = backgroundColor.labelColor.getRgbaColor(); + ctx.fillStyle = backgroundColor.labelColor.getRgbaColor(); + + if (radial) { + ctx.font = 0.046728 * imageWidth + 'px ' + stdFontName; + ctx.fillText(titleString, imageWidth / 2, imageHeight * 0.3, imageWidth * 0.3); + ctx.fillText(unitString, imageWidth / 2, imageHeight * 0.38, imageWidth * 0.3); + } else { + // linear + if (vertical) { + ctx.font = 0.1 * imageWidth + 'px ' + stdFontName; + ctx.save(); + ctx.translate(0.671428 * imageWidth, 0.1375 * imageHeight); + ctx.rotate(1.570796); + ctx.fillText(titleString, 0, 0); + ctx.translate(-0.671428 * imageWidth, -0.1375 * imageHeight); + ctx.restore(); + ctx.font = 0.071428 * imageWidth + 'px ' + stdFontName; + if (altPos) { + // LCD visible + if (gaugeType.type === 'type2') { + ctx.textAlign = 'right'; + ctx.fillText(unitString, 0.36 * imageWidth, imageHeight * 0.79, imageWidth * 0.25); + } else { + ctx.fillText(unitString, 0.63 * imageWidth, imageHeight * 0.85, imageWidth * 0.2); + } + } else { + // LCD hidden + ctx.textAlign = 'center'; + if (gaugeType.type === 'type2') { + ctx.fillText(unitString, imageWidth / 2, imageHeight * 0.92, imageWidth * 0.2); + } else { + ctx.fillText(unitString, imageWidth / 2, imageHeight * 0.89, imageWidth * 0.2); + } + } + } else { //linear horizontal + ctx.font = 0.035 * imageWidth + 'px ' + stdFontName; + ctx.fillText(titleString, imageWidth * 0.15, imageHeight * 0.25, imageWidth * 0.3); + ctx.font = 0.025 * imageWidth + 'px ' + stdFontName; + ctx.fillText(unitString, imageWidth * 0.0625, imageHeight * 0.7, imageWidth * 0.07); + } + } + ctx.restore(); + }; + + //***************************************** T E X T U R E S **************************************************** + var carbonBuffer = drawToBuffer(12, 12, function (ctx) { + var imageWidth = ctx.canvas.width, + imageHeight = ctx.canvas.height, + offsetX = 0, + offsetY = 0, + grad; + + ctx.save(); + + // RULB + ctx.save(); + ctx.beginPath(); + ctx.rect(0, 0, imageWidth * 0.5, imageHeight * 0.5); + ctx.closePath(); + ctx.restore(); + + grad = ctx.createLinearGradient(0, offsetY * imageHeight, 0, 0.5 * imageHeight + offsetY * imageHeight); + grad.addColorStop(0, 'rgb(35, 35, 35)'); + grad.addColorStop(1, 'rgb(23, 23, 23)'); + ctx.fillStyle = grad; + ctx.fill(); + + // RULF + ctx.save(); + ctx.beginPath(); + ctx.rect(imageWidth * 0.083333, 0, imageWidth * 0.333333, imageHeight * 0.416666); + ctx.closePath(); + ctx.restore(); + offsetX = 0.083333; + offsetY = 0; + grad = ctx.createLinearGradient(0, offsetY * imageHeight, 0, 0.416666 * imageHeight + offsetY * imageHeight); + grad.addColorStop(0, 'rgb(38, 38, 38)'); + grad.addColorStop(1, 'rgb(30, 30, 30)'); + ctx.fillStyle = grad; + ctx.fill(); + + // RLRB + ctx.save(); + ctx.beginPath(); + ctx.rect(imageWidth * 0.5, imageHeight * 0.5, imageWidth * 0.5, imageHeight * 0.5); + ctx.closePath(); + ctx.restore(); + offsetX = 0.5; + offsetY = 0.5; + grad = ctx.createLinearGradient(0, offsetY * imageHeight, 0, 0.5 * imageHeight + offsetY * imageHeight); + grad.addColorStop(0, 'rgb(35, 35, 35)'); + grad.addColorStop(1, 'rgb(23, 23, 23)'); + ctx.fillStyle = grad; + ctx.fill(); + + // RLRF + ctx.save(); + ctx.beginPath(); + ctx.rect(imageWidth * 0.583333, imageHeight * 0.5, imageWidth * 0.333333, imageHeight * 0.416666); + ctx.closePath(); + ctx.restore(); + offsetX = 0.583333; + offsetY = 0.5; + grad = ctx.createLinearGradient(0, offsetY * imageHeight, 0, 0.416666 * imageHeight + offsetY * imageHeight); + grad.addColorStop(0, 'rgb(38, 38, 38)'); + grad.addColorStop(1, 'rgb(30, 30, 30)'); + ctx.fillStyle = grad; + ctx.fill(); + + // RURB + ctx.save(); + ctx.beginPath(); + ctx.rect(imageWidth * 0.5, 0, imageWidth * 0.5, imageHeight * 0.5); + ctx.closePath(); + ctx.restore(); + offsetX = 0.5; + offsetY = 0; + grad = ctx.createLinearGradient(0, offsetY * imageHeight, 0, 0.5 * imageHeight + offsetY * imageHeight); + grad.addColorStop(0, '#303030'); + grad.addColorStop(1, 'rgb(40, 40, 40)'); + ctx.fillStyle = grad; + ctx.fill(); + + // RURF + ctx.save(); + ctx.beginPath(); + ctx.rect(imageWidth * 0.583333, imageHeight * 0.083333, imageWidth * 0.333333, imageHeight * 0.416666); + ctx.closePath(); + ctx.restore(); + offsetX = 0.583333; + offsetY = 0.083333; + grad = ctx.createLinearGradient(0, offsetY * imageHeight, 0, 0.416666 * imageHeight + offsetY * imageHeight); + grad.addColorStop(0, 'rgb(53, 53, 53)'); + grad.addColorStop(1, 'rgb(45, 45, 45)'); + ctx.fillStyle = grad; + ctx.fill(); + + // RLLB + ctx.save(); + ctx.beginPath(); + ctx.rect(0, imageHeight * 0.5, imageWidth * 0.5, imageHeight * 0.5); + ctx.closePath(); + ctx.restore(); + offsetX = 0; + offsetY = 0.5; + grad = ctx.createLinearGradient(0, offsetY * imageHeight, 0, 0.5 * imageHeight + offsetY * imageHeight); + grad.addColorStop(0, '#303030'); + grad.addColorStop(1, '#282828'); + ctx.fillStyle = grad; + ctx.fill(); + + // RLLF + ctx.save(); + ctx.beginPath(); + ctx.rect(imageWidth * 0.083333, imageHeight * 0.583333, imageWidth * 0.333333, imageHeight * 0.416666); + ctx.closePath(); + ctx.restore(); + offsetX = 0.083333; + offsetY = 0.583333; + grad = ctx.createLinearGradient(0, offsetY * imageHeight, 0, 0.416666 * imageHeight + offsetY * imageHeight); + grad.addColorStop(0, '#353535'); + grad.addColorStop(1, '#2d2d2d'); + ctx.fillStyle = grad; + ctx.fill(); + + ctx.restore(); + }); + + var punchedSheetBuffer = drawToBuffer(15, 15, function (ctx) { + var imageWidth = ctx.canvas.width, + imageHeight = ctx.canvas.height, + grad; + + ctx.save(); + + // BACK + ctx.save(); + ctx.beginPath(); + ctx.rect(0, 0, imageWidth, imageHeight); + ctx.closePath(); + ctx.restore(); + ctx.fillStyle = '#1D2123'; + ctx.fill(); + + // ULB + ctx.save(); + ctx.beginPath(); + ctx.moveTo(0, imageHeight * 0.266666); + ctx.bezierCurveTo(0, imageHeight * 0.4, imageWidth * 0.066666, imageHeight * 0.466666, imageWidth * 0.2, imageHeight * 0.466666); + ctx.bezierCurveTo(imageWidth * 0.333333, imageHeight * 0.466666, imageWidth * 0.4, imageHeight * 0.4, imageWidth * 0.4, imageHeight * 0.266666); + ctx.bezierCurveTo(imageWidth * 0.4, imageHeight * 0.133333, imageWidth * 0.333333, imageHeight * 0.066666, imageWidth * 0.2, imageHeight * 0.066666); + ctx.bezierCurveTo(imageWidth * 0.066666, imageHeight * 0.066666, 0, imageHeight * 0.133333, 0, imageHeight * 0.266666); + ctx.closePath(); + grad = ctx.createLinearGradient(0, 0.066666 * imageHeight, 0, 0.466666 * imageHeight); + grad.addColorStop(0, '#000000'); + grad.addColorStop(1, '#444444'); + ctx.fillStyle = grad; + ctx.fill(); + + // ULF + ctx.save(); + ctx.beginPath(); + ctx.moveTo(0, imageHeight * 0.2); + ctx.bezierCurveTo(0, imageHeight * 0.333333, imageWidth * 0.066666, imageHeight * 0.4, imageWidth * 0.2, imageHeight * 0.4); + ctx.bezierCurveTo(imageWidth * 0.333333, imageHeight * 0.4, imageWidth * 0.4, imageHeight * 0.333333, imageWidth * 0.4, imageHeight * 0.2); + ctx.bezierCurveTo(imageWidth * 0.4, imageHeight * 0.066666, imageWidth * 0.333333, 0, imageWidth * 0.2, 0); + ctx.bezierCurveTo(imageWidth * 0.066666, 0, 0, imageHeight * 0.066666, 0, imageHeight * 0.2); + ctx.closePath(); + ctx.fillStyle = '#050506'; + ctx.fill(); + + // LRB + ctx.save(); + ctx.beginPath(); + ctx.moveTo(imageWidth * 0.466666, imageHeight * 0.733333); + ctx.bezierCurveTo(imageWidth * 0.466666, imageHeight * 0.866666, imageWidth * 0.533333, imageHeight * 0.933333, imageWidth * 0.666666, imageHeight * 0.933333); + ctx.bezierCurveTo(imageWidth * 0.8, imageHeight * 0.933333, imageWidth * 0.866666, imageHeight * 0.866666, imageWidth * 0.866666, imageHeight * 0.733333); + ctx.bezierCurveTo(imageWidth * 0.866666, imageHeight * 0.6, imageWidth * 0.8, imageHeight * 0.533333, imageWidth * 0.666666, imageHeight * 0.533333); + ctx.bezierCurveTo(imageWidth * 0.533333, imageHeight * 0.533333, imageWidth * 0.466666, imageHeight * 0.6, imageWidth * 0.466666, imageHeight * 0.733333); + ctx.closePath(); + grad = ctx.createLinearGradient(0, 0.533333 * imageHeight, 0, 0.933333 * imageHeight); + grad.addColorStop(0, '#000000'); + grad.addColorStop(1, '#444444'); + ctx.fillStyle = grad; + ctx.fill(); + + // LRF + ctx.save(); + ctx.beginPath(); + ctx.moveTo(imageWidth * 0.466666, imageHeight * 0.666666); + ctx.bezierCurveTo(imageWidth * 0.466666, imageHeight * 0.8, imageWidth * 0.533333, imageHeight * 0.866666, imageWidth * 0.666666, imageHeight * 0.866666); + ctx.bezierCurveTo(imageWidth * 0.8, imageHeight * 0.866666, imageWidth * 0.866666, imageHeight * 0.8, imageWidth * 0.866666, imageHeight * 0.666666); + ctx.bezierCurveTo(imageWidth * 0.866666, imageHeight * 0.533333, imageWidth * 0.8, imageHeight * 0.466666, imageWidth * 0.666666, imageHeight * 0.466666); + ctx.bezierCurveTo(imageWidth * 0.533333, imageHeight * 0.466666, imageWidth * 0.466666, imageHeight * 0.533333, imageWidth * 0.466666, imageHeight * 0.666666); + ctx.closePath(); + ctx.fillStyle = '#050506'; + ctx.fill(); + + ctx.restore(); + }); + + var brushedMetalTexture = function (color, radius, amount, monochrome, shine) { + + this.fill = function (startX, startY, endX, endY) { + var i, x, y, // loop counters + sinArr, + width, height, + outCanvas, outCanvasContext, // output canvas + inPixels, outPixels, // pixel arrays + //alpha = color & 0xff000000; + alpha = 255, + red = (color >> 16) & 0xff, + green = (color >> 8) & 0xff, + blue = color & 0xff, + n = 0, + variation = 255 * amount, + totR, totG, totB, + indx, tr, tg, tb, f; + + startX = Math.floor(startX); + startY = Math.floor(startY); + endX = Math.ceil(endX); + endY = Math.ceil(endY); + + width = endX - startX; + height = endY - startY; + + // Create output canvas + outCanvas = createBuffer(width, height); + outCanvasContext = outCanvas.getContext('2d'); + + // Create pixel arrays + inPixels = outCanvasContext.createImageData(width, height); + outPixels = outCanvasContext.createImageData(width, height); + + // Precreate sin() values + if (shine !== 0) { + sinArr = []; + for (i = 0; i < width; i++) { + sinArr[i] = (255 * shine * Math.sin(i / width * PI)) | 0; + } + } + + for (y = 0; y < height; y++) { + // The pixel array is addressed as 4 elements per pixel [r,g,b,a] + if (radius !== 0) { + totR = totG = totB = 0; + } + for (x = 0; x < width; x ++) { + indx = (y * width * 4) + (x * 4); + tr = red; + tg = green; + tb = blue; + if (shine !== 0) { + f = sinArr[x]; + tr += f; + tg += f; + tb += f; + } + + if (monochrome) { + n = ((2 * Math.random() - 1) * variation) | 0; + inPixels.data[indx] = clamp(tr + n); + inPixels.data[indx + 1] = clamp(tg + n); + inPixels.data[indx + 2] = clamp(tb + n); + inPixels.data[indx + 3] = alpha; + } else { + inPixels.data[indx] = random(tr, variation); + inPixels.data[indx + 1] = random(tg, variation); + inPixels.data[indx + 2] = random(tb, variation); + inPixels.data[indx + 3] = alpha; + } + } + } + + if (radius > 0) { + horizontalBlur(inPixels, outPixels, width, height, radius, alpha); + outCanvasContext.putImageData(outPixels, startX, startY); + } else { + outCanvasContext.putImageData(inPixels, startX, startY); + } + return outCanvas; + }; + + function random(x, vari) { + x += ((2 * Math.random() - 1) * vari) | 0; + return (x < 0 ? 0 : (x > 255 ? 255 : x)); + } + + function clamp(C) { + return (C < 0 ? 0 : (C > 255 ? 255 : C)); + } + + function horizontalBlur(inPix, outPix, width, height, radius, alpha) { + var x, y, // loop counters + i, mul, indx, + totR, totG, totB; + + if (radius >= width) { + radius = width - 1; + } + mul = 1 / (radius * 2 + 1); + indx = 0; + for (y = 0; y < height; y++) { + totR = totG = totB = 0; + for (x = 0; x < radius ; x++) { + i = (indx + x) * 4; + totR += inPix.data[i]; + totG += inPix.data[i + 1]; + totB += inPix.data[i + 2]; + } + for (x = 0; x < width; x++) { + if (x > radius) { + i = (indx - radius - 1) * 4; + totR -= inPix.data[i]; + totG -= inPix.data[i + 1]; + totB -= inPix.data[i + 2]; + } + if (x + radius < width) { + i = (indx + radius) * 4; + totR += inPix.data[i]; + totG += inPix.data[i + 1]; + totB += inPix.data[i + 2]; + } + i = indx * 4; + outPix.data[i] = (totR * mul) | 0; + outPix.data[i + 1] = (totG * mul) | 0; + outPix.data[i + 2] = (totB * mul) | 0; + outPix.data[i + 3] = alpha; + indx++; + } + } + } + + return this; + }; + + //******************************************** T O O L S ******************************************************* + var RgbaColor = function (r, g, b, a) { + var red, green, blue, alpha; + + if (arguments.length === 1) { + // hexadecimal input #112233 + b = parseInt(r.substr(5, 2), 16); + g = parseInt(r.substr(3, 2), 16); + r = parseInt(r.substr(1, 2), 16); + a = 1; + } else if (arguments.length === 3) { + a = 1; + } + + function validateColors() { + red = range(r, 255); + green = range(g, 255); + blue = range(b, 255); + alpha = range(a, 1); + } + + validateColors(); + + this.getRed = function () { + return red; + }; + + this.setRed = function (r) { + red = range(r, 255); + }; + + this.getGreen = function () { + return green; + }; + + this.setGreen = function (g) { + green = range(g, 255); + }; + + this.getBlue = function () { + return blue; + }; + + this.setBlue = function (b) { + blue = range(b, 255); + }; + + this.getAlpha = function () { + return alpha; + }; + + this.setAlpha = function (a) { + alpha = range(a, 1); + }; + + this.getRgbaColor = function () { + return 'rgba(' + red + ', ' + green + ', ' + blue + ', ' + alpha + ')'; + }; + + this.getRgbColor = function () { + return 'rgb(' + red + ', ' + green + ', ' + blue + ')'; + }; + + this.getHexColor = function () { + return '#' + red.toString(16) + green.toString(16) + blue.toString(16); + }; + }; + + var ConicalGradient = function (fractions, colors) { + var limit = fractions.length - 1, + i; + + // Pre-multipy fractions array into range -PI to PI + for (i = 0; i <= limit; i++) { + fractions[i] = TWO_PI * fractions[i] - PI; + } + + this.fillCircle = function (ctx, centerX, centerY, innerX, outerX) { + var angle, + radius = Math.ceil(outerX), + diameter = radius * 2, + pixels, alpha, + x, y, dx, dy, dy2, distance, + indx, pixColor, + buffer, bufferCtx; + +// Original Version using rotated lines +/* + ctx.save(); + ctx.lineWidth = 1.5; + ctx.translate(centerX, centerY); + ctx.rotate(rotationOffset); + ctx.translate(-centerX, -centerY); + for (i = 0, size = fractions.length - 1; i < size; i++) { + startAngle = TWO_PI * fractions[i]; + stopAngle = TWO_PI * fractions[i + 1]; + range = stopAngle - startAngle; + startColor = colors[i]; + stopColor = colors[i + 1]; + for (angle = startAngle; angle < stopAngle; angle += angleStep) { + ctx.beginPath(); + ctx.fillStyle = getColorFromFraction(startColor, stopColor, range, (angle - startAngle)).getRgbaColor(); + ctx.strokeStyle = ctx.fillStyle; + if (innerX > 0) { + ctx.arc(centerX, centerY, innerX, angle + angleStep, angle, true); + } else { + ctx.moveTo(centerX, centerY); + } + ctx.arc(centerX, centerY, outerX, angle, angle + angleStep); + ctx.fill(); + ctx.stroke(); + } + } +*/ +// End - Original Version + + // Create pixel array + pixels = ctx.createImageData(diameter, diameter); + alpha = 255; + + for (y = 0; y < diameter; y++) { + dy = radius - y; + dy2 = dy * dy; + for (x = 0; x < diameter; x++) { + dx = x - radius; + distance = Math.sqrt((dx * dx) + dy2); + if (distance <= radius && distance >= innerX) { // pixels are transparent by default, so only paint the ones we need + angle = Math.atan2(dx, dy); + for (i = 0; i < limit; i++) { + if (angle >= fractions[i] && angle < fractions[i + 1]) { + pixColor = getColorFromFraction(colors[i], colors[i + 1], fractions[i + 1] - fractions[i], angle - fractions[i], true); + } + } + // The pixel array is addressed as 4 elements per pixel [r,g,b,a] + indx = ((diameter - y) * diameter * 4) + (x * 4); // plot is 180 rotated from orginal method, so apply a simple invert (diameter - y) + pixels.data[indx] = pixColor[0]; + pixels.data[indx + 1] = pixColor[1]; + pixels.data[indx + 2] = pixColor[2]; + pixels.data[indx + 3] = alpha; + } + } + } + + // Create a new buffer to apply the raw data so we can rotate it + buffer = createBuffer(diameter, diameter); + bufferCtx = buffer.getContext('2d'); + bufferCtx.putImageData(pixels, 0, 0); + // Apply the image buffer + ctx.drawImage(buffer, centerX - radius, centerY - radius); + }; + + this.fillRect = function (ctx, centerX, centerY, width, height, thicknessX, thicknessY) { + var angle, + width2, + height2, + pixels, alpha, + x, y, dx, dy, + indx, + pixColor, + buffer, bufferCtx; + + width = Math.ceil(width); + height = Math.ceil(height); + width2 = width / 2; + height2 = height / 2; + thicknessX = Math.ceil(thicknessX); + thicknessY = Math.ceil(thicknessY); + + // Create pixel array + pixels = ctx.createImageData(width, height); + alpha = 255; + + for (y = 0; y < height; y++) { + dy = height2 - y; + for (x = 0; x < width; x++) { + if (y > thicknessY && y <= height - thicknessY) { + // we are in the range where we only draw the sides + if (x > thicknessX && x < width - thicknessX) { + // we are in the empty 'middle', jump to the next edge + x = width - thicknessX; + } + } + dx = x - width2; + angle = Math.atan2(dx, dy); + for (i = 0; i < limit; i++) { + if (angle >= fractions[i] && angle < fractions[i + 1]) { + pixColor = getColorFromFraction(colors[i], colors[i + 1], fractions[i + 1] - fractions[i], angle - fractions[i], true); + } + } + // The pixel array is addressed as 4 elements per pixel [r,g,b,a] + indx = ((height - y) * width * 4) + (x * 4); // plot is 180 rotated from orginal method, so apply a simple invert (height - y) + pixels.data[indx] = pixColor[0]; + pixels.data[indx + 1] = pixColor[0]; + pixels.data[indx + 2] = pixColor[0]; + pixels.data[indx + 3] = alpha; + } + } + // Create a new buffer to apply the raw data so we can clip it when drawing to canvas + buffer = createBuffer(width, height); + bufferCtx = buffer.getContext('2d'); + bufferCtx.putImageData(pixels, 0, 0); + + // draw the buffer back to the canvas + ctx.drawImage(buffer, centerX - width2, centerY - height2); + }; + + }; + + var GradientWrapper = function (start, end, fractions, colors) { + + this.getColorAt = function (fraction) { + var lowerLimit = 0, + lowerIndex = 0, + upperLimit = 1, + upperIndex = 1, + i, + interpolationFraction; + + fraction = (fraction < 0 ? 0 : (fraction > 1 ? 1 : fraction)); + + for (i = 0; i < fractions.length; i++) { + if (fractions[i] < fraction && lowerLimit < fractions[i]) { + lowerLimit = fractions[i]; + lowerIndex = i; + } + if (fractions[i] === fraction) { + return colors[i]; + } + if (fractions[i] > fraction && upperLimit >= fractions[i]) { + upperLimit = fractions[i]; + upperIndex = i; + } + } + interpolationFraction = (fraction - lowerLimit) / (upperLimit - lowerLimit); + return getColorFromFraction(colors[lowerIndex], colors[upperIndex], 1, interpolationFraction); + }; + + this.getStart = function () { + return start; + }; + + this.getEnd = function () { + return end; + }; + }; + + function setAlpha(hex, alpha) { + var hexColor = ('#' === hex.charAt(0)) ? hex.substring(1, 7) : hex, + red = parseInt((hexColor).substring(0, 2), 16), + green = parseInt((hexColor).substring(2, 4), 16), + blue = parseInt((hexColor).substring(4, 6), 16), + color = 'rgba(' + red + ',' + green + ',' + blue + ',' + alpha + ')'; + + return color; + } + + function getColorFromFraction(sourceColor, destinationColor, range, fraction, returnRawData) { + var INT_TO_FLOAT = 1 / 255, + sourceRed = sourceColor.getRed(), + sourceGreen = sourceColor.getGreen(), + sourceBlue = sourceColor.getBlue(), + sourceAlpha = sourceColor.getAlpha(), + + deltaRed = destinationColor.getRed() - sourceRed, + deltaGreen = destinationColor.getGreen() - sourceGreen, + deltaBlue = destinationColor.getBlue() - sourceBlue, + deltaAlpha = destinationColor.getAlpha() * INT_TO_FLOAT - sourceAlpha * INT_TO_FLOAT, + + fractionRed = deltaRed / range * fraction, + fractionGreen = deltaGreen / range * fraction, + fractionBlue = deltaBlue / range * fraction, + fractionAlpha = deltaAlpha / range * fraction; + + returnRawData = returnRawData || false; + if (returnRawData) { + return [(sourceRed + fractionRed).toFixed(0), (sourceGreen + fractionGreen).toFixed(0), (sourceBlue + fractionBlue).toFixed(0), sourceAlpha + fractionAlpha]; + } else { + return new RgbaColor((sourceRed + fractionRed).toFixed(0), (sourceGreen + fractionGreen).toFixed(0), (sourceBlue + fractionBlue).toFixed(0), sourceAlpha + fractionAlpha); + } + } + + function section(start, stop, color) { + return {start : start, + stop : stop, + color : color}; + } + + Math.log10 = function (value) { + return (Math.log(value) / Math.LN10); + }; + + function calcNiceNumber(range, round) { + var exponent = Math.floor(Math.log10(range)), // exponent of range + fraction = range / Math.pow(10, exponent), // fractional part of range + niceFraction; // nice, rounded fraction + + if (round) { + if (1.5 > fraction) { + niceFraction = 1; + } else if (3 > fraction) { + niceFraction = 2; + } else if (7 > fraction) { + niceFraction = 5; + } else { + niceFraction = 10; + } + } else { + if (1 >= fraction) { + niceFraction = 1; + } else if (2 >= fraction) { + niceFraction = 2; + } else if (5 >= fraction) { + niceFraction = 5; + } else { + niceFraction = 10; + } + } + return niceFraction * Math.pow(10, exponent); + } + + function roundedRectangle(ctx, x, y, w, h, radius) { + var r = x + w, + b = y + h; + ctx.beginPath(); + ctx.moveTo(x + radius, y); + ctx.lineTo(r - radius, y); + ctx.quadraticCurveTo(r, y, r, y + radius); + ctx.lineTo(r, y + h - radius); + ctx.quadraticCurveTo(r, b, r - radius, b); + ctx.lineTo(x + radius, b); + ctx.quadraticCurveTo(x, b, x, b - radius); + ctx.lineTo(x, y + radius); + ctx.quadraticCurveTo(x, y, x + radius, y); + ctx.closePath(); +// ctx.stroke(); + } + + function createBuffer(width, height) { + var buffer = doc.createElement('canvas'); + buffer.width = width; + buffer.height = height; + return buffer; + } + + function drawToBuffer(width, height, drawFunction) { + var buffer = doc.createElement('canvas'); + buffer.width = width; + buffer.height = height; + drawFunction(buffer.getContext('2d')); + return buffer; + } + + function getColorValues(color) { + var colorData, + lookupBuffer = drawToBuffer(1, 1, function (ctx) { + ctx.fillStyle = color; + ctx.beginPath(); + ctx.rect(0, 0, 1, 1); + ctx.fill(); + }); + colorData = lookupBuffer.getContext('2d').getImageData(0, 0, 2, 2).data; + + /* + for (var i = 0; i < data.length; i += 4) { + var red = data[i]; // red + var green = data[i + 1]; // green + var blue = data[i + 2]; // blue + //var alpha = data[i + 3]; // alpha + console.log(red + ', ' + green + ', ' + blue); + } + */ + + return [colorData[0], colorData[1], colorData[2], colorData[3]]; + } + + function customColorDef(color) { + var VERY_DARK, + DARK, + LIGHT, + LIGHTER, + VERY_LIGHT, + values = getColorValues(color), + rgbaCol = new RgbaColor(values[0], values[1], values[2], values[3]); + + VERY_DARK = darker(rgbaCol, 0.32); + DARK = darker(rgbaCol, 0.62); + LIGHT = lighter(rgbaCol, 0.84); + LIGHTER = lighter(rgbaCol, 0.94); + VERY_LIGHT = lighter(rgbaCol, 1); + + return new ColorDef(VERY_DARK, DARK, rgbaCol, LIGHT, LIGHTER, VERY_LIGHT); + } + + function rgbToHsl(red, green, blue) { + var min, max, hue, saturation, lightness, delta; + + red /= 255; + green /= 255; + blue /= 255; + + max = Math.max(red, green, blue); + min = Math.min(red, green, blue); + lightness = (max + min) / 2; + + if (max === min) { + hue = saturation = 0; // achromatic + } else { + delta = max - min; + saturation = lightness > 0.5 ? delta / (2 - max - min) : delta / (max + min); + switch (max) { + case red: + hue = (green - blue) / delta + (green < blue ? 6 : 0); + break; + case green: + hue = (blue - red) / delta + 2; + break; + case blue: + hue = (red - green) / delta + 4; + break; + } + hue /= 6; + } + return [hue, saturation, lightness]; + } + + function hsbToRgb(hue, saturation, brightness) { + var r, g, b, + i = Math.floor(hue * 6), + f = hue * 6 - i, + p = brightness * (1 - saturation), + q = brightness * (1 - f * saturation), + t = brightness * (1 - (1 - f) * saturation); + + switch (i % 6) { + case 0: + r = brightness; + g = t; + b = p; + break; + case 1: + r = q; + g = brightness; + b = p; + break; + case 2: + r = p; + g = brightness; + b = t; + break; + case 3: + r = p; + g = q; + b = brightness; + break; + case 4: + r = t; + g = p; + b = brightness; + break; + case 5: + r = brightness; + g = p; + b = q; + break; + } + + return [Math.floor(r * 255), Math.floor(g * 255), Math.floor(b * 255)]; + } + + function rgbToHsb(r, g, b) { + var min, max, hue, saturation, brightness, delta; + + r = r / 255; + g = g / 255; + b = b / 255; + max = Math.max(r, g, b); + min = Math.min(r, g, b); + brightness = max; + delta = max - min; + saturation = max === 0 ? 0 : delta / max; + + if (max === min) { + hue = 0; // achromatic + } else { + switch (max) { + case r: + hue = (g - b) / delta + (g < b ? 6 : 0); + break; + case g: + hue = (b - r) / delta + 2; + break; + case b: + hue = (r - g) / delta + 4; + break; + } + hue /= 6; + } + return [hue, saturation, brightness]; + } + + function range(value, limit) { + return (value < 0 ? 0 : (value > limit ? limit : value)); + } + + function darker(color, fraction) { + var red = Math.floor(color.getRed() * (1 - fraction)), + green = Math.floor(color.getGreen() * (1 - fraction)), + blue = Math.floor(color.getBlue() * (1 - fraction)); + + red = range(red, 255); + green = range(green, 255); + blue = range(blue, 255); + + return new RgbaColor(red, green, blue, color.getAlpha()); + } + + function lighter(color, fraction) { + var red = Math.round(color.getRed() * (1 + fraction)), + green = Math.round(color.getGreen() * (1 + fraction)), + blue = Math.round(color.getBlue() * (1 + fraction)); + + red = range(red, 255); + green = range(green, 255); + blue = range(blue, 255); + + return new RgbaColor(red, green, blue, color.getAlpha()); + } + + function wrap(value, lower, upper) { + var distance, times; + if (upper <= lower) { + throw 'Rotary bounds are of negative or zero size'; + } + + distance = upper - lower; + times = Math.floor((value - lower) / distance); + + return value - (times * distance); + } + + function getShortestAngle(from, to) { + return wrap((to - from), -180, 180); + } + + // shim layer + var requestAnimFrame = (function () { + return window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + window.oRequestAnimationFrame || + window.msRequestAnimationFrame || + function (callback) { + window.setTimeout(callback, 1000 / 16); + }; + }()); + + function getCanvasContext(elementOrId) { + var element = (typeof elementOrId === 'string' || elementOrId instanceof String) ? + doc.getElementById(elementOrId) : elementOrId; + return element.getContext('2d'); + } + //**************************************** C O N S T A N T S *************************************************** + var BackgroundColorDef; + (function () { + BackgroundColorDef = function (gradientStart, gradientFraction, gradientStop, labelColor, symbolColor, name) { + this.gradientStart = gradientStart; + this.gradientFraction = gradientFraction; + this.gradientStop = gradientStop; + this.labelColor = labelColor; + this.symbolColor = symbolColor; + this.name = name; + }; + }()); + + var LcdColorDef; + (function () { + LcdColorDef = function (gradientStartColor, gradientFraction1Color, gradientFraction2Color, gradientFraction3Color, gradientStopColor, textColor) { + this.gradientStartColor = gradientStartColor; + this.gradientFraction1Color = gradientFraction1Color; + this.gradientFraction2Color = gradientFraction2Color; + this.gradientFraction3Color = gradientFraction3Color; + this.gradientStopColor = gradientStopColor; + this.textColor = textColor; + }; + }()); + + var ColorDef; + (function () { + ColorDef = function (veryDark, dark, medium, light, lighter, veryLight) { + this.veryDark = veryDark; + this.dark = dark; + this.medium = medium; + this.light = light; + this.lighter = lighter; + this.veryLight = veryLight; + }; + }()); + + var LedColorDef; + (function () { + LedColorDef = function (innerColor1_ON, innerColor2_ON, outerColor_ON, coronaColor, innerColor1_OFF, innerColor2_OFF, outerColor_OFF) { + this.innerColor1_ON = innerColor1_ON; + this.innerColor2_ON = innerColor2_ON; + this.outerColor_ON = outerColor_ON; + this.coronaColor = coronaColor; + this.innerColor1_OFF = innerColor1_OFF; + this.innerColor2_OFF = innerColor2_OFF; + this.outerColor_OFF = outerColor_OFF; + }; + }()); + + var GaugeTypeDef; + (function () { + GaugeTypeDef = function (type) { + this.type = type; + }; + }()); + + var OrientationDef; + (function () { + OrientationDef = function (type) { + this.type = type; + }; + }()); + + var KnobTypeDef; + (function () { + KnobTypeDef = function (type) { + this.type = type; + }; + }()); + + var KnobStyleDef; + (function () { + KnobStyleDef = function (style) { + this.style = style; + }; + }()); + + var FrameDesignDef; + (function () { + FrameDesignDef = function (design) { + this.design = design; + }; + }()); + + var PointerTypeDef; + (function () { + PointerTypeDef = function (type) { + this.type = type; + }; + }()); + + var ForegroundTypeDef; + (function () { + ForegroundTypeDef = function (type) { + this.type = type; + }; + }()); + + var LabelNumberFormatDef; + (function () { + LabelNumberFormatDef = function (format) { + this.format = format; + }; + }()); + + var TickLabelOrientationDef; + (function () { + TickLabelOrientationDef = function (type) { + this.type = type; + }; + }()); + + var TrendStateDef; + (function () { + TrendStateDef = function (state) { + this.state = state; + }; + }()); + + //************************* I m p l e m e n t a t i o n s o f d e f i n i t i o n s ************************ + var backgroundColor = { + DARK_GRAY: new BackgroundColorDef(new RgbaColor(0, 0, 0, 1), new RgbaColor(51, 51, 51, 1), new RgbaColor(153, 153, 153, 1), new RgbaColor(255, 255, 255, 1), new RgbaColor(180, 180, 180, 1), 'DARK_GRAY'), + SATIN_GRAY: new BackgroundColorDef(new RgbaColor(45, 57, 57, 1), new RgbaColor(45, 57, 57, 1), new RgbaColor(45, 57, 57, 1), new RgbaColor(167, 184, 180, 1), new RgbaColor(137, 154, 150, 1), 'SATIN_GRAY'), + LIGHT_GRAY: new BackgroundColorDef(new RgbaColor(130, 130, 130, 1), new RgbaColor(181, 181, 181, 1), new RgbaColor(253, 253, 253, 1), new RgbaColor(0, 0, 0, 1), new RgbaColor(80, 80, 80, 1), 'LIGHT_GRAY'), + WHITE: new BackgroundColorDef(new RgbaColor(255, 255, 255, 1), new RgbaColor(255, 255, 255, 1), new RgbaColor(255, 255, 255, 1), new RgbaColor(0, 0, 0, 1), new RgbaColor(80, 80, 80, 1), 'WHITE'), + BLACK: new BackgroundColorDef(new RgbaColor(0, 0, 0, 1), new RgbaColor(0, 0, 0, 1), new RgbaColor(0, 0, 0, 1), new RgbaColor(255, 255, 255, 1), new RgbaColor(150, 150, 150, 1), 'BLACK'), + BEIGE: new BackgroundColorDef(new RgbaColor(178, 172, 150, 1), new RgbaColor(204, 205, 184, 1), new RgbaColor(231, 231, 214, 1), new RgbaColor(0, 0, 0, 1), new RgbaColor(80, 80, 80, 1), 'BEIGE'), + BROWN: new BackgroundColorDef(new RgbaColor(245, 225, 193, 1), new RgbaColor(245, 225, 193, 1), new RgbaColor(255, 250, 240, 1), new RgbaColor(109, 73, 47, 1), new RgbaColor(89, 53, 27, 1), 'BROWN'), + RED: new BackgroundColorDef(new RgbaColor(198, 93, 95, 1), new RgbaColor(212, 132, 134, 1), new RgbaColor(242, 218, 218, 1), new RgbaColor(0, 0, 0, 1), new RgbaColor(90, 0, 0, 1), 'RED'), + GREEN: new BackgroundColorDef(new RgbaColor(65, 120, 40, 1), new RgbaColor(129, 171, 95, 1), new RgbaColor(218, 237, 202, 1), new RgbaColor(0, 0, 0, 1), new RgbaColor(0, 90, 0, 1), 'GREEN'), + BLUE: new BackgroundColorDef(new RgbaColor(45, 83, 122, 1), new RgbaColor(115, 144, 170, 1), new RgbaColor(227, 234, 238, 1), new RgbaColor(0, 0, 0, 1), new RgbaColor(0, 0, 90, 1), 'BLUE'), + ANTHRACITE: new BackgroundColorDef(new RgbaColor(50, 50, 54, 1), new RgbaColor(47, 47, 51, 1), new RgbaColor(69, 69, 74, 1), new RgbaColor(250, 250, 250, 1), new RgbaColor(180, 180, 180, 1), 'ANTHRACITE'), + MUD: new BackgroundColorDef(new RgbaColor(80, 86, 82, 1), new RgbaColor(70, 76, 72, 1), new RgbaColor(57, 62, 58, 1), new RgbaColor(255, 255, 240, 1), new RgbaColor(225, 225, 210, 1), 'MUD'), + PUNCHED_SHEET: new BackgroundColorDef(new RgbaColor(50, 50, 54, 1), new RgbaColor(47, 47, 51, 1), new RgbaColor(69, 69, 74, 1), new RgbaColor(255, 255, 255, 1), new RgbaColor(180, 180, 180, 1), 'PUNCHED_SHEET'), + CARBON: new BackgroundColorDef(new RgbaColor(50, 50, 54, 1), new RgbaColor(47, 47, 51, 1), new RgbaColor(69, 69, 74, 1), new RgbaColor(255, 255, 255, 1), new RgbaColor(180, 180, 180, 1), 'CARBON'), + STAINLESS: new BackgroundColorDef(new RgbaColor(130, 130, 130, 1), new RgbaColor(181, 181, 181, 1), new RgbaColor(253, 253, 253, 1), new RgbaColor(0, 0, 0, 1), new RgbaColor(80, 80, 80, 1), 'STAINLESS'), + BRUSHED_METAL: new BackgroundColorDef(new RgbaColor(50, 50, 54, 1), new RgbaColor(47, 47, 51, 1), new RgbaColor(69, 69, 74, 1), new RgbaColor(0, 0, 0, 1), new RgbaColor(80, 80, 80, 1), 'BRUSHED_METAL'), + BRUSHED_STAINLESS: new BackgroundColorDef(new RgbaColor(50, 50, 54, 1), new RgbaColor(47, 47, 51, 1), new RgbaColor(110, 110, 112, 1), new RgbaColor(0, 0, 0, 1), new RgbaColor(80, 80, 80, 1), 'BRUSHED_STAINLESS'), + TURNED: new BackgroundColorDef(new RgbaColor(130, 130, 130, 1), new RgbaColor(181, 181, 181, 1), new RgbaColor(253, 253, 253, 1), new RgbaColor(0, 0, 0, 1), new RgbaColor(80, 80, 80, 1), 'TURNED') + }; + + var lcdColor = { + BEIGE: new LcdColorDef('#c8c8b1', 'rgb(241, 237, 207)', 'rgb(234, 230, 194)', 'rgb(225, 220, 183)', 'rgb(237, 232, 191)', '#000000'), + BLUE: new LcdColorDef('#ffffff', 'rgb(231, 246, 255)', 'rgb(170, 224, 255)', 'rgb(136, 212, 255)', 'rgb(192, 232, 255)', '#124564'), + ORANGE: new LcdColorDef('#ffffff', 'rgb(255, 245, 225)', 'rgb(255, 217, 147)', 'rgb(255, 201, 104)', 'rgb(255, 227, 173)', '#503700'), + RED: new LcdColorDef('#ffffff', 'rgb(255, 225, 225)', 'rgb(253, 152, 152)', 'rgb(252, 114, 115)', 'rgb(254, 178, 178)', '#4f0c0e'), + YELLOW: new LcdColorDef('#ffffff', 'rgb(245, 255, 186)', 'rgb(210, 255, 0)', 'rgb(158, 205, 0)', 'rgb(210, 255, 0)', '#405300'), + WHITE: new LcdColorDef('#ffffff', '#ffffff', 'rgb(241, 246, 242)', 'rgb(229, 239, 244)', '#ffffff', '#000000'), + GRAY: new LcdColorDef('#414141', 'rgb(117, 117, 117)', 'rgb(87, 87, 87)', '#414141', 'rgb(81, 81, 81)', '#ffffff'), + BLACK: new LcdColorDef('#414141', '#666666', '#333333', '#000000', '#333333', '#cccccc'), + GREEN: new LcdColorDef('rgb(33, 67, 67)', 'rgb(33, 67, 67)', 'rgb(29, 58, 58)', 'rgb(28, 57, 57)', 'rgb(23, 46, 46)', 'rgba(0, 185, 165, 255)'), + BLUE2: new LcdColorDef('rgb(0, 68, 103)', 'rgb(8, 109, 165)', 'rgb(0, 72, 117)', 'rgb(0, 72, 117)', 'rgb(0, 68, 103)', 'rgb(111, 182, 228)'), + BLUE_BLACK: new LcdColorDef('rgb(22, 125, 212)', 'rgb(3, 162, 254)', 'rgb(3, 162, 254)', 'rgb(3, 162, 254)', 'rgb(11, 172, 244)', '#000000'), + BLUE_DARKBLUE: new LcdColorDef('rgb(18, 33, 88)', 'rgb(18, 33, 88)', 'rgb(19, 30, 90)', 'rgb(17, 31, 94)', 'rgb(21, 25, 90)', 'rgb(23, 99, 221)'), + BLUE_GRAY: new LcdColorDef('rgb(135, 174, 255)', 'rgb(101, 159, 255)', 'rgb(44, 93, 255)', 'rgb(27, 65, 254)', 'rgb(12, 50, 255)', '#b2b4ed'), + STANDARD: new LcdColorDef('rgb(131, 133, 119)', 'rgb(176, 183, 167)', 'rgb(165, 174, 153)', 'rgb(166, 175, 156)', 'rgb(175, 184, 165)', 'rgb(35, 42, 52)'), + STANDARD_GREEN: new LcdColorDef('#ffffff', 'rgb(219, 230, 220)', 'rgb(179, 194, 178)', 'rgb(153, 176, 151)', 'rgb(114, 138, 109)', '#080C06'), + BLUE_BLUE: new LcdColorDef('rgb(100, 168, 253)', 'rgb(100, 168, 253)', 'rgb(95, 160, 250)', 'rgb(80, 144, 252)', 'rgb(74, 134, 255)', '#002cbb'), + RED_DARKRED: new LcdColorDef('rgb(72, 36, 50)', 'rgb(185, 111, 110)', 'rgb(148, 66, 72)', 'rgb(83, 19, 20)', 'rgb(7, 6, 14)', '#FE8B92'), + DARKBLUE: new LcdColorDef('rgb(14, 24, 31)', 'rgb(46, 105, 144)', 'rgb(19, 64, 96)', 'rgb(6, 20, 29)', 'rgb(8, 9, 10)', '#3DB3FF'), + LILA: new LcdColorDef('rgb(175, 164, 255)', 'rgb(188, 168, 253)', 'rgb(176, 159, 255)', 'rgb(174, 147, 252)', 'rgb(168, 136, 233)', '#076148'), + BLACKRED: new LcdColorDef('rgb(8, 12, 11)', 'rgb(10, 11, 13)', 'rgb(11, 10, 15)', 'rgb(7, 13, 9)', 'rgb(9, 13, 14)', '#B50026'), + DARKGREEN: new LcdColorDef('rgb(25, 85, 0)', 'rgb(47, 154, 0)', 'rgb(30, 101, 0)', 'rgb(30, 101, 0)', 'rgb(25, 85, 0)', '#233123'), + AMBER: new LcdColorDef('rgb(182, 71, 0)', 'rgb(236, 155, 25)', 'rgb(212, 93, 5)', 'rgb(212, 93, 5)', 'rgb(182, 71, 0)', '#593A0A'), + LIGHTBLUE: new LcdColorDef('rgb(125, 146, 184)', 'rgb(197, 212, 231)', 'rgb(138, 155, 194)', 'rgb(138, 155, 194)', 'rgb(125, 146, 184)', '#090051'), + SECTIONS: new LcdColorDef('#b2b2b2', '#ffffff', '#c4c4c4', '#c4c4c4', '#b2b2b2', '#000000') + }; + + var color = { + RED: new ColorDef(new RgbaColor(82, 0, 0, 1), new RgbaColor(158, 0, 19, 1), new RgbaColor(213, 0, 25, 1), new RgbaColor(240, 82, 88, 1), new RgbaColor(255, 171, 173, 1), new RgbaColor(255, 217, 218, 1)), + GREEN: new ColorDef(new RgbaColor(8, 54, 4, 1), new RgbaColor(0, 107, 14, 1), new RgbaColor(15, 148, 0, 1), new RgbaColor(121, 186, 37, 1), new RgbaColor(190, 231, 141, 1), new RgbaColor(234, 247, 218, 1)), + BLUE: new ColorDef(new RgbaColor(0, 11, 68, 1), new RgbaColor(0, 73, 135, 1), new RgbaColor(0, 108, 201, 1), new RgbaColor(0, 141, 242, 1), new RgbaColor(122, 200, 255, 1), new RgbaColor(204, 236, 255, 1)), + ORANGE: new ColorDef(new RgbaColor(118, 83, 30, 1), new RgbaColor(215, 67, 0, 1), new RgbaColor(240, 117, 0, 1), new RgbaColor(255, 166, 0, 1), new RgbaColor(255, 255, 128, 1), new RgbaColor(255, 247, 194, 1)), + YELLOW: new ColorDef(new RgbaColor(41, 41, 0, 1), new RgbaColor(102, 102, 0, 1), new RgbaColor(177, 165, 0, 1), new RgbaColor(255, 242, 0, 1), new RgbaColor(255, 250, 153, 1), new RgbaColor(255, 252, 204, 1)), + CYAN: new ColorDef(new RgbaColor(15, 109, 109, 1), new RgbaColor(0, 109, 144, 1), new RgbaColor(0, 144, 191, 1), new RgbaColor(0, 174, 239, 1), new RgbaColor(153, 223, 249, 1), new RgbaColor(204, 239, 252, 1)), + MAGENTA: new ColorDef(new RgbaColor(98, 0, 114, 1), new RgbaColor(128, 24, 72, 1), new RgbaColor(191, 36, 107, 1), new RgbaColor(255, 48, 143, 1), new RgbaColor(255, 172, 210, 1), new RgbaColor(255, 214, 23, 1)), + WHITE: new ColorDef(new RgbaColor(210, 210, 210, 1), new RgbaColor(220, 220, 220, 1), new RgbaColor(235, 235, 235, 1), new RgbaColor(255, 255, 255, 1), new RgbaColor(255, 255, 255, 1), new RgbaColor(255, 255, 255, 1)), + GRAY: new ColorDef(new RgbaColor(25, 25, 25, 1), new RgbaColor(51, 51, 51, 1), new RgbaColor(76, 76, 76, 1), new RgbaColor(128, 128, 128, 1), new RgbaColor(204, 204, 204, 1), new RgbaColor(243, 243, 243, 1)), + BLACK: new ColorDef(new RgbaColor(0, 0, 0, 1), new RgbaColor(5, 5, 5, 1), new RgbaColor(10, 10, 10, 1), new RgbaColor(15, 15, 15, 1), new RgbaColor(20, 20, 20, 1), new RgbaColor(25, 25, 25, 1)), + RAITH: new ColorDef(new RgbaColor(0, 32, 65, 1), new RgbaColor(0, 65, 125, 1), new RgbaColor(0, 106, 172, 1), new RgbaColor(130, 180, 214, 1), new RgbaColor(148, 203, 242, 1), new RgbaColor(191, 229, 255, 1)), + GREEN_LCD: new ColorDef(new RgbaColor(0, 55, 45, 1), new RgbaColor(15, 109, 93, 1), new RgbaColor(0, 185, 165, 1), new RgbaColor(48, 255, 204, 1), new RgbaColor(153, 255, 227, 1), new RgbaColor(204, 255, 241, 1)), + JUG_GREEN: new ColorDef(new RgbaColor(0, 56, 0, 1), new RgbaColor(32, 69, 36, 1), new RgbaColor(50, 161, 0, 1), new RgbaColor(129, 206, 0, 1), new RgbaColor(190, 231, 141, 1), new RgbaColor(234, 247, 218, 1)) + }; + + var ledColor = { + RED_LED: new LedColorDef('#FF9A89', '#FF9A89', '#FF3300', '#FF8D70', '#7E1C00', '#7E1C00', '#641B00'), + GREEN_LED: new LedColorDef('#9AFF89', '#9AFF89', '#59FF2A', '#A5FF00', '#1C7E00', '#1C7E00', '#1B6400'), + BLUE_LED: new LedColorDef('#899AFF', '#899AFF', '#0033FF', '#708DFF', '#001C7E', '#001C7E', '#001B64'), + ORANGE_LED: new LedColorDef('#FEA23F', '#FEA23F', '#FD6C00', '#FD6C00', '#592800', '#592800', '#421F00'), + YELLOW_LED: new LedColorDef('#FFFF62', '#FFFF62', '#FFFF00', '#FFFF00', '#6B6D00', '#6B6D00', '#515300'), + CYAN_LED: new LedColorDef('#00FFFF', '#00FFFF', '#1BC3C3', '#00FFFF', '#083B3B', '#083B3B', '#052727'), + MAGENTA_LED: new LedColorDef('#D300FF', '#D300FF', '#8600CB', '#C300FF', '#38004B', '#38004B', '#280035') + }; + + var gaugeType = { + TYPE1: new GaugeTypeDef('type1'), + TYPE2: new GaugeTypeDef('type2'), + TYPE3: new GaugeTypeDef('type3'), + TYPE4: new GaugeTypeDef('type4'), + TYPE5: new GaugeTypeDef('type5') + }; + + var orientation = { + NORTH: new OrientationDef('north'), + SOUTH: new OrientationDef('south'), + EAST: new OrientationDef('east'), + WEST: new OrientationDef('west') + }; + + var knobType = { + STANDARD_KNOB: new KnobTypeDef('standardKnob'), + METAL_KNOB: new KnobTypeDef('metalKnob') + }; + + var knobStyle = { + BLACK: new KnobStyleDef('black'), + BRASS: new KnobStyleDef('brass'), + SILVER: new KnobStyleDef('silver') + }; + + var frameDesign = { + BLACK_METAL: new FrameDesignDef('blackMetal'), + METAL: new FrameDesignDef('metal'), + SHINY_METAL: new FrameDesignDef('shinyMetal'), + BRASS: new FrameDesignDef('brass'), + STEEL: new FrameDesignDef('steel'), + CHROME: new FrameDesignDef('chrome'), + GOLD: new FrameDesignDef('gold'), + ANTHRACITE: new FrameDesignDef('anthracite'), + TILTED_GRAY: new FrameDesignDef('tiltedGray'), + TILTED_BLACK: new FrameDesignDef('tiltedBlack'), + GLOSSY_METAL: new FrameDesignDef('glossyMetal') + }; + + var pointerType = { + TYPE1: new PointerTypeDef('type1'), + TYPE2: new PointerTypeDef('type2'), + TYPE3: new PointerTypeDef('type3'), + TYPE4: new PointerTypeDef('type4'), + TYPE5: new PointerTypeDef('type5'), + TYPE6: new PointerTypeDef('type6'), + TYPE7: new PointerTypeDef('type7'), + TYPE8: new PointerTypeDef('type8'), + TYPE9: new PointerTypeDef('type9'), + TYPE10: new PointerTypeDef('type10'), + TYPE11: new PointerTypeDef('type11'), + TYPE12: new PointerTypeDef('type12'), + TYPE13: new PointerTypeDef('type13'), + TYPE14: new PointerTypeDef('type14'), + TYPE15: new PointerTypeDef('type15'), + TYPE16: new PointerTypeDef('type16') + }; + + var foregroundType = { + TYPE1: new ForegroundTypeDef('type1'), + TYPE2: new ForegroundTypeDef('type2'), + TYPE3: new ForegroundTypeDef('type3'), + TYPE4: new ForegroundTypeDef('type4'), + TYPE5: new ForegroundTypeDef('type5') + }; + + var labelNumberFormat = { + STANDARD: new LabelNumberFormatDef('standard'), + FRACTIONAL: new LabelNumberFormatDef('fractional'), + SCIENTIFIC: new LabelNumberFormatDef('scientific') + }; + + var tickLabelOrientation = { + NORMAL: new TickLabelOrientationDef('normal'), + HORIZONTAL: new TickLabelOrientationDef('horizontal'), + TANGENT: new TickLabelOrientationDef('tangent') + }; + + var trendState = { + UP: new TrendStateDef('up'), + STEADY: new TrendStateDef('steady'), + DOWN: new TrendStateDef('down'), + OFF: new TrendStateDef('off') + }; + + //********************************** E X P O R T F U N C T I O N S ******************************************* + return { + // Components EXTERNAL : INTERNAL + Radial : radial, + RadialBargraph : radialBargraph, + DisplaySingle: displaySingle, + WindDirection : windDirection, + Led : led, + Odometer: odometer, + + // Images + drawFrame : drawRadialFrameImage, + drawBackground : drawRadialBackgroundImage, + drawForeground : drawRadialForegroundImage, + + // Tools + rgbaColor : RgbaColor, + ConicalGradient : ConicalGradient, + setAlpha : setAlpha, + getColorFromFraction : getColorFromFraction, + gradientWrapper : GradientWrapper, + + // Constants + BackgroundColor : backgroundColor, + LcdColor : lcdColor, + ColorDef : color, + LedColor : ledColor, + GaugeType : gaugeType, + Orientation: orientation, + FrameDesign : frameDesign, + PointerType : pointerType, + ForegroundType : foregroundType, + KnobType : knobType, + KnobStyle: knobStyle, + LabelNumberFormat: labelNumberFormat, + TickLabelOrientation: tickLabelOrientation, + TrendState: trendState, + + // Other + Section : section + }; +}()); diff --git a/other-scripts/Steel-Gauges/web_server/script/src/steelseries.min.js b/other-scripts/Steel-Gauges/web_server/script/src/steelseries.min.js new file mode 100644 index 0000000..4fe248e --- /dev/null +++ b/other-scripts/Steel-Gauges/web_server/script/src/steelseries.min.js @@ -0,0 +1,25 @@ +/*! + * Name : steelseries.js + * Authors : Gerrit Grunwald, Mark Crossley + * Last modified : 01.12.2015 + * Revision : 0.14.16 + * + * Copyright (c) 2011, Gerrit Grunwald, Mark Crossley + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * # Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * # Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +var steelseries=function(){function u(n,t){var i="#"===n.charAt(0)?n.substring(1,7):n,r=parseInt(i.substring(0,2),16),u=parseInt(i.substring(2,4),16),f=parseInt(i.substring(4,6),16);return"rgba("+r+","+u+","+f+","+t+")"}function kt(t,i,r,u,f){var c=1/255,e=t.getRed(),o=t.getGreen(),s=t.getBlue(),h=t.getAlpha(),p=i.getRed()-e,w=i.getGreen()-o,b=i.getBlue()-s,k=i.getAlpha()*c-h*c,l=p/r*u,a=w/r*u,v=b/r*u,y=k/r*u;return f=f||!1,f?[(e+l).toFixed(0),(o+a).toFixed(0),(s+v).toFixed(0),h+y]:new n((e+l).toFixed(0),(o+a).toFixed(0),(s+v).toFixed(0),h+y)}function gi(n,t,i){return{start:n,stop:t,color:i}}function k(n,t){var r=Math.floor(Math.log10(n)),i=n/Math.pow(10,r),u;return u=t?1.5>i?1:3>i?2:7>i?5:10:1>=i?1:2>=i?2:5>=i?5:10,u*Math.pow(10,r)}function dt(n,t,i,r,u,f){var e=t+r,o=i+u;n.beginPath();n.moveTo(t+f,i);n.lineTo(e-f,i);n.quadraticCurveTo(e,i,e,i+f);n.lineTo(e,i+u-f);n.quadraticCurveTo(e,o,e-f,o);n.lineTo(t+f,o);n.quadraticCurveTo(t,o,t,o-f);n.lineTo(t,i+f);n.quadraticCurveTo(t,i,t+f,i);n.closePath()}function r(n,t){var i=d.createElement("canvas");return i.width=n,i.height=t,i}function ii(n,t,i){var r=d.createElement("canvas");return r.width=n,r.height=t,i(r.getContext("2d")),r}function rt(n){var t,i=ii(1,1,function(t){t.fillStyle=n;t.beginPath();t.rect(0,0,1,1);t.fill()});return t=i.getContext("2d").getImageData(0,0,2,2).data,[t[0],t[1],t[2],t[3]]}function ei(t){var u,f,e,o,s,r=rt(t),i=new n(r[0],r[1],r[2],r[3]);return u=oi(i,.32),f=oi(i,.62),e=ri(i,.84),o=ri(i,.94),s=ri(i,1),new y(u,f,i,e,o,s)}function st(n,t,i){var r,u,f,h=Math.floor(n*6),c=n*6-h,e=i*(1-t),o=i*(1-c*t),s=i*(1-(1-c)*t);switch(h%6){case 0:r=i;u=s;f=e;break;case 1:r=o;u=i;f=e;break;case 2:r=e;u=i;f=s;break;case 3:r=e;u=o;f=i;break;case 4:r=s;u=e;f=i;break;case 5:r=i;u=e;f=o}return[Math.floor(r*255),Math.floor(u*255),Math.floor(f*255)]}function ot(n,t,i){var e,r,u,o,s,f;if(n=n/255,t=t/255,i=i/255,r=Math.max(n,t,i),e=Math.min(n,t,i),s=r,f=r-e,o=r===0?0:f/r,r===e)u=0;else{switch(r){case n:u=(t-i)/f+(tt?t:n}function oi(t,i){var r=Math.floor(t.getRed()*(1-i)),u=Math.floor(t.getGreen()*(1-i)),f=Math.floor(t.getBlue()*(1-i));return r=p(r,255),u=p(u,255),f=p(f,255),new n(r,u,f,t.getAlpha())}function ri(t,i){var r=Math.round(t.getRed()*(1+i)),u=Math.round(t.getGreen()*(1+i)),f=Math.round(t.getBlue()*(1+i));return r=p(r,255),u=p(u,255),f=p(f,255),new n(r,u,f,t.getAlpha())}function nr(n,t,i){var r,u;if(i<=t)throw"Rotary bounds are of negative or zero size";return r=i-t,u=Math.floor((n-t)/r),n-u*r}function si(n,t){return nr(t-n,-180,180)}function ht(n){var t=typeof n=="string"||n instanceof String?d.getElementById(n):n;return t.getContext("2d")}var i=Math.PI*.5,t=Math.PI*2,o=Math.PI,c=Math.PI/180,pt=180/Math.PI,d=document,wt="LCDMono2Ultra,Arial,Verdana,sans-serif",s="Arial,Verdana,sans-serif",hi=function(n,u){var yi;u=u||{};var vt=undefined===u.gaugeType?steelseries.GaugeType.TYPE4:u.gaugeType,f=undefined===u.size?0:u.size,h=undefined===u.minValue?0:u.minValue,b=undefined===u.maxValue?h+100:u.maxValue,ve=undefined===u.niceScale?!0:u.niceScale,gt=undefined===u.threshold?(b-h)/2+h:u.threshold,ti=undefined===u.thresholdRising?!0:u.thresholdRising,ci=undefined===u.section?null:u.section,li=undefined===u.area?null:u.area,vu=undefined===u.titleString?"":u.titleString,yu=undefined===u.unitString?"":u.unitString,pu=undefined===u.frameDesign?steelseries.FrameDesign.METAL:u.frameDesign,wu=undefined===u.frameVisible?!0:u.frameVisible,ai=undefined===u.backgroundColor?steelseries.BackgroundColor.DARK_GRAY:u.backgroundColor,bu=undefined===u.backgroundVisible?!0:u.backgroundVisible,oi=undefined===u.pointerType?steelseries.PointerType.TYPE1:u.pointerType,ku=undefined===u.pointerColor?steelseries.ColorDef.RED:u.pointerColor,ye=undefined===u.knobType?steelseries.KnobType.STANDARD_KNOB:u.knobType,vi=undefined===u.knobStyle?steelseries.KnobStyle.SILVER:u.knobStyle,di=undefined===u.lcdColor?steelseries.LcdColor.STANDARD:u.lcdColor,iu=undefined===u.lcdVisible?!0:u.lcdVisible,du=undefined===u.lcdDecimals?2:u.lcdDecimals,pe=undefined===u.digitalFont?!1:u.digitalFont,gu=undefined===u.fractionalScaleDecimals?1:u.fractionalScaleDecimals,ru=undefined===u.ledColor?steelseries.LedColor.RED_LED:u.ledColor,uu=undefined===u.ledVisible?!0:u.ledVisible,fu=undefined===u.userLedColor?steelseries.LedColor.GREEN_LED:u.userLedColor,eu=undefined===u.userLedVisible?!1:u.userLedVisible,nf=undefined===u.thresholdVisible?!0:u.thresholdVisible,ou=undefined===u.minMeasuredValueVisible?!1:u.minMeasuredValueVisible,su=undefined===u.maxMeasuredValueVisible?!1:u.maxMeasuredValueVisible,tf=undefined===u.foregroundType?steelseries.ForegroundType.TYPE1:u.foregroundType,rf=undefined===u.foregroundVisible?!0:u.foregroundVisible,uf=undefined===u.labelNumberFormat?steelseries.LabelNumberFormat.STANDARD:u.labelNumberFormat,rr=undefined===u.playAlarm?!1:u.playAlarm,ff=undefined===u.alarmSound?!1:u.alarmSound,we=undefined===u.customLayer?null:u.customLayer,be=undefined===u.tickLabelOrientation?vt===steelseries.GaugeType.TYPE1?steelseries.TickLabelOrientation.TANGENT:steelseries.TickLabelOrientation.NORMAL:u.tickLabelOrientation,hu=undefined===u.trendVisible?!1:u.trendVisible,lr=undefined===u.trendColors?[steelseries.LedColor.RED_LED,steelseries.LedColor.GREEN_LED,steelseries.LedColor.CYAN_LED]:u.trendColors,ar=undefined===u.useOdometer?!1:u.useOdometer,si=undefined===u.odometerParams?{}:u.odometerParams,ke=undefined===u.odometerUseValue?!1:u.odometerUseValue,ef=undefined===u.fullScaleDeflectionTime?2.5:u.fullScaleDeflectionTime,e=ht(n);f===0&&(f=Math.min(e.canvas.width,e.canvas.height));e.canvas.width=f;e.canvas.height=f;rr&&ff!==!1&&(yi=d.createElement("audio"),yi.setAttribute("src",ff),yi.setAttribute("preload","auto"));var p=h,vr=h,of=this,pi=b,wi=h,ut=!1,yr=!1,sf=0,cu=0,bi,ki=!1,hf=steelseries.TrendState.OFF,pr=f*.06,wr=f*.29,br=f*.36,gi,yt,kr,pt,kt,lu=yt+(p-h)*kt,y=f,rt=f,st=y/2,lt=rt/2,ii=f*.093457,de=.6*y,ge=.4*rt,no=vt===steelseries.GaugeType.TYPE3?.6*y:st-ii/2,to=vt===steelseries.GaugeType.TYPE3?.72*rt:.75*rt,au=Math.floor(y/10),io=au+"px "+s,ro=au+"px "+wt,cf=rt*.13,ur=y*.4,lf=(y-ur)/2,af=rt*.57,vf,uo=rt*.61,yf=y*.006,pf=!1,dr=h,gr=b,fr=b-h,ri=gr-dr,nu=0,ui=0,nr=10,wf=10,fo=function(){ve?(fr=k(b-h,!1),ui=k(fr/(wf-1),!0),dr=Math.floor(h/ui)*ui,gr=Math.ceil(b/ui)*ui,nu=k(ui/(nr-1),!0),h=dr,b=gr,ri=b-h):(fr=b-h,dr=h,gr=b,ri=fr,ui=k(fr/(wf-1),!0),nu=k(ui/(nr-1),!0));switch(vt.type){case"type1":gi=0;yt=o;kr=i;pt=i;kt=pt/ri;break;case"type2":gi=0;yt=o;kr=i;pt=o;kt=pt/ri;break;case"type3":gi=0;yt=i;kr=0;pt=1.5*o;kt=pt/ri;break;case"type4":default:gi=60*c;yt=i+gi/2;kr=0;pt=t-gi;kt=pt/ri}lu=yt+(p-h)*kt},er=r(f,f),bf=er.getContext("2d"),or=r(f,f),at=or.getContext("2d"),kf,tr=r(ii,ii),df=tr.getContext("2d"),hi=r(ii,ii),gf=hi.getContext("2d"),ir=hi,ei=r(ii,ii),ne=ei.getContext("2d"),ni=r(ii,ii),te=ni.getContext("2d"),dt=ni,ie=r(Math.ceil(f*.028037),Math.ceil(f*.028037)),eo=ie.getContext("2d"),re=r(Math.ceil(f*.028037),Math.ceil(f*.028037)),oo=re.getContext("2d"),sr=r(f,f),ue=sr.getContext("2d"),hr=r(f,f),fe=hr.getContext("2d"),ee,oe,se,he,ce,tu,le;ar&&iu&&(tu=r(10,10),le=tu.getContext("2d"));var so=function(n,t){n.restore();n.save();n.textAlign="right";n.strokeStyle=di.textColor;n.fillStyle=di.textColor;(di===steelseries.LcdColor.STANDARD||di===steelseries.LcdColor.STANDARD_GREEN)&&(n.shadowColor="gray",n.shadowOffsetX=y*.007,n.shadowOffsetY=y*.007,n.shadowBlur=y*.007);n.font=pe?ro:io;n.fillText(t.toFixed(du),lf+ur-ur*.05,af+cf*.5+au*.38,ur*.9);n.restore()},ho=function(n){n.save();"type1"===vt.type&&n.drawImage(l(Math.ceil(rt*.037383),steelseries.KnobType.STANDARD_KNOB,vi),y*.523364,rt*.130841);("type1"===vt.type||"type2"===vt.type)&&n.drawImage(l(Math.ceil(rt*.037383),steelseries.KnobType.STANDARD_KNOB,vi),y*.130841,rt*.514018);("type2"===vt.type||"type3"===vt.type)&&n.drawImage(l(Math.ceil(rt*.037383),steelseries.KnobType.STANDARD_KNOB,vi),y*.831775,rt*.514018);"type3"===vt.type&&n.drawImage(l(Math.ceil(rt*.037383),steelseries.KnobType.STANDARD_KNOB,vi),y*.523364,rt*.831775);"type4"===vt.type&&(n.drawImage(l(Math.ceil(rt*.037383),steelseries.KnobType.STANDARD_KNOB,vi),y*.336448,rt*.803738),n.drawImage(l(Math.ceil(rt*.037383),steelseries.KnobType.STANDARD_KNOB,vi),y*.626168,rt*.803738));n.restore()},co=function(){var t=d.createElement("canvas"),n,i;return t.width=Math.ceil(f*.046728),t.height=Math.ceil(t.width*.9),n=t.getContext("2d"),n.save(),i=n.createLinearGradient(0,.1,0,t.height*.9),i.addColorStop(0,"#520000"),i.addColorStop(.3,"#fc1d00"),i.addColorStop(.59,"#fc1d00"),i.addColorStop(1,"#520000"),n.fillStyle=i,n.beginPath(),n.moveTo(t.width*.5,.1),n.lineTo(t.width*.9,t.height*.9),n.lineTo(t.width*.1,t.height*.9),n.lineTo(t.width*.5,.1),n.closePath(),n.fill(),n.strokeStyle="#FFFFFF",n.stroke(),n.restore(),t},ae=function(n,t,i,r,u){if(tb&&(t=b),ib&&(i=b),!(t>=i)){n.save();n.strokeStyle=r;n.fillStyle=r;n.lineWidth=y*.035;var f=pt/ri*t-pt/ri*h,e=f+(i-t)/(ri/pt);n.translate(st,lt);n.rotate(yt);n.beginPath();u?(n.moveTo(0,0),n.arc(0,0,y*.365-n.lineWidth/2,f,e,!1)):n.arc(0,0,y*.365,f,e,!1);u?(n.moveTo(0,0),n.fill()):n.stroke();n.translate(-st,-lt);n.restore()}},lo=function(n,t){var w=Math.ceil(y*.04),f=yt,r=kt*nu,u,e=h,c=nr-1,a=y*.38,k=y*.35,d=y*.355,g=y*.36,p=y*.3,l=y*.1,nt=nr/2,tt=parseFloat(b.toFixed(2)),v;for(ai.labelColor.setAlpha(1),n.save(),n.textAlign="center",n.textBaseline="middle",n.font=w+"px "+s,n.strokeStyle=ai.labelColor.getRgbaColor(),n.fillStyle=ai.labelColor.getRgbaColor(),n.translate(st,lt),n.rotate(yt),(vt.type==="type1"||vt.type==="type2")&&(l=y*.04),v=h;parseFloat(v.toFixed(2))<=tt;v+=nu){if(u=r+i,c++,c===nr){n.lineWidth=1.5;n.beginPath();n.moveTo(a,0);n.lineTo(k,0);n.closePath();n.stroke();n.save();n.translate(p,0);switch(be.type){case"horizontal":u=-f;break;case"tangent":u=f<=i+o?o:0;break;case"normal":default:u=i}n.rotate(u);switch(t.format){case"fractional":n.fillText(e.toFixed(gu),0,0,l);break;case"scientific":n.fillText(e.toPrecision(2),0,0,l);break;case"standard":default:n.fillText(e.toFixed(0),0,0,l)}n.translate(-p,0);n.restore();e+=ui;c=0;n.rotate(r);f+=r;continue}0==nr%2&&c===nt?(n.lineWidth=1,n.beginPath(),n.moveTo(a,0),n.lineTo(d,0),n.closePath(),n.stroke()):(n.lineWidth=.5,n.beginPath(),n.moveTo(a,0),n.lineTo(g,0),n.closePath(),n.stroke());n.rotate(r);f+=r}n.translate(-st,-lt);n.restore()},ot=function(n){var t,r,e;n=n||{};var o=undefined===n.frame?!1:n.frame,u=undefined===n.background?!1:n.background,s=undefined===n.led?!1:n.led,c=undefined===n.userLed?!1:n.userLed,l=undefined===n.pointer?!1:n.pointer,v=undefined===n.foreground?!1:n.foreground,b=undefined===n.trend?!1:n.trend,k=undefined===n.odo?!1:n.odo;if(pf=!0,fo(),o&&wu&&g(bf,pu,st,lt,y,rt),u&&bu&&(nt(at,ai,st,lt,y,rt),bt(at,we,st,lt,y,rt)),s&&(df.drawImage(a(Math.ceil(f*.093457),1,ru),0,0),gf.drawImage(a(Math.ceil(f*.093457),0,ru),0,0)),c&&(ne.drawImage(a(Math.ceil(f*.093457),1,fu),0,0),te.drawImage(a(Math.ceil(f*.093457),0,fu),0,0)),ou&&eo.drawImage(et(Math.ceil(f*.028037),steelseries.ColorDef.BLUE.dark.getRgbaColor(),!0,!0),0,0),su&&oo.drawImage(et(Math.ceil(f*.028037),steelseries.ColorDef.RED.medium.getRgbaColor(),!0),0,0),u&&bu){if(ho(at),null!==ci&&0b?b:n;return p!==t&&(p=t,p>wi&&(wi=p),p=gt&&!ut&&ti||p<=gt&&!ut&&!ti?(ut=!0,cr(ut),rr&&yi.play()):(pgt&&ut&&!ti)&&(ut=!1,cr(ut),rr&&yi.pause()),this.repaint()),this},this.getValue=function(){return p},this.setOdoValue=function(n){n=parseFloat(n);var t=n<0?0:n;return vr!==t&&(vr=t,this.repaint()),this},this.getOdoValue=function(){return vr},this.setValueAnimated=function(n,t){n=parseFloat(n);var r=nb?b:n,u=this,i;return p!==r&&(undefined!==bi&&bi.isPlaying&&bi.stop(),i=ef*Math.abs(r-p)/(b-h),i=Math.max(i,ef/5),bi=new Tween({},"",Tween.regularEaseInOut,p,r,i),bi.onMotionChanged=function(n){p=n.target._pos;p>=gt&&!ut&&ti||p<=gt&&!ut&&!ti?(ut=!0,cr(ut),rr&&yi.play()):(pgt&&ut&&!ti)&&(ut=!1,cr(ut),rr&&yi.pause());p>wi&&(wi=p);pb?b:n;return wi=t,this.repaint(),this},this.setMinMeasuredValue=function(n){n=parseFloat(n);var t=nb?b:n;return pi=t,this.repaint(),this},this.setTitleString=function(n){return vu=n,ct({background:!0}),ot({background:!0}),this.repaint(),this},this.setUnitString=function(n){return yu=n,ct({background:!0}),ot({background:!0}),this.repaint(),this},this.setMinValue=function(n){return h=parseFloat(n),ct({frame:!0,background:!0}),ot({frame:!0,background:!0}),this.repaint(),this},this.getMinValue=function(){return h},this.setMaxValue=function(n){return b=parseFloat(n),ct({frame:!0,background:!0}),ot({frame:!0,background:!0}),this.repaint(),this},this.getMaxValue=function(){return b},this.setThreshold=function(n){n=parseFloat(n);var t=nb?b:n;return gt=t,ct({background:!0}),ot({background:!0}),this.repaint(),this},this.setArea=function(n){return li=n,ct({background:!0,foreground:!0}),ot({background:!0,foreground:!0}),this.repaint(),this},this.setSection=function(n){return ci=n,ct({background:!0,foreground:!0}),ot({background:!0,foreground:!0}),this.repaint(),this},this.setThresholdVisible=function(n){return nf=!!n,this.repaint(),this},this.setThresholdRising=function(n){return ti=!!n,ut=!ut,cr(ut),this.repaint(),this},this.setLcdDecimals=function(n){return du=parseInt(n,10),this.repaint(),this},this.setFrameDesign=function(n){return ct({frame:!0}),pu=n,ot({frame:!0}),this.repaint(),this},this.setBackgroundColor=function(n){return ct({background:!0,pointer:oi.type==="type2"||oi.type==="type13"?!0:!1}),ai=n,ot({background:!0,pointer:oi.type==="type2"||oi.type==="type13"?!0:!1}),this.repaint(),this},this.setForegroundType=function(n){return ct({foreground:!0}),tf=n,ot({foreground:!0}),this.repaint(),this},this.setPointerType=function(n){return ct({pointer:!0,foreground:!0}),oi=n,ot({pointer:!0,foreground:!0}),this.repaint(),this},this.setPointerColor=function(n){return ct({pointer:!0}),ku=n,ot({pointer:!0}),this.repaint(),this},this.setLedColor=function(n){return ct({led:!0}),ru=n,ot({led:!0}),this.repaint(),this},this.setUserLedColor=function(n){return ct({userLed:!0}),fu=n,ot({userLed:!0}),this.repaint(),this},this.toggleUserLed=function(){return dt=dt===ei?ni:ei,this.repaint(),this},this.setUserLedOnOff=function(n){return dt=!0===n?ei:ni,this.repaint(),this},this.blinkUserLed=function(n){return n?yr||(yo(!0),yr=!0):yr&&(clearInterval(cu),yr=!1),this},this.setLedVisible=function(n){return uu=!!n,this.repaint(),this},this.setUserLedVisible=function(n){return eu=!!n,this.repaint(),this},this.setLcdColor=function(n){return di=n,ct({background:!0}),ot({background:!0}),this.repaint(),this},this.setTrend=function(n){return hf=n,this.repaint(),this},this.setTrendVisible=function(n){return hu=!!n,this.repaint(),this},this.setFractionalScaleDecimals=function(n){return gu=parseInt(n,10),ct({background:!0}),ot({background:!0}),this.repaint(),this},this.setLabelNumberFormat=function(n){return uf=n,ct({background:!0}),ot({background:!0}),this.repaint(),this},this.repaint=function(){if(pf||ot({frame:!0,background:!0,led:!0,userLed:!0,pointer:!0,trend:!0,foreground:!0,odo:!0}),e.clearRect(0,0,f,f),wu&&e.drawImage(er,0,0),e.drawImage(or,0,0),iu&&(ar?(ce.setValue(ke?p:vr),e.drawImage(tu,vf,uo)):so(e,p)),uu&&e.drawImage(ir,de,ge),eu&&e.drawImage(dt,no,to),hu)switch(hf.state){case"up":e.drawImage(ee,wr,br);break;case"steady":e.drawImage(oe,wr,br);break;case"down":e.drawImage(se,wr,br);break;case"off":e.drawImage(he,wr,br)}ou&&(e.save(),e.translate(st,lt),e.rotate(yt+i+(pi-h)*kt),e.translate(-st,-lt),e.drawImage(ie,e.canvas.width*.4865,e.canvas.height*.105),e.restore());su&&(e.save(),e.translate(st,lt),e.rotate(yt+i+(wi-h)*kt),e.translate(-st,-lt),e.drawImage(re,e.canvas.width*.4865,e.canvas.height*.105),e.restore());lu=yt+i+(p-h)*kt;e.save();e.translate(st,lt);e.rotate(lu);e.translate(-st,-lt);e.shadowColor="rgba(0, 0, 0, 0.8)";e.shadowOffsetX=e.shadowOffsetY=yf;e.shadowBlur=yf*2;e.drawImage(sr,0,0);e.restore();rf&&e.drawImage(hr,0,0);ki=!1},this.repaint(),this},ci=function(n,u){var li;u=u||{};var hi=undefined===u.gaugeType?steelseries.GaugeType.TYPE4:u.gaugeType,h=undefined===u.size?0:u.size,f=undefined===u.minValue?0:u.minValue,l=undefined===u.maxValue?f+100:u.maxValue,re=undefined===u.niceScale?!0:u.niceScale,gt=undefined===u.threshold?(l-f)/2+f:u.threshold,ni=undefined===u.thresholdRising?!0:u.thresholdRising,ci=undefined===u.section?null:u.section,su=undefined===u.useSectionColors?!1:u.useSectionColors,hu=undefined===u.titleString?"":u.titleString,cu=undefined===u.unitString?"":u.unitString,lu=undefined===u.frameDesign?steelseries.FrameDesign.METAL:u.frameDesign,au=undefined===u.frameVisible?!0:u.frameVisible,yi=undefined===u.backgroundColor?steelseries.BackgroundColor.DARK_GRAY:u.backgroundColor,vu=undefined===u.backgroundVisible?!0:u.backgroundVisible,sr=undefined===u.valueColor?steelseries.ColorDef.RED:u.valueColor,pi=undefined===u.lcdColor?steelseries.LcdColor.STANDARD:u.lcdColor,yu=undefined===u.lcdVisible?!0:u.lcdVisible,pu=undefined===u.lcdDecimals?2:u.lcdDecimals,ue=undefined===u.digitalFont?!1:u.digitalFont,wu=undefined===u.fractionalScaleDecimals?1:u.fractionalScaleDecimals,fe=undefined===u.customLayer?null:u.customLayer,dr=undefined===u.ledColor?steelseries.LedColor.RED_LED:u.ledColor,gr=undefined===u.ledVisible?!0:u.ledVisible,nu=undefined===u.userLedColor?steelseries.LedColor.GREEN_LED:u.userLedColor,tu=undefined===u.userLedVisible?!1:u.userLedVisible,bu=undefined===u.labelNumberFormat?steelseries.LabelNumberFormat.STANDARD:u.labelNumberFormat,ku=undefined===u.foregroundType?steelseries.ForegroundType.TYPE1:u.foregroundType,du=undefined===u.foregroundVisible?!0:u.foregroundVisible,gi=undefined===u.playAlarm?!1:u.playAlarm,gu=undefined===u.alarmSound?!1:u.alarmSound,nr=undefined===u.valueGradient?null:u.valueGradient,nf=undefined===u.useValueGradient?!1:u.useValueGradient,ee=undefined===u.tickLabelOrientation?hi===steelseries.GaugeType.TYPE1?steelseries.TickLabelOrientation.TANGENT:steelseries.TickLabelOrientation.NORMAL:u.tickLabelOrientation,iu=undefined===u.trendVisible?!1:u.trendVisible,hr=undefined===u.trendColors?[steelseries.LedColor.RED_LED,steelseries.LedColor.GREEN_LED,steelseries.LedColor.CYAN_LED]:u.trendColors,tf=undefined===u.fullScaleDeflectionTime?2.5:u.fullScaleDeflectionTime,p=ht(n);h===0&&(h=Math.min(p.canvas.width,p.canvas.height));p.canvas.width=h;p.canvas.height=h;gi&&gu!==!1&&(li=d.createElement("audio"),li.setAttribute("src",gu),li.setAttribute("preload","auto"));var ft=f,vt=l-f,rt=!1,rf=0,cr=!1,ru=0,ai,uf=this,vi=!1,at,ot,wi,ui,b,ti,kt,oe,bi=[],lr=!1,uu=!1,e=h,st=h,et=e/2,ct=st/2,fu=Math.floor(e/10),se=fu+"px "+s,he=fu+"px "+wt,eu=st*.13,tr=e*.4,ff=(e-tr)/2,ef=st/2-eu/2,ce=e*.116822,le=e*.485981,y=Math.ceil(h*.093457),of=e*.53,sf=st*.61,ae=hi===steelseries.GaugeType.TYPE3?.7*e:et-y/2,ve=hi===steelseries.GaugeType.TYPE3?.61*st:.75*st,hf=steelseries.TrendState.OFF,ar=h*.06,vr=h*.38,yr=h*.57;switch(hi.type){case"type1":at=0;ot=o;wi=0;ui=i;b=i;ti=b*pt;kt=b/vt;break;case"type2":at=0;ot=o;wi=0;ui=i;b=o;ti=b*pt;kt=b/vt;break;case"type3":at=0;ot=i;wi=-i;ui=0;b=1.5*o;ti=b*pt;kt=b/vt;break;case"type4":default:at=60*c;ot=i+at/2;wi=-t/6;ui=0;b=t-at;ti=b*pt;kt=b/vt}var ir=r(h,h),cf=ir.getContext("2d"),rr=r(h,h),oi=rr.getContext("2d"),lf,ur=r(Math.ceil(h*.060747),Math.ceil(h*.023364)),ou=ur.getContext("2d"),ki=r(y,y),af=ki.getContext("2d"),si=r(y,y),vf=si.getContext("2d"),di=si,ii=r(y,y),yf=ii.getContext("2d"),dt=r(y,y),pf=dt.getContext("2d"),yt=dt,ye,fr=r(h,h),wf=fr.getContext("2d"),bf,kf,df,gf,ne=!1,pr=f,wr=l,er=l-f;vt=wr-pr;var br=0,ri=0,kr=10,te=10,pe=function(){re?(er=k(l-f,!1),ri=k(er/(te-1),!0),pr=Math.floor(f/ri)*ri,wr=Math.ceil(l/ri)*ri,br=k(ri/(kr-1),!0),f=pr,l=wr,vt=l-f):(er=l-f,pr=f,wr=l,vt=er,ri=k(er/(te-1),!0),br=k(ri/(kr-1),!0));switch(hi.type){case"type1":at=0;ot=o;ui=i;b=i;kt=b/vt;break;case"type2":at=0;ot=o;ui=i;b=o;kt=b/vt;break;case"type3":at=0;ot=i;ui=0;b=1.5*o;kt=b/vt;break;case"type4":default:at=60*c;ot=i+at/2;ui=0;b=t-at;kt=b/vt}oe=ot+(ft-f)*kt},ut=function(n){var t;n=n||{};var r=undefined===n.frame?!1:n.frame,i=undefined===n.background?!1:n.background,u=undefined===n.led?!1:n.led,o=undefined===n.userLed?!1:n.userLed,s=undefined===n.value?!1:n.value,h=undefined===n.foreground?!1:n.foreground,c=undefined===n.trend?!1:n.trend;if(ne=!0,pe(),r&&au&&g(cf,lu,et,ct,e,st),i&&vu&&(nt(oi,yi,et,ct,e,st),bt(oi,fe,et,ct,e,st)),u&&(af.drawImage(a(y,1,dr),0,0),vf.drawImage(a(y,0,dr),0,0),ye=oi.getImageData(of,sf,y,y)),o&&(yf.drawImage(a(Math.ceil(y),1,nu),0,0),pf.drawImage(a(Math.ceil(y),0,nu),0,0)),i&&we(oi),i&&vu&&(ke(oi,bu),fi(oi,e,st,hu,cu,yi,!0,!0)),i&&yu&&(lf=it(tr,eu,pi),oi.drawImage(lf,ff,ef)),lr=!1,su&&null!==ci&&0l?l:n;return ft!==t&&(ft=t,ft>=gt&&!rt&&ni||ft<=gt&&!rt&&!ni?(rt=!0,or(rt),gi&&li.play()):(ftgt&&rt&&!ni)&&(rt=!1,or(rt),gi&&li.pause()),this.repaint()),this},this.getValue=function(){return ft},this.setValueAnimated=function(n,t){n=parseFloat(n);var r=nl?l:n,u=this,i;return ft!==r&&(undefined!==ai&&ai.isPlaying&&ai.stop(),i=tf*Math.abs(r-ft)/(l-f),i=Math.max(i,tf/5),ai=new Tween({},"",Tween.regularEaseInOut,ft,r,i),ai.onMotionChanged=function(n){ft=n.target._pos;ft>=gt&&!rt&&ni||ft<=gt&&!rt&&!ni?(rt=!0,or(rt),gi&&li.play()):(ftgt&&rt&&!ni)&&(rt=!1,or(rt),gi&&li.pause());vi||(vi=!0,v(u.repaint))},t&&typeof t=="function"&&(ai.onMotionFinished=t),ai.start()),this},this.setFrameDesign=function(n){return lt({frame:!0}),lu=n,ut({frame:!0}),this.repaint(),this},this.setBackgroundColor=function(n){return lt({background:!0,led:!0}),yi=n,ut({background:!0,led:!0}),this.repaint(),this},this.setForegroundType=function(n){return lt({foreground:!0}),ku=n,ut({foreground:!0}),this.repaint(),this},this.setValueColor=function(n){return lt({value:!0}),sr=n,ut({value:!0}),this.repaint(),this},this.setLedColor=function(n){return lt({led:!0}),dr=n,ut({led:!0}),this.repaint(),this},this.setUserLedColor=function(n){return lt({userLed:!0}),nu=n,ut({userLed:!0}),this.repaint(),this},this.toggleUserLed=function(){return yt=yt===ii?dt:ii,this.repaint(),this},this.setUserLedOnOff=function(n){return yt=!0===n?ii:dt,this.repaint(),this},this.blinkUserLed=function(n){return n?cr||(de(!0),cr=!0):cr&&(clearInterval(ru),cr=!1),this},this.setLedVisible=function(n){return gr=!!n,this.repaint(),this},this.setUserLedVisible=function(n){return tu=!!n,this.repaint(),this},this.setLcdColor=function(n){return pi=n,lt({background:!0}),ut({background:!0}),this.repaint(),this},this.setLcdDecimals=function(n){return pu=parseInt(n,10),this.repaint(),this},this.setSection=function(n){return ci=n,ut(),this.repaint(),this},this.setSectionActive=function(n){return su=n,ut(),this.repaint(),this},this.setGradient=function(n){return nr=n,ut(),this.repaint(),this},this.setGradientActive=function(n){return nf=n,ut(),this.repaint(),this},this.setMinValue=function(n){return f=n,lt({background:!0}),ut({background:!0}),this.repaint(),this},this.getMinValue=function(){return f},this.setMaxValue=function(n){return l=n,lt({background:!0}),ut({background:!0}),this.repaint(),this},this.getMaxValue=function(){return l},this.setThreshold=function(n){n=parseFloat(n);var t=nl?l:n;return gt=t,lt({background:!0}),ut({background:!0}),this.repaint(),this},this.setThresholdRising=function(n){return ni=!!n,rt=!rt,or(rt),this.repaint(),this},this.setTitleString=function(n){return hu=n,lt({background:!0}),ut({background:!0}),this.repaint(),this},this.setUnitString=function(n){return cu=n,lt({background:!0}),ut({background:!0}),this.repaint(),this},this.setTrend=function(n){return hf=n,this.repaint(),this},this.setTrendVisible=function(n){return iu=!!n,this.repaint(),this},this.setFractionalScaleDecimals=function(n){wu=parseInt(n,10);lt({background:!0});ut({background:!0});this.repaint()},this.setLabelNumberFormat=function(n){return bu=n,lt({background:!0}),ut({background:!0}),this.repaint(),this},this.repaint=function(){var s=(ft-f)/(l-f)*ti,t,u=sr,n,i,e,o,r;for(ne||ut({frame:!0,background:!0,led:!0,userLed:!0,value:!0,trend:!0,foreground:!0}),p.clearRect(0,0,h,h),au&&p.drawImage(ir,0,0),p.drawImage(rr,0,0),n=0;n<=s;n+=5){if(t=sr,uu)e=f+n/ti*(l-f),o=nr.getEnd()-nr.getStart(),r=(e-f)/o,r=Math.max(Math.min(r,1),0),t=ei(nr.getColorAt(r).getRgbaColor());else if(lr)for(i=0;i=bi[i].start&&ne-4?c||(o=h>e*.8?e-h-e*.2:0,c=!0,clearTimeout(b),b=setTimeout(d,200)):et&&h<=e-4&&(o=0,c=!1),i.fillText(n,e-2-o,f*.5+w*.38));i.restore()},ri=function(n,t,i,u){var tt=r(n,t),f=tt.getContext("2d");f.save();var h=0,et=n,it=t,ut=Math.min(n,t)*.095,s=f.createLinearGradient(0,h,0,h+it);s.addColorStop(0,"#4c4c4c");s.addColorStop(.08,"#666666");s.addColorStop(.92,"#666666");s.addColorStop(1,"#e6e6e6");f.fillStyle=s;dt(f,0,h,et,it,ut);f.fill();f.restore();f.save();var c=rt(i),e=ot(c[0],c[1],c[2]),l=rt(u.gradientStartColor),ht=ot(l[0],l[1],l[2]),a=rt(u.gradientFraction1Color),ct=ot(a[0],a[1],a[2]),v=rt(u.gradientFraction2Color),lt=ot(v[0],v[1],v[2]),y=rt(u.gradientFraction3Color),at=ot(y[0],y[1],y[2]),p=rt(u.gradientStopColor),vt=ot(p[0],p[1],p[2]),w=st(e[0],e[1],ht[2]-.31),b=st(e[0],e[1],ct[2]-.31),k=st(e[0],e[1],lt[2]-.31),d=st(e[0],e[1],at[2]-.31),g=st(e[0],e[1],vt[2]-.31),nt=1,yt=n-2,ft=t-2,pt=ut-1,o=f.createLinearGradient(0,nt,0,nt+ft);return o.addColorStop(0,"rgb("+w[0]+", "+w[1]+", "+w[2]+")"),o.addColorStop(.03,"rgb("+b[0]+","+b[1]+","+b[2]+")"),o.addColorStop(.49,"rgb("+k[0]+","+k[1]+","+k[2]+")"),o.addColorStop(.5,"rgb("+d[0]+","+d[1]+","+d[2]+")"),o.addColorStop(1,"rgb("+g[0]+","+g[1]+","+g[2]+")"),f.fillStyle=o,dt(f,1,nt,yt,ft,pt),f.fill(),f.restore(),tt},ui=function(n){var t=rt(n),r=ot(t[0],t[1],t[2]),i=st(r[0],.57,.83);return"rgb("+i[0]+", "+i[1]+", "+i[2]+")"},d=function(){c?(o>e&&(o=-h),o+=2,b=setTimeout(d,50)):o=0;k||(k=!0,v(ti.repaint))},g=function(){var n;if(at=!0,vt=it(l,a,y),null!==u&&0=u[n].start&&p<=u[n].stop){t=yt[n];r=pt[n];break}i.drawImage(t,0,0);ii(p,r);k=!1},this.repaint(),this},ai=function(n,u){u=u||{};var o=undefined===u.size?0:u.size,hi=undefined===u.frameDesign?steelseries.FrameDesign.METAL:u.frameDesign,ci=undefined===u.frameVisible?!0:u.frameVisible,rt=undefined===u.backgroundColor?steelseries.BackgroundColor.DARK_GRAY:u.backgroundColor,li=undefined===u.backgroundVisible?!0:u.backgroundVisible,dt=undefined===u.pointerTypeLatest?steelseries.PointerType.TYPE1:u.pointerTypeLatest,ai=undefined===u.pointerTypeAverage?steelseries.PointerType.TYPE8:u.pointerTypeAverage,ii=undefined===u.pointerColor?steelseries.ColorDef.RED:u.pointerColor,ri=undefined===u.pointerColorAverage?steelseries.ColorDef.BLUE:u.pointerColorAverage,ar=undefined===u.knobType?steelseries.KnobType.STANDARD_KNOB:u.knobType,vr=undefined===u.knobStyle?steelseries.KnobStyle.SILVER:u.knobStyle,vi=undefined===u.foregroundType?steelseries.ForegroundType.TYPE1:u.foregroundType,yi=undefined===u.foregroundVisible?!0:u.foregroundVisible,h=undefined===u.pointSymbols?["N","NE","E","SE","S","SW","W","NW"]:u.pointSymbols,yr=undefined===u.pointSymbolsVisible?!0:u.pointSymbolsVisible,pr=undefined===u.customLayer?null:u.customLayer,wr=undefined===u.degreeScale?!0:u.degreeScale,ui=undefined===u.degreeScaleHalf?!1:u.degreeScaleHalf,wi=undefined===u.roseVisible?!1:u.roseVisible,lt=undefined===u.lcdColor?steelseries.LcdColor.STANDARD:u.lcdColor,bi=undefined===u.lcdVisible?!0:u.lcdVisible,br=undefined===u.digitalFont?!1:u.digitalFont,et=undefined===u.section?null:u.section,ot=undefined===u.area?null:u.area,gt=undefined===u.lcdTitleStrings?["Latest","Average"]:u.lcdTitleStrings,ki=undefined===u.titleString?"":u.titleString,di=undefined===u.useColorLabels?!1:u.useColorLabels,ni=undefined===u.fullScaleDeflectionTime?2.5:u.fullScaleDeflectionTime,st,ct,y=0,p=0,at=c,gi=this.valueLatest,fi=this.valueAverage,kr=-i,nr=t,tr=360,l=!1,e=ht(n);o===0&&(o=Math.min(e.canvas.width,e.canvas.height));e.canvas.width=o;e.canvas.height=o;var f=o,w=o,b=f/2,k=w/2,ei=Math.floor(f/10),dr=ei+"px "+s,gr=ei+"px "+wt,ti=f*.3,ir=w*.12,rr=(f-ti)/2,ur=w*.32,fr=w*.565,er=!1,vt=r(o,o),ut=vt.getContext("2d"),oi,yt=r(o,o),or=yt.getContext("2d"),pt=r(o,o),sr=pt.getContext("2d"),kt=r(o,o),hr=kt.getContext("2d"),cr=function(n,t){for(e.save(),e.textAlign="center",e.strokeStyle=lt.textColor,e.fillStyle=lt.textColor;n<-180;)n+=360;!ui&&n<0&&(n+=360);ui&&n>180&&(n=-(360-n));n>=0?(n="00"+Math.round(n),n=n.substring(n.length,n.length-3)):(n="00"+Math.abs(Math.round(n)),n="-"+n.substring(n.length,n.length-3));(lt===steelseries.LcdColor.STANDARD||lt===steelseries.LcdColor.STANDARD_GREEN)&&(e.shadowColor="gray",e.shadowOffsetX=f*.007,e.shadowOffsetY=f*.007,e.shadowBlur=f*.007);e.font=br?gr:dr;e.fillText(n+"°",f/2+ti*.05,(t?ur:fr)+ir*.5+ei*.38,ti*.9);e.restore()},lr=function(n,t,i,r,u){n.save();n.strokeStyle=r;n.fillStyle=r;n.lineWidth=f*.035;var e=nr/tr*t,o=e+(i-t)/(tr/nr);n.translate(b,k);n.rotate(kr);n.beginPath();u?(n.moveTo(0,0),n.arc(0,0,f*.365-n.lineWidth/2,e,o,!1)):n.arc(0,0,f*.365,e,o,!1);u?(n.moveTo(0,0),n.fill()):n.stroke();n.translate(-b,-k);n.restore()},nu=function(n){var l=f*.38,a=f*.35,p=f*.36,c=f*.1,v=f*.31,u=f*.36,r,e,t,o,y;if(n.textAlign="center",n.textBaseline="middle",n.save(),n.strokeStyle=rt.labelColor.getRgbaColor(),n.fillStyle=rt.labelColor.getRgbaColor(),n.translate(b,k),wr)for(r=Math.floor(.1*f)+"px serif bold",e=Math.floor(f*.04)+"px "+s,n.rotate(at*5),t=5;360>=t;t+=5){if(n.save(),yr)switch(t){case 360:n.translate(u,0);n.rotate(i);n.font=r;n.fillText(h[2],0,0,c);n.translate(-u,0);break;case 90:n.translate(u,0);n.rotate(i);n.font=r;n.fillText(h[4],0,0,c);n.translate(-u,0);break;case 180:n.translate(u,0);n.rotate(i);n.font=r;n.fillText(h[6],0,0,c);n.translate(-u,0);break;case 270:n.translate(u,0);n.rotate(i);n.font=r;n.fillText(h[0],0,0,c);n.translate(-u,0);break;case 5:case 85:case 95:case 175:case 185:case 265:case 275:case 355:break;default:(t+90)%20?(n.lineWidth=(t+90)%5?1.5:1,n.beginPath(),n.moveTo(l,0),y=(t+90)%10?p:a,n.lineTo(y,0),n.closePath(),n.stroke()):(n.lineWidth=1.5,n.beginPath(),n.moveTo(l,0),n.lineTo(a,0),n.closePath(),n.stroke(),o=(t+90)%360,n.translate(v,0),n.rotate(i),n.font=e,n.fillText("0".substring(o>=100)+o,0,0,c),n.translate(-v,0))}else(t+90)%20?(n.lineWidth=(t+90)%5?1.5:1,n.beginPath(),n.moveTo(l,0),y=(t+90)%10?p:a,n.lineTo(y,0),n.closePath(),n.stroke()):(n.lineWidth=1.5,n.beginPath(),n.moveTo(l,0),n.lineTo(a,0),n.closePath(),n.stroke(),o=(t+90)%360,ui&&o>180&&(o=-(360-o)),n.translate(v,0),n.rotate(i),n.font=e,n.fillText(o,0,0,c),n.translate(-v,0));n.restore();n.rotate(at*5)}else for(r=.12*f+"px serif",e=.06*f+"px serif",n.lineWidth=1,n.strokeStyle=rt.symbolColor.getRgbaColor(),t=0;360>t;t+=2.5){0==t%5&&(n.beginPath(),n.moveTo(f*.38,0),n.lineTo(f*.36,0),n.closePath(),n.stroke());n.save();switch(t){case 0:n.translate(f*.35,0);n.rotate(i);n.font=r;n.fillText(h[2],0,0);n.translate(-f*.35,0);break;case 45:n.translate(f*.29,0);n.rotate(i);n.font=e;n.fillText(h[3],0,0);n.translate(-f*.29,0);break;case 90:n.translate(f*.35,0);n.rotate(i);n.font=r;n.fillText(h[4],0,0);n.translate(-f*.35,0);break;case 135:n.translate(f*.29,0);n.rotate(i);n.font=e;n.fillText(h[5],0,0);n.translate(-f*.29,0);break;case 180:n.translate(f*.35,0);n.rotate(i);n.font=r;n.fillText(h[6],0,0);n.translate(-f*.35,0);break;case 225:n.translate(f*.29,0);n.rotate(i);n.font=e;n.fillText(h[7],0,0);n.translate(-f*.29,0);break;case 270:n.translate(f*.35,0);n.rotate(i);n.font=r;n.fillText(h[0],0,0);n.translate(-f*.35,0);break;case 315:n.translate(f*.29,0);n.rotate(i);n.font=e;n.fillText(h[1],0,0);n.translate(-f*.29,0)}n.restore();wi&&(0===t||22.5===t||45===t||67.5===t||90===t||112.5===t||135===t||157.5===t||180===t||202.5===t||225===t||247.5===t||270===t||292.5===t||315===t||337.5===t||360===t)&&(n.save(),n.beginPath(),t%45?n.moveTo(f*.29,0):n.moveTo(f*.38,0),n.lineTo(f*.1,0),n.closePath(),n.restore(),n.stroke());n.rotate(at*2.5)}n.translate(-b,-k);n.restore()},tu=function(n){gt.length>0&&(n.save(),n.textAlign="center",n.textBaseline="middle",n.fillStyle=di?ii.medium.getRgbaColor():rt.labelColor.getRgbaColor(),n.font=.04*f+"px "+s,n.fillText(gt[0],f/2,w*.29,f*.3),n.fillStyle=di?ri.medium.getRgbaColor():rt.labelColor.getRgbaColor(),n.fillText(gt[1],f/2,w*.71,f*.3),ki.length>0&&(n.fillStyle=rt.labelColor.getRgbaColor(),n.font=.0467*f+"px "+s,n.fillText(ki,f/2,w*.5,f*.3)))},a=function(n){var t,i,u;n=n||{};var r=undefined===n.background?!1:n.background,e=undefined===n.pointer?!1:n.pointer,o=undefined===n.foreground?!1:n.foreground;if(er=!0,r&&ci&&g(ut,hi,b,k,f,w),r&&li){if(nt(ut,rt,b,k,f,w),bt(ut,pr,b,k,f,w),null!==et&&00)for(u.rect(0,0,f,s*1.1),u.fillStyle=ct,u.fill(),u.strokeStyle="#f0f0f0",u.lineWidth="1px",u.moveTo(0,0),u.lineTo(0,s*1.1),u.stroke(),u.strokeStyle="#202020",u.moveTo(f,0),u.lineTo(f,s*1.1),u.stroke(),u.textAlign="center",u.textBaseline="middle",u.font=g,u.fillStyle=lt,n=9;n<21;n++)u.fillText(n%10,f*.5,h*(n-9)+h/2);for(n=0;n=o;o+=90)n.beginPath(),n.moveTo(u*.560747,f*.584112),n.lineTo(u*.640186,f*.644859),n.lineTo(u*.584112,f*.560747),n.lineTo(u*.560747,f*.584112),n.closePath(),n.fillStyle=h,n.fill(),n.stroke(),n.beginPath(),n.moveTo(u*.523364,f*.397196),n.lineTo(u*.5,f*.196261),n.lineTo(u*.471962,f*.397196),n.lineTo(u*.523364,f*.397196),n.closePath(),s=n.createLinearGradient(.476635*u,0,.518691*u,0),s.addColorStop(0,"rgb(222, 223, 218)"),s.addColorStop(.48,"rgb(222, 223, 218)"),s.addColorStop(.49,h),s.addColorStop(1,h),n.fillStyle=s,n.fill(),n.stroke(),n.translate(i,r),n.rotate(o*c),n.translate(-i,-r);n.beginPath();n.translate(i,r);n.arc(0,0,u*.1,0,t,!1);n.lineWidth=u*.022;n.stroke();n.translate(-i,-r);n.restore()},ft=function(n,i,u,f,e){var c,o,s,h,l=i.toString()+u.type+f.light.getHexColor()+f.medium.getHexColor();if(!ft.cache[l]){c=r(i,i);o=c.getContext("2d");switch(u.type){case"type2":s=o.createLinearGradient(0,i*.471962,0,i*.130841);s.addColorStop(0,e.getRgbaColor());s.addColorStop(.36,e.getRgbaColor());s.addColorStop(.361,f.light.getRgbaColor());s.addColorStop(1,f.light.getRgbaColor());o.fillStyle=s;o.beginPath();o.moveTo(i*.518691,i*.471962);o.lineTo(i*.509345,i*.462616);o.lineTo(i*.509345,i*.341121);o.lineTo(i*.504672,i*.130841);o.lineTo(i*.495327,i*.130841);o.lineTo(i*.490654,i*.341121);o.lineTo(i*.490654,i*.462616);o.lineTo(i*.481308,i*.471962);o.closePath();o.fill();break;case"type3":o.beginPath();o.rect(i*.495327,i*.130841,i*.009345,i*.373831);o.closePath();o.fillStyle=f.light.getRgbaColor();o.fill();break;case"type4":s=o.createLinearGradient(.467289*i,0,.528036*i,0);s.addColorStop(0,f.dark.getRgbaColor());s.addColorStop(.51,f.dark.getRgbaColor());s.addColorStop(.52,f.light.getRgbaColor());s.addColorStop(1,f.light.getRgbaColor());o.fillStyle=s;o.beginPath();o.moveTo(i*.5,i*.126168);o.lineTo(i*.514018,i*.135514);o.lineTo(i*.53271,i*.5);o.lineTo(i*.523364,i*.602803);o.lineTo(i*.476635,i*.602803);o.lineTo(i*.467289,i*.5);o.lineTo(i*.485981,i*.135514);o.lineTo(i*.5,i*.126168);o.closePath();o.fill();break;case"type5":s=o.createLinearGradient(.471962*i,0,.528036*i,0);s.addColorStop(0,f.light.getRgbaColor());s.addColorStop(.5,f.light.getRgbaColor());s.addColorStop(.5,f.medium.getRgbaColor());s.addColorStop(1,f.medium.getRgbaColor());o.fillStyle=s;o.beginPath();o.moveTo(i*.5,i*.495327);o.lineTo(i*.528037,i*.495327);o.lineTo(i*.5,i*.149532);o.lineTo(i*.471962,i*.495327);o.lineTo(i*.5,i*.495327);o.closePath();o.fill();o.lineWidth=1;o.lineCap="square";o.lineJoin="miter";o.strokeStyle=f.dark.getRgbaColor();o.stroke();break;case"type6":o.fillStyle=f.medium.getRgbaColor();o.beginPath();o.moveTo(i*.481308,i*.485981);o.lineTo(i*.481308,i*.392523);o.lineTo(i*.485981,i*.317757);o.lineTo(i*.495327,i*.130841);o.lineTo(i*.504672,i*.130841);o.lineTo(i*.514018,i*.317757);o.lineTo(i*.518691,i*.38785);o.lineTo(i*.518691,i*.485981);o.lineTo(i*.504672,i*.485981);o.lineTo(i*.504672,i*.38785);o.lineTo(i*.5,i*.317757);o.lineTo(i*.495327,i*.392523);o.lineTo(i*.495327,i*.485981);o.lineTo(i*.481308,i*.485981);o.closePath();o.fill();break;case"type7":s=o.createLinearGradient(.481308*i,0,.518691*i,0);s.addColorStop(0,f.dark.getRgbaColor());s.addColorStop(1,f.medium.getRgbaColor());o.fillStyle=s;o.beginPath();o.moveTo(i*.490654,i*.130841);o.lineTo(i*.481308,i*.5);o.lineTo(i*.518691,i*.5);o.lineTo(i*.504672,i*.130841);o.lineTo(i*.490654,i*.130841);o.closePath();o.fill();break;case"type8":s=o.createLinearGradient(.471962*i,0,.528036*i,0);s.addColorStop(0,f.light.getRgbaColor());s.addColorStop(.5,f.light.getRgbaColor());s.addColorStop(.5,f.medium.getRgbaColor());s.addColorStop(1,f.medium.getRgbaColor());o.fillStyle=s;o.strokeStyle=f.dark.getRgbaColor();o.beginPath();o.moveTo(i*.5,i*.53271);o.lineTo(i*.53271,i*.5);o.bezierCurveTo(i*.53271,i*.5,i*.509345,i*.457943,i*.5,i*.149532);o.bezierCurveTo(i*.490654,i*.457943,i*.467289,i*.5,i*.467289,i*.5);o.lineTo(i*.5,i*.53271);o.closePath();o.fill();o.stroke();break;case"type9":s=o.createLinearGradient(.471962*i,0,.528036*i,0);s.addColorStop(0,"rgb(50, 50, 50)");s.addColorStop(.5,"#666666");s.addColorStop(1,"rgb(50, 50, 50)");o.fillStyle=s;o.strokeStyle="#2E2E2E";o.beginPath();o.moveTo(i*.495327,i*.233644);o.lineTo(i*.504672,i*.233644);o.lineTo(i*.514018,i*.439252);o.lineTo(i*.485981,i*.439252);o.lineTo(i*.495327,i*.233644);o.closePath();o.moveTo(i*.490654,i*.130841);o.lineTo(i*.471962,i*.471962);o.lineTo(i*.471962,i*.528037);o.bezierCurveTo(i*.471962,i*.528037,i*.476635,i*.602803,i*.476635,i*.602803);o.bezierCurveTo(i*.476635,i*.607476,i*.481308,i*.607476,i*.5,i*.607476);o.bezierCurveTo(i*.518691,i*.607476,i*.523364,i*.607476,i*.523364,i*.602803);o.bezierCurveTo(i*.523364,i*.602803,i*.528037,i*.528037,i*.528037,i*.528037);o.lineTo(i*.528037,i*.471962);o.lineTo(i*.509345,i*.130841);o.lineTo(i*.490654,i*.130841);o.closePath();o.fill();o.beginPath();o.moveTo(i*.495327,i*.219626);o.lineTo(i*.504672,i*.219626);o.lineTo(i*.504672,i*.135514);o.lineTo(i*.495327,i*.135514);o.lineTo(i*.495327,i*.219626);o.closePath();o.fillStyle=f.medium.getRgbaColor();o.fill();break;case"type10":o.beginPath();o.moveTo(i*.5,i*.149532);o.bezierCurveTo(i*.5,i*.149532,i*.443925,i*.490654,i*.443925,i*.5);o.bezierCurveTo(i*.443925,i*.53271,i*.467289,i*.556074,i*.5,i*.556074);o.bezierCurveTo(i*.53271,i*.556074,i*.556074,i*.53271,i*.556074,i*.5);o.bezierCurveTo(i*.556074,i*.490654,i*.5,i*.149532,i*.5,i*.149532);o.closePath();s=o.createLinearGradient(.471962*i,0,.528036*i,0);s.addColorStop(0,f.light.getRgbaColor());s.addColorStop(.5,f.light.getRgbaColor());s.addColorStop(.5,f.medium.getRgbaColor());s.addColorStop(1,f.medium.getRgbaColor());o.fillStyle=s;o.strokeStyle=f.medium.getRgbaColor();o.lineWidth=1;o.lineCap="square";o.lineJoin="miter";o.fill();o.stroke();break;case"type11":o.beginPath();o.moveTo(.5*i,.168224*i);o.lineTo(.485981*i,.5*i);o.bezierCurveTo(.485981*i,.5*i,.481308*i,.584112*i,.5*i,.584112*i);o.bezierCurveTo(.514018*i,.584112*i,.509345*i,.5*i,.509345*i,.5*i);o.lineTo(.5*i,.168224*i);o.closePath();s=o.createLinearGradient(0,.168224*i,0,.584112*i);s.addColorStop(0,f.medium.getRgbaColor());s.addColorStop(1,f.dark.getRgbaColor());o.fillStyle=s;o.strokeStyle=f.dark.getRgbaColor();o.fill();o.stroke();break;case"type12":o.beginPath();o.moveTo(.5*i,.168224*i);o.lineTo(.485981*i,.5*i);o.lineTo(.5*i,.504672*i);o.lineTo(.509345*i,.5*i);o.lineTo(.5*i,.168224*i);o.closePath();s=o.createLinearGradient(0,.168224*i,0,.504672*i);s.addColorStop(0,f.medium.getRgbaColor());s.addColorStop(1,f.dark.getRgbaColor());o.fillStyle=s;o.strokeStyle=f.dark.getRgbaColor();o.fill();o.stroke();break;case"type13":case"type14":o.beginPath();o.moveTo(.485981*i,.168224*i);o.lineTo(.5*i,.130841*i);o.lineTo(.509345*i,.168224*i);o.lineTo(.509345*i,.509345*i);o.lineTo(.485981*i,.509345*i);o.lineTo(.485981*i,.168224*i);o.closePath();u.type==="type13"?(s=o.createLinearGradient(0,.5*i,0,.130841*i),s.addColorStop(0,e.getRgbaColor()),s.addColorStop(.85,e.getRgbaColor()),s.addColorStop(.85,f.medium.getRgbaColor()),s.addColorStop(1,f.medium.getRgbaColor()),o.fillStyle=s):(s=o.createLinearGradient(.485981*i,0,.509345*i,0),s.addColorStop(0,f.veryDark.getRgbaColor()),s.addColorStop(.5,f.light.getRgbaColor()),s.addColorStop(1,f.veryDark.getRgbaColor()),o.fillStyle=s);o.fill();break;case"type15":case"type16":o.beginPath();o.moveTo(i*.509345,i*.457943);o.lineTo(i*.5015,i*.13);o.lineTo(i*.4985,i*.13);o.lineTo(i*.490654,i*.457943);o.bezierCurveTo(i*.490654,i*.457943,i*.490654,i*.457943,i*.490654,i*.457943);o.bezierCurveTo(i*.471962,i*.462616,i*.457943,i*.481308,i*.457943,i*.5);o.bezierCurveTo(i*.457943,i*.518691,i*.471962,i*.537383,i*.490654,i*.542056);o.bezierCurveTo(i*.490654,i*.542056,i*.490654,i*.542056,i*.490654,i*.542056);u.type==="type15"?(o.lineTo(i*.490654,i*.57),o.bezierCurveTo(i*.46,i*.58,i*.46,i*.62,i*.490654,i*.63),o.bezierCurveTo(i*.47,i*.62,i*.48,i*.59,i*.5,i*.59),o.bezierCurveTo(i*.53,i*.59,i*.52,i*.62,i*.509345,i*.63),o.bezierCurveTo(i*.54,i*.62,i*.54,i*.58,i*.509345,i*.57),o.lineTo(i*.509345,i*.57)):(o.lineTo(i*.490654,i*.621495),o.lineTo(i*.509345,i*.621495));o.lineTo(i*.509345,i*.542056);o.bezierCurveTo(i*.509345,i*.542056,i*.509345,i*.542056,i*.509345,i*.542056);o.bezierCurveTo(i*.528037,i*.537383,i*.542056,i*.518691,i*.542056,i*.5);o.bezierCurveTo(i*.542056,i*.481308,i*.528037,i*.462616,i*.509345,i*.457943);o.bezierCurveTo(i*.509345,i*.457943,i*.509345,i*.457943,i*.509345,i*.457943);o.closePath();s=u.type==="type15"?o.createLinearGradient(0,0,0,i*.63):o.createLinearGradient(0,0,0,i*.621495);s.addColorStop(0,f.medium.getRgbaColor());s.addColorStop(.388888,f.medium.getRgbaColor());s.addColorStop(.5,f.light.getRgbaColor());s.addColorStop(.611111,f.medium.getRgbaColor());s.addColorStop(1,f.medium.getRgbaColor());o.fillStyle=s;o.strokeStyle=f.dark.getRgbaColor();o.fill();o.stroke();o.beginPath();h=i*.06542/2;o.arc(i*.5,i*.5,h,0,t);s=o.createLinearGradient(i*.5-h,i*.5+h,0,i*.5+h);s.addColorStop(0,"#e6b35c");s.addColorStop(.01,"#e6b35c");s.addColorStop(.99,"#c48200");s.addColorStop(1,"#c48200");o.fillStyle=s;o.closePath();o.fill();o.beginPath();h=i*.046728/2;o.arc(i*.5,i*.5,h,0,t);s=o.createRadialGradient(i*.5,i*.5,0,i*.5,i*.5,h);s.addColorStop(0,"#c5c5c5");s.addColorStop(.19,"#c5c5c5");s.addColorStop(.22,"#000000");s.addColorStop(.8,"#000000");s.addColorStop(.99,"#707070");s.addColorStop(1,"#707070");o.fillStyle=s;o.closePath();o.fill();break;case"type1":default:s=o.createLinearGradient(0,i*.471962,0,i*.130841);s.addColorStop(0,f.veryDark.getRgbaColor());s.addColorStop(.3,f.medium.getRgbaColor());s.addColorStop(.59,f.medium.getRgbaColor());s.addColorStop(1,f.veryDark.getRgbaColor());o.fillStyle=s;o.beginPath();o.moveTo(i*.518691,i*.471962);o.bezierCurveTo(i*.514018,i*.457943,i*.509345,i*.415887,i*.509345,i*.401869);o.bezierCurveTo(i*.504672,i*.383177,i*.5,i*.130841,i*.5,i*.130841);o.bezierCurveTo(i*.5,i*.130841,i*.490654,i*.383177,i*.490654,i*.397196);o.bezierCurveTo(i*.490654,i*.415887,i*.485981,i*.457943,i*.481308,i*.471962);o.bezierCurveTo(i*.471962,i*.481308,i*.467289,i*.490654,i*.467289,i*.5);o.bezierCurveTo(i*.467289,i*.518691,i*.481308,i*.53271,i*.5,i*.53271);o.bezierCurveTo(i*.518691,i*.53271,i*.53271,i*.518691,i*.53271,i*.5);o.bezierCurveTo(i*.53271,i*.490654,i*.528037,i*.481308,i*.518691,i*.471962);o.closePath();o.fill()}ft.cache[l]=c}return n.drawImage(ft.cache[l],0,0),this},g,nt,bt,tt,l,a,it,et,w,v,e,f,y,ut,ct,vt,ui,gt,b,h,lt,ni,ti,yt;ft.cache={};g=function(i,u,f,e,o,s){var p,h,c,l,a,v,y,w=o.toString()+s+u.design;if(!g.cache[w]){p=r(o,s);h=p.getContext("2d");h.fillStyle="#848484";h.strokeStyle="rgba(132, 132, 132, 0.5)";h.beginPath();h.arc(f,e,o/2,0,t,!0);h.closePath();h.fill();h.stroke();h.beginPath();h.arc(f,e,o*.990654/2,0,t,!0);h.closePath();switch(u.design){case"metal":c=h.createLinearGradient(0,o*.004672,0,s*.990654);c.addColorStop(0,"#fefefe");c.addColorStop(.07,"rgb(210, 210, 210)");c.addColorStop(.12,"rgb(179, 179, 179)");c.addColorStop(1,"rgb(213, 213, 213)");h.fillStyle=c;h.fill();break;case"brass":c=h.createLinearGradient(0,o*.004672,0,s*.990654);c.addColorStop(0,"rgb(249, 243, 155)");c.addColorStop(.05,"rgb(246, 226, 101)");c.addColorStop(.1,"rgb(240, 225, 132)");c.addColorStop(.5,"rgb(90, 57, 22)");c.addColorStop(.9,"rgb(249, 237, 139)");c.addColorStop(.95,"rgb(243, 226, 108)");c.addColorStop(1,"rgb(202, 182, 113)");h.fillStyle=c;h.fill();break;case"steel":c=h.createLinearGradient(0,o*.004672,0,s*.990654);c.addColorStop(0,"rgb(231, 237, 237)");c.addColorStop(.05,"rgb(189, 199, 198)");c.addColorStop(.1,"rgb(192, 201, 200)");c.addColorStop(.5,"rgb(23, 31, 33)");c.addColorStop(.9,"rgb(196, 205, 204)");c.addColorStop(.95,"rgb(194, 204, 203)");c.addColorStop(1,"rgb(189, 201, 199)");h.fillStyle=c;h.fill();break;case"gold":c=h.createLinearGradient(0,o*.004672,0,s*.990654);c.addColorStop(0,"rgb(255, 255, 207)");c.addColorStop(.15,"rgb(255, 237, 96)");c.addColorStop(.22,"rgb(254, 199, 57)");c.addColorStop(.3,"rgb(255, 249, 203)");c.addColorStop(.38,"rgb(255, 199, 64)");c.addColorStop(.44,"rgb(252, 194, 60)");c.addColorStop(.51,"rgb(255, 204, 59)");c.addColorStop(.6,"rgb(213, 134, 29)");c.addColorStop(.68,"rgb(255, 201, 56)");c.addColorStop(.75,"rgb(212, 135, 29)");c.addColorStop(1,"rgb(247, 238, 101)");h.fillStyle=c;h.fill();break;case"anthracite":c=h.createLinearGradient(0,.004672*s,0,.995326*s);c.addColorStop(0,"rgb(118, 117, 135)");c.addColorStop(.06,"rgb(74, 74, 82)");c.addColorStop(.12,"rgb(50, 50, 54)");c.addColorStop(1,"rgb(79, 79, 87)");h.fillStyle=c;h.fill();break;case"tiltedGray":c=h.createLinearGradient(.233644*o,.084112*s,.81258*o,.910919*s);c.addColorStop(0,"#ffffff");c.addColorStop(.07,"rgb(210, 210, 210)");c.addColorStop(.16,"rgb(179, 179, 179)");c.addColorStop(.33,"#ffffff");c.addColorStop(.55,"#c5c5c5");c.addColorStop(.79,"#ffffff");c.addColorStop(1,"#666666");h.fillStyle=c;h.fill();break;case"tiltedBlack":c=h.createLinearGradient(.228971*o,.079439*s,.802547*o,.898591*s);c.addColorStop(0,"#666666");c.addColorStop(.21,"#000000");c.addColorStop(.47,"#666666");c.addColorStop(.99,"#000000");c.addColorStop(1,"#000000");h.fillStyle=c;h.fill();break;case"glossyMetal":c=h.createRadialGradient(.5*o,.5*s,0,.5*o,.5*o,.5*o);c.addColorStop(0,"rgb(207, 207, 207)");c.addColorStop(.96,"rgb(205, 204, 205)");c.addColorStop(1,"rgb(244, 244, 244)");h.fillStyle=c;h.fill();h.beginPath();h.arc(.5*o,.5*s,.973962*o/2,0,t);h.closePath();c=h.createLinearGradient(0,s-.971962*s,0,.971962*s);c.addColorStop(0,"rgb(249, 249, 249)");c.addColorStop(.23,"rgb(200, 195, 191)");c.addColorStop(.36,"#ffffff");c.addColorStop(.59,"rgb(29, 29, 29)");c.addColorStop(.76,"rgb(200, 194, 192)");c.addColorStop(1,"rgb(209, 209, 209)");h.fillStyle=c;h.fill();h.beginPath();h.arc(.5*o,.5*s,.869158*o/2,0,t);h.closePath();h.fillStyle="#f6f6f6";h.fill();h.beginPath();h.arc(.5*o,.5*s,.85*o/2,0,t);h.closePath();h.fillStyle="#333333";h.fill();break;case"blackMetal":v=[0,.125,.347222,.5,.680555,.875,1];y=[new n(254,254,254,1),new n(0,0,0,1),new n(153,153,153,1),new n(0,0,0,1),new n(153,153,153,1),new n(0,0,0,1),new n(254,254,254,1)];h.save();h.arc(f,e,o*.990654/2,0,t,!0);h.clip();l=o*.495327;a=o*.42056;c=new at(v,y);c.fillCircle(h,f,e,a,l);h.strokeStyle="#848484";h.strokeStyle="rgba(132, 132, 132, 0.8)";h.beginPath();h.lineWidth=o/90;h.arc(f,e,o/2,0,t,!0);h.closePath();h.stroke();h.restore();break;case"shinyMetal":v=[0,.125,.25,.347222,.5,.652777,.75,.875,1];y=[new n(254,254,254,1),new n(210,210,210,1),new n(179,179,179,1),new n(238,238,238,1),new n(160,160,160,1),new n(238,238,238,1),new n(179,179,179,1),new n(210,210,210,1),new n(254,254,254,1)];h.save();h.arc(f,e,o*.990654/2,0,t,!0);h.clip();l=o*.495327;a=o*.42056;c=new at(v,y);c.fillCircle(h,f,e,a,l);h.strokeStyle="#848484";h.strokeStyle="rgba(132, 132, 132, 0.8)";h.beginPath();h.lineWidth=o/90;h.arc(f,e,o/2,0,t,!0);h.closePath();h.stroke();h.restore();break;case"chrome":v=[0,.09,.12,.16,.25,.29,.33,.38,.48,.52,.63,.68,.8,.83,.87,.97,1];y=[new n(255,255,255,1),new n(255,255,255,1),new n(136,136,138,1),new n(164,185,190,1),new n(158,179,182,1),new n(112,112,112,1),new n(221,227,227,1),new n(155,176,179,1),new n(156,176,177,1),new n(254,255,255,1),new n(255,255,255,1),new n(156,180,180,1),new n(198,209,211,1),new n(246,248,247,1),new n(204,216,216,1),new n(164,188,190,1),new n(255,255,255,1)];h.save();h.arc(f,e,o*.990654/2,0,t,!0);h.clip();l=o*.495327;a=o*.42056;c=new at(v,y);c.fillCircle(h,f,e,a,l);h.strokeStyle="#848484";h.strokeStyle="rgba(132, 132, 132, 0.8)";h.beginPath();h.lineWidth=o/90;h.arc(f,e,o/2,0,t,!0);h.closePath();h.stroke();h.restore()}h.fillStyle="rgb(191, 191, 191)";h.beginPath();h.arc(f,e,o*.841121/2,0,t,!0);h.closePath();h.fill();h.globalCompositeOperation="destination-out";h.beginPath();h.arc(f,e,o*.83/2,0,t,!0);h.closePath();h.fill();g.cache[w]=p}return i.drawImage(g.cache[w],0,0),this};g.cache={};nt=function(i,u,f,e,o,s){var w,h,l,d,g,a=o*.831775/2,tt,it,rt,p,y,v,ut,b,k=o.toString()+s+u.name;if(!nt.cache[k]){if(w=r(o,s),h=w.getContext("2d"),h.beginPath(),h.arc(f,e,a,0,t,!0),h.closePath(),u.name==="CARBON"||u.name==="PUNCHED_SHEET"||u.name==="BRUSHED_METAL"||u.name==="BRUSHED_STAINLESS")u.name==="CARBON"&&(h.fillStyle=h.createPattern(wi,"repeat"),h.fill()),u.name==="PUNCHED_SHEET"&&(h.fillStyle=h.createPattern(bi,"repeat"),h.fill()),l=h.createLinearGradient(a,0,o-a,0),l.addColorStop(0,"rgba(0, 0, 0, 0.25)"),l.addColorStop(.5,"rgba(0, 0, 0, 0)"),l.addColorStop(1,"rgba(0, 0, 0, 0.25)"),h.fillStyle=l,h.beginPath(),h.arc(f,e,a,0,t,!0),h.closePath(),h.fill(),(u.name==="BRUSHED_METAL"||u.name==="BRUSHED_STAINLESS")&&(tt=u.name==="BRUSHED_METAL"?!0:!1,it=parseInt(u.gradientStop.getHexColor().substr(-6),16),rt=ki(it,5,.1,tt,.5),h.fillStyle=h.createPattern(rt.fill(0,0,o,s),"no-repeat"),h.fill());else if(u.name==="STAINLESS"||u.name==="TURNED"){if(d=[0,.03,.1,.14,.24,.33,.38,.5,.62,.67,.76,.81,.85,.97,1],g=[new n("#FDFDFD"),new n("#FDFDFD"),new n("#B2B2B4"),new n("#ACACAE"),new n("#FDFDFD"),new n("#8E8E8E"),new n("#8E8E8E"),new n("#FDFDFD"),new n("#8E8E8E"),new n("#8E8E8E"),new n("#FDFDFD"),new n("#ACACAE"),new n("#B2B2B4"),new n("#FDFDFD"),new n("#FDFDFD")],l=new at(d,g),l.fillCircle(h,f,e,0,a),u.name==="TURNED"){for(p=a,y=p*.55,v=c*(500/p),h.save(),h.beginPath(),h.arc(f,e,p,0,t),h.closePath(),h.clip(),h.lineWidth=.5,ut=t-v*.3,b=0;b0&&i.width>0&&(n.save(),n.beginPath(),n.arc(r,u,f*.831775/2,0,t,!0),n.clip(),n.drawImage(i,h,c,o,s),n.restore()),this};tt=function(n,t,i,u,f,e,o,s,h){var b,c,v=Math.ceil(u*.084112),y=i*.5-v/2,p=u*.5-v/2,d=i*.008,a,w,k=t.type+i+u+f+(e!==undefined?e.type:"-")+(o!==undefined?o.style:"-")+(h!==undefined?h.type:"-");if(!tt.cache[k]){b=r(i,u);c=b.getContext("2d");f&&(c.shadowColor="rgba(0, 0, 0, 0.8)",c.shadowOffsetX=c.shadowOffsetY=d,c.shadowBlur=d*2,s===steelseries.GaugeType.TYPE5?steelseries.Orientation.WEST===h?(y=i*.733644-v/2,c.drawImage(l(v,e,o),y,p)):steelseries.Orientation.EAST===h?(y=i*(1-.733644)-v/2,c.drawImage(l(v,e,o),y,p)):(p=u*.733644-v/2,c.drawImage(l(v,e,o),y,u*.6857)):c.drawImage(l(v,e,o),y,p),c.shadowOffsetX=c.shadowOffsetY=0,c.shadowBlur=0);switch(t.type){case"type2":c.beginPath();c.moveTo(i*.135514,u*.696261);c.bezierCurveTo(i*.214953,u*.588785,i*.317757,u*.5,i*.462616,u*.425233);c.bezierCurveTo(i*.612149,u*.345794,i*.733644,u*.317757,i*.873831,u*.322429);c.bezierCurveTo(i*.766355,u*.112149,i*.528037,u*.023364,i*.313084,u*.130841);c.bezierCurveTo(i*.09813,u*.238317,i*.028037,u*.485981,i*.135514,u*.696261);c.closePath();a=c.createLinearGradient(.313084*i,.135514*u,.495528*i,.493582*u);a.addColorStop(0,"rgba(255, 255, 255, 0.275)");a.addColorStop(1,"rgba(255, 255, 255, 0.015)");break;case"type3":c.beginPath();c.moveTo(i*.084112,u*.509345);c.bezierCurveTo(i*.21028,u*.556074,i*.462616,u*.560747,i*.5,u*.560747);c.bezierCurveTo(i*.537383,u*.560747,i*.794392,u*.560747,i*.915887,u*.509345);c.bezierCurveTo(i*.915887,u*.2757,i*.738317,u*.084112,i*.5,u*.084112);c.bezierCurveTo(i*.261682,u*.084112,i*.084112,u*.2757,i*.084112,u*.509345);c.closePath();a=c.createLinearGradient(0,.093457*u,0,.556073*u);a.addColorStop(0,"rgba(255, 255, 255, 0.275)");a.addColorStop(1,"rgba(255, 255, 255, 0.015)");break;case"type4":c.beginPath();c.moveTo(i*.67757,u*.24299);c.bezierCurveTo(i*.771028,u*.308411,i*.822429,u*.411214,i*.813084,u*.528037);c.bezierCurveTo(i*.799065,u*.654205,i*.719626,u*.757009,i*.593457,u*.799065);c.bezierCurveTo(i*.485981,u*.831775,i*.369158,u*.808411,i*.285046,u*.728971);c.bezierCurveTo(i*.2757,u*.719626,i*.252336,u*.714953,i*.233644,u*.728971);c.bezierCurveTo(i*.214953,u*.747663,i*.219626,u*.771028,i*.228971,u*.7757);c.bezierCurveTo(i*.331775,u*.878504,i*.476635,u*.915887,i*.616822,u*.869158);c.bezierCurveTo(i*.771028,u*.822429,i*.873831,u*.691588,i*.88785,u*.53271);c.bezierCurveTo(i*.897196,u*.38785,i*.836448,u*.257009,i*.719626,u*.182242);c.bezierCurveTo(i*.705607,u*.172897,i*.682242,u*.163551,i*.663551,u*.186915);c.bezierCurveTo(i*.654205,u*.205607,i*.668224,u*.238317,i*.67757,u*.24299);c.closePath();a=c.createRadialGradient(.5*i,.5*u,0,.5*i,.5*u,.38785*i);a.addColorStop(0,"rgba(255, 255, 255, 0)");a.addColorStop(.82,"rgba(255, 255, 255, 0)");a.addColorStop(.83,"rgba(255, 255, 255, 0)");a.addColorStop(1,"rgba(255, 255, 255, 0.15)");c.beginPath();c.moveTo(i*.261682,u*.224299);c.bezierCurveTo(i*.285046,u*.238317,i*.252336,u*.285046,i*.24299,u*.317757);c.bezierCurveTo(i*.24299,u*.350467,i*.271028,u*.383177,i*.271028,u*.397196);c.bezierCurveTo(i*.2757,u*.415887,i*.261682,u*.457943,i*.238317,u*.509345);c.bezierCurveTo(i*.224299,u*.542056,i*.17757,u*.612149,i*.158878,u*.612149);c.bezierCurveTo(i*.144859,u*.612149,i*.088785,u*.546728,i*.130841,u*.369158);c.bezierCurveTo(i*.140186,u*.336448,i*.214953,u*.200934,i*.261682,u*.224299);c.closePath();w=c.createLinearGradient(.130841*i,.369158*u,.273839*i,.412877*u);w.addColorStop(0,"rgba(255, 255, 255, 0.275)");w.addColorStop(1,"rgba(255, 255, 255, 0.015)");c.fillStyle=w;c.fill();break;case"type5":c.beginPath();c.moveTo(i*.084112,u*.5);c.bezierCurveTo(i*.084112,u*.271028,i*.271028,u*.084112,i*.5,u*.084112);c.bezierCurveTo(i*.700934,u*.084112,i*.864485,u*.224299,i*.906542,u*.411214);c.bezierCurveTo(i*.911214,u*.439252,i*.911214,u*.518691,i*.845794,u*.537383);c.bezierCurveTo(i*.794392,u*.546728,i*.551401,u*.411214,i*.392523,u*.457943);c.bezierCurveTo(i*.168224,u*.509345,i*.135514,u*.7757,i*.093457,u*.593457);c.bezierCurveTo(i*.088785,u*.560747,i*.084112,u*.53271,i*.084112,u*.5);c.closePath();a=c.createLinearGradient(0,.084112*u,0,.644859*u);a.addColorStop(0,"rgba(255, 255, 255, 0.275)");a.addColorStop(1,"rgba(255, 255, 255, 0.015)");break;case"type1":default:c.beginPath();c.moveTo(i*.084112,u*.509345);c.bezierCurveTo(i*.205607,u*.448598,i*.336448,u*.415887,i*.5,u*.415887);c.bezierCurveTo(i*.672897,u*.415887,i*.789719,u*.443925,i*.915887,u*.509345);c.bezierCurveTo(i*.915887,u*.2757,i*.738317,u*.084112,i*.5,u*.084112);c.bezierCurveTo(i*.261682,u*.084112,i*.084112,u*.2757,i*.084112,u*.509345);c.closePath();a=c.createLinearGradient(0,.088785*u,0,.490654*u);a.addColorStop(0,"rgba(255, 255, 255, 0.275)");a.addColorStop(1,"rgba(255, 255, 255, 0.015)")}c.fillStyle=a;c.fill();tt.cache[k]=b}return n.drawImage(tt.cache[k],0,0),this};tt.cache={};l=function(n,i,u){var h,f,o=n/2,s=n/2,e,c=n.toString()+i.type+u.style;if(!l.cache[c]){h=r(n*1.18889,n*1.18889);f=h.getContext("2d");switch(i.type){case"metalKnob":f.beginPath();f.moveTo(0,n*.5);f.bezierCurveTo(0,n*.222222,n*.222222,0,n*.5,0);f.bezierCurveTo(n*.777777,0,n,n*.222222,n,n*.5);f.bezierCurveTo(n,n*.777777,n*.777777,n,n*.5,n);f.bezierCurveTo(n*.222222,n,0,n*.777777,0,n*.5);f.closePath();e=f.createLinearGradient(0,0,0,n);e.addColorStop(0,"rgb(92, 95, 101)");e.addColorStop(.47,"rgb(46, 49, 53)");e.addColorStop(1,"rgb(22, 23, 26)");f.fillStyle=e;f.fill();f.beginPath();f.moveTo(n*.055555,n*.5);f.bezierCurveTo(n*.055555,n*.277777,n*.277777,n*.055555,n*.5,n*.055555);f.bezierCurveTo(n*.722222,n*.055555,n*.944444,n*.277777,n*.944444,n*.5);f.bezierCurveTo(n*.944444,n*.722222,n*.722222,n*.944444,n*.5,n*.944444);f.bezierCurveTo(n*.277777,n*.944444,n*.055555,n*.722222,n*.055555,n*.5);f.closePath();e=f.createLinearGradient(0,.055555*n,0,.944443*n);switch(u.style){case"black":e.addColorStop(0,"rgb(43, 42, 47)");e.addColorStop(1,"rgb(26, 27, 32)");break;case"brass":e.addColorStop(0,"rgb(150, 110, 54)");e.addColorStop(1,"rgb(124, 95, 61)");break;case"silver":default:e.addColorStop(0,"rgb(204, 204, 204)");e.addColorStop(1,"rgb(87, 92, 98)")}f.fillStyle=e;f.fill();f.beginPath();f.moveTo(n*.777777,n*.833333);f.bezierCurveTo(n*.722222,n*.722222,n*.611111,n*.666666,n*.5,n*.666666);f.bezierCurveTo(n*.388888,n*.666666,n*.277777,n*.722222,n*.222222,n*.833333);f.bezierCurveTo(n*.277777,n*.888888,n*.388888,n*.944444,n*.5,n*.944444);f.bezierCurveTo(n*.611111,n*.944444,n*.722222,n*.888888,n*.777777,n*.833333);f.closePath();e=f.createRadialGradient(.555555*n,.944444*n,0,.555555*n,.944444*n,.388888*n);e.addColorStop(0,"rgba(255, 255, 255, 0.6)");e.addColorStop(1,"rgba(255, 255, 255, 0)");f.fillStyle=e;f.fill();f.beginPath();f.moveTo(n*.944444,n*.277777);f.bezierCurveTo(n*.833333,n*.111111,n*.666666,0,n*.5,0);f.bezierCurveTo(n*.333333,0,n*.166666,n*.111111,n*.055555,n*.277777);f.bezierCurveTo(n*.166666,n*.333333,n*.333333,n*.388888,n*.5,n*.388888);f.bezierCurveTo(n*.666666,n*.388888,n*.833333,n*.333333,n*.944444,n*.277777);f.closePath();e=f.createRadialGradient(.5*n,0,0,.5*n,0,.583333*n);e.addColorStop(0,"rgba(255, 255, 255, 0.749019)");e.addColorStop(1,"rgba(255, 255, 255, 0)");f.fillStyle=e;f.fill();f.beginPath();f.moveTo(n*.277777,n*.555555);f.bezierCurveTo(n*.277777,n*.388888,n*.388888,n*.277777,n*.5,n*.277777);f.bezierCurveTo(n*.611111,n*.277777,n*.777777,n*.388888,n*.777777,n*.555555);f.bezierCurveTo(n*.777777,n*.666666,n*.611111,n*.777777,n*.5,n*.777777);f.bezierCurveTo(n*.388888,n*.777777,n*.277777,n*.666666,n*.277777,n*.555555);f.closePath();e=f.createLinearGradient(0,.277777*n,0,.722221*n);e.addColorStop(0,"#000000");e.addColorStop(1,"rgb(204, 204, 204)");f.fillStyle=e;f.fill();f.beginPath();f.moveTo(n*.333333,n*.555555);f.bezierCurveTo(n*.333333,n*.444444,n*.388888,n*.333333,n*.5,n*.333333);f.bezierCurveTo(n*.611111,n*.333333,n*.722222,n*.444444,n*.722222,n*.555555);f.bezierCurveTo(n*.722222,n*.611111,n*.611111,n*.722222,n*.5,n*.722222);f.bezierCurveTo(n*.388888,n*.722222,n*.333333,n*.611111,n*.333333,n*.555555);f.closePath();e=f.createLinearGradient(0,.333333*n,0,.666666*n);e.addColorStop(0,"rgb(10, 9, 1)");e.addColorStop(1,"rgb(42, 41, 37)");f.fillStyle=e;f.fill();break;case"standardKnob":e=f.createLinearGradient(0,0,0,n);e.addColorStop(0,"rgb(180, 180, 180)");e.addColorStop(.46,"rgb(63, 63, 63)");e.addColorStop(1,"rgb(40, 40, 40)");f.fillStyle=e;f.beginPath();f.arc(o,s,n/2,0,t,!0);f.closePath();f.fill();e=f.createLinearGradient(0,n-n*.77,0,n-n*.77+n*.77);switch(u.style){case"black":e.addColorStop(0,"rgb(191, 191, 191)");e.addColorStop(.5,"rgb(45, 44, 49)");e.addColorStop(1,"rgb(125, 126, 128)");break;case"brass":e.addColorStop(0,"rgb(223, 208, 174)");e.addColorStop(.5,"rgb(123, 95, 63)");e.addColorStop(1,"rgb(207, 190, 157)");break;case"silver":default:e.addColorStop(0,"rgb(215, 215, 215)");e.addColorStop(.5,"rgb(116, 116, 116)");e.addColorStop(1,"rgb(215, 215, 215)")}f.fillStyle=e;f.beginPath();f.arc(o,s,n*.77/2,0,t,!0);f.closePath();f.fill();e=f.createRadialGradient(o,s,0,o,s,n*.77/2);e.addColorStop(0,"rgba(0, 0, 0, 0)");e.addColorStop(.75,"rgba(0, 0, 0, 0)");e.addColorStop(.76,"rgba(0, 0, 0, 0.01)");e.addColorStop(1,"rgba(0, 0, 0, 0.2)");f.fillStyle=e;f.beginPath();f.arc(o,s,n*.77/2,0,t,!0);f.closePath();f.fill()}l.cache[c]=h}return l.cache[c]};l.cache={};a=function(n,i,f){var c,e,s=2*Math.round(n/4),h=2*Math.round(n/4),o,l=n.toString()+i+f.outerColor_ON;if(!a.cache[l]){c=r(n,n);e=c.getContext("2d");switch(i){case 0:o=e.createRadialGradient(s,h,0,s,h,n*.5/2);o.addColorStop(0,f.innerColor1_OFF);o.addColorStop(.2,f.innerColor2_OFF);o.addColorStop(1,f.outerColor_OFF);e.fillStyle=o;e.beginPath();e.arc(s,h,n*.5/2,0,t,!0);e.closePath();e.fill();o=e.createRadialGradient(s,h,0,s,h,n*.5/2);o.addColorStop(0,"rgba(0, 0, 0, 0)");o.addColorStop(.8,"rgba(0, 0, 0, 0)");o.addColorStop(1,"rgba(0, 0, 0, 0.4)");e.fillStyle=o;e.beginPath();e.arc(s,h,n*.5/2,0,t,!0);e.closePath();e.fill();o=e.createLinearGradient(0,.35*n,0,.35*n+.15*n);o.addColorStop(0,"rgba(255, 255, 255, 0.4)");o.addColorStop(1,"rgba(255, 255, 255, 0)");e.fillStyle=o;e.beginPath();e.arc(s,.35*n+.2*n/2,n*.2,0,t,!0);e.closePath();e.fill();break;case 1:o=e.createRadialGradient(s,h,0,s,h,n*.5/2);o.addColorStop(0,f.innerColor1_ON);o.addColorStop(.2,f.innerColor2_ON);o.addColorStop(1,f.outerColor_ON);e.fillStyle=o;e.beginPath();e.arc(s,h,n*.5/2,0,t,!0);e.closePath();e.fill();o=e.createRadialGradient(s,h,0,s,h,n*.5/2);o.addColorStop(0,"rgba(0, 0, 0, 0)");o.addColorStop(.8,"rgba(0, 0, 0, 0)");o.addColorStop(1,"rgba(0, 0, 0, 0.4)");e.fillStyle=o;e.beginPath();e.arc(s,h,n*.5/2,0,t,!0);e.closePath();e.fill();o=e.createLinearGradient(0,.35*n,0,.35*n+.15*n);o.addColorStop(0,"rgba(255, 255, 255, 0.4)");o.addColorStop(1,"rgba(255, 255, 255, 0)");e.fillStyle=o;e.beginPath();e.arc(s,.35*n+.2*n/2,n*.2,0,t,!0);e.closePath();e.fill();o=e.createRadialGradient(s,h,0,s,h,n/2);o.addColorStop(0,u(f.coronaColor,0));o.addColorStop(.6,u(f.coronaColor,.4));o.addColorStop(.7,u(f.coronaColor,.25));o.addColorStop(.8,u(f.coronaColor,.15));o.addColorStop(.85,u(f.coronaColor,.05));o.addColorStop(1,u(f.coronaColor,0));e.fillStyle=o;e.beginPath();e.arc(s,h,n/2,0,t,!0);e.closePath();e.fill()}a.cache[l]=c}return a.cache[l]};a.cache={};it=function(n,t,i){var e,f,o=0,v=n,c=t,l=Math.min(n,t)*.095,u,s=1,y=n-2,a=t-2,p=l-1,h=n.toString()+t+JSON.stringify(i);return it.cache[h]||(e=r(n,t),f=e.getContext("2d"),u=f.createLinearGradient(0,o,0,o+c),u.addColorStop(0,"#4c4c4c"),u.addColorStop(.08,"#666666"),u.addColorStop(.92,"#666666"),u.addColorStop(1,"#e6e6e6"),f.fillStyle=u,dt(f,0,o,v,c,l),f.fill(),u=f.createLinearGradient(0,s,0,s+a),u.addColorStop(0,i.gradientStartColor),u.addColorStop(.03,i.gradientFraction1Color),u.addColorStop(.49,i.gradientFraction2Color),u.addColorStop(.5,i.gradientFraction3Color),u.addColorStop(1,i.gradientStopColor),f.fillStyle=u,dt(f,1,s,y,a,p),f.fill(),it.cache[h]=e),it.cache[h]};it.cache={};et=function(n,t,i,r){var f,u,e=n.toString()+t+i+r;return et.cache[e]||(f=d.createElement("canvas"),u=f.getContext("2d"),f.width=n,f.height=n,u.fillStyle=t,i?(u.beginPath(),u.moveTo(n*.5,n),u.lineTo(0,0),u.lineTo(n,0),u.closePath(),u.fill()):r?(u.beginPath(),u.moveTo(n,n*.5),u.lineTo(0,0),u.lineTo(0,n),u.closePath(),u.fill()):(u.beginPath(),u.moveTo(n*.5,0),u.lineTo(n,n),u.lineTo(0,n),u.closePath(),u.fill()),et.cache[e]=f),et.cache[e]};et.cache={};w=function(n,i,f){var o=n*2,h,e,s,c=i.state+n+JSON.stringify(f),l=function(){var r=f[0];i.state==="up"?(s=e.createRadialGradient(.5*n,.2*o,0,.5*n,.2*o,.5*n),s.addColorStop(0,r.innerColor1_ON),s.addColorStop(.2,r.innerColor2_ON),s.addColorStop(1,r.outerColor_ON)):(s=e.createLinearGradient(0,0,0,.5*o),s.addColorStop(0,"#323232"),s.addColorStop(1,"#5c5c5c"));e.fillStyle=s;e.beginPath();e.moveTo(.5*n,0);e.lineTo(n,.2*o);e.lineTo(.752*n,.2*o);e.lineTo(.752*n,.37*o);e.lineTo(.252*n,.37*o);e.lineTo(.252*n,.2*o);e.lineTo(0,.2*o);e.closePath();e.fill();i.state!=="up"?(e.strokeStyle="rgba(0, 0, 0, 0.4)",e.beginPath(),e.moveTo(0,.2*o),e.lineTo(.5*n,0),e.lineTo(n,.2*o),e.moveTo(.252*n,.2*o),e.lineTo(.252*n,.37*o),e.stroke(),e.strokeStyle="rgba(255, 255, 255, 0.3)",e.beginPath(),e.moveTo(.252*n,.37*o),e.lineTo(.752*n,.37*o),e.lineTo(.752*n,.2*o),e.lineTo(n,.2*o),e.stroke()):(s=e.createRadialGradient(.5*n,.2*o,0,.5*n,.2*o,.7*n),s.addColorStop(0,u(r.coronaColor,0)),s.addColorStop(.5,u(r.coronaColor,.3)),s.addColorStop(.7,u(r.coronaColor,.2)),s.addColorStop(.8,u(r.coronaColor,.1)),s.addColorStop(.85,u(r.coronaColor,.05)),s.addColorStop(1,u(r.coronaColor,0)),e.fillStyle=s,e.beginPath(),e.arc(.5*n,.2*o,.7*n,0,t,!0),e.closePath(),e.fill())},a=function(){var r=f[1];e.beginPath();i.state==="steady"?(s=r.outerColor_ON,e.fillStyle=s,e.rect(.128*n,.41*o,.744*n,.074*o),e.rect(.128*n,.516*o,.744*n,.074*o),e.closePath(),e.fill()):(s=e.createLinearGradient(0,.41*o,0,.41*o+.074*o),s.addColorStop(0,"#323232"),s.addColorStop(1,"#5c5c5c"),e.fillStyle=s,e.rect(.128*n,.41*o,.744*n,.074*o),e.closePath(),e.fill(),s=e.createLinearGradient(0,.516*o,0,.516*o+.074*o),s.addColorStop(0,"#323232"),s.addColorStop(1,"#5c5c5c"),e.fillStyle=s,e.rect(.128*n,.516*o,.744*n,.074*o),e.closePath(),e.fill());i.state!=="steady"?(e.strokeStyle="rgba(0, 0, 0, 0.4)",e.beginPath(),e.moveTo(.128*n,.41*o+.074*o),e.lineTo(.128*n,.41*o),e.lineTo(.128*n+.744*n,.41*o),e.stroke(),e.beginPath(),e.moveTo(.128*n,.516*o+.074*o),e.lineTo(.128*n,.516*o),e.lineTo(.128*n+.744*n,.516*o),e.stroke(),e.strokeStyle="rgba(255, 255, 255, 0.3)",e.beginPath(),e.moveTo(.128*n+.744*n,.41*o),e.lineTo(.128*n+.744*n,.41*o+.074*o),e.lineTo(.128*n,.41*o+.074*o),e.stroke(),e.beginPath(),e.moveTo(.128*n+.744*n,.516*o),e.lineTo(.128*n+.744*n,.516*o+.074*o),e.lineTo(.128*n,.516*o+.074*o),e.stroke()):(s=e.createRadialGradient(.5*n,.5*o,0,.5*n,.5*o,.7*n),s.addColorStop(0,u(r.coronaColor,0)),s.addColorStop(.5,u(r.coronaColor,.3)),s.addColorStop(.7,u(r.coronaColor,.2)),s.addColorStop(.8,u(r.coronaColor,.1)),s.addColorStop(.85,u(r.coronaColor,.05)),s.addColorStop(1,u(r.coronaColor,0)),e.fillStyle=s,e.beginPath(),e.arc(.5*n,.5*o,.7*n,0,t,!0),e.closePath(),e.fill())},v=function(){var r=f[2];i.state==="down"?(s=e.createRadialGradient(.5*n,.8*o,0,.5*n,.8*o,.5*n),s.addColorStop(0,r.innerColor1_ON),s.addColorStop(.2,r.innerColor2_ON),s.addColorStop(1,r.outerColor_ON)):(s=e.createLinearGradient(0,.63*o,0,o),s.addColorStop(0,"#323232"),s.addColorStop(1,"#5c5c5c"));e.beginPath();e.fillStyle=s;e.moveTo(.5*n,o);e.lineTo(n,.8*o);e.lineTo(.725*n,.8*o);e.lineTo(.725*n,.63*o);e.lineTo(.252*n,.63*o);e.lineTo(.252*n,.8*o);e.lineTo(0,.8*o);e.closePath();e.fill();i.state!=="down"?(e.strokeStyle="rgba(0, 0, 0, 0.4)",e.beginPath(),e.moveTo(0,.8*o),e.lineTo(.252*n,.8*o),e.moveTo(.252*n,.63*o),e.lineTo(.752*n,.63*o),e.stroke(),e.beginPath(),e.moveTo(.752*n,.8*o),e.lineTo(n,.8*o),e.stroke(),e.strokeStyle="rgba(255, 255, 255, 0.3)",e.beginPath(),e.moveTo(0,.8*o),e.lineTo(.5*n,o),e.lineTo(n,.8*o),e.stroke(),e.beginPath(),e.moveTo(.752*n,.8*o),e.lineTo(.752*n,.63*o),e.stroke()):(s=e.createRadialGradient(.5*n,.8*o,0,.5*n,.8*o,.7*n),s.addColorStop(0,u(r.coronaColor,0)),s.addColorStop(.5,u(r.coronaColor,.3)),s.addColorStop(.7,u(r.coronaColor,.2)),s.addColorStop(.8,u(r.coronaColor,.1)),s.addColorStop(.85,u(r.coronaColor,.05)),s.addColorStop(1,u(r.coronaColor,0)),e.fillStyle=s,e.beginPath(),e.arc(.5*n,.8*o,.7*n,0,t,!0),e.closePath(),e.fill())};if(!w.cache[c]){h=r(n*2,n*4);e=h.getContext("2d");e.translate(n*.5,n*.5);switch(i.state){case"up":v();a();l();break;case"steady":v();l();a();break;case"down":default:l();a();v()}w.cache[c]=h}return w.cache[c]};w.cache={};var fi=function(n,t,i,r,u,f,e,o,h,c){c=undefined===c?c=steelseries.GaugeType.TYPE1:c;n.save();n.textAlign=o?"center":"left";n.textBaseline="middle";n.strokeStyle=f.labelColor.getRgbaColor();n.fillStyle=f.labelColor.getRgbaColor();o?(n.font=.046728*t+"px "+s,n.fillText(r,t/2,i*.3,t*.3),n.fillText(u,t/2,i*.38,t*.3)):e?(n.font=.1*t+"px "+s,n.save(),n.translate(.671428*t,.1375*i),n.rotate(1.570796),n.fillText(r,0,0),n.translate(-.671428*t,-.1375*i),n.restore(),n.font=.071428*t+"px "+s,h?c.type==="type2"?(n.textAlign="right",n.fillText(u,.36*t,i*.79,t*.25)):n.fillText(u,.63*t,i*.85,t*.2):(n.textAlign="center",c.type==="type2"?n.fillText(u,t/2,i*.92,t*.2):n.fillText(u,t/2,i*.89,t*.2))):(n.font=.035*t+"px "+s,n.fillText(r,t*.15,i*.25,t*.3),n.font=.025*t+"px "+s,n.fillText(u,t*.0625,i*.7,t*.07));n.restore()},wi=ii(12,12,function(n){var u=n.canvas.width,t=n.canvas.height,f=0,r=0,i;n.save();n.save();n.beginPath();n.rect(0,0,u*.5,t*.5);n.closePath();n.restore();i=n.createLinearGradient(0,r*t,0,.5*t+r*t);i.addColorStop(0,"rgb(35, 35, 35)");i.addColorStop(1,"rgb(23, 23, 23)");n.fillStyle=i;n.fill();n.save();n.beginPath();n.rect(u*.083333,0,u*.333333,t*.416666);n.closePath();n.restore();f=.083333;r=0;i=n.createLinearGradient(0,r*t,0,.416666*t+r*t);i.addColorStop(0,"rgb(38, 38, 38)");i.addColorStop(1,"rgb(30, 30, 30)");n.fillStyle=i;n.fill();n.save();n.beginPath();n.rect(u*.5,t*.5,u*.5,t*.5);n.closePath();n.restore();f=.5;r=.5;i=n.createLinearGradient(0,r*t,0,.5*t+r*t);i.addColorStop(0,"rgb(35, 35, 35)");i.addColorStop(1,"rgb(23, 23, 23)");n.fillStyle=i;n.fill();n.save();n.beginPath();n.rect(u*.583333,t*.5,u*.333333,t*.416666);n.closePath();n.restore();f=.583333;r=.5;i=n.createLinearGradient(0,r*t,0,.416666*t+r*t);i.addColorStop(0,"rgb(38, 38, 38)");i.addColorStop(1,"rgb(30, 30, 30)");n.fillStyle=i;n.fill();n.save();n.beginPath();n.rect(u*.5,0,u*.5,t*.5);n.closePath();n.restore();f=.5;r=0;i=n.createLinearGradient(0,r*t,0,.5*t+r*t);i.addColorStop(0,"#303030");i.addColorStop(1,"rgb(40, 40, 40)");n.fillStyle=i;n.fill();n.save();n.beginPath();n.rect(u*.583333,t*.083333,u*.333333,t*.416666);n.closePath();n.restore();f=.583333;r=.083333;i=n.createLinearGradient(0,r*t,0,.416666*t+r*t);i.addColorStop(0,"rgb(53, 53, 53)");i.addColorStop(1,"rgb(45, 45, 45)");n.fillStyle=i;n.fill();n.save();n.beginPath();n.rect(0,t*.5,u*.5,t*.5);n.closePath();n.restore();f=0;r=.5;i=n.createLinearGradient(0,r*t,0,.5*t+r*t);i.addColorStop(0,"#303030");i.addColorStop(1,"#282828");n.fillStyle=i;n.fill();n.save();n.beginPath();n.rect(u*.083333,t*.583333,u*.333333,t*.416666);n.closePath();n.restore();f=.083333;r=.583333;i=n.createLinearGradient(0,r*t,0,.416666*t+r*t);i.addColorStop(0,"#353535");i.addColorStop(1,"#2d2d2d");n.fillStyle=i;n.fill();n.restore()}),bi=ii(15,15,function(n){var i=n.canvas.width,t=n.canvas.height,r;n.save();n.save();n.beginPath();n.rect(0,0,i,t);n.closePath();n.restore();n.fillStyle="#1D2123";n.fill();n.save();n.beginPath();n.moveTo(0,t*.266666);n.bezierCurveTo(0,t*.4,i*.066666,t*.466666,i*.2,t*.466666);n.bezierCurveTo(i*.333333,t*.466666,i*.4,t*.4,i*.4,t*.266666);n.bezierCurveTo(i*.4,t*.133333,i*.333333,t*.066666,i*.2,t*.066666);n.bezierCurveTo(i*.066666,t*.066666,0,t*.133333,0,t*.266666);n.closePath();r=n.createLinearGradient(0,.066666*t,0,.466666*t);r.addColorStop(0,"#000000");r.addColorStop(1,"#444444");n.fillStyle=r;n.fill();n.save();n.beginPath();n.moveTo(0,t*.2);n.bezierCurveTo(0,t*.333333,i*.066666,t*.4,i*.2,t*.4);n.bezierCurveTo(i*.333333,t*.4,i*.4,t*.333333,i*.4,t*.2);n.bezierCurveTo(i*.4,t*.066666,i*.333333,0,i*.2,0);n.bezierCurveTo(i*.066666,0,0,t*.066666,0,t*.2);n.closePath();n.fillStyle="#050506";n.fill();n.save();n.beginPath();n.moveTo(i*.466666,t*.733333);n.bezierCurveTo(i*.466666,t*.866666,i*.533333,t*.933333,i*.666666,t*.933333);n.bezierCurveTo(i*.8,t*.933333,i*.866666,t*.866666,i*.866666,t*.733333);n.bezierCurveTo(i*.866666,t*.6,i*.8,t*.533333,i*.666666,t*.533333);n.bezierCurveTo(i*.533333,t*.533333,i*.466666,t*.6,i*.466666,t*.733333);n.closePath();r=n.createLinearGradient(0,.533333*t,0,.933333*t);r.addColorStop(0,"#000000");r.addColorStop(1,"#444444");n.fillStyle=r;n.fill();n.save();n.beginPath();n.moveTo(i*.466666,t*.666666);n.bezierCurveTo(i*.466666,t*.8,i*.533333,t*.866666,i*.666666,t*.866666);n.bezierCurveTo(i*.8,t*.866666,i*.866666,t*.8,i*.866666,t*.666666);n.bezierCurveTo(i*.866666,t*.533333,i*.8,t*.466666,i*.666666,t*.466666);n.bezierCurveTo(i*.533333,t*.466666,i*.466666,t*.533333,i*.466666,t*.666666);n.closePath();n.fillStyle="#050506";n.fill();n.restore()}),ki=function(n,t,i,u,f){function e(n,t){return n+=(2*Math.random()-1)*t|0,n<0?0:n>255?255:n}function s(n){return n<0?0:n>255?255:n}function h(n,t,i,r,u,f){var o,v,e,a,s,h,c,l;for(u>=i&&(u=i-1),a=1/(u*2+1),s=0,v=0;vu&&(e=(s-u-1)*4,h-=n.data[e],c-=n.data[e+1],l-=n.data[e+2]),o+u>16&255,at=n>>8&255,vt=n&255,tt=0,it=255*i,yt,pt,wt,w,rt,ut,ft,et;if(c=Math.floor(c),l=Math.floor(l),a=Math.ceil(a),v=Math.ceil(v),p=a-c,b=v-l,st=r(p,b),g=st.getContext("2d"),y=g.createImageData(p,b),ht=g.createImageData(p,b),f!==0)for(ot=[],k=0;k0?(h(y,ht,p,b,t,ct),g.putImageData(ht,c,l)):g.putImageData(y,c,l),st},this},n=function(n,t,i,r){function s(){u=p(n,255);f=p(t,255);e=p(i,255);o=p(r,1)}var u,f,e,o;arguments.length===1?(i=parseInt(n.substr(5,2),16),t=parseInt(n.substr(3,2),16),n=parseInt(n.substr(1,2),16),r=1):arguments.length===3&&(r=1);s();this.getRed=function(){return u};this.setRed=function(n){u=p(n,255)};this.getGreen=function(){return f};this.setGreen=function(n){f=p(n,255)};this.getBlue=function(){return e};this.setBlue=function(n){e=p(n,255)};this.getAlpha=function(){return o};this.setAlpha=function(n){o=p(n,1)};this.getRgbaColor=function(){return"rgba("+u+", "+f+", "+e+", "+o+")"};this.getRgbColor=function(){return"rgb("+u+", "+f+", "+e+")"};this.getHexColor=function(){return"#"+u.toString(16)+f.toString(16)+e.toString(16)}},at=function(n,i){for(var f=n.length-1,u=0;u<=f;u++)n[u]=t*n[u]-o;this.fillCircle=function(t,e,o,s,h){var w,l=Math.ceil(h),c=l*2,a,tt,v,y,b,k,it,g,p,d,nt,rt;for(a=t.createImageData(c,c),tt=255,y=0;y=s){for(w=Math.atan2(b,k),u=0;u=n[u]&&wl&&v<=h-l&&a>c&&a=n[u]&&w1?1:n,t=0;tn&&f>=i[t]&&(f=i[t],o=t)}return s=(n-u)/(f-u),kt(r[e],r[o],1,s)};this.getStart=function(){return n};this.getEnd=function(){return t}};Math.log10=function(n){return Math.log(n)/Math.LN10};v=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(n){window.setTimeout(n,1e3/16)}}(),function(){e=function(n,t,i,r,u,f){this.gradientStart=n;this.gradientFraction=t;this.gradientStop=i;this.labelColor=r;this.symbolColor=u;this.name=f}}(),function(){f=function(n,t,i,r,u,f){this.gradientStartColor=n;this.gradientFraction1Color=t;this.gradientFraction2Color=i;this.gradientFraction3Color=r;this.gradientStopColor=u;this.textColor=f}}(),function(){y=function(n,t,i,r,u,f){this.veryDark=n;this.dark=t;this.medium=i;this.light=r;this.lighter=u;this.veryLight=f}}(),function(){ut=function(n,t,i,r,u,f,e){this.innerColor1_ON=n;this.innerColor2_ON=t;this.outerColor_ON=i;this.coronaColor=r;this.innerColor1_OFF=u;this.innerColor2_OFF=f;this.outerColor_OFF=e}}(),function(){ct=function(n){this.type=n}}(),function(){vt=function(n){this.type=n}}(),function(){ui=function(n){this.type=n}}(),function(){gt=function(n){this.style=n}}(),function(){b=function(n){this.design=n}}(),function(){h=function(n){this.type=n}}(),function(){lt=function(n){this.type=n}}(),function(){ni=function(n){this.format=n}}(),function(){ti=function(n){this.type=n}}(),function(){yt=function(n){this.state=n}}();var tr={DARK_GRAY:new e(new n(0,0,0,1),new n(51,51,51,1),new n(153,153,153,1),new n(255,255,255,1),new n(180,180,180,1),"DARK_GRAY"),SATIN_GRAY:new e(new n(45,57,57,1),new n(45,57,57,1),new n(45,57,57,1),new n(167,184,180,1),new n(137,154,150,1),"SATIN_GRAY"),LIGHT_GRAY:new e(new n(130,130,130,1),new n(181,181,181,1),new n(253,253,253,1),new n(0,0,0,1),new n(80,80,80,1),"LIGHT_GRAY"),WHITE:new e(new n(255,255,255,1),new n(255,255,255,1),new n(255,255,255,1),new n(0,0,0,1),new n(80,80,80,1),"WHITE"),BLACK:new e(new n(0,0,0,1),new n(0,0,0,1),new n(0,0,0,1),new n(255,255,255,1),new n(150,150,150,1),"BLACK"),BEIGE:new e(new n(178,172,150,1),new n(204,205,184,1),new n(231,231,214,1),new n(0,0,0,1),new n(80,80,80,1),"BEIGE"),BROWN:new e(new n(245,225,193,1),new n(245,225,193,1),new n(255,250,240,1),new n(109,73,47,1),new n(89,53,27,1),"BROWN"),RED:new e(new n(198,93,95,1),new n(212,132,134,1),new n(242,218,218,1),new n(0,0,0,1),new n(90,0,0,1),"RED"),GREEN:new e(new n(65,120,40,1),new n(129,171,95,1),new n(218,237,202,1),new n(0,0,0,1),new n(0,90,0,1),"GREEN"),BLUE:new e(new n(45,83,122,1),new n(115,144,170,1),new n(227,234,238,1),new n(0,0,0,1),new n(0,0,90,1),"BLUE"),ANTHRACITE:new e(new n(50,50,54,1),new n(47,47,51,1),new n(69,69,74,1),new n(250,250,250,1),new n(180,180,180,1),"ANTHRACITE"),MUD:new e(new n(80,86,82,1),new n(70,76,72,1),new n(57,62,58,1),new n(255,255,240,1),new n(225,225,210,1),"MUD"),PUNCHED_SHEET:new e(new n(50,50,54,1),new n(47,47,51,1),new n(69,69,74,1),new n(255,255,255,1),new n(180,180,180,1),"PUNCHED_SHEET"),CARBON:new e(new n(50,50,54,1),new n(47,47,51,1),new n(69,69,74,1),new n(255,255,255,1),new n(180,180,180,1),"CARBON"),STAINLESS:new e(new n(130,130,130,1),new n(181,181,181,1),new n(253,253,253,1),new n(0,0,0,1),new n(80,80,80,1),"STAINLESS"),BRUSHED_METAL:new e(new n(50,50,54,1),new n(47,47,51,1),new n(69,69,74,1),new n(0,0,0,1),new n(80,80,80,1),"BRUSHED_METAL"),BRUSHED_STAINLESS:new e(new n(50,50,54,1),new n(47,47,51,1),new n(110,110,112,1),new n(0,0,0,1),new n(80,80,80,1),"BRUSHED_STAINLESS"),TURNED:new e(new n(130,130,130,1),new n(181,181,181,1),new n(253,253,253,1),new n(0,0,0,1),new n(80,80,80,1),"TURNED")},ir={BEIGE:new f("#c8c8b1","rgb(241, 237, 207)","rgb(234, 230, 194)","rgb(225, 220, 183)","rgb(237, 232, 191)","#000000"),BLUE:new f("#ffffff","rgb(231, 246, 255)","rgb(170, 224, 255)","rgb(136, 212, 255)","rgb(192, 232, 255)","#124564"),ORANGE:new f("#ffffff","rgb(255, 245, 225)","rgb(255, 217, 147)","rgb(255, 201, 104)","rgb(255, 227, 173)","#503700"),RED:new f("#ffffff","rgb(255, 225, 225)","rgb(253, 152, 152)","rgb(252, 114, 115)","rgb(254, 178, 178)","#4f0c0e"),YELLOW:new f("#ffffff","rgb(245, 255, 186)","rgb(210, 255, 0)","rgb(158, 205, 0)","rgb(210, 255, 0)","#405300"),WHITE:new f("#ffffff","#ffffff","rgb(241, 246, 242)","rgb(229, 239, 244)","#ffffff","#000000"),GRAY:new f("#414141","rgb(117, 117, 117)","rgb(87, 87, 87)","#414141","rgb(81, 81, 81)","#ffffff"),BLACK:new f("#414141","#666666","#333333","#000000","#333333","#cccccc"),GREEN:new f("rgb(33, 67, 67)","rgb(33, 67, 67)","rgb(29, 58, 58)","rgb(28, 57, 57)","rgb(23, 46, 46)","rgba(0, 185, 165, 255)"),BLUE2:new f("rgb(0, 68, 103)","rgb(8, 109, 165)","rgb(0, 72, 117)","rgb(0, 72, 117)","rgb(0, 68, 103)","rgb(111, 182, 228)"),BLUE_BLACK:new f("rgb(22, 125, 212)","rgb(3, 162, 254)","rgb(3, 162, 254)","rgb(3, 162, 254)","rgb(11, 172, 244)","#000000"),BLUE_DARKBLUE:new f("rgb(18, 33, 88)","rgb(18, 33, 88)","rgb(19, 30, 90)","rgb(17, 31, 94)","rgb(21, 25, 90)","rgb(23, 99, 221)"),BLUE_GRAY:new f("rgb(135, 174, 255)","rgb(101, 159, 255)","rgb(44, 93, 255)","rgb(27, 65, 254)","rgb(12, 50, 255)","#b2b4ed"),STANDARD:new f("rgb(131, 133, 119)","rgb(176, 183, 167)","rgb(165, 174, 153)","rgb(166, 175, 156)","rgb(175, 184, 165)","rgb(35, 42, 52)"),STANDARD_GREEN:new f("#ffffff","rgb(219, 230, 220)","rgb(179, 194, 178)","rgb(153, 176, 151)","rgb(114, 138, 109)","#080C06"),BLUE_BLUE:new f("rgb(100, 168, 253)","rgb(100, 168, 253)","rgb(95, 160, 250)","rgb(80, 144, 252)","rgb(74, 134, 255)","#002cbb"),RED_DARKRED:new f("rgb(72, 36, 50)","rgb(185, 111, 110)","rgb(148, 66, 72)","rgb(83, 19, 20)","rgb(7, 6, 14)","#FE8B92"),DARKBLUE:new f("rgb(14, 24, 31)","rgb(46, 105, 144)","rgb(19, 64, 96)","rgb(6, 20, 29)","rgb(8, 9, 10)","#3DB3FF"),LILA:new f("rgb(175, 164, 255)","rgb(188, 168, 253)","rgb(176, 159, 255)","rgb(174, 147, 252)","rgb(168, 136, 233)","#076148"),BLACKRED:new f("rgb(8, 12, 11)","rgb(10, 11, 13)","rgb(11, 10, 15)","rgb(7, 13, 9)","rgb(9, 13, 14)","#B50026"),DARKGREEN:new f("rgb(25, 85, 0)","rgb(47, 154, 0)","rgb(30, 101, 0)","rgb(30, 101, 0)","rgb(25, 85, 0)","#233123"),AMBER:new f("rgb(182, 71, 0)","rgb(236, 155, 25)","rgb(212, 93, 5)","rgb(212, 93, 5)","rgb(182, 71, 0)","#593A0A"),LIGHTBLUE:new f("rgb(125, 146, 184)","rgb(197, 212, 231)","rgb(138, 155, 194)","rgb(138, 155, 194)","rgb(125, 146, 184)","#090051"),SECTIONS:new f("#b2b2b2","#ffffff","#c4c4c4","#c4c4c4","#b2b2b2","#000000")},rr={RED:new y(new n(82,0,0,1),new n(158,0,19,1),new n(213,0,25,1),new n(240,82,88,1),new n(255,171,173,1),new n(255,217,218,1)),GREEN:new y(new n(8,54,4,1),new n(0,107,14,1),new n(15,148,0,1),new n(121,186,37,1),new n(190,231,141,1),new n(234,247,218,1)),BLUE:new y(new n(0,11,68,1),new n(0,73,135,1),new n(0,108,201,1),new n(0,141,242,1),new n(122,200,255,1),new n(204,236,255,1)),ORANGE:new y(new n(118,83,30,1),new n(215,67,0,1),new n(240,117,0,1),new n(255,166,0,1),new n(255,255,128,1),new n(255,247,194,1)),YELLOW:new y(new n(41,41,0,1),new n(102,102,0,1),new n(177,165,0,1),new n(255,242,0,1),new n(255,250,153,1),new n(255,252,204,1)),CYAN:new y(new n(15,109,109,1),new n(0,109,144,1),new n(0,144,191,1),new n(0,174,239,1),new n(153,223,249,1),new n(204,239,252,1)),MAGENTA:new y(new n(98,0,114,1),new n(128,24,72,1),new n(191,36,107,1),new n(255,48,143,1),new n(255,172,210,1),new n(255,214,23,1)),WHITE:new y(new n(210,210,210,1),new n(220,220,220,1),new n(235,235,235,1),new n(255,255,255,1),new n(255,255,255,1),new n(255,255,255,1)),GRAY:new y(new n(25,25,25,1),new n(51,51,51,1),new n(76,76,76,1),new n(128,128,128,1),new n(204,204,204,1),new n(243,243,243,1)),BLACK:new y(new n(0,0,0,1),new n(5,5,5,1),new n(10,10,10,1),new n(15,15,15,1),new n(20,20,20,1),new n(25,25,25,1)),RAITH:new y(new n(0,32,65,1),new n(0,65,125,1),new n(0,106,172,1),new n(130,180,214,1),new n(148,203,242,1),new n(191,229,255,1)),GREEN_LCD:new y(new n(0,55,45,1),new n(15,109,93,1),new n(0,185,165,1),new n(48,255,204,1),new n(153,255,227,1),new n(204,255,241,1)),JUG_GREEN:new y(new n(0,56,0,1),new n(32,69,36,1),new n(50,161,0,1),new n(129,206,0,1),new n(190,231,141,1),new n(234,247,218,1))},ur={RED_LED:new ut("#FF9A89","#FF9A89","#FF3300","#FF8D70","#7E1C00","#7E1C00","#641B00"),GREEN_LED:new ut("#9AFF89","#9AFF89","#59FF2A","#A5FF00","#1C7E00","#1C7E00","#1B6400"),BLUE_LED:new ut("#899AFF","#899AFF","#0033FF","#708DFF","#001C7E","#001C7E","#001B64"),ORANGE_LED:new ut("#FEA23F","#FEA23F","#FD6C00","#FD6C00","#592800","#592800","#421F00"),YELLOW_LED:new ut("#FFFF62","#FFFF62","#FFFF00","#FFFF00","#6B6D00","#6B6D00","#515300"),CYAN_LED:new ut("#00FFFF","#00FFFF","#1BC3C3","#00FFFF","#083B3B","#083B3B","#052727"),MAGENTA_LED:new ut("#D300FF","#D300FF","#8600CB","#C300FF","#38004B","#38004B","#280035")},fr={TYPE1:new ct("type1"),TYPE2:new ct("type2"),TYPE3:new ct("type3"),TYPE4:new ct("type4"),TYPE5:new ct("type5")},er={NORTH:new vt("north"),SOUTH:new vt("south"),EAST:new vt("east"),WEST:new vt("west")},or={STANDARD_KNOB:new ui("standardKnob"),METAL_KNOB:new ui("metalKnob")},sr={BLACK:new gt("black"),BRASS:new gt("brass"),SILVER:new gt("silver")},hr={BLACK_METAL:new b("blackMetal"),METAL:new b("metal"),SHINY_METAL:new b("shinyMetal"),BRASS:new b("brass"),STEEL:new b("steel"),CHROME:new b("chrome"),GOLD:new b("gold"),ANTHRACITE:new b("anthracite"),TILTED_GRAY:new b("tiltedGray"),TILTED_BLACK:new b("tiltedBlack"),GLOSSY_METAL:new b("glossyMetal")},cr={TYPE1:new h("type1"),TYPE2:new h("type2"),TYPE3:new h("type3"),TYPE4:new h("type4"),TYPE5:new h("type5"),TYPE6:new h("type6"),TYPE7:new h("type7"),TYPE8:new h("type8"),TYPE9:new h("type9"),TYPE10:new h("type10"),TYPE11:new h("type11"),TYPE12:new h("type12"),TYPE13:new h("type13"),TYPE14:new h("type14"),TYPE15:new h("type15"),TYPE16:new h("type16")},lr={TYPE1:new lt("type1"),TYPE2:new lt("type2"),TYPE3:new lt("type3"),TYPE4:new lt("type4"),TYPE5:new lt("type5")},ar={STANDARD:new ni("standard"),FRACTIONAL:new ni("fractional"),SCIENTIFIC:new ni("scientific")},vr={NORMAL:new ti("normal"),HORIZONTAL:new ti("horizontal"),TANGENT:new ti("tangent")},yr={UP:new yt("up"),STEADY:new yt("steady"),DOWN:new yt("down"),OFF:new yt("off")};return{Radial:hi,RadialBargraph:ci,DisplaySingle:li,WindDirection:ai,Led:vi,Odometer:yi,drawFrame:g,drawBackground:nt,drawForeground:tt,rgbaColor:n,ConicalGradient:at,setAlpha:u,getColorFromFraction:kt,gradientWrapper:di,BackgroundColor:tr,LcdColor:ir,ColorDef:rr,LedColor:ur,GaugeType:fr,Orientation:er,FrameDesign:hr,PointerType:cr,ForegroundType:lr,KnobType:or,KnobStyle:sr,LabelNumberFormat:ar,TickLabelOrientation:vr,TrendState:yr,Section:gi}}() +//# sourceMappingURL=steelseries.min.js.map diff --git a/other-scripts/Steel-Gauges/web_server/script/src/tween.js b/other-scripts/Steel-Gauges/web_server/script/src/tween.js new file mode 100644 index 0000000..73d1cdd --- /dev/null +++ b/other-scripts/Steel-Gauges/web_server/script/src/tween.js @@ -0,0 +1,380 @@ +/*!********************************************************************* +TERMS OF USE - EASING EQUATIONS +Open source under the BSD License. +Copyright (c) 2001 Robert Penner +JavaScript version copyright (C) 2006 by Philippe Maegerman +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of the author nor the names of contributors may +be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*****************************************/ +function Delegate() {} +Delegate.create = function (o, f) { + var a = [], i, l = arguments.length; + for (i = 2; i < l; i++) { + a[i - 2] = arguments[i]; + } + return function () { + var aP = [].concat(arguments, a); + f.apply(o, aP); + }; +}; + +/* +object: + type:Object + The object you want to modify. It can be any object, a visual object that you want to animate ( document.body.style ) or an anymous object ( new Object() ). +property: + type:String + The property that is updated on the target object, it can be empty ('') +easing: + type:Function + The easing that will be applied to motion. +start: + type:Number + Start value +end: + type:Number + End value +duration: + type:Number + Animation duration in seconds +suffixe: + type:String + A string to append to the updated property ('%','pt','em' ...). +*/ + +var Tween = function (obj, prop, func, begin, finish, duration, suffixe) { + this.init(obj, prop, func, begin, finish, duration, suffixe); +}; +var t = Tween.prototype; + +t.obj = {}; +t.prop = ''; +t.func = function (t, b, c, d) { return c * t / d + b; }; +t.begin = 0; +t.change = 0; +t.prevTime = 0; +t.prevPos = 0; +t.looping = false; +t._duration = 0; +t._time = 0; +t._pos = 0; +t._position = 0; +t._startTime = 0; +t._finish = 0; +t.name = ''; +t.suffixe = ''; +t._listeners = []; +t.setTime = function (t) { + this.prevTime = this._time; + if (t > this.getDuration()) { + if (this.looping) { + this.rewind(t - this._duration); + this.update(); + this.broadcastMessage('onMotionLooped', {target: this, type: 'onMotionLooped'}); + } else { + this._time = this._duration; + this.update(); + this.stop(); + this.broadcastMessage('onMotionFinished', {target: this, type: 'onMotionFinished'}); + } + } else if (t < 0) { + this.rewind(); + this.update(); + } else { + this._time = t; + this.update(); + } +}; +t.getTime = function () { + return this._time; +}; +t.setDuration = function (d) { + this._duration = (d === null || d <= 0) ? 100000 : d; +}; +t.getDuration = function () { + return this._duration; +}; +t.setPosition = function (p) { + this.prevPos = this._pos; + var a = this.suffixe !== '' ? this.suffixe : ''; + this.obj[this.prop] = Math.round(p) + a; + this._pos = p; + this.broadcastMessage('onMotionChanged', {target: this, type: 'onMotionChanged'}); +}; +t.getPosition = function (t) { + if (t === undefined) { + t = this._time; + } + return this.func(t, this.begin, this.change, this._duration); +}; +t.setFinish = function (f) { + this.change = f - this.begin; +}; +t.getFinish = function () { + return this.begin + this.change; +}; +t.init = function (obj, prop, func, begin, finish, duration, suffixe) { + if (!arguments.length) { + return; + } + this._listeners = []; + this.addListener(this); + if (suffixe) { + this.suffixe = suffixe; + } + this.obj = obj; + this.prop = prop; + this.begin = begin; + this._pos = begin; + this.setDuration(duration); + if (func !== null && func !== '') { + this.func = func; + } + this.setFinish(finish); +}; +t.start = function () { + this.rewind(); + this.startEnterFrame(); + this.broadcastMessage('onMotionStarted', {target: this, type: 'onMotionStarted'}); + //alert('in'); +}; +t.rewind = function (t) { + this.stop(); + this._time = (t === undefined) ? 0 : t; + this.fixTime(); + this.update(); +}; +t.fforward = function () { + this._time = this._duration; + this.fixTime(); + this.update(); +}; +t.update = function () { + this.setPosition(this.getPosition(this._time)); +}; +t.startEnterFrame = function () { + this.stopEnterFrame(); + this.isPlaying = true; + this.onEnterFrame(); +}; +t.onEnterFrame = function () { + if (this.isPlaying) { + this.nextFrame(); + // To get real smooth movement you have to set the timeout to 0 instead of 25 + setTimeout(Delegate.create(this, this.onEnterFrame), 25); + } +}; +t.nextFrame = function () { + this.setTime((this.getTimer() - this._startTime) / 1000); +}; +t.stop = function () { + this.stopEnterFrame(); + this.broadcastMessage('onMotionStopped', {target: this, type: 'onMotionStopped'}); +}; +t.stopEnterFrame = function () { + this.isPlaying = false; +}; +t.playing = function () { + return this.isPlaying; +}; +t.continueTo = function (finish, duration) { + this.begin = this._pos; + this.setFinish(finish); + if (this._duration !== undefined) { + this.setDuration(duration); + } + this.start(); +}; +t.resume = function () { + this.fixTime(); + this.startEnterFrame(); + this.broadcastMessage('onMotionResumed', {target: this, type: 'onMotionResumed'}); +}; +t.yoyo = function () { + this.continueTo(this.begin, this._time); +}; +t.addListener = function (o) { + this.removeListener(o); + return this._listeners.push(o); +}; +t.removeListener = function (o) { + var a = this._listeners, + i = a.length; + while (i--) { + if (a[i] === o) { + a.splice(i, 1); + return true; + } + } + return false; +}; +t.broadcastMessage = function () { + var arr = [], i, e, a = this._listeners, + l = a.length; + for (i = 0; i < arguments.length; i++) { + arr.push(arguments[i]); + } + e = arr.shift(); + + for (i = 0; i < l; i++) { + if (a[i][e]) { + a[i][e].apply(a[i], arr); + } + } +}; +t.fixTime = function () { + this._startTime = this.getTimer() - this._time * 1000; +}; +t.getTimer = function () { + return new Date().getTime() - this._time; +}; +Tween.backEaseIn = function (t, b, c, d, a, p) { + var s = 1.70158; + return c * (t /= d) * t * ((s + 1) * t - s) + b; +}; +Tween.backEaseOut = function (t, b, c, d, a, p) { + var s = 1.70158; + return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b; +}; +Tween.backEaseInOut = function (t, b, c, d, a, p) { + var s = 1.70158; + if ((t /= d / 2) < 1) { + return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b; + } + return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b; +}; +Tween.elasticEaseIn = function (t, b, c, d, a, p) { + var s; + if (t === 0) { + return b; + } + if ((t /= d) === 1) { + return b + c; + } + if (!p) { + p = d * 0.3; + } + if (!a || a < Math.abs(c)) { + a = c; + s = p / 4; + } else { + s = p / (2 * Math.PI) * Math.asin(c / a); + } + + return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b; + +}; +Tween.elasticEaseOut = function (t, b, c, d, a, p) { + var s; + if (t === 0) { + return b; + } + if ((t /= d) === 1) { + return b + c; + } + if (!p) { + p = d * 0.3; + } + if (!a || a < Math.abs(c)) { + a = c; + s = p / 4; + } else { + s = p / (2 * Math.PI) * Math.asin(c / a); + } + return (a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b); +}; +Tween.elasticEaseInOut = function (t, b, c, d, a, p) { + var s; + if (t === 0) { + return b; + } + if ((t /= d / 2) === 2) { + return b + c; + } + if (!p) { + p = d * (0.3 * 1.5); + } + if (!a || a < Math.abs(c)) { + a = c; + s = p / 4; + } else { + s = p / (2 * Math.PI) * Math.asin(c / a); + } + if (t < 1) { + return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b; + } + return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * 0.5 + c + b; +}; +Tween.bounceEaseOut = function (t, b, c, d) { + if ((t /= d) < (1 / 2.75)) { + return c * (7.5625 * t * t) + b; + } else if (t < (2 / 2.75)) { + return c * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75) + b; + } else if (t < (2.5 / 2.75)) { + return c * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375) + b; + } else { + return c * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375) + b; + } +}; +Tween.bounceEaseIn = function (t, b, c, d) { + return c - Tween.bounceEaseOut(d - t, 0, c, d) + b; +}; +Tween.bounceEaseInOut = function (t, b, c, d) { + if (t < d / 2) { + return Tween.bounceEaseIn(t * 2, 0, c, d) * 0.5 + b; + } else { + return Tween.bounceEaseOut(t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b; + } +}; +Tween.strongEaseInOut = function (t, b, c, d) { + return c * (t /= d) * t * t * t * t + b; +}; +Tween.regularEaseIn = function (t, b, c, d) { + return c * (t /= d) * t + b; +}; +Tween.regularEaseOut = function (t, b, c, d) { + return -c * (t /= d) * (t - 2) + b; +}; +Tween.regularEaseInOut = function (t, b, c, d) { + if ((t /= d / 2) < 1) { + return c / 2 * t * t + b; + } + return -c / 2 * ((--t) * (t - 2) - 1) + b; +}; +Tween.strongEaseIn = function (t, b, c, d) { + return c * (t /= d) * t * t * t * t + b; +}; +Tween.strongEaseOut = function (t, b, c, d) { + return c * ((t = t / d - 1) * t * t * t * t + 1) + b; +}; +Tween.strongEaseInOut = function (t, b, c, d) { + if ((t /= d / 2) < 1) { + return c / 2 * t * t * t * t * t + b; + } + return c / 2 * ((t -= 2) * t * t * t * t + 2) + b; +}; diff --git a/other-scripts/Steel-Gauges/web_server/script/src/tween.min.js b/other-scripts/Steel-Gauges/web_server/script/src/tween.min.js new file mode 100644 index 0000000..50b21ce --- /dev/null +++ b/other-scripts/Steel-Gauges/web_server/script/src/tween.min.js @@ -0,0 +1,31 @@ +/*!********************************************************************* +TERMS OF USE - EASING EQUATIONS +Open source under the BSD License. +Copyright (c) 2001 Robert Penner +JavaScript version copyright (C) 2006 by Philippe Maegerman +All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of the author nor the names of contributors may +be used to endorse or promote products derived from this software +without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*****************************************/ +function Delegate(){}Delegate.create=function(n,t){for(var r=[],u=arguments.length,i=2;ithis.getDuration()?this.looping?(this.rewind(n-this._duration),this.update(),this.broadcastMessage("onMotionLooped",{target:this,type:"onMotionLooped"})):(this._time=this._duration,this.update(),this.stop(),this.broadcastMessage("onMotionFinished",{target:this,type:"onMotionFinished"})):n<0?(this.rewind(),this.update()):(this._time=n,this.update())},t.getTime=function(){return this._time},t.setDuration=function(n){this._duration=n===null||n<=0?1e5:n},t.getDuration=function(){return this._duration},t.setPosition=function(n){this.prevPos=this._pos;var t=this.suffixe!==""?this.suffixe:"";this.obj[this.prop]=Math.round(n)+t,this._pos=n,this.broadcastMessage("onMotionChanged",{target:this,type:"onMotionChanged"})},t.getPosition=function(n){return n===undefined&&(n=this._time),this.func(n,this.begin,this.change,this._duration)},t.setFinish=function(n){this.change=n-this.begin},t.getFinish=function(){return this.begin+this.change},t.init=function(n,t,i,r,u,f,e){arguments.length&&(this._listeners=[],this.addListener(this),e&&(this.suffixe=e),this.obj=n,this.prop=t,this.begin=r,this._pos=r,this.setDuration(f),i!==null&&i!==""&&(this.func=i),this.setFinish(u))},t.start=function(){this.rewind(),this.startEnterFrame(),this.broadcastMessage("onMotionStarted",{target:this,type:"onMotionStarted"})},t.rewind=function(n){this.stop(),this._time=n===undefined?0:n,this.fixTime(),this.update()},t.fforward=function(){this._time=this._duration,this.fixTime(),this.update()},t.update=function(){this.setPosition(this.getPosition(this._time))},t.startEnterFrame=function(){this.stopEnterFrame(),this.isPlaying=!0,this.onEnterFrame()},t.onEnterFrame=function(){this.isPlaying&&(this.nextFrame(),setTimeout(Delegate.create(this,this.onEnterFrame),25))},t.nextFrame=function(){this.setTime((this.getTimer()-this._startTime)/1e3)},t.stop=function(){this.stopEnterFrame(),this.broadcastMessage("onMotionStopped",{target:this,type:"onMotionStopped"})},t.stopEnterFrame=function(){this.isPlaying=!1},t.playing=function(){return this.isPlaying},t.continueTo=function(n,t){this.begin=this._pos,this.setFinish(n),this._duration!==undefined&&this.setDuration(t),this.start()},t.resume=function(){this.fixTime(),this.startEnterFrame(),this.broadcastMessage("onMotionResumed",{target:this,type:"onMotionResumed"})},t.yoyo=function(){this.continueTo(this.begin,this._time)},t.addListener=function(n){return this.removeListener(n),this._listeners.push(n)},t.removeListener=function(n){for(var t=this._listeners,i=t.length;i--;)if(t[i]===n)return t.splice(i,1),!0;return!1},t.broadcastMessage=function(){for(var i=[],r,t=this._listeners,u=t.length,n=0;n