final Label la = ax.getLabel( ); final int iLabelLocation = ax.getLabelPosition( ); final int iOrientation = ax.getOrientation( ); DataElement oMinimum = scModel.getMin( ); DataElement oMaximum = scModel.getMax( ); Double oStep = scModel.isSetStep( ) ? new Double( scModel.getStep( ) ) : null;  AutoScale sc = null; AutoScale scCloned = null;  if ( ( iType & TEXT ) == TEXT || ax.isCategoryScale( ) ) { sc = new AutoScale( iType ); sc.fs = fs; sc.rtc = rtc; sc.bCategoryScale = true; sc.bAxisLabelStaggered = ax.isAxisLabelStaggered( ); sc.iLabelShowingInterval = ax.getLableShowingInterval( ); sc.dZoomFactor = zoomFactor; sc.setData( dsi ); sc.setDirection( direction ); sc.computeTicks( xs, ax.getLabel( ), iLabelLocation, iOrientation, dStart, dEnd, false, null ); } else if ( ( iType & LINEAR ) == LINEAR ) { Object oValue; double dValue, dMinValue = Double.MAX_VALUE, dMaxValue = -Double.MAX_VALUE; dsi.reset( ); double dPrecision = 0; while ( dsi.hasNext( ) ) { oValue = dsi.next( ); if ( oValue == null ) { continue; } dValue = ( (Double) oValue ).doubleValue( ); if ( dValue < dMinValue ) dMinValue = dValue; if ( dValue > dMaxValue ) dMaxValue = dValue; dPrecision = getPrecision( dPrecision, dValue ); }  double dDelta = dMaxValue - dMinValue; if ( dDelta == 0 )  { dDelta = 1; } final double dAbsMax = Math.abs( dMaxValue ); final double dAbsMin = Math.abs( dMinValue ); double dStep = Math.max( dAbsMax, dAbsMin ); dStep = Math.floor( Math.log( dDelta ) / LOG_10 ); dStep = Math.pow( 10, dStep );  if ( dStep < dPrecision ) { dStep = dPrecision; }  sc = new AutoScale( iType, new Double( 0 ), new Double( 0 ), new Double( dStep ) ); sc.setData( dsi ); sc.setDirection( direction ); sc.fs = fs; sc.rtc = rtc; sc.bAxisLabelStaggered = ax.isAxisLabelStaggered( ); sc.iLabelShowingInterval = ax.getLableShowingInterval( ); sc.dZoomFactor = zoomFactor; sc.dPrecision = dPrecision;   if ( oMinimum != null ) { if ( oMinimum instanceof NumberDataElement ) { sc.oMinimum = new Double( ( (NumberDataElement) oMinimum ).getValue( ) ); }  else { throw new ChartException( ChartEnginePlugin.ID, ChartException.GENERATION, "exception.invalid.minimum.scale.value", new Object[]{ sc.oMinimum, ax.getModelAxis( ).getType( ).getName( ) }, Messages.getResourceBundle( rtc.getULocale( ) ) ); } sc.bMinimumFixed = true; }   if ( oMaximum != null ) { if ( oMaximum instanceof NumberDataElement ) { sc.oMaximum = new Double( ( (NumberDataElement) oMaximum ).getValue( ) ); }  else { throw new ChartException( ChartEnginePlugin.ID, ChartException.GENERATION, "exception.invalid.maximum.scale.value", new Object[]{ sc.oMaximum, ax.getModelAxis( ).getType( ).getName( ) }, Messages.getResourceBundle( rtc.getULocale( ) ) ); } sc.bMaximumFixed = true; }   if ( oStep != null ) { sc.oStep = oStep; sc.bStepFixed = true;   if ( ( (Double) sc.oStep ).doubleValue( ) <= 0 ) { throw new ChartException( ChartEnginePlugin.ID, ChartException.GENERATION, "exception.invalid.step.value", new Object[]{ oStep }, Messages.getResourceBundle( rtc.getULocale( ) ) ); } }   if ( sc.bMaximumFixed && sc.bMinimumFixed ) { if ( ( (Double) sc.oMinimum ).doubleValue( ) > ( (Double) sc.oMaximum ).doubleValue( ) ) { throw new ChartException( ChartEnginePlugin.ID, ChartException.GENERATION, "exception.min.largerthan.max", new Object[]{ sc.oMinimum, sc.oMaximum }, Messages.getResourceBundle( rtc.getULocale( ) ) ); } }  final Object oMinValue = new Double( dMinValue ); final Object oMaxValue = new Double( dMaxValue ); sc.updateAxisMinMax( oMinValue, oMaxValue );  sc.computeTicks( xs, ax.getLabel( ), iLabelLocation, iOrientation, dStart, dEnd, false, null ); dStart = sc.dStart; dEnd = sc.dEnd;  boolean bFirstFit = sc.checkFit( xs, la, iLabelLocation ); boolean bFits = bFirstFit; boolean bZoomSuccess = false;   while ( bFits == bFirstFit ) { bZoomSuccess = true; scCloned = (AutoScale) sc.clone( ); if ( sc.bStepFixed ) { break; } if ( bFirstFit ) { if ( !bFits ) { break; } bZoomSuccess = sc.zoomIn( ); } else { if ( !bFits && sc.getTickCordinates( ).length == 2 ) { break; } bZoomSuccess = sc.zoomOut( ); } if ( !bZoomSuccess ) break;  sc.updateAxisMinMax( oMinValue, oMaxValue ); sc.computeTicks( xs, ax.getLabel( ), iLabelLocation, iOrientation, dStart, dEnd, false, null ); bFits = sc.checkFit( xs, la, iLabelLocation ); if ( !bFits && sc.getTickCordinates( ).length == 2 ) { sc = scCloned; break; } }   if ( scCloned != null && bFirstFit && bZoomSuccess ) { sc = scCloned; } }  else if ( ( iType & LOGARITHMIC ) == LOGARITHMIC ) { Object oValue; double dValue, dMinValue = Double.MAX_VALUE, dMaxValue = -Double.MAX_VALUE; if ( ( iType & PERCENT ) == PERCENT ) { dMinValue = 0; dMaxValue = 100; } else { dsi.reset( ); while ( dsi.hasNext( ) ) { oValue = dsi.next( ); if ( oValue == null ) { continue; } dValue = ( (Double) oValue ).doubleValue( ); if ( dValue < dMinValue ) dMinValue = dValue; if ( dValue > dMaxValue ) dMaxValue = dValue; } } final Object oMinValue = new Double( dMinValue ); final Object oMaxValue = new Double( dMaxValue );  sc = new AutoScale( iType, new Double( 0 ), new Double( 0 ), new Double( 10 ) ); sc.fs = fs; sc.rtc = rtc; sc.bAxisLabelStaggered = ax.isAxisLabelStaggered( ); sc.iLabelShowingInterval = ax.getLableShowingInterval( ); sc.dZoomFactor = zoomFactor; sc.setData( dsi ); sc.setDirection( direction ); sc.updateAxisMinMax( oMinValue, oMaxValue ); if ( ( iType & PERCENT ) == PERCENT ) { sc.bStepFixed = true; sc.bMaximumFixed = true; sc.bMinimumFixed = true; } sc.computeTicks( xs, ax.getLabel( ), iLabelLocation, iOrientation, dStart, dEnd, false, null ); if ( ( iType & PERCENT ) == PERCENT ) { return sc; }  dStart = sc.dStart; dEnd = sc.dEnd;  boolean bFirstFit = sc.checkFit( xs, la, iLabelLocation ); boolean bFits = bFirstFit; boolean bZoomSuccess = false;   while ( bFits == bFirstFit ) { bZoomSuccess = true; scCloned = (AutoScale) sc.clone( ); if ( sc.bStepFixed ) { break; } if ( bFirstFit ) { if ( !bFits ) { break; } bZoomSuccess = sc.zoomIn( ); } else { if ( !bFits && sc.getTickCordinates( ).length == 2 ) { break; } bZoomSuccess = sc.zoomOut( ); } if ( !bZoomSuccess ) break;  sc.updateAxisMinMax( oMinValue, oMaxValue ); sc.computeTicks( xs, ax.getLabel( ), iLabelLocation, iOrientation, dStart, dEnd, false, null );  bFits = sc.checkFit( xs, la, iLabelLocation ); if ( !bFits && sc.getTickCordinates( ).length == 2 ) { sc = scCloned; break; } }   if ( scCloned != null && bFirstFit && bZoomSuccess ) { sc = scCloned; } } else if ( ( iType & DATE_TIME ) == DATE_TIME ) { Calendar cValue; Calendar caMin = null, caMax = null; dsi.reset( ); while ( dsi.hasNext( ) ) { cValue = (Calendar) dsi.next( ); if ( cValue == null ) { continue; } if ( caMin == null ) { caMin = cValue; } if ( caMax == null ) { caMax = cValue; } if ( cValue.before( caMin ) ) caMin = cValue; else if ( cValue.after( caMax ) ) caMax = cValue; }  CDateTime cdtMinValue = new CDateTime( caMin ); CDateTime cdtMaxValue = new CDateTime( caMax ); int iUnit; if ( oStep != null ) { iUnit = ChartUtil.convertUnitTypeToCalendarConstant( scModel.getUnit( ) ); } else { iUnit = CDateTime.getDifference( cdtMinValue, cdtMaxValue ); }   if ( iUnit == 0 ) iUnit = CDateTime.SECOND;  CDateTime cdtMinAxis = cdtMinValue.backward( iUnit, 1 ); CDateTime cdtMaxAxis = cdtMaxValue.forward( iUnit, 1 ); cdtMinAxis.clearBelow( iUnit ); cdtMaxAxis.clearBelow( iUnit );  sc = new AutoScale( DATE_TIME, cdtMinAxis, cdtMaxAxis, new Integer( iUnit ), new Integer( 1 ) ); sc.setDirection( direction ); sc.fs = fs; sc.rtc = rtc; sc.bAxisLabelStaggered = ax.isAxisLabelStaggered( ); sc.iLabelShowingInterval = ax.getLableShowingInterval( ); sc.dZoomFactor = zoomFactor;   if ( oMinimum != null ) { if ( oMinimum instanceof DateTimeDataElement ) { sc.oMinimum = ( (DateTimeDataElement) oMinimum ).getValueAsCDateTime( ); } else { throw new ChartException( ChartEnginePlugin.ID, ChartException.GENERATION, "exception.invalid.minimum.scale.value", new Object[]{ oMinimum, ax.getModelAxis( ).getType( ).getName( ) }, Messages.getResourceBundle( rtc.getULocale( ) ) ); } sc.bMinimumFixed = true; }   if ( oMaximum != null ) { if ( oMaximum instanceof DateTimeDataElement ) { sc.oMaximum = ( (DateTimeDataElement) oMaximum ).getValueAsCDateTime( ); } else { throw new ChartException( ChartEnginePlugin.ID, ChartException.GENERATION, "exception.invalid.maximum.scale.value", new Object[]{ sc.oMaximum, ax.getModelAxis( ).getType( ).getName( ) }, Messages.getResourceBundle( rtc.getULocale( ) ) ); } sc.bMaximumFixed = true; }   if ( oStep != null ) { sc.oStep = oStep; sc.bStepFixed = true;  if ( ( (Double) sc.oStep ).doubleValue( ) <= 0 ) { throw new ChartException( ChartEnginePlugin.ID, ChartException.GENERATION, "exception.invalid.step.value", new Object[]{ oStep }, Messages.getResourceBundle( rtc.getULocale( ) ) ); } }   if ( sc.bMaximumFixed && sc.bMinimumFixed ) { if ( ( (CDateTime) sc.oMinimum ).after( sc.oMaximum ) ) { throw new ChartException( ChartEnginePlugin.ID, ChartException.GENERATION, "exception.min.largerthan.max", new Object[]{ sc.oMinimum, sc.oMaximum }, Messages.getResourceBundle( rtc.getULocale( ) ) ); } }  sc.computeTicks( xs, la, iLabelLocation, iOrientation, dStart, dEnd, false, null ); dStart = sc.dStart; dEnd = sc.dEnd;  boolean bFirstFit = sc.checkFit( xs, la, iLabelLocation ); boolean bFits = bFirstFit, bZoomSuccess = false;  while ( bFits == bFirstFit ) { bZoomSuccess = true; scCloned = (AutoScale) sc.clone( ); if ( sc.bStepFixed ) { break; } if ( bFirstFit ) { if ( !bFits ) { break; } bZoomSuccess = sc.zoomIn( ); } else { if ( !bFits && sc.getTickCordinates( ).length == 2 ) { break; } bZoomSuccess = sc.zoomOut( ); } if ( !bZoomSuccess ) break;  sc.adjustAxisMinMax( cdtMinValue, cdtMaxValue );  sc.computeTicks( xs, la, iLabelLocation, iOrientation, dStart, dEnd, false, null ); bFits = sc.checkFit( xs, la, iLabelLocation ); if ( !bFits && sc.getTickCordinates( ).length == 2 ) { sc = scCloned; break; } }   if ( scCloned != null && bFirstFit && bZoomSuccess ) { sc = scCloned; } }  sc.setData( dsi ); return sc;
return computeScale( xs, ax, dsi, iType, dStart, dEnd, scModel, fs, rtc, direction, 1.0 );
	static final AutoScale computeScale( IDisplayServer xs, OneAxis ax,			DataSetIterator dsi, int iType, double dStart, double dEnd,			Scale scModel, FormatSpecifier fs, RunTimeContext rtc, int direction,			double zoomFactor ) throws ChartException	{		final Label la = ax.getLabel( );		final int iLabelLocation = ax.getLabelPosition( );		final int iOrientation = ax.getOrientation( );		DataElement oMinimum = scModel.getMin( );		DataElement oMaximum = scModel.getMax( );		Double oStep = scModel.isSetStep( ) ? new Double( scModel.getStep( ) )				: null;				AutoScale sc = null;		AutoScale scCloned = null;		if ( ( iType & TEXT ) == TEXT || ax.isCategoryScale( ) )		{			sc = new AutoScale( iType );			sc.fs = fs;			sc.rtc = rtc;			sc.bCategoryScale = true;			sc.bAxisLabelStaggered = ax.isAxisLabelStaggered( );			sc.iLabelShowingInterval = ax.getLableShowingInterval( );			sc.dZoomFactor = zoomFactor;			sc.setData( dsi );			sc.setDirection( direction );			sc.computeTicks( xs,					ax.getLabel( ),					iLabelLocation,					iOrientation,					dStart,					dEnd,					false,					null );		}		else if ( ( iType & LINEAR ) == LINEAR )		{			Object oValue;			double dValue, dMinValue = Double.MAX_VALUE, dMaxValue = -Double.MAX_VALUE;			dsi.reset( );			double dPrecision = 0;			while ( dsi.hasNext( ) )			{				oValue = dsi.next( );				if ( oValue == null ) // NULL VALUE CHECK				{					continue;				}				dValue = ( (Double) oValue ).doubleValue( );				if ( dValue < dMinValue )					dMinValue = dValue;				if ( dValue > dMaxValue )					dMaxValue = dValue;				dPrecision = getPrecision( dPrecision, dValue );			}			double dDelta = dMaxValue - dMinValue;			if ( dDelta == 0 ) // PREVENT INFINITE LOOP DUE TO LOG(dDelta) IN			// AUTO SCALING ALGORITHM			{				dDelta = 1;			}			final double dAbsMax = Math.abs( dMaxValue );			final double dAbsMin = Math.abs( dMinValue );			double dStep = Math.max( dAbsMax, dAbsMin );			dStep = Math.floor( Math.log( dDelta ) / LOG_10 );			dStep = Math.pow( 10, dStep );			// The automatic step should never be more precise than the data itself			if ( dStep < dPrecision )			{				dStep = dPrecision;			}			sc = new AutoScale( iType,					new Double( 0 ),					new Double( 0 ),					new Double( dStep ) );			sc.setData( dsi );			sc.setDirection( direction );			sc.fs = fs; // FORMAT SPECIFIER			sc.rtc = rtc; // LOCALE			sc.bAxisLabelStaggered = ax.isAxisLabelStaggered( );			sc.iLabelShowingInterval = ax.getLableShowingInterval( );			sc.dZoomFactor = zoomFactor;			sc.dPrecision = dPrecision;			// OVERRIDE MINIMUM IF SPECIFIED			if ( oMinimum != null )			{				if ( oMinimum instanceof NumberDataElement )				{					sc.oMinimum = new Double( ( (NumberDataElement) oMinimum ).getValue( ) );				}				/*				 * else if (oMinimum instanceof DateTimeDataElement) {				 * sc.oMinimum = ((DateTimeDataElement)				 * oMinimum).getValueAsCDateTime(); }				 */				else				{					throw new ChartException( ChartEnginePlugin.ID,							ChartException.GENERATION,							"exception.invalid.minimum.scale.value", //$NON-NLS-1$							new Object[]{									sc.oMinimum,									ax.getModelAxis( ).getType( ).getName( )							},							Messages.getResourceBundle( rtc.getULocale( ) ) );				}				sc.bMinimumFixed = true;			}			// OVERRIDE MAXIMUM IF SPECIFIED			if ( oMaximum != null )			{				if ( oMaximum instanceof NumberDataElement )				{					sc.oMaximum = new Double( ( (NumberDataElement) oMaximum ).getValue( ) );				}				/*				 * else if (oMaximum instanceof DateTimeDataElement) {				 * sc.oMaximum = ((DateTimeDataElement)				 * oMaximum).getValueAsCDateTime(); }				 */				else				{					throw new ChartException( ChartEnginePlugin.ID,							ChartException.GENERATION,							"exception.invalid.maximum.scale.value", //$NON-NLS-1$							new Object[]{									sc.oMaximum,									ax.getModelAxis( ).getType( ).getName( )							},							Messages.getResourceBundle( rtc.getULocale( ) ) );				}				sc.bMaximumFixed = true;			}			// OVERRIDE STEP IF SPECIFIED			if ( oStep != null )			{				sc.oStep = oStep;				sc.bStepFixed = true;				// VALIDATE OVERRIDDEN STEP				if ( ( (Double) sc.oStep ).doubleValue( ) <= 0 )				{					throw new ChartException( ChartEnginePlugin.ID,							ChartException.GENERATION,							"exception.invalid.step.value", //$NON-NLS-1$							new Object[]{								oStep							},							Messages.getResourceBundle( rtc.getULocale( ) ) );				}			}			// VALIDATE OVERRIDDEN MIN/MAX			if ( sc.bMaximumFixed && sc.bMinimumFixed )			{				if ( ( (Double) sc.oMinimum ).doubleValue( ) > ( (Double) sc.oMaximum ).doubleValue( ) )				{					throw new ChartException( ChartEnginePlugin.ID,							ChartException.GENERATION,							"exception.min.largerthan.max", //$NON-NLS-1$ 							new Object[]{									sc.oMinimum, sc.oMaximum							},							Messages.getResourceBundle( rtc.getULocale( ) ) );				}			}			final Object oMinValue = new Double( dMinValue );			final Object oMaxValue = new Double( dMaxValue );			sc.updateAxisMinMax( oMinValue, oMaxValue );			sc.computeTicks( xs,					ax.getLabel( ),					iLabelLocation,					iOrientation,					dStart,					dEnd,					false,					null );			dStart = sc.dStart;			dEnd = sc.dEnd;			boolean bFirstFit = sc.checkFit( xs, la, iLabelLocation );			boolean bFits = bFirstFit;			boolean bZoomSuccess = false;			// THE AUTO ZOOM LOOP			while ( bFits == bFirstFit )			{				bZoomSuccess = true;				scCloned = (AutoScale) sc.clone( );				if ( sc.bStepFixed ) // DO NOT AUTO ZOOM IF STEP IS FIXED				{					break;				}				if ( bFirstFit )				{					if ( !bFits )					{						break;					}					bZoomSuccess = sc.zoomIn( );				}				else				{					if ( !bFits && sc.getTickCordinates( ).length == 2 )					{						break;					}					bZoomSuccess = sc.zoomOut( );				}				if ( !bZoomSuccess )					break;				sc.updateAxisMinMax( oMinValue, oMaxValue );				sc.computeTicks( xs,						ax.getLabel( ),						iLabelLocation,						iOrientation,						dStart,						dEnd,						false,						null );				bFits = sc.checkFit( xs, la, iLabelLocation );				if ( !bFits && sc.getTickCordinates( ).length == 2 )				{					sc = scCloned;					break;				}			}			// RESTORE TO LAST SCALE BEFORE ZOOM			if ( scCloned != null && bFirstFit && bZoomSuccess )			{				sc = scCloned;			}		}		else if ( ( iType & LOGARITHMIC ) == LOGARITHMIC )		{			Object oValue;			double dValue, dMinValue = Double.MAX_VALUE, dMaxValue = -Double.MAX_VALUE;			if ( ( iType & PERCENT ) == PERCENT )			{				dMinValue = 0;				dMaxValue = 100;			}			else			{				dsi.reset( );				while ( dsi.hasNext( ) )				{					oValue = dsi.next( );					if ( oValue == null ) // NULL VALUE CHECK					{						continue;					}					dValue = ( (Double) oValue ).doubleValue( );					if ( dValue < dMinValue )						dMinValue = dValue;					if ( dValue > dMaxValue )						dMaxValue = dValue;				}			}			final Object oMinValue = new Double( dMinValue );			final Object oMaxValue = new Double( dMaxValue );			sc = new AutoScale( iType,					new Double( 0 ),					new Double( 0 ),					new Double( 10 ) );			sc.fs = fs; // FORMAT SPECIFIER			sc.rtc = rtc; // LOCALE			sc.bAxisLabelStaggered = ax.isAxisLabelStaggered( );			sc.iLabelShowingInterval = ax.getLableShowingInterval( );			sc.dZoomFactor = zoomFactor;			sc.setData( dsi );			sc.setDirection( direction );			sc.updateAxisMinMax( oMinValue, oMaxValue );			if ( ( iType & PERCENT ) == PERCENT )			{				sc.bStepFixed = true;				sc.bMaximumFixed = true;				sc.bMinimumFixed = true;			}			sc.computeTicks( xs,					ax.getLabel( ),					iLabelLocation,					iOrientation,					dStart,					dEnd,					false,					null );			if ( ( iType & PERCENT ) == PERCENT )			{				return sc;			}			dStart = sc.dStart;			dEnd = sc.dEnd;			boolean bFirstFit = sc.checkFit( xs, la, iLabelLocation );			boolean bFits = bFirstFit;			boolean bZoomSuccess = false;			// sc.oDebug = String.valueOf(bFirstFit);			while ( bFits == bFirstFit )			{				bZoomSuccess = true;				scCloned = (AutoScale) sc.clone( );				if ( sc.bStepFixed ) // DO NOT AUTO ZOOM IF STEP IS FIXED				{					break;				}				if ( bFirstFit )				{					if ( !bFits )					{						break;					}					bZoomSuccess = sc.zoomIn( );				}				else				{					if ( !bFits && sc.getTickCordinates( ).length == 2 )					{						break;					}					bZoomSuccess = sc.zoomOut( );				}				if ( !bZoomSuccess )					break;				sc.updateAxisMinMax( oMinValue, oMaxValue );				sc.computeTicks( xs,						ax.getLabel( ),						iLabelLocation,						iOrientation,						dStart,						dEnd,						false,						null );				bFits = sc.checkFit( xs, la, iLabelLocation );				if ( !bFits && sc.getTickCordinates( ).length == 2 )				{					sc = scCloned;					break;				}			}			// RESTORE TO LAST SCALE BEFORE ZOOM			if ( scCloned != null && bFirstFit && bZoomSuccess )			{				sc = scCloned;			}		}		else if ( ( iType & DATE_TIME ) == DATE_TIME )		{			Calendar cValue;			Calendar caMin = null, caMax = null;			dsi.reset( );			while ( dsi.hasNext( ) )			{				cValue = (Calendar) dsi.next( );				if ( cValue == null ) // NULL VALUE CHECK				{					continue;				}				if ( caMin == null )				{					caMin = cValue;				}				if ( caMax == null )				{					caMax = cValue;				}				if ( cValue.before( caMin ) )					caMin = cValue;				else if ( cValue.after( caMax ) )					caMax = cValue;			}			CDateTime cdtMinValue = new CDateTime( caMin );			CDateTime cdtMaxValue = new CDateTime( caMax );			int iUnit;			if ( oStep != null )			{				iUnit = ChartUtil.convertUnitTypeToCalendarConstant( scModel.getUnit( ) );			}			else			{				iUnit = CDateTime.getDifference( cdtMinValue, cdtMaxValue );			}			// Can't detect a difference, assume ms			if ( iUnit == 0 )				iUnit = CDateTime.SECOND;			CDateTime cdtMinAxis = cdtMinValue.backward( iUnit, 1 );			CDateTime cdtMaxAxis = cdtMaxValue.forward( iUnit, 1 );			cdtMinAxis.clearBelow( iUnit );			cdtMaxAxis.clearBelow( iUnit );			sc = new AutoScale( DATE_TIME,					cdtMinAxis,					cdtMaxAxis,					new Integer( iUnit ),					new Integer( 1 ) );			sc.setDirection( direction );			sc.fs = fs; // FORMAT SPECIFIER			sc.rtc = rtc; // LOCALE			sc.bAxisLabelStaggered = ax.isAxisLabelStaggered( );			sc.iLabelShowingInterval = ax.getLableShowingInterval( );			sc.dZoomFactor = zoomFactor;			// OVERRIDE MINIMUM IF SPECIFIED			if ( oMinimum != null )			{				if ( oMinimum instanceof DateTimeDataElement )				{					sc.oMinimum = ( (DateTimeDataElement) oMinimum ).getValueAsCDateTime( );				}				else				{					throw new ChartException( ChartEnginePlugin.ID,							ChartException.GENERATION,							"exception.invalid.minimum.scale.value", //$NON-NLS-1$ 							new Object[]{									oMinimum,									ax.getModelAxis( ).getType( ).getName( )							},							Messages.getResourceBundle( rtc.getULocale( ) ) );				}				sc.bMinimumFixed = true;			}			// OVERRIDE MAXIMUM IF SPECIFIED			if ( oMaximum != null )			{				if ( oMaximum instanceof DateTimeDataElement )				{					sc.oMaximum = ( (DateTimeDataElement) oMaximum ).getValueAsCDateTime( );				}				else				{					throw new ChartException( ChartEnginePlugin.ID,							ChartException.GENERATION,							"exception.invalid.maximum.scale.value", //$NON-NLS-1$							new Object[]{									sc.oMaximum,									ax.getModelAxis( ).getType( ).getName( )							},							Messages.getResourceBundle( rtc.getULocale( ) ) );				}				sc.bMaximumFixed = true;			}			// OVERRIDE STEP IF SPECIFIED			if ( oStep != null )			{				sc.oStep = oStep;				sc.bStepFixed = true;				// VALIDATE OVERRIDDEN STEP				if ( ( (Double) sc.oStep ).doubleValue( ) <= 0 )				{					throw new ChartException( ChartEnginePlugin.ID,							ChartException.GENERATION,							"exception.invalid.step.value", //$NON-NLS-1$							new Object[]{								oStep							},							Messages.getResourceBundle( rtc.getULocale( ) ) );				}			}			// VALIDATE OVERRIDDEN MIN/MAX			if ( sc.bMaximumFixed && sc.bMinimumFixed )			{				if ( ( (CDateTime) sc.oMinimum ).after( sc.oMaximum ) )				{					throw new ChartException( ChartEnginePlugin.ID,							ChartException.GENERATION,							"exception.min.largerthan.max", //$NON-NLS-1$							new Object[]{									sc.oMinimum, sc.oMaximum							},							Messages.getResourceBundle( rtc.getULocale( ) ) );				}			}						sc.computeTicks( xs,					la,					iLabelLocation,					iOrientation,					dStart,					dEnd,					false,					null );			dStart = sc.dStart;			dEnd = sc.dEnd;			boolean bFirstFit = sc.checkFit( xs, la, iLabelLocation );			boolean bFits = bFirstFit, bZoomSuccess = false;			while ( bFits == bFirstFit )			{				bZoomSuccess = true;				scCloned = (AutoScale) sc.clone( );				if ( sc.bStepFixed ) // DO NOT AUTO ZOOM IF STEP IS FIXED				{					break;				}				if ( bFirstFit )				{					if ( !bFits )					{						break;					}					bZoomSuccess = sc.zoomIn( );				}				else				{					if ( !bFits && sc.getTickCordinates( ).length == 2 )					{						break;					}					bZoomSuccess = sc.zoomOut( );				}				if ( !bZoomSuccess )					break;				sc.adjustAxisMinMax( cdtMinValue, cdtMaxValue );				sc.computeTicks( xs,						la,						iLabelLocation,						iOrientation,						dStart,						dEnd,						false,						null );				bFits = sc.checkFit( xs, la, iLabelLocation );				if ( !bFits && sc.getTickCordinates( ).length == 2 )				{					sc = scCloned;					break;				}			}			// RESTORE TO LAST SCALE BEFORE ZOOM			if ( scCloned != null && bFirstFit && bZoomSuccess )			{				sc = scCloned;			}		}		sc.setData( dsi );		return sc;	}