text: /*
  	Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
  	Available via Academic Free License >= 2.1 OR the modified BSD license.
  	see: http://dojotoolkit.org/license for details
  */
  
  
  if(!dojo._hasResource["dojox.charting.Theme"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  dojo._hasResource["dojox.charting.Theme"] = true;
  dojo.provide("dojox.charting.Theme");
  
  dojo.require("dojox.color");
  dojo.require("dojox.color.Palette");
  dojo.require("dojox.lang.utils");
  dojo.require("dojox.gfx.gradutils");
  
  dojo.declare("dojox.charting.Theme", null, {
  	//	summary:
  	//		A Theme is a pre-defined object, primarily JSON-based, that makes up the definitions to
  	//		style a chart.
  	//
  	//	description:
  	//		While you can set up style definitions on a chart directly (usually through the various add methods
  	//		on a dojox.charting.Chart2D object), a Theme simplifies this manual setup by allowing you to
  	//		pre-define all of the various visual parameters of each element in a chart.
  	//
  	//		Most of the properties of a Theme are straight-forward; if something is line-based (such as
  	//		an axis or the ticks on an axis), they will be defined using basic stroke parameters.  Likewise,
  	//		if an element is primarily block-based (such as the background of a chart), it will be primarily
  	//		fill-based.
  	//
  	//		In addition (for convenience), a Theme definition does not have to contain the entire JSON-based
  	//		structure.  Each theme is built on top of a default theme (which serves as the basis for the theme
  	//		"GreySkies"), and is mixed into the default theme object.  This allows you to create a theme based,
  	//		say, solely on colors for data series.
  	//
  	//		Defining a new theme is relatively easy; see any of the themes in dojox.charting.themes for examples
  	//		on how to define your own.
  	//
  	//		When you set a theme on a chart, the theme itself is deep-cloned.  This means that you cannot alter
  	//		the theme itself after setting the theme value on a chart, and expect it to change your chart.  If you
  	//		are looking to make alterations to a theme for a chart, the suggestion would be to create your own
  	//		theme, based on the one you want to use, that makes those alterations before it is applied to a chart.
  	//
  	//		Finally, a Theme contains a number of functions to facilitate rendering operations on a chart--the main
  	//		helper of which is the ~next~ method, in which a chart asks for the information for the next data series
  	//		to be rendered.
  	//
  	//		A note on colors:
  	//		The Theme constructor was on the use of dojox.color.Palette (in general) for creating a visually distinct
  	//		set of colors for usage in a chart.  A palette is usually comprised of 5 different color definitions, and
  	//		no more.  If you have a need to render a chart with more than 5 data elements, you can simply "push"
  	//		new color definitions into the theme's .color array.  Make sure that you do that with the actual
  	//		theme object from a Chart, and not in the theme itself (i.e. either do that before using .setTheme
  	//		on a chart).
  	//
  	//		example:
  	//			The default theme (and structure) looks like so:
  	//	|	// all objects are structs used directly in dojox.gfx
  	//	|	chart:{
  	//	|		stroke: null,
  	//	|		fill: "white",
  	//	|		pageStyle: null // suggested page style as an object suitable for dojo.style()
  	//	|	},
  	//	|	plotarea:{
  	//	|		stroke: null,
  	//	|		fill: "white"
  	//	|	},
  	//	|	axis:{
  	//	|		stroke:	{ // the axis itself
  	//	|			color: "#333",
  	//	|			width: 1
  	//	|		},
  	//	|		tick: {	// used as a foundation for all ticks
  	//	|			color:     "#666",
  	//	|			position:  "center",
  	//	|			font:      "normal normal normal 7pt Tahoma",	// labels on axis
  	//	|			fontColor: "#333"								// color of labels
  	//	|		},
  	//	|		majorTick:	{ // major ticks on axis, and used for major gridlines
  	//	|			width:  1,
  	//	|			length: 6
  	//	|		},
  	//	|		minorTick:	{ // minor ticks on axis, and used for minor gridlines
  	//	|			width:  0.8,
  	//	|			length: 3
  	//	|		},
  	//	|		microTick:	{ // minor ticks on axis, and used for minor gridlines
  	//	|			width:  0.5,
  	//	|			length: 1
  	//	|		}
  	//	|	},
  	//	|	series: {
  	//	|		stroke:  {width: 1.5, color: "#333"},		// line
  	//	|		outline: {width: 0.1, color: "#ccc"},		// outline
  	//	|		//shadow:  {dx: 1, dy: 1, width: 2, color: [0, 0, 0, 0.3]},
  	//	|		shadow: null,								// no shadow
  	//	|		fill:    "#ccc",							// fill, if appropriate
  	//	|		font:    "normal normal normal 8pt Tahoma",	// if there's a label
  	//	|		fontColor: "#000"							// color of labels
  	//	|	},
  	//	|	marker: {	// any markers on a series
  	//	|		symbol:  "m-3,3 l3,-6 3,6 z",				// symbol
  	//	|		stroke:  {width: 1.5, color: "#333"},		// stroke
  	//	|		outline: {width: 0.1, color: "#ccc"},		// outline
  	//	|		shadow: null,								// no shadow
  	//	|		fill:    "#ccc",							// fill if needed
  	//	|		font:    "normal normal normal 8pt Tahoma",	// label
  	//	|		fontColor: "#000"
  	//	|	}
  	//
  	//	example:
  	//		Defining a new theme is pretty simple:
  	//	|	dojox.charting.themes.Grasslands = new dojox.charting.Theme({
  	//	|		colors: [ "#70803a", "#dde574", "#788062", "#b1cc5d", "#eff2c2" ]
  	//	|	});
  	//	|
  	//	|	myChart.setTheme(dojox.charting.themes.Grasslands);
  
  	shapeSpaces: {shape: 1, shapeX: 1, shapeY: 1},
  
  	constructor: function(kwArgs){
  		//	summary:
  		//		Initialize a theme using the keyword arguments.  Note that the arguments
  		//		look like the example (above), and may include a few more parameters.
  		kwArgs = kwArgs || {};
  
  		// populate theme with defaults updating them if needed
  		var def = dojox.charting.Theme.defaultTheme;
  		dojo.forEach(["chart", "plotarea", "axis", "series", "marker"], function(name){
  			this[name] = dojo.delegate(def[name], kwArgs[name]);
  		}, this);
  
  		// personalize theme
  		if(kwArgs.seriesThemes && kwArgs.seriesThemes.length){
  			this.colors  = null;
  			this.seriesThemes = kwArgs.seriesThemes.slice(0);
  		}else{
  			this.seriesThemes = null;
  			this.colors = (kwArgs.colors || dojox.charting.Theme.defaultColors).slice(0);
  		}
  		this.markerThemes = null;
  		if(kwArgs.markerThemes && kwArgs.markerThemes.length){
  			this.markerThemes = kwArgs.markerThemes.slice(0);
  		}
  		this.markers = dojo.delegate(dojox.charting.Theme.defaultMarkers, kwArgs.markers);
  
  		// set flags
  		this.noGradConv = kwArgs.noGradConv;
  		this.noRadialConv = kwArgs.noRadialConv;
  		if(kwArgs.reverseFills){
  			this.reverseFills();
  		}
  
  		//	private housekeeping
  		this._current = 0;
  		this._buildMarkerArray();
  	},
  
  	clone: function(){
  		//	summary:
  		//		Clone the current theme.
  		//	returns: dojox.charting.Theme
  		//		The cloned theme; any alterations made will not affect the original.
  		var theme = new dojox.charting.Theme({
  			// theme components
  			chart: this.chart,
  			plotarea: this.plotarea,
  			axis: this.axis,
  			series: this.series,
  			marker: this.marker,
  			// individual arrays
  			colors: this.colors,
  			markers: this.markers,
  			seriesThemes: this.seriesThemes,
  			markerThemes: this.markerThemes,
  			// flags
  			noGradConv: this.noGradConv,
  			noRadialConv: this.noRadialConv
  		});
  		// copy custom methods
  		dojo.forEach(
  			["clone", "clear", "next", "skip", "addMixin", "post", "getTick"],
  			function(name){
  				if(this.hasOwnProperty(name)){
  					theme[name] = this[name];
  				}
  			},
  			this
  		);
  		return theme;	//	dojox.charting.Theme
  	},
  
  	clear: function(){
  		//	summary:
  		//		Clear and reset the internal pointer to start fresh.
  		this._current = 0;
  	},
  
  	next: function(elementType, mixin, doPost){
  		//	summary:
  		//		Get the next color or series theme.
  		//	elementType: String?
  		//		An optional element type (for use with series themes)
  		//	mixin: Object?
  		//		An optional object to mix into the theme.
  		//	doPost: Boolean?
  		//		A flag to post-process the results.
  		//	returns: Object
  		//		An object of the structure { series, marker, symbol }
  		var merge = dojox.lang.utils.merge, series, marker;
  		if(this.colors){
  			series = dojo.delegate(this.series);
  			marker = dojo.delegate(this.marker);
  			var color = new dojo.Color(this.colors[this._current % this.colors.length]), old;
  			// modify the stroke
  			if(series.stroke && series.stroke.color){
  				series.stroke = dojo.delegate(series.stroke);
  				old = new dojo.Color(series.stroke.color);
  				series.stroke.color = new dojo.Color(color);
  				series.stroke.color.a = old.a;
  			}else{
  				series.stroke = {color: color};
  			}
  			if(marker.stroke && marker.stroke.color){
  				marker.stroke = dojo.delegate(marker.stroke);
  				old = new dojo.Color(marker.stroke.color);
  				marker.stroke.color = new dojo.Color(color);
  				marker.stroke.color.a = old.a;
  			}else{
  				marker.stroke = {color: color};
  			}
  			// modify the fill
  			if(!series.fill || series.fill.type){
  				series.fill = color;
  			}else{
  				old = new dojo.Color(series.fill);
  				series.fill = new dojo.Color(color);
  				series.fill.a = old.a;
  			}
  			if(!marker.fill || marker.fill.type){
  				marker.fill = color;
  			}else{
  				old = new dojo.Color(marker.fill);
  				marker.fill = new dojo.Color(color);
  				marker.fill.a = old.a;
  			}
  		}else{
  			series = this.seriesThemes ?
  				merge(this.series, this.seriesThemes[this._current % this.seriesThemes.length]) :
  				this.series;
  			marker = this.markerThemes ?
  				merge(this.marker, this.markerThemes[this._current % this.markerThemes.length]) :
  				series;
  		}
  
  		var symbol = marker && marker.symbol || this._markers[this._current % this._markers.length];
  
  		var theme = {series: series, marker: marker, symbol: symbol};
  		
  		// advance the counter
  		++this._current;
  
  		if(mixin){
  			theme = this.addMixin(theme, elementType, mixin);
  		}
  		if(doPost){
  			theme = this.post(theme, elementType);
  		}
  
  		return theme;	//	Object
  	},
  
  	skip: function(){
  		//	summary:
  		//		Skip the next internal color.
  		++this._current;
  	},
  
  	addMixin: function(theme, elementType, mixin, doPost){
  		//	summary:
  		//		Add a mixin object to the passed theme and process.
  		//	theme: dojox.charting.Theme
  		//		The theme to mixin to.
  		//	elementType: String
  		//		The type of element in question. Can be "line", "bar" or "circle"
  		//	mixin: Object|Array
  		//		The object or objects to mix into the theme.
  		//	doPost: Boolean
  		//		If true, run the new theme through the post-processor.
  		//	returns: dojox.charting.Theme
  		//		The new theme.
  		if(dojo.isArray(mixin)){
  			dojo.forEach(mixin, function(m){
  				theme = this.addMixin(theme, elementType, m);
  			}, this);
  		}else{
  			var t = {};
  			if("color" in mixin){
  				if(elementType == "line" || elementType == "area"){
  					dojo.setObject("series.stroke.color", mixin.color, t);
  					dojo.setObject("marker.stroke.color", mixin.color, t);
  				}else{
  					dojo.setObject("series.fill", mixin.color, t);
  				}
  			}
  			dojo.forEach(["stroke", "outline", "shadow", "fill", "font", "fontColor"], function(name){
  				var markerName = "marker" + name.charAt(0).toUpperCase() + name.substr(1),
  					b = markerName in mixin;
  				if(name in mixin){
  					dojo.setObject("series." + name, mixin[name], t);
  					if(!b){
  						dojo.setObject("marker." + name, mixin[name], t);
  					}
  				}
  				if(b){
  					dojo.setObject("marker." + name, mixin[markerName], t);
  				}
  			});
  			if("marker" in mixin){
  				t.symbol = mixin.marker;
  			}
  			theme = dojox.lang.utils.merge(theme, t);
  		}
  		if(doPost){
  			theme = this.post(theme, elementType);
  		}
  		return theme;	//	dojox.charting.Theme
  	},
  
  	post: function(theme, elementType){
  		//	summary:
  		//		Process any post-shape fills.
  		//	theme: dojox.charting.Theme
  		//		The theme to post process with.
  		//	elementType: String
  		//		The type of element being filled.  Can be "bar" or "circle".
  		//	returns: dojox.charting.Theme
  		//		The post-processed theme.
  		var fill = theme.series.fill, t;
  		if(!this.noGradConv && this.shapeSpaces[fill.space] && fill.type == "linear"){
  			if(elementType == "bar"){
  				// transpose start and end points
  				t = {
  					x1: fill.y1,
  					y1: fill.x1,
  					x2: fill.y2,
  					y2: fill.x2
  				};
  			}else if(!this.noRadialConv && fill.space == "shape" && (elementType == "slice" || elementType == "circle")){
  				// switch to radial
  				t = {
  					type: "radial",
  					cx: 0,
  					cy: 0,
  					r:  100
  				};
  			}
  			if(t){
  				return dojox.lang.utils.merge(theme, {series: {fill: t}});
  			}
  		}
  		return theme;	//	dojox.charting.Theme
  	},
  
  	getTick: function(name, mixin){
  		//	summary:
  		//		Calculates and merges tick parameters.
  		//	name: String
  		//		Tick name, can be "major", "minor", or "micro".
  		//	mixin: Object?
  		//		Optional object to mix in to the tick.
  		var tick = this.axis.tick, tickName = name + "Tick";
  			merge = dojox.lang.utils.merge;
  		if(tick){
  			if(this.axis[tickName]){
  				tick = merge(tick, this.axis[tickName]);
  			}
  		}else{
  			tick = this.axis[tickName];
  		}
  		if(mixin){
  			if(tick){
  				if(mixin[tickName]){
  					tick = merge(tick, mixin[tickName]);
  				}
  			}else{
  				tick = mixin[tickName];
  			}
  		}
  		return tick;	//	Object
  	},
  
  	inspectObjects: function(f){
  		dojo.forEach(["chart", "plotarea", "axis", "series", "marker"], function(name){
  			f(this[name]);
  		}, this);
  		if(this.seriesThemes){
  			dojo.forEach(this.seriesThemes, f);
  		}
  		if(this.markerThemes){
  			dojo.forEach(this.markerThemes, f);
  		}
  	},
  
  	reverseFills: function(){
  		this.inspectObjects(function(o){
  			if(o && o.fill){
  				o.fill = dojox.gfx.gradutils.reverse(o.fill);
  			}
  		});
  	},
  
  	addMarker:function(/*String*/ name, /*String*/ segment){
  		//	summary:
  		//		Add a custom marker to this theme.
  		//	example:
  		//	|	myTheme.addMarker("Ellipse", foo);
  		this.markers[name] = segment;
  		this._buildMarkerArray();
  	},
  
  	setMarkers:function(/*Object*/ obj){
  		//	summary:
  		//		Set all the markers of this theme at once.  obj should be a
  		//		dictionary of keys and path segments.
  		//
  		//	example:
  		//	|	myTheme.setMarkers({ "CIRCLE": foo });
  		this.markers = obj;
  		this._buildMarkerArray();
  	},
  
  	_buildMarkerArray: function(){
  		this._markers = [];
  		for(var p in this.markers){
  			this._markers.push(this.markers[p]);
  		}
  	}
  });
  
  /*=====
  dojox.charting.Theme.__DefineColorArgs = function(num, colors, hue, saturation, low, high, base, generator){
  	//	summary:
  	//		The arguments object that can be passed to define colors for a theme.
  	//	num: Number?
  	//		The number of colors to generate.  Defaults to 5.
  	//	colors: String[]|dojo.Color[]?
  	//		A pre-defined set of colors; this is passed through to the Theme directly.
  	//	hue: Number?
  	//		A hue to base the generated colors from (a number from 0 - 359).
  	//	saturation: Number?
  	//		If a hue is passed, this is used for the saturation value (0 - 100).
  	//	low: Number?
  	//		An optional value to determine the lowest value used to generate a color (HSV model)
  	//	high: Number?
  	//		An optional value to determine the highest value used to generate a color (HSV model)
  	//	base: String|dojo.Color?
  	//		A base color to use if we are defining colors using dojox.color.Palette
  	//	generator: String?
  	//		The generator function name from dojox.color.Palette.
  	this.num = num;
  	this.colors = colors;
  	this.hue = hue;
  	this.saturation = saturation;
  	this.low = low;
  	this.high = high;
  	this.base = base;
  	this.generator = generator;
  }
  =====*/
  dojo.mixin(dojox.charting.Theme, {
  	defaultMarkers: {
  		CIRCLE:   "m-3,0 c0,-4 6,-4 6,0 m-6,0 c0,4 6,4 6,0",
  		SQUARE:   "m-3,-3 l0,6 6,0 0,-6 z",
  		DIAMOND:  "m0,-3 l3,3 -3,3 -3,-3 z",
  		CROSS:    "m0,-3 l0,6 m-3,-3 l6,0",
  		X:        "m-3,-3 l6,6 m0,-6 l-6,6",
  		TRIANGLE: "m-3,3 l3,-6 3,6 z",
  		TRIANGLE_INVERTED: "m-3,-3 l3,6 3,-6 z"
  	},
  
  	defaultColors:[
  		// gray skies
  		"#54544c", "#858e94", "#6e767a", "#948585", "#474747"
  	],
  
  	defaultTheme: {
  		// all objects are structs used directly in dojox.gfx
  		chart:{
  			stroke: null,
  			fill: "white",
  			pageStyle: null
  		},
  		plotarea:{
  			stroke: null,
  			fill: "white"
  		},
  		// TODO: label rotation on axis
  		axis:{
  			stroke:	{ // the axis itself
  				color: "#333",
  				width: 1
  			},
  			tick: {	// used as a foundation for all ticks
  				color:     "#666",
  				position:  "center",
  				font:      "normal normal normal 7pt Tahoma",	// labels on axis
  				fontColor: "#333"								// color of labels
  			},
  			majorTick:	{ // major ticks on axis, and used for major gridlines
  				width:  1,
  				length: 6
  			},
  			minorTick:	{ // minor ticks on axis, and used for minor gridlines
  				width:  0.8,
  				length: 3
  			},
  			microTick:	{ // minor ticks on axis, and used for minor gridlines
  				width:  0.5,
  				length: 1
  			}
  		},
  		series: {
  			// used as a "main" theme for series, sThemes augment it
  			stroke:  {width: 1.5, color: "#333"},		// line
  			outline: {width: 0.1, color: "#ccc"},		// outline
  			//shadow:  {dx: 1, dy: 1, width: 2, color: [0, 0, 0, 0.3]},
  			shadow: null,								// no shadow
  			fill:    "#ccc",							// fill, if appropriate
  			font:    "normal normal normal 8pt Tahoma",	// if there's a label
  			fontColor: "#000"							// color of labels
  		},
  		marker: {	// any markers on a series
  			stroke:  {width: 1.5, color: "#333"},		// stroke
  			outline: {width: 0.1, color: "#ccc"},		// outline
  			//shadow:  {dx: 1, dy: 1, width: 2, color: [0, 0, 0, 0.3]},
  			shadow: null,								// no shadow
  			fill:    "#ccc",							// fill if needed
  			font:    "normal normal normal 8pt Tahoma",	// label
  			fontColor: "#000"
  		}
  	},
  
  	defineColors: function(kwArgs){
  		//	summary:
  		//		Generate a set of colors for the theme based on keyword
  		//		arguments.
  		//	kwArgs: dojox.charting.Theme.__DefineColorArgs
  		//		The arguments object used to define colors.
  		//	returns: dojo.Color[]
  		//		An array of colors for use in a theme.
  		//
  		//	example:
  		//	|	var colors = dojox.charting.Theme.defineColors({
  		//	|		base: "#369",
  		//	|		generator: "compound"
  		//	|	});
  		//
  		//	example:
  		//	|	var colors = dojox.charting.Theme.defineColors({
  		//	|		hue: 60,
  		//	|		saturation: 90,
  		//	|		low: 30,
  		//	|		high: 80
  		//	|	});
  		kwArgs = kwArgs || {};
  		var c = [], n = kwArgs.num || 5;	// the number of colors to generate
  		if(kwArgs.colors){
  			// we have an array of colors predefined, so fix for the number of series.
  			var l = kwArgs.colors.length;
  			for(var i = 0; i < n; i++){
  				c.push(kwArgs.colors[i % l]);
  			}
  			return c;	//	dojo.Color[]
  		}
  		if(kwArgs.hue){
  			// single hue, generate a set based on brightness
  			var s = kwArgs.saturation || 100;	// saturation
  			var st = kwArgs.low || 30;
  			var end = kwArgs.high || 90;
  			// we'd like it to be a little on the darker side.
  			var l = (end + st) / 2;
  			// alternately, use "shades"
  			return dojox.color.Palette.generate(
  				dojox.color.fromHsv(kwArgs.hue, s, l), "monochromatic"
  			).colors;
  		}
  		if(kwArgs.generator){
  			//	pass a base color and the name of a generator
  			return dojox.color.Palette.generate(kwArgs.base, kwArgs.generator).colors;
  		}
  		return c;	//	dojo.Color[]
  	},
  	
  	generateGradient: function(fillPattern, colorFrom, colorTo){
  		var fill = dojo.delegate(fillPattern);
  		fill.colors = [
  			{offset: 0, color: colorFrom},
  			{offset: 1, color: colorTo}
  		];
  		return fill;
  	},
  	
  	generateHslColor: function(color, luminance){
  		color = new dojox.color.Color(color);
  		var hsl    = color.toHsl(),
  			result = dojox.color.fromHsl(hsl.h, hsl.s, luminance);
  		result.a = color.a;	// add missing opacity
  		return result;
  	},
  
  	generateHslGradient: function(color, fillPattern, lumFrom, lumTo){
  		color = new dojox.color.Color(color);
  		var hsl       = color.toHsl(),
  			colorFrom = dojox.color.fromHsl(hsl.h, hsl.s, lumFrom),
  			colorTo   = dojox.color.fromHsl(hsl.h, hsl.s, lumTo);
  		colorFrom.a = colorTo.a = color.a;	// add missing opacity
  		return dojox.charting.Theme.generateGradient(fillPattern, colorFrom, colorTo);	// Object
  	}
  });
  
  }
  