Index: src/java/org/apache/fop/area/inline/InlineArea.java
===================================================================
--- src/java/org/apache/fop/area/inline/InlineArea.java	(revision 752208)
+++ src/java/org/apache/fop/area/inline/InlineArea.java	Tue Mar 10 22:25:21 CET 2009
@@ -19,6 +19,8 @@
 
 package org.apache.fop.area.inline;
 
+import java.io.Serializable;
+
 import org.apache.fop.area.Area;
 import org.apache.fop.area.LineArea;
 import org.apache.fop.area.Trait;
@@ -35,7 +37,7 @@
      * that can be used in order to re-compute adjustments when a
      * page-number or a page-number-citation is resolved
      */
-    protected class InlineAdjustingInfo {
+    protected class InlineAdjustingInfo implements Serializable {
         /** stretch of the inline area */
         protected int availableStretch;
         /** shrink of the inline area */
Index: src/java/org/apache/fop/apps/FOUserAgent.java
===================================================================
--- src/java/org/apache/fop/apps/FOUserAgent.java	(revision 752208)
+++ src/java/org/apache/fop/apps/FOUserAgent.java	Thu Mar 12 20:40:14 CET 2009
@@ -97,6 +97,7 @@
     private Renderer rendererOverride = null;
     private FOEventHandler foEventHandlerOverride = null;
     private boolean locatorEnabled = true; // true by default (for error messages).
+    private boolean conserveMemoryPolicy = false;
     private EventBroadcaster eventBroadcaster = new FOPEventBroadcaster();
 
     /** Producer:  Metadata element for the system/software that produces
@@ -615,5 +616,23 @@
 
     }
 
+    /**
+     * Check whether memory-conservation is enabled.
+     *
+     * @return true if FOP is to conserve as much as possible
+     */
+    public boolean isConserveMemoryPolicyEnabled() {
+        return this.conserveMemoryPolicy;
-}
+    }
 
+    /**
+     * Control whether memory-conservation should be enabled
+     *
+     * @param conserveMemoryPolicy the cachingEnabled to set
+     */
+    public void setConserveMemoryPolicy(boolean conserveMemoryPolicy) {
+        this.conserveMemoryPolicy = conserveMemoryPolicy;
+    }
+
+}
+
Index: src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java	(revision 752208)
+++ src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java	Thu Mar 12 20:25:32 CET 2009
@@ -167,6 +167,13 @@
         addChildToArea(childArea, getCurrentArea());
     }
 
+    /** {@inheritDoc} */
+    protected void notifyEndOfLayout() {
+        super.notifyEndOfLayout();
+        // Free memory of the area tree
+        //this.parentArea = null;
+    }
+
     /**
      * Force current area to be added to parent area.
      */
@@ -486,7 +493,7 @@
         //      ? "penalty" : (lastElement.isGlue() ? "glue" : "box" )));
 /*LF*/  //log.debug("  position e' " + lastElement.getPosition().getClass().getName());
 /*LF*/  //log.debug("  " + (bpUnit > 0 ? "unit" : ""));
-        Position innerPosition = ((NonLeafPosition) lastElement.getPosition()).getPosition();
+        Position innerPosition = lastElement.getPosition().getPosition();
 
         if (innerPosition == null && lastElement.isGlue()) {
             // this adjustment applies to space-before or space-after of this block
@@ -536,7 +543,7 @@
 /*LF*/              //log.debug("  BLM.negotiateBPDAdjustment> chiamata passata");
                     return ((BlockLevelLayoutManager)storedPenalty.getLayoutManager())
                            .negotiateBPDAdjustment(storedPenalty.getW(),
-                                   (KnuthElement)storedPenalty);
+                                   storedPenalty);
                 } else {
                     // the original penalty has width = 0
                     // the adjustment involves only the spaces before and after
@@ -787,12 +794,12 @@
                 returnList.add(new KnuthGlue(0, 0, 0,
                         SPACE_AFTER_ADJUSTMENT,
                         new NonLeafPosition(this, null),
-                        (!spaceAfterIsConditional) ? false : true));
+                        spaceAfterIsConditional));
             } else {
                 returnList.add(new KnuthGlue(adjustedSpaceAfter, 0, 0,
                         SPACE_AFTER_ADJUSTMENT,
                         new NonLeafPosition(this, null),
-                        (!spaceAfterIsConditional) ? false : true));
+                        spaceAfterIsConditional));
             }
             if (!spaceAfterIsConditional) {
                 returnList.add(new KnuthBox(0,
@@ -1201,8 +1208,8 @@
                 totalLength.add(new MinOptMax(element.getW()));
                 //log.debug("box " + element.getW());
             } else if (element.isGlue()) {
-                totalLength.min -= ((KnuthGlue) element).getZ();
-                totalLength.max += ((KnuthGlue) element).getY();
+                totalLength.min -= element.getZ();
+                totalLength.max += element.getY();
                 //leafValue = ((LeafPosition) element.getPosition()).getLeafPos();
                 //log.debug("glue " + element.getW() + " + "
                 //    + ((KnuthGlue) element).getY() + " - " + ((KnuthGlue) element).getZ());
@@ -1239,10 +1246,10 @@
                 lengthAfterBreak.subtract(new MinOptMax(element.getW()));
                 bPrevIsBox = true;
             } else if (element.isGlue()) {
-                lengthBeforeBreak.min -= ((KnuthGlue) element).getZ();
-                lengthAfterBreak.min += ((KnuthGlue) element).getZ();
-                lengthBeforeBreak.max += ((KnuthGlue) element).getY();
-                lengthAfterBreak.max -= ((KnuthGlue) element).getY();
+                lengthBeforeBreak.min -= element.getZ();
+                lengthAfterBreak.min += element.getZ();
+                lengthBeforeBreak.max += element.getY();
+                lengthAfterBreak.max -= element.getY();
                 bPrevIsBox = false;
             } else {
                 lengthBeforeBreak.add(new MinOptMax(element.getW()));
@@ -1250,7 +1257,7 @@
             }
 
             // create the new elements
-            if (element.isPenalty() && ((KnuthPenalty) element).getP() < KnuthElement.INFINITE
+            if (element.isPenalty() && element.getP() < KnuthElement.INFINITE
                     || element.isGlue() && bPrevIsBox
                     || !oldListIterator.hasNext()) {
                 // suppress elements after the breaking point
@@ -1260,8 +1267,8 @@
                     iStepsForward++;
                     if (el.isGlue()) {
                         // suppressed glue
-                        lengthAfterBreak.min += ((KnuthGlue) el).getZ();
-                        lengthAfterBreak.max -= ((KnuthGlue) el).getY();
+                        lengthAfterBreak.min += el.getZ();
+                        lengthAfterBreak.max -= el.getY();
                     } else if (el.isPenalty()) {
                         // suppressed penalty, do nothing
                     } else {
@@ -1281,8 +1288,8 @@
                 for (int i = 0; i < iStepsForward; i++) {
                     KnuthElement el = (KnuthElement) oldListIterator.previous();
                     if (el.isGlue()) {
-                        lengthAfterBreak.min -= ((KnuthGlue) el).getZ();
-                        lengthAfterBreak.max += ((KnuthGlue) el).getY();
+                        lengthAfterBreak.min -= el.getZ();
+                        lengthAfterBreak.max += el.getY();
                     }
                 }
 
Index: src/java/org/apache/fop/area/CachedRenderPagesModel.java
===================================================================
--- src/java/org/apache/fop/area/CachedRenderPagesModel.java	(revision 752208)
+++ src/java/org/apache/fop/area/CachedRenderPagesModel.java	Tue Mar 10 22:25:21 CET 2009
@@ -129,7 +129,7 @@
         try {
             // save page to cache
             ObjectOutputStream tempstream;
-            String fname = "fop-page-" + page.toString() + ".ser";
+            String fname = "fop-page-" + page.getPageIndex() + ".ser";
             File tempFile = new File(baseDir, fname);
             tempFile.deleteOnExit();
             tempstream = new ObjectOutputStream(new BufferedOutputStream(
Index: src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java	(revision 752208)
+++ src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java	Tue Mar 10 22:28:55 CET 2009
@@ -201,8 +201,6 @@
             p.setP(0);
         }
 
-        notifyEndOfLayout();
-
         setFinished(true);
         return returnList;
     }
@@ -427,6 +425,8 @@
         flush();
 
         curBlockArea = null;
+
+        notifyEndOfLayout();
     }
 
     /** Adds background areas for the column, body and row, if any. */
Index: src/java/org/apache/fop/area/AreaTreeHandler.java
===================================================================
--- src/java/org/apache/fop/area/AreaTreeHandler.java	(revision 752208)
+++ src/java/org/apache/fop/area/AreaTreeHandler.java	Thu Mar 12 20:41:15 CET 2009
@@ -124,8 +124,12 @@
      */
     protected void setupModel(FOUserAgent userAgent, String outputFormat,
             OutputStream stream) throws FOPException {
+        if (userAgent.isConserveMemoryPolicyEnabled()) {
+            this.model = new CachedRenderPagesModel(userAgent, outputFormat, fontInfo, stream);
+        } else {
-        this.model = new RenderPagesModel(userAgent, outputFormat, fontInfo, stream);
-    }
+            this.model = new RenderPagesModel(userAgent, outputFormat, fontInfo, stream);
+        }
+    }
 
     /**
      * Get the area tree model for this area tree.
@@ -442,7 +446,6 @@
 
         /**
          * Default constructor
-         * @param areaTreeHandler area tree handler
          */
         protected Statistics() {
             this.runtime = Runtime.getRuntime();
Index: src/java/org/apache/fop/cli/CommandLineOptions.java
===================================================================
--- src/java/org/apache/fop/cli/CommandLineOptions.java	(revision 752208)
+++ src/java/org/apache/fop/cli/CommandLineOptions.java	Thu Mar 12 20:47:12 CET 2009
@@ -110,6 +110,8 @@
     private Map renderingOptions = new java.util.HashMap();
     /* target resolution (for the user agent) */
     private int targetResolution = 0;
+    /* control memory-conservation policy */
+    private boolean conserveMemoryPolicy = false;
 
     private FopFactory factory = FopFactory.newInstance();
     private FOUserAgent foUserAgent;
@@ -168,6 +170,7 @@
                 }
                 addXSLTParameter("fop-output-format", getOutputFormat());
                 addXSLTParameter("fop-version", Version.getVersion());
+                foUserAgent.setConserveMemoryPolicy(conserveMemoryPolicy);
             } else {
                 return false;
             }
@@ -268,6 +271,8 @@
                 setLogOption("debug", "debug");
             } else if (args[i].equals("-r")) {
                 factory.setStrictValidation(false);
+            } else if (args[i].equals("-conserve")) {
+                conserveMemoryPolicy = true;
             } else if (args[i].equals("-dpi")) {
                 i = i + parseResolution(args, i);
             } else if (args[i].equals("-q") || args[i].equals("--quiet")) {
@@ -1122,6 +1127,7 @@
             + "  -r                relaxed/less strict validation (where available)\n"
             + "  -dpi xxx          target resolution in dots per inch (dpi) where xxx is a number\n"
             + "  -s                for area tree XML, down to block areas only\n"
+            + "  -cache            reduce memory usage when there are forward references\n"
             + "  -v                to show FOP version being used\n\n"
             + "  -o [password]     PDF file will be encrypted with option owner password\n"
             + "  -u [password]     PDF file will be encrypted with option user password\n"
@@ -1131,6 +1137,8 @@
             + "  -noannotations    PDF file will be encrypted without edit annotation permission\n"
             + "  -pdfprofile prof  PDF file will be generated with the specified profile\n"
             + "                    (Examples for prof: PDF/A-1b or PDF/X-3:2003)\n\n"
+            + "  -conserve         Enable memory-conservation policy (trades memory-consumption for disk I/O)"
+            + "                    (Note: currently only influences whether the area tree is cached.)"
             + " [INPUT]  \n"
             + "  infile            xsl:fo input file (the same as the next) \n"
             + "                    (use '-' for infile to pipe input from stdin)\n"
