work in progress


git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPAffineTransform@629729 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/build.xml b/build.xml
index 18bf3e8..5380bbd 100644
--- a/build.xml
+++ b/build.xml
@@ -622,6 +622,7 @@
       <exclude name="org/apache/fop/render/pdf/PDFRenderer.class"/>
       <exclude name="org/apache/fop/render/pdf/PDFXMLHandler*"/>
       <include name="org/apache/fop/render/*RendererConfigurator**"/>
+      <include name="org/apache/fop/render/AbstractState*"/>
       <include name="org/apache/fop/pdf/**"/>
     </patternset>
     <!-- PS transcoder -->
diff --git a/src/java/org/apache/fop/area/Trait.java b/src/java/org/apache/fop/area/Trait.java
index 98bed09..3b654bc 100644
--- a/src/java/org/apache/fop/area/Trait.java
+++ b/src/java/org/apache/fop/area/Trait.java
@@ -36,6 +36,8 @@
  */
 public class Trait implements Serializable {
 
+    private static final long serialVersionUID = -7613709600372824471L;
+
     /**
      * Id reference line, not resolved.
      * not sure if this is needed.
@@ -418,6 +420,8 @@
      */
     public static class InternalLink implements Serializable {
 
+        private static final long serialVersionUID = -6395526777690537059L;
+
         /** The unique key of the PageViewport. */
         private String pvKey;
 
@@ -553,6 +557,8 @@
      */
     public static class Background implements Serializable {
 
+        private static final long serialVersionUID = 8452078676273242870L;
+
         /** The background color if any. */
         private Color color = null;
 
diff --git a/src/java/org/apache/fop/pdf/PDFState.java b/src/java/org/apache/fop/pdf/PDFState.java
index e453d7b..5e77da0 100644
--- a/src/java/org/apache/fop/pdf/PDFState.java
+++ b/src/java/org/apache/fop/pdf/PDFState.java
@@ -19,14 +19,9 @@
  
 package org.apache.fop.pdf;
 
-import java.io.Serializable;
-import java.util.List;
 import java.util.Iterator;
-
-import java.awt.Color;
 import java.awt.Paint;
 import java.awt.Shape;
-import java.awt.geom.AffineTransform;
 import java.awt.geom.Area;
 import java.awt.geom.GeneralPath;
 
@@ -47,67 +42,62 @@
  * It is impossible to optimise the result without analysing the all
  * the possible combinations after completing.
  */
-public class PDFState {
-
-    private Data data = new Data();
-    
-    private List stateStack = new java.util.ArrayList();
+public class PDFState extends org.apache.fop.render.AbstractState {
 
     /**
      * PDF State for storing graphics state.
      */
     public PDFState() {
-
     }
 
-    /**
-     * Push the current state onto the stack.
-     * This call should be used when the q operator is used
-     * so that the state is known when popped.
-     */
-    public void push() {
-        Data copy;
-        try {
-            copy = (Data)getData().clone();
-            getData().resetTransform();
-        } catch (CloneNotSupportedException e) {
-            throw new RuntimeException(e.getMessage());
-        }
-        stateStack.add(copy);
-    }
-
-    /**
-     * @return the currently valid state
-     */
-    public Data getData() {
-        return data;
-    }
-    
-    /**
-     * Pop the state from the stack and set current values to popped state.
-     * This should be called when a Q operator is used so
-     * the state is restored to the correct values.
-     * @return the restored state, null if the stack is empty
-     */
-    public Data pop() {
-        if (getStackLevel() > 0) {
-            Data popped = (Data)stateStack.remove(stateStack.size() - 1);
-
-            data = popped;
-            return popped;
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Get the current stack level.
-     *
-     * @return the current stack level
-     */
-    public int getStackLevel() {
-        return stateStack.size();
-    }
+//    /**
+//     * Push the current state onto the stack.
+//     * This call should be used when the q operator is used
+//     * so that the state is known when popped.
+//     */
+//    public void push() {
+//        PDFData copy;
+//        try {
+//            copy = (PDFData)getData().clone();
+//            getData().resetTransform();
+//        } catch (CloneNotSupportedException e) {
+//            throw new RuntimeException(e.getMessage());
+//        }
+//        stateStack.add(copy);
+//    }
+//
+//    /**
+//     * @return the currently valid state
+//     */
+//    public PDFData getData() {
+//        return data;
+//    }
+//    
+//    /**
+//     * Pop the state from the stack and set current values to popped state.
+//     * This should be called when a Q operator is used so
+//     * the state is restored to the correct values.
+//     * @return the restored state, null if the stack is empty
+//     */
+//    public PDFData pop() {
+//        if (getStackLevel() > 0) {
+//            PDFData popped = (PDFData)stateStack.remove(stateStack.size() - 1);
+//
+//            data = popped;
+//            return popped;
+//        } else {
+//            return null;
+//        }
+//    }
+//
+//    /**
+//     * Get the current stack level.
+//     *
+//     * @return the current stack level
+//     */
+//    public int getStackLevel() {
+//        return stateStack.size();
+//    }
 
     /**
      * Restore the state to a particular level.
@@ -141,51 +131,51 @@
         return false;
     }*/
 
-    /**
-     * Set the current line width.
-     * @param width the line width in points
-     * @return true if the line width has changed
-     */
-    public boolean setLineWidth(float width) {
-        if (getData().lineWidth != width) {
-            getData().lineWidth = width;
-            return true;
-        } else {
-            return false;
-        }
-    }
-    
-    /**
-     * Set the current color.
-     * Check if the new color is a change and then set the current color.
-     *
-     * @param col the color to set
-     * @return true if the color has changed
-     */
-    public boolean setColor(Color col) {
-        if (!col.equals(getData().color)) {
-            getData().color = col;
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * Set the current background color.
-     * Check if the background color will change and then set the new color.
-     *
-     * @param col the new background color
-     * @return true if the background color has changed
-     */
-    public boolean setBackColor(Color col) {
-        if (!col.equals(getData().backcolor)) {
-            getData().backcolor = col;
-            return true;
-        } else {
-            return false;
-        }
-    }
+//    /**
+//     * Set the current line width.
+//     * @param width the line width in points
+//     * @return true if the line width has changed
+//     */
+//    public boolean setLineWidth(float width) {
+//        if (getData().lineWidth != width) {
+//            getData().lineWidth = width;
+//            return true;
+//        } else {
+//            return false;
+//        }
+//    }
+//    
+//    /**
+//     * Set the current color.
+//     * Check if the new color is a change and then set the current color.
+//     *
+//     * @param col the color to set
+//     * @return true if the color has changed
+//     */
+//    public boolean setColor(Color col) {
+//        if (!col.equals(getData().color)) {
+//            getData().color = col;
+//            return true;
+//        } else {
+//            return false;
+//        }
+//    }
+//
+//    /**
+//     * Set the current background color.
+//     * Check if the background color will change and then set the new color.
+//     *
+//     * @param col the new background color
+//     * @return true if the background color has changed
+//     */
+//    public boolean setBackColor(Color col) {
+//        if (!col.equals(getData().backcolor)) {
+//            getData().backcolor = col;
+//            return true;
+//        } else {
+//            return false;
+//        }
+//    }
 
     /**
      * Set the current paint.
@@ -195,13 +185,14 @@
      * @return true if the new paint changes the current paint
      */
     public boolean setPaint(Paint p) {
-        if (getData().paint == null) {
+        Paint paint = ((PDFData)getData()).paint; 
+        if (paint == null) {
             if (p != null) {
-                getData().paint = p;
+                ((PDFData)getData()).paint = p;
                 return true;
             }
-        } else if (!data.paint.equals(p)) {
-            getData().paint = p;
+        } else if (!paint.equals(p)) {
+            ((PDFData)getData()).paint = p;
             return true;
         }
         return false;
@@ -220,11 +211,12 @@
      * @return true if the clip will change the current clip.
      */
     public boolean checkClip(Shape cl) {
-        if (getData().clip == null) {
+        Shape clip = ((PDFData)getData()).clip; 
+        if (clip == null) {
             if (cl != null) {
                 return true;
             }
-        } else if (!new Area(getData().clip).equals(new Area(cl))) {
+        } else if (!new Area(clip).equals(new Area(cl))) {
             return true;
         }
         //TODO check for clips that are larger than the current
@@ -239,81 +231,54 @@
      * @param cl the new clip in the current state
      */
     public void setClip(Shape cl) {
-        if (getData().clip != null) {
-            Area newClip = new Area(getData().clip);
+        Shape clip = ((PDFData)getData()).clip; 
+        if (clip != null) {
+            Area newClip = new Area(clip);
             newClip.intersect(new Area(cl));
-            getData().clip = new GeneralPath(newClip);
+            ((PDFData)getData()).clip = new GeneralPath(newClip);
         } else {
-            getData().clip = cl;
+            ((PDFData)getData()).clip = cl;
         }
     }
 
-    /**
-     * Check the current transform.
-     * The transform for the current state is the combination of all
-     * transforms in the current state. The parameter is compared
-     * against this current transform.
-     *
-     * @param tf the transform the check against
-     * @return true if the new transform is different then the current transform
-     */
-    public boolean checkTransform(AffineTransform tf) {
-        return !tf.equals(getData().transform);
-    }
+//    /**
+//     * Set a new transform.
+//     * This transform is appended to the transform of
+//     * the current graphic state.
+//     *
+//     * @param tf the transform to concatonate to the current level transform
+//     * @deprecated This method name is misleading. Use concatenate(AffineTransform) instead!
+//     */
+//    public void setTransform(AffineTransform tf) {
+//        concatenate(tf);
+//    }
+//    
+//    /**
+//     * Concatenates the given AffineTransform to the current one.
+//     * @param tf the transform to concatenate to the current level transform
+//     */
+//    public void concatenate(AffineTransform tf) {
+//        getData().concatenate(tf);
+//    }
 
-    /**
-     * Set a new transform.
-     * This transform is appended to the transform of
-     * the current graphic state.
-     *
-     * @param tf the transform to concatonate to the current level transform
-     * @deprecated This method name is misleading. Use concatenate(AffineTransform) instead!
-     */
-    public void setTransform(AffineTransform tf) {
-        concatenate(tf);
-    }
-    
-    /**
-     * Concatenates the given AffineTransform to the current one.
-     * @param tf the transform to concatenate to the current level transform
-     */
-    public void concatenate(AffineTransform tf) {
-        getData().concatenate(tf);
-    }
-
-    /**
-     * Get the current transform.
-     * This gets the combination of all transforms in the
-     * current state.
-     *
-     * @return the calculate combined transform for the current state
-     */
-    public AffineTransform getTransform() {
-       AffineTransform tf;
-       AffineTransform at = new AffineTransform();
-       for (Iterator iter = stateStack.iterator(); iter.hasNext();) {
-           Data d = (Data)iter.next();
-           tf = d.transform;
-           at.concatenate(tf);
-       }
-       at.concatenate(getData().transform);
-       return at;
-    }
-
-    /**
-     * Get a copy of the base transform for the page. Used to translate
-     * IPP/BPP values into X,Y positions when positioning is "fixed".
-     *
-     * @return the base transform, or null if the state stack is empty
-     */
-    public AffineTransform getBaseTransform() {
-       if (stateStack.size() == 0) {
-           return null;
-       } else {
-           Data baseData = (Data) stateStack.get(0);
-           return (AffineTransform) baseData.transform.clone();
-       }
-    }
+//    /**
+//     * Get the current transform.
+//     * This gets the combination of all transforms in the
+//     * current state.
+//     *
+//     * @return the calculate combined transform for the current state
+//     */
+//    public AffineTransform getTransform() {
+//       AffineTransform tf;
+//       AffineTransform at = new AffineTransform();
+//       for (Iterator iter = stateStack.iterator(); iter.hasNext();) {
+//           PDFData d = (PDFData)iter.next();
+//           tf = d.getTransform();
+//           at.concatenate(tf);
+//       }
+//       at.concatenate(getData().getTransform());
+//       return at;
+//    }
 
     /**
      * Get the graphics state.
@@ -328,90 +293,54 @@
         PDFGState defaultState = PDFGState.DEFAULT;
 
         PDFGState state;
-        PDFGState newstate = new PDFGState();
-        newstate.addValues(defaultState);
-        for (Iterator iter = stateStack.iterator(); iter.hasNext();) {
-            Data d = (Data)iter.next();
+        PDFGState newState = new PDFGState();
+        newState.addValues(defaultState);
+        for (Iterator iter = getStateStack().iterator(); iter.hasNext();) {
+            PDFData d = (PDFData)iter.next();
             state = d.gstate;
             if (state != null) {
-                newstate.addValues(state);
+                newState.addValues(state);
             }
         }
-        if (getData().gstate != null) {
-            newstate.addValues(getData().gstate);
+        if (((PDFData)getData()).gstate != null) {
+            newState.addValues(((PDFData)getData()).gstate);
         }
-
-        return newstate;
+        return newState;
     }
     
-    public class Data implements Cloneable, Serializable {
+    private class PDFData extends org.apache.fop.render.AbstractState.AbstractData {
         
-        public Color color = Color.black;
-        public Color backcolor = Color.black;
-        public Paint paint = null;
-        public Paint backPaint = null;
-        public int lineCap = 0;
-        public int lineJoin = 0;
-        public float lineWidth = 1;
-        public float miterLimit = 0;
-        public boolean text = false;
-        public int dashOffset = 0;
-        public int[] dashArray = new int[0];
-        public AffineTransform transform = new AffineTransform();
-        public float fontSize = 0;
-        public String fontName = "";
-        public Shape clip = null;
-        public PDFGState gstate = null;
+        private static final long serialVersionUID = 3527950647293177764L;
 
+        private Paint paint = null;
+        private Paint backPaint = null;
+        private int lineCap = 0;
+        private int lineJoin = 0;
+        private float miterLimit = 0;
+        private boolean text = false;
+        private int dashOffset = 0;
+        private Shape clip = null;
+        private PDFGState gstate = null;
         
         /** {@inheritDoc} */
         public Object clone() throws CloneNotSupportedException {
-            Data obj = new Data();
-            obj.color = this.color;
-            obj.backcolor = this.backcolor;
+            PDFData obj = (PDFData)super.clone();
             obj.paint = this.paint;
             obj.backPaint = this.paint;
             obj.lineCap = this.lineCap;
             obj.lineJoin = this.lineJoin;
-            obj.lineWidth = this.lineWidth;
             obj.miterLimit = this.miterLimit;
             obj.text = this.text;
             obj.dashOffset = this.dashOffset;
-            obj.dashArray = this.dashArray;
-            obj.transform = new AffineTransform(this.transform);
-            obj.fontSize = this.fontSize;
-            obj.fontName = this.fontName;
             obj.clip = this.clip;
             obj.gstate = this.gstate;
             return obj;
-        }
-        
-        /**
-         * Get the current Transform.
-         */
-        public AffineTransform getTransform() {
-            return transform;
-        }
+        }        
+    }
 
-        public void resetTransform() {
-            transform = new AffineTransform();
-        }
-
-        /**
-         * Concatenate the given AffineTransform with the current thus creating
-         * a new viewport. Note that all concatenation operations are logged
-         * so they can be replayed if necessary (ex. for block-containers with
-         * "fixed" positioning.
-         * @param at Transformation to perform
-         */
-        public void concatenate(AffineTransform at) {
-            transform.concatenate(at);
-        }
-        
-        /** {@inheritDoc} */
-        public String toString() {
-            return super.toString() + ", " + this.transform;
-        }
+    /** {@inheritDoc} */
+    protected AbstractData instantiateData() {
+        return new PDFData();
     }
 }
 
diff --git a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java
index 9e13476..ba8ad14 100644
--- a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java
+++ b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java
@@ -34,6 +34,7 @@
 
 import org.apache.fop.area.Area;
 import org.apache.fop.area.Block;
+import org.apache.fop.area.BlockParent;
 import org.apache.fop.area.BlockViewport;
 import org.apache.fop.area.CTM;
 import org.apache.fop.area.RegionViewport;
@@ -62,29 +63,20 @@
      * @param block the block to render the traits
      */
     protected void handleBlockTraits(Block block) {
-        int borderPaddingStart = block.getBorderAndPaddingWidthStart();
-        int borderPaddingBefore = block.getBorderAndPaddingWidthBefore();
-        
-        float startx = currentIPPosition / 1000f;
-        float starty = currentBPPosition / 1000f;
-        float width = block.getIPD() / 1000f;
-        float height = block.getBPD() / 1000f;
-
         /* using start-indent now
         Integer spaceStart = (Integer) block.getTrait(Trait.SPACE_START);
         if (spaceStart != null) {
             startx += spaceStart.floatValue() / 1000f;
         }*/
-        startx += block.getStartIndent() / 1000f;
-        startx -= block.getBorderAndPaddingWidthStart() / 1000f;
-
-        width += borderPaddingStart / 1000f;
-        width += block.getBorderAndPaddingWidthEnd() / 1000f;
-        height += borderPaddingBefore / 1000f;
-        height += block.getBorderAndPaddingWidthAfter() / 1000f;
-
-        drawBackAndBorders(block, startx, starty,
-            width, height);
+        float startx = getBlockTraitsStartX(block);
+        float starty = getBlockTraitsStartY(block);
+        float width = (block.getIPD()
+                + block.getBorderAndPaddingWidthStart()
+                + block.getBorderAndPaddingWidthEnd()) / 1000f;
+        float height = (block.getBPD()
+                + block.getBorderAndPaddingWidthBefore()
+                + block.getBorderAndPaddingWidthAfter()) / 1000f;
+        drawBackAndBorders(block, startx, starty, width, height);
     }
 
     /**
@@ -95,19 +87,17 @@
      */
     protected void handleRegionTraits(RegionViewport region) {
         Rectangle2D viewArea = region.getViewArea();
-        float startx = (float)(viewArea.getX() / 1000f);
-        float starty = (float)(viewArea.getY() / 1000f);
-        float width = (float)(viewArea.getWidth() / 1000f);
-        float height = (float)(viewArea.getHeight() / 1000f);
-
         if (region.getRegionReference().getRegionClass() == FO_REGION_BODY) {
             currentBPPosition = region.getBorderAndPaddingWidthBefore();
             currentIPPosition = region.getBorderAndPaddingWidthStart();
         }
+        float startx = (float)(viewArea.getX() / 1000f);
+        float starty = (float)(viewArea.getY() / 1000f);
+        float width = (float)(viewArea.getWidth() / 1000f);
+        float height = (float)(viewArea.getHeight() / 1000f);
         drawBackAndBorders(region, startx, starty, width, height);
     }
 
-    
     /**
      * Draw the background and borders.
      * This draws the background and border traits for an area given
@@ -123,7 +113,6 @@
                     float startx, float starty,
                     float width, float height) {
         // draw background then border
-
         BorderProps bpsBefore = (BorderProps)area.getTrait(Trait.BORDER_BEFORE);
         BorderProps bpsAfter = (BorderProps)area.getTrait(Trait.BORDER_AFTER);
         BorderProps bpsStart = (BorderProps)area.getTrait(Trait.BORDER_START);
@@ -197,14 +186,22 @@
                         drawImage(back.getURL(), pos);
                     }
                 }
-                
                 restoreGraphicsState();
             }
         }
 
         Rectangle2D.Float borderRect = new Rectangle2D.Float(startx, starty, width, height);
-        drawBorders(borderRect, bpsBefore, bpsAfter, bpsStart, bpsEnd);
+        boolean hasBorder = (bpsBefore != null || bpsAfter != null
+                || bpsStart != null || bpsEnd != null);
+        if (hasBorder) {
+            drawBorders(borderRect, bpsBefore, bpsAfter, bpsStart, bpsEnd);            
+        }
     }
+        
+    private static final int BEFORE = 0;
+    private static final int END = 1;
+    private static final int AFTER = 2;
+    private static final int START = 3;
 
     /**
      * Draws borders.
@@ -213,48 +210,50 @@
      * @param bpsAfter the border specification on the after side
      * @param bpsStart the border specification on the start side
      * @param bpsEnd the border specification on the end side
+     * 
+     * TODO: generalize each of the four conditions into using a parameterized drawBorder()
      */
     protected void drawBorders(Rectangle2D.Float borderRect, 
             BorderProps bpsBefore, BorderProps bpsAfter, BorderProps bpsStart, BorderProps bpsEnd) {
+        boolean[] border = new boolean[] {
+                (bpsBefore != null), (bpsEnd != null), 
+                (bpsAfter != null), (bpsStart != null)};
         float startx = borderRect.x;
         float starty = borderRect.y;
         float width = borderRect.width;
         float height = borderRect.height;
-        boolean[] b = new boolean[] {
-            (bpsBefore != null), (bpsEnd != null), 
-            (bpsAfter != null), (bpsStart != null)};
-        if (!b[0] && !b[1] && !b[2] && !b[3]) {
-            return;
-        }
-        float[] bw = new float[] {
-            (b[0] ? bpsBefore.width / 1000f : 0.0f),
-            (b[1] ? bpsEnd.width / 1000f : 0.0f),
-            (b[2] ? bpsAfter.width / 1000f : 0.0f),
-            (b[3] ? bpsStart.width / 1000f : 0.0f)};
+        float[] borderWidth = new float[] {
+            (border[BEFORE] ? bpsBefore.width / 1000f : 0.0f),
+            (border[END] ? bpsEnd.width / 1000f : 0.0f),
+            (border[AFTER] ? bpsAfter.width / 1000f : 0.0f),
+            (border[START] ? bpsStart.width / 1000f : 0.0f)};
         float[] clipw = new float[] {
             BorderProps.getClippedWidth(bpsBefore) / 1000f,    
             BorderProps.getClippedWidth(bpsEnd) / 1000f,    
             BorderProps.getClippedWidth(bpsAfter) / 1000f,    
             BorderProps.getClippedWidth(bpsStart) / 1000f};
-        starty += clipw[0];
-        height -= clipw[0];
-        height -= clipw[2];
-        startx += clipw[3];
-        width -= clipw[3];
-        width -= clipw[1];
+        starty += clipw[BEFORE];
+        height -= clipw[BEFORE];
+        height -= clipw[AFTER];
+        startx += clipw[START];
+        width -= clipw[START];
+        width -= clipw[END];
         
         boolean[] slant = new boolean[] {
-            (b[3] && b[0]), (b[0] && b[1]), (b[1] && b[2]), (b[2] && b[3])};
+            (border[START] && border[BEFORE]),
+            (border[BEFORE] && border[END]),
+            (border[END] && border[AFTER]),
+            (border[AFTER] && border[START])};
         if (bpsBefore != null) {
             endTextObject();
 
             float sx1 = startx;
-            float sx2 = (slant[0] ? sx1 + bw[3] - clipw[3] : sx1);
+            float sx2 = (slant[BEFORE] ? sx1 + borderWidth[START] - clipw[START] : sx1);
             float ex1 = startx + width;
-            float ex2 = (slant[1] ? ex1 - bw[1] + clipw[1] : ex1);
-            float outery = starty - clipw[0];
-            float clipy = outery + clipw[0];
-            float innery = outery + bw[0];
+            float ex2 = (slant[END] ? ex1 - borderWidth[END] + clipw[END] : ex1);
+            float outery = starty - clipw[BEFORE];
+            float clipy = outery + clipw[BEFORE];
+            float innery = outery + borderWidth[BEFORE];
 
             saveGraphicsState();
             moveTo(sx1, clipy);
@@ -262,10 +261,10 @@
             float ex1a = ex1;
             if (bpsBefore.mode == BorderProps.COLLAPSE_OUTER) {
                 if (bpsStart != null && bpsStart.mode == BorderProps.COLLAPSE_OUTER) {
-                    sx1a -= clipw[3];
+                    sx1a -= clipw[START];
                 }
                 if (bpsEnd != null && bpsEnd.mode == BorderProps.COLLAPSE_OUTER) {
-                    ex1a += clipw[1];
+                    ex1a += clipw[END];
                 }
                 lineTo(sx1a, outery);
                 lineTo(ex1a, outery);
@@ -283,12 +282,12 @@
             endTextObject();
 
             float sy1 = starty;
-            float sy2 = (slant[1] ? sy1 + bw[0] - clipw[0] : sy1);
+            float sy2 = (slant[END] ? sy1 + borderWidth[BEFORE] - clipw[BEFORE] : sy1);
             float ey1 = starty + height;
-            float ey2 = (slant[2] ? ey1 - bw[2] + clipw[2] : ey1);
-            float outerx = startx + width + clipw[1];
-            float clipx = outerx - clipw[1];
-            float innerx = outerx - bw[1];
+            float ey2 = (slant[AFTER] ? ey1 - borderWidth[AFTER] + clipw[AFTER] : ey1);
+            float outerx = startx + width + clipw[END];
+            float clipx = outerx - clipw[END];
+            float innerx = outerx - borderWidth[END];
             
             saveGraphicsState();
             moveTo(clipx, sy1);
@@ -296,10 +295,10 @@
             float ey1a = ey1;
             if (bpsEnd.mode == BorderProps.COLLAPSE_OUTER) {
                 if (bpsBefore != null && bpsBefore.mode == BorderProps.COLLAPSE_OUTER) {
-                    sy1a -= clipw[0];
+                    sy1a -= clipw[BEFORE];
                 }
                 if (bpsAfter != null && bpsAfter.mode == BorderProps.COLLAPSE_OUTER) {
-                    ey1a += clipw[2];
+                    ey1a += clipw[AFTER];
                 }
                 lineTo(outerx, sy1a);
                 lineTo(outerx, ey1a);
@@ -316,12 +315,12 @@
             endTextObject();
 
             float sx1 = startx;
-            float sx2 = (slant[3] ? sx1 + bw[3] - clipw[3] : sx1);
+            float sx2 = (slant[START] ? sx1 + borderWidth[AFTER] - clipw[AFTER] : sx1);
             float ex1 = startx + width;
-            float ex2 = (slant[2] ? ex1 - bw[1] + clipw[1] : ex1);
-            float outery = starty + height + clipw[2];
-            float clipy = outery - clipw[2];
-            float innery = outery - bw[2];
+            float ex2 = (slant[AFTER] ? ex1 - borderWidth[END] + clipw[END] : ex1);
+            float outery = starty + height + clipw[AFTER];
+            float clipy = outery - clipw[AFTER];
+            float innery = outery - borderWidth[AFTER];
 
             saveGraphicsState();
             moveTo(ex1, clipy);
@@ -329,10 +328,10 @@
             float ex1a = ex1;
             if (bpsAfter.mode == BorderProps.COLLAPSE_OUTER) {
                 if (bpsStart != null && bpsStart.mode == BorderProps.COLLAPSE_OUTER) {
-                    sx1a -= clipw[3];
+                    sx1a -= clipw[START];
                 }
                 if (bpsEnd != null && bpsEnd.mode == BorderProps.COLLAPSE_OUTER) {
-                    ex1a += clipw[1];
+                    ex1a += clipw[END];
                 }
                 lineTo(ex1a, outery);
                 lineTo(sx1a, outery);
@@ -349,12 +348,12 @@
             endTextObject();
 
             float sy1 = starty;
-            float sy2 = (slant[0] ? sy1 + bw[0] - clipw[0] : sy1);
+            float sy2 = (slant[START] ? sy1 + borderWidth[BEFORE] - clipw[BEFORE] : sy1);
             float ey1 = sy1 + height;
-            float ey2 = (slant[3] ? ey1 - bw[2] + clipw[2] : ey1);
-            float outerx = startx - clipw[3];
-            float clipx = outerx + clipw[3];
-            float innerx = outerx + bw[3];
+            float ey2 = (slant[START] ? ey1 - borderWidth[AFTER] + clipw[AFTER] : ey1);
+            float outerx = startx - clipw[START];
+            float clipx = outerx + clipw[START];
+            float innerx = outerx + borderWidth[START];
 
             saveGraphicsState();
             moveTo(clipx, ey1);
@@ -362,10 +361,10 @@
             float ey1a = ey1;
             if (bpsStart.mode == BorderProps.COLLAPSE_OUTER) {
                 if (bpsBefore != null && bpsBefore.mode == BorderProps.COLLAPSE_OUTER) {
-                    sy1a -= clipw[0];
+                    sy1a -= clipw[BEFORE];
                 }
                 if (bpsAfter != null && bpsAfter.mode == BorderProps.COLLAPSE_OUTER) {
-                    ey1a += clipw[2];
+                    ey1a += clipw[AFTER];
                 }
                 lineTo(outerx, ey1a);
                 lineTo(outerx, sy1a);
@@ -380,6 +379,22 @@
         }
     }
     
+    protected java.awt.geom.Point2D getInlineAreaPoint(InlineArea area) {
+        float startx = currentIPPosition / 1000f;
+        float starty = (currentBPPosition + area.getOffset()
+                + area.getBorderAndPaddingWidthBefore()) / 1000f;
+        return new java.awt.geom.Point2D.Float(startx, starty);
+    }
+    
+//    protected float getInlineAreaStartX(InlineArea area) {
+//        return currentIPPosition / 1000f;
+//    }
+//
+//    protected float getInlineAreaStartY(InlineArea area) {
+//        return (currentBPPosition + area.getOffset()
+//                + area.getBorderAndPaddingWidthBefore()) / 1000f;
+//    }
+
     /** 
      * Common method to render the background and borders for any inline area.
      * The all borders and padding are drawn outside the specified area.
@@ -387,29 +402,75 @@
      * rendered
      */
     protected void renderInlineAreaBackAndBorders(InlineArea area) {
-        float x = currentIPPosition / 1000f;
-        float y = (currentBPPosition + area.getOffset()) / 1000f;
+        java.awt.geom.Point2D p = getInlineAreaPoint(area);
+//        float startx = (float)p.getX();
+//        float starty = (float)p.getY();
+        float startx = currentIPPosition / 1000f;
+        float starty = (currentBPPosition + area.getOffset()
+                + area.getBorderAndPaddingWidthBefore()) / 1000f;
         float width = area.getIPD() / 1000f;
         float height = area.getBPD() / 1000f;
         float borderPaddingStart = area.getBorderAndPaddingWidthStart() / 1000f;
-        float borderPaddingBefore = area.getBorderAndPaddingWidthBefore() / 1000f;
         float bpwidth = borderPaddingStart 
                 + (area.getBorderAndPaddingWidthEnd() / 1000f);
-        float bpheight = borderPaddingBefore
+        float bpheight = starty
                 + (area.getBorderAndPaddingWidthAfter() / 1000f);
         
         if (height != 0.0f || bpheight != 0.0f && bpwidth != 0.0f) {
-            drawBackAndBorders(area, x, y - borderPaddingBefore
-                                , width + bpwidth
-                                , height + bpheight);
+            drawBackAndBorders(area, startx, starty, width + bpwidth, height + bpheight);
         }
-        
     }
     
+    /**
+     * Returns the position transform.
+     * @param bp        The block parent
+     * @return the position transform
+     */
+    protected AffineTransform getPositionTransform(BlockParent bp) {
+        AffineTransform transform = new AffineTransform();
+        transform.translate(bp.getXOffset(), bp.getYOffset());
+        
+        //"left/"top" (bv.getX/YOffset()) specify the position of the content rectangle
+        transform.translate(
+                -bp.getBorderAndPaddingWidthStart(),
+                -bp.getBorderAndPaddingWidthBefore());
+        return transform;
+    }
+
+    protected float getBlockTraitsStartX(Block block) {
+        return (currentIPPosition + block.getStartIndent()
+                - block.getBorderAndPaddingWidthStart() ) / 1000f;
+    }
+
+    protected float getBlockTraitsStartY(Block block) {
+        return currentBPPosition / 1000f;
+    }
+
+
+    /**
+     * Returns the starting X position for back and borders
+     * @param bv        The block viewport
+     * @return the starting X position
+     */
+    protected float getBackAndBordersStartX(BlockViewport bv) {
+        return 0;
+    }
+
+    /**
+     * Returns the starting Y position for back and borders
+     * @param bv        The block viewport
+     * @return the starting Y position
+     */
+    protected float getBackAndBordersStartY(BlockViewport bv) {
+        return 0;
+    }
+
     private static final QName FOX_TRANSFORM
-            = new QName(ExtensionElementMapping.URI, "fox:transform");
-    
-    /** {@inheritDoc} */
+        = new QName(ExtensionElementMapping.URI, "fox:transform");
+
+    /**
+     * {@inheritDoc}
+     */
     protected void renderBlockViewport(BlockViewport bv, List children) {
         // clip and position viewport if necessary
 
@@ -417,13 +478,6 @@
         int saveIP = currentIPPosition;
         int saveBP = currentBPPosition;
 
-        CTM ctm = bv.getCTM();
-        int borderPaddingStart = bv.getBorderAndPaddingWidthStart();
-        int borderPaddingBefore = bv.getBorderAndPaddingWidthBefore();
-        //This is the content-rect
-        float width = (float)bv.getIPD() / 1000f;
-        float height = (float)bv.getBPD() / 1000f;
-
         if (bv.getPositioning() == Block.ABSOLUTE
                 || bv.getPositioning() == Block.FIXED) {
 
@@ -435,15 +489,10 @@
                 breakOutList = breakOutOfStateStack();
             }
             
-            AffineTransform positionTransform = new AffineTransform();
-            positionTransform.translate(bv.getXOffset(), bv.getYOffset());
+            AffineTransform positionTransform = getPositionTransform(bv);
             
-            //"left/"top" (bv.getX/YOffset()) specify the position of the content rectangle
-            positionTransform.translate(-borderPaddingStart, -borderPaddingBefore);
-
             //Free transformation for the block-container viewport
-            String transf;
-            transf = bv.getForeignAttributeValue(FOX_TRANSFORM);
+            String transf = bv.getForeignAttributeValue(FOX_TRANSFORM);
             if (transf != null) {
                 AffineTransform freeTransform = AWTTransformProducer.createAffineTransform(transf);
                 positionTransform.concatenate(freeTransform);
@@ -452,15 +501,27 @@
             saveGraphicsState();
             //Viewport position
             concatenateTransformationMatrix(mptToPt(positionTransform));
-            
+                    
+            //This is the content-rect
+            float width = (float)bv.getIPD() / 1000f;
+            float height = (float)bv.getBPD() / 1000f;
+
             //Background and borders
-            float bpwidth = (borderPaddingStart + bv.getBorderAndPaddingWidthEnd()) / 1000f;
-            float bpheight = (borderPaddingBefore + bv.getBorderAndPaddingWidthAfter()) / 1000f;
-            drawBackAndBorders(bv, 0, 0, width + bpwidth, height + bpheight);
+            float bpwidth
+                = (bv.getBorderAndPaddingWidthStart()
+                        + bv.getBorderAndPaddingWidthEnd()) / 1000f;
+            float bpheight
+                = (bv.getBorderAndPaddingWidthBefore()
+                        + bv.getBorderAndPaddingWidthAfter()) / 1000f;
+
+            drawBackAndBorders(bv, 0/*getBackAndBordersStartX(bv)*/, /*getBackAndBordersStartY(bv)*/0,
+                    width + bpwidth, height + bpheight);
 
             //Shift to content rectangle after border painting
             AffineTransform contentRectTransform = new AffineTransform();
-            contentRectTransform.translate(borderPaddingStart, borderPaddingBefore);
+            contentRectTransform.translate(
+                    bv.getBorderAndPaddingWidthStart(),
+                    bv.getBorderAndPaddingWidthBefore());
             concatenateTransformationMatrix(mptToPt(contentRectTransform));
             
             //Clipping
@@ -470,7 +531,7 @@
 
             saveGraphicsState();
             //Set up coordinate system for content rectangle
-            AffineTransform contentTransform = ctm.toAffineTransform();
+            AffineTransform contentTransform = bv.getCTM().toAffineTransform();
             concatenateTransformationMatrix(mptToPt(contentTransform));
             
             currentIPPosition = 0;
@@ -479,7 +540,7 @@
 
             restoreGraphicsState();
             restoreGraphicsState();
-            
+
             if (breakOutList != null) {
                 restoreStateStackAfterBreakOut(breakOutList);
             }
@@ -487,6 +548,8 @@
             currentIPPosition = saveIP;
             currentBPPosition = saveBP;
         } else {
+            // bv.getPositioning() == Block.STACK ||
+            // by.getPositioning() == Block.RELATIVE
 
             currentBPPosition += bv.getSpaceBefore();
 
@@ -497,10 +560,10 @@
             currentIPPosition += bv.getStartIndent();
 
             CTM tempctm = new CTM(containingIPPosition, currentBPPosition);
-            ctm = tempctm.multiply(ctm);
+            CTM ctm = tempctm.multiply(bv.getCTM());
             
             //Now adjust for border/padding
-            currentBPPosition += borderPaddingBefore;
+            currentBPPosition += bv.getBorderAndPaddingWidthBefore();
 
             Rectangle2D clippingRect = null;
             if (bv.getClip()) {
@@ -534,7 +597,6 @@
      * @param viewport the viewport to handle
      */
     public void renderViewport(Viewport viewport) {
-
         float x = currentIPPosition / 1000f;
         float y = (currentBPPosition + viewport.getOffset()) / 1000f;
         float width = viewport.getIPD() / 1000f;
diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java
index 32c4b33..d5a395c 100644
--- a/src/java/org/apache/fop/render/AbstractRenderer.java
+++ b/src/java/org/apache/fop/render/AbstractRenderer.java
@@ -276,7 +276,7 @@
             handleRegionTraits(port);
 
             //  shouldn't the viewport have the CTM
-            startVParea(regionReference.getCTM(), port.isClip() ? view : null);
+            startVParea(regionReference.getCTM(), getRegionViewportViewArea(port));
             // do after starting viewport area
             if (regionReference.getRegionClass() == FO_REGION_BODY) {
                 renderBodyRegion((BodyRegion) regionReference);
@@ -287,6 +287,10 @@
         }
     }
 
+    protected Rectangle2D getRegionViewportViewArea(RegionViewport port) {
+        return port.isClip() ? port.getViewArea() : null;
+    }
+    
     /**
      * Establishes a new viewport area.
      *
diff --git a/src/java/org/apache/fop/render/afp/AFPPageFonts.java b/src/java/org/apache/fop/render/afp/AFPPageFonts.java
index e09167f..356d38c 100644
--- a/src/java/org/apache/fop/render/afp/AFPPageFonts.java
+++ b/src/java/org/apache/fop/render/afp/AFPPageFonts.java
@@ -36,13 +36,15 @@
      */
     public AFPFontAttributes registerFont(String fontName, AFPFont font, int fontSize) {
         String pageFontKey = fontName + "_" + fontSize;
-        AFPFontAttributes afpFontAttributes = (AFPFontAttributes)super.get(pageFontKey);
-        // Add to page font mapping if not already present
-        if (afpFontAttributes == null) {
-            afpFontAttributes = new AFPFontAttributes(fontName, font, fontSize);
-            super.put(pageFontKey, afpFontAttributes);
-            afpFontAttributes.setFontReference(super.size());
+        if (!super.containsKey(pageFontKey)) {
+            AFPFontAttributes afpFontAttributes = (AFPFontAttributes)super.get(pageFontKey);
+            // Add to page font mapping if not already present
+            if (afpFontAttributes == null) {
+                afpFontAttributes = new AFPFontAttributes(fontName, font, fontSize);
+                super.put(pageFontKey, afpFontAttributes);
+                afpFontAttributes.setFontReference(super.size());
+            }
         }
-        return afpFontAttributes;
+        return (AFPFontAttributes)super.get(pageFontKey);
     }
 }
\ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java
index 5cdd55d..ebf9beb 100644
--- a/src/java/org/apache/fop/render/afp/AFPRenderer.java
+++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java
@@ -30,11 +30,10 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Stack;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.output.ByteArrayOutputStream;
@@ -52,22 +51,19 @@
 import org.apache.xmlgraphics.image.loader.util.ImageUtil;
 import org.apache.xmlgraphics.ps.ImageEncodingHelper;
 
+import org.apache.fop.apps.FOPException;
 import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.apps.MimeConstants;
-import org.apache.fop.area.Block;
+import org.apache.fop.area.BlockParent;
 import org.apache.fop.area.BlockViewport;
-import org.apache.fop.area.BodyRegion;
 import org.apache.fop.area.CTM;
 import org.apache.fop.area.OffDocumentItem;
 import org.apache.fop.area.PageViewport;
-import org.apache.fop.area.RegionReference;
 import org.apache.fop.area.RegionViewport;
 import org.apache.fop.area.Trait;
 import org.apache.fop.area.inline.Image;
 import org.apache.fop.area.inline.Leader;
-import org.apache.fop.area.inline.SpaceArea;
 import org.apache.fop.area.inline.TextArea;
-import org.apache.fop.area.inline.WordArea;
 import org.apache.fop.datatypes.URISpecification;
 import org.apache.fop.fo.Constants;
 import org.apache.fop.fo.extensions.ExtensionAttachment;
@@ -77,6 +73,7 @@
 import org.apache.fop.fonts.base14.Helvetica;
 import org.apache.fop.fonts.base14.TimesRoman;
 import org.apache.fop.render.AbstractPathOrientedRenderer;
+import org.apache.fop.render.AbstractState;
 import org.apache.fop.render.Graphics2DAdapter;
 import org.apache.fop.render.RendererContext;
 import org.apache.fop.render.afp.extensions.AFPElementMapping;
@@ -90,6 +87,7 @@
 import org.apache.fop.render.afp.modca.AFPDataStream;
 import org.apache.fop.render.afp.modca.ImageObject;
 import org.apache.fop.render.afp.modca.PageObject;
+import org.apache.fop.render.pdf.CTMHelper;
 
 /**
  * This is an implementation of a FOP Renderer that renders areas to AFP.
@@ -175,12 +173,12 @@
     /**
      * The page width
      */
-    private int pageWidth = 0;
+    private int currentPageWidth = 0;
 
     /**
      * The page height
      */
-    private int pageHeight = 0;
+    private int currentPageHeight = 0;
 
     /**
      * The portrait rotation
@@ -222,6 +220,13 @@
         super();
     }
 
+    private AFPState getState() {
+        if (currentState == null) {
+            currentState = new AFPState();
+        }
+        return currentState;
+    }
+    
     /**
      * Set up the font info
      * 
@@ -281,34 +286,25 @@
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public void setUserAgent(FOUserAgent agent) {
         super.setUserAgent(agent);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public void startRenderer(OutputStream outputStream) throws IOException {
-        this.currentState = new AFPState();
-        this.afpDataStream = new AFPDataStream();
-        this.afpDataStream.setPortraitRotation(portraitRotation);
-        this.afpDataStream.setLandscapeRotation(landscapeRotation);
-        this.afpDataStream.startDocument(outputStream);
+        getState();
+        getAFPDataStream().setPortraitRotation(portraitRotation);
+        getAFPDataStream().setLandscapeRotation(landscapeRotation);
+        getAFPDataStream().startDocument(outputStream);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public void stopRenderer() throws IOException {
-        this.afpDataStream.endDocument();
+        getAFPDataStream().endDocument();
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public boolean supportsOutOfOrder() {
         // return false;
         return true;
@@ -324,262 +320,243 @@
      * {@inheritDoc}
      */
     public void preparePage(PageViewport page) {
-
-        this.currentState.reset();
+        getState().reset();
 
         Rectangle2D bounds = page.getViewArea();
 
-        this.pageWidth = mpts2units(bounds.getWidth());
-        this.pageHeight = mpts2units(bounds.getHeight());
+        this.currentPageWidth = mpts2units(bounds.getWidth());
+        this.currentPageHeight = mpts2units(bounds.getHeight());
 
         final int pageRotation = 0;
-        this.afpDataStream.startPage(pageWidth, pageHeight, pageRotation,
+        getAFPDataStream().startPage(currentPageWidth, currentPageHeight, pageRotation,
                 this.resolution, this.resolution);
 
         renderPageObjectExtensions(page);
 
         if (this.pages == null) {
-            this.pages = new HashMap();
+            this.pages = new java.util.HashMap();
         }
-        this.pages.put(page, afpDataStream.savePage());
-
+        this.pages.put(page, getAFPDataStream().savePage());
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public void processOffDocumentItem(OffDocumentItem odi) {
         // TODO
+        log.debug("NYI processOffDocumentItem(" + odi + ")");
     }
 
     /** {@inheritDoc} */
     public Graphics2DAdapter getGraphics2DAdapter() {
         return new AFPGraphics2DAdapter();
     }
-
-    /**
-     * {@inheritDoc}
-     */
+        
+    /** {@inheritDoc} */
     public void startVParea(CTM ctm, Rectangle2D clippingRect) {
-        // dummy not used
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void endVParea() {
-        // dummy not used
-    }
-
-    /**
-     * Renders a region viewport.
-     * <p>
-     * 
-     * The region may clip the area and it establishes a position from where the
-     * region is placed.
-     * </p>
-     * 
-     * @param port
-     *            The region viewport to be rendered
-     */
-    public void renderRegionViewport(RegionViewport port) {
-        if (port != null) {
-            Rectangle2D view = port.getViewArea();
-            // The CTM will transform coordinates relative to
-            // this region-reference area into page coords, so
-            // set origin for the region to 0,0.
-            currentBPPosition = 0;
-            currentIPPosition = 0;
-
-            RegionReference regionReference = port.getRegionReference();
-            handleRegionTraits(port);
-
-            /*
-             * _afpDataStream.startOverlay(mpts2units(view.getX()) ,
-             * mpts2units(view.getY()) , mpts2units(view.getWidth()) ,
-             * mpts2units(view.getHeight()) , rotation);
-             */
-
-            pushViewPortPos(new ViewPortPos(view, regionReference.getCTM()));
-
-            if (regionReference.getRegionClass() == FO_REGION_BODY) {
-                renderBodyRegion((BodyRegion) regionReference);
-            } else {
-                renderRegion(regionReference);
-            }
-            /*
-             * _afpDataStream.endOverlay();
-             */
-            popViewPortPos();
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void renderBlockViewport(BlockViewport bv, List children) {
-        // clip and position viewport if necessary
-
-        // save positions
-        int saveIP = currentIPPosition;
-        int saveBP = currentBPPosition;
-        // String saveFontName = currentFontName;
-
-        CTM ctm = bv.getCTM();
-        int borderPaddingStart = bv.getBorderAndPaddingWidthStart();
-        int borderPaddingBefore = bv.getBorderAndPaddingWidthBefore();
-        float x, y;
-        x = (float) (bv.getXOffset() + containingIPPosition) / 1000f;
-        y = (float) (bv.getYOffset() + containingBPPosition) / 1000f;
-        // This is the content-rect
-        float width = (float) bv.getIPD() / 1000f;
-        float height = (float) bv.getBPD() / 1000f;
-
-        if (bv.getPositioning() == Block.ABSOLUTE
-                || bv.getPositioning() == Block.FIXED) {
-
-            currentIPPosition = bv.getXOffset();
-            currentBPPosition = bv.getYOffset();
-
-            // For FIXED, we need to break out of the current viewports to the
-            // one established by the page. We save the state stack for
-            // restoration
-            // after the block-container has been painted. See below.
-            List breakOutList = null;
-            if (bv.getPositioning() == Block.FIXED) {
-                breakOutList = breakOutOfStateStack();
-            }
-
-            CTM tempctm = new CTM(containingIPPosition, containingBPPosition);
-            ctm = tempctm.multiply(ctm);
-
-            // Adjust for spaces (from margin or indirectly by start-indent etc.
-            x += bv.getSpaceStart() / 1000f;
-            currentIPPosition += bv.getSpaceStart();
-
-            y += bv.getSpaceBefore() / 1000f;
-            currentBPPosition += bv.getSpaceBefore();
-
-            float bpwidth = (borderPaddingStart + bv
-                    .getBorderAndPaddingWidthEnd()) / 1000f;
-            float bpheight = (borderPaddingBefore + bv
-                    .getBorderAndPaddingWidthAfter()) / 1000f;
-
-            drawBackAndBorders(bv, x, y, width + bpwidth, height + bpheight);
-
-            // Now adjust for border/padding
-            currentIPPosition += borderPaddingStart;
-            currentBPPosition += borderPaddingBefore;
-
-            Rectangle2D clippingRect = null;
-            clippingRect = new Rectangle(currentIPPosition, currentBPPosition,
-                    bv.getIPD(), bv.getBPD());
-
-            // startVParea(ctm, clippingRect);
-            pushViewPortPos(new ViewPortPos(clippingRect, ctm));
-            currentIPPosition = 0;
-            currentBPPosition = 0;
-            renderBlocks(bv, children);
-            // endVParea();
-            popViewPortPos();
-
-            if (breakOutList != null) {
-                restoreStateStackAfterBreakOut(breakOutList);
-            }
-
-            currentIPPosition = saveIP;
-            currentBPPosition = saveBP;
+        saveGraphicsState();
+        ViewPortPos vpp;
+        if (ctm != null && clippingRect != null) {
+            AffineTransform at = new AffineTransform(CTMHelper.toPDFArray(ctm));
+            // Set the given CTM in the graphics state
+            getState().concatenate(at);
+            vpp = new ViewPortPos(clippingRect, ctm);
         } else {
-
-            currentBPPosition += bv.getSpaceBefore();
-
-            // borders and background in the old coordinate system
-            handleBlockTraits(bv);
-
-            // Advance to start of content area
-            currentIPPosition += bv.getStartIndent();
-
-            CTM tempctm = new CTM(containingIPPosition, currentBPPosition);
-            ctm = tempctm.multiply(ctm);
-
-            // Now adjust for border/padding
-            currentBPPosition += borderPaddingBefore;
-
-            Rectangle2D clippingRect = null;
-            clippingRect = new Rectangle(currentIPPosition, currentBPPosition,
-                    bv.getIPD(), bv.getBPD());
-
-            // startVParea(ctm, clippingRect);
-            pushViewPortPos(new ViewPortPos(clippingRect, ctm));
-
-            currentIPPosition = 0;
-            currentBPPosition = 0;
-            renderBlocks(bv, children);
-            // endVParea();
-            popViewPortPos();
-
-            currentIPPosition = saveIP;
-            currentBPPosition = saveBP;
-
-            currentBPPosition += (int) (bv.getAllocBPD());
+            vpp = new ViewPortPos();
         }
-        // currentFontName = saveFontName;
+        getViewPortStack().push(vpp);
+        getAFPDataStream().setOffsets(vpp.x, vpp.y, vpp.rot);
     }
 
     /** {@inheritDoc} */
-    protected void concatenateTransformationMatrix(AffineTransform at) {
-        //Not used here since AFPRenderer defines its own renderBlockViewport() method.
-        throw new UnsupportedOperationException("NYI");
+    public void endVParea() {
+        if (!getViewPortStack().isEmpty()) {
+            ViewPortPos vpp = (ViewPortPos)getViewPortStack().pop();            
+            getAFPDataStream().setOffsets(vpp.x, vpp.y, vpp.rot);
+        }
+        restoreGraphicsState();
     }
     
+    /** {@inheritDoc} */
+    protected void concatenateTransformationMatrix(AffineTransform at) {
+        if (!at.isIdentity()) {
+            getState().concatenate(at);
+//            double transX = at.getTranslateX();
+//            double transY = at.getTranslateY();
+            float[] srcPts = new float[] {0, 0};
+            int rot = 0;
+            if (!getViewPortStack().isEmpty()) {
+//                new ViewPortPos(new CTM(at));
+                ViewPortPos vpp = (ViewPortPos)getViewPortStack().peek();
+                srcPts[0] = vpp.x;
+                srcPts[1] = vpp.y;
+                rot = vpp.rot;
+//                    ViewPortPos transVpp
+//                        = new ViewPortPos(Math.round(dstPts[0]), Math.round(dstPts[1]), vpp.rot);
+//                    getViewPortPositions().add(transVpp);
+//                    getAFPDataStream().setOffsets(transVpp.x, transVpp.y, transVpp.rot);
+            }
+            float[] dstPts = new float[2];
+            at.transform(srcPts, 0, dstPts, 0, 1);
+//            getAFPDataStream().setOffsets(pts2units(dstPts[0]), pts2units(dstPts[1]), rot);
+            getAFPDataStream().setOffsets(Math.round(dstPts[0]), Math.round(dstPts[1]), rot);
+//            getViewPortPositions().
+//            getViewPortPositions().add(vpp);
+        }
+    }
+
+//    protected Rectangle2D getRegionViewportViewArea(RegionViewport port) {
+//        return port.getViewArea();
+//    }
+
+//    /**
+//     * Renders a region viewport.
+//     * <p>
+//     * 
+//     * The region may clip the area and it establishes a position from where the
+//     * region is placed.
+//     * </p>
+//     * 
+//     * @param port
+//     *            The region viewport to be rendered
+//     */
+//    public void renderRegionViewport(RegionViewport port) {
+//        if (port != null) {
+//            Rectangle2D view = port.getViewArea();
+//            // The CTM will transform coordinates relative to
+//            // this region-reference area into page coords, so
+//            // set origin for the region to 0,0.
+//            currentBPPosition = 0;
+//            currentIPPosition = 0;
+//
+//            RegionReference regionReference = port.getRegionReference();
+//            handleRegionTraits(port);
+//
+//            /*
+//             * _afpDataStream.startOverlay(mpts2units(view.getX()) ,
+//             * mpts2units(view.getY()) , mpts2units(view.getWidth()) ,
+//             * mpts2units(view.getHeight()) , rotation);
+//             */
+//
+//            startVParea(regionReference.getCTM(), view);
+//
+//            if (regionReference.getRegionClass() == FO_REGION_BODY) {
+//                renderBodyRegion((BodyRegion) regionReference);
+//            } else {
+//                renderRegion(regionReference);
+//            }
+//            /*
+//             * _afpDataStream.endOverlay();
+//             */
+//            endVParea();
+//        }
+//    }
+
     /**
-     * {@inheritDoc}
+     * Returns the position transform
+     * @param bp        The block parent
+     * @return the position transform
      */
-    public void renderPage(PageViewport pageViewport) {
+    protected AffineTransform getPositionTransform(BlockParent bp) {
+        AffineTransform transform = super.getPositionTransform(bp);
+//        AffineTransform at = new AffineTransform();
+//        at.
+//        Math.round(mpt / (DPI_CONVERSION_FACTOR / getResolution()));
+//        transform.concatenate(at);
+        return transform;
+    }
 
-        currentState.reset();
+    /** {@inheritDoc} */
+    protected float getBackAndBordersStartX(BlockViewport bv) {
+        return (float) (bv.getXOffset() + bv.getSpaceStart() + containingIPPosition) / 1000f;
+    }
 
+    /** {@inheritDoc} */
+    protected float getBackAndBordersStartY(BlockViewport bv) {
+        return (float) (bv.getYOffset() + bv.getSpaceBefore() + containingBPPosition) / 1000f;
+    }
+
+//    /** {@inheritDoc} */
+//    protected float getInlineAreaStartX(InlineArea area) {
+//        return currentIPPosition / 1000f;
+//    }
+//
+//    /** {@inheritDoc} */
+//    protected float getInlineAreaStartY(InlineArea area) {
+//        float height = area.getBPD() / 1000f;
+//        float blah = (currentBPPosition + area.getOffset()
+//                - area.getBorderAndPaddingWidthBefore() / 1000f);
+//        return height - blah;
+//    }
+
+    /** {@inheritDoc} */    
+//    protected void handleDrawBackAndBorders(BlockViewport bv, List children) {
+//
+//        CTM tempctm = new CTM(containingIPPosition, containingBPPosition);
+//        CTM ctm = tempctm.multiply(bv.getCTM());
+//
+//        // Adjust for spaces (from margin or indirectly by start-indent etc.
+//        currentIPPosition = bv.getXOffset() + bv.getSpaceStart();
+//        currentBPPosition = bv.getYOffset() + bv.getSpaceBefore();
+//
+//        float bpwidth
+//            = (bv.getBorderAndPaddingWidthStart() + bv.getBorderAndPaddingWidthEnd()) / 1000f;
+//        float bpheight
+//            = (bv.getBorderAndPaddingWidthBefore() + bv.getBorderAndPaddingWidthAfter()) / 1000f;
+//
+//        float x = (float) (bv.getXOffset() + bv.getSpaceStart() + containingIPPosition) / 1000f;
+//        float y = (float) (bv.getYOffset() + bv.getSpaceBefore() + containingBPPosition) / 1000f;
+//
+//        //This is the content-rect
+//        float width = (float)bv.getIPD() / 1000f;
+//        float height = (float)bv.getBPD() / 1000f;
+//
+//        drawBackAndBorders(bv, x, y, width + bpwidth, height + bpheight);
+//
+//        // Now adjust for border/padding
+//        currentIPPosition += bv.getBorderAndPaddingWidthStart();
+//        currentBPPosition += bv.getBorderAndPaddingWidthBefore();
+//
+//        Rectangle2D clippingRect = null;
+//        clippingRect
+//            = new Rectangle(currentIPPosition, currentBPPosition, bv.getIPD(), bv.getBPD());
+//
+//        startVParea(ctm, clippingRect);
+//        currentIPPosition = 0;
+//        currentBPPosition = 0;
+//        renderBlocks(bv, children);
+//        endVParea();
+//    }
+    
+    /** {@inheritDoc} */
+    public void renderPage(PageViewport pageViewport) throws IOException, FOPException {
+        getState().reset();
         Rectangle2D bounds = pageViewport.getViewArea();
-
-        this.pageWidth = mpts2units(bounds.getWidth());
-        this.pageHeight = mpts2units(bounds.getHeight());
-
+        this.currentPageWidth = mpts2units(bounds.getWidth());
+        this.currentPageHeight = mpts2units(bounds.getHeight());
         if (pages != null && pages.containsKey(pageViewport)) {
-
-            this.afpDataStream.restorePage((PageObject) pages
+            getAFPDataStream().restorePage((PageObject) pages
                     .remove(pageViewport));
-
         } else {
-
             final int pageRotation = 0;
-            this.afpDataStream.startPage(pageWidth, pageHeight, pageRotation,
+            getAFPDataStream().startPage(currentPageWidth, currentPageHeight, pageRotation,
                     this.resolution, this.resolution);
 
             renderPageObjectExtensions(pageViewport);
-
         }
+//        startVParea(null, null);
+        
+        getAFPDataStream().addFontsToCurrentPage(getState().getPageFonts());
 
-        pushViewPortPos(new ViewPortPos());
+        super.renderPage(pageViewport);
+        
+        getAFPDataStream().endPage();
 
-        renderPageAreas(pageViewport.getPage());
-
-        this.afpDataStream.addFontsToCurrentPage(currentState.getPageFonts());
-
-        try {
-            afpDataStream.endPage();
-        } catch (IOException ioex) {
-            // TODO What shall we do?
-        }
-
-        popViewPortPos();
-
+//        endVParea();
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public void clip() {
         // TODO
+        log.debug("NYI: clip()");
     }
 
     /**
@@ -587,45 +564,39 @@
      */
     public void clipRect(float x, float y, float width, float height) {
         // TODO
+        log.debug("NYI: clipRect(x=" + x + ",y=" + y + ",width=" + width + ",height=" + height + ")");
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public void moveTo(float x, float y) {
         // TODO
+        log.debug("NYI: moveTo(x=" + x + ",y=" + y + ")");
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public void lineTo(float x, float y) {
         // TODO
+        log.debug("NYI: lineTo(x=" + x + ",y=" + y + ")");
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public void closePath() {
         // TODO
+        log.debug("NYI: closePath()");
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public void fillRect(float x, float y, float width, float height) {
         /*
          * afpDataStream.createShading( pts2units(x), pts2units(y),
          * pts2units(width), pts2units(height), currentColor.getRed(),
          * currentColor.getGreen(), currentColor.getBlue());
          */
-        afpDataStream.createLine(pts2units(x), pts2units(y), pts2units(x
-                + width), pts2units(y), pts2units(height), currentState.getColor());
+        getAFPDataStream().createLine(pts2units(x), pts2units(y), pts2units(x
+                + width), pts2units(y), pts2units(height), getState().getColor());
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public void drawBorderLine(float x1, float y1, float x2, float y2,
             boolean horz, boolean startOrBefore, int style, Color col) {
         float w = x2 - x1;
@@ -640,17 +611,17 @@
                 float h3 = h / 3;
                 float ym1 = y1;
                 float ym2 = ym1 + h3 + h3;
-                afpDataStream.createLine(pts2units(x1), pts2units(ym1),
+                getAFPDataStream().createLine(pts2units(x1), pts2units(ym1),
                         pts2units(x2), pts2units(ym1), pts2units(h3), col);
-                afpDataStream.createLine(pts2units(x1), pts2units(ym2),
+                getAFPDataStream().createLine(pts2units(x1), pts2units(ym2),
                         pts2units(x2), pts2units(ym2), pts2units(h3), col);
             } else {
                 float w3 = w / 3;
                 float xm1 = x1;
                 float xm2 = xm1 + w3 + w3;
-                afpDataStream.createLine(pts2units(xm1), pts2units(y1),
+                getAFPDataStream().createLine(pts2units(xm1), pts2units(y1),
                         pts2units(xm1), pts2units(y2), pts2units(w3), col);
-                afpDataStream.createLine(pts2units(xm2), pts2units(y1),
+                getAFPDataStream().createLine(pts2units(xm2), pts2units(y1),
                         pts2units(xm2), pts2units(y2), pts2units(w3), col);
             }
             break;
@@ -658,7 +629,7 @@
             if (horz) {
                 float w2 = 2 * h;
                 while (x1 + w2 < x2) {
-                    afpDataStream.createLine(pts2units(x1), pts2units(y1),
+                    getAFPDataStream().createLine(pts2units(x1), pts2units(y1),
                             pts2units(x1 + w2), pts2units(y1), pts2units(h),
                             col);
                     x1 += 2 * w2;
@@ -666,7 +637,7 @@
             } else {
                 float h2 = 2 * w;
                 while (y1 + h2 < y2) {
-                    afpDataStream.createLine(pts2units(x1), pts2units(y1),
+                    getAFPDataStream().createLine(pts2units(x1), pts2units(y1),
                             pts2units(x1), pts2units(y1 + h2), pts2units(w),
                             col);
                     y1 += 2 * h2;
@@ -676,7 +647,7 @@
         case Constants.EN_DOTTED:
             if (horz) {
                 while (x1 + h < x2) {
-                    afpDataStream
+                    getAFPDataStream()
                             .createLine(pts2units(x1), pts2units(y1),
                                     pts2units(x1 + h), pts2units(y1),
                                     pts2units(h), col);
@@ -684,7 +655,7 @@
                 }
             } else {
                 while (y1 + w < y2) {
-                    afpDataStream
+                    getAFPDataStream()
                             .createLine(pts2units(x1), pts2units(y1),
                                     pts2units(x1), pts2units(y1 + w),
                                     pts2units(w), col);
@@ -700,11 +671,11 @@
                 Color lowercol = lightenColor(col, colFactor);
                 float h3 = h / 3;
                 float ym1 = y1;
-                afpDataStream.createLine(pts2units(x1), pts2units(ym1),
+                getAFPDataStream().createLine(pts2units(x1), pts2units(ym1),
                         pts2units(x2), pts2units(ym1), pts2units(h3), uppercol);
-                afpDataStream.createLine(pts2units(x1), pts2units(ym1 + h3),
+                getAFPDataStream().createLine(pts2units(x1), pts2units(ym1 + h3),
                         pts2units(x2), pts2units(ym1 + h3), pts2units(h3), col);
-                afpDataStream.createLine(pts2units(x1),
+                getAFPDataStream().createLine(pts2units(x1),
                         pts2units(ym1 + h3 + h3), pts2units(x2), pts2units(ym1
                                 + h3 + h3), pts2units(h3), lowercol);
             } else {
@@ -712,11 +683,11 @@
                 Color rightcol = lightenColor(col, colFactor);
                 float w3 = w / 3;
                 float xm1 = x1 + (w3 / 2);
-                afpDataStream.createLine(pts2units(xm1), pts2units(y1),
+                getAFPDataStream().createLine(pts2units(xm1), pts2units(y1),
                         pts2units(xm1), pts2units(y2), pts2units(w3), leftcol);
-                afpDataStream.createLine(pts2units(xm1 + w3), pts2units(y1),
+                getAFPDataStream().createLine(pts2units(xm1 + w3), pts2units(y1),
                         pts2units(xm1 + w3), pts2units(y2), pts2units(w3), col);
-                afpDataStream.createLine(pts2units(xm1 + w3 + w3),
+                getAFPDataStream().createLine(pts2units(xm1 + w3 + w3),
                         pts2units(y1), pts2units(xm1 + w3 + w3), pts2units(y2),
                         pts2units(w3), rightcol);
             }
@@ -727,15 +698,13 @@
         case Constants.EN_INSET:
         case Constants.EN_OUTSET:
         default:
-            afpDataStream.createLine(pts2units(x1), pts2units(y1),
+            getAFPDataStream().createLine(pts2units(x1), pts2units(y1),
                     pts2units(horz ? x2 : x1), pts2units(horz ? y1 : y2),
                     pts2units(Math.abs(horz ? (y2 - y1) : (x2 - x1))), col);
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     protected RendererContext createRendererContext(int x, int y, int width,
             int height, Map foreignAttributes) {
         RendererContext context;
@@ -750,9 +719,9 @@
         context.setProperty(AFPRendererContextConstants.AFP_BITS_PER_PIXEL,
                 new Integer(this.bitsPerPixel));
         context.setProperty(AFPRendererContextConstants.AFP_DATASTREAM,
-                this.afpDataStream);
+                getAFPDataStream());
         context.setProperty(AFPRendererContextConstants.AFP_STATE,
-                this.currentState);
+                getState());
         return context;
     }
 
@@ -780,7 +749,7 @@
             name = (String) pageSegmentsMap.get(uri);
         }
         if (name != null) {
-            afpDataStream.createIncludePageSegment(name, mpts2units(x), mpts2units(y));
+            getAFPDataStream().createIncludePageSegment(name, mpts2units(x), mpts2units(y));
         } else {
             ImageManager manager = getUserAgent().getFactory().getImageManager();
             ImageInfo info = null;
@@ -819,7 +788,7 @@
                     int afpw = mpts2units(posInt.getWidth());
                     int afph = mpts2units(posInt.getHeight());
                     int afpres = getResolution();
-                    ImageObject io = afpDataStream.getImageObject(afpx, afpy, afpw, afph,
+                    ImageObject io = getAFPDataStream().getImageObject(afpx, afpy, afpw, afph,
                             afpres, afpres);
                     io.setImageParameters(
                             (int) (ccitt.getSize().getDpiHorizontal() * 10),
@@ -1022,7 +991,7 @@
             byte[] buf = baout.toByteArray();
 
             // Generate image
-            ImageObject io = afpDataStream.getImageObject(afpx, afpy, afpw,
+            ImageObject io = getAFPDataStream().getImageObject(afpx, afpy, afpw,
                     afph, afpres, afpres);
             io.setImageParameters(imageResolution, imageResolution,
                     image.getWidth(), image.getHeight());
@@ -1046,94 +1015,94 @@
      */
     public void updateColor(Color col, boolean fill) {
         if (fill) {
-            currentState.setColor(col);
+            getState().setColor(col);
         }
     }
 
-    /**
-     * Restores the state stack after a break out.
-     * 
-     * @param breakOutList
-     *            the state stack to restore.
-     */
+    /** {@inheritDoc} */
     public void restoreStateStackAfterBreakOut(List breakOutList) {
-
+        AbstractState.AbstractData data;
+        Iterator i = breakOutList.iterator();
+        while (i.hasNext()) {
+            data = (AbstractState.AbstractData)i.next();
+            saveGraphicsState();
+            concatenateTransformationMatrix(data.getTransform());
+        }
     }
 
-    /**
-     * Breaks out of the state stack to handle fixed block-containers.
-     * 
-     * @return the saved state stack to recreate later
-     */
-    public List breakOutOfStateStack() {
-        return null;
+    /** {@inheritDoc} */
+    protected List breakOutOfStateStack() {
+        List breakOutList = new java.util.ArrayList();
+        AbstractState.AbstractData data;
+        while (true) {
+            data = currentState.getData();
+            if (currentState.pop() == null) {
+                break;
+            }
+            breakOutList.add(0, data); //Insert because of stack-popping
+        }
+        return breakOutList;
     }
 
-    /** Saves the graphics state of the rendering engine. */
+    /** {@inheritDoc} */
     public void saveGraphicsState() {
-
+        getState().push();
     }
 
-    /** Restores the last graphics state of the rendering engine. */
+    /** {@inheritDoc} */
     public void restoreGraphicsState() {
-
+        getState().pop();
     }
 
-    /** Indicates the beginning of a text object. */
+    /** {@inheritDoc} */
     public void beginTextObject() {
-
     }
 
-    /** Indicates the end of a text object. */
+    /** {@inheritDoc} */
     public void endTextObject() {
-
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public void renderImage(Image image, Rectangle2D pos) {
         String url = image.getURL();
         drawImage(url, pos);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+//    protected java.awt.geom.Point2D getInlineAreaPoint(InlineArea area) {
+//        return getState().getTransform().transform(super.getInlineAreaPoint(area), null);
+//    }
+
+    /** {@inheritDoc} */
     public void renderText(TextArea text) {
         renderInlineAreaBackAndBorders(text);
-
+        
+        //TODO: remove internal state handling of PresentationText objects and plug in AFPState 
         String internalFontName = getInternalFontNameForArea(text);
-        this.currentState.setFontName(internalFontName);
+        getState().setFontName(internalFontName);
+        
         int currentFontSize = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue();
-        this.currentState.setFontSize(currentFontSize); 
+        getState().setFontSize(currentFontSize);
+        
         AFPFont font = (AFPFont) fontInfo.getFonts().get(internalFontName);
-
+        
         Color col = (Color) text.getTrait(Trait.COLOR);
-
-        int vsci = mpts2units(font.getWidth(' ', currentFontSize) / 1000
+        getState().setColor(col);
+        
+        int variableSpaceCharacterIncrement = mpts2units(font.getWidth(' ', currentFontSize) / 1000
                 + text.getTextWordSpaceAdjust()
                 + text.getTextLetterSpaceAdjust());
-
         // word.getOffset() = only height of text itself
         // currentBlockIPPosition: 0 for beginning of line; nonzero
         // where previous line area failed to take up entire allocated space
         int rx = currentIPPosition + text.getBorderAndPaddingWidthStart();
-        int bl = currentBPPosition + text.getOffset()
-                + text.getBaselineOffset();
-
+        int bl = currentBPPosition + text.getOffset() + text.getBaselineOffset();
         // Set letterSpacing
         // float ls = fs.getLetterSpacing() / this.currentFontSize;
-
         String worddata = text.getText();
-
-        AFPPageFonts pageFonts = this.currentState.getPageFonts();
-        AFPFontAttributes afpFontAttributes = pageFonts.registerFont(
+        AFPFontAttributes afpFontAttributes = getState().getPageFonts().registerFont(
                 internalFontName, font, currentFontSize);
-
         // Try and get the encoding to use for the font
         String encoding = null;
-
         try {
             encoding = font.getCharacterSet(currentFontSize).getEncoding();
         } catch (Throwable ex) {
@@ -1141,63 +1110,21 @@
             log.warn("renderText():: Error getting encoding for font "
                     + " - using default encoding " + encoding);
         }
-
         try {
-            afpDataStream.createText(afpFontAttributes.getFontReference(),
-                    mpts2units(rx), pts2units(bl), col, vsci, mpts2units(text
-                            .getTextLetterSpaceAdjust()), worddata
-                            .getBytes(encoding));
+            getAFPDataStream().createText(afpFontAttributes.getFontReference(),
+                    mpts2units(rx), pts2units(bl),
+                    col, variableSpaceCharacterIncrement,
+                    mpts2units(text.getTextLetterSpaceAdjust()),
+                        worddata.getBytes(encoding));
         } catch (UnsupportedEncodingException usee) {
             log.error("renderText:: Font " + afpFontAttributes.getFontKey()
                     + " caused UnsupportedEncodingException");
         }
-
         super.renderText(text);
-
         renderTextDecoration(font, currentFontSize, text, bl, rx);
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public void renderWord(WordArea word) {
-        // UNUSED
-        // String name = getInternalFontNameForArea(word.getParentArea());
-        // int size = ((Integer)
-        // word.getParentArea().getTrait(Trait.FONT_SIZE)).intValue();
-        // AFPFont tf = (AFPFont) fontInfo.getFonts().get(name);
-        //
-        // String s = word.getWord();
-        //
-        // FontMetrics metrics = fontInfo.getMetricsFor(name);
-
-        super.renderWord(word);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void renderSpace(SpaceArea space) {
-        // UNUSED
-        // String name = getInternalFontNameForArea(space.getParentArea());
-        // int size = ((Integer)
-        // space.getParentArea().getTrait(Trait.FONT_SIZE)).intValue();
-        // AFPFont tf = (AFPFont) fontInfo.getFonts().get(name);
-        //
-        // String s = space.getSpace();
-        //
-        // FontMetrics metrics = fontInfo.getMetricsFor(name);
-
-        super.renderSpace(space);
-    }
-
-    /**
-     * Render leader area. This renders a leader area which is an area with a
-     * rule.
-     * 
-     * @param area
-     *            the leader area to render
-     */
+    /** {@inheritDoc} */
     public void renderLeader(Leader area) {
         renderInlineAreaBackAndBorders(area);
 
@@ -1234,7 +1161,6 @@
      *            The rotation in degrees.
      */
     public void setPortraitRotation(int rotation) {
-
         if (rotation == 0 || rotation == 90 || rotation == 180
                 || rotation == 270) {
             portraitRotation = rotation;
@@ -1242,9 +1168,7 @@
             throw new IllegalArgumentException(
                     "The portrait rotation must be one"
                             + " of the values 0, 90, 180, 270");
-
         }
-
     }
 
     /**
@@ -1255,7 +1179,6 @@
      *            The rotation in degrees.
      */
     public void setLandscapeRotation(int rotation) {
-
         if (rotation == 0 || rotation == 90 || rotation == 180
                 || rotation == 270) {
             landscapeRotation = rotation;
@@ -1264,7 +1187,6 @@
                     "The landscape rotation must be one"
                             + " of the values 0, 90, 180, 270");
         }
-
     }
 
     /**
@@ -1284,7 +1206,6 @@
      *            the page object
      */
     private void renderPageObjectExtensions(PageViewport pageViewport) {
-
         pageSegmentsMap = null;
         if (pageViewport.getExtensionAttachments() != null
                 && pageViewport.getExtensionAttachments().size() > 0) {
@@ -1299,14 +1220,14 @@
                     if (AFPElementMapping.INCLUDE_PAGE_OVERLAY.equals(element)) {
                         String overlay = aps.getName();
                         if (overlay != null) {
-                            afpDataStream.createIncludePageOverlay(overlay);
+                            getAFPDataStream().createIncludePageOverlay(overlay);
                         }
                     } else if (AFPElementMapping.INCLUDE_PAGE_SEGMENT
                             .equals(element)) {
                         String name = aps.getName();
                         String source = aps.getValue();
                         if (pageSegmentsMap == null) {
-                            pageSegmentsMap = new HashMap();
+                            pageSegmentsMap = new java.util.HashMap();
                         }
                         pageSegmentsMap.put(source, name);
                     } else if (AFPElementMapping.TAG_LOGICAL_ELEMENT
@@ -1314,19 +1235,18 @@
                         String name = aps.getName();
                         String value = aps.getValue();
                         if (pageSegmentsMap == null) {
-                            pageSegmentsMap = new HashMap();
+                            pageSegmentsMap = new java.util.HashMap();
                         }
-                        afpDataStream.createTagLogicalElement(name, value);
+                        getAFPDataStream().createTagLogicalElement(name, value);
                     } else if (AFPElementMapping.NO_OPERATION.equals(element)) {
                         String content = aps.getContent();
                         if (content != null) {
-                            afpDataStream.createNoOperation(content);
+                            getAFPDataStream().createNoOperation(content);
                         }
                     }
                 }
             }
         }
-
     }
 
     /**
@@ -1356,9 +1276,8 @@
      *            the millipoints value
      * @return afp measurement unit value
      */
-    private int mpts2units(double mpt) {
-        return (int) Math
-                .round(mpt / (DPI_CONVERSION_FACTOR / getResolution()));
+    protected int mpts2units(double mpt) {
+        return (int)Math.round(mpt / (DPI_CONVERSION_FACTOR / getResolution()));
     }
 
     /**
@@ -1423,6 +1342,15 @@
         io.setImageData(bw);
     }
 
+    private Stack/*<ViewPortPos>*/ viewPortStack = null;
+
+    private Stack/*<ViewPortPos>*/ getViewPortStack() {
+        if (viewPortStack == null) {
+            viewPortStack = new Stack/*<ViewPortPos>*/();
+        }
+        return viewPortStack;
+    }
+
     private final class ViewPortPos {
         private int x = 0;
 
@@ -1430,12 +1358,21 @@
 
         private int rot = 0;
 
-        private ViewPortPos() {
+        private Rectangle2D view;
+
+        ViewPortPos() {
         }
 
+//        private ViewPortPos(int x, int y, int rot) {
+//            this.x = x;
+//            this.y = y;
+//            this.rot = rot;
+//        }
+//
+        
         private ViewPortPos(Rectangle2D view, CTM ctm) {
-            ViewPortPos currentVP = (ViewPortPos) viewPortPositions
-                    .get(viewPortPositions.size() - 1);
+            this.view = view;
+            ViewPortPos currentVP = (ViewPortPos)getViewPortStack().peek();
             int xOrigin;
             int yOrigin;
             int width;
@@ -1444,23 +1381,23 @@
             case 90:
                 width = mpts2units(view.getHeight());
                 height = mpts2units(view.getWidth());
-                xOrigin = pageWidth - width - mpts2units(view.getY())
+                xOrigin = currentPageWidth - width - mpts2units(view.getY())
                         - currentVP.y;
                 yOrigin = mpts2units(view.getX()) + currentVP.x;
                 break;
             case 180:
                 width = mpts2units(view.getWidth());
                 height = mpts2units(view.getHeight());
-                xOrigin = pageWidth - width - mpts2units(view.getX())
+                xOrigin = currentPageWidth - width - mpts2units(view.getX())
                         - currentVP.x;
-                yOrigin = pageHeight - height - mpts2units(view.getY())
+                yOrigin = currentPageHeight - height - mpts2units(view.getY())
                         - currentVP.y;
                 break;
             case 270:
                 width = mpts2units(view.getHeight());
                 height = mpts2units(view.getWidth());
                 xOrigin = mpts2units(view.getY()) + currentVP.y;
-                yOrigin = pageHeight - height - mpts2units(view.getX())
+                yOrigin = currentPageHeight - height - mpts2units(view.getX())
                         - currentVP.x;
                 break;
             default:
@@ -1501,14 +1438,14 @@
                 break;
             case 90:
                 this.x = yOrigin;
-                this.y = pageWidth - width - xOrigin;
+                this.y = currentPageWidth - width - xOrigin;
                 break;
             case 180:
-                this.x = pageWidth - width - xOrigin;
-                this.y = pageHeight - height - yOrigin;
+                this.x = currentPageWidth - width - xOrigin;
+                this.y = currentPageHeight - height - yOrigin;
                 break;
             case 270:
-                this.x = pageHeight - height - yOrigin;
+                this.x = currentPageHeight - height - yOrigin;
                 this.y = xOrigin;
                 break;
             default:
@@ -1518,23 +1455,6 @@
         public String toString() {
             return "x:" + x + " y:" + y + " rot:" + rot;
         }
-
-    }
-
-    private List viewPortPositions = new ArrayList();
-
-    private void pushViewPortPos(ViewPortPos vpp) {
-        viewPortPositions.add(vpp);
-        afpDataStream.setOffsets(vpp.x, vpp.y, vpp.rot);
-    }
-
-    private void popViewPortPos() {
-        viewPortPositions.remove(viewPortPositions.size() - 1);
-        if (viewPortPositions.size() > 0) {
-            ViewPortPos vpp = (ViewPortPos) viewPortPositions
-                    .get(viewPortPositions.size() - 1);
-            afpDataStream.setOffsets(vpp.x, vpp.y, vpp.rot);
-        }
     }
 
     /**
@@ -1573,6 +1493,9 @@
      * @return the AFPDataStream
      */
     public AFPDataStream getAFPDataStream() {
+        if (afpDataStream == null) {
+            this.afpDataStream = new AFPDataStream();
+        }
         return afpDataStream;
     }
 
@@ -1603,4 +1526,20 @@
     public int getResolution() {
         return this.resolution;
     }
+
+    private boolean gocaEnabled = false;
+
+    /**
+     * @param enabled true if AFP GOCA is enabled for SVG support
+     */
+    protected void setGOCAEnabled(boolean enabled) {
+        this.gocaEnabled = enabled;
+    }
+
+    /**
+     * @return true of AFP GOCA is enabled for SVG support
+     */
+    protected boolean isGOCAEnabled() {
+        return this.gocaEnabled;
+    }
 }
diff --git a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
index 9917eec..5a68768 100644
--- a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
+++ b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
@@ -242,6 +242,11 @@
                 afpRenderer.setResolution(rendererResolutionCfg.getValueAsInteger(
                         AFPRenderer.DPI_240_RESOLUTION));
             }
+
+            Configuration gocaSupportCfg = cfg.getChild("goca-enabled", false);
+            if (gocaSupportCfg != null) {
+                afpRenderer.setGOCAEnabled(true);
+            }
         }
     }
 }
diff --git a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java
index 13fa625..bc09ed5 100644
--- a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java
+++ b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java
@@ -158,7 +158,12 @@
     
     /** {@inheritDoc} */
     public boolean supportsRenderer(Renderer renderer) {
-        return (renderer instanceof AFPRenderer);
+        //return (renderer instanceof AFPRenderer);
+        if (renderer instanceof AFPRenderer) {
+            AFPRenderer afpRenderer = (AFPRenderer)renderer;
+            return afpRenderer.isGOCAEnabled();
+        }
+        return false;
     }
     
     /** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/afp/AFPState.java b/src/java/org/apache/fop/render/afp/AFPState.java
index 7cb37e2..0dabead 100644
--- a/src/java/org/apache/fop/render/afp/AFPState.java
+++ b/src/java/org/apache/fop/render/afp/AFPState.java
@@ -19,66 +19,14 @@
 
 package org.apache.fop.render.afp;
 
-import java.awt.Color;
-import java.util.Arrays;
-
 /**
- * This keeps information about the current state when writing to pdf.
+ * This keeps information about the current state when writing to an AFP datastream.
  */
-public class AFPState {
-    /**
-     * The current color
-     */
-    private Color color = null;
+public class AFPState extends org.apache.fop.render.AbstractState {
 
-    /**
-     * The current background color
-     */
-    private Color backColor = null;
-
-    /**
-     * The current font name
-     */
-    private String fontName = null;
-
-    /**
-     * The current font size
-     */
-    private int fontSize = 0;
-
-    /**
-     * The current line width
-     */
-    private float lineWidth = 0;
-
-    /**
-     * The dash array for the current basic stroke (line type)
-     */
-    private float[] dashArray = null;
-
-    /**
-     * The current fill status
-     */
-    private boolean filled = false;
-    
-    /**
-     * The fonts on the current page
-     */
-    private AFPPageFonts pageFonts = null;
-
-    /**
-     * Set the current color.
-     * Check if the new color is a change and then set the current color.
-     *
-     * @param col the color to set
-     * @return true if the color has changed
-     */
-    protected boolean setColor(Color col) {
-        if (!col.equals(this.color)) {
-            this.color = col;
-            return true;
-        }
-        return false;
+    /** {@inheritDoc} */
+    protected AbstractData instantiateData() {
+        return new AFPData();
     }
 
     /**
@@ -87,123 +35,8 @@
      * @return true if the fill value has changed
      */
     protected boolean setFill(boolean fill) {
-        if (fill != this.filled) {
-            this.filled = fill;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Get the color.
-     * @return the color
-     */
-    protected Color getColor() {
-        if (this.color == null) {
-            this.color = Color.black;
-        }
-        return this.color;
-    }
-
-    /**
-     * Set the current line width.
-     * @param width the line width in points
-     * @return true if the line width has changed
-     */
-    protected boolean setLineWidth(float width) {
-        if (this.lineWidth != width) {
-            this.lineWidth = width;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Sets the dash array (line type) for the current basic stroke
-     * @param dash the line dash array
-     * @return true if the dash array has changed
-     */
-    public boolean setDashArray(float[] dash) {
-        if (!Arrays.equals(dash, this.dashArray)) {
-            this.dashArray = dash;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Gets the current line width
-     * @return the current line width
-     */
-    protected float getLineWidth() {
-        return lineWidth;
-    }
-
-    /**
-     * Get the background color.
-     * @return the background color
-     */
-    protected Color getBackColor() {
-        if (this.backColor == null) {
-            this.backColor = Color.white;
-        }
-        return backColor;
-    }
-
-    /**
-     * Set the current background color.
-     * Check if the new background color is a change and then set the current background color.
-     *
-     * @param col the background color to set
-     * @return true if the color has changed
-     */
-    protected boolean setBackColor(Color col) {
-        if (!col.equals(this.backColor)) {
-            this.backColor = col;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Set the current font name
-     * @param internalFontName the internal font name
-     * @return true if the font name has changed
-     */
-    protected boolean setFontName(String internalFontName) {
-        if (!internalFontName.equals(this.fontName)) {
-            this.fontName = internalFontName;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Gets the current font name
-     * @return the current font name
-     */
-    protected String getFontName() {
-        return this.fontName;
-    }
-    
-    /**
-     * Gets the current font size
-     * @return the current font size
-     */
-    protected int getFontSize() {
-        return this.fontSize;
-    }
-
-    /**
-     * Set the current font size.
-     * Check if the font size is a change and then set the current font size.
-     *
-     * @param size the font size to set
-     * @return true if the font size has changed
-     */
-    protected boolean setFontSize(int size) {
-        if (size != this.fontSize) {
-            this.fontSize = size;
+        if (fill != ((AFPData)getData()).filled) {
+            ((AFPData)getData()).filled = fill;
             return true;
         }
         return false;
@@ -214,25 +47,27 @@
      * @return the current page fonts
      */
     protected AFPPageFonts getPageFonts() {
-        if (this.pageFonts == null) {
-            this.pageFonts = new AFPPageFonts();
+        if (((AFPData)getData()).pageFonts == null) {
+            ((AFPData)getData()).pageFonts = new AFPPageFonts();
         }
-        return this.pageFonts;
+        return ((AFPData)getData()).pageFonts;
     }
+    
+    private class AFPData extends org.apache.fop.render.AbstractState.AbstractData {
+        private static final long serialVersionUID = -1789481244175275686L;
 
-    /**
-     * Resets the current state
-     */    
-    protected void reset() {
-        this.color = null;
-        this.backColor = null;
-        this.fontName = null;         
-        this.fontSize = 0;         
-        this.lineWidth = 0;
-        this.dashArray = null;
-        this.filled = false;
-        if (this.pageFonts != null) {
-            this.pageFonts.clear();
+        /** The current fill status */
+        private boolean filled = false;
+        
+        /** The fonts on the current page */
+        private AFPPageFonts pageFonts = null;
+
+        /** {@inheritDoc} */
+        public Object clone() throws CloneNotSupportedException {
+            AFPData obj = (AFPData)super.clone();
+            obj.filled = this.filled;
+            obj.pageFonts = this.pageFonts;
+            return obj;
         }
     }
 }
\ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java b/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java
index 30a78d6..3011fc7 100644
--- a/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java
+++ b/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java
@@ -54,7 +54,7 @@
     private static final int MAX_SIZE = 8192;
 
     /**
-     * The afp data relating to this presentaion text data.
+     * The afp data relating to this presentation text data.
      */
     private ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
 
@@ -68,6 +68,7 @@
      */
     private int currentYCoordinate = -1;
 
+    // TODO: move all these 'current' member variables into a higher level state class
     /**
      * The current font
      */
@@ -97,9 +98,7 @@
      * Default constructor for the PresentationTextData.
      */
     public PresentationTextData() {
-
         this(false);
-
     }
 
     /**
@@ -111,7 +110,6 @@
      *            The control sequence indicator.
      */
     public PresentationTextData(boolean controlInd) {
-
         baos.write(new byte[] {0x5A, // Structured field identifier
             0x00, // Record length byte 1
             0x00, // Record length byte 2
@@ -126,7 +124,6 @@
         if (controlInd) {
             baos.write(new byte[] {0x2B, (byte) 0xD3}, 0, 2);
         }
-
     }
 
     /**
@@ -140,7 +137,6 @@
      *            The output stream to which data should be written.
      */
     private void setCodedFont(byte font, ByteArrayOutputStream afpdata) {
-
         // Avoid unnecessary specification of the font
         if (String.valueOf(font).equals(currentFont)) {
             return;
@@ -149,7 +145,6 @@
         }
 
         afpdata.write(new byte[] {0x03, (byte) 0xF1, font}, 0, 3);
-
     }
 
     /**
@@ -162,15 +157,13 @@
      * @param afpdata
      *            The output stream to which data should be written.
      */
-    private void absoluteMoveInline(int coordinate,
-        ByteArrayOutputStream afpdata) {
+    private void absoluteMoveInline(int coordinate, ByteArrayOutputStream afpdata) {
 
         byte[] b = BinaryUtils.convert(coordinate, 2);
 
         afpdata.write(new byte[] {0x04, (byte) 0xC7, b[0], b[1]}, 0, 4);
 
         currentXCoordinate = coordinate;
-
     }
 
     /**
@@ -183,15 +176,10 @@
      * @param afpdata
      *            The output stream to which data should be written.
      */
-    private void absoluteMoveBaseline(int coordinate,
-        ByteArrayOutputStream afpdata) {
-
+    private void absoluteMoveBaseline(int coordinate, ByteArrayOutputStream afpdata) {
         byte[] b = BinaryUtils.convert(coordinate, 2);
-
         afpdata.write(new byte[] {0x04, (byte) 0xD3, b[0], b[1]}, 0, 4);
-
         currentYCoordinate = coordinate;
-
     }
 
     /**
@@ -204,7 +192,6 @@
      *            The output stream to which data should be written.
      */
     private void addTransparentData(byte[] data, ByteArrayOutputStream afpdata) {
-
         // Calculate the length
         int l = data.length + 2;
 
@@ -213,12 +200,8 @@
             throw new IllegalArgumentException(
                 "Transparent data is longer than 253 bytes: " + data);
         }
-
-        afpdata.write(new byte[] {BinaryUtils.convert(l)[0], (byte) 0xDB},
-            0, 2);
-
+        afpdata.write(new byte[] {BinaryUtils.convert(l)[0], (byte) 0xDB}, 0, 2);
         afpdata.write(data, 0, data.length);
-
     }
 
     /**
@@ -233,8 +216,7 @@
      * @param afpdata
      *            The output stream to which data should be written.
      */
-    private void drawBaxisRule(int length, int width,
-        ByteArrayOutputStream afpdata) {
+    private void drawBaxisRule(int length, int width, ByteArrayOutputStream afpdata) {
 
         afpdata.write(new byte[] {0x07, // Length
             (byte) 0xE7, // Type
@@ -248,7 +230,6 @@
         afpdata.write(data2, 0, data2.length);
         // Rule width fraction
         afpdata.write(0x00);
-
     }
 
     /**
@@ -263,8 +244,7 @@
      * @param afpdata
      *            The output stream to which data should be written.
      */
-    private void drawIaxisRule(int length, int width,
-        ByteArrayOutputStream afpdata) {
+    private void drawIaxisRule(int length, int width, ByteArrayOutputStream afpdata) {
 
         afpdata.write(new byte[] {0x07, // Length
             (byte) 0xE5, // Type
@@ -278,7 +258,6 @@
         afpdata.write(data2, 0, data2.length);
         // Rule width fraction
         afpdata.write(0x00);
-
     }
 
     /**
@@ -358,7 +337,6 @@
 
         byte[] outputdata = afpdata.toByteArray();
         baos.write(outputdata, 0, outputdata.length);
-
     }
 
     /**
@@ -424,7 +402,6 @@
 
         byte[] outputdata = afpdata.toByteArray();
         baos.write(outputdata, 0, outputdata.length);
-
     }
 
     /**
@@ -441,8 +418,7 @@
      * @param afpdata
      *            The output stream to which data should be written.
      */
-    private void setTextOrientation(int orientation,
-        ByteArrayOutputStream afpdata) {
+    private void setTextOrientation(int orientation, ByteArrayOutputStream afpdata) {
 
         afpdata.write(new byte[] {0x06, (byte) 0xF7}, 0, 2);
 
@@ -472,7 +448,6 @@
                 afpdata.write(0x00);
                 break;
         }
-
     }
 
     /**
@@ -486,9 +461,7 @@
      * @param afpdata
      *            The output stream to which data should be written.
      */
-    private void setExtendedTextColor(Color col,
-        ByteArrayOutputStream afpdata) {
-
+    private void setExtendedTextColor(Color col, ByteArrayOutputStream afpdata) {
         afpdata.write(new byte[] {
               15                // Control sequence length
             , (byte)0x81        // Control sequence function type
@@ -506,7 +479,6 @@
             , (byte)(col.getGreen()) // Green intensity
             , (byte)(col.getBlue())  // Blue intensity
         }, 0, 15);
-
     }
 
     /**
@@ -529,7 +501,6 @@
             , b[0]
             , b[1]
         }, 0, 4);
-
     }
 
     /**
@@ -553,7 +524,6 @@
             , b[1]
             , (byte)(incr >= 0 ? 0 : 1) // Direction
         }, 0, 5);
-
     }
 
     /**
@@ -570,7 +540,6 @@
         data[2] = size[1];
 
         os.write(data);
-
     }
 
     /**
@@ -583,7 +552,6 @@
      * @throws MaximumSizeExceededException if the maximum size is exceeded
      */
     public void endControlSequence() throws MaximumSizeExceededException {
-
         byte[] data = new byte[2];
         data[0] = 0x02;
         data[1] = (byte) 0xF8;
@@ -593,5 +561,4 @@
         }
         baos.write(data, 0, data.length);
     }
-
 }
\ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java b/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java
index 901f24b..c2cb164 100644
--- a/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java
+++ b/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java
@@ -119,23 +119,16 @@
      */
     public void createTextData(int fontReference, int x, int y, int orientation,
         Color col, int vsci, int ica, byte[] data) {
-
         if (currentPresentationTextData == null) {
             startPresentationTextData();
         }
-
         try {
-
             currentPresentationTextData.createTextData(fontReference, x, y,
                 orientation, col, vsci, ica, data);
-
         } catch (MaximumSizeExceededException msee) {
-
             endPresentationTextData();
             createTextData(fontReference, x, y, orientation, col, vsci, ica, data);
-
         }
-
     }
 
     /**
diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java
index 5b7dd84..c96ee76 100644
--- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java
+++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java
@@ -110,6 +110,7 @@
 import org.apache.fop.pdf.PDFXMode;
 import org.apache.fop.pdf.PDFXObject;
 import org.apache.fop.render.AbstractPathOrientedRenderer;
+import org.apache.fop.render.AbstractState;
 import org.apache.fop.render.Graphics2DAdapter;
 import org.apache.fop.render.RendererContext;
 import org.apache.fop.util.CharUtilities;
@@ -839,7 +840,7 @@
             currentStream.add(CTMHelper.toPDFString(at, false) + " cm\n");
         }
     }
-    
+
     /**
      * Handle the traits for a region
      * This is used to draw the traits for the given page region.
@@ -1112,7 +1113,7 @@
      */
     protected List breakOutOfStateStack() {
         List breakOutList = new java.util.ArrayList();
-        PDFState.Data data;
+        AbstractState.AbstractData data;
         while (true) {
             data = currentState.getData();
             if (currentState.pop() == null) {
@@ -1133,10 +1134,10 @@
      */
     protected void restoreStateStackAfterBreakOut(List breakOutList) {
         comment("------ restoring context after break-out...");
-        PDFState.Data data;
+        AbstractState.AbstractData data;
         Iterator i = breakOutList.iterator();
         while (i.hasNext()) {
-            data = (PDFState.Data)i.next();
+            data = (AbstractState.AbstractData)i.next();
             saveGraphicsState();
             AffineTransform at = data.getTransform();
             concatenateTransformationMatrix(at);
diff --git a/src/java/org/apache/fop/traits/BorderProps.java b/src/java/org/apache/fop/traits/BorderProps.java
index d00bdb0..f4f0d21 100644
--- a/src/java/org/apache/fop/traits/BorderProps.java
+++ b/src/java/org/apache/fop/traits/BorderProps.java
@@ -30,7 +30,7 @@
 
 /**
  * Border properties.
- * Class to store border trait propties for the area tree.
+ * Class to store border trait properties for the area tree.
  */
 public class BorderProps implements Serializable {