Phase 2: Building the Area tree
Initiating the layout process
In the PageSequence.end() method the
FOTreeHandler object
foInputHandler notifies the
FOTreeListeners of the PageSequence-end
event. There is only one listener, the
FOTreeControl object
foTreeControl. This listener asks its
LayoutManagerLS object to format the FO subtree of
the PageSequence FO node. This object constructs a
PageLayoutManager for the
PageSequence FO node, which does the work.
org.apache.fop.fo.pagination.PageSequence.end():
this.getFOTreeControl().getFOInputHandler().endPageSequence(this):
-> foTreeControl.getFOInputHandler().endPageSequence(this)
-> foInputHandler.endPageSequence(this) (type FOTreeHandler):
This method only calls
FOTreeHandler.notifyPageSequenceComplete(pageSequence),
which notifies the FOTreeListeners of the
PageSequence-end event. The PageSequence object
attaches itself to the event, from which the listeners can retrieve it
again.
There is only one listener. It is an
org.apache.fop.apps.Document object. It is the same
object as pageSequence.root.foTreeControl. Its
method foPageSequenceComplete(event) is called,
which is a method of the FOTreeListener
interface. It handles an FOTreeEvent that is fired
when a PageSequence object has been
completed.
The listener formats the FO subtree of the
PageSequence FO node. It calls its layout
strategy's method LayoutManagerLS.format(pageSeq,
areaTree).
This method creates a new PageLayoutManager
for the PageSequence FO node and calls its
run method (could start another thread). The pages
in this page sequence are completely layed out by the
PageLayoutManager, in its
doLayout method. The first step in the layout
process is getting the page setup from the page masters. Then the FO
tree is processed.
[1] org.apache.fop.layoutmgr.PageLayoutManager.doLayout (PageLayoutManager.java:220)
[2] org.apache.fop.layoutmgr.PageLayoutManager.run (PageLayoutManager.java:208)
[3] org.apache.fop.layoutmgr.LayoutManagerLS.format (LayoutManagerLS.java:83)
[4] org.apache.fop.apps.Document.foPageSequenceComplete (Document.java:348)
[5] org.apache.fop.fo.FOTreeHandler.notifyPageSequenceComplete (FOTreeHandler.java:497)
[6] org.apache.fop.fo.FOTreeHandler.endPageSequence (FOTreeHandler.java:215)
[7] org.apache.fop.fo.pagination.PageSequence.end (PageSequence.java:350)
[8] org.apache.fop.fo.FOTreeBuilder.endElement (FOTreeBuilder.java:223)
... parser stuff
[16] org.apache.xerces.parsers.AbstractSAXParser.parse (null)
[17] org.apache.fop.apps.Driver.render (Driver.java:622)
[18] org.apache.fop.apps.Driver.render (Driver.java:558)
[19] org.apache.fop.apps.Fop.main (Fop.java:102)
main[1] dump pageLM
pageLM = {
pageNumberGenerator: instance of org.apache.fop.fo.pagination.PageNumberGenerator(id=1005)
pageCount: 1
pageNumberString: "1"
isFirstPage: true
bFirstPage: false
curPage: null
curBody: null
curSpan: null
curSpanColumns: 0
curFlow: null
flowBPD: 0
flowIPD: 0
areaTree: instance of org.apache.fop.area.AreaTree(id=1025)
pageSequence: instance of org.apache.fop.fo.pagination.PageSequence(id=997)
currentSimplePageMaster: null
staticContentLMs: instance of java.util.HashMap(id=1033)
lmls: instance of org.apache.fop.layoutmgr.LayoutManagerLS(id=1034)
org.apache.fop.layoutmgr.AbstractLayoutManager.userAgent: instance of org.apache.fop.apps.FOUserAgent(id=1035)
org.apache.fop.layoutmgr.AbstractLayoutManager.parentLM: null
org.apache.fop.layoutmgr.AbstractLayoutManager.fobj: instance of org.apache.fop.fo.pagination.PageSequence(id=997)
org.apache.fop.layoutmgr.AbstractLayoutManager.foID: null
org.apache.fop.layoutmgr.AbstractLayoutManager.markers: null
org.apache.fop.layoutmgr.AbstractLayoutManager.bFinished: false
org.apache.fop.layoutmgr.AbstractLayoutManager.curChildLM: null
org.apache.fop.layoutmgr.AbstractLayoutManager.childLMiter: instance of org.apache.fop.layoutmgr.LMiter(id=1036)
org.apache.fop.layoutmgr.AbstractLayoutManager.bInited: false
}
The above calling sequence contains two configuration
points. FOP's area tree building process can be modified by
registering other listeners with the FO tree handler. It can also be
configured by giving the Document object a different layout strategy
object. See also the AddLMVisitor class which
controls the creation of Layout Managers.
TO BE EXPANDED
Creating the page and body areas
Overview
Create the layout (doLayout)
First create a new Page Viewport
(makeNewPage).
First finish the current page
(finishPage).
Then create the new page viewport
(createPage).
First get the page master
(getSimplePageMasterToUse,
pageSequence.getPageSequenceMaster or
pageSequence.getSimplePageMaster).
Then get the body
(currentSimplePageMaster.getRegion, from
currentSimplePageMaster's
regions map).
Then create the page viewport
(createPageAreas(currentSimplePageMaster)).
From the properties of the page
master create the page reference rectangle, a new page, a new
FODimension object, and a CTM object.
For each region in the page master
(in our example we only have a body):
make a region viewport
(makeRegionViewport), which involves calculating
the position of the region on the page, using the FODimension and CTM
objects.
make the reference area
(makeRegionBodyReferenceArea,
makeRegionReferenceArea).
At this point the page viewport and its region viewports
have been laid out.
Then create the body's main reference area
(createBodyMainReferenceArea).
Then create a Span
(createSpan).
And get the flowIPD
(curFlow.getIPD()).
At this point the body has a single span area with a
single flow area without children.
Detailed view
The call stack when creating the region viewports:
[1] org.apache.fop.layoutmgr.PageLayoutManager.makeRegionViewport (PageLayoutManager.java:832)
[2] org.apache.fop.layoutmgr.PageLayoutManager.createPageAreas (PageLayoutManager.java:805)
[3] org.apache.fop.layoutmgr.PageLayoutManager.createPage (PageLayoutManager.java:748)
[4] org.apache.fop.layoutmgr.PageLayoutManager.makeNewPage (PageLayoutManager.java:467)
[5] org.apache.fop.layoutmgr.PageLayoutManager.doLayout (PageLayoutManager.java:220)
At the end of createPageAreas the following
properties of the page have been established:
The page reference rectangle:
pageRefRect = {
x: 56692
y: 56692
width: 481891
height: 728505
serialVersionUID: -4345857070255674764
}
The page reference area:
page = {
regionBefore: null
regionStart: null
regionBody: instance of org.apache.fop.area.RegionViewport(id=1279)
regionEnd: null
regionAfter: null
unresolved: null
}
page.regionBody = {
region: instance of org.apache.fop.area.BodyRegion(id=1280)
viewArea: instance of java.awt.Rectangle(id=1281)
clip: false
org.apache.fop.area.Area.areaClass: 0
org.apache.fop.area.Area.ipd: 0
org.apache.fop.area.Area.props: null
}
page.regionBody.region = {
beforeFloat: null
mainReference: null
footnote: null
columnGap: 18000
columnCount: 1
refIPD: 0
org.apache.fop.area.RegionReference.regionClass: 2
org.apache.fop.area.RegionReference.ctm: instance of org.apache.fop.area.CTM(id=1282)
org.apache.fop.area.RegionReference.blocks: instance of java.util.ArrayList(id=1283)
org.apache.fop.area.Area.areaClass: 0
org.apache.fop.area.Area.ipd: 0
org.apache.fop.area.Area.props: null
}
page.regionBody.viewArea = {
x: 56692
y: 56692
width: 481891
height: 728505
serialVersionUID: -4345857070255674764
}
The PageViewport is returned:
curPage = {
page: instance of org.apache.fop.area.Page(id=1261)
viewArea: instance of java.awt.Rectangle(id=1289)
clip: false
pageNumber: null
idReferences: null
unresolved: null
pendingResolved: null
markerFirstStart: null
markerLastStart: null
markerFirstAny: null
markerLastEnd: null
markerLastAny: null
}
When makeNewPage returns, the Page
LayoutManager has a Page Viewport and a Body Region object. The layout
dimensions have been calculated:
this = {
pageNumberGenerator: instance of org.apache.fop.fo.pagination.PageNumberGenerator(id=1003)
pageCount: 1
pageNumberString: "1"
isFirstPage: false
bFirstPage: false
curPage: instance of org.apache.fop.area.PageViewport(id=1288)
curBody: instance of org.apache.fop.area.BodyRegion(id=1280)
curSpan: null
curSpanColumns: 0
curFlow: null
flowBPD: 728505
flowIPD: 0
areaTree: instance of org.apache.fop.area.AreaTree(id=1005)
pageSequence: instance of org.apache.fop.fo.pagination.PageSequence(id=1006)
currentSimplePageMaster: instance of org.apache.fop.fo.pagination.SimplePageMaster(id=1007)
staticContentLMs: instance of java.util.HashMap(id=1008)
lmls: instance of org.apache.fop.layoutmgr.LayoutManagerLS(id=1009)
org.apache.fop.layoutmgr.AbstractLayoutManager.userAgent: instance of org.apache.fop.apps.FOUserAgent(id=1010)
org.apache.fop.layoutmgr.AbstractLayoutManager.parentLM: null
org.apache.fop.layoutmgr.AbstractLayoutManager.fobj: instance of org.apache.fop.fo.pagination.PageSequence(id=1006)
org.apache.fop.layoutmgr.AbstractLayoutManager.foID: null
org.apache.fop.layoutmgr.AbstractLayoutManager.markers: null
org.apache.fop.layoutmgr.AbstractLayoutManager.bFinished: false
org.apache.fop.layoutmgr.AbstractLayoutManager.curChildLM: null
org.apache.fop.layoutmgr.AbstractLayoutManager.childLMiter: instance of org.apache.fop.layoutmgr.LMiter(id=1011)
org.apache.fop.layoutmgr.AbstractLayoutManager.bInited: false
}
The method createBodyMainReferenceArea() adds
a MainReferenceArea to the body region:
curBody = {
beforeFloat: null
mainReference: instance of org.apache.fop.area.MainReference(id=1293)
footnote: null
columnGap: 18000
columnCount: 1
refIPD: 0
org.apache.fop.area.RegionReference.regionClass: 2
org.apache.fop.area.RegionReference.ctm: instance of org.apache.fop.area.CTM(id=1282)
org.apache.fop.area.RegionReference.blocks: instance of java.util.ArrayList(id=1283)
org.apache.fop.area.Area.areaClass: 0
org.apache.fop.area.Area.ipd: 0
org.apache.fop.area.Area.props: null
}
curBody.mainReference = {
spanAreas: instance of java.util.ArrayList(id=1294)
columnGap: 0
width: 0
org.apache.fop.area.Area.areaClass: 0
org.apache.fop.area.Area.ipd: 0
org.apache.fop.area.Area.props: null
}
curBody.mainReference.spanAreas = "[]"
After createSpan(1):
curBody.mainReference.spanAreas = "[org.apache.fop.area.Span@1581e80]"
curBody.mainReference.spanAreas.get(0) = {
flowAreas: instance of java.util.ArrayList(id=1299)
height: 0
org.apache.fop.area.Area.areaClass: 0
org.apache.fop.area.Area.ipd: 481891
org.apache.fop.area.Area.props: null
}