Phase 0: Preparation
This chapter describes the structure of FOP as it was in the
first quarter of 2004. In the second quarter of that year the top
level structure was strongly refactored. The new situation is not
described here.
The preparation process
FOP's processing model is the SAX parsing model:
Construct a suitable content handler object of type
org.xml.sax.ContentHandler,
create a parser of type
org.xml.sax.XMLReader,
register the content handler with the parser,
call the parser's parse method on the input
source.
From there on the parser takes control. For every XML
event it passes control to the appropriate content handler methods.
When these methods return, parsing continues until the next XML event
is encountered. Once the parser has taken control, its content handler
is the only entry point into FOP's data structures and methods.
The preparatory phase of FOP concerns itself with the
construction of a suitable content handler object, whose methods allow
FOP's process to handle the FO elements reported by the parser and
build the required output document.
An application may choose to deal with the whole
preparatory phase itself, and then call the parser's
parse method.
The input source may be an FO file, which may be fed to
the parse method as a string or as an
org.xml.sax.InputSource object. Alternatively, a
DOM document object may be used as input, e.g. the output of an XSLT
processor. In that case:
the parser should be of type
org.apache.fop.tools.DocumentReader,
the input source should be of type
org.apache.fop.tools.DocumentInputSource, created
with the DOM document as the argument of the constructor.
The classes Fop and
Driver contain methods which applications may use
as more convenient entry points into FOP.
The method Fop.main may be called with
the input and output file names as arguments. This is mainly useful
for starting Fop from the command line.
The class Driver contains a method
getContentHandler, which can be used to create a
suitable content handler. It also contains three
render methods which are convenient entry points
for applications.
These 4 methods may be invoked on a driver object which
already has the following members: userAgent,
renderer, log,
stream. In addition, the driver object may have the
following members: a TreeBuilder object having a
member userAgent, and a Document
object, which may have a member layoutStrategy.
Using one's own TreeBuilder and
Document objects allows one to customize FOP's
behaviour in a major way.
The render methods invoke
getContentHandler to create a suitable content
handler. They register it as the content handler of the parser. They
register the member currentDocument as a tree
listener to the member foInputHandler.
A suitable org.xml.sax.ContentHandler
object for FOP processing is an object of type
org.apache.fop.fo.FOTreeBuilder and has the
following structure:
treeBuilder
|
+--------------+------------------+
| | |
foInputHandler userAgent foTreeControl
| |
foTreeControl driver
foTreeListeners: usedFonts
[foTreeControl] triplets
fonts
layoutStrategy -- foTreeControl
areaTree -- atModel, foTreeControl
atModel -- renderer
foInputHandler
The driver and
renderer objects are complex objects:
driver renderer
| |
treeBuilder foTreeControl
renderer userAgent
foInputHandler fontList
ostream ostream
userAgent
foTreeControl
A detailed overview of the objects
treeBuilder = {
fobjTable: instance of java.util.HashMap(id=589)
namespaces: instance of java.util.HashSet(id=590)
currentFObj: null
rootFObj: null
foInputHandler: instance of org.apache.fop.fo.FOTreeHandler(id=591)
userAgent: instance of org.apache.fop.apps.FOUserAgent(id=592)
foTreeControl: instance of org.apache.fop.apps.Document(id=593)
class$org$apache$fop$fo$ElementMapping: instance of java.lang.Class(reflected class=org.apache.fop.fo.ElementMapping, id=450)
}
treeBuilder.foInputHandler = {
collectStatistics: true
MEM_PROFILE_WITH_GC: false
runtime: instance of java.lang.Runtime(id=595)
pageCount: 0
initialMemory: 0
startTime: 0
foTreeListeners: instance of java.util.HashSet(id=596)
org.apache.fop.fo.FOInputHandler.foTreeControl: instance of org.apache.fop.apps.Document(id=593)
org.apache.avalon.framework.logger.AbstractLogEnabled.m_logger: instance of org.apache.avalon.framework.logger.ConsoleLogger(id=597)
}
treeBuilder.foTreeControl = "org.apache.fop.apps.Document@125844f"
treeBuilder.foInputHandler.foTreeListeners = "[org.apache.fop.apps.Document@125844f]"
treeBuilder.userAgent = {
log: instance of org.apache.avalon.framework.logger.ConsoleLogger(id=597)
defaults: instance of java.util.HashMap(id=601)
handlers: instance of java.util.HashMap(id=602)
baseURL: ""
pdfEncryptionParams: null
px2mm: 0.35277778
}
treeBuilder.foTreeControl = {
driver: instance of org.apache.fop.apps.Driver(id=587)
usedFonts: instance of java.util.HashMap(id=604)
triplets: instance of java.util.HashMap(id=605)
fonts: instance of java.util.HashMap(id=606)
layoutStrategy: instance of org.apache.fop.layoutmgr.LayoutManagerLS(id=607)
areaTree: instance of org.apache.fop.area.AreaTree(id=608)
atModel: instance of org.apache.fop.area.RenderPagesModel(id=609)
bookmarks: null
idReferences: instance of java.util.HashSet(id=610)
foInputHandler: instance of org.apache.fop.fo.FOTreeHandler(id=591)
}
treeBuilder.foTreeControl.driver = {
NOT_SET: 0
RENDER_PDF: 1
RENDER_AWT: 2
RENDER_MIF: 3
RENDER_XML: 4
RENDER_PRINT: 5
RENDER_PCL: 6
RENDER_PS: 7
RENDER_TXT: 8
RENDER_SVG: 9
RENDER_RTF: 10
treeBuilder: instance of org.apache.fop.fo.FOTreeBuilder(id=588)
rendererType: 1
renderer: instance of org.apache.fop.render.pdf.PDFRenderer(id=599)
foInputHandler: instance of org.apache.fop.fo.FOTreeHandler(id=591)
source: null
stream: instance of java.io.BufferedOutputStream(id=600)
reader: null
log: instance of org.apache.avalon.framework.logger.ConsoleLogger(id=597)
userAgent: instance of org.apache.fop.apps.FOUserAgent(id=592)
currentDocument: instance of org.apache.fop.apps.Document(id=593)
}
treeBuilder.foTreeControl.areaTree = {
model: instance of org.apache.fop.area.RenderPagesModel(id=609)
atControl: instance of org.apache.fop.apps.Document(id=593)
idLocations: instance of java.util.HashMap(id=615)
resolve: instance of java.util.HashMap(id=616)
treeExtensions: instance of java.util.ArrayList(id=617)
}
treeBuilder.foTreeControl.atModel = {
renderer: instance of org.apache.fop.render.pdf.PDFRenderer(id=599)
prepared: instance of java.util.ArrayList(id=618)
pendingExt: instance of java.util.ArrayList(id=619)
endDocExt: instance of java.util.ArrayList(id=620)
org.apache.fop.area.StorePagesModel.pageSequence: null
org.apache.fop.area.StorePagesModel.titles: instance of java.util.ArrayList(id=621)
org.apache.fop.area.StorePagesModel.currSequence: null
org.apache.fop.area.StorePagesModel.extensions: instance of java.util.ArrayList(id=622)
}
treeBuilder.foTreeControl.atModel.renderer = {
MIME_TYPE: "application/pdf"
pdfDoc: instance of org.apache.fop.pdf.PDFDocument(id=624)
pages: null
pageReferences: instance of java.util.HashMap(id=625)
pvReferences: instance of java.util.HashMap(id=626)
ostream: instance of java.io.BufferedOutputStream(id=600)
pdfResources: null
currentStream: null
currentContext: null
currentPage: null
currentState: null
currentFontName: ""
currentFontSize: 0
pageHeight: 0
filterMap: null
textOpen: false
prevWordY: 0
prevWordX: 0
prevWordWidth: 0
wordAreaPDF: instance of java.lang.StringBuffer(id=627)
BPMarginOffset: 0
IPMarginOffset: 0
org.apache.fop.render.PrintRenderer.fontInfo: instance of org.apache.fop.apps.Document(id=593)
org.apache.fop.render.PrintRenderer.fontList: null
org.apache.fop.render.AbstractRenderer.userAgent: instance of org.apache.fop.apps.FOUserAgent(id=592)
org.apache.fop.render.AbstractRenderer.producer: "FOP 1.0dev"
org.apache.fop.render.AbstractRenderer.creator: null
org.apache.fop.render.AbstractRenderer.creationDate: null
org.apache.fop.render.AbstractRenderer.options: instance of java.util.HashMap(id=629)
org.apache.fop.render.AbstractRenderer.currentBPPosition: 0
org.apache.fop.render.AbstractRenderer.currentIPPosition: 0
org.apache.fop.render.AbstractRenderer.currentBlockIPPosition: 0
org.apache.fop.render.AbstractRenderer.containingBPPosition: 0
org.apache.fop.render.AbstractRenderer.containingIPPosition: 0
org.apache.avalon.framework.logger.AbstractLogEnabled.m_logger: instance of org.apache.avalon.framework.logger.ConsoleLogger(id=597)
}
treeBuilder.foTreeControl.layoutStrategy = {
name: "layoutmgr"
addLMVisitor: null
org.apache.fop.layout.LayoutStrategy.name: "undefined"
org.apache.fop.layout.LayoutStrategy.document: instance of org.apache.fop.apps.Document(id=593)
}
treeBuilder.foTreeControl.atModel.renderer.ostream = {
buf: instance of byte[512] (id=632)
count: 15
java.io.FilterOutputStream.out: instance of java.io.FileOutputStream(id=633)
}
For the members fontList,
fonts, usedFonts and
triplets of treeBuilder.foTreeControl,
see under Fonts.
A detailed overview of the entry methods
Already created (e.g. in Fop.main): an
object of type Driver with the members
userAgent, renderer,
log, stream.
To create userAgent one may use
Driver.getUserAgent: if driver
does not have userAgent, create a new
UserAgent.
To create renderer one may use one of
three methods:
setRenderer(int
renderer)
setRenderer(String
rendererClassName)
setRenderer(Renderer
renderer)
All three methods set the FOP version on the
renderer, and register userAgent
with it, which is obtained using
Driver.getUserAgent.
render(InputHandler inputHandler):
creates XMLReader parser,
InputSource source;
calls render(XMLReader parser,
InputSource source).
render(org.w3c.dom.Document
document):
creates DocumentReader reader,
DocumentInputSource source;
calls render(XMLReader parser,
InputSource source).
render(XMLReader parser, InputSource
source):
creates content handler by calling
getContentHandler().
registers the content handler with the parser.
Adds currentDocument as a tree
listener to foInputHandler.
calls parser.parse(source).
getContentHandler():
if driver does not have a
treeBuilder, call initialize():
create a new TreeBuilder, set the
UserAgent on it.
if driver does not have a
currentDocument, create a new
Document.
create a new FOTreeHandler
foInputHandler using currentDocument as
an argument (currentDocument is member
foTreeControl in
foInputHandler).
create a new AreaTree using currentDocument as an argument, and
register it with currentDocument.
create a new RenderPagesModel
using renderer as an argument, and register it with
currentDocument and with
currentDocument.areaTree.
register currentDocument with
the renderer (currentDocument is
member fontInfo in renderer);
setup fontList in
currentDocument.
start the renderer with the
outputstream.
register foInputHandler with
currentDocument.
if currentDocument does not
have a layoutStrategy, create a new
LayoutStrategyLS for it with
currentDocument as an argument.
register userAgent,
foInputHandler and
currentDocument with treeBuilder
(currentDocument is member
foTreeControl in
treeBuilder).
return treeBuilder.