org.apache.fop.render.rtf.RTFHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.apache.fop Show documentation
Show all versions of org.apache.fop Show documentation
The core maven build properties
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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: RTFHandler.java 1896753 2022-01-06 14:18:11Z ssteiner $ */
package org.apache.fop.render.rtf;
// Java
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.geom.Point2D;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Iterator;
import java.util.Map;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageException;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageManager;
import org.apache.xmlgraphics.image.loader.ImageSessionContext;
import org.apache.xmlgraphics.image.loader.ImageSize;
import org.apache.xmlgraphics.image.loader.impl.ImageRawStream;
import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
import org.apache.xmlgraphics.image.loader.util.ImageUtil;
import org.apache.fop.ResourceEventProducer;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.datatypes.LengthBase;
import org.apache.fop.datatypes.PercentBaseContext;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FOEventHandler;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FOText;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.XMLObj;
import org.apache.fop.fo.flow.AbstractGraphics;
import org.apache.fop.fo.flow.BasicLink;
import org.apache.fop.fo.flow.Block;
import org.apache.fop.fo.flow.BlockContainer;
import org.apache.fop.fo.flow.Character;
import org.apache.fop.fo.flow.ExternalGraphic;
import org.apache.fop.fo.flow.Footnote;
import org.apache.fop.fo.flow.FootnoteBody;
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.ListItemBody;
import org.apache.fop.fo.flow.ListItemLabel;
import org.apache.fop.fo.flow.PageNumber;
import org.apache.fop.fo.flow.PageNumberCitation;
import org.apache.fop.fo.flow.PageNumberCitationLast;
import org.apache.fop.fo.flow.table.Table;
import org.apache.fop.fo.flow.table.TableBody;
import org.apache.fop.fo.flow.table.TableCell;
import org.apache.fop.fo.flow.table.TableColumn;
import org.apache.fop.fo.flow.table.TableFooter;
import org.apache.fop.fo.flow.table.TableHeader;
import org.apache.fop.fo.flow.table.TablePart;
import org.apache.fop.fo.flow.table.TableRow;
import org.apache.fop.fo.pagination.Flow;
import org.apache.fop.fo.pagination.PageSequence;
import org.apache.fop.fo.pagination.PageSequenceMaster;
import org.apache.fop.fo.pagination.Region;
import org.apache.fop.fo.pagination.SimplePageMaster;
import org.apache.fop.fo.pagination.StaticContent;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.EnumLength;
import org.apache.fop.fonts.FontSetup;
import org.apache.fop.layoutmgr.inline.ImageLayout;
import org.apache.fop.layoutmgr.table.ColumnSetup;
import org.apache.fop.render.RendererEventProducer;
import org.apache.fop.render.rtf.rtflib.exceptions.RtfException;
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.IRtfTableContainer;
import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfTextrunContainer;
import org.apache.fop.render.rtf.rtflib.rtfdoc.ITableAttributes;
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.RtfFootnote;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfHyperLink;
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.RtfPage;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfParagraphBreak;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfSection;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTable;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTableCell;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTableRow;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTextrun;
import org.apache.fop.render.rtf.rtflib.tools.BuilderContext;
import org.apache.fop.render.rtf.rtflib.tools.PercentContext;
import org.apache.fop.render.rtf.rtflib.tools.TableContext;
/**
* RTF Handler: generates RTF output using the structure events from
* the FO Tree sent to this structure handler.
*/
public class RTFHandler extends FOEventHandler {
private RtfFile rtfFile;
private final OutputStream os;
private static Log log = LogFactory.getLog(RTFHandler.class);
private RtfSection sect;
private RtfDocumentArea docArea;
private boolean bDefer; //true, if each called handler shall be
//processed at later time.
private boolean bPrevHeaderSpecified; //true, if there has been a
//header in any page-sequence
private boolean bPrevFooterSpecified; //true, if there has been a
//footer in any page-sequence
private boolean bHeaderSpecified; //true, if there is a header
//in current page-sequence
private boolean bFooterSpecified; //true, if there is a footer
//in current page-sequence
private BuilderContext builderContext = new BuilderContext(null);
private SimplePageMaster pagemaster;
private int nestedTableDepth = 1;
private PercentContext percentManager = new PercentContext();
/**
* Creates a new RTF structure handler.
* @param userAgent the FOUserAgent for this process
* @param os OutputStream to write to
*/
public RTFHandler(FOUserAgent userAgent, OutputStream os) {
super(userAgent);
this.os = os;
bDefer = true;
boolean base14Kerning = false;
FontSetup.setup(fontInfo, null, userAgent.getResourceResolver(), base14Kerning);
}
/**
* Central exception handler for I/O exceptions.
* @param ioe IOException to handle
*/
protected void handleIOTrouble(IOException ioe) {
RendererEventProducer eventProducer = RendererEventProducer.Provider.get(
getUserAgent().getEventBroadcaster());
eventProducer.ioError(this, ioe);
}
/** {@inheritDoc} */
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 FOEventHandler events?
throw new SAXException(ioe);
}
}
/** {@inheritDoc} */
public void endDocument() throws SAXException {
try {
rtfFile.flush();
} catch (IOException ioe) {
// TODO could we throw Exception in all FOEventHandler events?
throw new SAXException(ioe);
}
}
/** {@inheritDoc} */
public void startPageSequence(PageSequence pageSeq) {
try {
//This is needed for region handling
if (this.pagemaster == null) {
String reference = pageSeq.getMasterReference();
this.pagemaster
= pageSeq.getRoot().getLayoutMasterSet().getSimplePageMaster(reference);
if (this.pagemaster == null) {
RTFEventProducer eventProducer = RTFEventProducer.Provider.get(
getUserAgent().getEventBroadcaster());
eventProducer.onlySPMSupported(this, reference, pageSeq.getLocator());
PageSequenceMaster master
= pageSeq.getRoot().getLayoutMasterSet().getPageSequenceMaster(reference);
if (pageSeq.getMainFlow() != null) {
this.pagemaster = master.getNextSimplePageMaster(false, false, false,
false, pageSeq.getMainFlow().getFlowName(), false);
}
}
}
if (bDefer) {
return;
}
sect = docArea.newSection();
//read page size and margins, if specified
//only simple-page-master supported, so pagemaster may be null
if (pagemaster != null) {
sect.getRtfAttributes().set(
PageAttributesConverter.convertPageAttributes(
pagemaster));
} else {
RTFEventProducer eventProducer = RTFEventProducer.Provider.get(
getUserAgent().getEventBroadcaster());
eventProducer.noSPMFound(this, pageSeq.getLocator());
}
builderContext.pushContainer(sect);
//Calculate usable page width for this flow
int useAblePageWidth = pagemaster.getPageWidth().getValue()
- pagemaster.getCommonMarginBlock().marginLeft.getValue()
- pagemaster.getCommonMarginBlock().marginRight.getValue()
- sect.getRtfAttributes().getValueAsInteger(RtfPage.MARGIN_LEFT)
- sect.getRtfAttributes().getValueAsInteger(RtfPage.MARGIN_RIGHT);
percentManager.setDimension(pageSeq, useAblePageWidth);
bHeaderSpecified = false;
bFooterSpecified = false;
} catch (IOException ioe) {
handleIOTrouble(ioe);
}
}
/** {@inheritDoc} */
public void endPageSequence(PageSequence pageSeq) {
if (bDefer) {
//If endBlock was called while SAX parsing, and the passed FO is Block
//nested within another Block, stop deferring.
//Now process all deferred FOs.
bDefer = false;
recurseFONode(pageSeq);
this.pagemaster = null;
bDefer = true;
return;
} else {
builderContext.popContainer(RtfSection.class, this);
this.pagemaster = null;
}
}
/** {@inheritDoc} */
public void startFlow(Flow fl) {
if (bDefer) {
return;
}
try {
log.debug("starting flow: " + fl.getFlowName());
boolean handled = false;
Region regionBody = pagemaster.getRegion(Constants.FO_REGION_BODY);
Region regionBefore = pagemaster.getRegion(Constants.FO_REGION_BEFORE);
Region regionAfter = pagemaster.getRegion(Constants.FO_REGION_AFTER);
if (fl.getFlowName().equals(regionBody.getRegionName())) {
// 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);
}
handled = true;
} else if (regionBefore != null
&& fl.getFlowName().equals(regionBefore.getRegionName())) {
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);
handled = true;
} else if (regionAfter != null
&& fl.getFlowName().equals(regionAfter.getRegionName())) {
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);
handled = true;
}
if (!handled) {
log.warn("A " + fl.getLocalName() + " has been skipped: " + fl.getFlowName());
}
} catch (IOException ioe) {
handleIOTrouble(ioe);
} catch (Exception e) {
log.error("startFlow: " + e.getMessage());
throw new RuntimeException(e.getMessage());
}
}
/** {@inheritDoc} */
public void endFlow(Flow fl) {
if (bDefer) {
return;
}
try {
Region regionBody = pagemaster.getRegion(Constants.FO_REGION_BODY);
Region regionBefore = pagemaster.getRegion(Constants.FO_REGION_BEFORE);
Region regionAfter = pagemaster.getRegion(Constants.FO_REGION_AFTER);
if (fl.getFlowName().equals(regionBody.getRegionName())) {
//just do nothing
} else if (regionBefore != null
&& fl.getFlowName().equals(regionBefore.getRegionName())) {
builderContext.popContainer(RtfBefore.class, this);
} else if (regionAfter != null
&& fl.getFlowName().equals(regionAfter.getRegionName())) {
builderContext.popContainer(RtfAfter.class, this);
}
} catch (Exception e) {
log.error("endFlow: " + e.getMessage());
throw new RuntimeException(e.getMessage());
}
}
/** {@inheritDoc} */
public void startBlock(Block bl) {
if (bDefer) {
return;
}
try {
RtfAttributes rtfAttr
= TextAttributesConverter.convertAttributes(bl);
IRtfTextrunContainer container
= (IRtfTextrunContainer)builderContext.getContainer(
IRtfTextrunContainer.class,
true, this);
RtfTextrun textrun = container.getTextrun();
textrun.addParagraphBreak();
textrun.pushBlockAttributes(rtfAttr);
textrun.addBookmark(bl.getId());
} catch (IOException ioe) {
handleIOTrouble(ioe);
} catch (Exception e) {
log.error("startBlock: " + e.getMessage());
throw new RuntimeException("Exception: " + e);
}
}
/** {@inheritDoc} */
public void endBlock(Block bl) {
if (bDefer) {
return;
}
try {
IRtfTextrunContainer container
= (IRtfTextrunContainer)builderContext.getContainer(
IRtfTextrunContainer.class,
true, this);
RtfTextrun textrun = container.getTextrun();
RtfParagraphBreak par = textrun.addParagraphBreak();
RtfTableCell cellParent = (RtfTableCell)textrun.getParentOfClass(RtfTableCell.class);
if (cellParent != null && par != null) {
cellParent.setLastParagraph(par);
}
int breakValue = toRtfBreakValue(bl.getBreakAfter());
textrun.popBlockAttributes(breakValue);
} catch (IOException ioe) {
handleIOTrouble(ioe);
} catch (Exception e) {
log.error("startBlock:" + e.getMessage());
throw new RuntimeException(e.getMessage());
}
}
/** {@inheritDoc} */
public void startBlockContainer(BlockContainer blc) {
if (bDefer) {
return;
}
try {
RtfAttributes rtfAttr
= TextAttributesConverter.convertBlockContainerAttributes(blc);
IRtfTextrunContainer container
= (IRtfTextrunContainer)builderContext.getContainer(
IRtfTextrunContainer.class,
true, this);
RtfTextrun textrun = container.getTextrun();
textrun.addParagraphBreak();
textrun.pushBlockAttributes(rtfAttr);
} catch (IOException ioe) {
handleIOTrouble(ioe);
} catch (Exception e) {
log.error("startBlock: " + e.getMessage());
throw new RuntimeException("Exception: " + e);
}
}
/** {@inheritDoc} */
public void endBlockContainer(BlockContainer bl) {
if (bDefer) {
return;
}
try {
IRtfTextrunContainer container
= (IRtfTextrunContainer)builderContext.getContainer(
IRtfTextrunContainer.class,
true, this);
RtfTextrun textrun = container.getTextrun();
textrun.addParagraphBreak();
int breakValue = toRtfBreakValue(bl.getBreakAfter());
textrun.popBlockAttributes(breakValue);
} catch (IOException ioe) {
handleIOTrouble(ioe);
} catch (Exception e) {
log.error("startBlock:" + e.getMessage());
throw new RuntimeException(e.getMessage());
}
}
private int toRtfBreakValue(int foBreakValue) {
switch (foBreakValue) {
case Constants.EN_PAGE:
return RtfTextrun.BREAK_PAGE;
case Constants.EN_EVEN_PAGE:
return RtfTextrun.BREAK_EVEN_PAGE;
case Constants.EN_ODD_PAGE:
return RtfTextrun.BREAK_ODD_PAGE;
case Constants.EN_COLUMN:
return RtfTextrun.BREAK_COLUMN;
default:
return RtfTextrun.BREAK_NONE;
}
}
/** {@inheritDoc} */
public void startTable(Table tbl) {
if (bDefer) {
return;
}
// create an RtfTable in the current table container
TableContext tableContext = new TableContext(builderContext);
try {
final IRtfTableContainer tc
= (IRtfTableContainer)builderContext.getContainer(
IRtfTableContainer.class, true, null);
RtfAttributes atts
= TableAttributesConverter.convertTableAttributes(tbl);
RtfTable table = tc.newTable(atts, tableContext);
table.setNestedTableDepth(nestedTableDepth);
nestedTableDepth++;
CommonBorderPaddingBackground border = tbl.getCommonBorderPaddingBackground();
RtfAttributes borderAttributes = new RtfAttributes();
BorderAttributesConverter.makeBorder(border, CommonBorderPaddingBackground.BEFORE,
borderAttributes, ITableAttributes.CELL_BORDER_TOP);
BorderAttributesConverter.makeBorder(border, CommonBorderPaddingBackground.AFTER,
borderAttributes, ITableAttributes.CELL_BORDER_BOTTOM);
BorderAttributesConverter.makeBorder(border, CommonBorderPaddingBackground.START,
borderAttributes, ITableAttributes.CELL_BORDER_LEFT);
BorderAttributesConverter.makeBorder(border, CommonBorderPaddingBackground.END,
borderAttributes, ITableAttributes.CELL_BORDER_RIGHT);
table.setBorderAttributes(borderAttributes);
builderContext.pushContainer(table);
} catch (IOException ioe) {
handleIOTrouble(ioe);
} catch (Exception e) {
log.error("startTable:" + e.getMessage());
throw new RuntimeException(e.getMessage());
}
builderContext.pushTableContext(tableContext);
}
/** {@inheritDoc} */
public void endTable(Table tbl) {
if (bDefer) {
return;
}
nestedTableDepth--;
builderContext.popTableContext();
builderContext.popContainer(RtfTable.class, this);
}
/** {@inheritDoc} */
public void startColumn(TableColumn tc) {
if (bDefer) {
return;
}
try {
int iWidth = tc.getColumnWidth().getValue(percentManager);
percentManager.setDimension(tc, iWidth);
//convert to twips
Float width = FoUnitsConverter.getInstance().convertMptToTwips(iWidth);
builderContext.getTableContext().setNextColumnWidth(width);
builderContext.getTableContext().setNextColumnRowSpanning(
0, null);
builderContext.getTableContext().setNextFirstSpanningCol(false);
} catch (Exception e) {
log.error("startColumn: " + e.getMessage());
throw new RuntimeException(e.getMessage());
}
}
/** {@inheritDoc} */
public void endColumn(TableColumn tc) {
}
/** {@inheritDoc} */
public void startHeader(TableHeader header) {
builderContext.pushPart(header);
startPart(header);
}
/** {@inheritDoc} */
public void endHeader(TableHeader header) {
builderContext.popPart(header.getClass(), this);
endPart(header);
}
/** {@inheritDoc} */
public void startFooter(TableFooter footer) {
builderContext.pushPart(footer);
startPart(footer);
}
/** {@inheritDoc} */
public void endFooter(TableFooter footer) {
builderContext.popPart(footer.getClass(), this);
endPart(footer);
}
/** {@inheritDoc} */
public void startInline(Inline inl) {
if (bDefer) {
return;
}
try {
RtfAttributes rtfAttr
= TextAttributesConverter.convertCharacterAttributes(inl);
IRtfTextrunContainer container
= (IRtfTextrunContainer)builderContext.getContainer(
IRtfTextrunContainer.class, true, this);
RtfTextrun textrun = container.getTextrun();
textrun.pushInlineAttributes(rtfAttr);
textrun.addBookmark(inl.getId());
} catch (IOException ioe) {
handleIOTrouble(ioe);
} catch (FOPException fe) {
log.error("startInline:" + fe.getMessage());
throw new RuntimeException(fe.getMessage());
} catch (Exception e) {
log.error("startInline:" + e.getMessage());
throw new RuntimeException(e.getMessage());
}
}
/** {@inheritDoc} */
public void endInline(Inline inl) {
if (bDefer) {
return;
}
try {
IRtfTextrunContainer container
= (IRtfTextrunContainer)builderContext.getContainer(
IRtfTextrunContainer.class, true, this);
RtfTextrun textrun = container.getTextrun();
textrun.popInlineAttributes();
} catch (IOException ioe) {
handleIOTrouble(ioe);
} catch (Exception e) {
log.error("startInline:" + e.getMessage());
throw new RuntimeException(e.getMessage());
}
}
private void startPart(TablePart part) {
if (bDefer) {
return;
}
try {
RtfAttributes atts = TableAttributesConverter.convertTablePartAttributes(part);
// @SuppressFBWarnings("BC_UNCONFIRMED_CAST_OF_RETURN_VALUE")
RtfTable tbl = (RtfTable)builderContext.getContainer(RtfTable.class, true, this);
tbl.setHeaderAttribs(atts);
} catch (IOException ioe) {
handleIOTrouble(ioe);
} catch (Exception e) {
log.error("startPart: " + e.getMessage());
throw new RuntimeException(e.getMessage());
}
}
private void endPart(TablePart tb) {
if (bDefer) {
return;
}
try {
// @SuppressFBWarnings("BC_UNCONFIRMED_CAST_OF_RETURN_VALUE")
RtfTable tbl = (RtfTable)builderContext.getContainer(RtfTable.class, true, this);
tbl.setHeaderAttribs(null);
} catch (IOException ioe) {
handleIOTrouble(ioe);
} catch (Exception e) {
log.error("endPart: " + e.getMessage());
throw new RuntimeException(e.getMessage());
}
}
/**
* {@inheritDoc}
*/
public void startBody(TableBody body) {
builderContext.pushPart(body);
startPart(body);
}
/** {@inheritDoc} */
public void endBody(TableBody body) {
builderContext.popPart(TableBody.class, this);
endPart(body);
}
/**
* {@inheritDoc}
*/
public void startRow(TableRow tr) {
if (bDefer) {
return;
}
try {
// create an RtfTableRow in the current RtfTable
// @SuppressFBWarnings("BC_UNCONFIRMED_CAST_OF_RETURN_VALUE")
final RtfTable tbl = (RtfTable)builderContext.getContainer(RtfTable.class,
true, null);
RtfAttributes atts = TableAttributesConverter.convertRowAttributes(tr,
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 (IOException ioe) {
handleIOTrouble(ioe);
} catch (Exception e) {
log.error("startRow: " + e.getMessage());
throw new RuntimeException(e.getMessage());
}
}
/** {@inheritDoc} */
public void endRow(TableRow tr) {
if (bDefer) {
return;
}
try {
TableContext tctx = builderContext.getTableContext();
// @SuppressFBWarnings("BC_UNCONFIRMED_CAST_OF_RETURN_VALUE")
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() > 0) {
RtfTableCell vCell = row.newTableCellMergedVertically(
(int)tctx.getColumnWidth(),
tctx.getColumnRowSpanningAttrs());
if (!tctx.getFirstSpanningCol()) {
vCell.setHMerge(RtfTableCell.MERGE_WITH_PREVIOUS);
}
tctx.selectNextColumn();
}
} catch (IOException ioe) {
handleIOTrouble(ioe);
} catch (Exception e) {
log.error("endRow: " + e.getMessage());
throw new RuntimeException(e.getMessage());
}
builderContext.popContainer(RtfTableRow.class, this);
builderContext.getTableContext().decreaseRowSpannings();
}
/** {@inheritDoc} */
public void startCell(TableCell tc) {
if (bDefer) {
return;
}
try {
TableContext tctx = builderContext.getTableContext();
// @SuppressFBWarnings("BC_UNCONFIRMED_CAST_OF_RETURN_VALUE")
final RtfTableRow row = (RtfTableRow)builderContext.getContainer(RtfTableRow.class,
true, null);
int numberRowsSpanned = tc.getNumberRowsSpanned();
int numberColumnsSpanned = tc.getNumberColumnsSpanned();
//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() > 0) {
RtfTableCell vCell = row.newTableCellMergedVertically(
(int)tctx.getColumnWidth(),
tctx.getColumnRowSpanningAttrs());
if (!tctx.getFirstSpanningCol()) {
vCell.setHMerge(RtfTableCell.MERGE_WITH_PREVIOUS);
}
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);
RtfTableCell cell = row.newTableCell((int)width, atts);
//process number-rows-spanned attribute
if (numberRowsSpanned > 1) {
// Start vertical merge
cell.setVMerge(RtfTableCell.MERGE_START);
// set the number of rows spanned
tctx.setCurrentColumnRowSpanning(numberRowsSpanned,
cell.getRtfAttributes());
} else {
tctx.setCurrentColumnRowSpanning(
numberRowsSpanned, null);
}
//process number-columns-spanned attribute
if (numberColumnsSpanned > 0) {
// Get the number of columns spanned
tctx.setCurrentFirstSpanningCol(true);
// We widthdraw one cell because the first cell is already created
// (it's the current cell) !
for (int i = 0; i < numberColumnsSpanned - 1; ++i) {
tctx.selectNextColumn();
//aggregate width for further elements
width += tctx.getColumnWidth();
tctx.setCurrentFirstSpanningCol(false);
RtfTableCell hCell = row.newTableCellMergedHorizontally(
0, null);
if (numberRowsSpanned > 1) {
// Start vertical merge
hCell.setVMerge(RtfTableCell.MERGE_START);
// set the number of rows spanned
tctx.setCurrentColumnRowSpanning(
numberRowsSpanned,
cell.getRtfAttributes());
} else {
tctx.setCurrentColumnRowSpanning(
numberRowsSpanned, cell.getRtfAttributes());
}
}
}
//save width of the cell, convert from twips to mpt
percentManager.setDimension(tc, (int)width * 50);
builderContext.pushContainer(cell);
} catch (IOException ioe) {
handleIOTrouble(ioe);
} catch (Exception e) {
log.error("startCell: " + e.getMessage());
throw new RuntimeException(e.getMessage());
}
}
/** {@inheritDoc} */
public void endCell(TableCell tc) {
if (bDefer) {
return;
}
try {
// @SuppressFBWarnings("BC_UNCONFIRMED_CAST_OF_RETURN_VALUE")
RtfTableCell cell = (RtfTableCell)builderContext.getContainer(RtfTableCell.class, false, this);
cell.finish();
} catch (Exception e) {
log.error("endCell: " + e.getMessage());
throw new RuntimeException(e.getMessage());
}
builderContext.popContainer(RtfTableCell.class, this);
builderContext.getTableContext().selectNextColumn();
}
// Lists
/** {@inheritDoc} */
public void startList(ListBlock lb) {
if (bDefer) {
return;
}
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));
builderContext.pushContainer(newList);
} catch (IOException ioe) {
handleIOTrouble(ioe);
} catch (FOPException fe) {
log.error("startList: " + fe.getMessage());
throw new RuntimeException(fe.getMessage());
} catch (Exception e) {
log.error("startList: " + e.getMessage());
throw new RuntimeException(e.getMessage());
}
}
/** {@inheritDoc} */
public void endList(ListBlock lb) {
if (bDefer) {
return;
}
builderContext.popContainer(RtfList.class, this);
}
/** {@inheritDoc} */
public void startListItem(ListItem li) {
if (bDefer) {
return;
}
// create an RtfListItem in the current RtfList
try {
// @SuppressFBWarnings("BC_UNCONFIRMED_CAST_OF_RETURN_VALUE")
RtfList list = (RtfList)builderContext.getContainer(
RtfList.class, true, this);
/**
* If the current list already contains a list item, then close the
* list and open a new one, so every single list item gets its own
* list. This allows every item to have a different list label.
* If all the items would be in the same list, they had all the
* same label.
*/
//TODO: do this only, if the labels content <> previous labels content
if (list.getChildCount() > 0) {
this.endListBody(null);
this.endList((ListBlock) li.getParent());
this.startList((ListBlock) li.getParent());
this.startListBody(null);
list = (RtfList)builderContext.getContainer(
RtfList.class, true, this);
}
builderContext.pushContainer(list.newListItem());
} catch (IOException ioe) {
handleIOTrouble(ioe);
} catch (Exception e) {
log.error("startList: " + e.getMessage());
throw new RuntimeException(e.getMessage());
}
}
/** {@inheritDoc} */
public void endListItem(ListItem li) {
if (bDefer) {
return;
}
builderContext.popContainer(RtfListItem.class, this);
}
/** {@inheritDoc} */
public void startListLabel(ListItemLabel listItemLabel) {
if (bDefer) {
return;
}
try {
// @SuppressFBWarnings("BC_UNCONFIRMED_CAST_OF_RETURN_VALUE")
RtfListItem item
= (RtfListItem)builderContext.getContainer(RtfListItem.class, true, this);
RtfListItemLabel label = item.new RtfListItemLabel(item);
builderContext.pushContainer(label);
} catch (IOException ioe) {
handleIOTrouble(ioe);
} catch (Exception e) {
log.error("startPageNumber: " + e.getMessage());
throw new RuntimeException(e.getMessage());
}
}
/** {@inheritDoc} */
public void endListLabel(ListItemLabel listItemLabel) {
if (bDefer) {
return;
}
builderContext.popContainer(RtfListItemLabel.class, this);
}
/** {@inheritDoc} */
public void startListBody(ListItemBody listItemBody) {
}
/** {@inheritDoc} */
public void endListBody(ListItemBody listItemBody) {
}
// Static Regions
/** {@inheritDoc} */
public void startStatic(StaticContent staticContent) {
}
/** {@inheritDoc} */
public void endStatic(StaticContent statisContent) {
}
/** {@inheritDoc} */
public void startMarkup() {
}
/** {@inheritDoc} */
public void endMarkup() {
}
/** {@inheritDoc} */
public void startLink(BasicLink basicLink) {
if (bDefer) {
return;
}
try {
IRtfTextrunContainer container
= (IRtfTextrunContainer)builderContext.getContainer(
IRtfTextrunContainer.class, true, this);
RtfTextrun textrun = container.getTextrun();
RtfHyperLink link = textrun.addHyperlink(new RtfAttributes());
if (basicLink.hasExternalDestination()) {
link.setExternalURL(basicLink.getExternalDestination());
} else {
link.setInternalURL(basicLink.getInternalDestination());
}
builderContext.pushContainer(link);
} catch (IOException ioe) {
handleIOTrouble(ioe);
} catch (Exception e) {
log.error("startLink: " + e.getMessage());
throw new RuntimeException(e.getMessage());
}
}
/** {@inheritDoc} */
public void endLink(BasicLink basicLink) {
if (bDefer) {
return;
}
builderContext.popContainer(RtfHyperLink.class, this);
}
/** {@inheritDoc} */
public void image(ExternalGraphic eg) {
if (bDefer) {
return;
}
String uri = eg.getURL();
ImageInfo info = null;
try {
//set image data
FOUserAgent userAgent = eg.getUserAgent();
ImageManager manager = userAgent.getImageManager();
info = manager.getImageInfo(uri, userAgent.getImageSessionContext());
putGraphic(eg, info);
} catch (ImageException ie) {
ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
getUserAgent().getEventBroadcaster());
eventProducer.imageError(this, uri, ie, null);
} catch (FileNotFoundException fe) {
ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
getUserAgent().getEventBroadcaster());
eventProducer.imageNotFound(this, (info != null ? info.toString() : uri), fe, null);
} catch (IOException ioe) {
ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
getUserAgent().getEventBroadcaster());
eventProducer.imageIOError(this, (info != null ? info.toString() : uri), ioe, null);
}
}
/** {@inheritDoc} */
public void endInstreamForeignObject(InstreamForeignObject ifo) {
if (bDefer) {
return;
}
try {
XMLObj child = ifo.getChildXMLObj();
Document doc = child.getDOMDocument();
String ns = child.getNamespaceURI();
ImageInfo info = new ImageInfo(null, null);
// Set the resolution to that of the FOUserAgent
FOUserAgent ua = ifo.getUserAgent();
ImageSize size = new ImageSize();
size.setResolution(ua.getSourceResolution());
// Set the image size to the size of the svg.
Point2D csize = new Point2D.Float(-1, -1);
Point2D intrinsicDimensions = child.getDimension(csize);
if (intrinsicDimensions == null) {
ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
getUserAgent().getEventBroadcaster());
eventProducer.ifoNoIntrinsicSize(this, child.getLocator());
return;
}
size.setSizeInMillipoints(
(int)Math.round(intrinsicDimensions.getX() * 1000),
(int)Math.round(intrinsicDimensions.getY() * 1000));
size.calcPixelsFromSize();
info.setSize(size);
ImageXMLDOM image = new ImageXMLDOM(info, doc, ns);
FOUserAgent userAgent = ifo.getUserAgent();
ImageManager manager = userAgent.getImageManager();
Map hints = ImageUtil.getDefaultHints(ua.getImageSessionContext());
Image converted = manager.convertImage(image, FLAVORS, hints);
putGraphic(ifo, converted);
} catch (ImageException ie) {
ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
getUserAgent().getEventBroadcaster());
eventProducer.imageError(this, null, ie, null);
} catch (IOException ioe) {
ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
getUserAgent().getEventBroadcaster());
eventProducer.imageIOError(this, null, ioe, null);
}
}
private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {
ImageFlavor.RAW_EMF, ImageFlavor.RAW_PNG, ImageFlavor.RAW_JPEG
};
/**
* Puts a graphic/image into the generated RTF file.
* @param abstractGraphic the graphic (external-graphic or instream-foreign-object)
* @param info the image info object
* @throws IOException In case of an I/O error
*/
private void putGraphic(AbstractGraphics abstractGraphic, ImageInfo info)
throws IOException {
try {
FOUserAgent userAgent = abstractGraphic.getUserAgent();
ImageManager manager = userAgent.getImageManager();
ImageSessionContext sessionContext = userAgent.getImageSessionContext();
Map hints = ImageUtil.getDefaultHints(sessionContext);
Image image = manager.getImage(info, FLAVORS, hints, sessionContext);
putGraphic(abstractGraphic, image);
} catch (ImageException ie) {
ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
getUserAgent().getEventBroadcaster());
eventProducer.imageError(this, null, ie, null);
}
}
/**
* Puts a graphic/image into the generated RTF file.
* @param abstractGraphic the graphic (external-graphic or instream-foreign-object)
* @param image the image
* @throws IOException In case of an I/O error
*/
private void putGraphic(AbstractGraphics abstractGraphic, Image image)
throws IOException {
byte[] rawData = null;
final ImageInfo info = image.getInfo();
if (image instanceof ImageRawStream) {
ImageRawStream rawImage = (ImageRawStream)image;
InputStream in = rawImage.createInputStream();
try {
rawData = IOUtils.toByteArray(in);
} finally {
IOUtils.closeQuietly(in);
}
}
if (rawData == null) {
ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
getUserAgent().getEventBroadcaster());
eventProducer.imageWritingError(this, null);
return;
}
//Set up percentage calculations
this.percentManager.setDimension(abstractGraphic);
PercentBaseContext pContext = new PercentBaseContext() {
public int getBaseLength(int lengthBase, FObj fobj) {
switch (lengthBase) {
case LengthBase.IMAGE_INTRINSIC_WIDTH:
return info.getSize().getWidthMpt();
case LengthBase.IMAGE_INTRINSIC_HEIGHT:
return info.getSize().getHeightMpt();
default:
return percentManager.getBaseLength(lengthBase, fobj);
}
}
};
ImageLayout layout = new ImageLayout(abstractGraphic, pContext,
image.getInfo().getSize().getDimensionMpt());
final IRtfTextrunContainer c
= (IRtfTextrunContainer)builderContext.getContainer(
IRtfTextrunContainer.class, true, this);
final RtfExternalGraphic rtfGraphic = c.getTextrun().newImage();
//set URL
if (info.getOriginalURI() != null) {
rtfGraphic.setURL(info.getOriginalURI());
}
rtfGraphic.setImageData(rawData);
FoUnitsConverter converter = FoUnitsConverter.getInstance();
Dimension viewport = layout.getViewportSize();
Rectangle placement = layout.getPlacement();
int cropLeft = Math.round(converter.convertMptToTwips(-placement.x));
int cropTop = Math.round(converter.convertMptToTwips(-placement.y));
int cropRight = Math.round(converter.convertMptToTwips(
-1 * (viewport.width - placement.x - placement.width)));
int cropBottom = Math.round(converter.convertMptToTwips(
-1 * (viewport.height - placement.y - placement.height)));
rtfGraphic.setCropping(cropLeft, cropTop, cropRight, cropBottom);
int width = Math.round(converter.convertMptToTwips(viewport.width));
int height = Math.round(converter.convertMptToTwips(viewport.height));
width += cropLeft + cropRight;
height += cropTop + cropBottom;
rtfGraphic.setWidthTwips(width);
rtfGraphic.setHeightTwips(height);
//TODO: make this configurable:
// int compression = m_context.m_options.getRtfExternalGraphicCompressionRate ();
int compression = 0;
if (compression != 0) {
if (!rtfGraphic.setCompressionRate(compression)) {
log.warn("The compression rate " + compression
+ " is invalid. The value has to be between 1 and 100 %.");
}
}
}
/** {@inheritDoc} */
public void pageRef() {
}
/** {@inheritDoc} */
public void startFootnote(Footnote footnote) {
if (bDefer) {
return;
}
try {
IRtfTextrunContainer container
= (IRtfTextrunContainer)builderContext.getContainer(
IRtfTextrunContainer.class,
true, this);
RtfTextrun textrun = container.getTextrun();
RtfFootnote rtfFootnote = textrun.addFootnote();
builderContext.pushContainer(rtfFootnote);
} catch (IOException ioe) {
handleIOTrouble(ioe);
} catch (Exception e) {
log.error("startFootnote: " + e.getMessage());
throw new RuntimeException("Exception: " + e);
}
}
/** {@inheritDoc} */
public void endFootnote(Footnote footnote) {
if (bDefer) {
return;
}
builderContext.popContainer(RtfFootnote.class, this);
}
/** {@inheritDoc} */
public void startFootnoteBody(FootnoteBody body) {
if (bDefer) {
return;
}
try {
// @SuppressFBWarnings("BC_UNCONFIRMED_CAST_OF_RETURN_VALUE")
RtfFootnote rtfFootnote
= (RtfFootnote)builderContext.getContainer(
RtfFootnote.class,
true, this);
rtfFootnote.startBody();
} catch (IOException ioe) {
handleIOTrouble(ioe);
} catch (Exception e) {
log.error("startFootnoteBody: " + e.getMessage());
throw new RuntimeException("Exception: " + e);
}
}
/** {@inheritDoc} */
public void endFootnoteBody(FootnoteBody body) {
if (bDefer) {
return;
}
try {
// @SuppressFBWarnings("BC_UNCONFIRMED_CAST_OF_RETURN_VALUE")
RtfFootnote rtfFootnote
= (RtfFootnote)builderContext.getContainer(
RtfFootnote.class,
true, this);
rtfFootnote.endBody();
} catch (IOException ioe) {
handleIOTrouble(ioe);
} catch (Exception e) {
log.error("endFootnoteBody: " + e.getMessage());
throw new RuntimeException("Exception: " + e);
}
}
/** {@inheritDoc} */
public void startLeader(Leader l) {
if (bDefer) {
return;
}
try {
percentManager.setDimension(l);
RtfAttributes rtfAttr = TextAttributesConverter.convertLeaderAttributes(
l, percentManager);
IRtfTextrunContainer container
= (IRtfTextrunContainer)builderContext.getContainer(
IRtfTextrunContainer.class, true, this);
RtfTextrun textrun = container.getTextrun();
textrun.addLeader(rtfAttr);
} catch (IOException e) {
log.error("startLeader: " + e.getMessage());
throw new RuntimeException(e.getMessage());
} catch (FOPException e) {
log.error("startLeader: " + e.getMessage());
throw new RuntimeException(e.getMessage());
}
}
/**
* @param text FOText object
* @param characters CharSequence of the characters to process.
*/
public void text(FOText text, CharSequence characters) {
if (bDefer) {
return;
}
try {
IRtfTextrunContainer container
= (IRtfTextrunContainer)builderContext.getContainer(
IRtfTextrunContainer.class, true, this);
RtfTextrun textrun = container.getTextrun();
RtfAttributes rtfAttr
= TextAttributesConverter.convertCharacterAttributes(text);
textrun.pushInlineAttributes(rtfAttr);
textrun.addString(characters.toString());
textrun.popInlineAttributes();
} catch (IOException ioe) {
handleIOTrouble(ioe);
} catch (Exception e) {
log.error("characters:" + e.getMessage());
throw new RuntimeException(e.getMessage());
}
}
/** {@inheritDoc} */
public void startPageNumber(PageNumber pagenum) {
if (bDefer) {
return;
}
try {
RtfAttributes rtfAttr
= TextAttributesConverter.convertCharacterAttributes(
pagenum);
IRtfTextrunContainer container
= (IRtfTextrunContainer)builderContext.getContainer(
IRtfTextrunContainer.class, true, this);
RtfTextrun textrun = container.getTextrun();
textrun.addPageNumber(rtfAttr);
} catch (IOException ioe) {
handleIOTrouble(ioe);
} catch (Exception e) {
log.error("startPageNumber: " + e.getMessage());
throw new RuntimeException(e.getMessage());
}
}
/** {@inheritDoc} */
public void endPageNumber(PageNumber pagenum) {
}
/** {@inheritDoc} */
public void startPageNumberCitation(PageNumberCitation l) {
if (bDefer) {
return;
}
try {
IRtfTextrunContainer container
= (IRtfTextrunContainer)builderContext.getContainer(
IRtfTextrunContainer.class, true, this);
RtfTextrun textrun = container.getTextrun();
textrun.addPageNumberCitation(l.getRefId());
} catch (Exception e) {
log.error("startPageNumberCitation: " + e.getMessage());
throw new RuntimeException(e.getMessage());
}
}
/** {@inheritDoc} */
public void startPageNumberCitationLast(PageNumberCitationLast l) {
if (bDefer) {
return;
}
try {
IRtfTextrunContainer container
= (IRtfTextrunContainer)builderContext.getContainer(
IRtfTextrunContainer.class, true, this);
RtfTextrun textrun = container.getTextrun();
textrun.addPageNumberCitation(l.getRefId());
} catch (RtfException e) {
log.error("startPageNumberCitationLast: " + e.getMessage());
throw new RuntimeException(e.getMessage());
} catch (IOException e) {
log.error("startPageNumberCitationLast: " + e.getMessage());
throw new RuntimeException(e.getMessage());
}
}
private void prepareTable(Table tab) {
// Allows to receive the available width of the table
percentManager.setDimension(tab);
// Table gets expanded by half of the border on each side inside Word
// When using wide borders the table gets cut off
int tabDiff = tab.getCommonBorderPaddingBackground().getBorderStartWidth(false) / 2
+ tab.getCommonBorderPaddingBackground().getBorderEndWidth(false);
// check for "auto" value
if (!(tab.getInlineProgressionDimension().getMaximum(null).getLength()
instanceof EnumLength)) {
// value specified
percentManager.setDimension(tab,
tab.getInlineProgressionDimension().getMaximum(null)
.getLength().getValue(percentManager)
- tabDiff);
} else {
// set table width again without border width
percentManager.setDimension(tab, percentManager.getBaseLength(
LengthBase.CONTAINING_BLOCK_WIDTH, tab) - tabDiff);
}
ColumnSetup columnSetup = new ColumnSetup(tab);
//int sumOfColumns = columnSetup.getSumOfColumnWidths(percentManager);
float tableWidth = percentManager.getBaseLength(LengthBase.CONTAINING_BLOCK_WIDTH, tab);
float tableUnit = columnSetup.computeTableUnit(percentManager, Math.round(tableWidth));
percentManager.setTableUnit(tab, Math.round(tableUnit));
}
/**
* Calls the appropriate event handler for the passed FObj.
*
* @param foNode FO node whose event is to be called
* @param bStart TRUE calls the start handler, FALSE the end handler
*/
private void invokeDeferredEvent(FONode foNode, boolean bStart) {
if (foNode instanceof PageSequence) {
if (bStart) {
startPageSequence((PageSequence) foNode);
} else {
endPageSequence((PageSequence) foNode);
}
} else if (foNode instanceof Flow) {
if (bStart) {
startFlow((Flow) foNode);
} else {
endFlow((Flow) foNode);
}
} else if (foNode instanceof StaticContent) {
if (bStart) {
startStatic(null);
} else {
endStatic(null);
}
} else if (foNode instanceof ExternalGraphic) {
if (bStart) {
image((ExternalGraphic) foNode);
}
} else if (foNode instanceof InstreamForeignObject) {
if (bStart) {
endInstreamForeignObject((InstreamForeignObject) foNode);
}
} else if (foNode instanceof Block) {
if (bStart) {
startBlock((Block) foNode);
} else {
endBlock((Block) foNode);
}
} else if (foNode instanceof BlockContainer) {
if (bStart) {
startBlockContainer((BlockContainer) foNode);
} else {
endBlockContainer((BlockContainer) foNode);
}
} else if (foNode instanceof BasicLink) {
//BasicLink must be placed before Inline
if (bStart) {
startLink((BasicLink) foNode);
} else {
endLink(null);
}
} else if (foNode instanceof Inline) {
if (bStart) {
startInline((Inline) foNode);
} else {
endInline((Inline) foNode);
}
} else if (foNode instanceof FOText) {
if (bStart) {
FOText text = (FOText) foNode;
text(text, text.getCharSequence());
}
} else if (foNode instanceof Character) {
if (bStart) {
Character c = (Character) foNode;
character(c);
}
} else if (foNode instanceof PageNumber) {
if (bStart) {
startPageNumber((PageNumber) foNode);
} else {
endPageNumber((PageNumber) foNode);
}
} else if (foNode instanceof Footnote) {
if (bStart) {
startFootnote((Footnote) foNode);
} else {
endFootnote((Footnote) foNode);
}
} else if (foNode instanceof FootnoteBody) {
if (bStart) {
startFootnoteBody((FootnoteBody) foNode);
} else {
endFootnoteBody((FootnoteBody) foNode);
}
} else if (foNode instanceof ListBlock) {
if (bStart) {
startList((ListBlock) foNode);
} else {
endList((ListBlock) foNode);
}
} else if (foNode instanceof ListItemBody) {
if (bStart) {
startListBody(null);
} else {
endListBody(null);
}
} else if (foNode instanceof ListItem) {
if (bStart) {
startListItem((ListItem) foNode);
} else {
endListItem((ListItem) foNode);
}
} else if (foNode instanceof ListItemLabel) {
if (bStart) {
startListLabel(null);
} else {
endListLabel(null);
}
} else if (foNode instanceof Table) {
if (bStart) {
startTable((Table) foNode);
} else {
endTable((Table) foNode);
}
} else if (foNode instanceof TableHeader) {
if (bStart) {
startHeader((TableHeader) foNode);
} else {
endHeader((TableHeader) foNode);
}
} else if (foNode instanceof TableFooter) {
if (bStart) {
startFooter((TableFooter) foNode);
} else {
endFooter((TableFooter) foNode);
}
} else if (foNode instanceof TableBody) {
if (bStart) {
startBody((TableBody) foNode);
} else {
endBody((TableBody) foNode);
}
} else if (foNode instanceof TableColumn) {
if (bStart) {
startColumn((TableColumn) foNode);
} else {
endColumn((TableColumn) foNode);
}
} else if (foNode instanceof TableRow) {
if (bStart) {
startRow((TableRow) foNode);
} else {
endRow((TableRow) foNode);
}
} else if (foNode instanceof TableCell) {
if (bStart) {
startCell((TableCell) foNode);
} else {
endCell((TableCell) foNode);
}
} else if (foNode instanceof Leader) {
if (bStart) {
startLeader((Leader) foNode);
}
} else if (foNode instanceof PageNumberCitation) {
if (bStart) {
startPageNumberCitation((PageNumberCitation) foNode);
} else {
endPageNumberCitation((PageNumberCitation) foNode);
}
} else if (foNode instanceof PageNumberCitationLast) {
if (bStart) {
startPageNumberCitationLast((PageNumberCitationLast) foNode);
} else {
endPageNumberCitationLast((PageNumberCitationLast) foNode);
}
} else {
RTFEventProducer eventProducer = RTFEventProducer.Provider.get(
getUserAgent().getEventBroadcaster());
eventProducer.ignoredDeferredEvent(this, foNode, bStart, foNode.getLocator());
}
}
/**
* Closes any mismatched tags that are detected in the RTF structure.
* @param containerClass The class representing the tag to close.
* @return Determines whether the tag mismatch has been handled.
*/
public boolean endContainer(Class containerClass) {
if (containerClass == RtfTableRow.class) {
endRow(null);
return true;
}
return false;
}
/**
* Calls the event handlers for the passed FONode and all its elements.
*
* @param foNode FONode object which shall be recursed
*/
private void recurseFONode(FONode foNode) {
invokeDeferredEvent(foNode, true);
if (foNode instanceof PageSequence) {
PageSequence pageSequence = (PageSequence) foNode;
Region regionBefore = pagemaster.getRegion(Constants.FO_REGION_BEFORE);
if (regionBefore != null) {
FONode staticBefore = pageSequence.getFlowMap().get(
regionBefore.getRegionName());
if (staticBefore != null) {
recurseFONode(staticBefore);
}
}
Region regionAfter = pagemaster.getRegion(Constants.FO_REGION_AFTER);
if (regionAfter != null) {
FONode staticAfter = pageSequence.getFlowMap().get(
regionAfter.getRegionName());
if (staticAfter != null) {
recurseFONode(staticAfter);
}
}
recurseFONode(pageSequence.getMainFlow());
} else if (foNode instanceof Table) {
Table table = (Table) foNode;
//recurse all table-columns
if (table.getColumns() != null) {
//Calculation for column-widths which are not set
prepareTable(table);
for (Object o : table.getColumns()) {
recurseFONode((FONode) o);
}
} else {
//TODO Implement implicit column setup handling!
RTFEventProducer eventProducer = RTFEventProducer.Provider.get(
getUserAgent().getEventBroadcaster());
eventProducer.explicitTableColumnsRequired(this, table.getLocator());
}
//recurse table-header
if (table.getTableHeader() != null) {
recurseFONode(table.getTableHeader());
}
//recurse table-footer
if (table.getTableFooter() != null) {
recurseFONode(table.getTableFooter());
}
if (foNode.getChildNodes() != null) {
for (Iterator it = foNode.getChildNodes(); it.hasNext();) {
recurseFONode((FONode) it.next());
}
}
} else if (foNode instanceof ListItem) {
ListItem item = (ListItem) foNode;
recurseFONode(item.getLabel());
recurseFONode(item.getBody());
} else if (foNode instanceof Footnote) {
Footnote fn = (Footnote)foNode;
recurseFONode(fn.getFootnoteCitation());
recurseFONode(fn.getFootnoteBody());
} else {
//Any other FO-Object: Simply recurse through all childNodes.
if (foNode.getChildNodes() != null) {
for (Iterator it = foNode.getChildNodes(); it.hasNext();) {
FONode fn = (FONode)it.next();
if (log.isTraceEnabled()) {
log.trace(" ChildNode for " + fn + " (" + fn.getName() + ")");
}
recurseFONode(fn);
}
}
}
invokeDeferredEvent(foNode, false);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy