Program: 70619
Project: 70619
Buggy source:
/** 
 * @param dBlockY
 * @param dBlockHeight
 * @param aax
 * @return
 */
protected final double adjustVerticalDueToHorizontal(double dBlockY,double dBlockHeight,AllAxes aax) throws ChartException, IllegalArgumentException {
  final OneAxis axPH=aax.areAxesSwapped() ? aax.getPrimaryOrthogonal() : aax.getPrimaryBase();
  final OneAxis axPV=aax.areAxesSwapped() ? aax.getPrimaryBase() : aax.getPrimaryOrthogonal();
  final AutoScale scX=axPH.getScale();
  final AutoScale scY=axPV.getScale();
  final int iXLabelLocation=axPH.getLabelPosition();
  final int iYLabelLocation=axPV.getLabelPosition();
  final int iXTitleLocation=axPH.getTitlePosition();
  final Label laXAxisTitle=axPH.getTitle();
  final Label laYAxisLabels=axPV.getLabel();
  final int iXTickStyle=axPH.getCombinedTickStyle();
  final IntersectionValue iv=axPH.getIntersectionValue();
  double dXAxisLabelsThickness=scX.computeAxisLabelThickness(ids,axPH.getLabel(),HORIZONTAL);
  double[] dDecorationThickness={0,0};
  Series[] sea=cwa.getSeries(IConstants.ORTHOGONAL);
  Map<Series,LegendItemRenderingHints> seriesRenderingHints=rtc.getSeriesRenderers();
  for (int i=0; i < sea.length; i++) {
    LegendItemRenderingHints lirh=seriesRenderingHints.get(sea[i]);
    if (lirh != null && lirh.getRenderer() instanceof AxesRenderer) {
      IAxesDecorator iad=((AxesRenderer)lirh.getRenderer()).getAxesDecorator(axPH);
      if (iad != null) {
        double[] thickness=iad.computeDecorationThickness(ids,axPH);
        if (thickness[0] > dDecorationThickness[0]) {
          dDecorationThickness[0]=thickness[0];
        }
        if (thickness[1] > dDecorationThickness[1]) {
          dDecorationThickness[1]=thickness[1];
        }
      }
    }
  }
  double dXAxisTitleThickness=0;
  if (laXAxisTitle.isVisible()) {
    final String sPreviousValue=laXAxisTitle.getCaption().getValue();
    laXAxisTitle.getCaption().setValue(rtc.externalizedMessage(sPreviousValue));
    double maxWidth=Math.abs(scX.getEnd() - scX.getStart());
    double maxHeight=AXIS_TITLE_PERCENT * boPlot.getHeight();
    LabelLimiter lblLimit=new LabelLimiter(maxWidth,maxHeight,0);
    lblLimit.computeWrapping(ids,laXAxisTitle);
    lblLimit=lblLimit.limitLabelSize(ids,laXAxisTitle,EnumSet.of(LabelLimiter.Option.FIX_WIDTH));
    putLabelLimiter(axPH.getModelAxis().getTitle(),lblLimit);
    dXAxisTitleThickness=lblLimit.getMaxHeight();
    laXAxisTitle.getCaption().setValue(sPreviousValue);
  }
  double dHTotal=Math.abs(scY.getStart() - scY.getEnd());
  if (axPH.getModelAxis().isSetLabelSpan()) {
    double dFixedLabelThickness=axPH.getModelAxis().getLabelSpan();
    if (dFixedLabelThickness < dHTotal - 2 * getTickSize()) {
      if (dXAxisTitleThickness + dXAxisLabelsThickness > dFixedLabelThickness) {
        axPH.setShowLabels(false);
      }
      if (dXAxisTitleThickness > dFixedLabelThickness) {
        laXAxisTitle.setVisible(false);
        dXAxisLabelsThickness=0;
      }
      dXAxisLabelsThickness=dFixedLabelThickness;
    }
  }
  double dY=getLocation(scY,iv), dY1=dY, dY2=dY;
  final boolean bTicksAbove=(iXTickStyle & TICK_ABOVE) == TICK_ABOVE;
  final boolean bTicksBelow=(iXTickStyle & TICK_BELOW) == TICK_BELOW;
  final double dAppliedXAxisPlotSpacing=(iv.iType == IConstants.MAX || iv.iType == IConstants.MIN) ? dXAxisPlotSpacing : 0;
  final boolean bForwardScale=scY.getDirection() == FORWARD;
  if ((bForwardScale && iv.iType == IConstants.MIN) || (!bForwardScale && iv.iType == IConstants.MAX)) {
    dY-=dAppliedXAxisPlotSpacing;
    dHTotal-=dAppliedXAxisPlotSpacing;
    dY1=dY;
    dY2=dY;
    double dTickSize=getTickSize();
    if (bTicksAbove && dTickSize <= dHTotal) {
      dY1-=dTickSize;
      dHTotal-=dTickSize;
    }
 else {
      dTickSize=0;
    }
    double dH1=0;
    double dH2=0;
    if (iXLabelLocation == ABOVE) {
      dH1=Math.max(dXAxisLabelsThickness,dDecorationThickness[0]);
      dH2=Math.max(bTicksBelow ? getTickSize() : 0,dAppliedXAxisPlotSpacing);
    }
 else     if (iXLabelLocation == BELOW) {
      dH1=dDecorationThickness[0];
      dH2+=Math.max((bTicksBelow ? getTickSize() : 0) + dXAxisLabelsThickness,dAppliedXAxisPlotSpacing);
    }
    if (dH1 + dH2 <= dHTotal) {
      dY1-=dH1;
      dY2+=dH2;
      dHTotal-=(dH1 + dH2);
    }
 else {
      axPH.setShowLabels(false);
    }
    if (iXTitleLocation == ABOVE) {
      dY1-=dXAxisTitleThickness;
    }
 else     if (iXTitleLocation == BELOW) {
      dY2+=dXAxisTitleThickness;
    }
    if (dY1 < dBlockY) {
      final double dDelta=(dBlockY - dY1);
      dY1=dBlockY;
      dY+=dDelta;
      dY2+=dDelta;
    }
    double dDeltaY1=dY - dY1;
    double dDeltaY2=dY2 - dY;
    dXAxisLabelsThickness=0;
    if (iXLabelLocation == ABOVE) {
      dXAxisLabelsThickness=dY2 - dY1;
    }
 else     if (iXLabelLocation == BELOW) {
      dY2=(dY + dAppliedXAxisPlotSpacing);
      dXAxisLabelsThickness=dY2 - dY1;
    }
    if ((bForwardScale && dXAxisLabelsThickness > scY.getStartShift()) || (!bForwardScale && dXAxisLabelsThickness > scY.getEndShift())) {
      double dStart=scY.getStart(), dEnd=dY2 - scY.getEndShift();
      if (bForwardScale) {
        dStart=dY2 - scY.getStartShift();
        dEnd=scY.getEnd();
      }
      scY.resetShifts();
      scY.setEndPoints(dStart,dEnd);
      scY.computeTicks(ids,laYAxisLabels,iYLabelLocation,VERTICAL,dStart,dEnd,true,aax);
      if (!scY.isStepFixed()) {
        final Object[] oaMinMax=scY.getMinMax();
        while (!scY.checkFit(ids,laYAxisLabels,iYLabelLocation)) {
          if (!scY.zoomOut()) {
            break;
          }
          scY.updateAxisMinMax(oaMinMax[0],oaMinMax[1]);
          int tickCount=scY.computeTicks(ids,laYAxisLabels,iYLabelLocation,VERTICAL,dStart,dEnd,true,aax);
          if (scY.getUnit() != null && asInteger(scY.getUnit()) == Calendar.YEAR && tickCount <= 3 || isSharedScale()) {
            break;
          }
        }
      }
    }
    dY-=insCA.getTop();
    dY1=dY - dDeltaY1;
    dY2=dY + dDeltaY2;
    axPH.setTitleCoordinate((iXTitleLocation == ABOVE) ? dY1 - 1 : dY2 + 1 - dXAxisTitleThickness);
  }
 else   if ((bForwardScale && iv.iType == IConstants.MAX) || (!bForwardScale && iv.iType == IConstants.MIN)) {
    dY+=dAppliedXAxisPlotSpacing;
    dHTotal-=dAppliedXAxisPlotSpacing;
    dY1=dY;
    dY2=dY;
    double dTickSize=getTickSize();
    if (bTicksBelow && dTickSize < dHTotal) {
      dY2+=dTickSize;
      dHTotal-=dTickSize;
    }
 else {
      dTickSize=0;
    }
    if (iXLabelLocation == ABOVE) {
      double dXLabelHeight=Math.max((bTicksAbove ? dTickSize : 0) + dXAxisLabelsThickness,dAppliedXAxisPlotSpacing);
      if (dXLabelHeight + dDecorationThickness[1] < dHTotal) {
        dY1-=dXLabelHeight;
        dY2+=dDecorationThickness[1];
        dHTotal-=(dXLabelHeight + dDecorationThickness[1]);
      }
 else {
        dXLabelHeight=0;
        axPH.setShowLabels(false);
      }
    }
 else     if (iXLabelLocation == BELOW) {
      double dXLabelHeight=Math.max(dXAxisLabelsThickness,dDecorationThickness[1]);
      double dHt1=Math.max(bTicksAbove ? dTickSize : 0,dAppliedXAxisPlotSpacing);
      if (dXLabelHeight + dHt1 <= dHTotal) {
        dY2+=dXLabelHeight;
        dY1-=dHt1;
        dHTotal-=(dXLabelHeight + dHt1);
      }
 else {
        dXLabelHeight=0;
        axPH.setShowLabels(false);
      }
    }
    if (iXTitleLocation == ABOVE) {
      dY1-=dXAxisTitleThickness;
    }
 else     if (iXTitleLocation == BELOW) {
      dY2+=dXAxisTitleThickness;
    }
    if (dY2 > dBlockY + dBlockHeight) {
      final double dDelta=(dY2 - (dBlockY + dBlockHeight));
      dY2=dBlockY + dBlockHeight;
      dY-=dDelta;
      dY1-=dDelta;
    }
    double dDeltaY1=dY - dY1;
    double dDeltaY2=dY2 - dY;
    dXAxisLabelsThickness=0;
    if (iXLabelLocation == ABOVE) {
      dY1=(dY - dAppliedXAxisPlotSpacing);
      dXAxisLabelsThickness=dY2 - dY1;
    }
 else     if (iXLabelLocation == BELOW) {
      dXAxisLabelsThickness=dY2 - dY1;
    }
    if ((bForwardScale && dXAxisLabelsThickness > scY.getEndShift()) || (!bForwardScale && dXAxisLabelsThickness > scY.getStartShift())) {
      double dStart=dY1 + scY.getStartShift(), dEnd=scY.getEnd();
      if (bForwardScale) {
        dStart=scY.getStart();
        dEnd=dY1 + scY.getEndShift();
      }
      scY.resetShifts();
      if (dStart < dEnd + 1) {
        dStart=dEnd + 1;
      }
      scY.setEndPoints(dStart,dEnd);
      scY.computeTicks(ids,laYAxisLabels,iYLabelLocation,VERTICAL,dStart,dEnd,true,aax);
      if (!scY.isStepFixed()) {
        final Object[] oaMinMax=scY.getMinMax();
        while (!scY.checkFit(ids,laYAxisLabels,iYLabelLocation)) {
          if (!scY.zoomOut()) {
            break;
          }
          double dOldStep=((Number)scY.getStep()).doubleValue();
          scY.updateAxisMinMax(oaMinMax[0],oaMinMax[1]);
          int tickCount=scY.computeTicks(ids,laYAxisLabels,iYLabelLocation,VERTICAL,dStart,dEnd,true,aax);
          double dNewStep=((Number)scY.getStep()).doubleValue();
          if (dNewStep < dOldStep) {
            break;
          }
          if (scY.getUnit() != null && asInteger(scY.getUnit()) == Calendar.YEAR && tickCount <= 3 || isSharedScale()) {
            break;
          }
        }
      }
    }
    dY+=insCA.getBottom();
    dY1=dY - dDeltaY1;
    dY2=dY + dDeltaY2;
    axPH.setTitleCoordinate((iXTitleLocation == ABOVE) ? dY1 - 1 : dY2 + 1 - dXAxisTitleThickness);
  }
 else {
    double dDeltaY1=0, dDeltaY2=0;
    if (iXLabelLocation == ABOVE) {
      double dH1=(bTicksAbove ? getTickSize() : 0) + Math.max(dXAxisLabelsThickness,dDecorationThickness[0]);
      double dH2=(bTicksBelow ? getTickSize() : 0);
      if (dH1 + dH2 <= dHTotal) {
        dY1-=dH1;
        dY2+=dH2;
        dHTotal-=(dH1 + dH2);
      }
 else {
        axPH.setShowLabels(false);
      }
      if (iXTitleLocation == ABOVE) {
        dY1-=dXAxisTitleThickness;
      }
 else       if (iXTitleLocation == BELOW) {
        dY2+=dXAxisTitleThickness;
      }
      dDeltaY1=dY - dY1;
      dDeltaY2=dY2 - dY;
      if (dY1 < dBlockY) {
        final Object[] oaMinMax=scY.getMinMax();
        boolean bForceBreak=false;
        do {
          scY.setEndPoints(scY.getStart() + scY.getStartShift(),scY.getEnd() - scY.getEndShift());
          scY.resetShifts();
          double[] da=scY.getEndPoints();
          double dT_RI=dBlockY - dY1;
          double dStart, dEnd;
          if (bForwardScale) {
            double dAMin_AMax=da[1] - da[0];
            double dAMin_RI=da[1] - dY;
            dEnd=da[1];
            dStart=(dT_RI / dAMin_RI) * dAMin_AMax + da[0];
            if (dStart < dBlockY) {
              dStart=dBlockY;
              bForceBreak=true;
            }
          }
 else {
            double dAMin_AMax=da[0] - da[1];
            double dAMin_RI=da[0] - dY;
            dStart=da[0];
            dEnd=(dT_RI / dAMin_RI) * dAMin_AMax + da[1];
            if (dEnd < dBlockY) {
              dEnd=dBlockY;
              bForceBreak=true;
            }
          }
          scY.setEndPoints(dStart,dEnd);
          scY.computeTicks(ids,laYAxisLabels,iYLabelLocation,VERTICAL,dStart,dEnd,true,aax);
          if (!scY.isStepFixed()) {
            while (!scY.checkFit(ids,laYAxisLabels,iYLabelLocation)) {
              if (!scY.zoomOut()) {
                bForceBreak=true;
                break;
              }
              scY.updateAxisMinMax(oaMinMax[0],oaMinMax[1]);
              int tickCount=scY.computeTicks(ids,laYAxisLabels,iYLabelLocation,VERTICAL,dStart,dEnd,true,aax);
              if (scY.getUnit() != null && asInteger(scY.getUnit()) == Calendar.YEAR && tickCount <= 3 || isSharedScale()) {
                bForceBreak=true;
                break;
              }
            }
          }
          dY=getLocation(scY,iv);
          dY1=dY - dDeltaY1;
          dY2=dY + dDeltaY2;
        }
 while (Math.abs(dY1 - dBlockY) > 1 && !bForceBreak);
      }
    }
 else     if (iXLabelLocation == BELOW) {
      double dH1=(bTicksAbove ? getTickSize() : 0);
      double dH2=(bTicksBelow ? getTickSize() : 0) + Math.max(dXAxisLabelsThickness,dDecorationThickness[1]);
      if (dH1 + dH2 <= dHTotal) {
        dY1-=dH1;
        dY2+=dH2;
        dHTotal-=(dH1 + dH2);
      }
      if (iXTitleLocation == ABOVE) {
        dY1-=dXAxisTitleThickness;
      }
 else       if (iXTitleLocation == BELOW) {
        dY2+=dXAxisTitleThickness;
      }
      dDeltaY1=dY - dY1;
      dDeltaY2=dY2 - dY;
      if (dY2 > dBlockY + dBlockHeight) {
        final Object[] oaMinMax=scY.getMinMax();
        boolean bForceBreak=false;
        do {
          scY.setEndPoints(scY.getStart() + scY.getStartShift(),scY.getEnd() - scY.getEndShift());
          scY.resetShifts();
          double[] da=scY.getEndPoints();
          double dX2_X1=dY2 - (dBlockY + dBlockHeight);
          double dStart, dEnd;
          if (bForwardScale) {
            double dAMin_AMax=da[1] - da[0];
            double dX2_AMax=dY - da[0];
            dEnd=da[1] - (dX2_X1 / dX2_AMax) * dAMin_AMax;
            dStart=da[0];
            if (dEnd > dBlockY + dBlockHeight) {
              dEnd=dBlockY + dBlockHeight;
              bForceBreak=true;
            }
          }
 else {
            double dAMin_AMax=da[0] - da[1];
            double dX2_AMax=dY - da[1];
            dStart=da[0] - (dX2_X1 / dX2_AMax) * dAMin_AMax;
            dEnd=da[1];
            if (dStart > dBlockY + dBlockHeight) {
              dStart=dBlockY + dBlockHeight;
              bForceBreak=true;
            }
          }
          if (ChartUtil.mathEqual(Math.abs(dEnd - dStart),0)) {
            bForceBreak=true;
          }
          scY.setEndPoints(dStart,dEnd);
          scY.computeTicks(ids,laYAxisLabels,iYLabelLocation,VERTICAL,dStart,dEnd,true,aax);
          if (!scY.isStepFixed()) {
            while (!scY.checkFit(ids,laYAxisLabels,iYLabelLocation)) {
              if (!scY.zoomOut()) {
                bForceBreak=true;
                break;
              }
              scY.updateAxisMinMax(oaMinMax[0],oaMinMax[1]);
              int tickCount=scY.computeTicks(ids,laYAxisLabels,iYLabelLocation,VERTICAL,dStart,dEnd,true,aax);
              if (scY.getUnit() != null && asInteger(scY.getUnit()) == Calendar.YEAR && tickCount <= 3 || isSharedScale()) {
                bForceBreak=true;
                break;
              }
            }
          }
          dY=getLocation(scY,iv);
          dY2=dY + dDeltaY2;
          dY1=dY - dDeltaY1;
        }
 while (Math.abs(dY2 - (dBlockY + dBlockHeight)) > 1 && !bForceBreak);
      }
    }
    axPH.setTitleCoordinate((iXTitleLocation == ABOVE) ? dY1 - 1 : dY2 + 1 - dXAxisTitleThickness);
  }
  return dY;
}

Fixed version (ground truth):
/** 
 * @param dBlockY
 * @param dBlockHeight
 * @param aax
 * @return
 */
protected final double adjustVerticalDueToHorizontal(double dBlockY,double dBlockHeight,AllAxes aax) throws ChartException, IllegalArgumentException {
  final OneAxis axPH=aax.areAxesSwapped() ? aax.getPrimaryOrthogonal() : aax.getPrimaryBase();
  final OneAxis axPV=aax.areAxesSwapped() ? aax.getPrimaryBase() : aax.getPrimaryOrthogonal();
  final AutoScale scX=axPH.getScale();
  final AutoScale scY=axPV.getScale();
  final int iXLabelLocation=axPH.getLabelPosition();
  final int iYLabelLocation=axPV.getLabelPosition();
  final int iXTitleLocation=axPH.getTitlePosition();
  final Label laXAxisTitle=axPH.getTitle();
  final Label laYAxisLabels=axPV.getLabel();
  final int iXTickStyle=axPH.getCombinedTickStyle();
  final IntersectionValue iv=axPH.getIntersectionValue();
  double dXAxisLabelsThickness=scX.computeAxisLabelThickness(ids,axPH.getLabel(),HORIZONTAL);
  double[] dDecorationThickness={0,0};
  Series[] sea=cwa.getSeries(IConstants.ORTHOGONAL);
  Map<Series,LegendItemRenderingHints> seriesRenderingHints=rtc.getSeriesRenderers();
  for (int i=0; i < sea.length; i++) {
    LegendItemRenderingHints lirh=seriesRenderingHints.get(sea[i]);
    if (lirh != null && lirh.getRenderer() instanceof AxesRenderer) {
      IAxesDecorator iad=((AxesRenderer)lirh.getRenderer()).getAxesDecorator(axPH);
      if (iad != null) {
        double[] thickness=iad.computeDecorationThickness(ids,axPH);
        if (thickness[0] > dDecorationThickness[0]) {
          dDecorationThickness[0]=thickness[0];
        }
        if (thickness[1] > dDecorationThickness[1]) {
          dDecorationThickness[1]=thickness[1];
        }
      }
    }
  }
  double dXAxisTitleThickness=0;
  if (laXAxisTitle.isVisible()) {
    final String sPreviousValue=laXAxisTitle.getCaption().getValue();
    laXAxisTitle.getCaption().setValue(rtc.externalizedMessage(sPreviousValue));
    double maxWidth=Math.abs(scX.getEnd() - scX.getStart());
    double maxHeight=AXIS_TITLE_PERCENT * boPlot.getHeight();
    LabelLimiter lblLimit=new LabelLimiter(maxWidth,maxHeight,0);
    lblLimit.computeWrapping(ids,laXAxisTitle);
    lblLimit=lblLimit.limitLabelSize(ids,laXAxisTitle,EnumSet.of(LabelLimiter.Option.FIX_WIDTH));
    putLabelLimiter(axPH.getModelAxis().getTitle(),lblLimit);
    dXAxisTitleThickness=lblLimit.getMaxHeight();
    laXAxisTitle.getCaption().setValue(sPreviousValue);
  }
  double dHTotal=Math.abs(scY.getStart() - scY.getEnd());
  if (axPH.getModelAxis().isSetLabelSpan()) {
    double dFixedLabelThickness=axPH.getModelAxis().getLabelSpan() * dPointToPixel;
    if (dFixedLabelThickness < dHTotal - 2 * getTickSize()) {
      if (dXAxisTitleThickness + dXAxisLabelsThickness > dFixedLabelThickness) {
        axPH.setShowLabels(false);
      }
      if (dXAxisTitleThickness > dFixedLabelThickness) {
        laXAxisTitle.setVisible(false);
        dXAxisLabelsThickness=0;
      }
      dXAxisLabelsThickness=dFixedLabelThickness;
    }
  }
  double dY=getLocation(scY,iv), dY1=dY, dY2=dY;
  final boolean bTicksAbove=(iXTickStyle & TICK_ABOVE) == TICK_ABOVE;
  final boolean bTicksBelow=(iXTickStyle & TICK_BELOW) == TICK_BELOW;
  final double dAppliedXAxisPlotSpacing=(iv.iType == IConstants.MAX || iv.iType == IConstants.MIN) ? dXAxisPlotSpacing : 0;
  final boolean bForwardScale=scY.getDirection() == FORWARD;
  if ((bForwardScale && iv.iType == IConstants.MIN) || (!bForwardScale && iv.iType == IConstants.MAX)) {
    dY-=dAppliedXAxisPlotSpacing;
    dHTotal-=dAppliedXAxisPlotSpacing;
    dY1=dY;
    dY2=dY;
    double dTickSize=getTickSize();
    if (bTicksAbove && dTickSize <= dHTotal) {
      dY1-=dTickSize;
      dHTotal-=dTickSize;
    }
 else {
      dTickSize=0;
    }
    double dH1=0;
    double dH2=0;
    if (iXLabelLocation == ABOVE) {
      dH1=Math.max(dXAxisLabelsThickness,dDecorationThickness[0]);
      dH2=Math.max(bTicksBelow ? getTickSize() : 0,dAppliedXAxisPlotSpacing);
    }
 else     if (iXLabelLocation == BELOW) {
      dH1=dDecorationThickness[0];
      dH2+=Math.max((bTicksBelow ? getTickSize() : 0) + dXAxisLabelsThickness,dAppliedXAxisPlotSpacing);
    }
    if (dH1 + dH2 <= dHTotal) {
      dY1-=dH1;
      dY2+=dH2;
      dHTotal-=(dH1 + dH2);
    }
 else {
      axPH.setShowLabels(false);
    }
    if (iXTitleLocation == ABOVE) {
      dY1-=dXAxisTitleThickness;
    }
 else     if (iXTitleLocation == BELOW) {
      dY2+=dXAxisTitleThickness;
    }
    if (dY1 < dBlockY) {
      final double dDelta=(dBlockY - dY1);
      dY1=dBlockY;
      dY+=dDelta;
      dY2+=dDelta;
    }
    double dDeltaY1=dY - dY1;
    double dDeltaY2=dY2 - dY;
    dXAxisLabelsThickness=0;
    if (iXLabelLocation == ABOVE) {
      dXAxisLabelsThickness=dY2 - dY1;
    }
 else     if (iXLabelLocation == BELOW) {
      dY2=(dY + dAppliedXAxisPlotSpacing);
      dXAxisLabelsThickness=dY2 - dY1;
    }
    if ((bForwardScale && dXAxisLabelsThickness > scY.getStartShift()) || (!bForwardScale && dXAxisLabelsThickness > scY.getEndShift())) {
      double dStart=scY.getStart(), dEnd=dY2 - scY.getEndShift();
      if (bForwardScale) {
        dStart=dY2 - scY.getStartShift();
        dEnd=scY.getEnd();
      }
      scY.resetShifts();
      scY.setEndPoints(dStart,dEnd);
      scY.computeTicks(ids,laYAxisLabels,iYLabelLocation,VERTICAL,dStart,dEnd,true,aax);
      if (!scY.isStepFixed()) {
        final Object[] oaMinMax=scY.getMinMax();
        while (!scY.checkFit(ids,laYAxisLabels,iYLabelLocation)) {
          if (!scY.zoomOut()) {
            break;
          }
          scY.updateAxisMinMax(oaMinMax[0],oaMinMax[1]);
          int tickCount=scY.computeTicks(ids,laYAxisLabels,iYLabelLocation,VERTICAL,dStart,dEnd,true,aax);
          if (scY.getUnit() != null && asInteger(scY.getUnit()) == Calendar.YEAR && tickCount <= 3 || isSharedScale()) {
            break;
          }
        }
      }
    }
    dY-=insCA.getTop();
    dY1=dY - dDeltaY1;
    dY2=dY + dDeltaY2;
    axPH.setTitleCoordinate((iXTitleLocation == ABOVE) ? dY1 - 1 : dY2 + 1 - dXAxisTitleThickness);
  }
 else   if ((bForwardScale && iv.iType == IConstants.MAX) || (!bForwardScale && iv.iType == IConstants.MIN)) {
    dY+=dAppliedXAxisPlotSpacing;
    dHTotal-=dAppliedXAxisPlotSpacing;
    dY1=dY;
    dY2=dY;
    double dTickSize=getTickSize();
    if (bTicksBelow && dTickSize < dHTotal) {
      dY2+=dTickSize;
      dHTotal-=dTickSize;
    }
 else {
      dTickSize=0;
    }
    if (iXLabelLocation == ABOVE) {
      double dXLabelHeight=Math.max((bTicksAbove ? dTickSize : 0) + dXAxisLabelsThickness,dAppliedXAxisPlotSpacing);
      if (dXLabelHeight + dDecorationThickness[1] < dHTotal) {
        dY1-=dXLabelHeight;
        dY2+=dDecorationThickness[1];
        dHTotal-=(dXLabelHeight + dDecorationThickness[1]);
      }
 else {
        dXLabelHeight=0;
        axPH.setShowLabels(false);
      }
    }
 else     if (iXLabelLocation == BELOW) {
      double dXLabelHeight=Math.max(dXAxisLabelsThickness,dDecorationThickness[1]);
      double dHt1=Math.max(bTicksAbove ? dTickSize : 0,dAppliedXAxisPlotSpacing);
      if (dXLabelHeight + dHt1 <= dHTotal) {
        dY2+=dXLabelHeight;
        dY1-=dHt1;
        dHTotal-=(dXLabelHeight + dHt1);
      }
 else {
        dXLabelHeight=0;
        axPH.setShowLabels(false);
      }
    }
    if (iXTitleLocation == ABOVE) {
      dY1-=dXAxisTitleThickness;
    }
 else     if (iXTitleLocation == BELOW) {
      dY2+=dXAxisTitleThickness;
    }
    if (dY2 > dBlockY + dBlockHeight) {
      final double dDelta=(dY2 - (dBlockY + dBlockHeight));
      dY2=dBlockY + dBlockHeight;
      dY-=dDelta;
      dY1-=dDelta;
    }
    double dDeltaY1=dY - dY1;
    double dDeltaY2=dY2 - dY;
    dXAxisLabelsThickness=0;
    if (iXLabelLocation == ABOVE) {
      dY1=(dY - dAppliedXAxisPlotSpacing);
      dXAxisLabelsThickness=dY2 - dY1;
    }
 else     if (iXLabelLocation == BELOW) {
      dXAxisLabelsThickness=dY2 - dY1;
    }
    if ((bForwardScale && dXAxisLabelsThickness > scY.getEndShift()) || (!bForwardScale && dXAxisLabelsThickness > scY.getStartShift())) {
      double dStart=dY1 + scY.getStartShift(), dEnd=scY.getEnd();
      if (bForwardScale) {
        dStart=scY.getStart();
        dEnd=dY1 + scY.getEndShift();
      }
      scY.resetShifts();
      if (dStart < dEnd + 1) {
        dStart=dEnd + 1;
      }
      scY.setEndPoints(dStart,dEnd);
      scY.computeTicks(ids,laYAxisLabels,iYLabelLocation,VERTICAL,dStart,dEnd,true,aax);
      if (!scY.isStepFixed()) {
        final Object[] oaMinMax=scY.getMinMax();
        while (!scY.checkFit(ids,laYAxisLabels,iYLabelLocation)) {
          if (!scY.zoomOut()) {
            break;
          }
          double dOldStep=((Number)scY.getStep()).doubleValue();
          scY.updateAxisMinMax(oaMinMax[0],oaMinMax[1]);
          int tickCount=scY.computeTicks(ids,laYAxisLabels,iYLabelLocation,VERTICAL,dStart,dEnd,true,aax);
          double dNewStep=((Number)scY.getStep()).doubleValue();
          if (dNewStep < dOldStep) {
            break;
          }
          if (scY.getUnit() != null && asInteger(scY.getUnit()) == Calendar.YEAR && tickCount <= 3 || isSharedScale()) {
            break;
          }
        }
      }
    }
    dY+=insCA.getBottom();
    dY1=dY - dDeltaY1;
    dY2=dY + dDeltaY2;
    axPH.setTitleCoordinate((iXTitleLocation == ABOVE) ? dY1 - 1 : dY2 + 1 - dXAxisTitleThickness);
  }
 else {
    double dDeltaY1=0, dDeltaY2=0;
    if (iXLabelLocation == ABOVE) {
      double dH1=(bTicksAbove ? getTickSize() : 0) + Math.max(dXAxisLabelsThickness,dDecorationThickness[0]);
      double dH2=(bTicksBelow ? getTickSize() : 0);
      if (dH1 + dH2 <= dHTotal) {
        dY1-=dH1;
        dY2+=dH2;
        dHTotal-=(dH1 + dH2);
      }
 else {
        axPH.setShowLabels(false);
      }
      if (iXTitleLocation == ABOVE) {
        dY1-=dXAxisTitleThickness;
      }
 else       if (iXTitleLocation == BELOW) {
        dY2+=dXAxisTitleThickness;
      }
      dDeltaY1=dY - dY1;
      dDeltaY2=dY2 - dY;
      if (dY1 < dBlockY) {
        final Object[] oaMinMax=scY.getMinMax();
        boolean bForceBreak=false;
        do {
          scY.setEndPoints(scY.getStart() + scY.getStartShift(),scY.getEnd() - scY.getEndShift());
          scY.resetShifts();
          double[] da=scY.getEndPoints();
          double dT_RI=dBlockY - dY1;
          double dStart, dEnd;
          if (bForwardScale) {
            double dAMin_AMax=da[1] - da[0];
            double dAMin_RI=da[1] - dY;
            dEnd=da[1];
            dStart=(dT_RI / dAMin_RI) * dAMin_AMax + da[0];
            if (dStart < dBlockY) {
              dStart=dBlockY;
              bForceBreak=true;
            }
          }
 else {
            double dAMin_AMax=da[0] - da[1];
            double dAMin_RI=da[0] - dY;
            dStart=da[0];
            dEnd=(dT_RI / dAMin_RI) * dAMin_AMax + da[1];
            if (dEnd < dBlockY) {
              dEnd=dBlockY;
              bForceBreak=true;
            }
          }
          scY.setEndPoints(dStart,dEnd);
          scY.computeTicks(ids,laYAxisLabels,iYLabelLocation,VERTICAL,dStart,dEnd,true,aax);
          if (!scY.isStepFixed()) {
            while (!scY.checkFit(ids,laYAxisLabels,iYLabelLocation)) {
              if (!scY.zoomOut()) {
                bForceBreak=true;
                break;
              }
              scY.updateAxisMinMax(oaMinMax[0],oaMinMax[1]);
              int tickCount=scY.computeTicks(ids,laYAxisLabels,iYLabelLocation,VERTICAL,dStart,dEnd,true,aax);
              if (scY.getUnit() != null && asInteger(scY.getUnit()) == Calendar.YEAR && tickCount <= 3 || isSharedScale()) {
                bForceBreak=true;
                break;
              }
            }
          }
          dY=getLocation(scY,iv);
          dY1=dY - dDeltaY1;
          dY2=dY + dDeltaY2;
        }
 while (Math.abs(dY1 - dBlockY) > 1 && !bForceBreak);
      }
    }
 else     if (iXLabelLocation == BELOW) {
      double dH1=(bTicksAbove ? getTickSize() : 0);
      double dH2=(bTicksBelow ? getTickSize() : 0) + Math.max(dXAxisLabelsThickness,dDecorationThickness[1]);
      if (dH1 + dH2 <= dHTotal) {
        dY1-=dH1;
        dY2+=dH2;
        dHTotal-=(dH1 + dH2);
      }
      if (iXTitleLocation == ABOVE) {
        dY1-=dXAxisTitleThickness;
      }
 else       if (iXTitleLocation == BELOW) {
        dY2+=dXAxisTitleThickness;
      }
      dDeltaY1=dY - dY1;
      dDeltaY2=dY2 - dY;
      if (dY2 > dBlockY + dBlockHeight) {
        final Object[] oaMinMax=scY.getMinMax();
        boolean bForceBreak=false;
        do {
          scY.setEndPoints(scY.getStart() + scY.getStartShift(),scY.getEnd() - scY.getEndShift());
          scY.resetShifts();
          double[] da=scY.getEndPoints();
          double dX2_X1=dY2 - (dBlockY + dBlockHeight);
          double dStart, dEnd;
          if (bForwardScale) {
            double dAMin_AMax=da[1] - da[0];
            double dX2_AMax=dY - da[0];
            dEnd=da[1] - (dX2_X1 / dX2_AMax) * dAMin_AMax;
            dStart=da[0];
            if (dEnd > dBlockY + dBlockHeight) {
              dEnd=dBlockY + dBlockHeight;
              bForceBreak=true;
            }
          }
 else {
            double dAMin_AMax=da[0] - da[1];
            double dX2_AMax=dY - da[1];
            dStart=da[0] - (dX2_X1 / dX2_AMax) * dAMin_AMax;
            dEnd=da[1];
            if (dStart > dBlockY + dBlockHeight) {
              dStart=dBlockY + dBlockHeight;
              bForceBreak=true;
            }
          }
          if (ChartUtil.mathEqual(Math.abs(dEnd - dStart),0)) {
            bForceBreak=true;
          }
          scY.setEndPoints(dStart,dEnd);
          scY.computeTicks(ids,laYAxisLabels,iYLabelLocation,VERTICAL,dStart,dEnd,true,aax);
          if (!scY.isStepFixed()) {
            while (!scY.checkFit(ids,laYAxisLabels,iYLabelLocation)) {
              if (!scY.zoomOut()) {
                bForceBreak=true;
                break;
              }
              scY.updateAxisMinMax(oaMinMax[0],oaMinMax[1]);
              int tickCount=scY.computeTicks(ids,laYAxisLabels,iYLabelLocation,VERTICAL,dStart,dEnd,true,aax);
              if (scY.getUnit() != null && asInteger(scY.getUnit()) == Calendar.YEAR && tickCount <= 3 || isSharedScale()) {
                bForceBreak=true;
                break;
              }
            }
          }
          dY=getLocation(scY,iv);
          dY2=dY + dDeltaY2;
          dY1=dY - dDeltaY1;
        }
 while (Math.abs(dY2 - (dBlockY + dBlockHeight)) > 1 && !bForceBreak);
      }
    }
    axPH.setTitleCoordinate((iXTitleLocation == ABOVE) ? dY1 - 1 : dY2 + 1 - dXAxisTitleThickness);
  }
  return dY;
}