gt: 	protected abstract void cancelChildren( ) throws BirtException;
context: /***********************************************************************
   * Copyright (c) 2004, 2007 Actuate Corporation.
   * All rights reserved. This program and the accompanying materials
   * are made available under the terms of the Eclipse Public License v1.0
   * which accompanies this distribution, and is available at
   * http://www.eclipse.org/legal/epl-v10.html
   *
   * Contributors:
   * Actuate Corporation - initial API and implementation
   ***********************************************************************/
  
  package org.eclipse.birt.report.engine.layout.pdf;
  
  import java.util.Iterator;
  import java.util.logging.Level;
  import java.util.logging.Logger;
  
  import org.eclipse.birt.core.exception.BirtException;
  import org.eclipse.birt.report.engine.content.Dimension;
  import org.eclipse.birt.report.engine.content.IContent;
  import org.eclipse.birt.report.engine.content.IReportContent;
  import org.eclipse.birt.report.engine.content.IStyle;
  import org.eclipse.birt.report.engine.content.ITextContent;
  import org.eclipse.birt.report.engine.css.engine.value.FloatValue;
  import org.eclipse.birt.report.engine.css.engine.value.ListValue;
  import org.eclipse.birt.report.engine.css.engine.value.birt.BIRTConstants;
  import org.eclipse.birt.report.engine.executor.IReportExecutor;
  import org.eclipse.birt.report.engine.extension.IReportItemExecutor;
  import org.eclipse.birt.report.engine.extension.ReportItemExecutorBase;
  import org.eclipse.birt.report.engine.ir.DimensionType;
  import org.eclipse.birt.report.engine.ir.EngineIRConstants;
  import org.eclipse.birt.report.engine.ir.MasterPageDesign;
  import org.eclipse.birt.report.engine.ir.PageSetupDesign;
  import org.eclipse.birt.report.engine.layout.ILayoutManager;
  import org.eclipse.birt.report.engine.layout.PDFConstants;
  import org.eclipse.birt.report.engine.layout.area.IArea;
  import org.eclipse.birt.report.engine.layout.area.impl.AbstractArea;
  import org.eclipse.birt.report.engine.layout.area.impl.AreaFactory;
  import org.eclipse.birt.report.engine.layout.area.impl.CellArea;
  import org.eclipse.birt.report.engine.layout.area.impl.RowArea;
  import org.eclipse.birt.report.engine.layout.pdf.font.FontInfo;
  import org.w3c.dom.css.CSSPrimitiveValue;
  import org.w3c.dom.css.CSSValue;
  
  public abstract class PDFAbstractLM implements ILayoutManager
  {
  
  	// identy the status of layout manager
  	protected final static int STATUS_START = 0;
  	protected final static int STATUS_INPROGRESS = 1;
  	protected final static int STATUS_END = 3;
  
  	protected int status = STATUS_START;
  
  	protected static Logger logger = Logger.getLogger( PDFAbstractLM.class
  			.getName( ) );
  
  	protected PDFStackingLM parent;
  
  	protected IContent content;
  
  	protected PDFLayoutEngineContext context;
  
  	protected IReportItemExecutor executor;
  
  	/**
  	 * identify if current area is the first area generated by content
  	 */
  	protected boolean isFirst = true;
  
  	/**
  	 * identify if current area is the last area generated by content
  	 */
  	protected boolean isLast = false;
  
  	protected int specifiedWidth = 0;
  
  	protected int specifiedHeight = 0;
  
  	public IContent getContent( )
  	{
  		return content;
  	}
  
  	public PDFAbstractLM( PDFLayoutEngineContext context, PDFStackingLM parent,
  			IContent content, IReportItemExecutor executor )
  	{
  		this.context = context;
  		this.content = content;
  		this.parent = parent;
  		this.executor = executor;
  	}
  
  	/**
  	 * layout the content and its children.
  	 * 
  	 * It can be called in three status:
  	 * <ol> 
  	 * <li> start, the first time it is called. In this status, 
  	 * it first check if it need page-break-before,
  	 * 
  	 * <li> inprogress, the second or more time it is called. In this status, it
  	 * tries to layout the content and its children to the current page.
  	 * 
  	 * <li> end, the last time it is called. In this status, it means all the
  	 * content has been layout, it is the time to handle the page-break-after.
  	 * </ol>
  	 */
  	public boolean layout( ) throws BirtException
  	{
  		boolean hasNextPage = false;
  		switch ( status )
  		{
  			case STATUS_START :
  				// this element is in-visible, just as it doesn't exits.
  				// we must traverse all its children (to let the generate
  				// engine create all the content).
  				if ( handleVisibility( ) )
  				{
  					status = STATUS_END;
  					return false;
  				}
  				// we need put it in the new page or there is no
  				// space for the content.
  				if ( handlePageBreakBefore( ) || checkAvailableSpace( ) )
  				{
  					status = STATUS_INPROGRESS;
  					return true;
  				}
  				// we need continue to execute.
  				status = STATUS_INPROGRESS;
  			case STATUS_INPROGRESS :
  				hasNextPage = layoutChildren( );
  				if ( hasNextPage )
  				{
  					// there are still some content to output,
  					// return to caller to create the new page.
  					if(!hasNextChild())
  					{
  						closeExecutor( );
  						status = STATUS_END;
  					}
  					return true;
  				}
  				// we have finished the content and all its children.
  				closeExecutor( );
  				status = STATUS_END;
  				// We need create an extra page for the following elements, so
  				// return true for next element.
  				if ( handlePageBreakAfter( ) )
  				{
  					return true;
  				}
  			case STATUS_END :
  				return false;
  		}
  		return hasNextPage;
  	}
  
  	protected abstract boolean hasNextChild( ) throws BirtException;
  	
  	protected void closeExecutor( ) throws BirtException
  	{
  		if ( executor != null )
  		{
  			executor.close( );
  		}
  	}
  
  
  	protected abstract boolean layoutChildren( ) throws BirtException;
  
  	public boolean isFinished( )
  	{
  		return status == STATUS_END;
  	}
  
  	protected boolean allowPageBreak( )
  	{
  		return true;
  	}
  
  	public PDFStackingLM getParent( )
  	{
  		return this.parent;
  	}
  
  	protected PDFLayoutManagerFactory getFactory( )
  	{
  		return context.getFactory( );
  	}
  
  	protected boolean handlePageBreakBefore( )
  	{
  		if ( content == null )
  		{
  			return false;
  		}
  		IStyle style = content.getStyle( );
  		String pageBreak = style.getPageBreakBefore( );
  		handlePageBreakBeforeAvoid(pageBreak);
  		if ( canPageBreak( ) )
  		{
  			return needPageBreakBefore( pageBreak );
  		}
  		return false;
  	}
  
  	protected boolean handlePageBreakAfter( )
  	{
  		if ( content == null )
  		{
  			return false;
  		}
  		IStyle style = content.getStyle( );
  		String pageBreak = style.getPageBreakAfter( );
  		handlePageBreakAfterAvoid(pageBreak);
  		if ( canPageBreak( ) )
  		{
  			return needPageBreakAfter(pageBreak );
  		}
  		return false;
  	}
  
  	protected void handlePageBreakBeforeAvoid(String pageBreak)
  	{
  		if(parent instanceof PDFBlockStackingLM)
  		{
  			((PDFBlockStackingLM)parent).setKeepWithNext(IStyle.CSS_AVOID_VALUE == pageBreak);
  		}
  	}
  	
  	protected void handlePageBreakAfterAvoid(String pageBreak)
  	{
  		if(IStyle.CSS_AVOID_VALUE == pageBreak)
  		{
  			if(parent instanceof PDFBlockStackingLM)
  			{
  				((PDFBlockStackingLM)parent).setKeepWithNext(true);
  			}
  		}
  		
  	}
  	protected boolean canPageBreak( )
  	{
  		if ( !context.allowPageBreak( ) )
  		{
  			return false;
  		}
  		
  		PDFAbstractLM p = parent;
  		while ( p != null )
  		{
  			if ( !p.allowPageBreak( ) )
  			{
  				return false;
  			}
  			p = p.getParent( );
  		}
  		return true;
  	}
  
  	protected boolean needPageBreakBefore(String pageBreak )
  	{
  		boolean ret = hasMasterPageChanged( );
  
  		if ( IStyle.CSS_ALWAYS_VALUE == pageBreak
  				|| IStyle.CSS_LEFT_VALUE == pageBreak
  				|| IStyle.CSS_RIGHT_VALUE == pageBreak
  				|| IStyle.CSS_SOFT_VALUE == pageBreak)
  		{
  			return true;
  		}
  
  		return ret;
  	}
  
  	protected boolean needPageBreakAfter(String pageBreak )
  	{
  		if ( IStyle.CSS_ALWAYS_VALUE == pageBreak
  				|| IStyle.CSS_LEFT_VALUE == pageBreak
  				|| IStyle.CSS_RIGHT_VALUE == pageBreak )
  		{
  			return true;
  		}
  		return false;
  	}
  
  	private boolean hasMasterPageChanged( )
  	{
  		if ( content == null )
  		{
  			return false;
  		}
  		IStyle style = content.getStyle( );
  		if ( style == null )
  		{
  			return false;
  		}
  		String newMasterPage = style.getMasterPage( );
  		if ( newMasterPage == null || "".equals( newMasterPage ) ) //$NON-NLS-1$
  		{
  			return false;
  		}
  		String masterPage = context.getMasterPage( );
  		if ( !newMasterPage.equalsIgnoreCase( masterPage ) )
  		{
  			// check if this master exist
  			PageSetupDesign pageSetup = content.getReportContent( ).getDesign( )
  					.getPageSetup( );
  			if ( pageSetup.getMasterPageCount( ) > 0 )
  			{
  				MasterPageDesign masterPageDesign = pageSetup
  						.findMasterPage( newMasterPage );
  				if ( masterPageDesign != null )
  				{
  					context.setMasterPage( newMasterPage );
  					return true;
  				}
  			}
  		}
  		return false;
  	}
  
  	protected MasterPageDesign getMasterPage( IReportContent report )
  	{
  		String masterPage = context.getMasterPage( );
  		MasterPageDesign pageDesign = null;
  		if ( masterPage != null && !"".equals( masterPage ) ) //$NON-NLS-1$
  		{
  			pageDesign = report.getDesign( ).findMasterPage( masterPage );
  			if ( pageDesign != null )
  			{
  				return pageDesign;
  			}
  		}
  		return getDefaultMasterPage( report );
  	}
  
  	protected MasterPageDesign getDefaultMasterPage( IReportContent report )
  	{
  		PageSetupDesign pageSetup = report.getDesign( ).getPageSetup( );
  		int pageCount = pageSetup.getMasterPageCount( );
  		if ( pageCount > 0 )
  		{
  			MasterPageDesign pageDesign =  pageSetup.getMasterPage( 0 );
  			context.setMasterPage( pageDesign.getName( ) );
  			return pageDesign;
  		}
  		return null;
  	}
  
  	protected boolean handleVisibility( ) throws BirtException
  	{
  		if ( isHidden( ) )
  		{
  			traverse( executor );
  			return true;
  		}
  		else
  		{
  			return false;
  		}
  	}
  
  	private void traverse( IReportItemExecutor executor ) throws BirtException
  	{
  		if ( executor != null )
  		{
  			while ( executor.hasNextChild( ) )
  			{
  				IReportItemExecutor child = (IReportItemExecutor) executor
  						.getNextChild( );
  				if ( child != null )
  				{
  					child.execute( );
  					traverse( child );
  					child.close( );
  				}
  			}
  		}
  	}
  	
  	public abstract void autoPageBreak();
  	
  