final double dAngleInDegrees = fd.getRotation();
    static final AutoScale computeScale(IDisplayServer xs, OneAxis ax, DataSetIterator dsi, int iType, double dStart,        double dEnd, DataElement oMinimum, DataElement oMaximum, Double oStep, FormatSpecifier fs, Locale lcl)        throws GenerationException    {        final Label la = ax.getLabel();        final FontDefinition fd = la.getCaption().getFont();        final int iLabelLocation = ax.getLabelPosition();        final int iOrientation = ax.getOrientation();        final double dAngleInDegrees = fd.getRotation();        AutoScale sc = null;        AutoScale scCloned = null;        if ((iType & TEXT) == TEXT || ax.isCategoryScale())        {            sc = new AutoScale(iType);            sc.bCategoryScale = true;            sc.setData(dsi);            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.MIN_VALUE;            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;            }            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);            sc = new AutoScale(iType, new Double(0), new Double(0), new Double(dStep));            sc.setData(dsi);            sc.fs = fs; // FORMAT SPECIFIER            sc.lcl = lcl; // LOCALE            // 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 GenerationException("Cannot override minimum value for axis " + ax + " with value "                        + sc.oMinimum);                }                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 GenerationException("Cannot override maximum value for axis " + ax + " with value "                        + sc.oMaximum);                }                sc.bMaximumFixed = true;            }            // OVERRIDE STEP IF SPECIFIED            if (oStep != null)            {                sc.oStep = oStep;                sc.bStepFixed = true;            }            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 bZoomMore, bZoomSuccess = false;            //sc.oDebug = String.valueOf(bFirstFit);            // 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.getTickCount() == 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.getTickCount() == 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.MIN_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.lcl = lcl; // LOCALE            sc.setData(dsi);            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 bZoomMore, 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.getTickCount() == 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.getTickCount() == 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();                String s = cValue.toString();                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 = CDateTime.getDifference(cdtMinValue, cdtMaxValue);            CDateTime cdtMinAxis = cdtMinValue.backward(iUnit, 1);            CDateTime cdtMaxAxis = cdtMaxValue.forward(iUnit, 1);            cdtMinAxis.clearBelow(iUnit);            cdtMaxAxis.clearBelow(iUnit);            /*             * SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss"); String sMin =             * sdf.format(cdtMinAxis.getTime()); String sMax = sdf.format(cdtMaxAxis.getTime());             */            sc = new AutoScale(DATE_TIME, cdtMinAxis, cdtMaxAxis, new Integer(iUnit), new Integer(1));            sc.computeTicks(xs, la, iLabelLocation, iOrientation, dStart, dEnd, false, null);            sc.fs = fs; // FORMAT SPECIFIER            sc.lcl = lcl; // LOCALE            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.getTickCount() == 2)                    {                        break;                    }                    bZoomSuccess = sc.zoomOut();                }                if (!bZoomSuccess)                    break;                sc.adjustAxisMinMax(cdtMinValue, cdtMaxValue);                /*                 * sdf = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss"); sMin =                 * sdf.format(((CDateTime)sc.oMinimum).getTime()); sMax =                 * sdf.format(((CDateTime)sc.oMaximum).getTime());                 */                sc.computeTicks(xs, la, iLabelLocation, iOrientation, dStart, dEnd, false, null);                bFits = sc.checkFit(xs, la, iLabelLocation);                if (!bFits && sc.getTickCount() == 2)                {                    sc = scCloned;                    break;                }            }            // RESTORE TO LAST SCALE BEFORE ZOOM            if (scCloned != null && bFirstFit && bZoomSuccess)            {                sc = scCloned;            }        }        sc.setData(dsi);        return sc;    }