text: define(["dojo/_base/lang", "dojo/_base/array","dojo/_base/sniff", "dojo/_base/declare", 
  	"dojo/_base/connect", "dojo/_base/html", "dojo/dom-geometry", "./Invisible", 
  	"../scaler/common", "../scaler/linear", "./common", "dojox/gfx", "dojox/lang/utils"], 
  	function(lang, arr, has, declare, connect, html, domGeom, Invisible, scommon, 
  			lin, acommon, g, du){
  
  	/*=====
  		dojox.charting.axis2d.__AxisCtorArgs = function(
  			vertical, fixUpper, fixLower, natural, leftBottom,
  			includeZero, fixed, majorLabels, minorTicks, minorLabels, microTicks, htmlLabels,
  			min, max, from, to, majorTickStep, minorTickStep, microTickStep,
  			labels, labelFunc, maxLabelSize,
  			stroke, majorTick, minorTick, microTick, tick,
  			font, fontColor
  		){
  		//	summary:
  		//		Optional arguments used in the definition of an axis.
  		//
  		//	vertical: Boolean?
  		//		A flag that says whether an axis is vertical (i.e. y axis) or horizontal. Default is false (horizontal).
  		//	fixUpper: String?
  		//		Align the greatest value on the axis with the specified tick level. Options are "major", "minor", "micro", or "none".  Defaults to "none".
  		//	fixLower: String?
  		//		Align the smallest value on the axis with the specified tick level. Options are "major", "minor", "micro", or "none".  Defaults to "none".
  		//	natural: Boolean?
  		//		Ensure tick marks are made on "natural" numbers. Defaults to false.
  		//	leftBottom: Boolean?
  		//		The position of a vertical axis; if true, will be placed against the left-bottom corner of the chart.  Defaults to true.
  		//	includeZero: Boolean?
  		//		Include 0 on the axis rendering.  Default is false.
  		//	fixed: Boolean?
  		//		Force all axis labels to be fixed numbers.  Default is true.
  		//	majorLabels: Boolean?
  		//		Flag to draw all labels at major ticks. Default is true.
  		//	minorTicks: Boolean?
  		//		Flag to draw minor ticks on an axis.  Default is true.
  		//	minorLabels: Boolean?
  		//		Flag to draw labels on minor ticks. Default is true.
  		//	microTicks: Boolean?
  		//		Flag to draw micro ticks on an axis. Default is false.
  		//	htmlLabels: Boolean?
  		//		Flag to use HTML (as opposed to the native vector graphics engine) to draw labels. Default is true.
  		//	min: Number?
  		//		The smallest value on an axis. Default is 0.
  		//	max: Number?
  		//		The largest value on an axis. Default is 1.
  		//	from: Number?
  		//		Force the chart to render data visible from this value. Default is 0.
  		//	to: Number?
  		//		Force the chart to render data visible to this value. Default is 1.
  		//	majorTickStep: Number?
  		//		The amount to skip before a major tick is drawn.  Default is 4.
  		//	minorTickStep: Number?
  		//		The amount to skip before a minor tick is drawn. Default is 2.
  		//	microTickStep: Number?
  		//		The amount to skip before a micro tick is drawn. Default is 1.
  		//	labels: Object[]?
  		//		An array of labels for major ticks, with corresponding numeric values, ordered by value.
  		//	labelFunc: Function?
  		//		An optional function used to compute label values.
  		//	maxLabelSize: Number?
  		//		The maximum size, in pixels, for a label.  To be used with the optional label function.
  		//	stroke: dojox.gfx.Stroke?
  		//		An optional stroke to be used for drawing an axis.
  		//	majorTick: Object?
  		//		An object containing a dojox.gfx.Stroke, and a length (number) for a major tick.
  		//	minorTick: Object?
  		//		An object containing a dojox.gfx.Stroke, and a length (number) for a minor tick.
  		//	microTick: Object?
  		//		An object containing a dojox.gfx.Stroke, and a length (number) for a micro tick.
  		//	tick: Object?
  		//		An object containing a dojox.gfx.Stroke, and a length (number) for a tick.
  		//	font: String?
  		//		An optional font definition (as used in the CSS font property) for labels.
  		//	fontColor: String|dojo.Color?
  		//		An optional color to be used in drawing labels.
  		//	titleGap: Number?
  		//		An optional grap between axis title and axis label
  		//	titleFont: String?
  		// 		An optional font definition for axis title
  		//	titleFontColor:	 String?
  		// 		An optional axis title color
  		//	titleOrientation: String?
  		// 		An optional orientation for axis title. "axis" means the title facing the axis, "away" means facing away.
  		//		If no value is set "axis" is used.
  		//	enableCache: Boolean?
  		//		Whether the ticks and labels are cached from one rendering to another. This improves the rendering performance of
  		//		successive rendering but penalize the first rendering. For labels it is only working with gfx labels
  		//		not html ones.  Default false.
  	
  		this.vertical = vertical;
  		this.fixUpper = fixUpper;
  		this.fixLower = fixLower;
  		this.natural = natural;
  		this.leftBottom = leftBottom;
  		this.includeZero = includeZero;
  		this.fixed = fixed;
  		this.majorLabels = majorLabels;
  		this.minorTicks = minorTicks;
  		this.minorLabels = minorLabels;
  		this.microTicks = microTicks;
  		this.htmlLabels = htmlLabels;
  		this.min = min;
  		this.max = max;
  		this.from = from;
  		this.to = to;
  		this.majorTickStep = majorTickStep;
  		this.minorTickStep = minorTickStep;
  		this.microTickStep = microTickStep;
  		this.labels = labels;
  		this.labelFunc = labelFunc;
  		this.maxLabelSize = maxLabelSize;
  		this.stroke = stroke;
  		this.majorTick = majorTick;
  		this.minorTick = minorTick;
  		this.microTick = microTick;
  		this.tick = tick;
  		this.font = font;
  		this.fontColor = fontColor;
  		this.enableCache = enableCache;
  	}
  	var Invisible = dojox.charting.axis2d.Invisible
  	=====*/
  
  	var labelGap = 4,			// in pixels
  		centerAnchorLimit = 45;	// in degrees
  
  	return declare("dojox.charting.axis2d.Default", Invisible, {
  		//	summary:
  		//		The default axis object used in dojox.charting.  See dojox.charting.Chart.addAxis for details.
  		//
  		//	defaultParams: Object
  		//		The default parameters used to define any axis.
  		//	optionalParams: Object
  		//		Any optional parameters needed to define an axis.
  
  		/*
  		//	TODO: the documentation tools need these to be pre-defined in order to pick them up
  		//	correctly, but the code here is partially predicated on whether or not the properties
  		//	actually exist.  For now, we will leave these undocumented but in the code for later. -- TRT
  
  		//	opt: Object
  		//		The actual options used to define this axis, created at initialization.
  		//	scalar: Object
  		//		The calculated helper object to tell charts how to draw an axis and any data.
  		//	ticks: Object
  		//		The calculated tick object that helps a chart draw the scaling on an axis.
  		//	dirty: Boolean
  		//		The state of the axis (whether it needs to be redrawn or not)
  		//	scale: Number
  		//		The current scale of the axis.
  		//	offset: Number
  		//		The current offset of the axis.
  
  		opt: null,
  		scalar: null,
  		ticks: null,
  		dirty: true,
  		scale: 1,
  		offset: 0,
  		*/
  		defaultParams: {
  			vertical:    false,		// true for vertical axis
  			fixUpper:    "none",	// align the upper on ticks: "major", "minor", "micro", "none"
  			fixLower:    "none",	// align the lower on ticks: "major", "minor", "micro", "none"
  			natural:     false,		// all tick marks should be made on natural numbers
  			leftBottom:  true,		// position of the axis, used with "vertical"
  			includeZero: false,		// 0 should be included
  			fixed:       true,		// all labels are fixed numbers
  			majorLabels: true,		// draw major labels
  			minorTicks:  true,		// draw minor ticks
  			minorLabels: true,		// draw minor labels
  			microTicks:  false,		// draw micro ticks
  			rotation:    0,			// label rotation angle in degrees
  			htmlLabels:  true,		// use HTML to draw labels
  			enableCache: false		// whether we cache or not
  		},
  		optionalParams: {
  			min:			0,	// minimal value on this axis
  			max:			1,	// maximal value on this axis
  			from:			0,	// visible from this value
  			to:				1,	// visible to this value
  			majorTickStep:	4,	// major tick step
  			minorTickStep:	2,	// minor tick step
  			microTickStep:	1,	// micro tick step
  			labels:			[],	// array of labels for major ticks
  								// with corresponding numeric values
  								// ordered by values
  			labelFunc:		null, // function to compute label values
  			maxLabelSize:	0,	// size in px. For use with labelFunc
  			maxLabelCharCount:	0,	// size in word count.
  			trailingSymbol:	null,
  
  			// TODO: add support for minRange!
  			// minRange:		1,	// smallest distance from min allowed on the axis
  
  			// theme components
  			stroke:			{},	// stroke for an axis
  			majorTick:		{},	// stroke + length for a tick
  			minorTick:		{},	// stroke + length for a tick
  			microTick:		{},	// stroke + length for a tick
  			tick:           {},	// stroke + length for a tick
  			font:			"",	// font for labels
  			fontColor:		"",	// color for labels as a string
  			title:		 		"",	// axis title
  			titleGap:	 		0,		// gap between axis title and axis label
  			titleFont:	 		"",		// axis title font
  			titleFontColor:	 	"",		// axis title font color
  			titleOrientation: 	""		// "axis" means the title facing the axis, "away" means facing away
  		},
  
  		constructor: function(chart, kwArgs){
  			//	summary:
  			//		The constructor for an axis.
  			//	chart: dojox.charting.Chart
  			//		The chart the axis belongs to.
  			//	kwArgs: dojox.charting.axis2d.__AxisCtorArgs?
  			//		Any optional keyword arguments to be used to define this axis.
  			this.opt = lang.clone(this.defaultParams);
              du.updateWithObject(this.opt, kwArgs);
  			du.updateWithPattern(this.opt, kwArgs, this.optionalParams);
  			if(this.opt.enableCache){
  				this._textFreePool = [];
  				this._lineFreePool = [];
  				this._textUsePool = [];
  				this._lineUsePool = [];
  			}
  		},
  		getOffsets: function(){
  			//	summary:
  			//		Get the physical offset values for this axis (used in drawing data series).
  			//	returns: Object
  			//		The calculated offsets in the form of { l, r, t, b } (left, right, top, bottom).
  			var s = this.scaler, offsets = { l: 0, r: 0, t: 0, b: 0 };
  			if(!s){
  				return offsets;
  			}
  			var o = this.opt, labelWidth = 0, a, b, c, d,
  				gl = scommon.getNumericLabel,
  				offset = 0, ma = s.major, mi = s.minor,
  				ta = this.chart.theme.axis,
  				// TODO: we use one font --- of major tick, we need to use major and minor fonts
  				taFont = o.font || (ta.majorTick && ta.majorTick.font) || (ta.tick && ta.tick.font),
  				taTitleFont = o.titleFont || (ta.title && ta.title.font),
  				taTitleGap = (o.titleGap==0) ? 0 : o.titleGap || (ta.title && ta.title.gap),
  				taMajorTick = this.chart.theme.getTick("major", o),
  				taMinorTick = this.chart.theme.getTick("minor", o),
  				size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0,
  				tsize = taTitleFont ? g.normalizedLength(g.splitFontString(taTitleFont).size) : 0,
  				rotation = o.rotation % 360, leftBottom = o.leftBottom,
  				cosr = Math.abs(Math.cos(rotation * Math.PI / 180)),
  				sinr = Math.abs(Math.sin(rotation * Math.PI / 180));
  			this.trailingSymbol = (o.trailingSymbol === undefined || o.trailingSymbol === null) ? this.trailingSymbol : o.trailingSymbol;
  			if(rotation < 0){
  				rotation += 360;
  			}
  
  			if(size){
  				// we need width of all labels
  				if(this.labels){
  					labelWidth = this._groupLabelWidth(this.labels, taFont, o.maxLabelCharCount);
  				}else{
  					labelWidth = this._groupLabelWidth([
  						gl(ma.start, ma.prec, o),
  						gl(ma.start + ma.count * ma.tick, ma.prec, o),
  						gl(mi.start, mi.prec, o),
  						gl(mi.start + mi.count * mi.tick, mi.prec, o)
  					], taFont, o.maxLabelCharCount);
  				}
  				labelWidth = o.maxLabelSize ? Math.min(o.maxLabelSize, labelWidth) : labelWidth;
  				var side;
  				if(this.vertical){
  					side = leftBottom ? "l" : "r";
  					switch(rotation){
  						case 0:
  						case 180:
  							offsets[side] = labelWidth;
  							offsets.t = offsets.b = size / 2;
  							break;
  						case 90:
  						case 270:
  							offsets[side] = size;
  							offsets.t = offsets.b = labelWidth / 2;
  							break;
  						default:
  							if(rotation <= centerAnchorLimit || (180 < rotation && rotation <= (180 + centerAnchorLimit))){
  								offsets[side] = size * sinr / 2 + labelWidth * cosr;
  								offsets[leftBottom ? "t" : "b"] = size * cosr / 2 + labelWidth * sinr;
  								offsets[leftBottom ? "b" : "t"] = size * cosr / 2;
  							}else if(rotation > (360 - centerAnchorLimit) || (180 > rotation && rotation > (180 - centerAnchorLimit))){
  								offsets[side] = size * sinr / 2 + labelWidth * cosr;
  								offsets[leftBottom ? "b" : "t"] = size * cosr / 2 + labelWidth * sinr;
  								offsets[leftBottom ? "t" : "b"] = size * cosr / 2;
  							}else if(rotation < 90 || (180 < rotation && rotation < 270)){
  								offsets[side] = size * sinr + labelWidth * cosr;
  								offsets[leftBottom ? "t" : "b"] = size * cosr + labelWidth * sinr;
  							}else{
  								offsets[side] = size * sinr + labelWidth * cosr;
  								offsets[leftBottom ? "b" : "t"] = size * cosr + labelWidth * sinr;
  							}
  							break;
  					}
  					offsets[side] += labelGap + Math.max(taMajorTick.length, taMinorTick.length) + (o.title ? (tsize + taTitleGap) : 0);
  				}else{
  					side = leftBottom ? "b" : "t";
  					switch(rotation){
  						case 0:
  						case 180:
  							offsets[side] = size;
  							offsets.l = offsets.r = labelWidth / 2;
  							break;
  						case 90:
  						case 270:
  							offsets[side] = labelWidth;
  							offsets.l = offsets.r = size / 2;
  							break;
  						default:
  							if((90 - centerAnchorLimit) <= rotation && rotation <= 90 || (270 - centerAnchorLimit) <= rotation && rotation <= 270){
  								offsets[side] = size * sinr / 2 + labelWidth * cosr;
  								offsets[leftBottom ? "r" : "l"] = size * cosr / 2 + labelWidth * sinr;
  								offsets[leftBottom ? "l" : "r"] = size * cosr / 2;
  							}else if(90 <= rotation && rotation <= (90 + centerAnchorLimit) || 270 <= rotation && rotation <= (270 + centerAnchorLimit)){
  								offsets[side] = size * sinr / 2 + labelWidth * cosr;
  								offsets[leftBottom ? "l" : "r"] = size * cosr / 2 + labelWidth * sinr;
  								offsets[leftBottom ? "r" : "l"] = size * cosr / 2;
  							}else if(rotation < centerAnchorLimit || (180 < rotation && rotation < (180 - centerAnchorLimit))){
  								offsets[side] = size * sinr + labelWidth * cosr;
  								offsets[leftBottom ? "r" : "l"] = size * cosr + labelWidth * sinr;
  							}else{
  								offsets[side] = size * sinr + labelWidth * cosr;
  								offsets[leftBottom ? "l" : "r"] = size * cosr + labelWidth * sinr;
  							}
  							break;
  					}
  					offsets[side] += labelGap + Math.max(taMajorTick.length, taMinorTick.length) + (o.title ? (tsize + taTitleGap) : 0);
  				}
  			}
  			if(labelWidth){
  				this._cachedLabelWidth = labelWidth;
  			}
  			return offsets;	//	Object
  		},
  		cleanGroup: function(creator){
  			if(this.opt.enableCache && this.group){
  				this._lineFreePool = this._lineFreePool.concat(this._lineUsePool);
  				this._lineUsePool = [];
  				this._textFreePool = this._textFreePool.concat(this._textUsePool);
  				this._textUsePool = [];
  			}
  			this.inherited(arguments);
  		},
  		createText: function(labelType, creator, x, y, align, textContent, font, fontColor, labelWidth){
  			if(!this.opt.enableCache || labelType=="html"){
  				return acommon.createText[labelType](
  						this.chart,
  						creator,
  						x,
  						y,
  						align,
  						textContent,
  						font,
  						fontColor,
  						labelWidth
  					);
  			}
  			var text;
  			if (this._textFreePool.length > 0){
  				text = this._textFreePool.pop();
  				text.setShape({x: x, y: y, text: textContent, align: align});
  				// For now all items share the same font, no need to re-set it
  				//.setFont(font).setFill(fontColor);
  				// was cleared, add it back
  				creator.add(text);
  			}else{
  				text = acommon.createText[labelType](
  						this.chart,
  						creator,
  						x,
  						y,
  						align,
  						textContent,
  						font,
  						fontColor						
  					);			
  			}
  			this._textUsePool.push(text);
  			return text;
  		},
  		createLine: function(creator, params){
  			var line;
  			if(this.opt.enableCache && this._lineFreePool.length > 0){
  				line = this._lineFreePool.pop();
  				line.setShape(params);
  				// was cleared, add it back
  				creator.add(line);
  			}else{
  				line = creator.createLine(params);
  			}
  			if(this.opt.enableCache){
  				this._lineUsePool.push(line);
  			}
  			return line;
  		},
  		render: function(dim, offsets){
  			//	summary:
  			//		Render/draw the axis.
  			//	dim: Object
  			//		An object of the form { width, height}.
  			//	offsets: Object
  			//		An object of the form { l, r, t, b }.
  			//	returns: dojox.charting.axis2d.Default
  			//		The reference to the axis for functional chaining.
  			if(!this.dirty || !this.scaler){
  				return this;	//	dojox.charting.axis2d.Default
  			}
  			// prepare variable
  			var o = this.opt, ta = this.chart.theme.axis, leftBottom = o.leftBottom, rotation = o.rotation % 360,
  				start, stop, titlePos, titleRotation=0, titleOffset, axisVector, tickVector, anchorOffset, labelOffset, labelAlign,
  
  				// TODO: we use one font --- of major tick, we need to use major and minor fonts
  				taFont = o.font || (ta.majorTick && ta.majorTick.font) || (ta.tick && ta.tick.font),
  				taTitleFont = o.titleFont || (ta.title && ta.title.font),
  				// TODO: we use one font color --- we need to use different colors
  				taFontColor = o.fontColor || (ta.majorTick && ta.majorTick.fontColor) || (ta.tick && ta.tick.fontColor) || "black",
  				taTitleFontColor = o.titleFontColor || (ta.title && ta.title.fontColor) || "black",
  				taTitleGap = (o.titleGap==0) ? 0 : o.titleGap || (ta.title && ta.title.gap) || 15,
  				taTitleOrientation = o.titleOrientation || (ta.title && ta.title.orientation) || "axis",
  				taMajorTick = this.chart.theme.getTick("major", o),
  				taMinorTick = this.chart.theme.getTick("minor", o),
  				taMicroTick = this.chart.theme.getTick("micro", o),
  
  				tickSize = Math.max(taMajorTick.length, taMinorTick.length, taMicroTick.length),
  				taStroke = "stroke" in o ? o.stroke : ta.stroke,
  				size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0,
  				cosr = Math.abs(Math.cos(rotation * Math.PI / 180)),
  				sinr = Math.abs(Math.sin(rotation * Math.PI / 180)),
  				tsize = taTitleFont ? g.normalizedLength(g.splitFontString(taTitleFont).size) : 0;
  			if(rotation < 0){
  				rotation += 360;
  			}
  			if(this.vertical){
  				start = {y: dim.height - offsets.b};
  				stop  = {y: offsets.t};
  				titlePos = {y: (dim.height - offsets.b + offsets.t)/2};
  				titleOffset = size * sinr + (this._cachedLabelWidth || 0) * cosr + labelGap + Math.max(taMajorTick.length, taMinorTick.length) + tsize + taTitleGap;
  				axisVector = {x: 0, y: -1};
  				labelOffset = {x: 0, y: 0};
  				tickVector = {x: 1, y: 0};
  				anchorOffset = {x: labelGap, y: 0};
  				switch(rotation){
  					case 0:
  						labelAlign = "end";
  						labelOffset.y = size * 0.4;
  						break;
  					case 90:
  						labelAlign = "middle";
  						labelOffset.x = -size;
  						break;
  					case 180:
  						labelAlign = "start";
  						labelOffset.y = -size * 0.4;
  						break;
  					case 270:
  						labelAlign = "middle";
  						break;
  					default:
  						if(rotation < centerAnchorLimit){
  							labelAlign = "end";
  							labelOffset.y = size * 0.4;
  						}else if(rotation < 90){
  							labelAlign = "end";
  							labelOffset.y = size * 0.4;
  						}else if(rotation < (180 - centerAnchorLimit)){
  							labelAlign = "start";
  						}else if(rotation < (180 + centerAnchorLimit)){
  							labelAlign = "start";
  							labelOffset.y = -size * 0.4;
  						}else if(rotation < 270){
  							labelAlign = "start";
  							labelOffset.x = leftBottom ? 0 : size * 0.4;
  						}else if(rotation < (360 - centerAnchorLimit)){
  							labelAlign = "end";
  							labelOffset.x = leftBottom ? 0 : size * 0.4;
  						}else{
  							labelAlign = "end";
  							labelOffset.y = size * 0.4;
  						}
  				}
  				if(leftBottom){
  					start.x = stop.x = offsets.l;
  					titleRotation = (taTitleOrientation && taTitleOrientation == "away") ? 90 : 270;
  					titlePos.x = offsets.l - titleOffset + (titleRotation == 270 ? tsize : 0);
  					tickVector.x = -1;
  					anchorOffset.x = -anchorOffset.x;
  				}else{
  					start.x = stop.x = dim.width - offsets.r;
  					titleRotation = (taTitleOrientation && taTitleOrientation == "axis") ? 90 : 270;
  					titlePos.x = dim.width - offsets.r + titleOffset - (titleRotation == 270 ? 0 : tsize);
  					switch(labelAlign){
  						case "start":
  							labelAlign = "end";
  							break;
  						case "end":
  							labelAlign = "start";
  							break;
  						case "middle":
  							labelOffset.x += size;
  							break;
  					}
  				}
  			}else{
  				start = {x: offsets.l};
  				stop  = {x: dim.width - offsets.r};
  				titlePos = {x: (dim.width - offsets.r + offsets.l)/2};
  				titleOffset = size * cosr + (this._cachedLabelWidth || 0) * sinr + labelGap + Math.max(taMajorTick.length, taMinorTick.length) + tsize + taTitleGap;
  				axisVector = {x: 1, y: 0};
  				labelOffset = {x: 0, y: 0};
  				tickVector = {x: 0, y: 1};
  				anchorOffset = {x: 0, y: labelGap};
  				switch(rotation){
  					case 0:
  						labelAlign = "middle";
  						labelOffset.y = size;
  						break;
  					case 90:
  						labelAlign = "start";
  						labelOffset.x = -size * 0.4;
  						break;
  					case 180:
  						labelAlign = "middle";
  						break;
  					case 270:
  						labelAlign = "end";
  						labelOffset.x = size * 0.4;
  						break;
  					default:
  						if(rotation < (90 - centerAnchorLimit)){
  							labelAlign = "start";
  							labelOffset.y = leftBottom ? size : 0;
  						}else if(rotation < (90 + centerAnchorLimit)){
  							labelAlign = "start";
  							labelOffset.x = -size * 0.4;
  						}else if(rotation < 180){
  							labelAlign = "start";
  							labelOffset.y = leftBottom ? 0 : -size;
  						}else if(rotation < (270 - centerAnchorLimit)){
  							labelAlign = "end";
  							labelOffset.y = leftBottom ? 0 : -size;
  						}else if(rotation < (270 + centerAnchorLimit)){
  							labelAlign = "end";
  							labelOffset.y = leftBottom ? size * 0.4 : 0;
  						}else{
  							labelAlign = "end";
  							labelOffset.y = leftBottom ? size : 0;
  						}
  				}
  				if(leftBottom){
  					start.y = stop.y = dim.height - offsets.b;
  					titleRotation = (taTitleOrientation && taTitleOrientation == "axis") ? 180 : 0;
  					titlePos.y = dim.height - offsets.b + titleOffset - (titleRotation ? tsize : 0);
  				}else{
  					start.y = stop.y = offsets.t;
  					titleRotation = (taTitleOrientation && taTitleOrientation == "away") ? 180 : 0;
  					titlePos.y = offsets.t - titleOffset + (titleRotation ? 0 : tsize);
  					tickVector.y = -1;
  					anchorOffset.y = -anchorOffset.y;
  					switch(labelAlign){
  						case "start":
  							labelAlign = "end";
  							break;
  						case "end":
  							labelAlign = "start";
  							break;
  						case "middle":
  							labelOffset.y -= size;
  							break;
  					}
  				}
  			}
  
  			// render shapes
  
  			this.cleanGroup();
  
  			var s = this.group,
  				c = this.scaler,
  				t = this.ticks,
  				canLabel,
  				f = lin.getTransformerFromModel(this.scaler),
  				// GFX Canvas now supports labels, so let's _not_ fallback to HTML anymore on canvas, just use
  				// HTML labels if explicitly asked + no rotation + no IE + no Opera
  				labelType = (!o.title || !titleRotation) && !rotation && this.opt.htmlLabels && !has("ie") && !has("opera") ? "html" : "gfx",
  				dx = tickVector.x * taMajorTick.length,
  				dy = tickVector.y * taMajorTick.length;
  
  			s.createLine({
  				x1: start.x,
  				y1: start.y,
  				x2: stop.x,
  				y2: stop.y
  			}).setStroke(taStroke);
  
  			//create axis title
  			if(o.title){
  				var axisTitle = acommon.createText[labelType](
  					this.chart,
  					s,
  					titlePos.x,
  					titlePos.y,
  					"middle",
  					o.title,
  					taTitleFont,
  					taTitleFontColor
  				);
  				if(labelType == "html"){
  					this.htmlElements.push(axisTitle);
  				}else{
  					//as soon as rotation is provided, labelType won't be "html"
  					//rotate gfx labels
  					axisTitle.setTransform(g.matrix.rotategAt(titleRotation, titlePos.x, titlePos.y));
  				}
  			}
  
  			// go out nicely instead of try/catch
  			if(t==null){
  				this.dirty = false;
  				return this;
  			}
  
  			arr.forEach(t.major, function(tick){
  				var offset = f(tick.value), elem,
  					x = start.x + axisVector.x * offset,
  					y = start.y + axisVector.y * offset;
  					this.createLine(s, {
  						x1: x, y1: y,
  						x2: x + dx,
  						y2: y + dy
  					}).setStroke(taMajorTick);
  					if(tick.label){
  						var label = o.maxLabelCharCount ? this.getTextWithLimitCharCount(tick.label, taFont, o.maxLabelCharCount) : {
  							text: tick.label,
  							truncated: false
  						};
  						label = o.maxLabelSize ? this.getTextWithLimitLength(label.text, taFont, o.maxLabelSize, label.truncated) : label;
  						elem = this.createText(labelType,
  							s,
  							x + dx + anchorOffset.x + (rotation ? 0 : labelOffset.x),
  							y + dy + anchorOffset.y + (rotation ? 0 : labelOffset.y),
  							labelAlign,
  							label.text,
  							taFont,
  							taFontColor
  							//this._cachedLabelWidth
  						);
  
  						// if bidi support was required, the textDir is "auto" and truncation
  						// took place, we need to update the dir of the element for cases as:
  						// Fool label: 111111W (W for bidi character)
  						// truncated label: 11...
  						// in this case for auto textDir the dir will be "ltr" which is wrong.
  						if(this.chart.truncateBidi  && label.truncated){
  							this.chart.truncateBidi(elem, tick.label, labelType);
  						}
  						label.truncated && this.labelTooltip(elem, this.chart, tick.label, label.text, taFont, labelType);
  						if(labelType == "html"){
  							this.htmlElements.push(elem);
  						}else if(rotation){
  							elem.setTransform([
  								{dx: labelOffset.x, dy: labelOffset.y},
  								g.matrix.rotategAt(
  									rotation,
  									x + dx + anchorOffset.x,
  									y + dy + anchorOffset.y
  								)
  							]);
  						}
  					}
  			}, this);
  
  			dx = tickVector.x * taMinorTick.length;
  			dy = tickVector.y * taMinorTick.length;
  			canLabel = c.minMinorStep <= c.minor.tick * c.bounds.scale;
  			arr.forEach(t.minor, function(tick){
  				var offset = f(tick.value), elem,
  					x = start.x + axisVector.x * offset,
  					y = start.y + axisVector.y * offset;
  					this.createLine(s, {
  						x1: x, y1: y,
  						x2: x + dx,
  						y2: y + dy
  					}).setStroke(taMinorTick);
  					if(canLabel && tick.label){
  						var label = o.maxLabelCharCount ? this.getTextWithLimitCharCount(tick.label, taFont, o.maxLabelCharCount) : {
  							text: tick.label,
  							truncated: false
  						};
  						label = o.maxLabelSize ? this.getTextWithLimitLength(label.text, taFont, o.maxLabelSize, label.truncated) : label;
  						elem = this.createText(labelType,
  							s,
  							x + dx + anchorOffset.x + (rotation ? 0 : labelOffset.x),
  							y + dy + anchorOffset.y + (rotation ? 0 : labelOffset.y),
  							labelAlign,
  							label.text,
  							taFont,
  							taFontColor
  							//this._cachedLabelWidth
  						);
  						// if bidi support was required, the textDir is "auto" and truncation
  						// took place, we need to update the dir of the element for cases as:
  						// Fool label: 111111W (W for bidi character)
  						// truncated label: 11...
  						// in this case for auto textDir the dir will be "ltr" which is wrong.
  						if(this.chart.getTextDir && label.truncated){
  							this.chart.truncateBidi(elem, tick.label, labelType);
  						}
  						label.truncated && this.labelTooltip(elem, this.chart, tick.label, label.text, taFont, labelType);
  						if(labelType == "html"){
  							this.htmlElements.push(elem);
  						}else if(rotation){
  							elem.setTransform([
  								{dx: labelOffset.x, dy: labelOffset.y},
  								g.matrix.rotategAt(
  									rotation,
  									x + dx + anchorOffset.x,
  									y + dy + anchorOffset.y
  								)
  							]);
  						}
  					}
  			}, this);
  
  			dx = tickVector.x * taMicroTick.length;
  			dy = tickVector.y * taMicroTick.length;
  			arr.forEach(t.micro, function(tick){
  				var offset = f(tick.value), elem,
  					x = start.x + axisVector.x * offset,
  					y = start.y + axisVector.y * offset;
  					this.createLine(s, {
  						x1: x, y1: y,
  						x2: x + dx,
  						y2: y + dy
  					}).setStroke(taMicroTick);
  			}, this);
  
  			this.dirty = false;
  			return this;	//	dojox.charting.axis2d.Default
  		},
  		labelTooltip: function(elem, chart, label, truncatedLabel, font, elemType){
  			var modules = ["dijit/Tooltip"];
  			var aroundRect = {type: "rect"}, position = ["above", "below"],
  				fontWidth = g._base._getTextBox(truncatedLabel, {font: font}).w || 0,
  				fontHeight = font ? g.normalizedLength(g.splitFontString(font).size) : 0;
  			if(elemType == "html"){
  				lang.mixin(aroundRect, html.coords(elem.firstChild, true));
  				aroundRect.width = Math.ceil(fontWidth);
  				aroundRect.height = Math.ceil(fontHeight);
  				this._events.push({
  					shape:  dojo,
  					handle: connect.connect(elem.firstChild, "onmouseover", this, function(e){
  						require(modules, function(Tooltip){
  							Tooltip.show(label, aroundRect, position);
  						});
  					})
  				});
  				this._events.push({
  					shape:  dojo,
  					handle: connect.connect(elem.firstChild, "onmouseout", this, function(e){
  						require(modules, function(Tooltip){
  							Tooltip.hide(aroundRect);
  						});
  					})
  				});
  			}else{
  				var shp = elem.getShape(),
  					lt = html.coords(chart.node, true);
  				aroundRect = lang.mixin(aroundRect, {
  					x: shp.x - fontWidth / 2,
  					y: shp.y
  				});
  				aroundRect.x += lt.x;
  				aroundRect.y += lt.y;
  				aroundRect.x = Math.round(aroundRect.x);
  				aroundRect.y = Math.round(aroundRect.y);
  				aroundRect.width = Math.ceil(fontWidth);
  				aroundRect.height = Math.ceil(fontHeight);
  				this._events.push({
  					shape:  elem,
  					handle: elem.connect("onmouseenter", this, function(e){
  						require(modules, function(Tooltip){
  							Tooltip.show(label, aroundRect, position);
  						});
  					})
  				});
  				this._events.push({
  					shape:  elem,
  					handle: elem.connect("onmouseleave", this, function(e){
  						require(modules, function(Tooltip){
  							Tooltip.hide(aroundRect);
  						});
  					})
  				});
  			}
  		}
  	});
  });
  