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 }