Program: 75726
Project: 75726
Buggy source:
/** 
 * Computes the size of the legend. Note the computation relies on the title size, so the title block must be layouted first before this.
 * @param lg
 * @param sea
 * @throws GenerationException
 */
public final Size compute(IDisplayServer xs,Chart cm,SeriesDefinition[] seda,RunTimeContext rtc) throws ChartException {
  final Legend lg=cm.getLegend();
  LegendData legendData=new LegendData();
  if (!lg.isSetOrientation()) {
    throw new ChartException(ChartEnginePlugin.ID,ChartException.GENERATION,"String_Node_Str",Messages.getResourceBundle(xs.getULocale()));
  }
  if (!lg.isSetDirection()) {
    throw new ChartException(ChartEnginePlugin.ID,ChartException.GENERATION,"String_Node_Str",Messages.getResourceBundle(xs.getULocale()));
  }
  final Orientation orientation=lg.getOrientation();
  final Direction direction=lg.getDirection();
  final Position lgPosition=lg.getPosition();
  final boolean bPaletteByCategory=(lg.getItemType().getValue() == LegendItemType.CATEGORIES);
  Label la=LabelImpl.create();
  la.setCaption(TextImpl.copyInstance(lg.getText()));
  ClientArea ca=lg.getClientArea();
  LineAttributes lia=ca.getOutline();
  legendData.dSeparatorThickness=lia.getThickness();
  la.getCaption().setValue("String_Node_Str");
  final ITextMetrics itm=xs.getTextMetrics(la);
  legendData.dItemHeight=itm.getFullHeight();
  la.getCaption().setValue(ELLIPSIS_STRING);
  itm.reuse(la);
  legendData.dEllipsisWidth=itm.getFullWidth();
  legendData.dScale=xs.getDpiResolution() / 72d;
  legendData.insCa=ca.getInsets().scaledInstance(legendData.dScale);
  legendData.maxWrappingSize=lg.getWrappingSize() * legendData.dScale;
  legendData.dHorizontalSpacing=3 * legendData.dScale;
  legendData.dVerticalSpacing=3 * legendData.dScale;
  legendData.dSafeSpacing=3 * legendData.dScale;
  legendData.dHorizonalReservedSpace=legendData.insCa.getLeft() + legendData.insCa.getRight() + (3 * legendData.dItemHeight) / 2 + legendData.dHorizontalSpacing;
  legendData.dVerticalReservedSpace=legendData.insCa.getTop() + legendData.insCa.getBottom() + legendData.dVerticalSpacing;
  final Block bl=cm.getBlock();
  final Bounds boFull=bl.getBounds().scaledInstance(legendData.dScale);
  final Insets ins=bl.getInsets().scaledInstance(legendData.dScale);
  final Insets lgIns=lg.getInsets().scaledInstance(legendData.dScale);
  int titleWPos=0;
  int titleHPos=0;
  final TitleBlock titleBlock=cm.getTitle();
  final Bounds titleBounds=titleBlock.getBounds().scaledInstance(legendData.dScale);
  if (titleBlock.isVisible()) {
switch (titleBlock.getAnchor().getValue()) {
case Anchor.EAST:
case Anchor.WEST:
      titleWPos=1;
    break;
case Anchor.NORTH:
case Anchor.NORTH_EAST:
case Anchor.NORTH_WEST:
case Anchor.SOUTH:
case Anchor.SOUTH_EAST:
case Anchor.SOUTH_WEST:
  titleHPos=1;
break;
}
}
legendData.dAvailableWidth=boFull.getWidth() - ins.getLeft() - ins.getRight()- lgIns.getLeft()- lgIns.getRight()- titleBounds.getWidth() * titleWPos;
legendData.dAvailableHeight=boFull.getHeight() - ins.getTop() - ins.getBottom()- lgIns.getTop()- lgIns.getBottom()- titleBounds.getHeight() * titleHPos;
double dMaxLegendWidth=boFull.getWidth() / 3;
double dMaxLegendHeight=boFull.getHeight() / 3;
switch (lgPosition.getValue()) {
case Position.LEFT:
case Position.RIGHT:
case Position.OUTSIDE:
if (legendData.dAvailableWidth > dMaxLegendWidth) {
legendData.dAvailableWidth=dMaxLegendWidth;
}
break;
case Position.ABOVE:
case Position.BELOW:
if (legendData.dAvailableHeight > dMaxLegendHeight) {
legendData.dAvailableHeight=dMaxLegendHeight;
}
break;
}
boolean bMinSliceDefined=false;
if (cm instanceof ChartWithoutAxes) {
bMinSliceDefined=((ChartWithoutAxes)cm).isSetMinSlice();
legendData.sMinSliceLabel=((ChartWithoutAxes)cm).getMinSliceLabel();
if (legendData.sMinSliceLabel == null || legendData.sMinSliceLabel.length() == 0) {
legendData.sMinSliceLabel=IConstants.UNDEFINED_STRING;
}
 else {
legendData.sMinSliceLabel=rtc.externalizedMessage(legendData.sMinSliceLabel);
}
}
if (bMinSliceDefined && bPaletteByCategory && cm instanceof ChartWithoutAxes) {
calculateExtraLegend(cm,rtc,legendData);
}
Label lgTitle=lg.getTitle();
Size titleSize=null;
BoundingBox titleBounding=null;
int iTitlePos=-1;
if (lgTitle != null && lgTitle.isSetVisible() && lgTitle.isVisible()) {
lgTitle=LabelImpl.copyInstance(lgTitle);
final String sPreviousValue=lgTitle.getCaption().getValue();
lgTitle.getCaption().setValue(rtc.externalizedMessage(sPreviousValue));
try {
titleBounding=Methods.computeBox(xs,IConstants.ABOVE,lgTitle,0,0);
}
 catch (IllegalArgumentException uiex) {
throw new ChartException(ChartEnginePlugin.ID,ChartException.RENDERING,uiex);
}
iTitlePos=lg.getTitlePosition().getValue();
if (rtc.isRightToLeft()) {
if (iTitlePos == Position.LEFT) {
iTitlePos=Position.RIGHT;
}
 else if (iTitlePos == Position.RIGHT) {
iTitlePos=Position.LEFT;
}
}
double shadowness=3 * legendData.dScale;
switch (iTitlePos) {
case Position.ABOVE:
case Position.BELOW:
legendData.dAvailableHeight-=titleBounding.getHeight() + 2 * shadowness;
break;
case Position.LEFT:
case Position.RIGHT:
legendData.dAvailableWidth-=titleBounding.getWidth() + 2 * shadowness;
break;
}
titleSize=SizeImpl.create(titleBounding.getWidth() + 2 * shadowness,titleBounding.getHeight() + 2 * shadowness);
}
double[] size=null;
if (orientation.getValue() == Orientation.VERTICAL) {
if (bPaletteByCategory) {
size=computeVerticalByCategory(xs,cm,rtc,itm,la,legendData);
}
 else if (direction.getValue() == Direction.TOP_BOTTOM) {
size=computeVerticalByTopBottomValue(xs,cm,seda,rtc,itm,la,legendData);
}
 else if (direction.getValue() == Direction.LEFT_RIGHT) {
size=computeVerticalByLeftRightValue(xs,cm,seda,rtc,itm,la,legendData);
}
 else {
throw new ChartException(ChartEnginePlugin.ID,ChartException.GENERATION,"String_Node_Str",new Object[]{direction.getName()},Messages.getResourceBundle(xs.getULocale()));
}
}
 else if (orientation.getValue() == Orientation.HORIZONTAL) {
if (bPaletteByCategory) {
size=computeHorizalByCategory(xs,cm,rtc,itm,la,legendData);
}
 else if (direction.getValue() == Direction.TOP_BOTTOM) {
size=computeHorizalByTopBottomValue(xs,cm,seda,rtc,itm,la,legendData);
}
 else if (direction.getValue() == Direction.LEFT_RIGHT) {
size=computeHorizalByLeftRightValue(xs,cm,seda,rtc,itm,la,legendData);
}
 else {
throw new ChartException(ChartEnginePlugin.ID,ChartException.GENERATION,"String_Node_Str",new Object[]{direction},Messages.getResourceBundle(xs.getULocale()));
}
}
 else {
throw new ChartException(ChartEnginePlugin.ID,ChartException.GENERATION,"String_Node_Str",new Object[]{orientation},Messages.getResourceBundle(xs.getULocale()));
}
if (size == null) {
return SizeImpl.create(0,0);
}
double dWidth=size[0], dHeight=size[1];
if (iTitlePos != -1) {
double shadowness=3 * legendData.dScale;
switch (iTitlePos) {
case Position.ABOVE:
case Position.BELOW:
dHeight+=titleBounding.getHeight() + 2 * shadowness;
dWidth=Math.max(dWidth,titleBounding.getWidth() + 2 * shadowness);
break;
case Position.LEFT:
case Position.RIGHT:
dWidth+=titleBounding.getWidth() + 2 * shadowness;
dHeight=Math.max(dHeight,titleBounding.getHeight() + 2 * shadowness);
break;
}
}
itm.dispose();
if (rtc != null) {
List legendItems=legendData.legendItems;
LegendItemHints[] liha=(LegendItemHints[])legendItems.toArray(new LegendItemHints[legendItems.size()]);
if (liha.length > 1) {
boolean needInvert=false;
if (cm instanceof ChartWithAxes) {
needInvert=((ChartWithAxes)cm).isTransposed();
}
boolean isStack=true;
boolean hasOptionalGrouping=false;
exitStackCheck: for (int i=0; i < seda.length; i++) {
if (!hasOptionalGrouping && seda[i].getQuery() != null) {
String query=seda[i].getQuery().getDefinition();
if (query != null && query.trim().length() != 0) {
hasOptionalGrouping=true;
}
}
if (isStack) {
for (Iterator iter=seda[i].getSeries().iterator(); iter.hasNext(); ) {
Series series=(Series)iter.next();
if (!series.isStacked()) {
isStack=false;
if (hasOptionalGrouping) {
break exitStackCheck;
}
break;
}
}
}
}
if (!hasOptionalGrouping & isStack) {
needInvert=!needInvert;
}
if (needInvert) {
liha=invertLegendItems(liha);
}
}
LegendLayoutHints lilh=new LegendLayoutHints(SizeImpl.create(dWidth,dHeight),titleSize,legendData.bMinSliceApplied,legendData.sMinSliceLabel,liha);
rtc.setLegendLayoutHints(lilh);
}
sz=SizeImpl.create(dWidth,dHeight);
return sz;
}

Fixed version (ground truth):
/** 
 * Computes the size of the legend. Note the computation relies on the title size, so the title block must be layouted first before this.
 * @param lg
 * @param sea
 * @throws GenerationException
 */
public final Size compute(IDisplayServer xs,Chart cm,SeriesDefinition[] seda,RunTimeContext rtc) throws ChartException {
  final Legend lg=cm.getLegend();
  LegendData legendData=new LegendData();
  if (!lg.isSetOrientation()) {
    throw new ChartException(ChartEnginePlugin.ID,ChartException.GENERATION,"String_Node_Str",Messages.getResourceBundle(xs.getULocale()));
  }
  if (!lg.isSetDirection()) {
    throw new ChartException(ChartEnginePlugin.ID,ChartException.GENERATION,"String_Node_Str",Messages.getResourceBundle(xs.getULocale()));
  }
  final Orientation orientation=lg.getOrientation();
  final Direction direction=lg.getDirection();
  final Position lgPosition=lg.getPosition();
  final boolean bPaletteByCategory=(lg.getItemType().getValue() == LegendItemType.CATEGORIES);
  Label la=LabelImpl.create();
  la.setCaption(TextImpl.copyInstance(lg.getText()));
  ClientArea ca=lg.getClientArea();
  LineAttributes lia=ca.getOutline();
  legendData.dSeparatorThickness=lia.getThickness();
  la.getCaption().setValue("String_Node_Str");
  final ITextMetrics itm=xs.getTextMetrics(la);
  legendData.dItemHeight=itm.getFullHeight();
  la.getCaption().setValue(ELLIPSIS_STRING);
  itm.reuse(la);
  legendData.dEllipsisWidth=itm.getFullWidth();
  legendData.dScale=xs.getDpiResolution() / 72d;
  legendData.insCa=ca.getInsets().scaledInstance(legendData.dScale);
  legendData.maxWrappingSize=lg.getWrappingSize() * legendData.dScale;
  legendData.dHorizontalSpacing=3 * legendData.dScale;
  legendData.dVerticalSpacing=3 * legendData.dScale;
  legendData.dSafeSpacing=3 * legendData.dScale;
  legendData.dHorizonalReservedSpace=legendData.insCa.getLeft() + legendData.insCa.getRight() + (3 * legendData.dItemHeight) / 2 + legendData.dHorizontalSpacing;
  legendData.dVerticalReservedSpace=legendData.insCa.getTop() + legendData.insCa.getBottom() + legendData.dVerticalSpacing;
  final Block bl=cm.getBlock();
  final Bounds boFull=bl.getBounds().scaledInstance(legendData.dScale);
  final Insets ins=bl.getInsets().scaledInstance(legendData.dScale);
  final Insets lgIns=lg.getInsets().scaledInstance(legendData.dScale);
  int titleWPos=0;
  int titleHPos=0;
  final TitleBlock titleBlock=cm.getTitle();
  final Bounds titleBounds=titleBlock.getBounds().scaledInstance(legendData.dScale);
  if (titleBlock.isVisible()) {
switch (titleBlock.getAnchor().getValue()) {
case Anchor.EAST:
case Anchor.WEST:
      titleWPos=1;
    break;
case Anchor.NORTH:
case Anchor.NORTH_EAST:
case Anchor.NORTH_WEST:
case Anchor.SOUTH:
case Anchor.SOUTH_EAST:
case Anchor.SOUTH_WEST:
  titleHPos=1;
break;
}
}
legendData.dAvailableWidth=boFull.getWidth() - ins.getLeft() - ins.getRight()- lgIns.getLeft()- lgIns.getRight()- titleBounds.getWidth() * titleWPos;
legendData.dAvailableHeight=boFull.getHeight() - ins.getTop() - ins.getBottom()- lgIns.getTop()- lgIns.getBottom()- titleBounds.getHeight() * titleHPos;
double dMaxLegendWidth=boFull.getWidth() / 3;
double dMaxLegendHeight=boFull.getHeight() / 3;
switch (lgPosition.getValue()) {
case Position.LEFT:
case Position.RIGHT:
case Position.OUTSIDE:
if (legendData.dAvailableWidth > dMaxLegendWidth) {
legendData.dAvailableWidth=dMaxLegendWidth;
}
break;
case Position.ABOVE:
case Position.BELOW:
if (legendData.dAvailableHeight > dMaxLegendHeight) {
legendData.dAvailableHeight=dMaxLegendHeight;
}
break;
}
boolean bMinSliceDefined=false;
if (cm instanceof ChartWithoutAxes) {
bMinSliceDefined=((ChartWithoutAxes)cm).isSetMinSlice();
legendData.sMinSliceLabel=((ChartWithoutAxes)cm).getMinSliceLabel();
if (legendData.sMinSliceLabel == null || legendData.sMinSliceLabel.length() == 0) {
legendData.sMinSliceLabel=IConstants.UNDEFINED_STRING;
}
 else {
legendData.sMinSliceLabel=rtc.externalizedMessage(legendData.sMinSliceLabel);
}
}
if (bMinSliceDefined && bPaletteByCategory && cm instanceof ChartWithoutAxes) {
calculateExtraLegend(cm,rtc,legendData);
}
Label lgTitle=lg.getTitle();
Size titleSize=null;
BoundingBox titleBounding=null;
int iTitlePos=-1;
if (lgTitle != null && lgTitle.isSetVisible() && lgTitle.isVisible()) {
lgTitle=LabelImpl.copyInstance(lgTitle);
final String sPreviousValue=lgTitle.getCaption().getValue();
lgTitle.getCaption().setValue(rtc.externalizedMessage(sPreviousValue));
try {
titleBounding=Methods.computeBox(xs,IConstants.ABOVE,lgTitle,0,0);
}
 catch (IllegalArgumentException uiex) {
throw new ChartException(ChartEnginePlugin.ID,ChartException.RENDERING,uiex);
}
iTitlePos=lg.getTitlePosition().getValue();
if (rtc.isRightToLeft()) {
if (iTitlePos == Position.LEFT) {
iTitlePos=Position.RIGHT;
}
 else if (iTitlePos == Position.RIGHT) {
iTitlePos=Position.LEFT;
}
}
double shadowness=3 * legendData.dScale;
switch (iTitlePos) {
case Position.ABOVE:
case Position.BELOW:
legendData.dAvailableHeight-=titleBounding.getHeight() + 2 * shadowness;
break;
case Position.LEFT:
case Position.RIGHT:
legendData.dAvailableWidth-=titleBounding.getWidth() + 2 * shadowness;
break;
}
titleSize=SizeImpl.create(titleBounding.getWidth() + 2 * shadowness,titleBounding.getHeight() + 2 * shadowness);
}
double[] size=null;
if (orientation.getValue() == Orientation.VERTICAL) {
if (bPaletteByCategory) {
size=computeVerticalByCategory(xs,cm,rtc,itm,la,legendData);
}
 else if (direction.getValue() == Direction.TOP_BOTTOM) {
size=computeVerticalByTopBottomValue(xs,cm,seda,rtc,itm,la,legendData);
}
 else if (direction.getValue() == Direction.LEFT_RIGHT) {
size=computeVerticalByLeftRightValue(xs,cm,seda,rtc,itm,la,legendData);
}
 else {
throw new ChartException(ChartEnginePlugin.ID,ChartException.GENERATION,"String_Node_Str",new Object[]{direction.getName()},Messages.getResourceBundle(xs.getULocale()));
}
}
 else if (orientation.getValue() == Orientation.HORIZONTAL) {
if (bPaletteByCategory) {
size=computeHorizalByCategory(xs,cm,rtc,itm,la,legendData);
}
 else if (direction.getValue() == Direction.TOP_BOTTOM) {
size=computeHorizalByTopBottomValue(xs,cm,seda,rtc,itm,la,legendData);
}
 else if (direction.getValue() == Direction.LEFT_RIGHT) {
size=computeHorizalByLeftRightValue(xs,cm,seda,rtc,itm,la,legendData);
}
 else {
throw new ChartException(ChartEnginePlugin.ID,ChartException.GENERATION,"String_Node_Str",new Object[]{direction},Messages.getResourceBundle(xs.getULocale()));
}
}
 else {
throw new ChartException(ChartEnginePlugin.ID,ChartException.GENERATION,"String_Node_Str",new Object[]{orientation},Messages.getResourceBundle(xs.getULocale()));
}
if (size == null) {
return SizeImpl.create(0,0);
}
double dWidth=size[0], dHeight=size[1];
if (iTitlePos != -1) {
double shadowness=3 * legendData.dScale;
switch (iTitlePos) {
case Position.ABOVE:
case Position.BELOW:
dHeight+=titleBounding.getHeight() + 2 * shadowness;
dWidth=Math.max(dWidth,titleBounding.getWidth() + 2 * shadowness);
break;
case Position.LEFT:
case Position.RIGHT:
dWidth+=titleBounding.getWidth() + 2 * shadowness;
dHeight=Math.max(dHeight,titleBounding.getHeight() + 2 * shadowness);
break;
}
}
itm.dispose();
if (rtc != null) {
List legendItems=legendData.legendItems;
LegendItemHints[] liha=(LegendItemHints[])legendItems.toArray(new LegendItemHints[legendItems.size()]);
if (liha.length > 1) {
boolean needInvert=false;
if (cm instanceof ChartWithAxes) {
needInvert=((ChartWithAxes)cm).isTransposed();
}
boolean isStack=true;
for (int i=0; i < seda.length; i++) {
if (isStack) {
for (Iterator iter=seda[i].getSeries().iterator(); iter.hasNext(); ) {
Series series=(Series)iter.next();
if (!series.isStacked()) {
isStack=false;
break;
}
}
}
}
if (isStack) {
needInvert=!needInvert;
}
if (needInvert) {
liha=invertLegendItems(liha);
}
}
LegendLayoutHints lilh=new LegendLayoutHints(SizeImpl.create(dWidth,dHeight),titleSize,legendData.bMinSliceApplied,legendData.sMinSliceLabel,liha);
rtc.setLegendLayoutHints(lilh);
}
sz=SizeImpl.create(dWidth,dHeight);
return sz;
}