/* * $Id$ * ============================================================================ * The Apache Software License, Version 1.1 * ============================================================================ * * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. The end-user documentation included with the redistribution, if any, must * include the following acknowledgment: "This product includes software * developed by the Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, if * and wherever such third-party acknowledgments normally appear. * * 4. The names "FOP" and "Apache Software Foundation" must not be used to * endorse or promote products derived from this software without prior * written permission. For written permission, please contact * apache@apache.org. * * 5. Products derived from this software may not be called "Apache", nor may * "Apache" appear in their name, without prior written permission of the * Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ============================================================================ * * This software consists of voluntary contributions made by many individuals * on behalf of the Apache Software Foundation and was originally created by * James Tauber . For more information on the Apache * Software Foundation, please see . */ package org.apache.fop.render.rtf; // Java import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import org.apache.avalon.framework.logger.ConsoleLogger; import org.apache.avalon.framework.logger.Logger; import org.apache.fop.apps.FOPException; import org.apache.fop.fo.EnumProperty; import org.apache.fop.fo.FOInputHandler; import org.apache.fop.datatypes.FixedLength; import org.apache.fop.fo.flow.Block; import org.apache.fop.fo.flow.ExternalGraphic; import org.apache.fop.fo.flow.Inline; import org.apache.fop.fo.flow.InstreamForeignObject; import org.apache.fop.fo.flow.Leader; import org.apache.fop.fo.flow.ListBlock; import org.apache.fop.fo.flow.ListItem; import org.apache.fop.fo.flow.PageNumber; import org.apache.fop.fo.flow.Table; import org.apache.fop.fo.flow.TableColumn; import org.apache.fop.fo.flow.TableBody; import org.apache.fop.fo.flow.TableCell; import org.apache.fop.fo.flow.TableHeader; import org.apache.fop.fo.flow.TableRow; import org.apache.fop.fo.pagination.Flow; import org.apache.fop.fo.pagination.PageSequence; import org.apache.fop.fo.pagination.SimplePageMaster; import org.apache.fop.fo.properties.Constants; import org.apache.fop.fo.Property; import org.apache.fop.fo.LengthProperty; import org.apache.fop.apps.Document; import org.apache.fop.render.rtf.rtflib.rtfdoc.ITableAttributes; import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfAfterContainer; import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfBeforeContainer; import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfListContainer; import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfTextrunContainer; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfAfter; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfAttributes; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfBefore; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfDocumentArea; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfElement; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfExternalGraphic; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfFile; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfList; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfListItem; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfListItem.RtfListItemLabel; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfSection; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTextrun; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTable; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTableRow; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTableCell; import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfTableContainer; import org.apache.fop.fonts.FontSetup; import org.xml.sax.SAXException; /** * RTF Handler: generates RTF output using the structure events from * the FO Tree sent to this structure handler. * * @author Bertrand Delacretaz * @author Trembicki-Guy, Ed * @author Boris Poudérous * @author Peter Herweg * @author Andreas Putz */ public class RTFHandler extends FOInputHandler { private RtfFile rtfFile; private final OutputStream os; private final Logger log = new ConsoleLogger(); private RtfSection sect; private RtfDocumentArea docArea; private boolean bPrevHeaderSpecified = false;//true, if there has been a //header in any page-sequence private boolean bPrevFooterSpecified = false;//true, if there has been a //footer in any page-sequence private boolean bHeaderSpecified = false; //true, if there is a header //in current page-sequence private boolean bFooterSpecified = false; //true, if there is a footer //in current page-sequence private BuilderContext builderContext = new BuilderContext(null); private static final String ALPHA_WARNING = "WARNING: RTF renderer is " + "veryveryalpha at this time, see class org.apache.fop.rtf.renderer.RTFHandler"; /** * Creates a new RTF structure handler. * @param doc the Document for which this RTFHandler is processing * @param os OutputStream to write to */ public RTFHandler(Document doc, OutputStream os) { super(doc); this.os = os; FontSetup.setup(doc, null); log.warn(ALPHA_WARNING); } /** * @see org.apache.fop.fo.FOInputHandler#startDocument() */ public void startDocument() throws SAXException { // TODO sections should be created try { rtfFile = new RtfFile(new OutputStreamWriter(os)); docArea = rtfFile.startDocumentArea(); } catch (IOException ioe) { // TODO could we throw Exception in all FOInputHandler events? throw new SAXException(ioe); } } /** * @see org.apache.fop.fo.FOInputHandler#endDocument() */ public void endDocument() throws SAXException { try { rtfFile.flush(); } catch (IOException ioe) { // TODO could we throw Exception in all FOInputHandler events? throw new SAXException(ioe); } } /** * @see org.apache.fop.fo.FOInputHandler */ public void startPageSequence(PageSequence pageSeq) { try { sect = docArea.newSection(); //read page size and margins, if specified Property prop; if ((prop = pageSeq.properties.get("master-reference")) != null) { String reference = prop.getString(); SimplePageMaster pagemaster = pageSeq.getLayoutMasterSet().getSimplePageMaster(reference); //only simple-page-master supported, so pagemaster may be null if (pagemaster != null) { sect.getRtfAttributes().set( PageAttributesConverter.convertPageAttributes( pagemaster.properties, null)); } } builderContext.pushContainer(sect); bHeaderSpecified = false; bFooterSpecified = false; } catch (IOException ioe) { // TODO could we throw Exception in all FOInputHandler events? log.error("startPageSequence: " + ioe.getMessage()); //TODO throw new FOPException(ioe); } } /** * @see org.apache.fop.fo.FOInputHandler#endPageSequence(PageSequence) */ public void endPageSequence(PageSequence pageSeq) throws FOPException { builderContext.popContainer(); } /** * @see org.apache.fop.fo.FOInputHandler#startFlow(Flow) */ public void startFlow(Flow fl) { try { if (fl.getFlowName().equals("xsl-region-body")) { // if there is no header in current page-sequence but there has been // a header in a previous page-sequence, insert an empty header. if (bPrevHeaderSpecified && !bHeaderSpecified) { RtfAttributes attr = new RtfAttributes(); attr.set(RtfBefore.HEADER); final IRtfBeforeContainer contBefore = (IRtfBeforeContainer)builderContext.getContainer (IRtfBeforeContainer.class, true, this); contBefore.newBefore(attr); } // if there is no footer in current page-sequence but there has been // a footer in a previous page-sequence, insert an empty footer. if (bPrevFooterSpecified && !bFooterSpecified) { RtfAttributes attr = new RtfAttributes(); attr.set(RtfAfter.FOOTER); final IRtfAfterContainer contAfter = (IRtfAfterContainer)builderContext.getContainer (IRtfAfterContainer.class, true, this); contAfter.newAfter(attr); } } else if (fl.getFlowName().equals("xsl-region-before")) { bHeaderSpecified = true; bPrevHeaderSpecified = true; final IRtfBeforeContainer c = (IRtfBeforeContainer)builderContext.getContainer( IRtfBeforeContainer.class, true, this); RtfAttributes beforeAttributes = ((RtfElement)c).getRtfAttributes(); if (beforeAttributes == null) { beforeAttributes = new RtfAttributes(); } beforeAttributes.set(RtfBefore.HEADER); RtfBefore before = c.newBefore(beforeAttributes); builderContext.pushContainer(before); } else if (fl.getFlowName().equals("xsl-region-after")) { bFooterSpecified = true; bPrevFooterSpecified = true; final IRtfAfterContainer c = (IRtfAfterContainer)builderContext.getContainer( IRtfAfterContainer.class, true, this); RtfAttributes afterAttributes = ((RtfElement)c).getRtfAttributes(); if (afterAttributes == null) { afterAttributes = new RtfAttributes(); } afterAttributes.set(RtfAfter.FOOTER); RtfAfter after = c.newAfter(afterAttributes); builderContext.pushContainer(after); } } catch (IOException ioe) { log.error("startFlow: " + ioe.getMessage()); throw new Error(ioe.getMessage()); } catch (Exception e) { log.error("startFlow: " + e.getMessage()); throw new Error(e.getMessage()); } } /** * @see org.apache.fop.fo.FOInputHandler#endFlow(Flow) */ public void endFlow(Flow fl) { try { if (fl.getFlowName().equals("xsl-region-body")) { //just do nothing } else if (fl.getFlowName().equals("xsl-region-before")) { builderContext.popContainer(); } else if (fl.getFlowName().equals("xsl-region-after")) { builderContext.popContainer(); } } catch (Exception e) { log.error("endFlow: " + e.getMessage()); throw new Error(e.getMessage()); } } /** * @see org.apache.fop.fo.FOInputHandler#startBlock(Block) */ public void startBlock(Block bl) { try { RtfAttributes rtfAttr = TextAttributesConverter.convertAttributes(bl.properties, null); IRtfTextrunContainer container = (IRtfTextrunContainer)builderContext.getContainer( IRtfTextrunContainer.class, true, this); RtfTextrun textrun = container.getTextrun(); textrun.addParagraphBreak(); textrun.pushAttributes(rtfAttr); } catch (IOException ioe) { // TODO could we throw Exception in all FOInputHandler events? log.error("startBlock: " + ioe.getMessage()); throw new Error("IOException: " + ioe); } catch (Exception e) { log.error("startBlock: " + e.getMessage()); throw new Error("Exception: " + e); } } /** * @see org.apache.fop.fo.FOInputHandler#endBlock(Block) */ public void endBlock(Block bl) { try { IRtfTextrunContainer container = (IRtfTextrunContainer)builderContext.getContainer( IRtfTextrunContainer.class, true, this); RtfTextrun textrun = container.getTextrun(); textrun.addParagraphBreak(); textrun.popAttributes(); } catch (IOException ioe) { log.error("startBlock:" + ioe.getMessage()); throw new Error(ioe.getMessage()); } catch (Exception e) { log.error("startBlock:" + e.getMessage()); throw new Error(e.getMessage()); } } /** * @see org.apache.fop.fo.FOInputHandler#startTable(Table) */ public void startTable(Table tbl) { // create an RtfTable in the current table container TableContext tableContext = new TableContext(builderContext); try { RtfAttributes atts = TableAttributesConverter.convertTableAttributes(tbl.properties); final IRtfTableContainer tc = (IRtfTableContainer)builderContext.getContainer( IRtfTableContainer.class, true, null); builderContext.pushContainer(tc.newTable(atts, tableContext)); } catch (Exception e) { log.error("startTable:" + e.getMessage()); throw new Error(e.getMessage()); } builderContext.pushTableContext(tableContext); } /** * @see org.apache.fop.fo.FOInputHandler#endTable(Table) */ public void endTable(Table tbl) { builderContext.popTableContext(); builderContext.popContainer(); } /** * * @param tc TableColumn that is starting; */ public void startColumn(TableColumn tc) { try { Integer iWidth = new Integer(tc.getColumnWidth() / 1000); builderContext.getTableContext().setNextColumnWidth(iWidth.toString() + "pt"); builderContext.getTableContext().setNextColumnRowSpanning(new Integer(0), null); } catch (Exception e) { log.error("startColumn: " + e.getMessage()); throw new Error(e.getMessage()); } } /** * * @param tc TableColumn that is ending; */ public void endColumn(TableColumn tc) { } /** * @see org.apache.fop.fo.FOInputHandler#startHeader(TableBody) */ public void startHeader(TableBody th) { } /** * @see org.apache.fop.fo.FOInputHandler#endHeader(TableBody) */ public void endHeader(TableBody th) { } /** * @see org.apache.fop.fo.FOInputHandler#startFooter(TableBody) */ public void startFooter(TableBody tf) { } /** * @see org.apache.fop.fo.FOInputHandler#endFooter(TableBody) */ public void endFooter(TableBody tf) { } /** * * @param inl Inline that is starting. */ public void startInline(Inline inl) { try { RtfAttributes rtfAttr = TextAttributesConverter.convertCharacterAttributes(inl.properties, null); IRtfTextrunContainer container = (IRtfTextrunContainer)builderContext.getContainer( IRtfTextrunContainer.class, true, this); RtfTextrun textrun = container.getTextrun(); textrun.pushAttributes(rtfAttr); } catch (IOException ioe) { log.error("startInline:" + ioe.getMessage()); throw new Error(ioe.getMessage()); } catch (FOPException fe) { log.error("startInline:" + fe.getMessage()); throw new Error(fe.getMessage()); } catch (Exception e) { log.error("startInline:" + e.getMessage()); throw new Error(e.getMessage()); } } /** * * @param inl Inline that is ending. */ public void endInline(Inline inl) { try { IRtfTextrunContainer container = (IRtfTextrunContainer)builderContext.getContainer( IRtfTextrunContainer.class, true, this); RtfTextrun textrun = container.getTextrun(); textrun.popAttributes(); } catch (IOException ioe) { log.error("startInline:" + ioe.getMessage()); throw new Error(ioe.getMessage()); } catch (Exception e) { log.error("startInline:" + e.getMessage()); throw new Error(e.getMessage()); } } /** * @see org.apache.fop.fo.FOInputHandler#startBody(TableBody) */ public void startBody(TableBody tb) { try { RtfAttributes atts = TableAttributesConverter.convertRowAttributes (tb.properties, null); RtfTable tbl = (RtfTable)builderContext.getContainer(RtfTable.class, true, this); tbl.setHeaderAttribs(atts); } catch (Exception e) { log.error("startBody: " + e.getMessage()); throw new Error(e.getMessage()); } } /** * @see org.apache.fop.fo.FOInputHandler#endBody(TableBody) */ public void endBody(TableBody tb) { try { RtfTable tbl = (RtfTable)builderContext.getContainer(RtfTable.class, true, this); tbl.setHeaderAttribs(null); } catch (Exception e) { log.error("endBody: " + e.getMessage()); throw new Error(e.getMessage()); } } /** * @see org.apache.fop.fo.FOInputHandler#startRow(TableRow) */ public void startRow(TableRow tr) { try { // create an RtfTableRow in the current RtfTable final RtfTable tbl = (RtfTable)builderContext.getContainer(RtfTable.class, true, null); RtfAttributes atts = TableAttributesConverter.convertRowAttributes(tr.properties, tbl.getHeaderAttribs()); if (tr.getParent() instanceof TableHeader) { atts.set(ITableAttributes.ATTR_HEADER); } builderContext.pushContainer(tbl.newTableRow(atts)); // reset column iteration index to correctly access column widths builderContext.getTableContext().selectFirstColumn(); } catch (Exception e) { log.error("startRow: " + e.getMessage()); throw new Error(e.getMessage()); } } /** * @see org.apache.fop.fo.FOInputHandler#endRow(TableRow) */ public void endRow(TableRow tr) { builderContext.popContainer(); builderContext.getTableContext().decreaseRowSpannings(); } /** * @see org.apache.fop.fo.FOInputHandler#startCell(TableCell) */ public void startCell(TableCell tc) { try { TableContext tctx = builderContext.getTableContext(); final RtfTableRow row = (RtfTableRow)builderContext.getContainer(RtfTableRow.class, true, null); //while the current column is in row-spanning, act as if //a vertical merged cell would have been specified. while (tctx.getNumberOfColumns() > tctx.getColumnIndex() && tctx.getColumnRowSpanningNumber().intValue() > 0) { row.newTableCellMergedVertically((int)tctx.getColumnWidth(), tctx.getColumnRowSpanningAttrs()); tctx.selectNextColumn(); } //get the width of the currently started cell float width = tctx.getColumnWidth(); // create an RtfTableCell in the current RtfTableRow RtfAttributes atts = TableAttributesConverter.convertCellAttributes(tc.properties); RtfTableCell cell = row.newTableCell((int)width, atts); //process number-rows-spanned attribute Property p = null; if ((p = tc.properties.get("number-rows-spanned")) != null) { // Start vertical merge cell.setVMerge(RtfTableCell.MERGE_START); // set the number of rows spanned tctx.setCurrentColumnRowSpanning(new Integer(p.getNumber().intValue()), cell.getRtfAttributes()); } else { tctx.setCurrentColumnRowSpanning(new Integer(1), null); } builderContext.pushContainer(cell); } catch (Exception e) { log.error("startCell: " + e.getMessage()); throw new Error(e.getMessage()); } } /** * @see org.apache.fop.fo.FOInputHandler#endCell(TableCell) */ public void endCell(TableCell tc) { builderContext.popContainer(); builderContext.getTableContext().selectNextColumn(); } // Lists /** * @see org.apache.fop.fo.FOInputHandler#startList(ListBlock) */ public void startList(ListBlock lb) { try { // create an RtfList in the current list container final IRtfListContainer c = (IRtfListContainer)builderContext.getContainer( IRtfListContainer.class, true, this); final RtfList newList = c.newList( ListAttributesConverter.convertAttributes(lb.properties)); builderContext.pushContainer(newList); } catch (IOException ioe) { log.error("startList: " + ioe.getMessage()); throw new Error(ioe.getMessage()); } catch (FOPException fe) { log.error("startList: " + fe.getMessage()); throw new Error(fe.getMessage()); } catch (Exception e) { log.error("startList: " + e.getMessage()); throw new Error(e.getMessage()); } } /** * @see org.apache.fop.fo.FOInputHandler#endList(ListBlock) */ public void endList(ListBlock lb) { builderContext.popContainer(); } /** * @see org.apache.fop.fo.FOInputHandler#startListItem(ListItem) */ public void startListItem(ListItem li) { // create an RtfListItem in the current RtfList try { final RtfList list = (RtfList)builderContext.getContainer( RtfList.class, true, this); builderContext.pushContainer(list.newListItem()); } catch (IOException ioe) { log.error("startList: " + ioe.getMessage()); throw new Error(ioe.getMessage()); } catch (FOPException fe) { log.error("startList: " + fe.getMessage()); throw new Error(fe.getMessage()); } catch (Exception e) { log.error("startList: " + e.getMessage()); throw new Error(e.getMessage()); } } /** * @see org.apache.fop.fo.FOInputHandler#endListItem(ListItem) */ public void endListItem(ListItem li) { builderContext.popContainer(); } /** * @see org.apache.fop.fo.FOInputHandler#startListLabel() */ public void startListLabel() { try { RtfListItem item = (RtfListItem)builderContext.getContainer(RtfListItem.class, true, this); RtfListItemLabel label = item.new RtfListItemLabel(item); builderContext.pushContainer(label); } catch (IOException ioe) { log.error("startPageNumber:" + ioe.getMessage()); throw new Error(ioe.getMessage()); } catch (Exception e) { log.error("startPageNumber: " + e.getMessage()); throw new Error(e.getMessage()); } } /** * @see org.apache.fop.fo.FOInputHandler#endListLabel() */ public void endListLabel() { builderContext.popContainer(); } /** * @see org.apache.fop.fo.FOInputHandler#startListBody() */ public void startListBody() { } /** * @see org.apache.fop.fo.FOInputHandler#endListBody() */ public void endListBody() { } // Static Regions /** * @see org.apache.fop.fo.FOInputHandler#startStatic() */ public void startStatic() { } /** * @see org.apache.fop.fo.FOInputHandler#endStatic() */ public void endStatic() { } /** * @see org.apache.fop.fo.FOInputHandler#startMarkup() */ public void startMarkup() { } /** * @see org.apache.fop.fo.FOInputHandler#endMarkup() */ public void endMarkup() { } /** * @see org.apache.fop.fo.FOInputHandler#startLink() */ public void startLink() { } /** * @see org.apache.fop.fo.FOInputHandler#endLink() */ public void endLink() { } /** * @see org.apache.fop.fo.FOInputHandler#image(ExternalGraphic) */ public void image(ExternalGraphic eg) { try { final IRtfTextrunContainer c = (IRtfTextrunContainer)builderContext.getContainer( IRtfTextrunContainer.class, true, this); final RtfExternalGraphic newGraphic = c.getTextrun().newImage(); Property p = null; //get source file if ((p = eg.properties.get("src")) != null) { newGraphic.setURL (p.getString()); } else { log.error("The attribute 'src' of is required."); return; } //get scaling if ((p = eg.properties.get("scaling")) != null) { EnumProperty e = (EnumProperty)p; if (p.getEnum() == Constants.UNIFORM) { newGraphic.setScaling ("uniform"); } } //get width if ((p = eg.properties.get("width")) != null) { LengthProperty lengthProp = (LengthProperty)p; if (lengthProp.getLength() instanceof FixedLength) { Float f = new Float(lengthProp.getLength().getValue() / 1000f); String sValue = f.toString() + "pt"; newGraphic.setWidth(sValue); } } //get height if ((p = eg.properties.get("height")) != null) { LengthProperty lengthProp = (LengthProperty)p; if (lengthProp.getLength() instanceof FixedLength) { Float f = new Float(lengthProp.getLength().getValue() / 1000f); String sValue = f.toString() + "pt"; newGraphic.setHeight(sValue); } } //TODO: make this configurable: // int compression = m_context.m_options.getRtfExternalGraphicCompressionRate (); int compression = 0; if (compression != 0) { if (!newGraphic.setCompressionRate(compression)) { log.warn("The compression rate " + compression + " is invalid. The value has to be between 1 and 100 %."); } } } catch (Exception e) { log.error("image: " + e.getMessage()); } } /** * @see org.apache.fop.fo.FOInputHandler#pageRef() */ public void pageRef() { } /** * @see org.apache.fop.fo.FOInputHandler#foreignObject(InstreamForeignObject) */ public void foreignObject(InstreamForeignObject ifo) { } /** * @see org.apache.fop.fo.FOInputHandler#footnote() */ public void footnote() { } /** * @see org.apache.fop.fo.FOInputHandler#leader(Leader) */ public void leader(Leader l) { } /** * @see org.apache.fop.fo.FOInputHandler#characters(char[], int, int) */ public void characters(char[] data, int start, int length) { try { IRtfTextrunContainer container = (IRtfTextrunContainer)builderContext.getContainer( IRtfTextrunContainer.class, true, this); RtfTextrun textrun = container.getTextrun(); textrun.addString(new String(data, start, length)); } catch (IOException ioe) { // FIXME could we throw Exception in all FOInputHandler events? log.error("characters: " + ioe.getMessage()); throw new Error(ioe.getMessage()); } catch (Exception e) { log.error("characters:" + e.getMessage()); throw new Error(e.getMessage()); } } /** * * @param pagenum PageNumber that is starting. */ public void startPageNumber(PageNumber pagenum) { try { RtfAttributes rtfAttr = TextAttributesConverter.convertCharacterAttributes( pagenum.properties, null); IRtfTextrunContainer container = (IRtfTextrunContainer)builderContext.getContainer( IRtfTextrunContainer.class, true, this); RtfTextrun textrun = container.getTextrun(); textrun.addPageNumber(rtfAttr); } catch (IOException ioe) { log.error("startPageNumber:" + ioe.getMessage()); throw new Error(ioe.getMessage()); } catch (Exception e) { log.error("startPageNumber: " + e.getMessage()); throw new Error(e.getMessage()); } } /** * * @param pagenum PageNumber that is ending. */ public void endPageNumber(PageNumber pagenum) { } }