You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by ac...@apache.org on 2008/07/10 12:59:41 UTC

svn commit: r675507 [2/3] - in /xmlgraphics/fop/branches/Temp_AFPGOCAResources: ./ src/java/org/apache/fop/pdf/ src/java/org/apache/fop/render/ src/java/org/apache/fop/render/afp/ src/java/org/apache/fop/render/afp/modca/ src/java/org/apache/fop/render...

Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPRenderer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPRenderer.java?rev=675507&r1=675506&r2=675507&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPRenderer.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPRenderer.java Thu Jul 10 03:59:39 2008
@@ -23,7 +23,6 @@
 import java.awt.Point;
 import java.awt.Rectangle;
 import java.awt.geom.AffineTransform;
-import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 import java.awt.image.RenderedImage;
 import java.io.FileNotFoundException;
@@ -50,18 +49,14 @@
 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.BlockViewport;
-import org.apache.fop.area.BodyRegion;
 import org.apache.fop.area.CTM;
 import org.apache.fop.area.LineArea;
-import org.apache.fop.area.NormalFlow;
 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;
@@ -76,6 +71,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;
@@ -87,7 +83,6 @@
 import org.apache.fop.render.afp.fonts.OutlineFont;
 import org.apache.fop.render.afp.modca.AFPConstants;
 import org.apache.fop.render.afp.modca.AFPDataStream;
-import org.apache.fop.render.afp.modca.ImageObject;
 import org.apache.fop.render.afp.modca.PageObject;
 
 /**
@@ -146,15 +141,17 @@
  */
 public class AFPRenderer extends AbstractPathOrientedRenderer {
 
-    /**
-     * The default afp renderer output resolution
-     */
-    public static final int DPI_240_RESOLUTION = 240;
+    private static final int X = 0;
+    
+    private static final int Y = 1;
+    
+    private static final int X1 = 0;
 
-    /**
-     * The afp factor for calculating resolutions (e.g. 72000/240 = 300)
-     */
-    private static final int DPI_CONVERSION_FACTOR = 72000;
+    private static final int Y1 = 1;
+
+    private static final int X2 = 2;
+
+    private static final int Y2 = 3;
 
     /**
      * The afp data stream object responsible for generating afp data
@@ -162,107 +159,19 @@
     private AFPDataStream afpDataStream = null;
 
     /**
-     * The map of afp root extensions
-     */
-    // UNUSED
-    // private HashMap rootExtensionMap = null;
-    /**
      * The map of page segments
      */
     private Map/*<String,String>*/pageSegmentsMap = null;
 
     /**
-     * The fonts on the current page
-     */
-    private Map/*<String,AFPFontAttributes<*/currentPageFontMap = null;
-
-    /**
-     * The current color object
-     */
-    private Color currentColor = null;
-
-    /**
-     * The page font number counter, used to determine the next font reference
-     */
-    private int pageFontCounter = 0;
-
-    /**
-     * The current font family
-     */
-    // UNUSED
-    // private String currentFontFamily = "";
-    /**
-     * The current font size
-     */
-    private int currentFontSize = 0;
-
-    /**
-     * The Options to be set on the AFPRenderer
-     */
-    // UNUSED
-    // private Map afpOptions = null;
-    /**
-     * The page width
-     */
-    private int pageWidth = 0;
-
-    /**
-     * The page height
-     */
-    private int pageHeight = 0;
-
-    /**
-     * The current page sequence id
-     */
-    // UNUSED
-    // private String pageSequenceId = null;
-    /**
-     * The portrait rotation
-     */
-    private int portraitRotation = 0;
-
-    /**
-     * The landscape rotation
-     */
-    private int landscapeRotation = 270;
-
-    /**
-     * The line cache, avoids drawing duplicate lines in tables.
-     */
-    // UNUSED
-    // private HashSet lineCache = null;
-    /**
-     * The current x position for line drawing
-     */
-    // UNUSED
-    // private float x;
-    /**
-     * The current y position for line drawing
-     */
-    // UNUSED
-    // private float y;
-    /**
      * The map of saved incomplete pages
      */
     private Map pages = null;
 
-    /**
-     * Flag to the set the output object type for images
-     */
-    private boolean colorImages = false;
-
-    /**
-     * Default value for image depth
-     */
-    private int bitsPerPixel = 8;
-
-    /**
-     * The output resolution
-     */
-    private int resolution = DPI_240_RESOLUTION;
-
     /** drawing state */
-    private AFPState currentState = null;
+    private AFPState currentState = new AFPState();
+
+    private boolean gocaEnabled = false;
 
     /**
      * Constructor for AFPRenderer.
@@ -271,12 +180,7 @@
         super();
     }
 
-    /**
-     * Set up the font info
-     * 
-     * @param inFontInfo
-     *            font info to set up
-     */
+    /** {@inheritDoc} */
     public void setupFontInfo(FontInfo inFontInfo) {
         this.fontInfo = inFontInfo;
         int num = 1;
@@ -285,8 +189,7 @@
             for (Iterator it = super.embedFontInfoList.iterator(); it.hasNext();) {
                 AFPFontInfo afi = (AFPFontInfo) it.next();
                 AFPFont bf = (AFPFont) afi.getAFPFont();
-                for (Iterator it2 = afi.getFontTriplets().iterator(); it2
-                        .hasNext();) {
+                for (Iterator it2 = afi.getFontTriplets().iterator(); it2.hasNext();) {
                     FontTriplet ft = (FontTriplet) it2.next();
                     this.fontInfo.addFontProperties("F" + num, ft.getName(), ft
                             .getStyle(), ft.getWeight());
@@ -333,482 +236,209 @@
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public void setUserAgent(FOUserAgent agent) {
         super.setUserAgent(agent);
     }
 
-    private Map/*<String,AFPFontAttributes>*/getCurrentPageFonts() {
-        if (currentPageFontMap == null) {
-            this.currentPageFontMap = new java.util.HashMap/*<String,AFPFontAttributes>*/();
-        }
-        return this.currentPageFontMap;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public void startRenderer(OutputStream outputStream) throws IOException {
-        this.currentColor = new Color(255, 255, 255);
-        getAFPDataStream().setPortraitRotation(portraitRotation);
-        getAFPDataStream().setLandscapeRotation(landscapeRotation);
-        getAFPDataStream().setOutputStream(outputStream);
+        currentState.setColor(new Color(255, 255, 255));
+        getAFPDataStream().setPortraitRotation(currentState.getPortraitRotation());
+        afpDataStream.setLandscapeRotation(currentState.getLandscapeRotation());
+        afpDataStream.setOutputStream(outputStream);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public void stopRenderer() throws IOException {
         getAFPDataStream().write();
         afpDataStream = null;
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public void startPageSequence(LineArea seqTitle) {
         getAFPDataStream().endPageGroup();
-        getAFPDataStream().startPageGroup();
+        afpDataStream.startPageGroup();
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public boolean supportsOutOfOrder() {
         // return false;
         return true;
     }
 
-    /**
-     * Prepare a page for rendering. This is called if the renderer supports out
-     * of order rendering. The renderer should prepare the page so that a page
-     * further on in the set of pages can be rendered. The body of the page
-     * should not be rendered. The page will be rendered at a later time by the
-     * call to render page.
-     * 
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public void preparePage(PageViewport page) {
-        // initializeRootExtensions(page);
-
-        // this.currentFontFamily = "";
-        this.currentFontSize = 0;
-        this.pageFontCounter = 0;
-        this.currentPageFontMap = null;
-        // this.lineCache = new HashSet();
-
-        Rectangle2D bounds = page.getViewArea();
-
-        this.pageWidth = mpts2units(bounds.getWidth());
-        this.pageHeight = mpts2units(bounds.getHeight());
-
-        // renderPageGroupExtensions(page);
-
         final int pageRotation = 0;
+        int pageWidth = currentState.getPageWidth();
+        int pageHeight = currentState.getPageHeight();
         getAFPDataStream().startPage(pageWidth, pageHeight, pageRotation,
                 getResolution(), getResolution());
 
         renderPageObjectExtensions(page);
 
+        getPages().put(page, getAFPDataStream().savePage());
+    }
+
+    private Map/*<PageViewport, PageObject>*/ getPages() {
         if (this.pages == null) {
-            this.pages = new java.util.HashMap();
+            this.pages = new java.util.HashMap/*<PageViewport, PageObject>*/();
         }
-        this.pages.put(page, getAFPDataStream().savePage());
-
+        return this.pages;
     }
 
-    /**
-     * {@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();
+        saveGraphicsState();
+        if (ctm != null) {
+            AffineTransform at = ctm.toAffineTransform();
+            concatenateTransformationMatrix(at);
+        }
+        if (clippingRect != null) {
+            clipRect((float)clippingRect.getX() / 1000f, 
+                    (float)clippingRect.getY() / 1000f, 
+                    (float)clippingRect.getWidth() / 1000f, 
+                    (float)clippingRect.getHeight() / 1000f);
         }
     }
 
     /** {@inheritDoc} */
-    protected void renderBlockViewport(BlockViewport bv, List children) {
-        // clip and position viewport if necessary
-
-        // save positions
-        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) {
-
-            // 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();
-            }
-
-            AffineTransform positionTransform = new AffineTransform();
-            positionTransform.translate(bv.getXOffset(), bv.getYOffset());
-
-            // "left/"top" (bv.getX/YOffset()) specify the position of the
-            // content rectangle
-            positionTransform.translate(-borderPaddingStart,
-                    -borderPaddingBefore);
-
-            // skipping fox:transform here
-
-            // saveGraphicsState();
-            // Viewport position
-            // concatenateTransformationMatrix(mptToPt(positionTransform));
-
-            // Background and borders
-            float bpwidth = (borderPaddingStart + bv
-                    .getBorderAndPaddingWidthEnd()) / 1000f;
-            float bpheight = (borderPaddingBefore + bv
-                    .getBorderAndPaddingWidthAfter()) / 1000f;
-            Point2D ptSrc = new Point(0, 0);
-            Point2D ptDst = positionTransform.transform(ptSrc, null);
-            Rectangle2D borderRect = new Rectangle2D.Double(ptDst.getX(), ptDst
-                    .getY(), 1000 * (width + bpwidth),
-                    1000 * (height + bpheight));
-            pushViewPortPos(new ViewPortPos(borderRect, new CTM(
-                    positionTransform)));
-            drawBackAndBorders(bv, 0, 0, width + bpwidth, height + bpheight);
-
-            // Shift to content rectangle after border painting
-            AffineTransform contentRectTransform = new AffineTransform();
-            contentRectTransform.translate(borderPaddingStart,
-                    borderPaddingBefore);
-            // concatenateTransformationMatrix(mptToPt(contentRectTransform));
-            ptSrc = new Point(0, 0);
-            ptDst = contentRectTransform.transform(ptSrc, null);
-            Rectangle2D contentRect = new Rectangle2D.Double(ptDst.getX(),
-                    ptDst.getY(), 1000 * width, 1000 * height);
-            pushViewPortPos(new ViewPortPos(contentRect, new CTM(
-                    contentRectTransform)));
-
-            // Clipping is not supported, yet
-            // Rectangle2D clippingRect = null;
-            // clippingRect = new Rectangle(0, 0, bv.getIPD(), bv.getBPD());
-
-            // saveGraphicsState();
-            // Set up coordinate system for content rectangle
-            AffineTransform contentTransform = ctm.toAffineTransform();
-            // concatenateTransformationMatrix(mptToPt(contentTransform));
-            contentRect = new Rectangle2D.Double(0, 0, 1000 * width,
-                    1000 * height);
-            pushViewPortPos(new ViewPortPos(contentRect, new CTM(
-                    contentTransform)));
-
-            currentIPPosition = 0;
-            currentBPPosition = 0;
-            renderBlocks(bv, children);
-
-            popViewPortPos();
-            popViewPortPos();
-            // restoreGraphicsState();
-            popViewPortPos();
-            // restoreGraphicsState();
-
-            if (breakOutList != null) {
-                restoreStateStackAfterBreakOut(breakOutList);
-            }
-
-            currentIPPosition = saveIP;
-            currentBPPosition = saveBP;
-        } 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());
-        }
+    public void endVParea() {
+        restoreGraphicsState();
     }
 
     /** {@inheritDoc} */
-    protected void renderReferenceArea(Block block) {
-        //TODO Remove this method once concatenateTransformationMatrix() is implemented 
-        
-        // save position and offset
-        int saveIP = currentIPPosition;
-        int saveBP = currentBPPosition;
-
-        //Establish a new coordinate system
-        AffineTransform at = new AffineTransform();
-        at.translate(currentIPPosition, currentBPPosition);
-        at.translate(block.getXOffset(), block.getYOffset());
-        at.translate(0, block.getSpaceBefore());
-        
-        if (!at.isIdentity()) {
-            Rectangle2D contentRect
-                = new Rectangle2D.Double(at.getTranslateX(), at.getTranslateY(),
-                        block.getAllocIPD(), block.getAllocBPD());
-            pushViewPortPos(new ViewPortPos(contentRect, new CTM(at)));
-        }
-
-        currentIPPosition = 0;
-        currentBPPosition = 0;
-        handleBlockTraits(block);
-
-        List children = block.getChildAreas();
-        if (children != null) {
-            renderBlocks(block, children);
-        }
-
+    protected void concatenateTransformationMatrix(AffineTransform at) {
         if (!at.isIdentity()) {
-            popViewPortPos();
+            currentState.concatenate(at);
         }
-        
-        // stacked and relative blocks effect stacking
-        currentIPPosition = saveIP;
-        currentBPPosition = saveBP;
     }
-    
-    /** {@inheritDoc} */
-    protected void renderFlow(NormalFlow flow) {
-        // save position and offset
-        int saveIP = currentIPPosition;
-        int saveBP = currentBPPosition;
-
-        //Establish a new coordinate system
-        AffineTransform at = new AffineTransform();
-        at.translate(currentIPPosition, currentBPPosition);
-        
-        if (!at.isIdentity()) {
-            Rectangle2D contentRect
-                = new Rectangle2D.Double(at.getTranslateX(), at.getTranslateY(),
-                        flow.getAllocIPD(), flow.getAllocBPD());
-            pushViewPortPos(new ViewPortPos(contentRect, new CTM(at)));
-        }
 
-        currentIPPosition = 0;
-        currentBPPosition = 0;
-        super.renderFlow(flow);
-        
-        if (!at.isIdentity()) {
-            popViewPortPos();
-        }
-        
-        // stacked and relative blocks effect stacking
-        currentIPPosition = saveIP;
-        currentBPPosition = saveBP;
-    }
-    
-    
     /** {@inheritDoc} */
-    protected void concatenateTransformationMatrix(AffineTransform at) {
-        // Not used here since AFPRenderer defines its own renderBlockViewport()
-        // method.
-        throw new UnsupportedOperationException("NYI");
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void renderPage(PageViewport pageViewport) {
-
-        // initializeRootExtensions(page);
-
-        // this.currentFontFamily = "";
-        this.currentFontSize = 0;
-        this.pageFontCounter = 0;
-        this.currentPageFontMap = null;
-        // this.lineCache = new HashSet();
+    public void renderPage(PageViewport pageViewport) throws IOException, FOPException {
+        currentState.clear();
 
         Rectangle2D bounds = pageViewport.getViewArea();
+        
+        AffineTransform basicPageTransform = new AffineTransform();
+        int resolution = currentState.getResolution();
+        double scale = (double)1 / (AFPConstants.DPI_72_MPTS / resolution);
+        basicPageTransform.scale(scale, scale);
 
-        this.pageWidth = mpts2units(bounds.getWidth());
-        this.pageHeight = mpts2units(bounds.getHeight());
-
-        if (pages != null && pages.containsKey(pageViewport)) {
+        currentState.concatenate(basicPageTransform);
 
+        if (getPages().containsKey(pageViewport)) {
             getAFPDataStream().restorePage(
-                    (PageObject) pages.remove(pageViewport));
-
+                    (PageObject)getPages().remove(pageViewport));
         } else {
-            // renderPageGroupExtensions(page);
+            int pageWidth
+                = (int)Math.round(bounds.getWidth() / (AFPConstants.DPI_72_MPTS / resolution));
+            currentState.setPageWidth(pageWidth);
+            int pageHeight
+                = (int)Math.round(bounds.getHeight() / (AFPConstants.DPI_72_MPTS / resolution));
+            currentState.setPageHeight(pageHeight);
 
             final int pageRotation = 0;
             getAFPDataStream().startPage(pageWidth, pageHeight, pageRotation,
-                    getResolution(), getResolution());
+                    resolution, resolution);
 
             renderPageObjectExtensions(pageViewport);
-
         }
+        
+        super.renderPage(pageViewport);
 
-        pushViewPortPos(new ViewPortPos());
-
-        renderPageAreas(pageViewport.getPage());
-
-        if (currentPageFontMap != null) {
-            Iterator iter = currentPageFontMap.values().iterator();
-            while (iter.hasNext()) {
-                AFPFontAttributes afpFontAttributes = (AFPFontAttributes) iter
-                        .next();
-
-                getAFPDataStream().createFont(
-                        (byte) afpFontAttributes.getFontReference(),
-                        afpFontAttributes.getFont(),
-                        afpFontAttributes.getPointSize());
-            }
+        AFPPageFonts pageFonts = currentState.getPageFonts();
+        if (pageFonts != null && !pageFonts.isEmpty()) {
+            getAFPDataStream().addFontsToCurrentPage(pageFonts);
         }
 
         getAFPDataStream().endPage();
-
-        popViewPortPos();
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public void clip() {
         // TODO
+        log.debug("NYI clip()");
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     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}
-     */
+    private int[] mpts2units(float[] srcPts, float[] dstPts) {
+        return transformPoints(srcPts, dstPts, true);
+    }
+
+    private int[] pts2units(float[] srcPts, float[] dstPts) {
+        return transformPoints(srcPts, dstPts, false);
+    }
+
+    private int[] mpts2units(float[] srcPts) {
+        return transformPoints(srcPts, null, true);
+    }
+
+    private int[] pts2units(float[] srcPts) {
+        return transformPoints(srcPts, null, false);
+    }
+
+    /** {@inheritDoc} */
     public void fillRect(float x, float y, float width, float height) {
-//        getAFPDataStream().createShading(
-//                pts2units(x), pts2units(y), pts2units(width), pts2units(height),
-//                currentColor);
-        getAFPDataStream().createLine(pts2units(x), pts2units(y),
-                pts2units(x + width), pts2units(y), pts2units(height),
-                currentColor);
+        float[] srcPts = new float[] {x * 1000, y * 1000};
+        float[] dstPts = new float[srcPts.length];
+        int[] coords = mpts2units(srcPts, dstPts);        
+        int resolution = currentState.getResolution();
+        int x2 = Math.round(dstPts[X] + ((width * 1000) / (AFPConstants.DPI_72_MPTS / resolution)));
+        int thickness = Math.round((height * 1000) / (AFPConstants.DPI_72_MPTS / resolution));
+        getAFPDataStream().createLine(
+                coords[X],
+                coords[Y],
+                x2,
+                coords[Y],
+                thickness,
+                currentState.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;
-        float h = y2 - y1;
-        if ((w < 0) || (h < 0)) {
+        float[] srcPts = new float[] {x1 * 1000, y1 * 1000, x2 * 1000, y2 * 1000};
+        float[] dstPts = new float[srcPts.length];
+        int[] coords = mpts2units(srcPts, dstPts);
+
+        float width = dstPts[X2] - dstPts[X1];
+        float height = dstPts[Y2] - dstPts[Y1];
+        if ((width < 0) || (height < 0)) {
             log.error("Negative extent received. Border won't be painted.");
             return;
         }
@@ -816,58 +446,91 @@
         switch (style) {
         case Constants.EN_DOUBLE:
             if (horz) {
-                float h3 = h / 3;
-                float ym1 = y1;
-                float ym2 = ym1 + h3 + h3;
-                getAFPDataStream().createLine(pts2units(x1), pts2units(ym1),
-                        pts2units(x2), pts2units(ym1), pts2units(h3), col);
-                getAFPDataStream().createLine(pts2units(x1), pts2units(ym2),
-                        pts2units(x2), pts2units(ym2), pts2units(h3), col);
+                float h3 = height / 3;
+                float ym2 = dstPts[Y1] + h3 + h3;
+                afpDataStream.createLine(
+                        coords[X1],
+                        coords[Y1],
+                        coords[X2],
+                        coords[Y1],
+                        Math.round(h3),
+                        col);
+                afpDataStream.createLine(
+                        coords[X1],
+                        Math.round(ym2),
+                        coords[X2],
+                        Math.round(ym2),
+                        Math.round(h3),
+                        col);
             } else {
-                float w3 = w / 3;
-                float xm1 = x1;
-                float xm2 = xm1 + w3 + w3;
-                getAFPDataStream().createLine(pts2units(xm1), pts2units(y1),
-                        pts2units(xm1), pts2units(y2), pts2units(w3), col);
-                getAFPDataStream().createLine(pts2units(xm2), pts2units(y1),
-                        pts2units(xm2), pts2units(y2), pts2units(w3), col);
+                float w3 = width / 3;
+                float xm2 = dstPts[X1] + w3 + w3;
+                afpDataStream.createLine(
+                        coords[X1],
+                        coords[Y1],
+                        coords[X1],
+                        coords[Y2],
+                        Math.round(w3),
+                        col);
+                afpDataStream.createLine(
+                        Math.round(xm2),
+                        coords[Y1],
+                        Math.round(xm2),
+                        coords[Y2],
+                        Math.round(w3),
+                        col);
             }
             break;
         case Constants.EN_DASHED:
             if (horz) {
-                float w2 = 2 * h;
-                while (x1 + w2 < x2) {
-                    getAFPDataStream().createLine(pts2units(x1), pts2units(y1),
-                            pts2units(x1 + w2), pts2units(y1), pts2units(h),
+                float w2 = 2 * height;
+                while (coords[X1] + w2 < coords[X2]) {
+                    afpDataStream.createLine(
+                            coords[X1],
+                            coords[Y1],
+                            coords[X1] + Math.round(w2),
+                            coords[Y1],
+                            Math.round(height),
                             col);
-                    x1 += 2 * w2;
+                    coords[X1] += 2 * w2;
                 }
             } else {
-                float h2 = 2 * w;
-                while (y1 + h2 < y2) {
-                    getAFPDataStream().createLine(pts2units(x1), pts2units(y1),
-                            pts2units(x1), pts2units(y1 + h2), pts2units(w),
+                float h2 = 2 * width;
+                while (coords[Y1] + h2 < coords[Y2]) {
+                    afpDataStream.createLine(
+                            coords[X1],
+                            coords[Y2],
+                            coords[X1],
+                            coords[Y1] + Math.round(h2),
+                            Math.round(width),
                             col);
-                    y1 += 2 * h2;
+                    coords[Y1] += 2 * h2;
                 }
             }
             break;
         case Constants.EN_DOTTED:
             if (horz) {
-                while (x1 + h < x2) {
-                    getAFPDataStream()
-                            .createLine(pts2units(x1), pts2units(y1),
-                                    pts2units(x1 + h), pts2units(y1),
-                                    pts2units(h), col);
-                    x1 += 2 * h;
+                while (coords[X1] + height < coords[X2]) {
+                    afpDataStream.createLine(
+                            coords[X1],
+                            coords[Y1],
+                            coords[X1] + Math.round(height),
+                            coords[Y1],
+                            Math.round(height),
+                            col
+                    );
+                    coords[X1] += 2 * height;
                 }
             } else {
-                while (y1 + w < y2) {
-                    getAFPDataStream()
-                            .createLine(pts2units(x1), pts2units(y1),
-                                    pts2units(x1), pts2units(y1 + w),
-                                    pts2units(w), col);
-                    y1 += 2 * w;
+                while (y1 + width < y2) {
+                    afpDataStream.createLine(
+                            coords[X1],
+                            coords[Y1],
+                            coords[X1],
+                            coords[Y1] + Math.round(width),
+                            Math.round(width),
+                            col);
+                    coords[Y1] += 2 * width;
                 }
             }
             break;
@@ -877,29 +540,54 @@
             if (horz) {
                 Color uppercol = lightenColor(col, -colFactor);
                 Color lowercol = lightenColor(col, colFactor);
-                float h3 = h / 3;
-                float ym1 = y1;
-                getAFPDataStream().createLine(pts2units(x1), pts2units(ym1),
-                        pts2units(x2), pts2units(ym1), pts2units(h3), uppercol);
-                getAFPDataStream().createLine(pts2units(x1),
-                        pts2units(ym1 + h3), pts2units(x2),
-                        pts2units(ym1 + h3), pts2units(h3), col);
-                getAFPDataStream().createLine(pts2units(x1),
-                        pts2units(ym1 + h3 + h3), pts2units(x2),
-                        pts2units(ym1 + h3 + h3), pts2units(h3), lowercol);
+                float h3 = height / 3;
+                afpDataStream.createLine(
+                        coords[X1],
+                        coords[Y1],
+                        coords[X2],
+                        coords[Y1],
+                        Math.round(h3),
+                        uppercol);
+                afpDataStream.createLine(
+                        coords[X1],
+                        Math.round(dstPts[Y1] + h3),
+                        coords[X2],
+                        Math.round(dstPts[Y1] + h3),
+                        Math.round(h3),
+                        col);
+                afpDataStream.createLine(
+                        coords[X1],
+                        Math.round(dstPts[Y1] + h3 + h3),
+                        coords[X2],
+                        Math.round(dstPts[Y1] + h3 + h3),
+                        Math.round(h3),
+                        lowercol);
             } else {
                 Color leftcol = lightenColor(col, -colFactor);
                 Color rightcol = lightenColor(col, colFactor);
-                float w3 = w / 3;
-                float xm1 = x1 + (w3 / 2);
-                getAFPDataStream().createLine(pts2units(xm1), pts2units(y1),
-                        pts2units(xm1), pts2units(y2), pts2units(w3), leftcol);
-                getAFPDataStream().createLine(pts2units(xm1 + w3),
-                        pts2units(y1), pts2units(xm1 + w3), pts2units(y2),
-                        pts2units(w3), col);
-                getAFPDataStream().createLine(pts2units(xm1 + w3 + w3),
-                        pts2units(y1), pts2units(xm1 + w3 + w3), pts2units(y2),
-                        pts2units(w3), rightcol);
+                float w3 = width / 3;
+                float xm1 = dstPts[X1] + (w3 / 2);
+                afpDataStream.createLine(
+                        Math.round(xm1),
+                        coords[Y1],
+                        Math.round(xm1),
+                        coords[Y2],
+                        Math.round(w3),
+                        leftcol);
+                afpDataStream.createLine(
+                        Math.round(xm1 + w3), 
+                        coords[Y1],
+                        Math.round(xm1 + w3),
+                        coords[Y2],
+                        Math.round(w3),
+                        col);
+                afpDataStream.createLine(
+                        Math.round(xm1 + w3 + w3),
+                        coords[Y1],
+                        Math.round(xm1 + w3 + w3),
+                        coords[Y2],
+                        Math.round(w3),
+                        rightcol);
             }
             break;
         }
@@ -908,28 +596,24 @@
         case Constants.EN_INSET:
         case Constants.EN_OUTSET:
         default:
-            getAFPDataStream().createLine(pts2units(x1), pts2units(y1),
-                    pts2units(horz ? x2 : x1), pts2units(horz ? y1 : y2),
-                    pts2units(Math.abs(horz ? (y2 - y1) : (x2 - x1))), col);
+              afpDataStream.createLine(
+                      coords[X1],
+                      coords[Y1],
+                      (horz ? coords[X2] : coords[X1]),
+                      (horz ? coords[Y1] : coords[Y2]),
+                      Math.abs(Math.round(horz ? height : width)),
+                      col);
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     protected RendererContext createRendererContext(int x, int y, int width,
             int height, Map foreignAttributes) {
         RendererContext context;
         context = super.createRendererContext(x, y, width, height,
                 foreignAttributes);
-        context.setProperty(AFPRendererContextConstants.AFP_GRAYSCALE, Boolean
-                .valueOf(!this.colorImages));
         context.setProperty(AFPRendererContextConstants.AFP_FONT_INFO,
                 this.fontInfo);
-        context.setProperty(AFPRendererContextConstants.AFP_RESOLUTION,
-                new Integer(this.resolution));
-        context.setProperty(AFPRendererContextConstants.AFP_BITS_PER_PIXEL,
-                new Integer(this.bitsPerPixel));
         context.setProperty(AFPRendererContextConstants.AFP_DATASTREAM,
                 getAFPDataStream());
         context.setProperty(AFPRendererContextConstants.AFP_STATE, getState());
@@ -944,17 +628,18 @@
     /** {@inheritDoc} */
     public void drawImage(String uri, Rectangle2D pos, Map foreignAttributes) {
         uri = URISpecification.getURL(uri);
-        getState().setImageUri(uri);
+        currentState.setImageUri(uri);
         Rectangle posInt = new Rectangle((int) pos.getX(), (int) pos.getY(),
                 (int) pos.getWidth(), (int) pos.getHeight());
         Point origin = new Point(currentIPPosition, currentBPPosition);
         int x = origin.x + posInt.x;
         int y = origin.y + posInt.y;
-
+        
         String name = (String)getPageSegments().get(uri);
         if (name != null) {
-            getAFPDataStream().createIncludePageSegment(name, mpts2units(x),
-                    mpts2units(y));
+            float[] srcPts = {x, y};
+            int[] coords = mpts2units(srcPts);
+            getAFPDataStream().createIncludePageSegment(name, coords[X], coords[Y]);
         } else {
             ImageManager manager = getUserAgent().getFactory().getImageManager();
             ImageInfo info = null;
@@ -989,31 +674,41 @@
                     ImageRawCCITTFax ccitt = (ImageRawCCITTFax) img;
                     in = ccitt.createInputStream();
                     byte[] buf = IOUtils.toByteArray(in);
-                    int afpx = mpts2units(posInt.x + currentIPPosition);
-                    int afpy = mpts2units(posInt.y + currentBPPosition);
-                    int afpw = mpts2units(posInt.getWidth());
-                    int afph = mpts2units(posInt.getHeight());
-                    int afpres = getResolution();
+                    float[] srcPts = new float[] {
+                            posInt.x + currentIPPosition,
+                            posInt.y + currentBPPosition,
+                            (float)posInt.getWidth(),
+                            (float)posInt.getHeight()
+                    };
+                    int[] coords = mpts2units(srcPts);
                     String mimeType = info.getMimeType();
                     // create image object parameters
                     ImageObjectInfo imageObjectInfo = new ImageObjectInfo();
+                    imageObjectInfo.setBuffered(false);
                     imageObjectInfo.setUri(uri);
                     imageObjectInfo.setMimeType(mimeType);
                     
                     ObjectAreaInfo objectAreaInfo = new ObjectAreaInfo();
-                    objectAreaInfo.setX(afpx);
-                    objectAreaInfo.setY(afpy);
-                    objectAreaInfo.setWidth(afpw);
-                    objectAreaInfo.setHeight(afph);
-                    objectAreaInfo.setWidthRes(afpres);
-                    objectAreaInfo.setHeightRes(afpres);
+                    objectAreaInfo.setX(coords[X]);
+                    objectAreaInfo.setY(coords[Y]);
+                    int resolution = currentState.getResolution();
+                    int w = Math.round(
+                            ((float)posInt.getWidth() * 1000)
+                            / (AFPConstants.DPI_72_MPTS / resolution));
+                    int h = Math.round(
+                            ((float)posInt.getHeight() * 1000)
+                            / (AFPConstants.DPI_72_MPTS / resolution));
+                    objectAreaInfo.setWidth(w);
+                    objectAreaInfo.setHeight(h);
+                    objectAreaInfo.setWidthRes(resolution);
+                    objectAreaInfo.setHeightRes(resolution);
                     imageObjectInfo.setObjectAreaInfo(objectAreaInfo);
                     
                     imageObjectInfo.setData(buf);
                     imageObjectInfo.setDataHeight(ccitt.getSize().getHeightPx());
                     imageObjectInfo.setDataWidth(ccitt.getSize().getWidthPx());
-                    imageObjectInfo.setColor(colorImages);
-                    imageObjectInfo.setBitsPerPixel(bitsPerPixel);
+                    imageObjectInfo.setColor(currentState.isColorImages());
+                    imageObjectInfo.setBitsPerPixel(currentState.getBitsPerPixel());
                     imageObjectInfo.setCompression(ccitt.getCompression());
                     imageObjectInfo.setResourceInfoFromForeignAttributes(foreignAttributes);
                     getAFPDataStream().createObject(imageObjectInfo);
@@ -1079,15 +774,15 @@
      *            the x coordinate (in mpt)
      * @param y
      *            the y coordinate (in mpt)
-     * @param w
+     * @param width
      *            the width of the viewport (in mpt)
-     * @param h
+     * @param height
      *            the height of the viewport (in mpt)
      * @param foreignAttributes
      *            a mapping of foreign attributes
      */
     public void drawBufferedImage(ImageInfo imageInfo, RenderedImage image,
-            int imageRes, int x, int y, int w, int h, Map foreignAttributes) {
+            int imageRes, int x, int y, int width, int height, Map foreignAttributes) {
         ByteArrayOutputStream baout = new ByteArrayOutputStream();
         try {
             // Serialize image
@@ -1111,129 +806,127 @@
         }
 
         ObjectAreaInfo objectAreaInfo = new ObjectAreaInfo();
-        objectAreaInfo.setX(mpts2units(x));
-        objectAreaInfo.setY(mpts2units(y));
-        objectAreaInfo.setWidth(mpts2units(w));
-        objectAreaInfo.setHeight(mpts2units(h));
+
+        float[] srcPts = new float[] {x, y};
+        int[] coords = mpts2units(srcPts);
+        objectAreaInfo.setX(coords[X]);
+        objectAreaInfo.setY(coords[Y]);
+        int resolution = currentState.getResolution();
+        int w = Math.round(
+                (width * 1000)
+                / (AFPConstants.DPI_72_MPTS / resolution));
+        int h = Math.round(
+                (height * 1000)
+                / (AFPConstants.DPI_72_MPTS / resolution));
+        objectAreaInfo.setWidth(w);
+        objectAreaInfo.setHeight(h);
+        
         objectAreaInfo.setWidthRes(imageRes);
         objectAreaInfo.setHeightRes(imageRes);
         imageObjectInfo.setObjectAreaInfo(objectAreaInfo);
-        
+
         imageObjectInfo.setData(baout.toByteArray());
         imageObjectInfo.setDataHeight(image.getHeight());
         imageObjectInfo.setDataWidth(image.getWidth());
-        imageObjectInfo.setColor(colorImages);
-        imageObjectInfo.setBitsPerPixel(bitsPerPixel);
+        imageObjectInfo.setColor(currentState.isColorImages());
+        imageObjectInfo.setBitsPerPixel(currentState.getBitsPerPixel());
         imageObjectInfo.setResourceInfoFromForeignAttributes(foreignAttributes);
         getAFPDataStream().createObject(imageObjectInfo);
     }
 
-    /**
-     * Establishes a new foreground or fill color. {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public void updateColor(Color col, boolean fill) {
         if (fill) {
-            currentColor = col;
+            currentState.setColor(col);
         }
     }
 
     /** {@inheritDoc} */
-    public List breakOutOfStateStack() {
-        log.debug("Block.FIXED --> break out");
-        List breakOutList = new java.util.ArrayList();
-        //Don't pop the last ViewPortPos (created by renderPage())
-        while (this.viewPortPositions.size() > 1) {
-            breakOutList.add(0, popViewPortPos());
+    public void restoreStateStackAfterBreakOut(List breakOutList) {
+        log.debug("Block.FIXED --> restoring context after break-out");
+        AbstractState.AbstractData data;
+        Iterator it = breakOutList.iterator();
+        while (it.hasNext()) {
+            data = (AbstractState.AbstractData)it.next();
+            saveGraphicsState();
+            concatenateTransformationMatrix(data.getTransform());
         }
-        return breakOutList;
     }
 
     /** {@inheritDoc} */
-    public void restoreStateStackAfterBreakOut(List breakOutList) {
-        log.debug("Block.FIXED --> restoring context after break-out");
-        for (int i = 0, c = breakOutList.size(); i < c; i++) {
-            ViewPortPos vps = (ViewPortPos)breakOutList.get(i);
-            pushViewPortPos(vps);
+    protected List breakOutOfStateStack() {
+        log.debug("Block.FIXED --> break out");
+        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() {
-
+        currentState.push();
     }
 
-    /** Restores the last graphics state of the rendering engine. */
+    /** {@inheritDoc} */
     public void restoreGraphicsState() {
-
+        currentState.pop();
     }
 
     /** Indicates the beginning of a text object. */
     public void beginTextObject() {
-
+        //TODO maybe?
+        log.debug("NYI beginTextObject()");
     }
 
     /** Indicates the end of a text object. */
     public void endTextObject() {
-
+        //TODO maybe?
+        log.debug("NYI endTextObject()");
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public void renderImage(Image image, Rectangle2D pos) {
         drawImage(image.getURL(), pos, image.getForeignAttributes());
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public void renderText(TextArea text) {
+    /** {@inheritDoc} */
+    public void renderText(TextArea text) { 
+        log.debug(text.getText());
         renderInlineAreaBackAndBorders(text);
 
         String name = getInternalFontNameForArea(text);
-        this.currentFontSize = ((Integer) text.getTrait(Trait.FONT_SIZE))
-                .intValue();
-        AFPFont font = (AFPFont) fontInfo.getFonts().get(name);
-
-        Color col = (Color) text.getTrait(Trait.COLOR);
-
-        int vsci = 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 fontSize = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue();
+        currentState.setFontSize(fontSize);
+        AFPFont font = (AFPFont)fontInfo.getFonts().get(name);
 
         // Set letterSpacing
         // float ls = fs.getLetterSpacing() / this.currentFontSize;
 
-        String worddata = text.getText();
-
         // Create an AFPFontAttributes object from the current font details
-        AFPFontAttributes afpFontAttributes = new AFPFontAttributes(name, font,
-                currentFontSize);
+        AFPFontAttributes afpFontAttributes
+            = new AFPFontAttributes(name, font, fontSize);
 
-        if (!getCurrentPageFonts().containsKey(afpFontAttributes.getFontKey())) {
+        AFPPageFonts pageFonts = currentState.getPageFonts();
+        if (!pageFonts.containsKey(afpFontAttributes.getFontKey())) {
             // Font not found on current page, so add the new one
-            this.pageFontCounter++;
-            afpFontAttributes.setFontReference(pageFontCounter);
-            getCurrentPageFonts().put(afpFontAttributes.getFontKey(),
-                    afpFontAttributes);
+            afpFontAttributes.setFontReference(currentState.incrementPageFontCount());
+            pageFonts.put(afpFontAttributes.getFontKey(), afpFontAttributes);
         } else {
             // Use the previously stored font attributes
-            afpFontAttributes = (AFPFontAttributes) currentPageFontMap
-                    .get(afpFontAttributes.getFontKey());
+            afpFontAttributes = (AFPFontAttributes) pageFonts.get(afpFontAttributes.getFontKey());
         }
 
         // Try and get the encoding to use for the font
         String encoding = null;
 
         try {
-            encoding = font.getCharacterSet(currentFontSize).getEncoding();
+            encoding = font.getCharacterSet(fontSize).getEncoding();
         } catch (Throwable ex) {
             encoding = AFPConstants.EBCIDIC_ENCODING;
             log.warn("renderText():: Error getting encoding for font '"
@@ -1241,19 +934,50 @@
                     + encoding);
         }
 
+        byte[] data = null;
         try {
-            getAFPDataStream().createText(afpFontAttributes.getFontReference(),
-                    mpts2units(rx), mpts2units(bl), col, vsci,
-                    mpts2units(text.getTextLetterSpaceAdjust()),
-                    worddata.getBytes(encoding));
+            String worddata = text.getText();
+            data = worddata.getBytes(encoding);
         } catch (UnsupportedEncodingException usee) {
             log.error("renderText:: Font " + afpFontAttributes.getFontKey()
                     + " caused UnsupportedEncodingException");
+            return;
         }
 
+        int fontReference = afpFontAttributes.getFontReference();
+
+        int x = (currentIPPosition + text.getBorderAndPaddingWidthStart());
+        int y = (currentBPPosition + text.getOffset() + text.getBaselineOffset());
+        float[] srcPts = new float[] {x, y};
+        int[] coords = mpts2units(srcPts);
+
+        Color color = (Color) text.getTrait(Trait.COLOR);
+
+        int variableSpaceCharacterIncrement = font.getWidth(' ', fontSize) / 1000
+          + text.getTextWordSpaceAdjust()
+          + text.getTextLetterSpaceAdjust();
+        int resolution = currentState.getResolution();
+        variableSpaceCharacterIncrement /= (AFPConstants.DPI_72_MPTS / resolution);
+      
+        int interCharacterAdjustment = text.getTextLetterSpaceAdjust();
+        interCharacterAdjustment /= (AFPConstants.DPI_72_MPTS / resolution);
+
+        AFPTextDataInfo textDataInfo = new AFPTextDataInfo();
+        textDataInfo.setFontReference(fontReference);
+        textDataInfo.setX(coords[X]);
+        textDataInfo.setY(coords[Y]);
+        textDataInfo.setColor(color);
+        textDataInfo.setVariableSpaceCharacterIncrement(variableSpaceCharacterIncrement);
+        textDataInfo.setInterCharacterAdjustment(interCharacterAdjustment);
+        textDataInfo.setData(data);
+        getAFPDataStream().createText(textDataInfo);
+        // 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
+
         super.renderText(text);
 
-        renderTextDecoration(font, currentFontSize, text, bl, rx);
+        renderTextDecoration(font, fontSize, text, coords[Y], coords[X]);
     }
 
     /**
@@ -1292,58 +1016,6 @@
     }
 
     /**
-     * Sets the AFPRenderer options
-     * 
-     * @param options
-     *            the <code>Map</code> containing the options
-     */
-    // UNUSED
-    // public void setOptions(Map options) {
-    //
-    // this.afpOptions = options;
-    //
-    // }
-    /**
-     * Determines the orientation from the string representation, this method
-     * guarantees to return a value of either 0, 90, 180 or 270.
-     * 
-     * @return the orientation
-     */
-    // UNUSED
-    // private int getOrientation(String orientationString) {
-    //
-    // int orientation = 0;
-    // if (orientationString != null && orientationString.length() > 0) {
-    // try {
-    // orientation = Integer.parseInt(orientationString);
-    // } catch (NumberFormatException nfe) {
-    // log.error("Cannot use orientation of " + orientation
-    // + " defaulting to zero.");
-    // orientation = 0;
-    // }
-    // } else {
-    // orientation = 0;
-    // }
-    // switch (orientation) {
-    // case 0:
-    // break;
-    // case 90:
-    // break;
-    // case 180:
-    // break;
-    // case 270:
-    // break;
-    // default:
-    // log.error("Cannot use orientation of " + orientation
-    // + " defaulting to zero.");
-    // orientation = 0;
-    // break;
-    // }
-    //
-    // return orientation;
-    //
-    // }
-    /**
      * Sets the rotation to be used for portrait pages, valid values are 0
      * (default), 90, 180, 270.
      * 
@@ -1351,15 +1023,7 @@
      *            The rotation in degrees.
      */
     public void setPortraitRotation(int rotation) {
-        if (rotation == 0 || rotation == 90 || rotation == 180
-                || rotation == 270) {
-            portraitRotation = rotation;
-        } else {
-            throw new IllegalArgumentException(
-                    "The portrait rotation must be one"
-                            + " of the values 0, 90, 180, 270");
-
-        }
+        currentState.setPortraitRotation(rotation);
     }
 
     /**
@@ -1370,14 +1034,7 @@
      *            The rotation in degrees.
      */
     public void setLandscapeRotation(int rotation) {
-        if (rotation == 0 || rotation == 90 || rotation == 180
-                || rotation == 270) {
-            landscapeRotation = rotation;
-        } else {
-            throw new IllegalArgumentException(
-                    "The landscape rotation must be one"
-                            + " of the values 0, 90, 180, 270");
-        }
+        currentState.setLandscapeRotation(rotation);
     }
 
     /**
@@ -1445,232 +1102,13 @@
     }
 
     /**
-     * Converts FOP mpt measurement to afp measurement units
-     * 
-     * @param mpt
-     *            the millipoints value
-     */
-    private int mpts2units(int mpt) {
-        return mpts2units((double) mpt);
-    }
-
-    /**
-     * Converts FOP pt measurement to afp measurement units
-     * 
-     * @param mpt
-     *            the millipoints value
-     */
-    private int pts2units(float mpt) {
-        return mpts2units(mpt * 1000d);
-    }
-
-    /**
-     * Converts FOP mpt measurement to afp measurement units
-     * 
-     * @param mpt
-     *            the millipoints value
-     * @return afp measurement unit value
-     */
-    private int mpts2units(double mpt) {
-        return (int) Math
-                .round(mpt / (DPI_CONVERSION_FACTOR / getResolution()));
-    }
-
-    /**
-     * Converts a byte array containing 24 bit RGB image data to a grayscale
-     * image.
-     * 
-     * @param io
-     *            the target image object
-     * @param raw
-     *            the buffer containing the RGB image data
-     * @param width
-     *            the width of the image in pixels
-     * @param height
-     *            the height of the image in pixels
-     * @param bitsPerPixel
-     *            the number of bits to use per pixel
-     */
-    protected static void convertToGrayScaleImage(ImageObject io, byte[] raw,
-            int width, int height, int bitsPerPixel) {
-        int pixelsPerByte = 8 / bitsPerPixel;
-        int bytewidth = (width / pixelsPerByte);
-        if ((width % pixelsPerByte) != 0) {
-            bytewidth++;
-        }
-        byte[] bw = new byte[height * bytewidth];
-        byte ib;
-        for (int y = 0; y < height; y++) {
-            ib = 0;
-            int i = 3 * y * width;
-            for (int x = 0; x < width; x++, i += 3) {
-
-                // see http://www.jguru.com/faq/view.jsp?EID=221919
-                double greyVal = 0.212671d * ((int) raw[i] & 0xff) + 0.715160d
-                        * ((int) raw[i + 1] & 0xff) + 0.072169d
-                        * ((int) raw[i + 2] & 0xff);
-                switch (bitsPerPixel) {
-                case 1:
-                    if (greyVal < 128) {
-                        ib |= (byte) (1 << (7 - (x % 8)));
-                    }
-                    break;
-                case 4:
-                    greyVal /= 16;
-                    ib |= (byte) ((byte) greyVal << ((1 - (x % 2)) * 4));
-                    break;
-                case 8:
-                    ib = (byte) greyVal;
-                    break;
-                default:
-                    throw new UnsupportedOperationException(
-                            "Unsupported bits per pixel: " + bitsPerPixel);
-                }
-
-                if ((x % pixelsPerByte) == (pixelsPerByte - 1)
-                        || ((x + 1) == width)) {
-                    bw[(y * bytewidth) + (x / pixelsPerByte)] = ib;
-                    ib = 0;
-                }
-            }
-        }
-        io.setImageIDESize((byte) bitsPerPixel);
-        io.setImageData(bw);
-    }
-
-    private final class ViewPortPos {
-        private int x = 0;
-
-        private int y = 0;
-
-        private int rot = 0;
-
-        private ViewPortPos() {
-        }
-
-        private ViewPortPos(Rectangle2D view, CTM ctm) {
-            ViewPortPos currentVP = (ViewPortPos) viewPortPositions
-                    .get(viewPortPositions.size() - 1);
-            int xOrigin;
-            int yOrigin;
-            int width;
-            int height;
-            switch (currentVP.rot) {
-            case 90:
-                width = mpts2units(view.getHeight());
-                height = mpts2units(view.getWidth());
-                xOrigin = pageWidth - 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())
-                        - currentVP.x;
-                yOrigin = pageHeight - 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())
-                        - currentVP.x;
-                break;
-            default:
-                xOrigin = mpts2units(view.getX()) + currentVP.x;
-                yOrigin = mpts2units(view.getY()) + currentVP.y;
-                width = mpts2units(view.getWidth());
-                height = mpts2units(view.getHeight());
-                break;
-            }
-            this.rot = currentVP.rot;
-            double[] ctmf = ctm.toArray();
-            if (ctmf[0] == 0.0d && ctmf[1] == -1.0d && ctmf[2] == 1.0d
-                    && ctmf[3] == 0.d) {
-                this.rot += 270;
-            } else if (ctmf[0] == -1.0d && ctmf[1] == 0.0d && ctmf[2] == 0.0d
-                    && ctmf[3] == -1.0d) {
-                this.rot += 180;
-            } else if (ctmf[0] == 0.0d && ctmf[1] == 1.0d && ctmf[2] == -1.0d
-                    && ctmf[3] == 0.0d) {
-                this.rot += 90;
-            }
-            this.rot %= 360;
-            switch (this.rot) {
-            /*
-             * case 0: this.x = mpts2units(view.getX()) + x; this.y =
-             * mpts2units(view.getY()) + y; break; case 90: this.x =
-             * mpts2units(view.getY()) + y; this.y = _pageWidth -
-             * mpts2units(view.getX() + view.getWidth()) - x; break; case 180:
-             * this.x = _pageWidth - mpts2units(view.getX() + view.getWidth()) -
-             * x; this.y = _pageHeight - mpts2units(view.getY() +
-             * view.getHeight()) - y; break; case 270: this.x = _pageHeight -
-             * mpts2units(view.getY() + view.getHeight()) - y; this.y =
-             * mpts2units(view.getX()) + x; break;
-             */
-            case 0:
-                this.x = xOrigin;
-                this.y = yOrigin;
-                break;
-            case 90:
-                this.x = yOrigin;
-                this.y = pageWidth - width - xOrigin;
-                break;
-            case 180:
-                this.x = pageWidth - width - xOrigin;
-                this.y = pageHeight - height - yOrigin;
-                break;
-            case 270:
-                this.x = pageHeight - height - yOrigin;
-                this.y = xOrigin;
-                break;
-            default:
-            }
-        }
-
-        public String toString() {
-            return "x:" + x + " y:" + y + " rot:" + rot;
-        }
-
-    }
-
-    private List viewPortPositions = new java.util.ArrayList();
-
-    private void pushViewPortPos(ViewPortPos vpp) {
-        viewPortPositions.add(vpp);
-        getAFPDataStream().setOffsets(vpp.x, vpp.y, vpp.rot);
-    }
-
-    private ViewPortPos popViewPortPos() {
-        ViewPortPos current = (ViewPortPos)viewPortPositions.remove(viewPortPositions.size() - 1);
-        if (viewPortPositions.size() > 0) {
-            ViewPortPos vpp = (ViewPortPos) viewPortPositions
-                    .get(viewPortPositions.size() - 1);
-            getAFPDataStream().setOffsets(vpp.x, vpp.y, vpp.rot);
-        }
-        return current;
-    }
-
-    /**
      * Sets the number of bits used per pixel
      * 
      * @param bitsPerPixel
      *            number of bits per pixel
      */
     public void setBitsPerPixel(int bitsPerPixel) {
-        this.bitsPerPixel = bitsPerPixel;
-        switch (bitsPerPixel) {
-        case 1:
-        case 4:
-        case 8:
-            break;
-        default:
-            log.warn("Invalid bits_per_pixel value, must be 1, 4 or 8.");
-            bitsPerPixel = 8;
-            break;
-        }
+        currentState.setBitsPerPixel(bitsPerPixel);
     }
 
     /**
@@ -1680,7 +1118,7 @@
      *            color image output
      */
     public void setColorImages(boolean colorImages) {
-        this.colorImages = colorImages;
+        currentState.setColorImages(colorImages);
     }
 
     /**
@@ -1702,10 +1140,7 @@
      *            the output resolution (dpi)
      */
     public void setResolution(int resolution) {
-        if (log.isDebugEnabled()) {
-            log.debug("renderer-resolution set to: " + resolution + "dpi");
-        }
-        this.resolution = resolution;
+        ((AFPState)getState()).setResolution(resolution);
     }
 
     /**
@@ -1714,18 +1149,19 @@
      * @return the resolution in dpi
      */
     public int getResolution() {
-        return this.resolution;
+        return ((AFPState)getState()).getResolution();
     }
 
-    private AFPState getState() {
+    /**
+     * @return the current AFP state
+     */
+    protected AbstractState getState() {
         if (currentState == null) {
             currentState = new AFPState();
         }
         return currentState;
     }
 
-    private boolean gocaEnabled = false;
-
     /**
      * @param enabled
      *            true if AFP GOCA is enabled for SVG support
@@ -1740,4 +1176,61 @@
     protected boolean isGOCAEnabled() {
         return this.gocaEnabled;
     }
+    
+    // TODO: remove this and use the superclass implementation 
+    /** {@inheritDoc} */
+    protected void renderReferenceArea(Block block) {
+        // save position and offset
+        int saveIP = currentIPPosition;
+        int saveBP = currentBPPosition;
+
+        //Establish a new coordinate system
+        AffineTransform at = new AffineTransform();
+        at.translate(currentIPPosition, currentBPPosition);
+        at.translate(block.getXOffset(), block.getYOffset());
+        at.translate(0, block.getSpaceBefore());
+        
+        if (!at.isIdentity()) {
+            saveGraphicsState();
+            concatenateTransformationMatrix(at);
+        }
+
+        currentIPPosition = 0;
+        currentBPPosition = 0;
+        handleBlockTraits(block);
+
+        List children = block.getChildAreas();
+        if (children != null) {
+            renderBlocks(block, children);
+        }
+
+        if (!at.isIdentity()) {
+            restoreGraphicsState();
+        }
+        
+        // stacked and relative blocks effect stacking
+        currentIPPosition = saveIP;
+        currentBPPosition = saveBP;
+    }
+
+    protected int[] transformPoints(float[] srcPts, float[] dstPts) {
+        return transformPoints(srcPts, dstPts, true);
+    }
+
+    protected int[] transformPoints(float[] srcPts, float[] dstPts, boolean milli) {
+        if (dstPts == null) {
+            dstPts = new float[srcPts.length];
+        }
+        AbstractState state = (AbstractState)getState();
+        AffineTransform at = state.getData().getTransform();
+        at.transform(srcPts, 0, dstPts, 0, srcPts.length / 2);
+        int[] coords = new int[srcPts.length];
+        for (int i = 0; i < srcPts.length; i++) {
+            if (!milli) {
+                dstPts[i] *= 1000;
+            }
+            coords[i] = Math.round(dstPts[i]);
+        }
+        return coords;        
+    }
 }

Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPRendererContextConstants.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPRendererContextConstants.java?rev=675507&r1=675506&r2=675507&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPRendererContextConstants.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPRendererContextConstants.java Thu Jul 10 03:59:39 2008
@@ -35,15 +35,9 @@
     /** The font information for the AFP renderer. */
     String AFP_FONT_INFO = "afpFontInfo";
 
-    /** The afp resolution. */
-    String AFP_RESOLUTION = "afpResolution";
-
     /** The afp datastream */
     String AFP_DATASTREAM = "afpDataStream";
 
     /** The afp state */
     String AFP_STATE = "afpPageState";
-
-    /** The afp bits per pixel */
-    String AFP_BITS_PER_PIXEL = "afpBitsPerPixel";
 }

Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPSVGHandler.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPSVGHandler.java?rev=675507&r1=675506&r2=675507&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPSVGHandler.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPSVGHandler.java Thu Jul 10 03:59:39 2008
@@ -34,6 +34,7 @@
 import org.apache.fop.render.Renderer;
 import org.apache.fop.render.RendererContext;
 import org.apache.fop.render.RendererContextConstants;
+import org.apache.fop.render.afp.modca.AFPConstants;
 import org.apache.fop.render.afp.modca.AFPDataStream;
 import org.apache.fop.render.afp.modca.GraphicsObject;
 import org.apache.fop.svg.SVGUserAgent;
@@ -71,19 +72,13 @@
         afpi.setHandlerConfiguration((Configuration)context.getProperty(HANDLER_CONFIGURATION));
         afpi.setFontInfo((org.apache.fop.fonts.FontInfo)context.getProperty(
                 AFPRendererContextConstants.AFP_FONT_INFO));
-        afpi.setResolution(((Integer)context.getProperty(
-                AFPRendererContextConstants.AFP_RESOLUTION)).intValue());
         afpi.setState((AFPState)context.getProperty(
                 AFPRendererContextConstants.AFP_STATE));
         afpi.setAFPDataStream((AFPDataStream)context.getProperty(
                 AFPRendererContextConstants.AFP_DATASTREAM));
-        afpi.setColor(!((Boolean)context.getProperty(
-                AFPRendererContextConstants.AFP_GRAYSCALE)).booleanValue());
-        afpi.setBitsPerPixel(((Integer)context.getProperty(
-                AFPRendererContextConstants.AFP_BITS_PER_PIXEL)).intValue());
         return afpi;
     }
-
+    
     /**
      * Render the SVG document.
      * 
@@ -137,20 +132,20 @@
         double h = ctx.getDocumentSize().getHeight() * 1000f;
         
         // convert to afp inches
-        double sx = ((afpInfo.getWidth() / w) * res) / 72f;
-        double sy = ((afpInfo.getHeight() / h) * res) / 72f;
-        double xOffset = (afpInfo.getX() * res) / 72000f;
-        double yOffset = ((afpInfo.getHeight() - afpInfo.getY()) * res) / 72000f;
+        double scaleX = ((afpInfo.getWidth() / w) * res) / AFPConstants.DPI_72;
+        double scaleY = ((afpInfo.getHeight() / h) * res) / AFPConstants.DPI_72;
+        double xOffset = (afpInfo.getX() * res) / AFPConstants.DPI_72_MPTS;
+        double yOffset = ((afpInfo.getHeight() - afpInfo.getY()) * res) / AFPConstants.DPI_72_MPTS;
 
         // Transformation matrix that establishes the local coordinate system for the SVG graphic
         // in relation to the current coordinate system (note: y axis is inverted)
-        AffineTransform trans = new AffineTransform(sx, 0, 0, -sy, xOffset, yOffset);
+        AffineTransform trans = new AffineTransform(scaleX, 0, 0, -scaleY, xOffset, yOffset);
         graphics.setTransform(trans);
         
-        int x = (int)Math.round((afpInfo.getX() * 25.4f) / 1000);
-        int y = (int)Math.round((afpInfo.getY() * 25.4f) / 1000);
-        int width = (int)Math.round((afpInfo.getWidth() * res) / 72000f);
-        int height = (int)Math.round((afpInfo.getHeight() * res) / 72000f);
+        int x = (int)Math.round((afpInfo.getX() * 25.4f) / 1000f);
+        int y = (int)Math.round((afpInfo.getY() * 25.4f) / 1000f);
+        int width = (int)Math.round((afpInfo.getWidth() * res) / AFPConstants.DPI_72_MPTS);
+        int height = (int)Math.round((afpInfo.getHeight() * res) / AFPConstants.DPI_72_MPTS);
         
         // set the data object parameters
         DataObjectInfo dataObjectInfo = new DataObjectInfo();

Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPState.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPState.java?rev=675507&r1=675506&r2=675507&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPState.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPState.java Thu Jul 10 03:59:39 2008
@@ -19,157 +19,183 @@
 
 package org.apache.fop.render.afp;
 
-import java.awt.Color;
-import java.io.Serializable;
-import java.util.Arrays;
-import java.util.List;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 
 /**
- * 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 {
-    private Data data = new Data();
-    
-    private List stateStack = new java.util.ArrayList();
+public class AFPState extends org.apache.fop.render.AbstractState {
+
+    private static Log log = LogFactory.getLog("org.apache.fop.render.afp.AFPState");
 
     /**
-     * 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(getData().color)) {
-            getData().color = col;
-            return true;
+     * The portrait rotation
+     */
+    private int portraitRotation = 0;
+
+    /**
+     * The landscape rotation
+     */
+    private int landscapeRotation = 270;
+
+    /**
+     * Flag to the set the output object type for images
+     */
+    private boolean colorImages = false;
+
+    /**
+     * Default value for image depth
+     */
+    private int bitsPerPixel = 8;
+
+    /**
+     * The output resolution
+     */
+    private int resolution = 240; // 240 dpi
+
+    /**
+     * The current page 
+     */
+    private AFPPageState pageState = new AFPPageState();
+    
+    /**
+     * Sets the rotation to be used for portrait pages, valid values are 0
+     * (default), 90, 180, 270.
+     * 
+     * @param rotation
+     *            The rotation in degrees.
+     */
+    protected void setPortraitRotation(int rotation) {
+        if (rotation == 0 || rotation == 90 || rotation == 180
+                || rotation == 270) {
+            portraitRotation = rotation;
+        } else {
+            throw new IllegalArgumentException(
+                    "The portrait rotation must be one"
+                            + " of the values 0, 90, 180, 270");
+
         }
-        return false;
     }
 
     /**
-     * Sets if the current painted shape is to be filled
-     * @param fill true if the current painted shape is to be filled
-     * @return true if the fill value has changed
+     * @return the rotation to be used for portrait pages
      */
-    protected boolean setFill(boolean fill) {
-        if (fill != getData().filled) {
-            getData().filled = fill;
-            return true;
-        }
-        return false;
+    protected int getPortraitRotation() {
+        return this.portraitRotation;
     }
 
     /**
-     * Get the color.
-     * @return the color
+     * Sets the rotation to be used for landscape pages, valid values are 0, 90,
+     * 180, 270 (default).
+     * 
+     * @param rotation
+     *            The rotation in degrees.
      */
-    protected Color getColor() {
-        if (getData().color == null) {
-            getData().color = Color.black;
+    protected void setLandscapeRotation(int rotation) {
+        if (rotation == 0 || rotation == 90 || rotation == 180
+                || rotation == 270) {
+            landscapeRotation = rotation;
+        } else {
+            throw new IllegalArgumentException(
+                    "The landscape rotation must be one"
+                            + " of the values 0, 90, 180, 270");
         }
-        return getData().color;
     }
 
     /**
-     * Set the current line width.
-     * @param width the line width in points
-     * @return true if the line width has changed
+     * @return the landscape rotation
      */
-    protected boolean setLineWidth(float width) {
-        if (getData().lineWidth != width) {
-            getData().lineWidth = width;
-            return true;
-        }
-        return false;
+    protected int getLandscapeRotation() {
+        return this.landscapeRotation;
     }
 
     /**
-     * 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, getData().dashArray)) {
-            getData().dashArray = dash;
-            return true;
+     * Sets the number of bits used per pixel
+     * 
+     * @param bitsPerPixel
+     *            number of bits per pixel
+     */
+    public void setBitsPerPixel(int bitsPerPixel) {
+        this.bitsPerPixel = bitsPerPixel;
+        switch (bitsPerPixel) {
+        case 1:
+        case 4:
+        case 8:
+            break;
+        default:
+            log.warn("Invalid bits_per_pixel value, must be 1, 4 or 8.");
+            bitsPerPixel = 8;
+            break;
         }
-        return false;
     }
 
     /**
-     * Gets the current line width
-     * @return the current line width
+     * @return the number of bits per pixel
      */
-    protected float getLineWidth() {
-        return getData().lineWidth;
+    public int getBitsPerPixel() {
+        return this.bitsPerPixel;
     }
 
     /**
-     * Get the background color.
-     * @return the background color
+     * Sets whether images are color or not
+     * 
+     * @param colorImages
+     *            color image output
      */
-    protected Color getBackColor() {
-        if (getData().backColor == null) {
-            getData().backColor = Color.white;
-        }
-        return getData().backColor;
+    public void setColorImages(boolean colorImages) {
+        this.colorImages = colorImages;
     }
 
     /**
-     * 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
+     * @return true if color images are to be used
      */
-    protected boolean setBackColor(Color col) {
-        if (!col.equals(getData().backColor)) {
-            getData().backColor = col;
-            return true;
-        }
-        return false;
+    protected boolean isColorImages() {
+        return this.colorImages;
     }
 
     /**
-     * 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(getData().fontName)) {
-            getData().fontName = internalFontName;
-            return true;
+     * Sets the output/device resolution
+     * 
+     * @param resolution
+     *            the output resolution (dpi)
+     */
+    public void setResolution(int resolution) {
+        if (log.isDebugEnabled()) {
+            log.debug("renderer-resolution set to: " + resolution + "dpi");
         }
-        return false;
+        this.resolution = resolution;
     }
 
     /**
-     * Gets the current font name
-     * @return the current font name
+     * Returns the output/device resolution.
+     * 
+     * @return the resolution in dpi
      */
-    protected String getFontName() {
-        return getData().fontName;
+    protected int getResolution() {
+        return this.resolution;
     }
-    
+
+    /** {@inheritDoc} */
+    protected AbstractData instantiateData() {
+        return new AFPData();
+    }
+
     /**
-     * Gets the current font size
-     * @return the current font size
+     * @return the state of the current page
      */
-    protected int getFontSize() {
-        return getData().fontSize;
+    protected AFPPageState getPageState() {
+        return this.pageState;
     }
-
+    
     /**
-     * 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
+     * Sets if the current painted shape is to be filled
+     * @param fill true if the current painted shape is to be filled
+     * @return true if the fill value has changed
      */
-    protected boolean setFontSize(int size) {
-        if (size != getData().fontSize) {
-            getData().fontSize = size;
+    protected boolean setFill(boolean fill) {
+        if (fill != ((AFPData)getData()).filled) {
+            ((AFPData)getData()).filled = fill;
             return true;
         }
         return false;
@@ -180,137 +206,177 @@
      * @return the current page fonts
      */
     protected AFPPageFonts getPageFonts() {
-        if (getData().pageFonts == null) {
-            getData().pageFonts = new AFPPageFonts();
-        }
-        return getData().pageFonts;
+        return pageState.getFonts();
     }
 
     /**
-     * Sets the image uri of the current image being processed
-     * @param uri the image uri of the current image being processed
-     * @return true if the image uri has changed
+     * Increments and returns the page font count
+     * @return the page font count
      */
-    public boolean setImageUri(String uri) {
-        if (!uri.equals(getData().imageUri)) {
-            getData().imageUri = uri;
-            return true;
-        }
-        return false;
+    public int incrementPageFontCount() {
+        return pageState.incrementFontCount();
     }
 
     /**
-     * Returns the image uri of the current image being processed
-     * @return the image uri of the current image being processed
+     * Sets the page width
+     * @param pageWidth the page width
      */
-    protected String getImageUri() {
-        return getData().imageUri;
+    public void setPageWidth(int pageWidth) {
+        pageState.setWidth(pageWidth);
     }
-    
+
     /**
-     * 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.
+     * @return the page width
      */
-    public void push() {
-        Data copy;
-        try {
-            copy = (Data)getData().clone();
-        } catch (CloneNotSupportedException e) {
-            throw new RuntimeException(e.getMessage());
-        }
-        stateStack.add(copy);
+    public int getPageWidth() {
+        return pageState.getWidth();
     }
 
     /**
-     * Get the current stack level.
-     *
-     * @return the current stack level
+     * Sets the page height
+     * @param pageHeight the page height
      */
-    public int getStackLevel() {
-        return stateStack.size();
+    public void setPageHeight(int pageHeight) {
+        pageState.setHeight(pageHeight);
     }
 
     /**
-     * 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
+     * @return the page height
      */
-    public Data pop() {
-        if (getStackLevel() > 0) {
-            Data popped = (Data)stateStack.remove(stateStack.size() - 1);
-            data = popped;
-            return popped;
-        } else {
-            return null;
-        }
+    public int getPageHeight() {
+        return pageState.getHeight();
     }
 
     /**
-     * @return the currently valid state
+     * Sets the uri of the current image
+     * @param uri the uri of the current image
      */
-    public Data getData() {
-        return data;
+    protected void setImageUri(String uri) {
+        ((AFPData)getData()).imageUri = uri;
     }
-    
-    /** the state data instance */
-    public class Data implements Cloneable, Serializable {
-        private static final long serialVersionUID = -1789481244175275686L;
 
-        /** The current color */
-        private Color color = null;
+    /**
+     * Gets the uri of the current image
+     * @return the uri of the current image
+     */
+    public String getImageUri() {
+        return ((AFPData)getData()).imageUri;
+    }    
+
+    /** {@inheritDoc} */
+    public String toString() {
+        return "AFPState{portraitRotation=" + portraitRotation
+        + ", landscapeRotation=" + landscapeRotation
+        + ", colorImages=" + colorImages
+        + ", bitsPerPixel=" + bitsPerPixel
+        + ", resolution=" + resolution
+        + ", pageState=" + pageState
+        + "}";
+    }
+
+    /**
+     * Page level state data 
+     */
+    private class AFPPageState {
+        /** The current page width */
+        private int width = 0;
+
+        /** The current page height */
+        private int height = 0;
+
+        /** The current page fonts */
+        private AFPPageFonts fonts = new AFPPageFonts();
+
+        /** The current page font count */
+        private int fontCount = 0;
+
+        /**
+         * @return the page width
+         */
+        protected int getWidth() {
+            return width;
+        }
+
+        /**
+         * Sets the page width
+         * @param width the page width
+         */
+        protected void setWidth(int width) {
+            this.width = width;
+        }
+
+        /**
+         * @return the page height
+         */
+        protected int getHeight() {
+            return height;
+        }
 
-        /** The current background color */
-        private Color backColor = null;
+        /**
+         * Sets the page height
+         * @param height the page height
+         */
+        protected void setHeight(int height) {
+            this.height = height;
+        }
 
-        /** The current font name */
-        private String fontName = null;
+        /**
+         * @return the page fonts
+         */
+        protected AFPPageFonts getFonts() {
+            return fonts;
+        }
 
-        /** The current font size */
-        private int fontSize = 0;
+        /**
+         * Sets the current page fonts
+         * @param fonts the current page fonts
+         */
+        protected void setFonts(AFPPageFonts fonts) {
+            this.fonts = fonts;
+        }
 
-        /** The current line width */
-        private float lineWidth = 0;
+        /**
+         * @return increment and return the current page font count
+         */
+        protected int incrementFontCount() {
+            return ++fontCount;
+        }
+        
+        /** {@inheritDoc} */
+        public String toString() {
+            return "AFPPageState{width=" + width
+            + ", height=" + height
+            + ", fonts=" + fonts
+            + ", fontCount=" + fontCount
+            + "}";
+        }
+    }
 
-        /** The dash array for the current basic stroke (line type) */
-        private float[] dashArray = null;
+    /**
+     * Block level data
+     */
+    private class AFPData extends org.apache.fop.render.AbstractState.AbstractData {
+        private static final long serialVersionUID = -1789481244175275686L;
 
         /** The current fill status */
         private boolean filled = false;
         
-        /** The fonts on the current page */
-        private AFPPageFonts pageFonts = null;
-
-        /** The current image uri */
         private String imageUri = null;
         
         /** {@inheritDoc} */
         public Object clone() throws CloneNotSupportedException {
-            Data obj = new Data();
-            obj.color = this.color;
-            obj.backColor = this.backColor;
-            obj.fontName = this.fontName;
-            obj.fontSize = this.fontSize;
-            obj.lineWidth = this.lineWidth;
-            obj.dashArray = this.dashArray;
+            AFPData obj = (AFPData)super.clone();
             obj.filled = this.filled;
-            obj.pageFonts = this.pageFonts;
             obj.imageUri = this.imageUri;
             return obj;
         }
         
-        /** {@inheritDoc} */        
+        /** {@inheritDoc} */
         public String toString() {
-            return "color=" + color
-            + ", backColor=" + backColor
-            + ", fontName=" + fontName
-            + ", fontSize=" + fontSize
-            + ", lineWidth=" + lineWidth
-            + ", dashArray=" + dashArray
+            return "AFPData{" + super.toString()
             + ", filled=" + filled
-            + ", pageFonts=" + pageFonts
-            + ", imageUri=" + imageUri;
+            + ", imageUri=" + imageUri
+            + "}";
         }
     }
 }
\ No newline at end of file

Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/ObjectAreaInfo.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/ObjectAreaInfo.java?rev=675507&r1=675506&r2=675507&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/ObjectAreaInfo.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/ObjectAreaInfo.java Thu Jul 10 03:59:39 2008
@@ -16,6 +16,7 @@
  */
 
 /* $Id$ */
+
 package org.apache.fop.render.afp;
 
 public class ObjectAreaInfo {
@@ -144,4 +145,4 @@
         + ", heightRes=" + heightRes
         + ", rotation=" + rotation;
     }
-}
\ No newline at end of file
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org