diff options
author | fotis <fotis@unknown> | 2000-11-15 10:26:24 +0000 |
---|---|---|
committer | fotis <fotis@unknown> | 2000-11-15 10:26:24 +0000 |
commit | eb0e581ad71052c6afa1afdba6b576f2b9414a65 (patch) | |
tree | 6efd52bfe8aa12055e1a6fccb3b907f83e8eef27 | |
parent | d03ee13a49a09d14710c8d00cf861062cfc5fc86 (diff) | |
download | xmlgraphics-fop-eb0e581ad71052c6afa1afdba6b576f2b9414a65.tar.gz xmlgraphics-fop-eb0e581ad71052c6afa1afdba6b576f2b9414a65.zip |
region-name support, refactoring of region, PageSequence, PageMasterReference, flow/static [Kelly Campbell, Arved Sandstrom]
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@193805 13f79535-47bb-0310-9956-ffa450edef68
22 files changed, 1293 insertions, 460 deletions
diff --git a/src/org/apache/fop/apps/CommandLine.java b/src/org/apache/fop/apps/CommandLine.java index 3f3711d14..11cf71d33 100644 --- a/src/org/apache/fop/apps/CommandLine.java +++ b/src/org/apache/fop/apps/CommandLine.java @@ -80,6 +80,94 @@ import org.apache.fop.messaging.MessageHandler; */ public class CommandLine { + private String foFile = null; + private String pdfFile = null; + + /** show a full dump on error */ + private static boolean errorDump = false; + + public CommandLine(String[] args) + { + for (int i=0; i<args.length; i++) { + if (args[i].equals("-d") || args[i].equals("--full-error-dump")) { + errorDump = true; + } + else if (args[i].charAt(0) == '-') { + printUsage(args[i]); + } + else if (foFile == null) { + foFile = args[i]; + } + else if (pdfFile == null) { + pdfFile = args[i]; + } + else { + printUsage(args[i]); + } + } + if (foFile == null || pdfFile == null) { + printUsage(null); + } + } + + public void printUsage(String arg) + { + if (arg != null) { + MessageHandler.errorln("Unkown argument: '"+arg+"'"); + MessageHandler.errorln("Usage: java [-d]" + + "org.apache.fop.apps.CommandLine " + + "formatting-object-file pdf-file"); + MessageHandler.errorln("Options:\n" + + " -d or --full-error-dump Show stack traces upon error"); + + System.exit(1); + } + } + + + public void run() { + + XMLReader parser = createParser(); + + if (parser == null) { + MessageHandler.errorln("ERROR: Unable to create SAX parser"); + System.exit(1); + } + + // setting the parser features + try { + parser.setFeature("http://xml.org/sax/features/namespace-prefixes", true); + } catch (SAXException e) { + MessageHandler.errorln("Error in setting up parser feature namespace-prefixes"); + MessageHandler.errorln("You need a parser which supports SAX version 2"); + if (errorDump) { + e.printStackTrace(); + } + System.exit(1); + } + + try { + Driver driver = new Driver(); + driver.setErrorDump(errorDump); + driver.setRenderer("org.apache.fop.render.pdf.PDFRenderer", Version.getVersion()); + driver.addElementMapping("org.apache.fop.fo.StandardElementMapping"); + driver.addElementMapping("org.apache.fop.svg.SVGElementMapping"); + driver.addPropertyList("org.apache.fop.fo.StandardPropertyListMapping"); + driver.addPropertyList("org.apache.fop.svg.SVGPropertyListMapping"); + driver.buildFOTree(parser, fileInputSource(foFile)); + driver.format(); + driver.setWriter(new PrintWriter(new FileWriter(pdfFile))); + driver.render(); + } catch (Exception e) { + MessageHandler.errorln("FATAL ERROR: " + e.getMessage()); + if (errorDump){ + e.printStackTrace(); + } + System.exit(1); + } + } + + /** * creates a SAX parser, using the value of org.xml.sax.parser * defaulting to org.apache.xerces.parsers.SAXParser @@ -99,13 +187,25 @@ public class CommandLine { Class.forName(parserClassName).newInstance(); } catch (ClassNotFoundException e) { org.apache.fop.messaging.MessageHandler.errorln("Could not find " + parserClassName); + if (errorDump){ + e.printStackTrace(); + } } catch (InstantiationException e) { org.apache.fop.messaging.MessageHandler.errorln("Could not instantiate " + parserClassName); + if (errorDump){ + e.printStackTrace(); + } } catch (IllegalAccessException e) { org.apache.fop.messaging.MessageHandler.errorln("Could not access " + parserClassName); + if (errorDump){ + e.printStackTrace(); + } } catch (ClassCastException e) { org.apache.fop.messaging.MessageHandler.errorln(parserClassName + " is not a SAX driver"); + if (errorDump){ + e.printStackTrace(); + } } return null; } @@ -145,47 +245,11 @@ public class CommandLine { */ public static void main(String[] args) { String version = Version.getVersion(); - MessageHandler.errorln(version); - - - - if (args.length != 2) { - MessageHandler.errorln("usage: java " - + "org.apache.fop.apps.CommandLine " - + "formatting-object-file pdf-file"); - System.exit(1); - } - - XMLReader parser = createParser(); - - if (parser == null) { - MessageHandler.errorln("ERROR: Unable to create SAX parser"); - System.exit(1); - } + MessageHandler.errorln(version); + + CommandLine cmdLine = new CommandLine(args); + cmdLine.run(); - // setting the parser features - try { - parser.setFeature("http://xml.org/sax/features/namespace-prefixes", true); - } catch (SAXException e) { - MessageHandler.errorln("Error in setting up parser feature namespace-prefixes"); - MessageHandler.errorln("You need a parser which supports SAX version 2"); - System.exit(1); - } - - try { - Driver driver = new Driver(); - driver.setRenderer("org.apache.fop.render.pdf.PDFRenderer", version); - driver.addElementMapping("org.apache.fop.fo.StandardElementMapping"); - driver.addElementMapping("org.apache.fop.svg.SVGElementMapping"); - driver.addPropertyList("org.apache.fop.fo.StandardPropertyListMapping"); - driver.addPropertyList("org.apache.fop.svg.SVGPropertyListMapping"); - driver.setWriter(new PrintWriter(new FileWriter(args[1]))); - driver.buildFOTree(parser, fileInputSource(args[0])); - driver.format(); - driver.render(); - } catch (Exception e) { - MessageHandler.errorln("FATAL ERROR: " + e.getMessage()); - System.exit(1); - } } + } diff --git a/src/org/apache/fop/apps/Driver.java b/src/org/apache/fop/apps/Driver.java index d48b64306..ff2ad79bc 100644 --- a/src/org/apache/fop/apps/Driver.java +++ b/src/org/apache/fop/apps/Driver.java @@ -129,11 +129,22 @@ public class Driver { /** the PrintWriter to use to output the results of the renderer */ protected PrintWriter writer; + /** If true, full error stacks are reported */ + protected boolean errorDump; + /** create a new Driver */ public Driver() { this.treeBuilder = new FOTreeBuilder(); } + /** Set the error dump option + * @param dump if true, full stacks will be reported to the error log + */ + public void setErrorDump(boolean dump) + { + errorDump = dump; + } + /** set the Renderer to use */ public void setRenderer(Renderer renderer) { this.renderer = renderer; @@ -199,13 +210,17 @@ public class Driver { Class.forName(mappingClassName).newInstance(); } catch (ClassNotFoundException e) { MessageHandler.errorln("Could not find " + mappingClassName); + dumpError(e); } catch (InstantiationException e) { MessageHandler.errorln("Could not instantiate " + mappingClassName); + dumpError(e); } catch (IllegalAccessException e) { MessageHandler.errorln("Could not access " + mappingClassName); + dumpError(e); } catch (ClassCastException e) { MessageHandler.errorln(mappingClassName + " is not an element mapping"); + dumpError(e); } return null; } @@ -229,13 +244,17 @@ public class Driver { Class.forName(listClassName).newInstance(); } catch (ClassNotFoundException e) { MessageHandler.errorln("Could not find " + listClassName); + dumpError(e); } catch (InstantiationException e) { MessageHandler.errorln("Could not instantiate " + listClassName); + dumpError(e); } catch (IllegalAccessException e) { MessageHandler.errorln("Could not access " + listClassName); + dumpError(e); } catch (ClassCastException e) { MessageHandler.errorln(listClassName + " is not an property list"); + dumpError(e); } return null; } @@ -262,11 +281,16 @@ public class Driver { try { parser.parse(source); } catch (SAXException e) { - if (e.getException() instanceof FOPException) + if (e.getException() instanceof FOPException) { + dumpError(e.getException()); throw (FOPException) e.getException(); - else + } + else { + dumpError(e); throw new FOPException(e.getMessage()); + } } catch (IOException e) { + dumpError(e); throw new FOPException(e.getMessage()); } } @@ -356,11 +380,32 @@ public class Driver { } } } catch (SAXException e) { + dumpError(e); throw new FOPException(e.getMessage()); } } /** + * Dumps an error + */ + public void dumpError(Exception e) + { + if (errorDump) { + if (e instanceof SAXException) { + e.printStackTrace(); + if (((SAXException)e).getException() != null) { + ((SAXException)e).getException().printStackTrace(); + } + } + else { + e.printStackTrace(); + } + } + + } + + + /** * set the PrintWriter to use to output the result of the Renderer * (if applicable) */ diff --git a/src/org/apache/fop/fo/PropertyListBuilder.java b/src/org/apache/fop/fo/PropertyListBuilder.java index b625d6720..ddeaba833 100644 --- a/src/org/apache/fop/fo/PropertyListBuilder.java +++ b/src/org/apache/fop/fo/PropertyListBuilder.java @@ -183,7 +183,11 @@ public class PropertyListBuilder { else { propVal = propertyMaker.make(p,attributes.getValue(i),fo); } - p.put(propName,propVal); + + if (propVal != null) { + p.put(propName,propVal); + } + } else { //MessageHandler.errorln("WARNING: property " + attributeName + " ignored"); } diff --git a/src/org/apache/fop/fo/flow/Flow.java b/src/org/apache/fop/fo/flow/Flow.java index 58ddefa9d..70b677979 100644 --- a/src/org/apache/fop/fo/flow/Flow.java +++ b/src/org/apache/fop/fo/flow/Flow.java @@ -54,9 +54,10 @@ package org.apache.fop.fo.flow; // FOP import org.apache.fop.fo.*; import org.apache.fop.fo.properties.*; -import org.apache.fop.fo.pagination.PageSequence; +import org.apache.fop.fo.pagination.*; import org.apache.fop.layout.Area; import org.apache.fop.apps.FOPException; +import org.apache.fop.messaging.MessageHandler; // Java import java.util.Hashtable; @@ -75,13 +76,22 @@ public class Flow extends FObj { return new Flow.Maker(); } - PageSequence pageSequence; - private Area area; // Area in which we lay out our kids + /** PageSequence container */ + private PageSequence pageSequence; + + /** Area in which we lay out our kids */ + private Area area; + + /** flow-name attribute */ + private String _flowName; + + private Status _status = new Status(Status.AREA_FULL_NONE); + protected Flow(FObj parent, PropertyList propertyList) throws FOPException { super(parent, propertyList); - this.name = "fo:flow"; + this.name = getElementName(); if (parent.getName().equals("fo:page-sequence")) { this.pageSequence = (PageSequence) parent; @@ -89,11 +99,35 @@ public class Flow extends FObj { throw new FOPException("flow must be child of " + "page-sequence, not " + parent.getName()); - } - pageSequence.setFlow(this); + } + setFlowName(getProperty("flow-name").getString()); + pageSequence.addFlow(this); } + + protected void setFlowName(String name) + throws FOPException + { + if (name == null || name.equals("")) { + MessageHandler.errorln("WARNING: A 'flow-name' is required for "+getElementName()+". This constraint will be enforced in future versions of FOP"); + _flowName = "xsl-region-body"; + } + else { + _flowName = name; + } + } + + public String getFlowName() + { + return _flowName; + } + public Status layout(Area area) throws FOPException { + return layout(area, null); + + } + + public Status layout(Area area, Region region) throws FOPException { if (this.marker == START) { this.marker = 0; } @@ -103,23 +137,23 @@ public class Flow extends FObj { int numChildren = this.children.size(); for (int i = this.marker; i < numChildren; i++) { FObj fo = (FObj) children.elementAt(i); - Status status; - if ((status = fo.layout(area)).isIncomplete()) { - if ((prevChildMustKeepWithNext) && (status.laidOutNone())) { + if ((_status = fo.layout(area)).isIncomplete()) { + if ((prevChildMustKeepWithNext) && (_status.laidOutNone())) { this.marker = i - 1; FObj prevChild = (FObj) children.elementAt(this.marker); prevChild.removeAreas(); prevChild.resetMarker(); prevChild.removeID(area.getIDReferences()); - return new Status(Status.AREA_FULL_SOME); + _status = new Status(Status.AREA_FULL_SOME); + return _status; // should probably return AREA_FULL_NONE if first // or perhaps an entirely new status code } else { this.marker = i; - return status; + return _status; } } - if (status.getCode() == Status.KEEP_WITH_NEXT) { + if (_status.getCode() == Status.KEEP_WITH_NEXT) { prevChildMustKeepWithNext = true; } else { @@ -127,7 +161,8 @@ public class Flow extends FObj { } } - return new Status(Status.OK); + _status = new Status(Status.OK); + return _status; } /** @@ -139,4 +174,17 @@ public class Flow extends FObj { return area.getContentWidth(); //getAllocationWidth()?? else return 0; // not laid out yet } + + protected String getElementName() + { + return "fo:flow"; + } + + public Status getStatus() + { + return _status; + } + + + } diff --git a/src/org/apache/fop/fo/flow/StaticContent.java b/src/org/apache/fop/fo/flow/StaticContent.java index 9394c21d7..f9ea28ecc 100644 --- a/src/org/apache/fop/fo/flow/StaticContent.java +++ b/src/org/apache/fop/fo/flow/StaticContent.java @@ -53,14 +53,14 @@ package org.apache.fop.fo.flow; // FOP import org.apache.fop.fo.*; import org.apache.fop.fo.properties.*; -import org.apache.fop.fo.pagination.PageSequence; +import org.apache.fop.fo.pagination.*; import org.apache.fop.layout.Area; import org.apache.fop.apps.FOPException; // Java import java.util.Enumeration; -public class StaticContent extends FObj { +public class StaticContent extends Flow { public static class Maker extends FObj.Maker { public FObj make(FObj parent, PropertyList propertyList) @@ -73,37 +73,39 @@ public class StaticContent extends FObj { return new StaticContent.Maker(); } - PageSequence pageSequence; - protected StaticContent(FObj parent, PropertyList propertyList) throws FOPException { super(parent, propertyList); - this.name = "fo:static-content"; - - if (parent.getName().equals("fo:page-sequence")) { - this.pageSequence = (PageSequence) parent; - } else { - throw new FOPException("static-content must be child of " - + "fo:page-sequence, not " - + parent.getName()); - } - String flowName = this.properties.get("flow-name").getString(); - - pageSequence.setStaticContent(flowName, this); } public Status layout(Area area) throws FOPException { + return layout(area, null); + } + + + public Status layout(Area area, Region region) throws FOPException { int numChildren = this.children.size(); // Set area absolute height so that link rectangles will be drawn correctly in xsl-before and xsl-after - String flowName = this.properties.get("flow-name").getString(); - if(flowName.equals("xsl-region-before")) - { - area.setAbsoluteHeight(-area.getMaxHeight()); + String regionClass = "none"; + if (region != null) { + regionClass = region.getRegionClass(); } - else if(flowName.equals("xsl-region-after")) - { - area.setAbsoluteHeight(area.getPage().getBody().getMaxHeight()); + else { + if(getFlowName().equals("xsl-region-before")) { + regionClass = RegionBefore.REGION_CLASS; + } + else if(getFlowName().equals("xsl-region-after")) { + regionClass = RegionAfter.REGION_CLASS; + } + + } + + if(regionClass.equals(RegionBefore.REGION_CLASS)) { + area.setAbsoluteHeight(-area.getMaxHeight()); + } + else if(regionClass.equals(RegionAfter.REGION_CLASS)) { + area.setAbsoluteHeight(area.getPage().getBody().getMaxHeight()); } for (int i = 0; i < numChildren; i++) { @@ -117,9 +119,26 @@ public class StaticContent extends FObj { } return(status); } -// fo.layout(area); } resetMarker(); return new Status(Status.OK); } + + protected String getElementName() + { + return "fo:static-content"; + } + + // flowname checking is more stringient for static content currently + protected void setFlowName(String name) + throws FOPException + { + if (name == null || name.equals("")) { + throw new FOPException("A 'flow-name' is required for "+getElementName()+"."); + } + else { + super.setFlowName(name); + } + + } } diff --git a/src/org/apache/fop/fo/pagination/ConditionalPageMasterReference.java b/src/org/apache/fop/fo/pagination/ConditionalPageMasterReference.java index 5db191dfe..4f6fafacb 100644 --- a/src/org/apache/fop/fo/pagination/ConditionalPageMasterReference.java +++ b/src/org/apache/fop/fo/pagination/ConditionalPageMasterReference.java @@ -55,8 +55,8 @@ import org.apache.fop.fo.properties.*; import org.apache.fop.apps.FOPException; import org.apache.fop.messaging.MessageHandler; -public class ConditionalPageMasterReference - extends PageMasterReference implements SubSequenceSpecifier { +public class ConditionalPageMasterReference extends FObj +{ public static class Maker extends FObj.Maker { public FObj make(FObj parent, PropertyList propertyList) @@ -69,41 +69,48 @@ public class ConditionalPageMasterReference return new ConditionalPageMasterReference.Maker(); } - private String masterName; - private RepeatablePageMasterAlternatives repeatablePageMasterAlternatives; - - private int pagePosition; - private int oddOrEven; - private int blankOrNotBlank; - + private RepeatablePageMasterAlternatives repeatablePageMasterAlternatives; + + private String masterName; + + private int pagePosition; + private int oddOrEven; + private int blankOrNotBlank; + public ConditionalPageMasterReference(FObj parent, PropertyList propertyList) throws FOPException { super(parent, propertyList); - this.name = "fo:conditional-page-master-reference"; - if (parent.getName().equals("fo:repeatable-page-master-alternatives")) { - this.repeatablePageMasterAlternatives = - (RepeatablePageMasterAlternatives) parent; - setMasterName( this.properties.get("master-name").getString() ); - if (getMasterName() == null) { - System.err.println("WARNING: single-page-master-reference" + - "does not have a master-name and so is being ignored"); - } else { - this.repeatablePageMasterAlternatives.addConditionalPageMasterReference(this); - } - - setPagePosition( this.properties.get("page-position").getEnum() ); - setOddOrEven( this.properties.get("odd-or-even").getEnum() ); - setBlankOrNotBlank( this.properties.get("blank-or-not-blank").getEnum() ); - - } else { - throw new FOPException("fo:conditional-page-master-reference must be child " - + "of fo:repeatable-page-master-alternatives, not " - + parent.getName()); + this.name = getElementName(); + if (getProperty("master-name") != null) { + setMasterName(getProperty("master-name").getString() ); } + + validateParent(parent); + + setPagePosition( this.properties.get("page-position").getEnum() ); + setOddOrEven( this.properties.get("odd-or-even").getEnum() ); + setBlankOrNotBlank( this.properties.get("blank-or-not-blank").getEnum() ); + + } - protected boolean isValid( int currentPageNumber, boolean thisIsFirstPage ) + protected void setMasterName( String masterName ) + { + this.masterName = masterName; + } + + /** + * Returns the "master-name" attribute of this page master reference + */ + public String getMasterName() + { + return masterName; + } + + + protected boolean isValid( int currentPageNumber, boolean thisIsFirstPage, + boolean isEmptyPage) { // page-position boolean okOnPagePosition = true; // default is 'any' @@ -137,9 +144,22 @@ public class ConditionalPageMasterReference okOnOddOrEven = false; } - // no check for blankness at the moment + // experimental check for blank-or-not-blank + + boolean okOnBlankOrNotBlank = true; // default is 'any' + + int bnb = getBlankOrNotBlank(); + + if ((BlankOrNotBlank.BLANK == bnb) && !isEmptyPage) { + okOnBlankOrNotBlank = false; + } + else if ((BlankOrNotBlank.NOT_BLANK == bnb) && isEmptyPage) { + okOnBlankOrNotBlank = false; + } + + return (okOnOddOrEven && okOnPagePosition && + okOnBlankOrNotBlank); - return (okOnOddOrEven && okOnPagePosition); } protected void setPagePosition( int pagePosition ) @@ -171,4 +191,32 @@ public class ConditionalPageMasterReference { return this.blankOrNotBlank; } + + protected String getElementName() + { + return "fo:conditional-page-master-reference"; + } + + + protected void validateParent(FObj parent) + throws FOPException + { + if (parent.getName().equals("fo:repeatable-page-master-alternatives")) { + this.repeatablePageMasterAlternatives = + (RepeatablePageMasterAlternatives) parent; + + if (getMasterName() == null) { + MessageHandler.errorln("WARNING: single-page-master-reference" + + "does not have a master-name and so is being ignored"); + } else { + this.repeatablePageMasterAlternatives.addConditionalPageMasterReference(this); + } + } else { + throw new FOPException("fo:conditional-page-master-reference must be child " + + "of fo:repeatable-page-master-alternatives, not " + + parent.getName()); + } + } + + } diff --git a/src/org/apache/fop/fo/pagination/LayoutMasterSet.java b/src/org/apache/fop/fo/pagination/LayoutMasterSet.java index b0f8c32de..89d32c8c5 100644 --- a/src/org/apache/fop/fo/pagination/LayoutMasterSet.java +++ b/src/org/apache/fop/fo/pagination/LayoutMasterSet.java @@ -55,10 +55,9 @@ import org.apache.fop.fo.*; import org.apache.fop.fo.properties.*; import org.apache.fop.apps.FOPException; import org.apache.fop.layout.PageMaster; -import org.apache.fop.apps.FOPException; // Java -import java.util.Hashtable; +import java.util.*; public class LayoutMasterSet extends FObj { @@ -74,8 +73,10 @@ public class LayoutMasterSet extends FObj { } private Hashtable simplePageMasters; - private Hashtable pageSequenceMasters; - private Root root; + private Hashtable pageSequenceMasters; + private Hashtable allRegions; + + private Root root; protected LayoutMasterSet(FObj parent, PropertyList propertyList) throws FOPException { @@ -93,48 +94,27 @@ public class LayoutMasterSet extends FObj { new FOPException("fo:layout-master-set must be child of fo:root, not " + parent.getName()); } + allRegions = new Hashtable(); + } - public PageMaster getNextPageMaster( String pageSequenceName, - int currentPageNumber, boolean thisIsFirstPage ) - throws FOPException - { - PageMaster pm = null; - - PageSequenceMaster psm = getPageSequenceMaster( pageSequenceName ); - if (null != psm) - { - pm = psm.getNextPageMaster( currentPageNumber, thisIsFirstPage ); - } else { - SimplePageMaster spm = getSimplePageMaster( pageSequenceName ); - if (null == spm) - { - throw new FOPException( "'master-name' for 'fo:page-sequence'" + - "matches no 'simple-page-master' or 'page-sequence-master'" ); - } - pm = spm.getNextPageMaster(); - } - return pm; - } - - protected void addSimplePageMaster( - String masterName, SimplePageMaster simplePageMaster) + protected void addSimplePageMaster(SimplePageMaster simplePageMaster) throws FOPException { // check against duplication of master-name - if (existsName(masterName)) + if (existsName(simplePageMaster.getMasterName())) throw new FOPException( "'master-name' must be unique" + "across page-masters and page-sequence-masters" ); - this.simplePageMasters.put(masterName, simplePageMaster); + this.simplePageMasters.put(simplePageMaster.getMasterName(), simplePageMaster); } protected SimplePageMaster getSimplePageMaster(String masterName) { - return (SimplePageMaster)this.simplePageMasters.get(masterName); + return (SimplePageMaster)this.simplePageMasters.get(masterName); } protected void addPageSequenceMaster( String masterName, PageSequenceMaster pageSequenceMaster) throws FOPException { - // check against duplication of master-name + // check against duplication of master-name if (existsName(masterName)) throw new FOPException( "'master-name' must be unique " + "across page-masters and page-sequence-masters" ); @@ -153,4 +133,38 @@ public class LayoutMasterSet extends FObj { else return false; } + + protected void resetPageMasters() + { + for (Enumeration e = pageSequenceMasters.elements(); e.hasMoreElements(); ) + { + ((PageSequenceMaster)e.nextElement()).reset(); + } + + } + + protected void checkRegionNames() throws FOPException + { + // Section 7.33.15 check to see that if a region-name is a + // duplicate, that it maps to the same region-class. + for (Enumeration spm = simplePageMasters.elements(); spm.hasMoreElements(); ) { + SimplePageMaster simplePageMaster = (SimplePageMaster)spm.nextElement(); + Hashtable spmRegions = simplePageMaster.getRegions(); + for (Enumeration e = spmRegions.elements(); e.hasMoreElements(); ) { + Region region = (Region)e.nextElement(); + if (allRegions.containsKey(region.getRegionName())) { + String localClass = (String)allRegions.get(region.getRegionName()); + if (!localClass.equals(region.getRegionClass())) { + throw new FOPException("Duplicate region-names must map " + + "to the same region-class"); + } + } + allRegions.put(region.getRegionName(),region.getRegionClass()); + } + } + } + + + + } diff --git a/src/org/apache/fop/fo/pagination/PageMasterReference.java b/src/org/apache/fop/fo/pagination/PageMasterReference.java index b177f7251..3c88405bc 100644 --- a/src/org/apache/fop/fo/pagination/PageMasterReference.java +++ b/src/org/apache/fop/fo/pagination/PageMasterReference.java @@ -55,38 +55,88 @@ import org.apache.fop.fo.properties.*; import org.apache.fop.apps.FOPException; import org.apache.fop.messaging.MessageHandler; -public class PageMasterReference extends FObj implements SubSequenceSpecifier { - - public static class Maker extends FObj.Maker { - public FObj make(FObj parent, PropertyList propertyList) - throws FOPException { - return new PageMasterReference(parent,propertyList); - } - } +/** + * Base PageMasterReference class. Provides implementation for handling the + * master-name attribute and containment within a PageSequenceMaster + */ +public abstract class PageMasterReference extends FObj + implements SubSequenceSpecifier +{ - public static FObj.Maker maker() { - return new PageMasterReference.Maker(); - } + private String _masterName; + private PageSequenceMaster _pageSequenceMaster; - private String masterName; - public PageMasterReference(FObj parent, PropertyList propertyList) - throws FOPException { - super(parent, propertyList); - } - - public void setMasterName( String masterName ) - { - this.masterName = masterName; + throws FOPException + { + super(parent, propertyList); + this.name = getElementName(); + if (getProperty("master-name") != null) { + setMasterName(getProperty("master-name").getString() ); } + validateParent(parent); + } + + protected void setMasterName( String masterName ) + { + _masterName = masterName; + } + + /** + * Returns the "master-name" attribute of this page master reference + */ public String getMasterName() - { - return this.masterName; - } + { + return _masterName; + } - public String getNextPageMaster( int currentPageNumber, - boolean thisIsFirstPage ) { - return getMasterName(); + protected void setPageSequenceMaster(PageSequenceMaster pageSequenceMaster) + { + _pageSequenceMaster = pageSequenceMaster; + } + + protected PageSequenceMaster getPageSequenceMaster() + { + return _pageSequenceMaster; + } + + public abstract String getNextPageMaster(int currentPageNumber, + boolean thisIsFirstPage, boolean isEmptyPage); + + /** + * Gets the formating object name for this object. Subclasses must provide this. + * + * @return the element name of this reference. e.g. fo:repeatable-page-master-reference + */ + protected abstract String getElementName(); + + /** + * Checks that the parent is the right element. The default implementation + * checks for fo:page-sequence-master + */ + protected void validateParent(FObj parent) + throws FOPException + { + if (parent.getName().equals("fo:page-sequence-master")) { + _pageSequenceMaster = (PageSequenceMaster)parent; + + if (getMasterName() == null) { + MessageHandler.errorln("WARNING: " + getElementName() + + " does not have a master-name and so is being ignored"); + } else { + _pageSequenceMaster.addSubsequenceSpecifier(this); + } + } else { + throw new FOPException(getElementName() + " must be" + + "child of fo:page-sequence-master, not " + + parent.getName()); } + } + + public abstract void reset() ; + + + + } diff --git a/src/org/apache/fop/fo/pagination/PageSequence.java b/src/org/apache/fop/fo/pagination/PageSequence.java index 70930813d..aac9a1ed9 100644 --- a/src/org/apache/fop/fo/pagination/PageSequence.java +++ b/src/org/apache/fop/fo/pagination/PageSequence.java @@ -65,12 +65,18 @@ import org.apache.fop.layout.PageMaster; import org.apache.fop.apps.FOPException; // Java -import java.util.Hashtable; -import java.util.Vector; +import java.util.*; + +/** + * This provides pagination of flows onto pages. Much of the logic for paginating + * flows is contained in this class. The main entry point is the format method. + */ public class PageSequence extends FObj { - + // + // Factory methods + // public static class Maker extends FObj.Maker { public FObj make(FObj parent, PropertyList propertyList) @@ -83,24 +89,61 @@ public class PageSequence extends FObj return new PageSequence.Maker(); } - static final int EXPLICIT = 0; - static final int AUTO = 1; - static final int AUTO_EVEN = 2; - static final int AUTO_ODD = 3; - - protected Root root; - protected Flow flow; - // protected Title title; - protected StaticContent staticBefore; - protected StaticContent staticAfter; - protected LayoutMasterSet layoutMasterSet; - protected String masterName; + // + // intial-page-number types + // + private static final int EXPLICIT = 0; + private static final int AUTO = 1; + private static final int AUTO_EVEN = 2; + private static final int AUTO_ODD = 3; + + // + // associations + // + /** The parent root object */ + private Root root; + + /** the set of layout masters (provided by the root object) */ + private LayoutMasterSet layoutMasterSet; + + // There doesn't seem to be anything in the spec requiring flows + // to be in the order given, only that they map to the regions + // defined in the page sequence, so all we need is this one hashtable + // the set of flows includes StaticContent flows also + + /** Map of flows to their flow name (flow-name, Flow) */ + private Hashtable _flowMap; + + /** the "master-name" attribute */ + private String masterName; - protected Page currentPage; - protected int currentPageNumber = 0; - protected static int runningPageNumberCounter = 0; //keeps count of page number from previous PageSequence - protected int pageNumberType; // specifies page numbering type (auto|auto-even|auto-odd|explicit) - protected boolean thisIsFirstPage; // used to determine whether to calculate auto, auto-even, auto-odd + + // + // state attributes used during layout + // + + private Page currentPage; + + private int currentPageNumber = 0; + + /** keeps count of page number from previous PageSequence */ + private static int runningPageNumberCounter = 0; + + /** specifies page numbering type (auto|auto-even|auto-odd|explicit) */ + private int pageNumberType; + + /** used to determine whether to calculate auto, auto-even, auto-odd */ + private boolean thisIsFirstPage; + + /** the current subsequence while formatting a given page sequence */ + private SubSequenceSpecifier currentSubsequence; + + /** the current index in the subsequence list */ + private int currentSubsequenceNumber = -1; // starting case is -1 so that first getNext increments to 0 + + /** the name of the current page master */ + private String currentPageMasterName; + protected PageSequence(FObj parent, PropertyList propertyList) throws FOPException { @@ -121,6 +164,12 @@ public class PageSequence extends FObj } layoutMasterSet = root.getLayoutMasterSet(); + + // best time to run some checks on LayoutMasterSet + layoutMasterSet.checkRegionNames(); + + _flowMap = new Hashtable(); + thisIsFirstPage=true; // we are now on the first page of the page sequence String ipnValue= this.properties.get("initial-page-number").getString(); @@ -141,7 +190,7 @@ public class PageSequence extends FObj pageNumberType=EXPLICIT; try { - int pageStart = new Integer(ipnValue).intValue(); + int pageStart = new Integer(ipnValue).intValue(); this.currentPageNumber = (pageStart > 0) ? pageStart - 1 : 0; } catch ( NumberFormatException nfe ) @@ -151,37 +200,40 @@ public class PageSequence extends FObj } masterName = this.properties.get("master-name").getString(); - } - - protected Page makePage(AreaTree areaTree) throws FOPException { - // layout this page sequence - - // while there is still stuff in the flow, ask the - // layoutMasterSet for a new page + - // page number is 0-indexed - PageMaster pageMaster = - this.layoutMasterSet.getNextPageMaster( - masterName, currentPageNumber, thisIsFirstPage ); + } + + public void addFlow(Flow flow) + throws FOPException + { + if (_flowMap.containsKey(flow.getFlowName())) { + throw new FOPException("flow-names must be unique within an fo:page-sequence"); + } + _flowMap.put(flow.getFlowName(), flow); - // a legal alternative is to use the last sub-sequence - // specification. That's not done here. - if ( pageMaster == null ) - { - throw new FOPException("page masters exhausted"); - } - return pageMaster.makePage(areaTree); } + + /** + * Runs the formatting of this page sequence into the given area tree + */ public void format(AreaTree areaTree) throws FOPException { Status status = new Status(Status.OK); + this.layoutMasterSet.resetPageMasters(); + do { - currentPage = makePage(areaTree); - + // makePage() moved to after the page-number computations, + // but store the page-number at this point for that method, + // since we want the 'current' current page-number... + int firstAvailPageNumber = this.runningPageNumberCounter; + boolean tempIsFirstPage = false; + if ( thisIsFirstPage ) { + tempIsFirstPage = thisIsFirstPage; if ( pageNumberType==AUTO ) { this.currentPageNumber=this.runningPageNumberCounter; @@ -205,24 +257,35 @@ public class PageSequence extends FObj thisIsFirstPage=false; } - currentPage.setNumber(++this.currentPageNumber); - this.runningPageNumberCounter=this.currentPageNumber; + this.currentPageNumber++; + + // deliberately moved down here so page-number calculations + // are complete; + // compute flag for 'blank-or-not-blank' + boolean isEmptyPage = false; + + if ( (status.getCode() == Status.FORCE_PAGE_BREAK_EVEN) && + ((currentPageNumber % 2) == 1) ) { + isEmptyPage = true; + } + else if ( (status.getCode() == Status.FORCE_PAGE_BREAK_ODD) && + ((currentPageNumber % 2) == 0) ) { + isEmptyPage = true; + } + else { + isEmptyPage = false; + } + + currentPage = makePage(areaTree, firstAvailPageNumber, + tempIsFirstPage, isEmptyPage); + + currentPage.setNumber(this.currentPageNumber); + this.runningPageNumberCounter=this.currentPageNumber; MessageHandler.log(" [" + currentPageNumber); - if ( (this.staticBefore != null) && - (currentPage.getBefore() != null) ) - { - AreaContainer beforeArea = currentPage.getBefore(); - beforeArea.setIDReferences(areaTree.getIDReferences()); - this.staticBefore.layout(beforeArea); - } - if ( (this.staticAfter != null) && - (currentPage.getAfter() != null) ) - { - AreaContainer afterArea = currentPage.getAfter(); - afterArea.setIDReferences(areaTree.getIDReferences()); - this.staticAfter.layout(afterArea); - } + + formatStaticContent(areaTree); + if ( (status.getCode() == Status.FORCE_PAGE_BREAK_EVEN) && ((currentPageNumber % 2) == 1) ) { @@ -235,31 +298,276 @@ public class PageSequence extends FObj { AreaContainer bodyArea = currentPage.getBody(); bodyArea.setIDReferences(areaTree.getIDReferences()); - status = this.flow.layout(bodyArea); + + Flow flow = getCurrentFlow(RegionBody.REGION_CLASS); + + if (null == flow) { + MessageHandler.errorln("No flow found for region-body " + + "in page-master '" + currentPageMasterName + "'"); + break; + + } + else { + status = flow.layout(bodyArea); + } + } MessageHandler.log("]"); areaTree.addPage(currentPage); - } while ( status.isIncomplete() ); + } while ( flowsAreIncomplete() ); + MessageHandler.errorln(""); } - public void setFlow(Flow flow) { - this.flow = flow; - } + /** + * Creates a new page area for the given parameters + * @param areaTree the area tree the page should be contained in + * @param firstAvailPageNumber the page number for this page + * @param isFirstPage true when this is the first page in the sequence + * @param isEmptyPage true if this page will be empty (e.g. forced even or odd break) + * @return a Page layout object based on the page master selected from the params + */ + private Page makePage(AreaTree areaTree, int firstAvailPageNumber, + boolean isFirstPage, boolean isEmptyPage) + throws FOPException { + // layout this page sequence + + // while there is still stuff in the flow, ask the + // layoutMasterSet for a new page - public void setStaticContent(String name, StaticContent staticContent) { - if ( name.equals("xsl-region-before") ) - { - this.staticBefore = staticContent; - } - else if ( name.equals("xsl-region-after") ) - { - this.staticAfter = staticContent; - } - else + // page number is 0-indexed + PageMaster pageMaster = getNextPageMaster(masterName, firstAvailPageNumber, + isFirstPage, isEmptyPage ); + + // a legal alternative is to use the last sub-sequence + // specification which should be handled in getNextSubsequence. That's not done here. + if ( pageMaster == null ) { - MessageHandler.errorln("WARNING: this version of FOP only supports " - + "static-content in xsl-region-before and xsl-region-after"); + throw new FOPException("page masters exhausted. Cannot recover."); } + return pageMaster.makePage(areaTree); + } + + /** + * Formats the static content of the current page + */ + private void formatStaticContent(AreaTree areaTree) + throws FOPException + { + SimplePageMaster simpleMaster = getCurrentSimplePageMaster(); + + if (simpleMaster.getRegion(RegionBefore.REGION_CLASS) != null && (currentPage.getBefore() != null)) { + Flow staticFlow = (Flow)_flowMap.get(simpleMaster.getRegion(RegionBefore.REGION_CLASS).getRegionName()); + if (staticFlow != null) { + AreaContainer beforeArea = currentPage.getBefore(); + beforeArea.setIDReferences(areaTree.getIDReferences()); + layoutStaticContent(staticFlow, simpleMaster.getRegion(RegionBefore.REGION_CLASS), + beforeArea); + } + } + + if (simpleMaster.getRegion(RegionAfter.REGION_CLASS) != null && (currentPage.getAfter() != null)) { + Flow staticFlow = (Flow)_flowMap.get(simpleMaster.getRegion(RegionAfter.REGION_CLASS).getRegionName()); + if (staticFlow != null) { + AreaContainer afterArea = currentPage.getAfter(); + afterArea.setIDReferences(areaTree.getIDReferences()); + layoutStaticContent(staticFlow, simpleMaster.getRegion(RegionAfter.REGION_CLASS), + afterArea); + } + + } + + } + + private void layoutStaticContent(Flow flow, Region region, + AreaContainer area) + throws FOPException + { + if (flow instanceof StaticContent) { + AreaContainer beforeArea = currentPage.getBefore(); + ((StaticContent)flow).layout(area, region); + } + else { + MessageHandler.errorln("WARNING: "+region.getName()+" only supports static-content flows currently. Cannot use flow named '"+flow.getFlowName()+"'"); + } + } + + + + + + /** + * Returns the next SubSequenceSpecifier for the given page sequence master. The result + * is bassed on the current state of this page sequence. + */ + // refactored from PageSequenceMaster + private SubSequenceSpecifier getNextSubsequence(PageSequenceMaster master) + { + if (master.getSubSequenceSpecifierCount() > currentSubsequenceNumber + 1) { + + currentSubsequence = master.getSubSequenceSpecifier(currentSubsequenceNumber + 1); + currentSubsequenceNumber++; + return currentSubsequence; + } + else { + return null; + } + + } + + /** + * Returns the next simple page master for the given sequence master, page number and + * other state information + */ + private SimplePageMaster getNextSimplePageMaster(PageSequenceMaster sequenceMaster, + int currentPageNumber, + boolean thisIsFirstPage, + boolean isEmptyPage) + { + String nextPageMaster = getNextPageMasterName(sequenceMaster, currentPageNumber, thisIsFirstPage, isEmptyPage); + return this.layoutMasterSet.getSimplePageMaster( nextPageMaster ); + + } + + private String getNextPageMasterName(PageSequenceMaster sequenceMaster, + int currentPageNumber, + boolean thisIsFirstPage, + boolean isEmptyPage) + { + + if (null == currentSubsequence) { + currentSubsequence = getNextSubsequence(sequenceMaster); + } + + String nextPageMaster = + currentSubsequence.getNextPageMaster( currentPageNumber, thisIsFirstPage, isEmptyPage ); + + + if (null == nextPageMaster || isFlowForMasterNameDone(currentPageMasterName)) { + SubSequenceSpecifier nextSubsequence = getNextSubsequence(sequenceMaster); + if (nextSubsequence == null) { + MessageHandler.errorln("\nWARNING: Page subsequences exhausted. Using previous subsequence."); + thisIsFirstPage = true; // this becomes the first page in the new (old really) page master + currentSubsequence.reset(); + + // we leave currentSubsequence alone + } + else { + currentSubsequence = nextSubsequence; + } + + nextPageMaster = currentSubsequence.getNextPageMaster( currentPageNumber, + thisIsFirstPage, + isEmptyPage); + } + currentPageMasterName = nextPageMaster; + + return nextPageMaster; + + } + + private SimplePageMaster getCurrentSimplePageMaster() + { + return this.layoutMasterSet.getSimplePageMaster( currentPageMasterName ); + } + + private String getCurrentPageMasterName() + { + return currentPageMasterName; + } + + // refactored from LayoutMasterSet + private PageMaster getNextPageMaster(String pageSequenceName, + int currentPageNumber, + boolean thisIsFirstPage, + boolean isEmptyPage ) + throws FOPException + { + PageMaster pageMaster = null; + + // see if there is a page master sequence for this master name + PageSequenceMaster sequenceMaster = + this.layoutMasterSet.getPageSequenceMaster( pageSequenceName ); + + if (sequenceMaster != null) { + pageMaster = getNextSimplePageMaster(sequenceMaster, + currentPageNumber, + thisIsFirstPage, + isEmptyPage).getPageMaster(); + + } else { // otherwise see if there's a simple master by the given name + SimplePageMaster simpleMaster = + this.layoutMasterSet.getSimplePageMaster( pageSequenceName ); + if (simpleMaster == null) { + throw new FOPException( "'master-name' for 'fo:page-sequence'" + + "matches no 'simple-page-master' or 'page-sequence-master'" ); + } + currentPageMasterName = pageSequenceName; + + pageMaster = simpleMaster.getNextPageMaster(); + } + return pageMaster; + } + + + /** + * Returns true when there is more flow elements left to lay out. + */ + private boolean flowsAreIncomplete() + { + boolean isIncomplete = false; + + for (Enumeration e = _flowMap.elements(); e.hasMoreElements(); ) { + Flow flow = (Flow)e.nextElement(); + if (flow instanceof StaticContent) { + continue; + } + + Status status = flow.getStatus(); + isIncomplete |= status.isIncomplete(); + } + return isIncomplete; + } + + /** + * Returns the flow that maps to the given region class for the current + * page master. + */ + private Flow getCurrentFlow(String regionClass) + { + Region region = getCurrentSimplePageMaster().getRegion(regionClass); + if (region != null) { + Flow flow = (Flow)_flowMap.get(region.getRegionName()); + return flow; + + } + else { + + System.out.println("flow is null. regionClass = '"+regionClass+"' currentSPM = "+getCurrentSimplePageMaster()); + + return null; + } + + } + + private boolean isFlowForMasterNameDone( String masterName ) + { + // parameter is master-name of PMR; we need to locate PM + // referenced by this, and determine whether flow(s) are OK + if (masterName != null) { + + SimplePageMaster spm = this.layoutMasterSet.getSimplePageMaster( masterName ); + Region region = spm.getRegion(RegionBody.REGION_CLASS); + + + Flow flow = (Flow)_flowMap.get( region.getRegionName() ); + if ((null == flow) || flow.getStatus().isIncomplete()) + return false; + else + return true; + } + return false; + } + } diff --git a/src/org/apache/fop/fo/pagination/PageSequenceMaster.java b/src/org/apache/fop/fo/pagination/PageSequenceMaster.java index 068e71bc7..182805ca7 100644 --- a/src/org/apache/fop/fo/pagination/PageSequenceMaster.java +++ b/src/org/apache/fop/fo/pagination/PageSequenceMaster.java @@ -54,12 +54,11 @@ package org.apache.fop.fo.pagination; import org.apache.fop.fo.*; import org.apache.fop.fo.properties.*; import org.apache.fop.layout.PageMaster; -import org.apache.fop.layout.Region; import org.apache.fop.apps.FOPException; import org.apache.fop.messaging.MessageHandler; // Java -import java.util.Vector; +import java.util.*; public class PageSequenceMaster extends FObj { @@ -76,7 +75,7 @@ public class PageSequenceMaster extends FObj { LayoutMasterSet layoutMasterSet; Vector subSequenceSpecifiers; - SubSequenceSpecifier currentPmr; + // The terminology may be confusing. A 'page-sequence-master' consists // of a sequence of what the XSL spec refers to as @@ -95,7 +94,7 @@ public class PageSequenceMaster extends FObj { this.layoutMasterSet = (LayoutMasterSet) parent; String pm = this.properties.get("master-name").getString(); if (pm == null) { - System.err.println("WARNING: page-sequence-master does not have " + MessageHandler.errorln("WARNING: page-sequence-master does not have " + "a page-master-name and so is being ignored"); } else { this.layoutMasterSet.addPageSequenceMaster(pm, this); @@ -109,33 +108,31 @@ public class PageSequenceMaster extends FObj { protected void addSubsequenceSpecifier( SubSequenceSpecifier pageMasterReference ) { - subSequenceSpecifiers.addElement( pageMasterReference ); + subSequenceSpecifiers.addElement( pageMasterReference ); } - protected SubSequenceSpecifier getNextSubsequenceSpecifier() + protected SubSequenceSpecifier getSubSequenceSpecifier(int sequenceNumber) { - currentPmr = (SubSequenceSpecifier)subSequenceSpecifiers.elementAt( 0 ); - subSequenceSpecifiers.removeElementAt(0); - return currentPmr; + if (sequenceNumber >=0 && sequenceNumber < getSubSequenceSpecifierCount()) { + return (SubSequenceSpecifier)subSequenceSpecifiers.elementAt(sequenceNumber); + } + return null; + + } - - public PageMaster getNextPageMaster( int currentPageNumber, boolean thisIsFirstPage ) + + protected int getSubSequenceSpecifierCount() { - if (null == currentPmr) - { - currentPmr = getNextSubsequenceSpecifier(); - } - - String nextPageMaster = - currentPmr.getNextPageMaster( currentPageNumber, thisIsFirstPage ); - - if (null == nextPageMaster) - { - currentPmr = getNextSubsequenceSpecifier(); - nextPageMaster = - currentPmr.getNextPageMaster( currentPageNumber, thisIsFirstPage ); - } + return subSequenceSpecifiers.size(); + } + + public void reset() + { + for (Enumeration e = subSequenceSpecifiers.elements(); e.hasMoreElements(); ) { + ((SubSequenceSpecifier)e.nextElement()).reset(); + } - return this.layoutMasterSet.getSimplePageMaster( nextPageMaster ).getPageMaster(); } + + } diff --git a/src/org/apache/fop/fo/pagination/Region.java b/src/org/apache/fop/fo/pagination/Region.java new file mode 100644 index 000000000..8893fae8c --- /dev/null +++ b/src/org/apache/fop/fo/pagination/Region.java @@ -0,0 +1,161 @@ +/*-- $Id$ -- + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Fop" and "Apache Software Foundation" must not be used to + endorse or promote products derived from this software without prior + written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation and was originally created by + James Tauber <jtauber@jtauber.com>. For more information on the Apache + Software Foundation, please see <http://www.apache.org/>. + + */ +package org.apache.fop.fo.pagination; + +// FOP +import org.apache.fop.fo.FObj; +import org.apache.fop.fo.PropertyList; +import org.apache.fop.apps.FOPException; +import org.apache.fop.layout.RegionArea; + +/** + * This is an abstract base class for pagination regions + */ +public abstract class Region extends FObj +{ + public static final String PROP_REGION_NAME = "region-name"; + + private SimplePageMaster _layoutMaster; + private String _regionName; + + protected Region(FObj parent, PropertyList propertyList) + throws FOPException + { + super(parent, propertyList); + this.name = getElementName(); + + // regions may have name, or default + if (null == this.properties.get(PROP_REGION_NAME)) { + setRegionName(getDefaultRegionName()); + } + else if (this.properties.get(PROP_REGION_NAME).getString().equals("")) { + setRegionName(getDefaultRegionName()); + } + else { + setRegionName(this.properties.get(PROP_REGION_NAME).getString()); + // check that name is OK. Not very pretty. + if (isReserved(getRegionName()) && + !getRegionName().equals(getDefaultRegionName())) { + throw new FOPException(PROP_REGION_NAME+" '" + _regionName + + "' for "+this.name+" not permitted."); + } + } + + if (parent.getName().equals("fo:simple-page-master")) { + _layoutMaster = (SimplePageMaster) parent; + getPageMaster().addRegion(this); + } else { + throw new FOPException(getElementName()+" must be child " + + "of simple-page-master, not " + + parent.getName()); + } + } + + /** + * Creates a Region layout object for this pagination Region. + */ + abstract RegionArea makeRegionArea(int allocationRectangleXPosition, + int allocationRectangleYPosition, + int allocationRectangleWidth, + int allocationRectangleHeight); + + /** + * Returns the default region name (xsl-region-before, xsl-region-start, + * etc.) + */ + protected abstract String getDefaultRegionName(); + + /** + * Returns the element name ("fo:region-body", "fo:region-start", + * etc.) + */ + protected abstract String getElementName(); + + public abstract String getRegionClass(); + + + /** + * Returns the name of this region + */ + public String getRegionName() + { + return _regionName; + } + + private void setRegionName(String name) + { + _regionName = name; + } + + protected SimplePageMaster getPageMaster() + { + return _layoutMaster; + } + + + /** + * Checks to see if a given region name is one of the reserved names + * + * @param name a region name to check + * @return true if the name parameter is a reserved region name + */ + protected boolean isReserved(String name) + throws FOPException + { + return (name.equals( "xsl-region-before" ) || + name.equals( "xsl-region-start" ) || + name.equals( "xsl-region-end" ) || + name.equals( "xsl-region-after" ) || + name.equals( "xsl-before-float-separator" ) || + name.equals( "xsl-footnote-separator" )); + } + +} diff --git a/src/org/apache/fop/fo/pagination/RegionAfter.java b/src/org/apache/fop/fo/pagination/RegionAfter.java index 9b8872e1f..828907549 100644 --- a/src/org/apache/fop/fo/pagination/RegionAfter.java +++ b/src/org/apache/fop/fo/pagination/RegionAfter.java @@ -51,12 +51,12 @@ package org.apache.fop.fo.pagination; // FOP -import org.apache.fop.fo.*; -import org.apache.fop.fo.properties.*; -import org.apache.fop.layout.Region; -import org.apache.fop.apps.FOPException; +import org.apache.fop.fo.FObj; +import org.apache.fop.fo.PropertyList; +import org.apache.fop.apps.FOPException; +import org.apache.fop.layout.RegionArea; -public class RegionAfter extends FObj { +public class RegionAfter extends Region { public static class Maker extends FObj.Maker { public FObj make(FObj parent, PropertyList propertyList) throws FOPException { @@ -68,24 +68,16 @@ public class RegionAfter extends FObj { return new RegionAfter.Maker(); } - SimplePageMaster layoutMaster; + public static final String REGION_CLASS = "after"; + protected RegionAfter(FObj parent, PropertyList propertyList) - throws FOPException { + throws FOPException + { super(parent, propertyList); - this.name = "fo:region-after"; - - if (parent.getName().equals("fo:simple-page-master")) { - this.layoutMaster = (SimplePageMaster) parent; - this.layoutMaster.setRegionAfter(this); - } else { - throw new FOPException("region-after must be child " - + "of simple-page-master, not " - + parent.getName()); - } } - Region makeRegion(int allocationRectangleXPosition, + RegionArea makeRegionArea(int allocationRectangleXPosition, int allocationRectangleYPosition, int allocationRectangleWidth, int allocationRectangleHeight) { @@ -95,10 +87,27 @@ public class RegionAfter extends FObj { int marginRight = this.properties.get("margin-right").getLength().mvalue(); int extent = this.properties.get("extent").getLength().mvalue(); - return new Region(allocationRectangleXPosition + marginLeft, + return new RegionArea(allocationRectangleXPosition + marginLeft, allocationRectangleYPosition - allocationRectangleHeight + extent, allocationRectangleWidth - marginLeft - marginRight,extent); } + + + protected String getDefaultRegionName() + { + return "xsl-region-after"; + } + + protected String getElementName() + { + return "fo:region-after"; + } + + public String getRegionClass() + { + return REGION_CLASS; + } + } diff --git a/src/org/apache/fop/fo/pagination/RegionBefore.java b/src/org/apache/fop/fo/pagination/RegionBefore.java index 55747c196..2fcbf0259 100644 --- a/src/org/apache/fop/fo/pagination/RegionBefore.java +++ b/src/org/apache/fop/fo/pagination/RegionBefore.java @@ -53,10 +53,10 @@ package org.apache.fop.fo.pagination; // FOP import org.apache.fop.fo.*; import org.apache.fop.fo.properties.*; -import org.apache.fop.layout.Region; +import org.apache.fop.layout.RegionArea; import org.apache.fop.apps.FOPException; -public class RegionBefore extends FObj { +public class RegionBefore extends Region { public static class Maker extends FObj.Maker { public FObj make(FObj parent, PropertyList propertyList) throws FOPException { @@ -68,24 +68,17 @@ public class RegionBefore extends FObj { return new RegionBefore.Maker(); } - SimplePageMaster layoutMaster; + public static final String REGION_CLASS = "before"; + protected RegionBefore(FObj parent, PropertyList propertyList) - throws FOPException { + throws FOPException + { super(parent, propertyList); - this.name = "fo:region-before"; - - if (parent.getName().equals("fo:simple-page-master")) { - this.layoutMaster = (SimplePageMaster) parent; - this.layoutMaster.setRegionBefore(this); - } else { - throw new FOPException("region-before must be child of " - + "simple-page-master, not " - + parent.getName()); - } } + - Region makeRegion(int allocationRectangleXPosition, + RegionArea makeRegionArea(int allocationRectangleXPosition, int allocationRectangleYPosition, int allocationRectangleWidth, int allocationRectangleHeight) { @@ -95,9 +88,26 @@ public class RegionBefore extends FObj { int marginRight = this.properties.get("margin-right").getLength().mvalue(); int extent = this.properties.get("extent").getLength().mvalue(); - return new Region(allocationRectangleXPosition + marginLeft, + return new RegionArea(allocationRectangleXPosition + marginLeft, allocationRectangleYPosition - marginTop, allocationRectangleWidth - marginLeft - marginRight, extent); } + + + protected String getDefaultRegionName() + { + return "xsl-region-before"; + } + + protected String getElementName() + { + return "fo:region-before"; + } + + public String getRegionClass() + { + return REGION_CLASS; + } + } diff --git a/src/org/apache/fop/fo/pagination/RegionBody.java b/src/org/apache/fop/fo/pagination/RegionBody.java index 72a86819b..b8c6daa42 100644 --- a/src/org/apache/fop/fo/pagination/RegionBody.java +++ b/src/org/apache/fop/fo/pagination/RegionBody.java @@ -51,13 +51,14 @@ package org.apache.fop.fo.pagination; // FOP -import org.apache.fop.fo.*; -import org.apache.fop.fo.properties.*; -import org.apache.fop.layout.Region; -import org.apache.fop.apps.FOPException; +import org.apache.fop.fo.FObj; +import org.apache.fop.fo.PropertyList; +import org.apache.fop.apps.FOPException; +import org.apache.fop.layout.RegionArea; -public class RegionBody extends FObj { - +public class RegionBody extends Region { + + public static class Maker extends FObj.Maker { public FObj make(FObj parent, PropertyList propertyList) throws FOPException { return new RegionBody(parent, propertyList); @@ -68,21 +69,17 @@ public class RegionBody extends FObj { return new RegionBody.Maker(); } + public static final String REGION_CLASS = "body"; + + protected RegionBody(FObj parent, PropertyList propertyList) - throws FOPException { + throws FOPException + { super(parent, propertyList); - this.name = "fo:region-body"; - - if (parent.getName().equals("fo:simple-page-master")) { - ((SimplePageMaster) parent).setRegionBody(this); - } else { - throw new FOPException("region-body must be child of " - + "simple-page-master, not " - + parent.getName()); - } } + - Region makeRegion(int allocationRectangleXPosition, + RegionArea makeRegionArea(int allocationRectangleXPosition, int allocationRectangleYPosition, int allocationRectangleWidth, int allocationRectangleHeight) { @@ -91,10 +88,26 @@ public class RegionBody extends FObj { int marginLeft = this.properties.get("margin-left").getLength().mvalue(); int marginRight = this.properties.get("margin-right").getLength().mvalue(); - return new Region(allocationRectangleXPosition + marginLeft, + return new RegionArea(allocationRectangleXPosition + marginLeft, allocationRectangleYPosition - marginTop, allocationRectangleWidth - marginLeft - marginRight, allocationRectangleHeight - marginTop - marginBottom); } + + protected String getDefaultRegionName() + { + return "xsl-region-body"; + } + + protected String getElementName() + { + return "fo:region-body"; + } + + public String getRegionClass() + { + return REGION_CLASS; + } + } diff --git a/src/org/apache/fop/fo/pagination/RepeatablePageMasterAlternatives.java b/src/org/apache/fop/fo/pagination/RepeatablePageMasterAlternatives.java index 891e91cf3..4701b22e3 100644 --- a/src/org/apache/fop/fo/pagination/RepeatablePageMasterAlternatives.java +++ b/src/org/apache/fop/fo/pagination/RepeatablePageMasterAlternatives.java @@ -60,6 +60,9 @@ import java.util.Vector; public class RepeatablePageMasterAlternatives extends FObj implements SubSequenceSpecifier { + private static final int INFINITE = -1; + + public static class Maker extends FObj.Maker { public FObj make(FObj parent, PropertyList propertyList) throws FOPException { @@ -73,13 +76,12 @@ public class RepeatablePageMasterAlternatives extends FObj private PageSequenceMaster pageSequenceMaster; + /** + * Max times this page master can be repeated. + * INFINITE is used for the unbounded case */ private int maximumRepeats; private int numberConsumed = 0; - - private int BOUNDED = 1; - private int UNBOUNDED = 0; - - private int state; + private Vector conditionalPageMasterRefs; public RepeatablePageMasterAlternatives(FObj parent, PropertyList propertyList) @@ -98,32 +100,32 @@ public class RepeatablePageMasterAlternatives extends FObj parent.getName()); } - String mr = this.properties.get("maximum-repeats").getString(); - if (!mr.equals("no-limit")) - { + String mr = getProperty("maximum-repeats").getString(); + if (mr.equals("no-limit")) { + setMaximumRepeats(INFINITE); + } + else { try { - setMaximumRepeats( Integer.parseInt( mr ) ); - this.state = BOUNDED; + setMaximumRepeats( Integer.parseInt( mr ) ); } catch (NumberFormatException nfe) { - throw new FOPException( "Invalid number for " + - "'maximum-repeats' property" ); + throw new FOPException( "Invalid number for " + + "'maximum-repeats' property" ); } - - } else { - this.state = UNBOUNDED; // unbounded } } - public String getNextPageMaster( int currentPageNumber, boolean thisIsFirstPage ) { + public String getNextPageMaster( int currentPageNumber, + boolean thisIsFirstPage, + boolean isEmptyPage ) { String pm = null; - if (this.state == BOUNDED ) { - if (numberConsumed < getMaximumRepeats()) { - numberConsumed++; - } else { - return null; - } + if (getMaximumRepeats() != INFINITE ) { + if (numberConsumed < getMaximumRepeats()) { + numberConsumed++; + } else { + return null; + } } for (int i = 0; i < conditionalPageMasterRefs.size(); i++) @@ -132,20 +134,25 @@ public class RepeatablePageMasterAlternatives extends FObj (ConditionalPageMasterReference)conditionalPageMasterRefs.elementAt(i); // 0-indexed page number - if (cpmr.isValid(currentPageNumber + 1, thisIsFirstPage)) + if (cpmr.isValid(currentPageNumber + 1, thisIsFirstPage,false)) { pm = cpmr.getMasterName(); break; } } - return pm; } private void setMaximumRepeats( int maximumRepeats) { + if (maximumRepeats == INFINITE) { + this.maximumRepeats = maximumRepeats; + } + else { this.maximumRepeats = - (maximumRepeats < 0) ? 0 : maximumRepeats; + (maximumRepeats < 0) ? 0 : maximumRepeats; + } + } private int getMaximumRepeats() @@ -159,4 +166,14 @@ public class RepeatablePageMasterAlternatives extends FObj this.conditionalPageMasterRefs.addElement( cpmr ); } + public void reset() + { + this.numberConsumed = 0; + } + + + protected PageSequenceMaster getPageSequenceMaster() + { + return pageSequenceMaster; + } } diff --git a/src/org/apache/fop/fo/pagination/RepeatablePageMasterReference.java b/src/org/apache/fop/fo/pagination/RepeatablePageMasterReference.java index ac9c32723..098832f66 100644 --- a/src/org/apache/fop/fo/pagination/RepeatablePageMasterReference.java +++ b/src/org/apache/fop/fo/pagination/RepeatablePageMasterReference.java @@ -56,6 +56,8 @@ import org.apache.fop.apps.FOPException; public class RepeatablePageMasterReference extends PageMasterReference implements SubSequenceSpecifier { + private static final int INFINITE = -1; + public static class Maker extends FObj.Maker { public FObj make(FObj parent, PropertyList propertyList) throws FOPException { @@ -67,73 +69,56 @@ public class RepeatablePageMasterReference extends PageMasterReference return new RepeatablePageMasterReference.Maker(); } - private String masterName; - private PageSequenceMaster pageSequenceMaster; + + private PageSequenceMaster pageSequenceMaster; private int maximumRepeats; private int numberConsumed = 0; - private int BOUNDED = 1; - private int UNBOUNDED = 0; - - private int state; - public RepeatablePageMasterReference(FObj parent, PropertyList propertyList) throws FOPException { super(parent, propertyList); - this.name = "fo:repeatable-page-master-reference"; - - if (parent.getName().equals("fo:page-sequence-master")) { - this.pageSequenceMaster = (PageSequenceMaster) parent; - setMasterName( this.properties.get("master-name").getString() ); - if (getMasterName() == null) { - System.err.println("WARNING: repeatable-page-master-reference" + - "does not have a master-name and so is being ignored"); - } else { - this.pageSequenceMaster.addSubsequenceSpecifier(this); - } - } else { - throw new FOPException("fo:repeatable-page-master-reference must be" + - "child of fo:page-sequence, not " - + parent.getName()); - } - - String mr = this.properties.get("maximum-repeats").getString(); - if (!mr.equals("no-limit")) + + String mr = getProperty("maximum-repeats").getString(); + if (mr.equals("no-limit")) { + setMaximumRepeats(INFINITE); + } + else { try { - setMaximumRepeats( Integer.parseInt( mr ) ); - this.state = BOUNDED; + setMaximumRepeats( Integer.parseInt( mr ) ); } catch (NumberFormatException nfe) { - throw new FOPException( "Invalid number for " + - "'maximum-repeats' property" ); + throw new FOPException( "Invalid number for " + + "'maximum-repeats' property" ); } - - } else { - this.state = UNBOUNDED; // unbounded } } public String getNextPageMaster( int currentPageNumber, - boolean thisIsFirstPage ) { + boolean thisIsFirstPage, + boolean isEmptyPage ) { String pm = getMasterName(); - if (this.state == BOUNDED) - { - if (numberConsumed < getMaximumRepeats()) { - numberConsumed++; - } else { - pm = null; - } + if (getMaximumRepeats() != INFINITE ) { + if (numberConsumed < getMaximumRepeats()) { + numberConsumed++; + } else { + pm = null; + } } return pm; } private void setMaximumRepeats( int maximumRepeats) { + if (maximumRepeats == INFINITE) { + this.maximumRepeats = maximumRepeats; + } + else { this.maximumRepeats = - (maximumRepeats < 0) ? 0 : maximumRepeats; + (maximumRepeats < 0) ? 0 : maximumRepeats; + } } private int getMaximumRepeats() @@ -141,4 +126,14 @@ public class RepeatablePageMasterReference extends PageMasterReference return this.maximumRepeats; } + protected String getElementName() + { + return "fo:repeatable-page-master-reference"; + } + + public void reset() + { + this.numberConsumed = 0; + } + } diff --git a/src/org/apache/fop/fo/pagination/SimplePageMaster.java b/src/org/apache/fop/fo/pagination/SimplePageMaster.java index 556273354..a4bfeacde 100644 --- a/src/org/apache/fop/fo/pagination/SimplePageMaster.java +++ b/src/org/apache/fop/fo/pagination/SimplePageMaster.java @@ -55,9 +55,11 @@ import org.apache.fop.fo.*; import org.apache.fop.messaging.MessageHandler; import org.apache.fop.fo.properties.*; import org.apache.fop.layout.PageMaster; -import org.apache.fop.layout.Region; import org.apache.fop.apps.FOPException; +import java.util.Hashtable; + + public class SimplePageMaster extends FObj { public static class Maker extends FObj.Maker { @@ -71,13 +73,14 @@ public class SimplePageMaster extends FObj { return new SimplePageMaster.Maker(); } - RegionBody regionBody; - RegionBefore regionBefore; - RegionAfter regionAfter; - + /** Page regions (regionClass, Region) */ + private Hashtable _regions; + + LayoutMasterSet layoutMasterSet; PageMaster pageMaster; - + String masterName; + protected SimplePageMaster(FObj parent, PropertyList propertyList) throws FOPException { super(parent, propertyList); @@ -85,18 +88,20 @@ public class SimplePageMaster extends FObj { if (parent.getName().equals("fo:layout-master-set")) { this.layoutMasterSet = (LayoutMasterSet) parent; - String pm = this.properties.get("master-name").getString(); - if (pm == null) { + masterName = this.properties.get("master-name").getString(); + if (masterName == null) { MessageHandler.errorln("WARNING: simple-page-master does not have " + "a master-name and so is being ignored"); } else { - this.layoutMasterSet.addSimplePageMaster(pm, this); + this.layoutMasterSet.addSimplePageMaster(this); } } else { throw new FOPException("fo:simple-page-master must be child " + "of fo:layout-master-set, not " + parent.getName()); } + _regions = new Hashtable(); + } protected void end() { @@ -114,12 +119,21 @@ public class SimplePageMaster extends FObj { int contentRectangleHeight = pageHeight - marginTop - marginBottom; this.pageMaster = new PageMaster(pageWidth, pageHeight); - this.pageMaster.addBody(this.regionBody.makeRegion(contentRectangleXPosition,contentRectangleYPosition,contentRectangleWidth,contentRectangleHeight)); - - if (this.regionBefore != null) - this.pageMaster.addBefore(this.regionBefore.makeRegion(contentRectangleXPosition,contentRectangleYPosition,contentRectangleWidth,contentRectangleHeight)); - if (this.regionAfter != null) - this.pageMaster.addAfter(this.regionAfter.makeRegion(contentRectangleXPosition,contentRectangleYPosition,contentRectangleWidth,contentRectangleHeight)); + if (getRegion(RegionBody.REGION_CLASS) != null) { + this.pageMaster.addBody(getRegion(RegionBody.REGION_CLASS).makeRegionArea(contentRectangleXPosition,contentRectangleYPosition,contentRectangleWidth,contentRectangleHeight)); + } + else { + MessageHandler.errorln("ERROR: simple-page-master must have a region of class "+RegionBody.REGION_CLASS); + } + + if (getRegion(RegionBefore.REGION_CLASS) != null) { + this.pageMaster.addBefore(getRegion(RegionBefore.REGION_CLASS).makeRegionArea(contentRectangleXPosition,contentRectangleYPosition,contentRectangleWidth,contentRectangleHeight)); + } + + if (getRegion(RegionAfter.REGION_CLASS) != null) { + this.pageMaster.addAfter(getRegion(RegionAfter.REGION_CLASS).makeRegionArea(contentRectangleXPosition,contentRectangleYPosition,contentRectangleWidth,contentRectangleHeight)); + } + } public PageMaster getPageMaster() { @@ -130,15 +144,33 @@ public class SimplePageMaster extends FObj { return this.pageMaster; } - protected void setRegionAfter(RegionAfter region) { - this.regionAfter = region; + public String getMasterName() + { + return masterName; } + - protected void setRegionBefore(RegionBefore region) { - this.regionBefore = region; + protected void addRegion(Region region) + throws FOPException + { + if (_regions.containsKey(region.getRegionClass())) { + throw new FOPException("Only one region of class "+region.getRegionClass()+" allowed within a simple-page-master."); + } + else { + _regions.put(region.getRegionClass(), region); + } + } + + protected Region getRegion(String regionClass) + { + return (Region)_regions.get(regionClass); } - protected void setRegionBody(RegionBody region) { - this.regionBody = region; + protected Hashtable getRegions() + { + return _regions; } + + + } diff --git a/src/org/apache/fop/fo/pagination/SinglePageMasterReference.java b/src/org/apache/fop/fo/pagination/SinglePageMasterReference.java index cf6071c4e..5f05b0d70 100644 --- a/src/org/apache/fop/fo/pagination/SinglePageMasterReference.java +++ b/src/org/apache/fop/fo/pagination/SinglePageMasterReference.java @@ -67,51 +67,42 @@ public class SinglePageMasterReference extends PageMasterReference public static FObj.Maker maker() { return new SinglePageMasterReference.Maker(); } - - private String masterName; - private PageSequenceMaster pageSequenceMaster; - + private static final int FIRST = 0; private static final int DONE = 1; private int state; - + public SinglePageMasterReference(FObj parent, PropertyList propertyList) throws FOPException { - super(parent, propertyList); - this.name = "fo:single-page-master-reference"; - - if (parent.getName().equals("fo:page-sequence-master")) { - this.pageSequenceMaster = (PageSequenceMaster) parent; - setMasterName( this.properties.get("master-name").getString() ); - - if (getMasterName() == null) { - MessageHandler.error("WARNING: single-page-master-reference" + - "does not have a master-name and so is being ignored"); - } else { - this.pageSequenceMaster.addSubsequenceSpecifier(this); - } - } else { - throw new FOPException("fo:page-sequence-master must be child " - + "of fo:layout-master-set, not " - + parent.getName()); - } - this.state = FIRST; + } - public String getNextPageMaster( int currentPageNumber, boolean thisIsFirstPage ) { - return getMasterName(); + public String getNextPageMaster( int currentPageNumber, + boolean thisIsFirstPage, + boolean isEmptyPage) { + if (this.state == FIRST) { + this.state = DONE; + return getMasterName(); + } + else { + return null; + } + } - public void setMasterName( String masterName ) - { - this.masterName = masterName; - } + public void reset() + { + this.state = FIRST; + } + - public String getMasterName() - { - return this.masterName; - } + protected String getElementName() + { + return "fo:single-page-master-reference"; + } + + } diff --git a/src/org/apache/fop/fo/pagination/SubSequenceSpecifier.java b/src/org/apache/fop/fo/pagination/SubSequenceSpecifier.java index fe18f15fb..0e4828bc0 100644 --- a/src/org/apache/fop/fo/pagination/SubSequenceSpecifier.java +++ b/src/org/apache/fop/fo/pagination/SubSequenceSpecifier.java @@ -56,6 +56,12 @@ package org.apache.fop.fo.pagination; public interface SubSequenceSpecifier { public String getNextPageMaster( int currentPageNumber, - boolean thisIsFirstPage ); + boolean thisIsFirstPage, boolean isEmptyPage); + /** + * Called before a new page sequence is rendered so subsequences can reset + * any state they keep during the formatting process. + */ + public void reset(); + } diff --git a/src/org/apache/fop/layout/PageMaster.java b/src/org/apache/fop/layout/PageMaster.java index a677ad4ff..f564abda3 100644 --- a/src/org/apache/fop/layout/PageMaster.java +++ b/src/org/apache/fop/layout/PageMaster.java @@ -55,34 +55,34 @@ public class PageMaster { private int width; private int height; - private Region body; - private Region before; - private Region after; - private Region start; - private Region end; + private RegionArea body; + private RegionArea before; + private RegionArea after; + private RegionArea start; + private RegionArea end; public PageMaster(int pageWidth, int pageHeight) { this.width = pageWidth; this.height = pageHeight; } - public void addAfter(Region region) { + public void addAfter(RegionArea region) { this.after = region; } - public void addBefore(Region region) { + public void addBefore(RegionArea region) { this.before = region; } - public void addBody(Region region) { + public void addBody(RegionArea region) { this.body = region; } - public void addEnd(Region region) { + public void addEnd(RegionArea region) { this.end = region; } - public void addStart(Region region) { + public void addStart(RegionArea region) { this.start = region; } diff --git a/src/org/apache/fop/layout/Region.java b/src/org/apache/fop/layout/RegionArea.java index 634960e4e..d044c4f74 100644 --- a/src/org/apache/fop/layout/Region.java +++ b/src/org/apache/fop/layout/RegionArea.java @@ -51,14 +51,14 @@ package org.apache.fop.layout; import org.apache.fop.fo.properties.*; -public class Region { +public class RegionArea { private int xPosition; private int yPosition; private int width; private int height; - public Region(int xPosition, int yPosition, int width, int height) { + public RegionArea(int xPosition, int yPosition, int width, int height) { this.xPosition = xPosition; this.yPosition = yPosition; this.width = width; diff --git a/src/org/apache/fop/render/pdf/PDFRenderer.java b/src/org/apache/fop/render/pdf/PDFRenderer.java index ed14299e8..0de1cfab0 100644 --- a/src/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/org/apache/fop/render/pdf/PDFRenderer.java @@ -174,7 +174,9 @@ public class PDFRenderer implements Renderer { } if ( !idReferences.isEveryIdValid() ) { - throw new FOPException("The following id's were referenced but not found: "+idReferences.getInvalidIds()+"\n"); + // throw new FOPException("The following id's were referenced but not found: "+idReferences.getInvalidIds()+"\n"); + MessageHandler.errorln("WARNING: The following id's were referenced but not found: "+idReferences.getInvalidIds()+"\n"); + } MessageHandler.logln("writing out PDF"); |