k++;
	public void renderLegend( IPrimitiveRenderer ipr, Legend lg, Map htRenderers )			throws ChartException	{		if ( !lg.isVisible( ) ) // CHECK VISIBILITY		{			return;		}		renderBlock( ipr, lg, StructureSource.createLegend( lg ) );		final IDisplayServer xs = getDevice( ).getDisplayServer( );		final double dScale = xs.getDpiResolution( ) / 72d;		Bounds bo = lg.getBounds( ).scaledInstance( dScale );		Size sz = null;		double dX, dY;		if ( lg.getPosition( ) != Position.INSIDE_LITERAL )		{			try			{				sz = lg.getPreferredSize( xs, cm, rtc );			}			catch ( Exception ex )			{				throw new ChartException( ChartEnginePlugin.ID,						ChartException.RENDERING,						ex );			}			sz.scale( dScale );			// USE ANCHOR IN POSITIONING THE LEGEND CLIENT AREA WITHIN THE BLOCK			// SLACK SPACE			dX = bo.getLeft( ) + ( bo.getWidth( ) - sz.getWidth( ) ) / 2;			dY = 0;			if ( lg.isSetAnchor( ) )			{				int iAnchor = lg.getAnchor( ).getValue( );				// swap west/east				if ( isRightToLeft( ) )				{					if ( iAnchor == Anchor.EAST )					{						iAnchor = Anchor.WEST;					}					else if ( iAnchor == Anchor.NORTH_EAST )					{						iAnchor = Anchor.NORTH_WEST;					}					else if ( iAnchor == Anchor.SOUTH_EAST )					{						iAnchor = Anchor.SOUTH_WEST;					}					else if ( iAnchor == Anchor.WEST )					{						iAnchor = Anchor.EAST;					}					else if ( iAnchor == Anchor.NORTH_WEST )					{						iAnchor = Anchor.NORTH_EAST;					}					else if ( iAnchor == Anchor.SOUTH_WEST )					{						iAnchor = Anchor.SOUTH_EAST;					}				}				switch ( iAnchor )				{					case Anchor.NORTH :					case Anchor.NORTH_EAST :					case Anchor.NORTH_WEST :						dY = bo.getTop( );						break;					case Anchor.SOUTH :					case Anchor.SOUTH_EAST :					case Anchor.SOUTH_WEST :						dY = bo.getTop( ) + bo.getHeight( ) - sz.getHeight( );						break;					default : // CENTERED						dY = bo.getTop( )								+ ( bo.getHeight( ) - sz.getHeight( ) )								/ 2;						break;				}				switch ( iAnchor )				{					case Anchor.WEST :					case Anchor.NORTH_WEST :						dX = bo.getLeft( );						break;					case Anchor.EAST :					case Anchor.SOUTH_EAST :						dX = bo.getLeft( ) + bo.getWidth( ) - sz.getWidth( );						break;					default : // CENTERED						dX = bo.getLeft( )								+ ( bo.getWidth( ) - sz.getWidth( ) )								/ 2;						break;				}			}			else			{				dX = bo.getLeft( ) + ( bo.getWidth( ) - sz.getWidth( ) ) / 2;				dY = bo.getTop( ) + ( bo.getHeight( ) - sz.getHeight( ) ) / 2;			}		}		else		{			// USE PREVIOUSLY COMPUTED POSITION IN THE GENERATOR FOR LEGEND			// 'INSIDE' PLOT			dX = bo.getLeft( );			dY = bo.getTop( );			sz = SizeImpl.create( bo.getWidth( ), bo.getHeight( ) );		}		// get cached legend info.		final LegendLayoutHints lilh = rtc.getLegendLayoutHints( );		// consider legend title size.		Label lgTitle = lg.getTitle( );		double lgTitleWidth = 0, lgTitleHeight = 0;		double yOffset = 0, xOffset = 0, wOffset = 0, hOffset = 0;		final boolean bRenderLegendTitle = lgTitle != null				&& lgTitle.isSetVisible( )				&& lgTitle.isVisible( );		int iTitlePos = Position.ABOVE;		if ( bRenderLegendTitle )		{			lgTitle = LabelImpl.copyInstance( lgTitle );			if ( lilh != null )			{				// use cached value				Size titleSize = lilh.getTitleSize( );				lgTitleWidth = titleSize.getWidth( );				lgTitleHeight = titleSize.getHeight( );			}			else			{				// handle external resource string				final String sPreviousValue = lgTitle.getCaption( ).getValue( );				lgTitle.getCaption( )						.setValue( rtc.externalizedMessage( sPreviousValue ) );				BoundingBox bb = null;				try				{					bb = Methods.computeBox( xs,							IConstants.ABOVE,							lgTitle,							0,							0 );				}				catch ( IllegalArgumentException uiex )				{					throw new ChartException( ChartEnginePlugin.ID,							ChartException.RENDERING,							uiex );				}				lgTitleWidth = bb.getWidth( );				lgTitleHeight = bb.getHeight( );			}			iTitlePos = lg.getTitlePosition( ).getValue( );			// swap left/right			if ( isRightToLeft( ) )			{				if ( iTitlePos == Position.LEFT )				{					iTitlePos = Position.RIGHT;				}				else if ( iTitlePos == Position.RIGHT )				{					iTitlePos = Position.LEFT;				}			}			switch ( iTitlePos )			{				case Position.ABOVE :					yOffset = lgTitleHeight;					hOffset = -yOffset;					break;				case Position.BELOW :					hOffset = -lgTitleHeight;					break;				case Position.LEFT :					xOffset = lgTitleWidth;					wOffset = -xOffset;					break;				case Position.RIGHT :					wOffset = -lgTitleWidth;					break;			}		}		// RENDER THE LEGEND CLIENT AREA		final ClientArea ca = lg.getClientArea( );		final Insets lgIns = lg.getInsets( ).scaledInstance( dScale );		LineAttributes lia = ca.getOutline( );		bo = BoundsImpl.create( dX, dY, sz.getWidth( ), sz.getHeight( ) );		bo = bo.adjustedInstance( lgIns );		dX = bo.getLeft( );		dY = bo.getTop( );		// Adjust bounds.		bo.delta( xOffset, yOffset, wOffset, hOffset );		dX = bo.getLeft( );		dY = bo.getTop( );		final double dBaseX = dX;		final double dBaseY = dY;		final RectangleRenderEvent rre = (RectangleRenderEvent) ( (EventObjectCache) ir ).getEventObject( StructureSource.createLegend( lg ),				RectangleRenderEvent.class );		// render client area shadow.		if ( ca.getShadowColor( ) != null )		{			rre.setBounds( bo.translateInstance( 3, 3 ) );			rre.setBackground( ca.getShadowColor( ) );			ipr.fillRectangle( rre );		}		// render client area		rre.setBounds( bo );		rre.setOutline( lia );		rre.setBackground( ca.getBackground( ) );		ipr.fillRectangle( rre );		ipr.drawRectangle( rre );		lia = LineAttributesImpl.copyInstance( lia );		lia.setVisible( true ); // SEPARATOR LINES MUST BE VISIBLE		LineAttributes liSep = lg.getSeparator( ) == null ? lia				: lg.getSeparator( );		final SeriesDefinition[] seda = cm.getSeriesForLegend( );		// INITIALIZATION OF VARS USED IN FOLLOWING LOOPS		final Orientation o = lg.getOrientation( );		final Direction d = lg.getDirection( );		final Label la = LabelImpl.create( );		la.setCaption( TextImpl.copyInstance( lg.getText( ) ) );		la.getCaption( ).setValue( "X" ); //$NON-NLS-1$		final ITextMetrics itm = xs.getTextMetrics( la );		final double maxWrappingSize = lg.getWrappingSize( );		final double dItemHeight = itm.getFullHeight( );		final double dHorizontalSpacing = 4;		final double dVerticalSpacing = 4;		double dSeparatorThickness = lia.getThickness( );		Insets insCA = ca.getInsets( ).scaledInstance( dScale );		Series seBase;		ArrayList al;		LegendItemRenderingHints lirh;		Palette pa;		int iPaletteCount;		EList elPaletteEntries;		Fill fPaletteEntry;		final boolean bPaletteByCategory = ( cm.getLegend( )				.getItemType( )				.getValue( ) == LegendItemType.CATEGORIES );		// Get available maximum block width/height.		Block bl = cm.getBlock( );		Bounds boFull = bl.getBounds( ).scaledInstance( dScale );		Insets ins = bl.getInsets( ).scaledInstance( dScale );		double dMaxX = boFull.getLeft( )				+ boFull.getWidth( )				- ins.getRight( )				- lgIns.getRight( );		double dMaxY = boFull.getTop( )				+ boFull.getHeight( )				- ins.getBottom( )				- lgIns.getBottom( );		// Calculate if minSlice applicable.		String sMinSliceLabel = null;		boolean bMinSliceApplied = false;		if ( lilh != null )		{			// use cached value.			sMinSliceLabel = lilh.getMinSliceText( );			bMinSliceApplied = lilh.isMinSliceApplied( );		}		else		{			boolean bMinSliceDefined = false;			double dMinSlice = 0;			boolean bPercentageMinSlice = false;			if ( cm instanceof ChartWithoutAxes )			{				bMinSliceDefined = ( (ChartWithoutAxes) cm ).isSetMinSlice( );				dMinSlice = ( (ChartWithoutAxes) cm ).getMinSlice( );				bPercentageMinSlice = ( (ChartWithoutAxes) cm ).isMinSlicePercent( );				sMinSliceLabel = ( (ChartWithoutAxes) cm ).getMinSliceLabel( );				if ( sMinSliceLabel == null || sMinSliceLabel.length( ) == 0 )				{					sMinSliceLabel = IConstants.UNDEFINED_STRING;				}				else				{					sMinSliceLabel = rtc.externalizedMessage( sMinSliceLabel );				}			}			// calculate if need an extra legend item when minSlice defined.			if ( bMinSliceDefined					&& bPaletteByCategory					&& cm instanceof ChartWithoutAxes )			{				if ( !( (ChartWithoutAxes) cm ).getSeriesDefinitions( )						.isEmpty( ) )				{					// OK TO ASSUME THAT 1 BASE SERIES DEFINITION EXISTS					SeriesDefinition sdBase = (SeriesDefinition) ( (ChartWithoutAxes) cm ).getSeriesDefinitions( )							.get( 0 );					SeriesDefinition[] sdOrtho = (SeriesDefinition[]) sdBase.getSeriesDefinitions( )							.toArray( );					DataSetIterator dsiOrtho = null;					double dCurrentMinSlice = 0;					for ( int i = 0; i < sdOrtho.length && !bMinSliceApplied; i++ )					{						try						{							dsiOrtho = new DataSetIterator( ( (Series) sdOrtho[i].getRunTimeSeries( )									.get( 0 ) ).getDataSet( ) );						}						catch ( Exception ex )						{							throw new ChartException( ChartEnginePlugin.ID,									ChartException.RENDERING,									ex );						}						// TODO Check dataset type, throw exception or ignore?.						if ( bPercentageMinSlice )						{							double total = 0;							while ( dsiOrtho.hasNext( ) )							{								Object obj = dsiOrtho.next( );								if ( obj instanceof Number )								{									total += ( (Number) obj ).doubleValue( );								}							}							dsiOrtho.reset( );							dCurrentMinSlice = total * dMinSlice / 100d;						}						else						{							dCurrentMinSlice = dMinSlice;						}						while ( dsiOrtho.hasNext( ) )						{							Object obj = dsiOrtho.next( );							if ( obj instanceof Number )							{								double val = ( (Number) obj ).doubleValue( );								if ( val < dCurrentMinSlice )								{									bMinSliceApplied = true;									break;								}							}						}					}				}			}		}		// COMPUTATIONS HERE MUST BE IN SYNC WITH THE ACTUAL RENDERER		if ( o.getValue( ) == Orientation.VERTICAL )		{			double dXOffset = 0, dMaxW = 0;			if ( bPaletteByCategory )			{				SeriesDefinition sdBase = null;				FormatSpecifier fs = null;				if ( cm instanceof ChartWithAxes )				{					// ONLY SUPPORT 1 BASE AXIS FOR NOW					final Axis axPrimaryBase = ( (ChartWithAxes) cm ).getBaseAxes( )[0];					if ( axPrimaryBase.getSeriesDefinitions( ).isEmpty( ) )					{						// NOTHING TO RENDER (BASE AXIS HAS NO SERIES						// DEFINITIONS)						return;					}					// OK TO ASSUME THAT 1 BASE SERIES DEFINITION EXISTS					sdBase = (SeriesDefinition) axPrimaryBase.getSeriesDefinitions( )							.get( 0 );				}				else if ( cm instanceof ChartWithoutAxes )				{					if ( ( (ChartWithoutAxes) cm ).getSeriesDefinitions( )							.isEmpty( ) )					{						// NOTHING TO RENDER (BASE AXIS HAS NO SERIES						// DEFINITIONS)						return;					}					// OK TO ASSUME THAT 1 BASE SERIES DEFINITION EXISTS					sdBase = (SeriesDefinition) ( (ChartWithoutAxes) cm ).getSeriesDefinitions( )							.get( 0 );				}				// OK TO ASSUME THAT 1 BASE RUNTIME SERIES EXISTS				seBase = (Series) sdBase.getRunTimeSeries( ).get( 0 );				pa = sdBase.getSeriesPalette( );				elPaletteEntries = pa.getEntries( );				iPaletteCount = elPaletteEntries.size( );				if ( lilh != null && lilh.getLegendItemHints( ) != null )				{					// use cached value					LegendItemHints[] liha = lilh.getLegendItemHints( );					LegendItemHints lih;					Map columnCache = searchMaxColumnWidth( liha );					for ( int i = 0; i < liha.length; i++ )					{						// render each legend item.						lih = liha[i];						if ( ( lih.getType( ) & IConstants.LEGEND_ENTRY ) == IConstants.LEGEND_ENTRY )						{							la.getCaption( ).setValue( lih.getText( ) );							// CYCLE THROUGH THE PALETTE							fPaletteEntry = (Fill) elPaletteEntries.get( lih.getCategoryIndex( )									% iPaletteCount );							lirh = (LegendItemRenderingHints) htRenderers.get( seBase );							double columnWidth = bo.getWidth( );							Double cachedWidth = (Double) columnCache.get( lih );							if ( cachedWidth != null )							{								columnWidth = cachedWidth.doubleValue( )										+ 3										* dItemHeight										/ 2										+ 2										* insCA.getLeft( );							}							renderLegendItem( ipr,									lg,									la,									null,									dBaseX + lih.getLeft( ),									dBaseY + lih.getTop( ) + insCA.getTop( ),									lih.getWidth( ),									dItemHeight,									lih.getHeight( ),									0,									columnWidth,									insCA.getLeft( ),									dHorizontalSpacing,									seBase,									fPaletteEntry,									lirh );						}					}				}				else				{					DataSetIterator dsiBase = null;					try					{						dsiBase = new DataSetIterator( seBase.getDataSet( ) );					}					catch ( Exception ex )					{						throw new ChartException( ChartEnginePlugin.ID,								ChartException.RENDERING,								ex );					}					if ( sdBase != null )					{						fs = sdBase.getFormatSpecifier( );					}					int i = 0;					while ( dsiBase.hasNext( ) )					{						Object obj = dsiBase.next( );						// TODO filter the not-used legend.						// render legend item.						dY += insCA.getTop( );						String lgtext = String.valueOf( obj );						if ( fs != null )						{							try							{								lgtext = ValueFormatter.format( obj,										fs,										getRunTimeContext( ).getULocale( ),										null );							}							catch ( ChartException e )							{								// ignore, use original text.							}						}						la.getCaption( ).setValue( lgtext );						itm.reuse( la, maxWrappingSize ); // RECYCLED						fPaletteEntry = (Fill) elPaletteEntries.get( i++								% iPaletteCount ); // CYCLE THROUGH THE PALETTE						lirh = (LegendItemRenderingHints) htRenderers.get( seBase );						if ( dY + itm.getFullHeight( ) + insCA.getBottom( ) > dMaxY )						{							dXOffset += dMaxW									+ insCA.getLeft( )									+ insCA.getRight( )									+ ( 3 * dItemHeight )									/ 2									+ dHorizontalSpacing;							dMaxW = 0;							dY = bo.getTop( ) + insCA.getTop( );							dX = bo.getLeft( ) + dXOffset;						}						dMaxW = Math.max( dMaxW, itm.getFullWidth( ) );						renderLegendItem( ipr,								lg,								la,								null,								dX,								dY,								itm.getFullWidth( ),								dItemHeight,								itm.getFullHeight( ),								0,								bo.getWidth( ),								insCA.getLeft( ),								dHorizontalSpacing,								seBase,								fPaletteEntry,								lirh );						dY += itm.getFullHeight( ) + insCA.getBottom( );					}					// render the extra MinSlice legend item if applicable.					if ( bMinSliceApplied )					{						dY += insCA.getTop( );						la.getCaption( ).setValue( sMinSliceLabel );						itm.reuse( la, maxWrappingSize ); // RECYCLED						fPaletteEntry = (Fill) elPaletteEntries.get( dsiBase.size( )								% iPaletteCount ); // CYCLE THROUGH THE PALETTE						lirh = (LegendItemRenderingHints) htRenderers.get( seBase );						if ( dY + itm.getFullHeight( ) + insCA.getBottom( ) > dMaxY )						{							dXOffset += dMaxW									+ insCA.getLeft( )									+ insCA.getRight( )									+ ( 3 * dItemHeight )									/ 2									+ dHorizontalSpacing;							dMaxW = 0;							dY = bo.getTop( ) + insCA.getTop( );							dX = bo.getLeft( ) + dXOffset;						}						dMaxW = Math.max( dMaxW, itm.getFullWidth( ) );						renderLegendItem( ipr,								lg,								la,								null,								dX,								dY,								itm.getFullWidth( ),								dItemHeight,								itm.getFullHeight( ),								0,								bo.getWidth( ),								insCA.getLeft( ),								dHorizontalSpacing,								seBase,								fPaletteEntry,								lirh );						dY += itm.getFullHeight( ) + insCA.getBottom( );					}				}			}			else if ( d.getValue( ) == Direction.TOP_BOTTOM )			{				if ( lilh != null && lilh.getLegendItemHints( ) != null )				{					LegendItemHints[] liha = lilh.getLegendItemHints( );					LegendItemHints lih;					int k = 0;					Map columnCache = searchMaxColumnWidth( liha );					for ( int j = 0; j < seda.length; j++ )					{						al = seda[j].getRunTimeSeries( );						pa = seda[j].getSeriesPalette( );						elPaletteEntries = pa.getEntries( );						iPaletteCount = elPaletteEntries.size( );						for ( int i = 0; i < al.size( ); i++ )						{							seBase = (Series) al.get( i );							lirh = (LegendItemRenderingHints) htRenderers.get( seBase );							lih = liha[k++];							if ( lih.getType( ) == IConstants.LEGEND_ENTRY )							{								la.getCaption( ).setValue( lih.getText( ) );								Label valueLa = null;								if ( lg.isShowValue( ) )								{									valueLa = LabelImpl.copyInstance( seBase.getLabel( ) );									valueLa.getCaption( )											.setValue( lih.getExtraText( ) );								}								// CYCLE THROUGH THE PALETTE								fPaletteEntry = (Fill) elPaletteEntries.get( i										% iPaletteCount );								double columnWidth = bo.getWidth( );								Double cachedWidth = (Double) columnCache.get( lih );								if ( cachedWidth != null )								{									columnWidth = cachedWidth.doubleValue( )											+ 3											* dItemHeight											/ 2											+ 2											* insCA.getLeft( );								}								renderLegendItem( ipr,										lg,										la,										valueLa,										dBaseX + lih.getLeft( ),										dBaseY + lih.getTop( ) + insCA.getTop( ),										lih.getWidth( ),										dItemHeight,										lih.getHeight( ),										lih.getExtraHeight( ),										columnWidth,										insCA.getLeft( ),										dHorizontalSpacing,										seBase,										fPaletteEntry,										lirh );							}						}						if ( j < seda.length - 1 )						{							lih = liha[k];							if ( lih.getType( ) == IConstants.LEGEND_SEPERATOR )							{								k++;								renderSeparator( ipr,										lg,										liSep,										dBaseX + lih.getLeft( ),										dBaseY + lih.getTop( ),										lih.getWidth( ),										Orientation.HORIZONTAL_LITERAL );							}						}					}				}				else				{					dSeparatorThickness += dVerticalSpacing;					for ( int j = 0; j < seda.length; j++ )					{						al = seda[j].getRunTimeSeries( );						pa = seda[j].getSeriesPalette( );						elPaletteEntries = pa.getEntries( );						iPaletteCount = elPaletteEntries.size( );						FormatSpecifier fs = seda[j].getFormatSpecifier( );						for ( int i = 0; i < al.size( ); i++ )						{							seBase = (Series) al.get( i );							lirh = (LegendItemRenderingHints) htRenderers.get( seBase );							dY += insCA.getTop( );							Object obj = seBase.getSeriesIdentifier( );							String lgtext = rtc.externalizedMessage( String.valueOf( obj ) );							if ( fs != null )							{								try								{									lgtext = ValueFormatter.format( obj,											fs,											getRunTimeContext( ).getULocale( ),											null );								}								catch ( ChartException e )								{									// ignore, use original text.								}							}							la.getCaption( ).setValue( lgtext );							itm.reuse( la, maxWrappingSize ); // RECYCLED							double dFWidth = itm.getFullWidth( );							double dFHeight = itm.getFullHeight( );							Label valueLa = null;							double valueHeight = 0;							if ( lg.isShowValue( ) )							{								DataSetIterator dsiBase = null;								try								{									dsiBase = new DataSetIterator( seBase.getDataSet( ) );								}								catch ( Exception ex )								{									throw new ChartException( ChartEnginePlugin.ID,											ChartException.GENERATION,											ex );								}								// Use first value for each series.								if ( dsiBase.hasNext( ) )								{									obj = dsiBase.next( );									String valueText = String.valueOf( obj );									if ( fs != null )									{										try										{											lgtext = ValueFormatter.format( obj,													fs,													ULocale.getDefault( ),													null );										}										catch ( ChartException e )										{											// ignore, use original text.										}									}									valueLa = LabelImpl.copyInstance( seBase.getLabel( ) );									valueLa.getCaption( ).setValue( valueText );									itm.reuse( valueLa );									dFWidth = Math.max( dFWidth,											itm.getFullWidth( ) );									valueHeight = itm.getFullHeight( );								}							}							if ( dY									+ dFHeight									+ valueHeight									+ 2									+ insCA.getBottom( ) > dMaxY )							{								dXOffset += dMaxW										+ insCA.getLeft( )										+ insCA.getRight( )										+ ( 3 * dItemHeight )										/ 2										+ dHorizontalSpacing;								dMaxW = 0;								dY = bo.getTop( ) + insCA.getTop( );								dX = bo.getLeft( ) + dXOffset;							}							dMaxW = Math.max( dMaxW, dFWidth );							fPaletteEntry = (Fill) elPaletteEntries.get( i									% iPaletteCount ); // CYCLE THROUGH THE							// PALETTE							renderLegendItem( ipr,									lg,									la,									valueLa,									dX,									dY,									dFWidth,									dItemHeight,									dFHeight,									valueHeight,									bo.getWidth( ),									insCA.getLeft( ),									dHorizontalSpacing,									seBase,									fPaletteEntry,									lirh );							dY += dFHeight									+ insCA.getBottom( )									+ valueHeight									+ 2;						}						if ( j < seda.length - 1 )						{							renderSeparator( ipr, lg, liSep, dX, dY									+ dSeparatorThickness									/ 2, dMaxW									+ insCA.getLeft( )									+ insCA.getRight( )									+ ( 3 * dItemHeight )									/ 2, Orientation.HORIZONTAL_LITERAL );							dY += dSeparatorThickness;						}					}				}			}			else if ( d.getValue( ) == Direction.LEFT_RIGHT )			{				if ( lilh != null && lilh.getLegendItemHints( ) != null )				{					LegendItemHints[] liha = lilh.getLegendItemHints( );					LegendItemHints lih;					int k = 0;					Map columnCache = searchMaxColumnWidth( liha );					for ( int j = 0; j < seda.length; j++ )					{						al = seda[j].getRunTimeSeries( );						pa = seda[j].getSeriesPalette( );						elPaletteEntries = pa.getEntries( );						iPaletteCount = elPaletteEntries.size( );						for ( int i = 0; i < al.size( ); i++ )						{							seBase = (Series) al.get( i );							lirh = (LegendItemRenderingHints) htRenderers.get( seBase );							lih = liha[k++];							if ( lih.getType( ) == IConstants.LEGEND_ENTRY )							{								la.getCaption( ).setValue( lih.getText( ) );								Label valueLa = null;								if ( lg.isShowValue( ) )								{									valueLa = LabelImpl.copyInstance( seBase.getLabel( ) );									valueLa.getCaption( )											.setValue( lih.getExtraText( ) );								}								// CYCLE THROUGH THE PALETTE								fPaletteEntry = (Fill) elPaletteEntries.get( i										% iPaletteCount );								double columnWidth = bo.getWidth( );								Double cachedWidth = (Double) columnCache.get( lih );								if ( cachedWidth != null )								{									columnWidth = cachedWidth.doubleValue( )											+ 3											* dItemHeight											/ 2											+ 2											* insCA.getLeft( );								}								renderLegendItem( ipr,										lg,										la,										valueLa,										dBaseX + lih.getLeft( ),										dBaseY + lih.getTop( ) + insCA.getTop( ),										lih.getWidth( ),										dItemHeight,										lih.getHeight( ),										lih.getExtraHeight( ),										columnWidth,										insCA.getLeft( ),										dHorizontalSpacing,										seBase,										fPaletteEntry,										lirh );							}						}						if ( j < seda.length - 1 )						{							lih = liha[k];							if ( lih.getType( ) == IConstants.LEGEND_SEPERATOR )							{								k++;								renderSeparator( ipr,										lg,										liSep,										dBaseX + lih.getLeft( ),										dBaseY + lih.getTop( ),										bo.getHeight( ),										Orientation.VERTICAL_LITERAL );							}						}					}				}				else				{					dSeparatorThickness += dHorizontalSpacing;					for ( int j = 0; j < seda.length; j++ )					{						dMaxW = 0;						al = seda[j].getRunTimeSeries( );						pa = seda[j].getSeriesPalette( );						elPaletteEntries = pa.getEntries( );						iPaletteCount = elPaletteEntries.size( );						FormatSpecifier fs = seda[j].getFormatSpecifier( );						for ( int i = 0; i < al.size( ); i++ )						{							dY += insCA.getTop( );							seBase = (Series) al.get( i );							lirh = (LegendItemRenderingHints) htRenderers.get( seBase );							Object obj = seBase.getSeriesIdentifier( );							String lgtext = rtc.externalizedMessage( String.valueOf( obj ) );							if ( fs != null )							{								try								{									lgtext = ValueFormatter.format( obj,											fs,											getRunTimeContext( ).getULocale( ),											null );								}								catch ( ChartException e )								{									// ignore, use original text.								}							}							la.getCaption( ).setValue( lgtext );							itm.reuse( la, maxWrappingSize ); // RECYCLED							double dFWidth = itm.getFullWidth( );							double dFHeight = itm.getFullHeight( );							Label valueLa = null;							double valueHeight = 0;							if ( lg.isShowValue( ) )							{								DataSetIterator dsiBase = null;								try								{									dsiBase = new DataSetIterator( seBase.getDataSet( ) );								}								catch ( Exception ex )								{									throw new ChartException( ChartEnginePlugin.ID,											ChartException.GENERATION,											ex );								}								// Use first value for each series.								if ( dsiBase.hasNext( ) )								{									obj = dsiBase.next( );									String valueText = String.valueOf( obj );									if ( fs != null )									{										try										{											lgtext = ValueFormatter.format( obj,													fs,													ULocale.getDefault( ),													null );										}										catch ( ChartException e )										{											// ignore, use original text.										}									}									valueLa = LabelImpl.copyInstance( seBase.getLabel( ) );									valueLa.getCaption( ).setValue( valueText );									itm.reuse( valueLa );									dFWidth = Math.max( dFWidth,											itm.getFullWidth( ) );									valueHeight = itm.getFullHeight( );								}							}							if ( dY									+ dFHeight									+ valueHeight									+ 2									+ insCA.getBottom( ) > dMaxY )							{								dXOffset += dMaxW										+ insCA.getLeft( )										+ insCA.getRight( )										+ ( 3 * dItemHeight )										/ 2										+ dHorizontalSpacing;								dMaxW = 0;								dY = bo.getTop( );								dX = bo.getLeft( ) + dXOffset;							}							dMaxW = Math.max( dMaxW, dFWidth );							fPaletteEntry = (Fill) elPaletteEntries.get( i									% iPaletteCount ); // CYCLE THROUGH THE							// PALETTE							renderLegendItem( ipr,									lg,									la,									valueLa,									dX,									dY,									dFWidth,									dItemHeight,									dFHeight,									valueHeight,									bo.getWidth( ),									insCA.getLeft( ),									dHorizontalSpacing,									seBase,									fPaletteEntry,									lirh );							dY += dFHeight									+ insCA.getBottom( )									+ valueHeight									+ 2;						}						// LEFT INSETS + LEGEND ITEM WIDTH + HORIZONTAL SPACING						// +						// MAX ITEM WIDTH + RIGHT INSETS						dXOffset += insCA.getLeft( )								+ ( 3 * dItemHeight / 2 )								+ dHorizontalSpacing								+ dMaxW								+ insCA.getRight( );						dX += insCA.getLeft( )								+ ( 3 * dItemHeight / 2 )								+ dHorizontalSpacing								+ dMaxW								+ insCA.getRight( );						dY = bo.getTop( );						// SETUP VERTICAL SEPARATOR SPACING						if ( j < seda.length - 1 )						{							renderSeparator( ipr,									lg,									liSep,									dX + dSeparatorThickness / 2,									dY,									bo.getHeight( ),									Orientation.VERTICAL_LITERAL );							dX += dSeparatorThickness;						}					}				}			}			else			{				throw new ChartException( ChartEnginePlugin.ID,						ChartException.RENDERING,						"exception.illegal.legend.direction", //$NON-NLS-1$						new Object[]{							d.getName( )						},						ResourceBundle.getBundle( Messages.ENGINE,								rtc.getLocale( ) ) );			}		}		else if ( o.getValue( ) == Orientation.HORIZONTAL )		{			double dYOffset = 0, dMaxH = 0;			if ( bPaletteByCategory )			{				SeriesDefinition sdBase = null;				FormatSpecifier fs = null;				if ( cm instanceof ChartWithAxes )				{					// ONLY SUPPORT 1 BASE AXIS FOR NOW					final Axis axPrimaryBase = ( (ChartWithAxes) cm ).getBaseAxes( )[0];					if ( axPrimaryBase.getSeriesDefinitions( ).isEmpty( ) )					{						// NOTHING TO RENDER (BASE AXIS HAS NO SERIES						// DEFINITIONS)						return;					}					// OK TO ASSUME THAT 1 BASE SERIES DEFINITION EXISTS					sdBase = (SeriesDefinition) axPrimaryBase.getSeriesDefinitions( )							.get( 0 );				}				else if ( cm instanceof ChartWithoutAxes )				{					if ( ( (ChartWithoutAxes) cm ).getSeriesDefinitions( )							.isEmpty( ) )					{						// NOTHING TO RENDER (BASE AXIS HAS NO SERIES						// DEFINITIONS)						return;					}					// OK TO ASSUME THAT 1 BASE SERIES DEFINITION EXISTS					sdBase = (SeriesDefinition) ( (ChartWithoutAxes) cm ).getSeriesDefinitions( )							.get( 0 );				}				// OK TO ASSUME THAT 1 BASE RUNTIME SERIES EXISTS				seBase = (Series) sdBase.getRunTimeSeries( ).get( 0 );				pa = sdBase.getSeriesPalette( );				elPaletteEntries = pa.getEntries( );				iPaletteCount = elPaletteEntries.size( );				if ( lilh != null && lilh.getLegendItemHints( ) != null )				{					// use cached value					LegendItemHints[] liha = lilh.getLegendItemHints( );					LegendItemHints lih;					for ( int i = 0; i < liha.length; i++ )					{						// render each legend item.						lih = liha[i];						if ( ( lih.getType( ) & IConstants.LEGEND_ENTRY ) == IConstants.LEGEND_ENTRY )						{							la.getCaption( ).setValue( lih.getText( ) );							// CYCLE THROUGH THE PALETTE							fPaletteEntry = (Fill) elPaletteEntries.get( lih.getCategoryIndex( )									% iPaletteCount );							lirh = (LegendItemRenderingHints) htRenderers.get( seBase );							renderLegendItem( ipr,									lg,									la,									null,									dBaseX + lih.getLeft( ),									dBaseY + lih.getTop( ) + insCA.getTop( ),									lih.getWidth( ),									dItemHeight,									lih.getHeight( ),									0,									lih.getWidth( )											+ 3											* dItemHeight											/ 2											+ 2											* insCA.getLeft( ),									insCA.getLeft( ),									dHorizontalSpacing,									seBase,									fPaletteEntry,									lirh );						}					}				}				else				{					DataSetIterator dsiBase = null;					try					{						dsiBase = new DataSetIterator( seBase.getDataSet( ) );					}					catch ( Exception ex )					{						throw new ChartException( ChartEnginePlugin.ID,								ChartException.RENDERING,								ex );					}					if ( sdBase != null )					{						fs = sdBase.getFormatSpecifier( );					}					int i = 0;					double dFullWidth = 0;					dY += insCA.getTop( );					while ( dsiBase.hasNext( ) )					{						Object obj = dsiBase.next( );						// TODO filter the not-used legend.						dX += insCA.getLeft( );						String lgtext = String.valueOf( obj );						if ( fs != null )						{							try							{								lgtext = ValueFormatter.format( obj,										fs,										getRunTimeContext( ).getULocale( ),										null );							}							catch ( ChartException e )							{								// ignore, use original text.							}						}						la.getCaption( ).setValue( lgtext );						itm.reuse( la, maxWrappingSize ); // RECYCLED						fPaletteEntry = (Fill) elPaletteEntries.get( i++								% iPaletteCount ); // CYCLE THROUGH THE PALETTE						lirh = (LegendItemRenderingHints) htRenderers.get( seBase );						dFullWidth = itm.getFullWidth( );						if ( dX								+ dFullWidth								+ ( 3 * dItemHeight )								/ 2								+ insCA.getRight( ) > dMaxX )						{							dYOffset += dMaxH									+ insCA.getTop( )									+ insCA.getBottom( )									+ dVerticalSpacing;							dMaxH = 0;							dX = bo.getLeft( ) + insCA.getLeft( );							dY = bo.getTop( ) + insCA.getTop( ) + dYOffset;						}						dMaxH = Math.max( dMaxH, itm.getFullHeight( ) );						renderLegendItem( ipr,								lg,								la,								null,								dX,								dY,								dFullWidth,								dItemHeight,								itm.getFullHeight( ),								0,								dFullWidth										+ 3										* dItemHeight										/ 2										+ 2										* insCA.getLeft( ),								insCA.getLeft( ),								dHorizontalSpacing,								seBase,								fPaletteEntry,								lirh );						dX += dFullWidth								+ ( 3 * dItemHeight )								/ 2								+ insCA.getRight( );					}					// render the extra MinSlice legend item if applicable.					if ( bMinSliceApplied )					{						dX += insCA.getLeft( );						la.getCaption( ).setValue( sMinSliceLabel );						itm.reuse( la, maxWrappingSize ); // RECYCLED						fPaletteEntry = (Fill) elPaletteEntries.get( dsiBase.size( )								% iPaletteCount ); // CYCLE THROUGH THE PALETTE						lirh = (LegendItemRenderingHints) htRenderers.get( seBase );						dFullWidth = itm.getFullWidth( );						if ( dX								+ dFullWidth								+ ( 3 * dItemHeight )								/ 2								+ insCA.getRight( ) > dMaxX )						{							dYOffset += dMaxH									+ insCA.getTop( )									+ insCA.getBottom( )									+ dVerticalSpacing;							dMaxH = 0;							dX = bo.getLeft( ) + insCA.getLeft( );							dY = bo.getTop( ) + insCA.getTop( ) + dYOffset;						}						dMaxH = Math.max( dMaxH, itm.getFullHeight( ) );						renderLegendItem( ipr,								lg,								la,								null,								dX,								dY,								dFullWidth,								dItemHeight,								itm.getFullHeight( ),								0,								dFullWidth										+ 3										* dItemHeight										/ 2										+ 2										* insCA.getLeft( ),								insCA.getLeft( ),								dHorizontalSpacing,								seBase,								fPaletteEntry,								lirh );						dX += dFullWidth								+ ( 3 * dItemHeight )								/ 2								+ insCA.getRight( );					}				}			}			else if ( d.getValue( ) == Direction.TOP_BOTTOM )			{				if ( lilh != null && lilh.getLegendItemHints( ) != null )				{					LegendItemHints[] liha = lilh.getLegendItemHints( );					LegendItemHints lih;					int k = 0;					for ( int j = 0; j < seda.length; j++ )					{						al = seda[j].getRunTimeSeries( );						pa = seda[j].getSeriesPalette( );						elPaletteEntries = pa.getEntries( );						iPaletteCount = elPaletteEntries.size( );						for ( int i = 0; i < al.size( ); i++ )						{							seBase = (Series) al.get( i );							lirh = (LegendItemRenderingHints) htRenderers.get( seBase );							lih = liha[k++];							if ( lih.getType( ) == IConstants.LEGEND_ENTRY )							{								la.getCaption( ).setValue( lih.getText( ) );								Label valueLa = null;								if ( lg.isShowValue( ) )								{									valueLa = LabelImpl.copyInstance( seBase.getLabel( ) );									valueLa.getCaption( )											.setValue( lih.getExtraText( ) );								}								// CYCLE THROUGH THE PALETTE								fPaletteEntry = (Fill) elPaletteEntries.get( i										% iPaletteCount );								renderLegendItem( ipr,										lg,										la,										valueLa,										dBaseX + lih.getLeft( ),										dBaseY + lih.getTop( ) + insCA.getTop( ),										lih.getWidth( ),										dItemHeight,										lih.getHeight( ),										lih.getExtraHeight( ),										lih.getWidth( )												+ 3												* dItemHeight												/ 2												+ 2												* insCA.getLeft( ),										insCA.getLeft( ),										dHorizontalSpacing,										seBase,										fPaletteEntry,										lirh );							}						}						if ( j < seda.length - 1 )						{							lih = liha[k];							if ( lih.getType( ) == IConstants.LEGEND_SEPERATOR )							{								k++;								renderSeparator( ipr,										lg,										liSep,										dBaseX + lih.getLeft( ),										dBaseY + lih.getTop( ),										bo.getWidth( ),										Orientation.HORIZONTAL_LITERAL );							}						}					}				}				else				{					dSeparatorThickness += dVerticalSpacing;					for ( int j = 0; j < seda.length; j++ )					{						dMaxH = 0;						dY += insCA.getTop( );						dX = bo.getLeft( ) + insCA.getLeft( );						al = seda[j].getRunTimeSeries( );						pa = seda[j].getSeriesPalette( );						elPaletteEntries = pa.getEntries( );						iPaletteCount = elPaletteEntries.size( );						FormatSpecifier fs = seda[j].getFormatSpecifier( );						for ( int i = 0; i < al.size( ); i++ )						{							seBase = (Series) al.get( i );							lirh = (LegendItemRenderingHints) htRenderers.get( seBase );							Object obj = seBase.getSeriesIdentifier( );							String lgtext = rtc.externalizedMessage( String.valueOf( obj ) );							if ( fs != null )							{								try								{									lgtext = ValueFormatter.format( obj,											fs,											getRunTimeContext( ).getULocale( ),											null );								}								catch ( ChartException e )								{									// ignore, use original text.								}							}							la.getCaption( ).setValue( lgtext );							itm.reuse( la, maxWrappingSize ); // RECYCLED							double dFWidth = itm.getFullWidth( );							double dFHeight = itm.getFullHeight( );							Label valueLa = null;							double valueHeight = 0;							if ( lg.isShowValue( ) )							{								DataSetIterator dsiBase = null;								try								{									dsiBase = new DataSetIterator( seBase.getDataSet( ) );								}								catch ( Exception ex )								{									throw new ChartException( ChartEnginePlugin.ID,											ChartException.GENERATION,											ex );								}								// Use first value for each series.								if ( dsiBase.hasNext( ) )								{									obj = dsiBase.next( );									String valueText = String.valueOf( obj );									if ( fs != null )									{										try										{											lgtext = ValueFormatter.format( obj,													fs,													ULocale.getDefault( ),													null );										}										catch ( ChartException e )										{											// ignore, use original text.										}									}									valueLa = LabelImpl.copyInstance( seBase.getLabel( ) );									valueLa.getCaption( ).setValue( valueText );									itm.reuse( valueLa );									dFWidth = Math.max( dFWidth,											itm.getFullWidth( ) );									valueHeight = itm.getFullHeight( );								}							}							if ( dX									+ insCA.getLeft( )									+ dFWidth									+ ( 3 * dItemHeight )									/ 2									+ insCA.getRight( ) > dMaxX )							{								dYOffset += dMaxH										+ insCA.getTop( )										+ insCA.getBottom( )										+ dVerticalSpacing;								dMaxH = 0;								dX = bo.getLeft( ) + insCA.getLeft( );								dY = bo.getTop( ) + insCA.getTop( ) + dYOffset;							}							dMaxH = Math.max( dMaxH, dFHeight + valueHeight + 2 );							fPaletteEntry = (Fill) elPaletteEntries.get( i									% iPaletteCount ); // CYCLE THROUGH THE							// PALETTE							renderLegendItem( ipr,									lg,									la,									valueLa,									dX,									dY,									dFWidth,									dItemHeight,									dFHeight,									valueHeight,									dFWidth											+ 3											* dItemHeight											/ 2											+ 2											* insCA.getLeft( ),									insCA.getLeft( ),									dHorizontalSpacing,									seBase,									fPaletteEntry,									lirh );							// LEFT INSETS + LEGEND ITEM WIDTH + HORIZONTAL							// SPACING							// + MAX ITEM WIDTH + RIGHT INSETS							dX += insCA.getLeft( )									+ ( 3 * dItemHeight )									/ 2									+ dFWidth									+ insCA.getRight( );						}						dYOffset += insCA.getTop( )								+ insCA.getBottom( )								+ dMaxH								+ dVerticalSpacing;						dY += insCA.getTop( )								+ insCA.getBottom( )								+ dMaxH								+ dVerticalSpacing;						dX = bo.getLeft( ) + insCA.getLeft( );						// SETUP HORIZONTAL SEPARATOR SPACING						if ( j < seda.length - 1 )						{							renderSeparator( ipr,									lg,									liSep,									dX,									dY + dSeparatorThickness / 2,									bo.getWidth( ),									Orientation.HORIZONTAL_LITERAL );							dY += dSeparatorThickness;						}					}				}			}			else if ( d.getValue( ) == Direction.LEFT_RIGHT )			{				if ( lilh != null && lilh.getLegendItemHints( ) != null )				{					LegendItemHints[] liha = lilh.getLegendItemHints( );					LegendItemHints lih;					int k = 0;					for ( int j = 0; j < seda.length; j++ )					{						al = seda[j].getRunTimeSeries( );						pa = seda[j].getSeriesPalette( );						elPaletteEntries = pa.getEntries( );						iPaletteCount = elPaletteEntries.size( );						for ( int i = 0; i < al.size( ); i++ )						{							seBase = (Series) al.get( i );							lirh = (LegendItemRenderingHints) htRenderers.get( seBase );							lih = liha[k++];							if ( lih.getType( ) == IConstants.LEGEND_ENTRY )							{								la.getCaption( ).setValue( lih.getText( ) );								Label valueLa = null;								if ( lg.isShowValue( ) )								{									valueLa = LabelImpl.copyInstance( seBase.getLabel( ) );									valueLa.getCaption( )											.setValue( lih.getExtraText( ) );								}								// CYCLE THROUGH THE PALETTE								fPaletteEntry = (Fill) elPaletteEntries.get( i										% iPaletteCount );								renderLegendItem( ipr,										lg,										la,										valueLa,										dBaseX + lih.getLeft( ),										dBaseY + lih.getTop( ) + insCA.getTop( ),										lih.getWidth( ),										dItemHeight,										lih.getHeight( ),										lih.getExtraHeight( ),										lih.getWidth( )												+ 3												* dItemHeight												/ 2												+ 2												* insCA.getLeft( ),										insCA.getLeft( ),										dHorizontalSpacing,										seBase,										fPaletteEntry,										lirh );							}						}						if ( j < seda.length - 1 )						{							lih = liha[k];							if ( lih.getType( ) == IConstants.LEGEND_SEPERATOR )							{								k++;								renderSeparator( ipr,										lg,										liSep,										dBaseX + lih.getLeft( ),										dBaseY + lih.getTop( ),										lih.getHeight( ),										Orientation.VERTICAL_LITERAL );							}						}					}				}				else				{					dSeparatorThickness += dHorizontalSpacing;					dX += insCA.getLeft( );					dY += insCA.getTop( );					for ( int j = 0; j < seda.length; j++ )					{						al = seda[j].getRunTimeSeries( );						pa = seda[j].getSeriesPalette( );						elPaletteEntries = pa.getEntries( );						iPaletteCount = elPaletteEntries.size( );						FormatSpecifier fs = seda[j].getFormatSpecifier( );						for ( int i = 0; i < al.size( ); i++ )						{							seBase = (Series) al.get( i );							lirh = (LegendItemRenderingHints) htRenderers.get( seBase );							Object obj = seBase.getSeriesIdentifier( );							String lgtext = rtc.externalizedMessage( String.valueOf( obj ) );							if ( fs != null )							{								try								{									lgtext = ValueFormatter.format( obj,											fs,											getRunTimeContext( ).getULocale( ),											null );								}								catch ( ChartException e )								{									// ignore, use original text.								}							}							la.getCaption( ).setValue( lgtext );							itm.reuse( la, maxWrappingSize ); // RECYCLED							double dFWidth = itm.getFullWidth( );							double dFHeight = itm.getFullHeight( );							Label valueLa = null;							double valueHeight = 0;							if ( lg.isShowValue( ) )							{								DataSetIterator dsiBase = null;								try								{									dsiBase = new DataSetIterator( seBase.getDataSet( ) );								}								catch ( Exception ex )								{									throw new ChartException( ChartEnginePlugin.ID,											ChartException.GENERATION,											ex );								}								// Use first value for each series.								if ( dsiBase.hasNext( ) )								{									obj = dsiBase.next( );									String valueText = String.valueOf( obj );									if ( fs != null )									{										try										{											lgtext = ValueFormatter.format( obj,													fs,													ULocale.getDefault( ),													null );										}										catch ( ChartException e )										{											// ignore, use original text.										}									}									valueLa = LabelImpl.copyInstance( seBase.getLabel( ) );									valueLa.getCaption( ).setValue( valueText );									itm.reuse( valueLa );									dFWidth = Math.max( dFWidth,											itm.getFullWidth( ) );									valueHeight = itm.getFullHeight( );								}							}							if ( dX									+ insCA.getLeft( )									+ dFWidth									+ ( 3 * dItemHeight )									/ 2									+ insCA.getRight( ) > dMaxX )							{								dYOffset += dMaxH										+ insCA.getTop( )										+ insCA.getBottom( )										+ dVerticalSpacing;								dMaxH = 0;								dX = bo.getLeft( ) + insCA.getLeft( );								dY = bo.getTop( ) + dYOffset;							}							dMaxH = Math.max( dMaxH, dFHeight + valueHeight + 2 );							fPaletteEntry = (Fill) elPaletteEntries.get( i									% iPaletteCount ); // CYCLE THROUGH THE							// PALETTE							renderLegendItem( ipr,									lg,									la,									valueLa,									dX,									dY,									dFWidth,									dItemHeight,									dFHeight,									valueHeight,									dFWidth											+ 3											* dItemHeight											/ 2											+ 2											* insCA.getLeft( ),									insCA.getLeft( ),									dHorizontalSpacing,									seBase,									fPaletteEntry,									lirh );							// LEFT INSETS + LEGEND ITEM WIDTH + HORIZONTAL							// SPACING							// + MAX ITEM WIDTH + RIGHT INSETS							dX += insCA.getLeft( )									+ ( 3 * dItemHeight )									/ 2									+ dHorizontalSpacing									+ dFWidth									+ insCA.getRight( );						}						// SETUP VERTICAL SEPARATOR SPACING						if ( j < seda.length - 1 )						{							renderSeparator( ipr,									lg,									liSep,									dX + dSeparatorThickness / 2,									dY,									dMaxH,									Orientation.VERTICAL_LITERAL );							dX += dSeparatorThickness;						}					}				}			}			else			{				throw new ChartException( ChartEnginePlugin.ID,						ChartException.RENDERING,						"exception.illegal.legend.direction", //$NON-NLS-1$						new Object[]{							d.getName( )						},						ResourceBundle.getBundle( Messages.ENGINE,								rtc.getLocale( ) ) ); // i18n_CONCATENATIONS_REMOVED			}		}		else		{			throw new ChartException( ChartEnginePlugin.ID,					ChartException.RENDERING,					"exception.illegal.legend.orientation", //$NON-NLS-1$ 					new Object[]{						o.getName( )					},					ResourceBundle.getBundle( Messages.ENGINE, rtc.getLocale( ) ) );		}		// Render legend title if defined.		if ( bRenderLegendTitle )		{			double lX = bo.getLeft( );			double lY = bo.getTop( );			switch ( iTitlePos )			{				case Position.ABOVE :					lX = bo.getLeft( ) + ( bo.getWidth( ) - lgTitleWidth ) / 2d;					lY = bo.getTop( ) - lgTitleHeight;					break;				case Position.BELOW :					lX = bo.getLeft( ) + ( bo.getWidth( ) - lgTitleWidth ) / 2d;					lY = bo.getTop( ) + bo.getHeight( );					break;				case Position.LEFT :					lX = bo.getLeft( ) - lgTitleWidth;					lY = bo.getTop( )							+ ( bo.getHeight( ) - lgTitleHeight )							/ 2d;					break;				case Position.RIGHT :					lX = bo.getLeft( ) + bo.getWidth( );					lY = bo.getTop( )							+ ( bo.getHeight( ) - lgTitleHeight )							/ 2d;					break;			}			final TextRenderEvent tre = (TextRenderEvent) ( (EventObjectCache) ir ).getEventObject( WrappedStructureSource.createLegendTitle( lg,					lgTitle ),					TextRenderEvent.class );			tre.setBlockBounds( BoundsImpl.create( lX,					lY,					lgTitleWidth,					lgTitleHeight ) );			TextAlignment ta = TextAlignmentImpl.create( );			ta.setHorizontalAlignment( HorizontalAlignment.CENTER_LITERAL );			ta.setVerticalAlignment( VerticalAlignment.CENTER_LITERAL );			tre.setBlockAlignment( ta );			tre.setLabel( lgTitle );			tre.setAction( TextRenderEvent.RENDER_TEXT_IN_BLOCK );			ipr.drawText( tre );		}		itm.dispose( ); // DISPOSE RESOURCES AFTER USE	}