You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by gm...@apache.org on 2004/09/26 15:51:01 UTC
cvs commit: xml-fop/src/java/org/apache/fop/layoutmgr PageSequenceLayoutManager.java FlowLayoutManager.java StaticContentLayoutManager.java PageLayoutManager.java
gmazza 2004/09/26 06:51:01
Modified: src/java/org/apache/fop/area AreaTreeHandler.java
src/java/org/apache/fop/fo/pagination PageSequence.java
PageSequenceMaster.java
src/java/org/apache/fop/layoutmgr FlowLayoutManager.java
StaticContentLayoutManager.java
Added: src/java/org/apache/fop/layoutmgr
PageSequenceLayoutManager.java
Removed: src/java/org/apache/fop/layoutmgr PageLayoutManager.java
Log:
1.) Renamed PageLayoutManager to somewhat more intuitive PageSequenceLayoutManager.
2.) Moved layout logic for the fo:title of an fo:page-sequence from AreaTreeHandler
to PSLM. Also moved page number initialization logic there.
Comments most welcome.
Revision Changes Path
1.10 +20 -89 xml-fop/src/java/org/apache/fop/area/AreaTreeHandler.java
Index: AreaTreeHandler.java
===================================================================
RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/area/AreaTreeHandler.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- AreaTreeHandler.java 25 Sep 2004 21:55:36 -0000 1.9
+++ AreaTreeHandler.java 26 Sep 2004 13:51:00 -0000 1.10
@@ -39,10 +39,7 @@
import org.apache.fop.fo.extensions.Outline;
import org.apache.fop.fo.extensions.Bookmarks;
import org.apache.fop.fo.pagination.PageSequence;
-import org.apache.fop.fo.pagination.Title;
-import org.apache.fop.layoutmgr.ContentLayoutManager;
-import org.apache.fop.layoutmgr.InlineStackingLayoutManager;
-import org.apache.fop.layoutmgr.PageLayoutManager;
+import org.apache.fop.layoutmgr.PageSequenceLayoutManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -129,14 +126,6 @@
}
/**
- * Add a new page to the area tree.
- * @param page the page to add
- */
- public void addPage(PageViewport page) {
- model.addPage(page);
- }
-
- /**
* Add an id reference pointing to a page viewport.
* @param id the id of the reference
* @param pv the page viewport that contains the id reference
@@ -343,10 +332,8 @@
* The area tree then handles what happens with the pages.
*
* @param pageSequence the page sequence ending
- * @throws FOPException if there is an error formatting the pages
*/
public void endPageSequence(PageSequence pageSequence) {
- //areaTree.setFontInfo(fontInfo);
if (collectStatistics) {
if (MEM_PROFILE_WITH_GC) {
@@ -359,88 +346,32 @@
}
}
- addBookmarks(pageSequence.getRoot().getBookmarks());
- formatPageSequence(pageSequence);
+ // If no main flow, nothing to layout!
+ if (pageSequence.getMainFlow() != null) {
+ addBookmarks(pageSequence.getRoot().getBookmarks());
+ PageSequenceLayoutManager pageSLM
+ = new PageSequenceLayoutManager(this, pageSequence);
+ pageSLM.run();
+ pageSequence.setCurrentPageNumber(pageSLM.getPageCount());
+ }
}
/**
- * Runs the formatting of this page sequence into the given area tree
- *
- * @param pageSeq the PageSequence to be formatted
- * @param areaTree the area tree to format this page sequence into
- * @throws FOPException if there is an error formatting the contents
- */
- private void formatPageSequence(PageSequence pageSeq) {
- LineArea title = null;
- if (pageSeq.getTitleFO() != null) {
- title = getTitleArea(pageSeq.getTitleFO());
- }
-
+ * Add a new page to the area tree.
+ * @param page the page to add
+ */
+ public void startPageSequence(LineArea title) {
model.startPageSequence(title);
-
- // Make a new PageLayoutManager and a FlowLayoutManager
- // Run the PLM in a thread
- // Wait for them to finish.
-
- // If no main flow, nothing to layout!
- if (pageSeq.getMainFlow() == null) {
- return;
- }
-
- // Initialize if already used?
- // this.layoutMasterSet.resetPageMasters();
- if (pageSeq.getPageSequenceMaster() != null) {
- pageSeq.getPageSequenceMaster().reset();
- }
-
- pageSeq.initPageNumber();
-
- // This will layout pages and add them to the area tree
- PageLayoutManager pageLM = new PageLayoutManager(this, pageSeq);
- pageLM.setPageCounting(pageSeq.getCurrentPageNumber(),
- pageSeq.getPageNumberGenerator());
-
- // For now, skip the threading and just call run directly.
- pageLM.run();
-
- // Thread layoutThread = new Thread(pageLM);
- // layoutThread.start();
- // log.debug("Layout thread started");
-
- // // wait on both managers
- // try {
- // layoutThread.join();
- // log.debug("Layout thread done");
- // } catch (InterruptedException ie) {
- // log.error("PageSequence.format() interrupted waiting on layout");
- // }
-
- pageSeq.setCurrentPageNumber(pageLM.getPageCount());
- // Tell the root the last page number we created.
- pageSeq.getRoot().setRunningPageNumberCounter(pageSeq.getCurrentPageNumber());
}
/**
- * @return the Title area
- */
- private LineArea getTitleArea(Title foTitle) {
- // get breaks then add areas to title
- LineArea title = new LineArea();
-
- ContentLayoutManager clm = new ContentLayoutManager(title);
- clm.setUserAgent(foTitle.getUserAgent());
-
- // use special layout manager to add the inline areas
- // to the Title.
- InlineStackingLayoutManager lm;
- lm = new InlineStackingLayoutManager(foTitle);
- clm.addChildLM(lm);
-
- clm.fillArea(lm);
-
- return title;
+ * Add a new page to the area tree.
+ * @param page the page to add
+ */
+ public void addPage(PageViewport page) {
+ model.addPage(page);
}
-
+
/**
* Accessor for the currentLMList.
* @return the currentLMList.
1.46 +3 -0 xml-fop/src/java/org/apache/fop/fo/pagination/PageSequence.java
Index: PageSequence.java
===================================================================
RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/fo/pagination/PageSequence.java,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -r1.45 -r1.46
--- PageSequence.java 13 Sep 2004 08:05:34 -0000 1.45
+++ PageSequence.java 26 Sep 2004 13:51:00 -0000 1.46
@@ -673,6 +673,9 @@
*/
public void setCurrentPageNumber(int currentPageNumber) {
this.currentPageNumber = currentPageNumber;
+
+ // Tell the root the last page number we created.
+ root.setRunningPageNumberCounter(currentPageNumber);
}
/**
1.23 +21 -24 xml-fop/src/java/org/apache/fop/fo/pagination/PageSequenceMaster.java
Index: PageSequenceMaster.java
===================================================================
RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/fo/pagination/PageSequenceMaster.java,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- PageSequenceMaster.java 7 Sep 2004 20:47:10 -0000 1.22
+++ PageSequenceMaster.java 26 Sep 2004 13:51:00 -0000 1.23
@@ -58,7 +58,27 @@
super(parent);
}
-
+ /**
+ * @see org.apache.fop.fo.FObj#addProperties
+ */
+ protected void addProperties(Attributes attlist) throws SAXParseException {
+ super.addProperties(attlist);
+ subSequenceSpecifiers = new java.util.ArrayList();
+ if (parent.getName().equals("fo:layout-master-set")) {
+ this.layoutMasterSet = (LayoutMasterSet)parent;
+ masterName = getPropString(PR_MASTER_NAME);
+ if (masterName == null) {
+ getLogger().warn("page-sequence-master does not have "
+ + "a master-name and so is being ignored");
+ } else {
+ this.layoutMasterSet.addPageSequenceMaster(masterName, this);
+ }
+ } else {
+ throw new SAXParseException("fo:page-sequence-master must be child "
+ + "of fo:layout-master-set, not "
+ + parent.getName(), locator);
+ }
+ }
/**
* @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String)
@@ -82,29 +102,6 @@
if (childNodes == null) {
missingChildElementError("(single-page-master-reference|" +
"repeatable-page-master-reference|repeatable-page-master-alternatives)+");
- }
- }
-
-
- /**
- * @see org.apache.fop.fo.FObj#addProperties
- */
- protected void addProperties(Attributes attlist) throws SAXParseException {
- super.addProperties(attlist);
- subSequenceSpecifiers = new java.util.ArrayList();
- if (parent.getName().equals("fo:layout-master-set")) {
- this.layoutMasterSet = (LayoutMasterSet)parent;
- masterName = getPropString(PR_MASTER_NAME);
- if (masterName == null) {
- getLogger().warn("page-sequence-master does not have "
- + "a master-name and so is being ignored");
- } else {
- this.layoutMasterSet.addPageSequenceMaster(masterName, this);
- }
- } else {
- throw new SAXParseException("fo:page-sequence-master must be child "
- + "of fo:layout-master-set, not "
- + parent.getName(), locator);
}
}
1.8 +1 -1 xml-fop/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java
Index: FlowLayoutManager.java
===================================================================
RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- FlowLayoutManager.java 15 May 2004 21:51:59 -0000 1.7
+++ FlowLayoutManager.java 26 Sep 2004 13:51:00 -0000 1.8
@@ -29,7 +29,7 @@
/**
* LayoutManager for an fo:flow object.
- * Its parent LM is the PageLayoutManager.
+ * Its parent LM is the PageSequenceLayoutManager.
* This LM is responsible for getting columns of the appropriate size
* and filling them with block-level areas generated by its children.
*/
1.5 +1 -1 xml-fop/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java
Index: StaticContentLayoutManager.java
===================================================================
RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- StaticContentLayoutManager.java 12 May 2004 23:19:52 -0000 1.4
+++ StaticContentLayoutManager.java 26 Sep 2004 13:51:01 -0000 1.5
@@ -28,7 +28,7 @@
/**
* LayoutManager for an fo:flow object.
- * Its parent LM is the PageLayoutManager.
+ * Its parent LM is the PageSequenceLayoutManager.
* This LM is responsible for getting columns of the appropriate size
* and filling them with block-level areas generated by its children.
*/
1.1 xml-fop/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java
Index: PageSequenceLayoutManager.java
===================================================================
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
* Licensed 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: PageSequenceLayoutManager.java,v 1.1 2004/09/26 13:51:01 gmazza Exp $ */
package org.apache.fop.layoutmgr;
import org.apache.fop.apps.FOPException;
import org.apache.fop.area.CTM;
import org.apache.fop.area.AreaTreeHandler;
import org.apache.fop.area.AreaTreeModel;
import org.apache.fop.area.Area;
import org.apache.fop.area.PageViewport;
import org.apache.fop.area.Flow;
import org.apache.fop.area.LineArea;
import org.apache.fop.area.Page;
import org.apache.fop.area.RegionViewport;
import org.apache.fop.area.RegionReference;
import org.apache.fop.area.BodyRegion;
import org.apache.fop.area.MainReference;
import org.apache.fop.area.Span;
import org.apache.fop.area.BeforeFloat;
import org.apache.fop.area.Footnote;
import org.apache.fop.area.Resolveable;
import org.apache.fop.area.Trait;
import org.apache.fop.datatypes.PercentBase;
import org.apache.fop.datatypes.FODimension;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.flow.Marker;
import org.apache.fop.fo.pagination.PageNumberGenerator;
import org.apache.fop.fo.pagination.PageSequence;
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.pagination.Title;
import org.apache.fop.fo.properties.CommonBackground;
import org.apache.fop.fo.properties.CommonBorderAndPadding;
import org.apache.fop.fo.properties.CommonMarginBlock;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.awt.Rectangle;
import java.util.Iterator;
import java.awt.geom.Rectangle2D;
import org.apache.fop.traits.MinOptMax;
/**
* LayoutManager for a PageSequence and its flow.
* It manages all page-related layout.
*/
public class PageSequenceLayoutManager extends AbstractLayoutManager implements Runnable {
private static class BlockBreakPosition extends LeafPosition {
protected BreakPoss breakps;
protected BlockBreakPosition(LayoutManager lm, BreakPoss bp) {
super(lm, 0);
breakps = bp;
}
}
private PageNumberGenerator pageNumberGenerator;
private int pageCount = 1;
private String pageNumberString;
private boolean isFirstPage = true;
/** True if haven't yet laid out any pages.*/
private boolean bFirstPage;
/** Current page being worked on. */
private PageViewport curPage;
/** Body region of the current page */
private BodyRegion curBody;
/** Current span being filled */
private Span curSpan;
/** Number of columns in current span area. */
private int curSpanColumns;
/** Current flow-reference-area (column) being filled. */
private Flow curFlow;
private int flowBPD = 0;
private int flowIPD = 0;
/** Manager which handles a queue of all pages which are completely
* laid out and ready for rendering, except for resolution of ID
* references?
*/
private AreaTreeHandler areaTreeHandler;
private PageSequence pageSequence;
/**
* This is the SimplePageMaster that should be used to create the page. It
* will be equal to the PageSequence's simplePageMaster, if it exists, or
* to the correct member of the PageSequence's pageSequenceMaster, if that
* exists instead.
*/
private SimplePageMaster currentSimplePageMaster;
/**
* The collection of StaticContentLayoutManager objects that are associated
* with this Page Sequence, keyed by flow-name.
*/
private HashMap staticContentLMs = new HashMap(4);
/**
* This is the top level layout manager.
* It is created by the PageSequence FO.
*
* @param areaTree the area tree to add pages to
* @param pageseq the page sequence fo
*/
public PageSequenceLayoutManager(AreaTreeHandler areaTreeHandler, PageSequence pageseq) {
super(pageseq);
this.areaTreeHandler = areaTreeHandler;
pageSequence = pageseq;
if (pageSequence.getPageSequenceMaster() != null) {
pageSequence.getPageSequenceMaster().reset();
}
}
/**
* Set the page counting for this page sequence.
* This sets the initial page number and the page number formatter.
*
* @param pc the starting page number
* @param generator the page number generator
*/
private void setPageCounting(int pc, PageNumberGenerator generator) {
pageSequence.initPageNumber();
pageCount = pc;
pageNumberGenerator = generator;
pageNumberString = pageNumberGenerator.makeFormattedPageNumber(pageCount);
}
/**
* The layout process is designed to be able to be run in a thread.
* In theory it can run at the same
* time as FO tree generation, once the layout-master-set has been read.
* We can arrange it so that the iterator over the fobj children waits
* until the next child is available.
* As it produces pages, it adds them to the AreaTree, where the
* rendering process can also run in a parallel thread.
*/
public void run() {
setPageCounting(pageSequence.getCurrentPageNumber(),
pageSequence.getPageNumberGenerator());
LineArea title = null;
if (pageSequence.getTitleFO() != null) {
title = getTitleArea(pageSequence.getTitleFO());
}
areaTreeHandler.startPageSequence(title);
doLayout();
flush();
}
/**
* Get the page count.
* Used to get the last page number for reference for
* the next page sequence.
*
* @return the page number
*/
public int getPageCount() {
return pageCount;
}
/**
* @return the Title area
*/
private LineArea getTitleArea(Title foTitle) {
// get breaks then add areas to title
LineArea title = new LineArea();
ContentLayoutManager clm = new ContentLayoutManager(title);
clm.setUserAgent(foTitle.getUserAgent());
// use special layout manager to add the inline areas
// to the Title.
InlineStackingLayoutManager lm;
lm = new InlineStackingLayoutManager(foTitle);
clm.addChildLM(lm);
clm.fillArea(lm);
return title;
}
/**
* Do the layout of this page sequence.
* This completes the layout of the page sequence
* which creates and adds all the pages to the area tree.
*/
protected void doLayout() {
log.debug("Starting layout");
// this should be done another way
makeNewPage(false, false);
createBodyMainReferenceArea();
createSpan(1);
flowIPD = curFlow.getIPD();
BreakPoss bp;
LayoutContext childLC = new LayoutContext(0);
while (!isFinished()) {
if ((bp = getNextBreakPoss(childLC)) != null) {
addAreas((BlockBreakPosition)bp.getPosition());
// add static areas and resolve any new id areas
// finish page and add to area tree
finishPage();
pageCount++;
pageNumberString = pageNumberGenerator.makeFormattedPageNumber(pageCount);
}
}
pageCount--;
log.debug("Ending layout");
}
/**
* Get the next break possibility.
* This finds the next break for a page which is always at the end
* of the page.
*
* @param context the layout context for finding breaks
* @return the break for the page
*/
public BreakPoss getNextBreakPoss(LayoutContext context) {
LayoutManager curLM ; // currently active LM
while ((curLM = getChildLM()) != null) {
BreakPoss bp = null;
LayoutContext childLC = new LayoutContext(0);
childLC.setStackLimit(new MinOptMax(flowBPD));
childLC.setRefIPD(flowIPD);
if (!curLM.isFinished()) {
fobj.setLayoutDimension(PercentBase.REFERENCE_AREA_IPD, flowIPD);
fobj.setLayoutDimension(PercentBase.REFERENCE_AREA_BPD, flowBPD);
bp = curLM.getNextBreakPoss(childLC);
}
if (bp != null) {
return new BreakPoss(
new BlockBreakPosition(curLM, bp));
}
}
setFinished(true);
return null;
}
/**
* Get the current page number string.
* This returns the formatted string for the current page.
*
* @return the formatted page number string
*/
public String getCurrentPageNumber() {
return pageNumberString;
}
/**
* Resolve a reference ID.
* This resolves a reference ID and returns the first PageViewport
* that contains the reference ID or null if reference not found.
*
* @param ref the reference ID to lookup
* @return the first page viewport that contains the reference
*/
public PageViewport resolveRefID(String ref) {
List list = areaTreeHandler.getIDReferences(ref);
if (list != null && list.size() > 0) {
return (PageViewport)list.get(0);
}
return null;
}
/**
* Add the areas to the current page.
* Given the page break position this adds the areas to the current
* page.
*
* @param bbp the block break position
*/
public void addAreas(BlockBreakPosition bbp) {
List list = new ArrayList();
list.add(bbp.breakps);
bbp.getLM().addAreas(new BreakPossPosIter(list, 0,
1), null);
}
/**
* Add an ID reference to the current page.
* When adding areas the area adds its ID reference.
* For the page layout manager it adds the id reference
* with the current page to the area tree.
*
* @param id the ID reference to add
*/
public void addIDToPage(String id) {
areaTreeHandler.addIDRef(id, curPage);
}
/**
* Add an unresolved area to the layout manager.
* The Page layout manager handles the unresolved ID
* reference by adding to the current page and then adding
* the page as a resolveable to the area tree.
* This is so that the area tree can resolve the reference
* and the page can serialize the resolvers if required.
*
* @param id the ID reference to add
* @param res the resolveable object that needs resolving
*/
public void addUnresolvedArea(String id, Resolveable res) {
// add unresolved to tree
// adds to the page viewport so it can serialize
curPage.addUnresolvedID(id, res);
areaTreeHandler.addUnresolvedID(id, curPage);
}
/**
* Add the marker to the page layout manager.
*
* @param name the marker class name
* @param lm the layout manager for the marker contents
* @param start true if starting marker area, false for ending
*/
public void addMarkerMap(Map marks, boolean start, boolean isfirst) {
//getLogger().debug("adding markers: " + marks + ":" + start);
// add markers to page on area tree
curPage.addMarkers(marks, start, isfirst);
}
/**
* Retrieve a marker from this layout manager.
* If the boundary is page then it will only check the
* current page. For page-sequence and document it will
* lookup preceding pages from the area tree and try to find
* a marker.
*
* @param name the marker class name to lookup
* @param pos the position to locate the marker
* @param boundary the boundary for locating the marker
* @return the layout manager for the marker contents
*/
public Marker retrieveMarker(String name, int pos, int boundary) {
// get marker from the current markers on area tree
Marker mark = (Marker)curPage.getMarker(name, pos);
if (mark == null && boundary != RetrieveBoundary.PAGE) {
// go back over pages until mark found
// if document boundary then keep going
boolean doc = boundary == RetrieveBoundary.DOCUMENT;
AreaTreeModel atm = areaTreeHandler.getAreaTreeModel();
int seq = atm.getPageSequenceCount();
int page = atm.getPageCount(seq) - 1;
while (page >= 0) {
PageViewport pv = atm.getPage(seq, page);
mark = (Marker)curPage.getMarker(name, pos);
if (mark != null) {
return mark;
}
page--;
if (page == -1 && doc && seq > 0) {
seq--;
page = atm.getPageCount(seq) - 1;
}
}
}
return mark;
}
/**
* For now, only handle normal flow areas.
*
* @param childArea the child area to add
*/
public void addChild(Area childArea) {
if (childArea == null) {
return;
}
if (childArea.getAreaClass() == Area.CLASS_NORMAL) {
placeFlowRefArea(childArea);
} else {
// todo: all the others!
}
}
/**
* Place a FlowReferenceArea into the current span. The FlowLM is
* responsible for making sure that it will actually fit in the
* current span area. In fact the area has already been added to the
* current span, so we are just checking to see if the span is "full",
* possibly moving to the next column or to the next page.
*
* @param area the area to place
*/
protected void placeFlowRefArea(Area area) {
// assert (curSpan != null);
// assert (area == curFlow);
// assert (curFlow == curSpan.getFlow(curSpan.getColumnCount()-1));
// assert (area.getBPD().min < curSpan.getHeight());
// Last column on this page is filled
// See if the flow is full. The Flow LM can add an area before
// it's full in the case of a break or a span.
// Also in the case of a float to be placed. In that case, there
// may be further material added later.
// The Flow LM sets the "finished" flag on the Flow Area if it has
// completely filled it. In this case, if on the last column
// end the page.
getParentArea(area);
// Alternatively the child LM indicates to parent that it's full?
//getLogger().debug("size: " + area.getAllocationBPD().max +
// ":" + curSpan.getMaxBPD().min);
/*if (area.getAllocationBPD().max >= curSpan.getMaxBPD().min) {
// Consider it filled
if (curSpan.getColumnCount() == curSpanColumns) {
finishPage();
} else
curFlow = null; // Create new flow on next getParentArea()
}*/
}
protected void placeAbsoluteArea(Area area) {
}
protected void placeBeforeFloat(Area area) {
}
protected void placeSideFloat(Area area) {
}
protected void placeFootnote(Area area) {
// After doing this, reduce available space on the curSpan.
// This has to be propagated to the curFlow (FlowLM) so that
// it can adjust its limit for composition (or it just asks
// curSpan for BPD before doing the break?)
// If multi-column, we may have to balance to find more space
// for a float. When?
}
private PageViewport makeNewPage(boolean bIsBlank, boolean bIsLast) {
finishPage();
try {
curPage = createPage(bIsBlank, bIsLast);
isFirstPage = false;
} catch (FOPException fopex) { /* ???? */
fopex.printStackTrace();
}
curPage.setPageNumber(getCurrentPageNumber());
RegionViewport rv = curPage.getPage().getRegionViewport(
FO_REGION_BODY);
curBody = (BodyRegion) rv.getRegion();
flowBPD = (int) curBody.getBPD() -
rv.getBorderAndPaddingWidthBefore() - rv.getBorderAndPaddingWidthAfter();
return curPage;
}
private void layoutStaticContent(Region region, int regionClass) {
if (region == null) {
return;
}
StaticContent flow = pageSequence.getStaticContent(region.getRegionName());
if (flow == null) {
return;
}
RegionViewport reg = curPage.getPage().getRegionViewport(regionClass);
if (reg == null) {
log.error("no region viewport: shouldn't happen");
}
StaticContentLayoutManager lm = getStaticContentLayoutManager(flow);
lm.initialize();
lm.setRegionReference(reg.getRegion());
lm.setParent(this);
LayoutContext childLC = new LayoutContext(0);
childLC.setStackLimit(new MinOptMax((int)curPage.getViewArea().getHeight()));
childLC.setRefIPD(reg.getRegion().getIPD());
while (!lm.isFinished()) {
BreakPoss bp = lm.getNextBreakPoss(childLC);
if (bp != null) {
List vecBreakPoss = new ArrayList();
vecBreakPoss.add(bp);
lm.addAreas(new BreakPossPosIter(vecBreakPoss, 0,
vecBreakPoss.size()), null);
} else {
log.error("bp==null cls=" + regionClass);
}
}
//lm.flush();
lm.reset(null);
}
private void finishPage() {
if (curPage == null) {
return;
}
// Layout static content into the regions
// Need help from pageseq for this
layoutStaticContent(currentSimplePageMaster.getRegion(FO_REGION_BEFORE),
FO_REGION_BEFORE);
layoutStaticContent(currentSimplePageMaster.getRegion(FO_REGION_AFTER),
FO_REGION_AFTER);
layoutStaticContent(currentSimplePageMaster.getRegion(FO_REGION_START),
FO_REGION_START);
layoutStaticContent(currentSimplePageMaster.getRegion(FO_REGION_END),
FO_REGION_END);
// Queue for ID resolution and rendering
areaTreeHandler.addPage(curPage);
curPage = null;
curBody = null;
curSpan = null;
curFlow = null;
}
/**
* This is called from FlowLayoutManager when it needs to start
* a new flow container (while generating areas).
*
* @param childArea The area for which a container is needed. It must be
* some kind of block-level area. It must have area-class, break-before
* and span properties set.
* @return the parent area
*/
public Area getParentArea(Area childArea) {
int aclass = childArea.getAreaClass();
if (aclass == Area.CLASS_NORMAL) {
// todo: how to get properties from the Area???
// Need span, break
int breakVal = Constants.AUTO;
Integer breakBefore = (Integer)childArea.getTrait(Trait.BREAK_BEFORE);
if (breakBefore != null) {
breakVal = breakBefore.intValue();
}
if (breakVal != Constants.AUTO) {
// We may be forced to make new page
handleBreak(breakVal);
} else if (curPage == null) {
makeNewPage(false, false);
}
// Now we should be on the right kind of page
boolean bNeedSpan = false;
int span = Constants.NONE; // childArea.getSpan()
int numCols = 1;
if (span == Constants.ALL) {
// Assume the number of columns is stored on the curBody object.
//numCols = curBody.getProperty(NUMBER_OF_COLUMNS);
}
if (curSpan == null) {
createBodyMainReferenceArea();
bNeedSpan = true;
} else if (numCols != curSpanColumns) {
// todo: BALANCE EXISTING COLUMNS
if (curSpanColumns > 1) {
// balanceColumns();
}
bNeedSpan = true;
}
if (bNeedSpan) {
// Make a new span and the first flow
createSpan(numCols);
} else if (curFlow == null) {
createFlow();
}
return curFlow;
} else {
if (curPage == null) {
makeNewPage(false, false);
}
// Now handle different kinds of areas
if (aclass == Area.CLASS_BEFORE_FLOAT) {
BeforeFloat bf = curBody.getBeforeFloat();
if (bf == null) {
bf = new BeforeFloat();
curBody.setBeforeFloat(bf);
}
return bf;
} else if (aclass == Area.CLASS_FOOTNOTE) {
Footnote fn = curBody.getFootnote();
if (fn == null) {
fn = new Footnote();
curBody.setFootnote(fn);
}
return fn;
}
// todo!!! other area classes (side-float, absolute, fixed)
return null;
}
}
/**
* Depending on the kind of break condition, make new column
* or page. May need to make an empty page if next page would
* not have the desired "handedness".
*
* @param breakVal the break value to handle
*/
private void handleBreak(int breakVal) {
if (breakVal == Constants.COLUMN) {
if (curSpan != null
&& curSpan.getColumnCount() != curSpanColumns) {
// Move to next column
createFlow();
return;
}
// else need new page
breakVal = Constants.PAGE;
}
if (needEmptyPage(breakVal)) {
curPage = makeNewPage(true, false);
}
if (needNewPage(breakVal)) {
curPage = makeNewPage(false, false);
}
}
/**
* If we have already started to layout content on a page,
* and there is a forced break, see if we need to generate
* an empty page.
* Note that if not all content is placed, we aren't sure whether
* it will flow onto another page or not, so we'd probably better
* block until the queue of layoutable stuff is empty!
*/
private boolean needEmptyPage(int breakValue) {
if (breakValue == Constants.PAGE || curPage.getPage().isEmpty()) {
// any page is OK or we already have an empty page
return false;
}
else {
/* IF we are on the kind of page we need, we'll need a new page. */
if (pageCount%2 != 0) {
// Current page is odd
return (breakValue == Constants.ODD_PAGE);
}
else {
return (breakValue == Constants.EVEN_PAGE);
}
}
}
/**
* See if need to generate a new page for a forced break condition.
*/
private boolean needNewPage(int breakValue) {
if (curPage.getPage().isEmpty()) {
if (breakValue == Constants.PAGE) {
return false;
}
else if (pageCount%2 != 0) {
// Current page is odd
return (breakValue == Constants.EVEN_PAGE);
}
else {
return (breakValue == Constants.ODD_PAGE);
}
}
else {
return true;
}
}
private void createBodyMainReferenceArea() {
curBody.setMainReference(new MainReference());
}
private Flow createFlow() {
curFlow = new Flow();
curFlow.setIPD(curSpan.getIPD()); // adjust for columns
//curFlow.setBPD(100000);
// Set IPD and max BPD on the curFlow from curBody
curSpan.addFlow(curFlow);
return curFlow;
}
private void createSpan(int numCols) {
// check number of columns (= all in Body or 1)
// If already have a span, get its size and position (as MinMaxOpt)
// This determines the position of the new span area
// Attention: space calculation between the span areas.
//MinOptMax newpos ;
//if (curSpan != null) {
//newpos = curSpan.getPosition(BPD);
//newpos.add(curSpan.getDimension(BPD));
//}
//else newpos = new MinOptMax();
curSpan = new Span(numCols);
curSpanColumns = numCols;
// get Width or Height as IPD for span
RegionViewport rv = curPage.getPage().getRegionViewport(FO_REGION_BODY);
int ipdWidth = (int) rv.getRegion().getIPD() -
rv.getBorderAndPaddingWidthStart() - rv.getBorderAndPaddingWidthEnd();
curSpan.setIPD(ipdWidth);
//curSpan.setPosition(BPD, newpos);
curBody.getMainReference().addSpan(curSpan);
createFlow();
}
// See finishPage...
protected void flush() {
finishPage();
}
/**
* Called when a new page is needed.
*
* @param bIsBlank If true, use a master for a blank page.
* @param bIsLast If true, use the master for the last page in the sequence.
* @return the page viewport created for the page number
* @throws FOPException if there is an error creating page
*/
private PageViewport createPage(boolean bIsBlank, boolean bIsLast)
throws FOPException {
currentSimplePageMaster = getSimplePageMasterToUse(bIsBlank);
Region body = currentSimplePageMaster.getRegion(FO_REGION_BODY);
if (!pageSequence.getMainFlow().getPropString(PR_FLOW_NAME).equals(body.getRegionName())) {
throw new FOPException("Flow '" + pageSequence.getMainFlow().getPropString(PR_FLOW_NAME)
+ "' does not map to the region-body in page-master '"
+ currentSimplePageMaster.getMasterName() + "'");
}
PageViewport p = createPageAreas(currentSimplePageMaster);
return p;
// The page will have a viewport/reference area pair defined
// for each region in the master.
// Set up the page itself
// SKIP ALL THIS FOR NOW!!!
// //pageSequence.root.setRunningPageNumberCounter(pageSequence.currentPageNumber);
// pageSequence.pageCount++; // used for 'force-page-count' calculations
// handle the 'force-page-count'
//forcePage(areaTree, firstAvailPageNumber);
}
private SimplePageMaster getSimplePageMasterToUse(boolean bIsBlank)
throws FOPException {
if (pageSequence.getPageSequenceMaster() == null) {
return pageSequence.getSimplePageMaster();
}
boolean isOddPage = ((pageCount % 2) == 1);
return pageSequence.getPageSequenceMaster()
.getNextSimplePageMaster(isOddPage, isFirstPage, bIsBlank);
}
private PageViewport createPageAreas(SimplePageMaster spm) {
int pageWidth = spm.getPropLength(PR_PAGE_WIDTH);
int pageHeight = spm.getPropLength(PR_PAGE_HEIGHT);
// Set the page dimension as the toplevel containing block for margin.
((FObj) fobj.getParent()).setLayoutDimension(PercentBase.BLOCK_IPD, pageWidth);
((FObj) fobj.getParent()).setLayoutDimension(PercentBase.BLOCK_BPD, pageHeight);
// Get absolute margin properties (top, left, bottom, right)
CommonMarginBlock mProps = spm.getPropertyManager().getMarginProps();
/* Create the page reference area rectangle (0,0 is at top left
* of the "page media" and y increases
* when moving towards the bottom of the page.
* The media rectangle itself is (0,0,pageWidth,pageHeight).
*/
Rectangle pageRefRect =
new Rectangle(mProps.marginLeft, mProps.marginTop,
pageWidth - mProps.marginLeft - mProps.marginRight,
pageHeight - mProps.marginTop - mProps.marginBottom);
Page page = new Page(); // page reference area
// Set up the CTM on the page reference area based on writing-mode
// and reference-orientation
FODimension reldims = new FODimension(0, 0);
CTM pageCTM = CTM.getCTMandRelDims(spm.getPropertyManager().getAbsRefOrient(),
spm.getPropertyManager().getWritingMode(), pageRefRect, reldims);
// Create a RegionViewport/ reference area pair for each page region
for (Iterator regenum = spm.getRegions().values().iterator();
regenum.hasNext();) {
Region r = (Region)regenum.next();
r.setLayoutDimension(PercentBase.BLOCK_IPD, pageWidth);
r.setLayoutDimension(PercentBase.BLOCK_BPD, pageHeight);
RegionViewport rvp = makeRegionViewport(r, reldims, pageCTM);
if (r.getNameId() == FO_REGION_BODY) {
rvp.setRegion(makeRegionBodyReferenceArea(r, rvp.getViewArea()));
} else {
rvp.setRegion(makeRegionReferenceArea(r, rvp.getViewArea()));
}
page.setRegionViewport(r.getNameId(), rvp);
}
return new PageViewport(page, new Rectangle(0, 0, pageWidth, pageHeight));
}
/**
* Creates a RegionViewport Area object for this pagination Region.
* @param reldims relative dimensions
* @param pageCTM page coordinate transformation matrix
* @return the new region viewport
*/
private RegionViewport makeRegionViewport(Region r, FODimension reldims, CTM pageCTM) {
Rectangle2D relRegionRect = r.getViewportRectangle(reldims);
Rectangle2D absRegionRect = pageCTM.transform(relRegionRect);
// Get the region viewport rectangle in absolute coords by
// transforming it using the page CTM
RegionViewport rv = new RegionViewport(absRegionRect);
setRegionViewportTraits(r, rv);
return rv;
}
/**
* Set the region viewport traits.
* The viewport has the border, background and
* clipping overflow traits.
*
* @param r the region viewport
*/
private void setRegionViewportTraits(Region r, RegionViewport rv) {
// Common Border, Padding, and Background Properties
CommonBorderAndPadding bap = r.getPropertyManager().getBorderAndPadding();
CommonBackground bProps = r.getPropertyManager().getBackgroundProps();
TraitSetter.addBorders(rv, bap);
TraitSetter.addBackground(rv, bProps);
}
private RegionReference makeRegionBodyReferenceArea(Region r,
Rectangle2D absRegVPRect) {
// Should set some column stuff here I think, or put it elsewhere
BodyRegion body = new BodyRegion();
setRegionPosition(r, body, absRegVPRect);
int columnCount =
r.getProperty(PR_COLUMN_COUNT).getNumber().intValue();
if ((columnCount > 1) && (r.overflow == Overflow.SCROLL)) {
// recover by setting 'column-count' to 1. This is allowed but
// not required by the spec.
log.error("Setting 'column-count' to 1 because "
+ "'overflow' is set to 'scroll'");
columnCount = 1;
}
body.setColumnCount(columnCount);
int columnGap = r.getPropLength(PR_COLUMN_GAP);
body.setColumnGap(columnGap);
return body;
}
/**
* Create the region reference area for this region master.
* @param absRegVPRect The region viewport rectangle is "absolute" coordinates
* where x=distance from left, y=distance from bottom, width=right-left
* height=top-bottom
* @return a new region reference area
*/
private RegionReference makeRegionReferenceArea(Region r,
Rectangle2D absRegVPRect) {
RegionReference rr = new RegionReference(r.getNameId());
setRegionPosition(r, rr, absRegVPRect);
return rr;
}
/**
* Set the region position inside the region viewport.
* This sets the trasnform that is used to place the contents of
* the region.
*
* @param r the region reference area
* @param absRegVPRect the rectangle to place the region contents
*/
private void setRegionPosition(Region r, RegionReference rr,
Rectangle2D absRegVPRect) {
FODimension reldims = new FODimension(0, 0);
rr.setCTM(CTM.getCTMandRelDims(r.getPropertyManager().getAbsRefOrient(),
r.getPropertyManager().getWritingMode(), absRegVPRect, reldims));
rr.setIPD(reldims.ipd);
rr.setBPD(reldims.bpd);
}
/**
* @return a StaticContent layout manager
*/
private StaticContentLayoutManager getStaticContentLayoutManager(StaticContent sc) {
StaticContentLayoutManager lm =
(StaticContentLayoutManager)staticContentLMs.get(sc.getPropString(PR_FLOW_NAME));
if (lm != null) {
return lm;
}
lm = new StaticContentLayoutManager();
lm.setFObj(sc);
staticContentLMs.put(sc.getPropString(PR_FLOW_NAME), lm);
return lm;
}
/**
* @return the apps.FOTreeHandler object controlling this generation
*/
public AreaTreeHandler getAreaTreeHandler() {
return areaTreeHandler;
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: fop-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: fop-cvs-help@xml.apache.org