/* * Copyright 1999-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* $Id$ */ package org.apache.fop.area; // Java import java.io.IOException; import java.io.OutputStream; import java.util.List; import java.util.Iterator; // XML import org.xml.sax.SAXException; // FOP import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.fonts.FontInfo; import org.apache.fop.render.Renderer; import org.apache.fop.render.RendererFactory; /** * This uses the store pages model to store the pages * each page is either rendered if ready or prepared * for later rendering. * Once a page is rendered it is cleared to release the * contents but the PageViewport is retained. So even * though the pages are stored the contents are discarded. */ public class RenderPagesModel extends StorePagesModel { /** * The renderer that will render the pages. */ protected Renderer renderer; /** * Pages that have been prepared but not rendered yet. */ protected List prepared = new java.util.ArrayList(); private List pendingODI = new java.util.ArrayList(); private List endDocODI = new java.util.ArrayList(); /** * Create a new render pages model with the given renderer. * @param userAgent FOUserAgent object for process * @param renderType Desired fo.Constants output type (RENDER_PDF, * RENDER_PS, etc.) * @param fontInfo FontInfo object * @param stream OutputStream * @throws FOPException if the renderer cannot be properly initialized */ public RenderPagesModel (FOUserAgent userAgent, int renderType, FontInfo fontInfo, OutputStream stream) throws FOPException { renderer = RendererFactory.createRenderer(userAgent, renderType); try { renderer.setupFontInfo(fontInfo); // check that the "any,normal,400" font exists if (!fontInfo.isSetupValid()) { throw new FOPException( "No default font defined by OutputConverter"); } renderer.startRenderer(stream); } catch (IOException e) { throw new FOPException(e); } } /** * Start a new page sequence. * This tells the renderer that a new page sequence has * started with the given title. * @param title the title of the new page sequence */ public void startPageSequence(LineArea title) { super.startPageSequence(title); renderer.startPageSequence(title); } /** * Add a page to the render page model. * If the page is finished it can be rendered immediately. * If the page needs resolving then if the renderer supports * out of order rendering it can prepare the page. Otherwise * the page is added to a queue. * @param page the page to add to the model */ public void addPage(PageViewport page) { super.addPage(page); // for links the renderer needs to prepare the page // it is more appropriate to do this after queued pages but // it will mean that the renderer has not prepared a page that // could be referenced boolean done = renderer.supportsOutOfOrder() && page.isResolved(); if (done) { try { renderer.renderPage(page); } catch (Exception e) { // use error handler to handle this FOP or IO Exception e.printStackTrace(); } page.clear(); } else { preparePage(page); } // check prepared pages boolean cont = checkPreparedPages(page); if (cont) { processOffDocumentItems(pendingODI); pendingODI.clear(); } } /** * Check prepared pages * * @param newpage the new page being added * @return true if the current page should be rendered * false if the renderer doesn't support out of order * rendering and there are pending pages */ protected boolean checkPreparedPages(PageViewport newpage) { for (Iterator iter = prepared.iterator(); iter.hasNext();) { PageViewport p = (PageViewport)iter.next(); if (p.isResolved()) { try { renderer.renderPage(p); } catch (Exception e) { // use error handler to handle this FOP or IO Exception e.printStackTrace(); } p.clear(); iter.remove(); } else { // if keeping order then stop at first page not resolved if (!renderer.supportsOutOfOrder()) { break; } } } return renderer.supportsOutOfOrder() || prepared.isEmpty(); } /** * Prepare a page. * An unresolved page can be prepared if the renderer supports * it and the page will be rendered later. * @param page the page to prepare */ protected void preparePage(PageViewport page) { if (renderer.supportsOutOfOrder()) { renderer.preparePage(page); } prepared.add(page); } /** * @see org.apache.fop.area.AreaTreeModel#handleOffDocumentItem(OffDocumentItem) */ public void handleOffDocumentItem(OffDocumentItem oDI) { switch(oDI.getWhenToProcess()) { case OffDocumentItem.IMMEDIATELY: renderer.processOffDocumentItem(oDI); break; case OffDocumentItem.AFTER_PAGE: pendingODI.add(oDI); break; case OffDocumentItem.END_OF_DOC: endDocODI.add(oDI); break; } } private void processOffDocumentItems(List list) { for (int count = 0; count < list.size(); count++) { OffDocumentItem oDI = (OffDocumentItem)list.get(count); renderer.processOffDocumentItem(oDI); } } /** * End the document. Render any end document OffDocumentItems * @see org.apache.fop.area.AreaTreeModel#endDocument() */ public void endDocument() throws SAXException { // render any pages that had unresolved ids checkPreparedPages(null); processOffDocumentItems(pendingODI); pendingODI.clear(); processOffDocumentItems(endDocODI); try { renderer.stopRenderer(); } catch (IOException ex) { throw new SAXException(ex); } } }