Index: src/java/META-INF/services/org.apache.fop.fo.ElementMapping
===================================================================
--- src/java/META-INF/services/org.apache.fop.fo.ElementMapping	(revision 744229)
+++ src/java/META-INF/services/org.apache.fop.fo.ElementMapping	(working copy)
@@ -2,6 +2,7 @@
 org.apache.fop.fo.extensions.svg.SVGElementMapping
 org.apache.fop.fo.extensions.svg.BatikExtensionElementMapping
 org.apache.fop.fo.extensions.ExtensionElementMapping
+org.apache.fop.fo.extensions.InternalElementMapping
 org.apache.fop.fo.extensions.OldExtensionElementMapping
 org.apache.fop.fo.extensions.xmp.XMPElementMapping
 org.apache.fop.fo.extensions.xmp.RDFElementMapping
Index: src/java/org/apache/fop/accessibility/TransformerNode.java
===================================================================
--- src/java/org/apache/fop/accessibility/TransformerNode.java	(revision 0)
+++ src/java/org/apache/fop/accessibility/TransformerNode.java	(revision 0)
@@ -0,0 +1,338 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.accessibility;
+
+
+    import java.io.File;
+    import javax.xml.transform.Result;
+    import javax.xml.transform.Source;
+    import javax.xml.transform.TransformerConfigurationException;
+    import javax.xml.transform.TransformerFactory;
+    import javax.xml.transform.sax.SAXResult;
+    import javax.xml.transform.sax.SAXTransformerFactory;
+    import javax.xml.transform.sax.TransformerHandler;
+    import javax.xml.transform.stream.StreamSource;
+    import org.apache.fop.apps.FOPException;
+    import org.xml.sax.Attributes;
+    import org.xml.sax.Locator;
+    import org.xml.sax.SAXException;
+    import org.xml.sax.helpers.AttributesImpl;
+    import org.xml.sax.helpers.DefaultHandler;
+
+    /**
+     * Used for accessibility to run required xslt transforms
+     */
+    public class TransformerNode extends DefaultHandler {
+
+        private TransformerHandler mTranHandler;
+
+        /**
+         * happens after setParams have been broadcast.
+         * @param downstreamHandler the handler passed in
+         * @param xsltFile for transform
+         * @throws FOPException for general errors
+         */
+        public TransformerNode(DefaultHandler downstreamHandler, File xsltFile)
+            throws FOPException {
+            try {
+                 TransformerFactory transFact = TransformerFactory.newInstance();
+                 SAXTransformerFactory saxTFactory = ((SAXTransformerFactory) transFact);
+                 // StreamSource ss = new StreamSource(new StringReader(xsltText));
+                 StreamSource ss = new StreamSource(xsltFile);
+                 mTranHandler = saxTFactory.newTransformerHandler(ss);
+                 SAXResult saxResult = new SAXResult();
+                 saxResult.setHandler(downstreamHandler);
+                 mTranHandler.setResult(saxResult);
+              } catch (TransformerConfigurationException t) {
+                 throw new FOPException(t);
+              }
+           }
+
+        /**
+         *
+         * @param result of transform
+         * @param xsltFile for transform
+         * @throws FOPException for general errors
+         */
+        public TransformerNode(Result result, File xsltFile)
+            throws FOPException {
+            try {
+                TransformerFactory transFact = TransformerFactory.newInstance();
+                SAXTransformerFactory saxTFactory = ((SAXTransformerFactory) transFact);
+                StreamSource ss = new StreamSource(xsltFile);
+                mTranHandler = saxTFactory.newTransformerHandler(ss);
+                mTranHandler.setResult(result);
+            } catch (TransformerConfigurationException t) {
+                throw new FOPException(t);
+            }
+        }
+
+           /**
+            * This is part of a two phase construction.  Call this, then call initResult.
+            * @param xsltFile for transform
+            * @throws FOPException for general errors
+            */
+           public TransformerNode(Source xsltFile)
+              throws FOPException {
+              try {
+                 TransformerFactory transFact = TransformerFactory.newInstance();
+                 SAXTransformerFactory saxTFactory = ((SAXTransformerFactory) transFact);
+                 mTranHandler = saxTFactory.newTransformerHandler(xsltFile);
+              } catch (TransformerConfigurationException t) {
+                  throw new FOPException(t);
+              }
+           }
+
+           /**
+            * Call this after calling constructor for xsltFile only above.
+            * @param result of transform
+            */
+           public void initResult(Result result) {
+                mTranHandler.setResult(result);
+           }
+
+
+
+           /******************** start of ContentHandler ***************************/
+           /**
+            * @param locator - the locator
+            */
+           public void setDocumentLocator(Locator locator) {
+              if (mTranHandler != null) {
+                 mTranHandler.setDocumentLocator(locator);
+              }
+           }
+
+           /**
+            * handle startDocument event
+            * @throws SAXException - if parser fails
+            */
+           public void startDocument()
+           throws SAXException {
+              if (mTranHandler != null) {
+                 mTranHandler.startDocument();
+              }
+           }
+
+           /**
+            * handle endDocument event
+            * @throws SAXException - if parser fails
+            */
+           public void endDocument()
+           throws SAXException {
+              if (mTranHandler != null) {
+                 mTranHandler.endDocument();
+              }
+           }
+
+           /** Processing instruction.
+            * @param target - of processing instruction
+            * @param data - of processing instruction
+            * @throws SAXException - if parser fails
+            */
+           public void processingInstruction(String target, String data)
+           throws SAXException {
+              if (mTranHandler != null) {
+                 mTranHandler.processingInstruction(target, data);
+              }
+           }
+
+           /**
+            * Start element.
+            * This one is usually overridden for special processing as well as endElement
+            * @param uri - the uri
+            * @param local - the local
+            * @param raw - the raw version
+            * @param attrs - the attributes of the element
+            * @throws SAXException - if parser fails
+            */
+           public void startElement(String uri, String local, String raw,
+                   Attributes attrs) throws SAXException {
+              AttributesImpl ai = new AttributesImpl(attrs);
+              if (mTranHandler != null) {
+                 mTranHandler.startElement(uri, local, raw, ai);
+              }
+           }
+
+           /**
+            * Characters.
+            * @param ch the characters
+            * @param start - start index
+            * @param length - the length of ch
+            *
+            * @throws SAXException - if parser fails
+            */
+           public void characters(char[] ch, int start, int length)
+           throws SAXException {
+              if (mTranHandler != null) {
+                 mTranHandler.characters(ch, start, length);
+              }
+           }
+
+           /**
+            * Ignorable whitespace.
+            * @param ch the characters
+            * @param start - start index
+            * @param length - the length of ch
+            * @throws SAXException - if parser fails
+            */
+           public void ignorableWhitespace(char[] ch, int start, int length)
+           throws SAXException {
+              if (mTranHandler != null) {
+                 mTranHandler.ignorableWhitespace(ch, start, length);
+              }
+           }
+
+           /**
+            * End element.
+            * @param uri - the uri
+            * @param local - the local
+            * @param raw - the raw version
+            * @throws SAXException - if parser fails
+            */
+
+           public void endElement(String uri, String local, String raw)
+           throws SAXException {
+              if (mTranHandler != null) {
+                 mTranHandler.endElement(uri, local, raw);
+              }
+           }
+
+           /**
+            * @param string - to be skipped
+            * @throws SAXException - if parser fails
+            */
+           public void skippedEntity(String string)
+           throws SAXException {
+              if (mTranHandler != null) {
+                 mTranHandler.skippedEntity(string);
+              }
+           }
+
+           /**
+            * @param string - param1
+            * @param string1 - param2
+            * @throws SAXException - if parser fails
+            */
+           public void startPrefixMapping(String string, String string1)
+           throws SAXException {
+              if (mTranHandler != null) {
+                 mTranHandler.startPrefixMapping(string, string1);
+              }
+           }
+
+           /**
+            * @param string - param1
+            * @throws SAXException - if parser fails
+            */
+           public void endPrefixMapping(String string)
+           throws SAXException {
+              if (mTranHandler != null) {
+                 mTranHandler.endPrefixMapping(string);
+              }
+           }
+
+           /***************************** LexicalHandlerImpl**************************/
+           /**
+            * @param name - param1
+            * @param pid - param2
+            * @param lid - param3
+            * @throws SAXException - if parser fails
+            */
+           public void startDTD(String name, String pid, String lid)
+           throws SAXException {
+              if (mTranHandler != null) {
+                 mTranHandler.startDTD(name, pid, lid);
+              }
+           }
+
+           /**
+            * End of DTD
+            * @throws SAXException - if parser fails
+            */
+           public void endDTD()
+           throws SAXException {
+              if (mTranHandler != null) {
+                 mTranHandler.endDTD();
+              }
+           }
+
+           /**
+            * startEnitity.
+            * @param string - param 1
+            * @throws SAXException - if parser fails
+            */
+           public void startEntity(String string)
+           throws SAXException {
+              if (mTranHandler != null) {
+                 mTranHandler.startEntity(string);
+              }
+           }
+
+           /**
+            * end Entity
+            * @param string - param 1
+            * @throws SAXException - if paser fails
+            */
+           public void endEntity(String string)
+           throws SAXException {
+              if (mTranHandler != null) {
+                 mTranHandler.endEntity(string);
+              }
+           }
+
+           /**
+            * Start of CDATA section
+            * @throws SAXException - parser fails
+            */
+           public void startCDATA()
+           throws SAXException {
+              if (mTranHandler != null) {
+                 mTranHandler.startCDATA();
+              }
+           }
+
+           /**
+            * endCDATA section
+            * @throws SAXException - if paser fails
+            */
+           public void endCDATA()
+           throws SAXException {
+              if (mTranHandler != null) {
+                 mTranHandler.endCDATA();
+              }
+           }
+
+           /**
+            *
+            * @param charArray - the characters
+            * @param int1 - param 2
+            * @param int2 - param 3
+            * @throws SAXException - if paser fails
+            */
+           public void comment(char[] charArray, int int1, int int2)
+           throws SAXException {
+              if (mTranHandler != null) {
+                 mTranHandler.comment(charArray, int1, int2);
+              }
+           }
+
+           /******************** End of Lexical Handler ***********************/
+    }
Index: src/java/org/apache/fop/accessibility/TransformerNodeEndProcessing.java
===================================================================
--- src/java/org/apache/fop/accessibility/TransformerNodeEndProcessing.java	(revision 0)
+++ src/java/org/apache/fop/accessibility/TransformerNodeEndProcessing.java	(revision 0)
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.accessibility;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.apps.FOUserAgent;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * An extension of TransformerNode used to run 2nd transform after completion of first
+ *
+ */
+public class TransformerNodeEndProcessing extends TransformerNode {
+    private final ByteArrayOutputStream mBaosBuf = new ByteArrayOutputStream();
+    private DefaultHandler mFopHandler = null;
+    private final FOUserAgent userAgent;
+
+
+
+
+
+    /**
+     * Do a transform, but perform special processing at the end for the access
+     * stuff.
+     *
+     * @param xsltFile
+     *            . Transform to do.
+     * @param fopHandler
+     *            . Used in the end processing
+     * @param userAgent
+     *            . the userAgent
+     * @throws FOPException
+     *                      if transform fails
+     */
+
+    public TransformerNodeEndProcessing(Source xsltFile, DefaultHandler fopHandler,
+            FOUserAgent userAgent) throws FOPException {
+        super(xsltFile);
+        mFopHandler = fopHandler;
+        this.userAgent = userAgent;
+        Result res1 = new StreamResult(mBaosBuf);
+        super.initResult(res1);
+    }
+
+    /**
+     * @throws SAXException
+     *         if the parser fails
+     */
+    public void endDocument() throws SAXException {
+        super.endDocument();
+        // do the second tranform to struct
+        Source xsltFile = new
+            StreamSource(getClass().getResource("reduceFOTree.xsl").toExternalForm());
+        TransformerFactory factory = TransformerFactory.newInstance();
+        try {
+            Transformer transformer = factory.newTransformer(xsltFile);
+            Source src = new StreamSource(new ByteArrayInputStream(mBaosBuf
+                    .toByteArray()));
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            Result res = new StreamResult(out);
+            userAgent.putResult(out);
+            transformer.transform(src, res);
+            SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
+            saxParserFactory.setNamespaceAware(true);
+            saxParserFactory.setValidating(false);
+            SAXParser saxParser = saxParserFactory.newSAXParser();
+            InputStream in = new ByteArrayInputStream(mBaosBuf.toByteArray());
+            saxParser.parse(in, mFopHandler);
+        } catch (Exception e) {
+            // TODO Auto-generated catch block
+            throw new SAXException(e);
+        }
+
+    }
+
+}
Index: src/java/org/apache/fop/accessibility/addPtr.xsl
===================================================================
--- src/java/org/apache/fop/accessibility/addPtr.xsl	(revision 0)
+++ src/java/org/apache/fop/accessibility/addPtr.xsl	(revision 0)
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:foi="http://xmlgraphics.apache.org/fop/internal">
+<xsl:template match="fo:block|fo:block-container"><xsl:call-template name="addPtr"/></xsl:template>
+<xsl:template match="fo:list-block|fo:list-item|fo:list-item-label|fo:list-item-body"><xsl:call-template name="addPtr"/></xsl:template>
+<xsl:template match="fo:table|fo:table-body|fo:table-header|fo:table-footer|fo:table-row|fo:table-cell"><xsl:call-template name="addPtr"/></xsl:template>
+<xsl:template match="fo:inline|fo:wrapper|fo:basic-link|fo:character"><xsl:call-template name="addPtr"/></xsl:template>
+<xsl:template match="fo:instream-foreign-object|fo:external-graphic"><xsl:call-template name="addPtr"/></xsl:template>
+<xsl:template match="fo:page-number|fo:page-number-citation|fo:page-number-citation-last"><xsl:call-template name="addPtr"/></xsl:template>
+<xsl:template match="fo:footnote|fo:footnote-body"><xsl:call-template name="addPtr"/></xsl:template>
+<xsl:template match="fo:marker"><xsl:call-template name="addPtr"/></xsl:template>
+<xsl:template name="addPtr"><xsl:element name="{name()}" namespace="{namespace-uri()}"><xsl:apply-templates select="@*"/><xsl:attribute name="foi:ptr"><xsl:value-of select="generate-id()"/></xsl:attribute><xsl:apply-templates/></xsl:element></xsl:template>
+<xsl:template match="@*|node()"><xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy></xsl:template>
+</xsl:stylesheet>
\ No newline at end of file
Index: src/java/org/apache/fop/accessibility/reduceFOTree.xsl
===================================================================
--- src/java/org/apache/fop/accessibility/reduceFOTree.xsl	(revision 0)
+++ src/java/org/apache/fop/accessibility/reduceFOTree.xsl	(revision 0)
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:fo="http://www.w3.org/1999/XSL/Format"
+  xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" 
+  xmlns:svg="http://www.w3.org/2000/svg"
+  xmlns:foi="http://xmlgraphics.apache.org/fop/internal" 
+  version="1.0">
+    <xsl:output method="xml" indent="no"/>
+    
+    <xsl:template match="*">
+        <xsl:element name="{name()}">
+            <xsl:copy-of select="@foi:ptr"/>
+            <xsl:apply-templates/>
+        </xsl:element>
+    </xsl:template>
+    
+    <xsl:template match="@master-reference|@flow-name"></xsl:template>
+    
+    <xsl:template match="fo:block">
+        <xsl:element name="{name()}">
+            <xsl:copy-of select="@foi:ptr"/>
+            <xsl:apply-templates/>
+        </xsl:element>
+    </xsl:template>
+    
+    <xsl:template match="fo:inline|fo:wrapper|fo:page-number|fo:page-number-citation|fo:page-number-citation-last">
+        <xsl:element name="{name()}">
+            <xsl:copy-of select="@foi:ptr"/>
+            <xsl:apply-templates/>
+        </xsl:element>
+    </xsl:template>
+    
+    <xsl:template match="fo:table-cell|fo:table|fo:table-body|fo:table-footer|fo:table-row|fo:table-header">
+        <xsl:element name="{name()}">
+            <xsl:copy-of select="@foi:ptr"/>
+            <xsl:apply-templates/>
+        </xsl:element>
+    </xsl:template>
+    
+    <xsl:template match="fo:list-block|fo:list-item|fo:list-item-label|fo:list-item-body">
+        <xsl:element name="{name()}">
+            <xsl:copy-of select="@foi:ptr"/>
+            <xsl:apply-templates/>
+        </xsl:element>
+    </xsl:template>
+    
+    <xsl:template match="fo:basic-link|fo:block-container|fo:character|fo:instream-foreign-object|fo:marker">
+        <xsl:element name="{name()}">
+            <xsl:copy-of select="@foi:ptr"/>
+            <xsl:apply-templates/>
+        </xsl:element>
+    </xsl:template>
+    
+    <xsl:template match="fo:external-graphic|fo:instream-foreign-object">
+        <xsl:element name="{name()}">
+            <xsl:copy-of select="@fox:alt-text|@foi:ptr"/>
+            <xsl:apply-templates/>
+        </xsl:element>
+    </xsl:template>
+    
+    
+    
+    <xsl:template match="text()"></xsl:template>
+    
+    <xsl:template match="fo:layout-master-set|comment() | processing-instruction() | fo:simple-page-master | fo:table-column | fo:leader | fo:retrieve-marker "/>
+
+    <xsl:template match="svg:svg | svg | fo:inline-container | fo:float | fo:bidi-override"/>
+    
+</xsl:stylesheet>
Index: src/java/org/apache/fop/apps/FOUserAgent.java
===================================================================
--- src/java/org/apache/fop/apps/FOUserAgent.java	(revision 744229)
+++ src/java/org/apache/fop/apps/FOUserAgent.java	(working copy)
@@ -20,6 +20,7 @@
 package org.apache.fop.apps;
 
 // Java
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.util.Date;
 import java.util.Map;
@@ -76,7 +77,7 @@
 
     private static Log log = LogFactory.getLog("FOP");
 
-    private FopFactory factory;
+    private final FopFactory factory;
 
     /**
      *  The base URL for all URL resolutions, especially for
@@ -91,13 +92,14 @@
     private URIResolver uriResolver = null;
 
     private float targetResolution = FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION;
-    private Map rendererOptions = new java.util.HashMap();
+    private final Map rendererOptions = new java.util.HashMap();
     private File outputFile = null;
     private IFDocumentHandler documentHandlerOverride = null;
     private Renderer rendererOverride = null;
     private FOEventHandler foEventHandlerOverride = null;
     private boolean locatorEnabled = true; // true by default (for error messages).
-    private EventBroadcaster eventBroadcaster = new FOPEventBroadcaster();
+    private final EventBroadcaster eventBroadcaster = new FOPEventBroadcaster();
+    private ByteArrayOutputStream reducedFOTree;  // accessibility: reduced FO
 
     /** Producer:  Metadata element for the system/software that produces
      * the document. (Some renderers can store this in the document.)
@@ -123,7 +125,7 @@
     /** Set of keywords applicable to this document. */
     protected String keywords = null;
 
-    private ImageSessionContext imageSessionContext = new AbstractImageSessionContext() {
+    private final ImageSessionContext imageSessionContext = new AbstractImageSessionContext() {
 
         public ImageContext getParentContext() {
             return getFactory();
@@ -153,6 +155,9 @@
         setBaseURL(factory.getBaseURL());
         setFontBaseURL(factory.getFontManager().getFontBaseURL());
         setTargetResolution(factory.getTargetResolution());
+        if (this.getRendererOptions().get("accessibility") == null) {
+            this.rendererOptions.put("accessibility", Boolean.FALSE);
+        }
     }
 
     /** @return the associated FopFactory instance */
@@ -197,6 +202,7 @@
         return rendererOverride;
     }
 
+
     /**
      * Sets an explicit FOEventHandler instance which overrides the one
      * defined by the render type setting.
@@ -615,5 +621,33 @@
 
     }
 
+    /**
+     * check if accessibility is enabled
+     * @return boolean
+     */
+    public boolean accessibilityEnabled() {
+        Object obj = this.getRendererOptions().get("accessibility");
+        if (obj == null) {
+            obj = Boolean.FALSE;
+        }
+        return ((Boolean) obj).booleanValue();
+        //return ((Boolean)this.getRendererOptions().get("accessibility")).booleanValue();
+    }
+
+    /**
+     * Used for accessibility, store result from 2nd transform for later use
+     * @param res the result from 2nd transform
+     */
+    public void putResult(ByteArrayOutputStream res) {
+        this.reducedFOTree = res;
+    }
+
+    /**
+     * Used for accessibility
+     * @return result from 2nd transform as byte array
+     */
+    public byte[] getResultAsByteArray() {
+        return this.reducedFOTree.toByteArray();
+    }
 }
 
Index: src/java/org/apache/fop/apps/Fop.java
===================================================================
--- src/java/org/apache/fop/apps/Fop.java	(revision 744229)
+++ src/java/org/apache/fop/apps/Fop.java	(working copy)
@@ -19,33 +19,35 @@
 
 package org.apache.fop.apps;
 
-// Java
 import java.io.OutputStream;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
 
 import org.xml.sax.helpers.DefaultHandler;
-
 import org.apache.fop.fo.FOTreeBuilder;
+import org.apache.fop.accessibility.TransformerNodeEndProcessing;
 
 /**
  * Primary class that activates the FOP process for embedded usage.
  * <P>
- * JAXP is the standard method of embedding FOP in Java programs.
- * Please check our
- * <a href="http://xmlgraphics.apache.org/fop/trunk/embedding.html">embedding page</a>
- * for samples (these are also available within the distribution in
+ * JAXP is the standard method of embedding FOP in Java programs. Please check
+ * our <a
+ * href="http://xmlgraphics.apache.org/fop/trunk/embedding.html">embedding
+ * page</a> for samples (these are also available within the distribution in
  * FOP_DIR\examples\embedding)
  * <P>
  * Methods within FOUserAgent are available to customize portions of the
- * process.  For example, a specific Renderer object can be specified,
- * also ElementMappings which determine elements in the FO that can be
- * processed) can be added.
+ * process. For example, a specific Renderer object can be specified, also
+ * ElementMappings which determine elements in the FO that can be processed) can
+ * be added.
  * <P>
- * At the moment, it is recommended not to reuse an instance of this
- * class for more than one rendering run.
+ * At the moment, it is recommended not to reuse an instance of this class for
+ * more than one rendering run.
  */
 public class Fop {
 
-    // desired output format: MIME type such as "application/pdf", "application/postscript" etc.
+    // desired output format: MIME type such as "application/pdf",
+    // "application/postscript" etc.
     private String outputFormat = null;
 
     // output stream to send results to
@@ -57,15 +59,24 @@
     // FOTreeBuilder object to maintain reference for access to results
     private FOTreeBuilder foTreeBuilder = null;
 
+
+
     /**
-     * Constructor for use with already-created FOUserAgents. It uses MIME types to select the
-     * output format (ex. "application/pdf" for PDF).
-     * @param outputFormat the MIME type of the output format to use (ex. "application/pdf").
-     * @param ua FOUserAgent object
-     * @param stream the output stream
-     * @throws FOPException if setting up the DefaultHandler fails
+     * Constructor for use with already-created FOUserAgents. It uses MIME types
+     * to select the output format (ex. "application/pdf" for PDF).
+     *
+     * @param outputFormat
+     *            the MIME type of the output format to use (ex.
+     *            "application/pdf").
+     * @param ua
+     *            FOUserAgent object
+     * @param stream
+     *            the output stream
+     * @throws FOPException
+     *             if setting up the DefaultHandler fails
      */
-    Fop(String outputFormat, FOUserAgent ua, OutputStream stream) throws FOPException {
+    Fop(String outputFormat, FOUserAgent ua, OutputStream stream)
+            throws FOPException {
         this.outputFormat = outputFormat;
 
         foUserAgent = ua;
@@ -79,7 +90,9 @@
     }
 
     /**
-     * Get the FOUserAgent instance associated with the rendering run represented by this instance.
+     * Get the FOUserAgent instance associated with the rendering run
+     * represented by this instance.
+     *
      * @return the user agent
      */
     public FOUserAgent getUserAgent() {
@@ -87,40 +100,60 @@
     }
 
     /**
-     * Creates a DefaultHandler object used to generate the document.
-     * Note this object implements the ContentHandler interface.
-     * For processing with a Transformer object, this DefaultHandler object
-     * can be used in the SAXResult constructor.
-     * Alternatively, for processing with a SAXParser, this object can be
-     * used as the DefaultHandler argument to its parse() methods.
+     * Creates a DefaultHandler object used to generate the document. Note this
+     * object implements the ContentHandler interface. For processing with a
+     * Transformer object, this DefaultHandler object can be used in the
+     * SAXResult constructor. Alternatively, for processing with a SAXParser,
+     * this object can be used as the DefaultHandler argument to its parse()
+     * methods.
      *
-     * @throws FOPException if setting up the DefaultHandler fails
+     * @throws FOPException
+     *             if setting up the DefaultHandler fails
      */
     private void createDefaultHandler() throws FOPException {
-        this.foTreeBuilder = new FOTreeBuilder(outputFormat, foUserAgent, stream);
+        this.foTreeBuilder = new FOTreeBuilder(outputFormat, foUserAgent,
+                stream);
     }
 
+
+
+
     /**
-     * Returns the DefaultHandler object that will receive the SAX stream containing the
-     * FO document to be rendered.
+     * Returns the DefaultHandler object that will receive the SAX stream
+     * containing the FO document to be rendered.
+     *
      * @return the SAX DefaultHandler for handling the SAX events.
-     * @throws FOPException if setting up the DefaultHandler fails
+     * @throws FOPException
+     *             if setting up the DefaultHandler fails
      */
-    public DefaultHandler getDefaultHandler() throws FOPException {
+    public DefaultHandler getDefaultHandler() throws
+        FOPException {
+        DefaultHandler fopHandler = null;
+
         if (foTreeBuilder == null) {
             createDefaultHandler();
         }
-        return this.foTreeBuilder;
+        fopHandler = this.foTreeBuilder;
+        if (this.foUserAgent.accessibilityEnabled()) {
+            Source xsltFile = new StreamSource(getClass().getResource(
+                     "/org/apache/fop/accessibility/addPtr.xsl").toExternalForm());
+            DefaultHandler transformNode = new TransformerNodeEndProcessing(
+                 xsltFile, fopHandler, foUserAgent);
+            return transformNode;
+        } else {
+            return fopHandler;
+        }
     }
 
     /**
-     * Returns the results of the rendering process. Information includes
-     * the total number of pages generated and the number of pages per
+     * Returns the results of the rendering process. Information includes the
+     * total number of pages generated and the number of pages per
      * page-sequence. Call this method only after the rendering process is
      * finished. Note that the results are only available for output formats
      * which make use of FOP's layout engine (PDF, PS, etc.).
+     *
      * @return the results of the rendering process, or null for flow-oriented
-     * output formats like RTF and MIF.
+     *         output formats like RTF and MIF.
      */
     public FormattingResults getResults() {
         if (foTreeBuilder == null) {
Index: src/java/org/apache/fop/apps/FopFactory.java
===================================================================
--- src/java/org/apache/fop/apps/FopFactory.java	(revision 744229)
+++ src/java/org/apache/fop/apps/FopFactory.java	(working copy)
@@ -99,6 +99,11 @@
      *  external-graphics.
      */
     private String base = null;
+    
+    /**
+     *  Controls if accessibility is turned on or off
+     */
+    private boolean accessibility = false;
 
     /** The base URL for all hyphen URL resolutions. */
     private String hyphenBase = null;
@@ -181,10 +186,19 @@
      */
     public FOUserAgent newFOUserAgent() {
         FOUserAgent userAgent = new FOUserAgent(this);
+        userAgent.getRendererOptions().put("accessibility", Boolean.valueOf(this.accessibility));
         return userAgent;
     }
 
     /**
+     * Used for accessibility to pass value to newFOUserAgent
+     * @param value set through xconf file
+     */
+    void setAccessibility(boolean value) {
+        this.accessibility = value;
+    }
+    
+    /**
      * Returns a new {@link Fop} instance. FOP will be configured with a default user agent
      * instance.
      * <p>
Index: src/java/org/apache/fop/apps/FopFactoryConfigurator.java
===================================================================
--- src/java/org/apache/fop/apps/FopFactoryConfigurator.java	(revision 744229)
+++ src/java/org/apache/fop/apps/FopFactoryConfigurator.java	(working copy)
@@ -90,6 +90,21 @@
             log.debug("Initializing FopFactory Configuration");
         }
 
+        if (cfg.getChild("accessibility", false) != null) {
+            try {
+                String s = cfg.getChild("accessibility").getValue();
+                if ("true".equals(s)) {
+                    this.factory.setAccessibility(true);
+                } else if ("false".equals(s)) {
+                    this.factory.setAccessibility(false);
+                } else {
+                     throw new FOPException("Invalid value for accessibility");
+                }
+            } catch (ConfigurationException e) {
+                throw new FOPException(e);
+            }
+        } 
+        
         // strict configuration
         if (cfg.getChild("strict-configuration", false) != null) {
             try {
Index: src/java/org/apache/fop/area/AreaTreeParser.java
===================================================================
--- src/java/org/apache/fop/area/AreaTreeParser.java	(revision 744229)
+++ src/java/org/apache/fop/area/AreaTreeParser.java	(working copy)
@@ -127,11 +127,11 @@
 
     private static class Handler extends DefaultHandler {
 
-        private Map makers = new java.util.HashMap();
+        private final Map makers = new java.util.HashMap();
 
-        private AreaTreeModel treeModel;
-        private FOUserAgent userAgent;
-        private ElementMappingRegistry elementMappingRegistry;
+        private final AreaTreeModel treeModel;
+        private final FOUserAgent userAgent;
+        private final ElementMappingRegistry elementMappingRegistry;
 
         private Attributes lastAttributes;
 
@@ -139,14 +139,14 @@
         private boolean ignoreCharacters = true;
 
         private PageViewport currentPageViewport;
-        private Map pageViewportsByKey = new java.util.HashMap();
+        private final Map pageViewportsByKey = new java.util.HashMap();
         // set of "ID firsts" that have already been assigned to a PV:
-        private Set idFirstsAssigned = new java.util.HashSet();
+        private final Set idFirstsAssigned = new java.util.HashSet();
 
-        private Stack areaStack = new Stack();
+        private final Stack areaStack = new Stack();
         private boolean firstFlow;
 
-        private Stack delegateStack = new Stack();
+        private final Stack delegateStack = new Stack();
         private ContentHandler delegate;
         private DOMImplementation domImplementation;
 
@@ -839,7 +839,8 @@
 
             public void startElement(Attributes attributes) {
                 String url = attributes.getValue("url");
-                Image image = new Image(url);
+                //String ptr = attributes.getValue("ptr");
+                Image image = new Image(url/*, ptr*/);
                 transferForeignObjects(attributes, image);
                 setAreaAttributes(attributes, image);
                 setTraits(attributes, image, SUBSET_COMMON);
Index: src/java/org/apache/fop/area/Trait.java
===================================================================
--- src/java/org/apache/fop/area/Trait.java	(revision 744229)
+++ src/java/org/apache/fop/area/Trait.java	(working copy)
@@ -194,12 +194,16 @@
     public static final Integer OVERLINE_COLOR = new Integer(35);
     /** Trait for color of linethrough decorations when rendering inline parent. */
     public static final Integer LINETHROUGH_COLOR = new Integer(36);
+    
+    /** The ptr trait. Used for accessibility   */
+    public static final Integer PTR = new Integer(37);
 
     /** Maximum value used by trait keys */
-    public static final int MAX_TRAIT_KEY = 36;
+    public static final int MAX_TRAIT_KEY = 37;
 
     private static final TraitInfo[] TRAIT_INFO = new TraitInfo[MAX_TRAIT_KEY + 1];
 
+
     private static class TraitInfo {
         private String name;
         private Class clazz; // Class of trait data
@@ -225,6 +229,7 @@
     static {
         // Create a hashmap mapping trait code to name for external representation
         //put(ID_LINK, new TraitInfo("id-link", String.class));
+        put(PTR, new TraitInfo("ptr", String.class));
         put(INTERNAL_LINK, new TraitInfo("internal-link", InternalLink.class));
         put(EXTERNAL_LINK, new TraitInfo("external-link", ExternalLink.class));
         put(FONT,         new TraitInfo("font", FontTriplet.class));
@@ -277,7 +282,6 @@
                 new TraitInfo("is-reference-area", Boolean.class));
         put(IS_VIEWPORT_AREA,
                 new TraitInfo("is-viewport-area", Boolean.class));
-
     }
 
     /**
Index: src/java/org/apache/fop/area/inline/Image.java
===================================================================
--- src/java/org/apache/fop/area/inline/Image.java	(revision 744229)
+++ src/java/org/apache/fop/area/inline/Image.java	(working copy)
@@ -27,15 +27,18 @@
  * The url of the image is used as a key to reference the image cache.
  */
 public class Image extends Area {
-    private String url;
-    
+    private final String url;
+    //private String ptr; // used for accessibility
+
     /**
      * Create a new image with the given url.
      *
      * @param url the url of the image
+     * @param ptr used for accessibility
      */
-    public Image(String url) {
+    public Image(String url/*, String ptr*/) {
         this.url = url;
+    //    this.ptr = ptr;
     }
 
     /**
@@ -47,5 +50,14 @@
     public String getURL() {
         return this.url;
     }
+
+    /**
+     * Used for accessibility
+     * @return ptr of this image
+     */
+  //  public String getPtr() {
+  //      return ptr;
+  //  }
+
 }
 
Index: src/java/org/apache/fop/cli/CommandLineOptions.java
===================================================================
--- src/java/org/apache/fop/cli/CommandLineOptions.java	(revision 744229)
+++ src/java/org/apache/fop/cli/CommandLineOptions.java	(working copy)
@@ -327,6 +327,8 @@
                 i = i + parseAreaTreeOption(args, i);
             } else if (args[i].equals("-if")) {
                 i = i + parseIntermediateFormatOption(args, i);
+            } else if (args[i].equals("-a")) { 
+                this.renderingOptions.put("accessibility", Boolean.TRUE);
             } else if (args[i].equals("-v")) {
                 printVersion();
                 return false;
@@ -445,7 +447,8 @@
     }
 
     private int parsePDFOutputOption(String[] args, int i, String pdfAMode) throws FOPException {
-        setOutputMode(MimeConstants.MIME_PDF);
+//        setOutputMode(MimeConstants.MIME_PDF);
+        setOutputMode(MimeConstants.MIME_PDF + ";mode=painter");
         if ((i + 1 == args.length)
                 || (isOption(args[i + 1]))) {
             throw new FOPException("you must specify the PDF output file");
@@ -1129,6 +1132,7 @@
             + "  -nocopy           PDF file will be encrypted without copy content permission\n"
             + "  -noedit           PDF file will be encrypted without edit content permission\n"
             + "  -noannotations    PDF file will be encrypted without edit annotation permission\n"
+            + "  -a                enables PDF accessibility (default off)\n"
             + "  -pdfprofile prof  PDF file will be generated with the specified profile\n"
             + "                    (Examples for prof: PDF/A-1b or PDF/X-3:2003)\n\n"
             + " [INPUT]  \n"
Index: src/java/org/apache/fop/cli/InputHandler.java
===================================================================
--- src/java/org/apache/fop/cli/InputHandler.java	(revision 744229)
+++ src/java/org/apache/fop/cli/InputHandler.java	(working copy)
@@ -51,9 +51,6 @@
 import org.apache.fop.apps.Fop;
 import org.apache.fop.apps.FopFactory;
 import org.apache.fop.render.awt.viewer.Renderable;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
 
 /**
  * Class for handling files input from command line
Index: src/java/org/apache/fop/events/EventFormatter.xml
===================================================================
--- src/java/org/apache/fop/events/EventFormatter.xml	(revision 744229)
+++ src/java/org/apache/fop/events/EventFormatter.xml	(working copy)
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
     Licensed to the Apache Software Foundation (ASF) under one or more
     contributor license agreements.  See the NOTICE file distributed with
     this work for additional information regarding copyright ownership.
@@ -13,7 +14,9 @@
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
---><!-- $Id$ --><catalogue xml:lang="en">
+-->
+<!-- $Id$ -->
+<catalogue xml:lang="en">
   <message key="locator">[ (See position {loc})| (See {#gatherContextInfo})| (No context info available)]</message>
   <message key="rule.markerDescendantOfFlow">An fo:marker is permitted only as the descendant of an fo:flow.</message>
   <message key="rule.retrieveMarkerDescendantOfStaticContent">An fo:retrieve-marker is permitted only as the descendant of an fo:static-content.</message>
Index: src/java/org/apache/fop/fo/Constants.java
===================================================================
--- src/java/org/apache/fop/fo/Constants.java	(revision 744229)
+++ src/java/org/apache/fop/fo/Constants.java	(working copy)
@@ -771,8 +771,14 @@
      * multi-column layouts.
      */
     int PR_X_DISABLE_COLUMN_BALANCING = 273;
+    /** Property constant - FOP proprietary: FOP internal use for accessibility */
+    int PR_X_PTR = 274;
+    /** Property constant - FOP proprietary: alt text for fo:external-graphic, 
+     * used for accessibility */
+    int PR_X_ALT = 275;
+
     /** Number of property constants defined */
-    int PROPERTY_COUNT = 273;
+    int PROPERTY_COUNT = 275;
 
     // compound property constants
 
Index: src/java/org/apache/fop/fo/FONode.java
===================================================================
--- src/java/org/apache/fop/fo/FONode.java	(revision 744229)
+++ src/java/org/apache/fop/fo/FONode.java	(working copy)
@@ -36,7 +36,9 @@
 import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.fo.extensions.ExtensionAttachment;
 import org.apache.fop.fo.extensions.ExtensionElementMapping;
+import org.apache.fop.fo.extensions.InternalElementMapping;
 import org.apache.fop.fo.extensions.svg.SVGElementMapping;
+//import org.apache.fop.fo.extensions.InternalElementMapping;
 import org.apache.fop.fo.pagination.Root;
 import org.apache.fop.util.CharUtilities;
 import org.apache.fop.util.ContentHandlerFactory;
@@ -49,6 +51,7 @@
 
     /** the XSL-FO namespace URI */
     protected static final String FO_URI = FOElementMapping.URI;
+    
     /** FOP's proprietary extension namespace URI */
     protected static final String FOX_URI = ExtensionElementMapping.URI;
 
@@ -419,6 +422,8 @@
             return "fo:" + localName;
         } else if (namespaceURI.equals(ExtensionElementMapping.URI)) {
             return "fox:" + localName;
+        } else if (namespaceURI.equals(InternalElementMapping.URI)) {
+            return "foi:" + localName;  // used FOP internally for accessibility
         } else if (namespaceURI.equals(SVGElementMapping.URI)) {
             return "svg:" + localName;
         } else {
Index: src/java/org/apache/fop/fo/FOPropertyMapping.java
===================================================================
--- src/java/org/apache/fop/fo/FOPropertyMapping.java	(revision 744229)
+++ src/java/org/apache/fop/fo/FOPropertyMapping.java	(working copy)
@@ -1074,6 +1074,7 @@
         m.addShorthand(s_generics[PR_XML_LANG]);
         addPropertyMaker("language", m);
 
+        
         // script
         m  = new StringProperty.Maker(PR_SCRIPT);
         m.setInherited(true);
@@ -2514,6 +2515,18 @@
         m.setInherited(false);
         m.setDefault("");
         addPropertyMaker("id", m);
+        
+        // foi:ptr, used for accessibility
+        m = new StringProperty.Maker(PR_X_PTR);
+        m.setInherited(false);
+        m.setDefault("");
+        addPropertyMaker("foi:ptr", m);
+        
+        // fox:alt, used for accessibility
+        m = new StringProperty.Maker(PR_X_ALT);
+        m.setInherited(false);
+        m.setDefault("");
+        addPropertyMaker("fox:alt-text", m);
 
         // provisional-label-separation
         m  = new LengthProperty.Maker(PR_PROVISIONAL_LABEL_SEPARATION);
Index: src/java/org/apache/fop/fo/FOTreeBuilder.java
===================================================================
--- src/java/org/apache/fop/fo/FOTreeBuilder.java	(revision 744229)
+++ src/java/org/apache/fop/fo/FOTreeBuilder.java	(working copy)
@@ -39,6 +39,7 @@
 import org.apache.fop.area.AreaTreeHandler;
 import org.apache.fop.fo.ElementMapping.Maker;
 import org.apache.fop.fo.extensions.ExtensionElementMapping;
+//import org.apache.fop.fo.extensions.InternalElementMapping;
 import org.apache.fop.fo.pagination.Root;
 import org.apache.fop.util.ContentHandlerFactory;
 import org.apache.fop.util.ContentHandlerFactory.ObjectBuiltListener;
@@ -97,7 +98,6 @@
                 FOUserAgent foUserAgent,
                 OutputStream stream)
             throws FOPException {
-
         this.userAgent = foUserAgent;
         this.elementMappingRegistry = userAgent.getFactory().getElementMappingRegistry();
         //This creates either an AreaTreeHandler and ultimately a Renderer, or
@@ -263,7 +263,8 @@
                 }
             } else { // check that incoming node is valid for currentFObj
                 if (currentFObj.getNamespaceURI().equals(FOElementMapping.URI)
-                    || currentFObj.getNamespaceURI().equals(ExtensionElementMapping.URI)) {
+                    || currentFObj.getNamespaceURI().equals(ExtensionElementMapping.URI)
+                    /*|| currentFObj.getNamespaceURI().equals(InternalElementMapping.URI)*/ ) {
                     currentFObj.validateChildNode(locator, namespaceURI, localName);
                 }
             }
Index: src/java/org/apache/fop/fo/FObj.java
===================================================================
--- src/java/org/apache/fop/fo/FObj.java	(revision 744229)
+++ src/java/org/apache/fop/fo/FObj.java	(working copy)
@@ -33,6 +33,7 @@
 import org.apache.xmlgraphics.util.QName;
 
 import org.apache.fop.apps.FOPException;
+import org.apache.fop.fo.FONode.FONodeIterator;
 import org.apache.fop.fo.extensions.ExtensionAttachment;
 import org.apache.fop.fo.flow.Marker;
 import org.apache.fop.fo.properties.PropertyMaker;
Index: src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java
===================================================================
--- src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java	(revision 744229)
+++ src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java	(working copy)
@@ -46,6 +46,8 @@
         propertyAttributes.add("orphan-content-limit");
         propertyAttributes.add("internal-destination");
         propertyAttributes.add("disable-column-balancing");
+        //These are FOP's extension properties for accessibility
+        propertyAttributes.add("alt");
     }
 
     /**
Index: src/java/org/apache/fop/fo/extensions/ExternalDocument.java
===================================================================
--- src/java/org/apache/fop/fo/extensions/ExternalDocument.java	(revision 744229)
+++ src/java/org/apache/fop/fo/extensions/ExternalDocument.java	(working copy)
@@ -31,7 +31,7 @@
 import org.apache.fop.fo.properties.LengthRangeProperty;
 
 /**
- * Class for the fox:external-document extenstion element.
+ * Class for the fox:external-document extension element.
  */
 public class ExternalDocument extends AbstractPageSequence implements GraphicsProperties {
 
Index: src/java/org/apache/fop/fo/extensions/InternalElementMapping.java
===================================================================
--- src/java/org/apache/fop/fo/extensions/InternalElementMapping.java	(revision 0)
+++ src/java/org/apache/fop/fo/extensions/InternalElementMapping.java	(revision 0)
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: InternalElementMapping.java 679781 2008-07-25 12:44:20Z jeremias $ */
+
+package org.apache.fop.fo.extensions;
+
+import java.util.HashMap;
+import java.util.Set;
+
+import org.apache.xmlgraphics.util.QName;
+
+import org.apache.fop.fo.ElementMapping;
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.UnknownXMLObj;
+import org.apache.fop.fo.extensions.destination.Destination;
+
+/**
+ * Element mapping for FOP's internal extension to XSL-FO.
+ */
+public class InternalElementMapping extends ElementMapping {
+
+    /** The FOP extension namespace URI */
+    public static final String URI = "http://xmlgraphics.apache.org/fop/internal";
+
+   private static final Set propertyAttributes = new java.util.HashSet();
+
+   static {
+        //These are FOP's extension properties for accessibility
+        propertyAttributes.add("ptr");
+    }
+
+    /**
+     * Constructor.
+     */
+    public InternalElementMapping() {
+        namespaceURI = URI;
+    }
+
+    /**
+     * Initialize the data structures.
+     */
+    protected void initialize() {
+        if (foObjs == null) {
+            foObjs = new HashMap();
+        }
+    }
+
+    /* static class DestinationMaker extends ElementMapping.Maker {
+        public FONode make(FONode parent) {
+            return new Destination(parent);
+        }
+    } */
+
+    
+    /**
+     * used internally for accessibility
+     */
+    public String getStandardPrefix() {
+        return "foi";
+    }
+
+    /** {@inheritDoc} */
+    public boolean isAttributeProperty(QName attributeName) {
+        if (!URI.equals(attributeName.getNamespaceURI())) {
+            throw new IllegalArgumentException("The namespace URIs don't match");
+        }
+        return propertyAttributes.contains(attributeName.getLocalName());
+    }
+
+}
Index: src/java/org/apache/fop/fo/flow/AbstractGraphics.java
===================================================================
--- src/java/org/apache/fop/fo/flow/AbstractGraphics.java	(revision 744229)
+++ src/java/org/apache/fop/fo/flow/AbstractGraphics.java	(working copy)
@@ -60,6 +60,7 @@
     private int scaling;
     private int textAlign;
     private Length width;
+    private String ptr;   // used for accessibility
     // Unused but valid items, commented out for performance:
     //     private CommonAccessibility commonAccessibility;
     //     private CommonAural commonAural;
@@ -94,6 +95,7 @@
         dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
         height = pList.get(PR_HEIGHT).getLength();
         id = pList.get(PR_ID).getString();
+        ptr = pList.get(PR_X_PTR).getString();   // used for accessibility
         inlineProgressionDimension = pList.get(PR_INLINE_PROGRESSION_DIMENSION).getLengthRange();
         keepWithNext = pList.get(PR_KEEP_WITH_NEXT).getKeep();
         keepWithPrevious = pList.get(PR_KEEP_WITH_PREVIOUS).getKeep();
@@ -104,6 +106,12 @@
         width = pList.get(PR_WIDTH).getLength();
     }
 
+    /** @return the "foi:ptr" property.  */
+    public String getPtr() {
+        return ptr;
+    }
+    
+    
     /**
      * @return the "id" property.
      */
Index: src/java/org/apache/fop/fo/flow/AbstractListItemPart.java
===================================================================
--- src/java/org/apache/fop/fo/flow/AbstractListItemPart.java	(revision 744229)
+++ src/java/org/apache/fop/fo/flow/AbstractListItemPart.java	(working copy)
@@ -90,5 +90,7 @@
     public KeepProperty getKeepTogether() {
         return keepTogether;
     }
+
+    
 }
 
Index: src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java
===================================================================
--- src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java	(revision 744229)
+++ src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java	(working copy)
@@ -51,6 +51,7 @@
     private int alignmentBaseline;
     private Length baselineShift;
     private int dominantBaseline;
+    private String ptr;  // used for accessibility
     // private ToBeImplementedProperty letterSpacing;
     private SpaceProperty lineHeight;
     private String refId;
@@ -96,6 +97,7 @@
         dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
         // letterSpacing = pList.get(PR_LETTER_SPACING);
         lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
+        ptr = pList.get(PR_X_PTR).getString();   // used for accessibility
         refId = pList.get(PR_REF_ID).getString();
         textDecoration = pList.getTextDecorationProps();
         // textShadow = pList.get(PR_TEXT_SHADOW);
@@ -138,6 +140,11 @@
         return textDecoration;
     }
 
+    /** @return the "foi:ptr" property.  */
+    public String getPtr() {
+        return ptr;
+    }
+    
     /** @return the "alignment-adjust" property */
     public Length getAlignmentAdjust() {
         return alignmentAdjust;
Index: src/java/org/apache/fop/fo/flow/BasicLink.java
===================================================================
--- src/java/org/apache/fop/fo/flow/BasicLink.java	(revision 744229)
+++ src/java/org/apache/fop/fo/flow/BasicLink.java	(working copy)
@@ -65,6 +65,7 @@
     /** {@inheritDoc} */
     public void bind(PropertyList pList) throws FOPException {
         super.bind(pList);
+
         // destinationPlacementOffset = pList.get(PR_DESTINATION_PLACEMENT_OFFSET);
         externalDestination = pList.get(PR_EXTERNAL_DESTINATION).getString();
         // indicateDestination = pList.get(PR_INDICATE_DESTINATION);
@@ -83,6 +84,11 @@
         }
     }
 
+    /** @return the "fox:ptr" property.  */
+    public String getPtr() {
+        return super.getPtr();
+    }
+
     /** {@inheritDoc} */
     protected void startOfNode() throws FOPException {
         super.startOfNode();
Index: src/java/org/apache/fop/fo/flow/Block.java
===================================================================
--- src/java/org/apache/fop/fo/flow/Block.java	(revision 744229)
+++ src/java/org/apache/fop/fo/flow/Block.java	(working copy)
@@ -71,6 +71,7 @@
     private int lineHeightShiftAdjustment;
     private int lineStackingStrategy;
     private Numeric orphans;
+    private String ptr;  //used for accessibility
     private int whiteSpaceTreatment;
     private int span;
     private int textAlign;
@@ -80,6 +81,7 @@
     private Numeric widows;
     private int wrapOption;
     private int disableColumnBalancing;
+    private String xmlLang;
     // Unused but valid items, commented out for performance:
     //     private CommonAccessibility commonAccessibility;
     //     private CommonAural commonAural;
@@ -122,6 +124,7 @@
         lineHeightShiftAdjustment = pList.get(PR_LINE_HEIGHT_SHIFT_ADJUSTMENT).getEnum();
         lineStackingStrategy = pList.get(PR_LINE_STACKING_STRATEGY).getEnum();
         orphans = pList.get(PR_ORPHANS).getNumeric();
+        ptr = pList.get(PR_X_PTR).getString();  //used for accessibility
         whiteSpaceTreatment = pList.get(PR_WHITE_SPACE_TREATMENT).getEnum();
         span = pList.get(PR_SPAN).getEnum();
         textAlign = pList.get(PR_TEXT_ALIGN).getEnum();
@@ -131,6 +134,7 @@
         widows = pList.get(PR_WIDOWS).getNumeric();
         wrapOption = pList.get(PR_WRAP_OPTION).getEnum();
         disableColumnBalancing = pList.get(PR_X_DISABLE_COLUMN_BALANCING).getEnum();
+        xmlLang = pList.get(PR_XML_LANG).getString();
     }
 
     /** {@inheritDoc} */
@@ -171,6 +175,17 @@
         return breakAfter;
     }
 
+    /** @return the "foi:ptr" property.  */
+    public String getPtr() {
+        return ptr;
+    }
+    
+    
+    /** @return the "xml:lang" property. */
+    public String getXmlLang() {
+        return xmlLang;
+    }
+    
     /** @return the "break-before" property. */
     public int getBreakBefore() {
         return breakBefore;
Index: src/java/org/apache/fop/fo/flow/BlockContainer.java
===================================================================
--- src/java/org/apache/fop/fo/flow/BlockContainer.java	(revision 744229)
+++ src/java/org/apache/fop/fo/flow/BlockContainer.java	(working copy)
@@ -101,7 +101,7 @@
         super.startOfNode();
         getFOEventHandler().startBlockContainer(this);
     }
-
+    
     /**
      * {@inheritDoc}
      * <br>XSL Content Model: marker* (%block;)+
Index: src/java/org/apache/fop/fo/flow/Character.java
===================================================================
--- src/java/org/apache/fop/fo/flow/Character.java	(revision 744229)
+++ src/java/org/apache/fop/fo/flow/Character.java	(working copy)
@@ -62,6 +62,7 @@
     private CommonTextDecoration textDecoration;
     // private ToBeImplementedProperty textShadow;
     private Property wordSpacing;
+    private String ptr;  // used for accessibility
     // Unused but valid items, commented out for performance:
     //     private CommonAural commonAural;
     //     private CommonMarginInline commonMarginInline;
@@ -108,8 +109,14 @@
         lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
         textDecoration = pList.getTextDecorationProps();
         wordSpacing = pList.get(PR_WORD_SPACING);
+        ptr = pList.get(PR_X_PTR).getString();  // used for accessibility
     }
-
+    
+    /** @return the "fox:ptr" property.  */
+    public String getPtr() {
+        return ptr;
+    }
+    
     /** {@inheritDoc} */
     protected void startOfNode() throws FOPException {
         super.startOfNode();
Index: src/java/org/apache/fop/fo/flow/Footnote.java
===================================================================
--- src/java/org/apache/fop/fo/flow/Footnote.java	(revision 744229)
+++ src/java/org/apache/fop/fo/flow/Footnote.java	(working copy)
@@ -53,7 +53,7 @@
     public void bind(PropertyList pList) throws FOPException {
         // No active properties -> do nothing.
     }
-
+    
     /** {@inheritDoc} */
     protected void startOfNode() throws FOPException {
         getFOEventHandler().startFootnote(this);
Index: src/java/org/apache/fop/fo/flow/FootnoteBody.java
===================================================================
--- src/java/org/apache/fop/fo/flow/FootnoteBody.java	(revision 744229)
+++ src/java/org/apache/fop/fo/flow/FootnoteBody.java	(working copy)
@@ -33,10 +33,11 @@
  * <code>fo:footnote-body</code></a> object.
  */
 public class FootnoteBody extends FObj {
-    // The value of properties relevant for fo:footnote-body (commented out for perforance).
+    // The value of properties relevant for fo:footnote-body (commented out for performance).
     //     private CommonAccessibility commonAccessibility;
     // End of property values
 
+    
     /**
      * Base constructor
      *
@@ -49,7 +50,9 @@
     /** {@inheritDoc} */
     public void bind(PropertyList pList) throws FOPException {
     }
+    
 
+
     /** {@inheritDoc} */
     protected void startOfNode() throws FOPException {
         getFOEventHandler().startFootnoteBody(this);
Index: src/java/org/apache/fop/fo/flow/Inline.java
===================================================================
--- src/java/org/apache/fop/fo/flow/Inline.java	(revision 744229)
+++ src/java/org/apache/fop/fo/flow/Inline.java	(working copy)
@@ -37,6 +37,7 @@
     private Length alignmentAdjust;
     private int alignmentBaseline;
     private Length baselineShift;
+    private String ptr;  // used for accessibility
     private int dominantBaseline;
     // Unused but valid items, commented out for performance:
     //     private CommonRelativePosition commonRelativePosition;
@@ -66,6 +67,7 @@
         alignmentBaseline = pList.get(PR_ALIGNMENT_BASELINE).getEnum();
         baselineShift = pList.get(PR_BASELINE_SHIFT).getLength();
         dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
+        ptr = pList.get(PR_X_PTR).getString(); // used for accessibility
     }
 
     /** {@inheritDoc} */
@@ -149,6 +151,11 @@
         return "inline";
     }
 
+    /** @return the "foi:ptr" property.  */
+    public String getPtr() {
+        return ptr;
+    }
+
     /**
      * {@inheritDoc}
      * @return {@link org.apache.fop.fo.Constants#FO_INLINE}
Index: src/java/org/apache/fop/fo/flow/ListBlock.java
===================================================================
--- src/java/org/apache/fop/fo/flow/ListBlock.java	(revision 744229)
+++ src/java/org/apache/fop/fo/flow/ListBlock.java	(working copy)
@@ -132,7 +132,7 @@
     public CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
         return commonBorderPaddingBackground;
     }
-
+    
     /** @return the "break-after" property */
     public int getBreakAfter() {
         return breakAfter;
Index: src/java/org/apache/fop/fo/flow/ListItem.java
===================================================================
--- src/java/org/apache/fop/fo/flow/ListItem.java	(revision 744229)
+++ src/java/org/apache/fop/fo/flow/ListItem.java	(working copy)
@@ -138,7 +138,7 @@
     public CommonMarginBlock getCommonMarginBlock() {
         return commonMarginBlock;
     }
-
+    
     /** @return the {@link CommonBorderPaddingBackground} */
     public CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
         return commonBorderPaddingBackground;
Index: src/java/org/apache/fop/fo/flow/Marker.java
===================================================================
--- src/java/org/apache/fop/fo/flow/Marker.java	(revision 744229)
+++ src/java/org/apache/fop/fo/flow/Marker.java	(working copy)
@@ -19,7 +19,6 @@
 
 package org.apache.fop.fo.flow;
 
-import java.util.Collections;
 import java.util.Map;
 
 import org.xml.sax.Attributes;
@@ -65,12 +64,11 @@
         }
 
         markerClassName = pList.get(PR_MARKER_CLASS_NAME).getString();
-
         if (markerClassName == null || markerClassName.equals("")) {
             missingPropertyError("marker-class-name");
         }
     }
-
+    
     /**
      * Retrieve the property list of the given {@link FONode}
      * descendant
Index: src/java/org/apache/fop/fo/flow/PageNumber.java
===================================================================
--- src/java/org/apache/fop/fo/flow/PageNumber.java	(revision 744229)
+++ src/java/org/apache/fop/fo/flow/PageNumber.java	(working copy)
@@ -47,6 +47,7 @@
     private int alignmentBaseline;
     private Length baselineShift;
     private int dominantBaseline;
+    private String ptr; // used for accessibility
     // private ToBeImplementedProperty letterSpacing;
     private SpaceProperty lineHeight;
     /** Holds the text decoration values. May be null */
@@ -92,6 +93,7 @@
         // letterSpacing = pList.get(PR_LETTER_SPACING);
         lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
         textDecoration = pList.getTextDecorationProps();
+        ptr = pList.get(PR_X_PTR).getString(); // used for accessibility
         // textShadow = pList.get(PR_TEXT_SHADOW);
 
         // implicit properties
@@ -109,6 +111,11 @@
         getFOEventHandler().endPageNumber(this);
     }
 
+    /** @return the "foi:ptr" property.  */
+    public String getPtr() {
+        return ptr;
+    }
+    
     /**
      * {@inheritDoc}
      * <br>XSL Content Model: empty
Index: src/java/org/apache/fop/fo/flow/Wrapper.java
===================================================================
--- src/java/org/apache/fop/fo/flow/Wrapper.java	(revision 744229)
+++ src/java/org/apache/fop/fo/flow/Wrapper.java	(working copy)
@@ -26,6 +26,7 @@
 import org.apache.fop.fo.FONode;
 import org.apache.fop.fo.FOText;
 import org.apache.fop.fo.FObjMixed;
+import org.apache.fop.fo.PropertyList;
 import org.apache.fop.fo.ValidationException;
 
 /**
@@ -51,6 +52,11 @@
         super(parent);
     }
 
+    /** {@inheritDoc} */
+    public void bind(PropertyList pList) throws FOPException {
+        super.bind(pList);
+    }
+    
     /**
      * {@inheritDoc}
      * <br>XSL Content Model: marker* (#PCDATA|%inline;|%block;)*
Index: src/java/org/apache/fop/fo/flow/table/TableFObj.java
===================================================================
--- src/java/org/apache/fop/fo/flow/table/TableFObj.java	(revision 744229)
+++ src/java/org/apache/fop/fo/flow/table/TableFObj.java	(working copy)
@@ -46,6 +46,7 @@
     private Numeric borderBeforePrecedence;
     private Numeric borderEndPrecedence;
     private Numeric borderStartPrecedence;
+    private String ptr;
 
     ConditionalBorder borderBefore;
     ConditionalBorder borderAfter;
@@ -71,6 +72,7 @@
         borderBeforePrecedence = pList.get(PR_BORDER_BEFORE_PRECEDENCE).getNumeric();
         borderEndPrecedence = pList.get(PR_BORDER_END_PRECEDENCE).getNumeric();
         borderStartPrecedence = pList.get(PR_BORDER_START_PRECEDENCE).getNumeric();
+        ptr = pList.get(PR_X_PTR).getString();
         if (getNameId() != FO_TABLE //Separate check for fo:table in Table.java
                 && getNameId() != FO_TABLE_CELL
                 && getCommonBorderPaddingBackground().hasPadding(
@@ -235,6 +237,11 @@
         }
     }
 
+    /** @return the "foi:ptr" property.  */
+    public String getPtr() {
+        return ptr;
+    }
+    
     /**
      * Prepares the borders of this element if the collapsing-border model is in use.
      * Conflict resolution with parent elements is done where applicable.
Index: src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java	(revision 744229)
+++ src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java	(working copy)
@@ -385,6 +385,7 @@
 
         addMarkersToPage(false, isFirst(firstPos), isLast(lastPos));
 
+        TraitSetter.addPtr(curBlockArea, getBlockFO().getPtr());  // used for accessibility
         TraitSetter.addSpaceBeforeAfter(curBlockArea, layoutContext.getSpaceAdjust(),
                 effSpaceBefore, effSpaceAfter);
         flush();
Index: src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java	(revision 744229)
+++ src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java	(working copy)
@@ -95,7 +95,7 @@
         pageSequenceAreaObject.setLanguage(getPageSequence().getLanguage());
         pageSequenceAreaObject.setCountry(getPageSequence().getCountry());
         areaTreeModel.startPageSequence(pageSequenceAreaObject);
-        if (log.isDebugEnabled()) {
+         if (log.isDebugEnabled()) {
             log.debug("Starting layout");
         }
 
Index: src/java/org/apache/fop/layoutmgr/TraitSetter.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/TraitSetter.java	(revision 744229)
+++ src/java/org/apache/fop/layoutmgr/TraitSetter.java	(working copy)
@@ -584,6 +584,17 @@
     }
 
     /**
+     * Adds the ptr trait to the area.
+     * @param area the area to set the traits on
+     * @param ptr string
+     */
+    public static void addPtr(Area area, String ptr) {
+        if (ptr != null && ptr.length() > 0) {
+            area.addTrait(Trait.PTR, ptr);
+        }
+    }
+    
+    /**
      * Sets the producer's ID as a trait on the area. This can be used to track back the
      * generating FO node.
      * @param area the area to set the traits on
Index: src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java	(revision 744229)
+++ src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java	(working copy)
@@ -39,6 +39,7 @@
  */
 public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManager {
 
+    
     /**
      * Constructor.
      *
@@ -85,6 +86,7 @@
         transferForeignAttributes(viewportArea);
 
         Viewport vp = new Viewport(viewportArea);
+        TraitSetter.addPtr(vp, fobj.getPtr());  // used for accessibility
         TraitSetter.setProducerID(vp, fobj.getId());
         vp.setIPD(imageLayout.getViewportSize().width);
         vp.setBPD(imageLayout.getViewportSize().height);
@@ -102,6 +104,9 @@
         return vp;
     }
 
+
+    
+    
     /** {@inheritDoc} */
     public List getNextKnuthElements(LayoutContext context,
                                            int alignment) {
Index: src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java	(revision 744229)
+++ src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java	(working copy)
@@ -138,6 +138,7 @@
         text.setBaselineOffset(font.getAscender());
         TraitSetter.addFontTraits(text, font);
         text.addTrait(Trait.COLOR, fobj.getColor());
+        TraitSetter.addPtr(text, fobj.getPtr());   // used for accessibility
         TraitSetter.addTextDecoration(text, fobj.getTextDecoration());
     }
 
Index: src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java	(revision 744229)
+++ src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java	(working copy)
@@ -56,6 +56,7 @@
     private void setupBasicLinkArea(InlineArea area) {
         BasicLink fobj = (BasicLink) this.fobj;
         // internal destinations take precedence:
+        area.addTrait(Trait.PTR, fobj.getPtr());  // used for accessibility
         if (fobj.hasInternalDestination()) {
             String idref = fobj.getInternalDestination();
             PageSequenceLayoutManager pslm = getPSLM();
Index: src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java	(revision 744229)
+++ src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java	(working copy)
@@ -86,6 +86,7 @@
         }
         TraitSetter.setProducerID(text, node.getId());
         TraitSetter.addTextDecoration(text, node.getTextDecoration());
+        TraitSetter.addPtr(text, node.getPtr()); // used for accessibility
         return text;
     }
 
Index: src/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java	(revision 744229)
+++ src/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java	(working copy)
@@ -41,8 +41,8 @@
     }
 
     /** {@inheritDoc} */
-    protected Area getChildArea() {
-        return new Image(((ExternalGraphic) fobj).getSrc());
+    protected Area getChildArea() {                         // used for accessibility
+        return new Image(((ExternalGraphic) fobj).getSrc()/*, ((ExternalGraphic) fobj).getPtr()*/);
     }
 
 }
Index: src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java	(revision 744229)
+++ src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java	(working copy)
@@ -85,9 +85,8 @@
         text.setBaselineOffset(font.getAscender());
         TraitSetter.addFontTraits(text, font);
         text.addTrait(Trait.COLOR, fobj.getColor());
-
+        TraitSetter.addPtr(text, fobj.getPtr()); // used for accessibility
         TraitSetter.addTextDecoration(text, fobj.getTextDecoration());
-
         return text;
     }
 
Index: src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java	(revision 744229)
+++ src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java	(working copy)
@@ -27,8 +27,10 @@
 import org.apache.commons.logging.LogFactory;
 import org.apache.fop.area.Trait;
 import org.apache.fop.area.inline.TextArea;
+import org.apache.fop.area.Block;  // ??
 import org.apache.fop.fo.Constants;
 import org.apache.fop.fo.FOText;
+import org.apache.fop.fo.FObj;
 import org.apache.fop.fonts.Font;
 import org.apache.fop.fonts.FontSelector;
 import org.apache.fop.layoutmgr.InlineKnuthSequence;
@@ -504,12 +506,27 @@
         }
         TraitSetter.addFontTraits(textArea, font);
         textArea.addTrait(Trait.COLOR, this.foText.getColor());
-
+        textArea.addTrait(Trait.PTR, getPtr());  // used for accessibility
         TraitSetter.addTextDecoration(textArea, this.foText.getTextDecoration());
-
         return textArea;
     }
 
+    /**
+     * used for accessibility
+     * @return ptr of fobj
+     */
+    private String getPtr() {
+        FObj fobj = this.parentLM.getFObj();
+        if (fobj instanceof org.apache.fop.fo.flow.Block) {
+            return (((org.apache.fop.fo.flow.Block) fobj).getPtr());
+        } else if (fobj instanceof org.apache.fop.fo.flow.Inline) {
+            return (((org.apache.fop.fo.flow.Inline) fobj).getPtr());
+        } else {
+            log.warn("Accessibility: TLM.getPtr-no Ptr found");
+            return "";
+        }
+    }
+    
     private void addToLetterAdjust(final int index, final int width) {
         if (this.letterAdjustArray[index] == null) {
             this.letterAdjustArray[index] = new MinOptMax(width);
Index: src/java/org/apache/fop/pdf/PDFArray.java
===================================================================
--- src/java/org/apache/fop/pdf/PDFArray.java	(revision 744229)
+++ src/java/org/apache/fop/pdf/PDFArray.java	(working copy)
@@ -107,6 +107,15 @@
     }
 
     /**
+     * Used for accessibility
+     * @param obj searched
+     * @return boolean indicating if obj is contained or not
+     */
+    public boolean contains(Object obj) {
+        return this.values.contains(obj);
+    }
+    
+    /**
      * Returns the length of the array
      * @return the length of the array
      */
Index: src/java/org/apache/fop/pdf/PDFDocument.java
===================================================================
--- src/java/org/apache/fop/pdf/PDFDocument.java	(revision 744229)
+++ src/java/org/apache/fop/pdf/PDFDocument.java	(working copy)
@@ -75,14 +75,16 @@
     /** Integer constant to represent PDF 1.4 */
     public static final int PDF_VERSION_1_4 = 4;
 
+
     /** the encoding to use when converting strings to PDF commands */
+
     public static final String ENCODING = "ISO-8859-1";
 
     /** the counter for object numbering */
     protected int objectcount = 0;
 
     /** the logger instance */
-    private Log log = LogFactory.getLog("org.apache.fop.pdf");
+    private final Log log = LogFactory.getLog("org.apache.fop.pdf");
 
     /** the current character position */
     private int position = 0;
@@ -91,40 +93,40 @@
     private int xref;
 
     /** the character position of each object */
-    private List location = new ArrayList();
+    private final List location = new ArrayList();
 
     /** List of objects to write in the trailer */
-    private List trailerObjects = new ArrayList();
+    private final List trailerObjects = new ArrayList();
 
     /** the objects themselves */
-    private List objects = new LinkedList();
+    private final List objects = new LinkedList();
 
     /** Indicates what PDF version is active */
-    private int pdfVersion = PDF_VERSION_1_4;
+    private final int pdfVersion = PDF_VERSION_1_4;
 
     /** Indicates which PDF profiles are active (PDF/A, PDF/X etc.) */
-    private PDFProfile pdfProfile = new PDFProfile(this);
+    private final PDFProfile pdfProfile = new PDFProfile(this);
 
     /** the /Root object */
-    private PDFRoot root;
+    private final PDFRoot root;
 
     /** The root outline object */
     private PDFOutline outlineRoot = null;
 
     /** The /Pages object (mark-fop@inomial.com) */
-    private PDFPages pages;
+    private final PDFPages pages;
 
     /** the /Info object */
-    private PDFInfo info;
+    private final PDFInfo info;
 
     /** the /Resources object */
-    private PDFResources resources;
+    private final PDFResources resources;
 
     /** the document's encryption, if it exists */
     private PDFEncryption encryption;
 
     /** the colorspace (0=RGB, 1=CMYK) */
-    private PDFDeviceColorSpace colorspace =
+    private final PDFDeviceColorSpace colorspace =
         new PDFDeviceColorSpace(PDFDeviceColorSpace.DEVICE_RGB);
 
     /** the counter for Pattern name numbering (e.g. 'Pattern1') */
@@ -138,43 +140,43 @@
 
     /** the {@link PDFXObject}s map */
     /* TODO: Should be modified (works only for image subtype) */
-    private Map xObjectsMap = new HashMap();
+    private final Map xObjectsMap = new HashMap();
 
     /** The {@link PDFFont} map */
-    private Map fontMap = new HashMap();
+    private final Map fontMap = new HashMap();
 
     /** The {@link PDFFilter} map */
     private Map filterMap = new HashMap();
 
     /** List of {@link PDFGState}s. */
-    private List gstates = new ArrayList();
+    private final List gstates = new ArrayList();
 
     /** List of {@link PDFFunction}s. */
-    private List functions = new ArrayList();
+    private final List functions = new ArrayList();
 
     /** List of {@link PDFShading}s. */
-    private List shadings = new ArrayList();
+    private final List shadings = new ArrayList();
 
     /** List of {@link PDFPattern}s. */
-    private List patterns = new ArrayList();
+    private final List patterns = new ArrayList();
 
     /** List of {@link PDFLink}s. */
-    private List links = new ArrayList();
+    private final List links = new ArrayList();
 
     /** List of {@link PDFDestination}s. */
     private List destinations;
 
     /** List of {@link PDFFileSpec}s. */
-    private List filespecs = new ArrayList();
+    private final List filespecs = new ArrayList();
 
     /** List of {@link PDFGoToRemote}s. */
-    private List gotoremotes = new ArrayList();
+    private final List gotoremotes = new ArrayList();
 
     /** List of {@link PDFGoTo}s. */
-    private List gotos = new ArrayList();
+    private final List gotos = new ArrayList();
 
     /** List of {@link PDFLaunch}es. */
-    private List launches = new ArrayList();
+    private final List launches = new ArrayList();
 
     /**
      * The PDFDests object for the name dictionary.
@@ -182,9 +184,9 @@
      */
     private PDFDests dests;
 
-    private PDFFactory factory;
+    private final PDFFactory factory;
 
-    private boolean encodingOnTheFly = true;
+    private final boolean encodingOnTheFly = true;
 
     /**
      * Creates an empty PDF document.
@@ -206,15 +208,17 @@
         this.pages = getFactory().makePages();
 
         // Create the Root object
-        this.root = getFactory().makeRoot(this.pages);
+        this.root = getFactory().makeRoot(pages);
 
         // Create the Resources object
         this.resources = getFactory().makeResources();
 
         // Make the /Info record
         this.info = getFactory().makeInfo(prod);
+
     }
 
+
     /**
      * @return the integer representing the active PDF version
      *          (one of PDFDocument.PDF_VERSION_*)
@@ -470,7 +474,6 @@
      */
     public void addTrailerObject(PDFObject obj) {
         this.trailerObjects.add(obj);
-
         if (obj instanceof PDFGoTo) {
             this.gotos.add(obj);
         }
@@ -1068,4 +1071,5 @@
         return pdfBytes.length;
     }
 
+
 }
Index: src/java/org/apache/fop/pdf/PDFFactory.java
===================================================================
--- src/java/org/apache/fop/pdf/PDFFactory.java	(revision 744229)
+++ src/java/org/apache/fop/pdf/PDFFactory.java	(working copy)
@@ -65,9 +65,9 @@
  */
 public class PDFFactory {
 
-    private PDFDocument document;
+    private final PDFDocument document;
 
-    private Log log = LogFactory.getLog(PDFFactory.class);
+    private final Log log = LogFactory.getLog(PDFFactory.class);
 
     /**
      * Creates a new PDFFactory.
@@ -94,6 +94,7 @@
      *
      * @param pages the pages pdf object that the root points to
      * @return the new pdf root object for this document
+     *
      */
     public PDFRoot makeRoot(PDFPages pages) {
         //Make a /Pages object. This object is written in the trailer.
@@ -177,19 +178,19 @@
      * @param pageWidth width of the page in points
      * @param pageHeight height of the page in points
      * @param pageIndex index of the page (zero-based)
+     * @param currentPageParentKey used for accessibility
      *
      * @return the created /Page object
      */
     public PDFPage makePage(PDFResources resources,
-                            int pageWidth, int pageHeight, int pageIndex) {
-
+                            int pageWidth, int pageHeight, int pageIndex,
+                            int currentPageParentKey) {
         /*
          * create a PDFPage with the next object number, the given
          * resources, contents and dimensions
          */
-        PDFPage page = new PDFPage(resources,
-                                   pageWidth, pageHeight, pageIndex);
-
+        PDFPage page = new PDFPage(resources,                       // old numPages
+                                   pageWidth, pageHeight, pageIndex, currentPageParentKey);
         getDocument().assignObjectNumber(page);
         getDocument().getPages().addPage(page);
         return page;
@@ -203,12 +204,14 @@
      * @param resources resources object to use
      * @param pageWidth width of the page in points
      * @param pageHeight height of the page in points
+     * @param currentPageParentKey used for accessibility
      *
      * @return the created /Page object
      */
     public PDFPage makePage(PDFResources resources,
-                            int pageWidth, int pageHeight) {
-        return makePage(resources, pageWidth, pageHeight, -1);
+                            int pageWidth, int pageHeight,
+                            int currentPageParentKey) {
+        return makePage(resources, pageWidth, pageHeight, -1,  currentPageParentKey);
     }
 
     /* ========================= functions ================================= */
@@ -868,6 +871,17 @@
     }
 
     /**
+     * Used for accessibility
+     * @return structure Tree Root element
+     */
+    public PDFStructTreeRoot makeStructTreeRoot() {
+        PDFStructTreeRoot structTreeRoot = new PDFStructTreeRoot();
+        getDocument().assignObjectNumber(structTreeRoot);
+        getDocument().addTrailerObject(structTreeRoot);
+        return structTreeRoot;
+    }
+
+    /**
      * Make a the head object of the name dictionary (the /Dests object).
      *
      * @param destinationList a list of PDFDestination instances
Index: src/java/org/apache/fop/pdf/PDFLink.java
===================================================================
--- src/java/org/apache/fop/pdf/PDFLink.java	(revision 744229)
+++ src/java/org/apache/fop/pdf/PDFLink.java	(working copy)
@@ -42,6 +42,7 @@
     private float bry;
     private String color;
     private PDFAction action;
+    private String structParent = "";
 
     /**
      * create objects associated with a link annotation (GoToR)
@@ -68,7 +69,16 @@
         this.action = action;
     }
 
+    
     /**
+     * Used for accessibility
+     * @param mcid of this structParent
+     */
+    public void setStructParent(int mcid) {
+        this.structParent = "/StructParent " + String.valueOf(mcid) + "\n";
+    }
+    
+    /**
      * {@inheritDoc}
      */
     public String toPDFString() {
@@ -87,6 +97,7 @@
                    + (brx) + " " + (bry) + " ]\n" + "/C [ "
                    + this.color + " ]\n" + "/Border [ 0 0 0 ]\n" + "/A "
                    + this.action.getAction() + "\n" + "/H /I\n"
+                   + this.structParent 
                    + fFlag + "\n>>\nendobj\n";
         return s;
     }
Index: src/java/org/apache/fop/pdf/PDFPage.java
===================================================================
--- src/java/org/apache/fop/pdf/PDFPage.java	(revision 744229)
+++ src/java/org/apache/fop/pdf/PDFPage.java	(working copy)
@@ -42,9 +42,10 @@
      * @param pageWidth the page's width in points
      * @param pageHeight the page's height in points
      * @param pageIndex the page's zero-based index (or -1 if the page number is auto-determined)
+     * @param structParents used for accessibility
      */
     public PDFPage(PDFResources resources, PDFStream contents,
-                   int pageWidth, int pageHeight, int pageIndex) {
+                   int pageWidth, int pageHeight, int pageIndex, int structParents) {
 
         /* generic creation of object */
         super(resources);
@@ -54,6 +55,10 @@
         setContents(contents);
         setSimplePageSize(pageWidth, pageHeight);
         this.pageIndex = pageIndex;
+        if (structParents > -1) {
+            put("StructParents", structParents);
+            put("Tabs", new PDFName("S"));
+        }
     }
 
     /**
@@ -63,10 +68,11 @@
      * @param pageWidth the page's width in points
      * @param pageHeight the page's height in points
      * @param pageIndex the page's zero-based index (or -1 if the page number is auto-determined)
+     * @param structParents used for accessibility
      */
     public PDFPage(PDFResources resources,
-                   int pageWidth, int pageHeight, int pageIndex) {
-        this(resources, null, pageWidth, pageHeight, pageIndex);
+                   int pageWidth, int pageHeight, int pageIndex, int structParents) {
+        this(resources, null, pageWidth, pageHeight, pageIndex, structParents);
     }
 
     private void setSimplePageSize(int width, int height) {
Index: src/java/org/apache/fop/pdf/PDFParentTree.java
===================================================================
--- src/java/org/apache/fop/pdf/PDFParentTree.java	(revision 0)
+++ src/java/org/apache/fop/pdf/PDFParentTree.java	(revision 0)
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf;
+
+/**
+ * Class representing a PDF /ParentTree
+ */
+public class PDFParentTree extends PDFNumberTreeNode {  
+    
+    /**
+     * Create the /ParentTree NumberTreeNode
+     */
+    public PDFParentTree() {
+        super();
+    }
+    
+    /**
+     * get the parentTree
+     * @return parentTree as PDFNumsArray
+     */
+    public PDFNumsArray getNums() {
+        PDFNumsArray nums = super.getNums();
+        if (nums == null) {
+            nums = new PDFNumsArray(this);
+            setNums(nums);
+        }
+        return nums;
+    }
+}
+
+
+
+
Index: src/java/org/apache/fop/pdf/PDFRoot.java
===================================================================
--- src/java/org/apache/fop/pdf/PDFRoot.java	(revision 744229)
+++ src/java/org/apache/fop/pdf/PDFRoot.java	(working copy)
@@ -19,6 +19,7 @@
 
 package org.apache.fop.pdf;
 
+
 /**
  * Class representing a Root (/Catalog) object.
  */
@@ -51,6 +52,8 @@
         new PDFName("FullScreen"),
     };
 
+
+
     /**
      * create a Root (/Catalog) object. NOTE: The PDFRoot
      * object must be created before the PDF document is
@@ -63,7 +66,7 @@
      */
     public PDFRoot(int objnum, PDFPages pages) {
         super();
-        setObjectNumber(objnum);
+         setObjectNumber(objnum);
         put("Type", new PDFName("Catalog"));
         setRootPages(pages);
     }
@@ -252,4 +255,25 @@
         put("Lang", lang);
     }
 
-}
+    /**
+     * Used for accessibility
+     * @param structTreeRoot of this document
+     */
+
+    public void setStructTreeRoot(PDFStructTreeRoot structTreeRoot) {
+        if (structTreeRoot == null) {
+            throw new NullPointerException("structTreeRoot must not be null");
+        }
+        put("StructTreeRoot", structTreeRoot);
+    }
+
+    /**
+     * Used for accessibility
+     */
+    public void makeTagged() {
+        PDFDictionary dict = new PDFDictionary();
+        dict.put("Marked", Boolean.TRUE);
+        put("MarkInfo", dict);  //new PDFMarkInfo()
+    }
+
+}
\ No newline at end of file
Index: src/java/org/apache/fop/pdf/PDFStructElem.java
===================================================================
--- src/java/org/apache/fop/pdf/PDFStructElem.java	(revision 0)
+++ src/java/org/apache/fop/pdf/PDFStructElem.java	(revision 0)
@@ -0,0 +1,199 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf;
+
+
+
+/**
+ * 
+ * Class representing a PDF Structure Element
+ *
+ */
+public class PDFStructElem extends PDFDictionary {
+
+    private PDFObject parentObject = null;
+    private String source = "";
+    private boolean level1 = false;
+    
+    /**
+     * Create the /StructTreeRoot dictionary
+     * @param fo passed in fo object
+     * @param parent Parent of this PDFStructElem
+     */
+    public PDFStructElem(String fo, PDFObject parent) {
+        super();
+        if (parent instanceof PDFStructElem) {
+            parentObject = (PDFStructElem) parent;
+        }
+        put("Type", new PDFName("StructElem"));
+        source = fo;
+        if ("block".equals(fo)) {
+            put("S", new PDFName("P"));
+        } else if ("inline".equals(fo) || "wrapper".equals(fo) || "character".equals(fo)) { 
+            put("S", new PDFName("Span"));
+        } else if ("table-cell".equals(fo)) {
+            PDFStructElem grandParent = (PDFStructElem)
+                ((PDFStructElem)parent).getParentStructElem();
+            String s = grandParent.getSource();
+            if ("table-header".equals(s)) {   
+                put("S", new PDFName("TH"));
+            } else {
+                put("S", new PDFName("TD"));             
+            }
+        } else if ("table-row".equals(fo)) {
+            put("S", new PDFName("TR"));
+        } else if ("root".equals(fo)) {
+            put("S", new PDFName("Document"));
+        } else if ("page-sequence".equals(fo)) {
+            put("S", new PDFName("Part"));
+        } else if ("flow".equals(fo) || "static-content".equals(fo)) {
+            put("S", new PDFName("Sect"));
+        }   else if ("page-number".equals(fo) || "page-number-citation".equals(fo) 
+                || "page-number-citation-last".equals(fo)) {
+            put("S", new PDFName("Quote"));     
+        } else if ("external-graphic".equals(fo) || "instream-foreign-object".equals(fo)) {
+            put("S", new PDFName("Figure"));
+        } else if ("table".equals(fo)) {
+            put("S", new PDFName("Table"));
+        } else if ("table-body".equals(fo)) {
+            put("S", new PDFName("TBody"));
+        } else if ("table-header".equals(fo)) {
+            put("S", new PDFName("THead"));
+        } else if ("table-footer".equals(fo)) { 
+            put("S", new PDFName("TFoot"));
+        }  else if ("list-block".equals(fo)) {
+            put("S", new PDFName("L"));
+        } else if ("list-item".equals(fo)) {
+            put("S", new PDFName("LI"));
+        } else if ("list-item-label".equals(fo)) {
+            put("S", new PDFName("Lbl"));
+        } else if ("list-item-body".equals(fo)) {
+            put("S", new PDFName("LBody"));
+        } else if ("block-container".equals(fo)) { 
+            put("S", new PDFName("Div"));
+        } else if ("basic-link".equals(fo)) {
+            put("S", new PDFName("Link"));
+        } else if ("footnote".equals(fo)) { 
+            put("S", new PDFName("Note"));
+        } else if ("footnote-body".equals(fo)) { 
+            put("S", new PDFName("Sect"));
+        } else if ("marker".equals(fo)) {
+            put("S", new PDFName("Private"));
+        }  else {
+            log.error("Accessibility: PDFStructElem constructor is missing: " + fo);
+        }
+        setParent(parent);
+        if (!"external-graphic".equals(fo) && !"instream-foreign-object".equals(fo)) {
+            put("K", new PDFArray());
+        }
+    }
+
+    /**
+     * This method is called for PDFStructElements which are direct children of
+     * fo:static-content or fo:flow-section
+     */
+    public void setLevel1() {
+        this.level1 = true;
+    }
+    
+    /**
+     * 
+     * @return true if the PDFStructElement is a direct child of
+     * fo:static-content or fo:flow-section
+     */
+    public boolean getLevel1() {
+        return this.level1;
+    }
+    
+    /**
+     * Get the parent
+     * @return PDFStructElem of parent
+     */
+    public PDFObject getParentStructElem() {
+        return (PDFStructElem)this.parentObject;
+    }
+
+    /**
+     * Set the parent for this StructElem
+     * @param parent to be added
+     */
+    public void setParent(PDFObject parent) {
+        if (parent != null) {
+           put("P", new PDFReference(parent));
+        }
+    }
+
+    /**
+     * Get the source of this StructElem
+     * @return the source
+     */
+    public String getSource() {
+        return source;
+    }
+
+    /**
+     * The kids of this StructElem
+     * @return the kids
+     */
+    public PDFArray getKids() {
+        return (PDFArray)get("K");
+    }
+    
+    /**
+     * Add a kid to this strucElem
+     * @param kid to be added
+     */
+    public void addKid(PDFObject kid) {
+        getKids().add(kid); 
+    }
+
+    /**
+     * Add a kid, but only if it does not already exist
+     * @param kid to be added
+     * @return true if kid did not already exist
+     */
+    public boolean addUniqueKid(PDFObject kid) {
+        PDFArray mArray = getKids();
+        if (!mArray.contains(kid)) {
+            getKids().add(kid);
+            return true;
+        } else {
+            return false;
+        }
+    }
+    
+    /**
+     * Add kid referenced through mcid integer
+     * used fo:external-graphic
+     * @param mcid of this kid
+     */
+    public void addMCIDKid(int mcid) {
+        put("K", mcid);
+    }
+    
+    /**
+     * Add a page reference to this structElem
+     * @param pageObject to be added
+     */
+    public void addPage(Object pageObject) {
+        put("Pg", (PDFObject) pageObject);
+    }
+    
+}
Index: src/java/org/apache/fop/pdf/PDFStructTreeRoot.java
===================================================================
--- src/java/org/apache/fop/pdf/PDFStructTreeRoot.java	(revision 0)
+++ src/java/org/apache/fop/pdf/PDFStructTreeRoot.java	(revision 0)
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf;
+
+/**
+ * Class representing a PDF /StructTreeRoot dictionary.
+ */
+public class PDFStructTreeRoot extends PDFDictionary {
+
+    /**
+     * Create the /StructTreeRoot dictionary
+     */
+    public PDFStructTreeRoot() {
+        super();
+        put("Type", new PDFName("StructTreeRoot"));
+        put("K", new PDFArray());
+    }
+    
+    /**
+     * Add parentTree entry
+     * @param parentTree to be added
+     */
+    public void addParentTree(PDFParentTree parentTree) {
+        put("ParentTree", parentTree);
+    }
+    
+    /**
+     * Get the kids
+     * @return the kids
+     */
+    public PDFArray getKids() {
+        return (PDFArray)get("K");
+    }
+    
+    /**
+     * add a kid
+     * @param kid to be added
+     */
+    public void addKid(PDFObject kid) {
+        getKids().add(kid);
+    }
+}
\ No newline at end of file
Index: src/java/org/apache/fop/pdf/PDFTextUtil.java
===================================================================
--- src/java/org/apache/fop/pdf/PDFTextUtil.java	(revision 744229)
+++ src/java/org/apache/fop/pdf/PDFTextUtil.java	(working copy)
@@ -128,16 +128,68 @@
     }
 
     /**
+     * begin of a regular text object, used for accessibility
+     * @param mcid of text object
+     * @param structElemType of parent
+     */
+    public void beginTextObjectAccess(int mcid, String structElemType) {
+        if (inTextObject) {
+            throw new IllegalStateException("Already in text object");
+        }
+           write(structElemType + " <</MCID " 
+                   + String.valueOf(mcid) + ">>\nBDC\nBT\n");
+        this.inTextObject = true;
+    }
+    
+
+    /**
+     * begin of a fo:leader text object
+     * used for accessibility
+     */
+    public void beginLeaderTextObject() {
+        if (inTextObject) {
+            throw new IllegalStateException("Already in text object");
+        }
+        write("/Artifact\nBMC\nBT\n");
+        this.inTextObject = true;
+    }
+
+    
+    
+    /**
      * Called when a text object should be ended.
+     * @param accessEnabled indicating if accessibility is turned on or not
      */
-    public void endTextObject() {
+    public void endTextObject(boolean accessEnabled) {
         checkInTextObject();
-        write("ET\n");
+        if (accessEnabled) {
+            write("ET\nEMC\n");
+        } else {
+            write("ET\n");
+        }
         this.inTextObject = false;
         initValues();
     }
 
     /**
+     * used for accessibility, separate 2 text elements
+     * @param mcid of new text element
+     * @param structElemType of parent
+     */
+    public void makeTextSeparator(int mcid, String structElemType) {
+        write("ET\nEMC\n" + structElemType + " <</MCID " 
+                + String.valueOf(mcid) + ">>\nBDC\nBT\n");
+    }
+    
+    /**
+     * used for accessibility, separate regular text from fo:leader text
+     */
+    public void separateTextFromLeader() {
+        write("ET\nEMC\n/Artifact\nBMC\nBT\n");
+    }
+    
+    
+    /**
      * Resets the state fields.
      */
     protected void initValues() {
@@ -300,4 +352,7 @@
         return bufTJ != null && bufTJ.length() > 0;
     }
 
+   
+
+
 }
Index: src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java
===================================================================
--- src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java	(revision 744229)
+++ src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java	(working copy)
@@ -834,8 +834,10 @@
      * @param url the URI/URL of the image
      * @param pos the position of the image
      * @param foreignAttributes an optional Map with foreign attributes, may be null
+     * @param ptr used for accessibility
      */
-    protected abstract void drawImage(String url, Rectangle2D pos, Map foreignAttributes);
+    protected abstract void drawImage(String url, Rectangle2D pos, Map foreignAttributes, 
+            String ptr);
 
     /**
      * Draw an image at the indicated location.
@@ -843,7 +845,7 @@
      * @param pos the position of the image
      */
     protected final void drawImage(String url, Rectangle2D pos) {
-        drawImage(url, pos, null);
+        drawImage(url, pos, null, "");
     }
 
     /**
Index: src/java/org/apache/fop/render/AbstractRenderer.java
===================================================================
--- src/java/org/apache/fop/render/AbstractRenderer.java	(revision 744229)
+++ src/java/org/apache/fop/render/AbstractRenderer.java	(working copy)
@@ -737,11 +737,13 @@
         currentBPPosition += viewport.getOffset();
         Rectangle2D contpos = viewport.getContentPosition();
         if (content instanceof Image) {
-            renderImage((Image) content, contpos);
+            String ptr = (String) viewport.getTrait(Trait.PTR);
+            renderImage((Image) content, contpos, ptr);
         } else if (content instanceof Container) {
             renderContainer((Container) content);
         } else if (content instanceof ForeignObject) {
-            renderForeignObject((ForeignObject) content, contpos);
+            String ptr = (String) viewport.getTrait(Trait.PTR);
+            renderForeignObject((ForeignObject) content, contpos, ptr);
         } else if (content instanceof InlineBlockParent) {
             renderInlineBlockParent((InlineBlockParent) content);
         }
@@ -754,9 +756,10 @@
      *
      * @param image  The image
      * @param pos    The target position of the image
+     * @param ptr  used for accessibility
      * (todo) Make renderImage() protected
      */
-    public void renderImage(Image image, Rectangle2D pos) {
+    public void renderImage(Image image, Rectangle2D pos, String ptr) {
         // Default: do nothing.
         // Some renderers (ex. Text) don't support images.
     }
@@ -780,9 +783,10 @@
      *
      * @param fo   The foreign object area
      * @param pos  The target position of the foreign object
+     * @param ptr  used for accessibility
      * (todo) Make renderForeignObject() protected
      */
-    protected void renderForeignObject(ForeignObject fo, Rectangle2D pos) {
+    protected void renderForeignObject(ForeignObject fo, Rectangle2D pos, String ptr) {
         // Default: do nothing.
         // Some renderers (ex. Text) don't support foreign objects.
     }
Index: src/java/org/apache/fop/render/afp/AFPPainter.java
===================================================================
--- src/java/org/apache/fop/render/afp/AFPPainter.java	(revision 744229)
+++ src/java/org/apache/fop/render/afp/AFPPainter.java	(working copy)
@@ -183,7 +183,7 @@
     }
 
     /** {@inheritDoc} */
-    public void drawImage(String uri, Rectangle rect) throws IFException {
+    public void drawImage(String uri, Rectangle rect, String ptr) throws IFException {
         String name = documentHandler.getPageSegmentNameFor(uri);
         if (name != null) {
             float[] srcPts = {rect.x, rect.y};
@@ -195,7 +195,7 @@
     }
 
     /** {@inheritDoc} */
-    public void drawImage(Document doc, Rectangle rect) throws IFException {
+    public void drawImage(Document doc, Rectangle rect, String ptr) throws IFException {
         drawImageUsingDocument(doc, rect);
     }
 
@@ -312,7 +312,7 @@
     /** {@inheritDoc} */
     public void drawText(int x, int y,
             final int letterSpacing, final int wordSpacing, final int[] dx,
-            final String text) throws IFException {
+            final String text, final String ptr) throws IFException {
         final int fontSize = this.state.getFontSize();
         getPaintingState().setFontSize(fontSize);
 
Index: src/java/org/apache/fop/render/afp/AFPRenderer.java
===================================================================
--- src/java/org/apache/fop/render/afp/AFPRenderer.java	(revision 744229)
+++ src/java/org/apache/fop/render/afp/AFPRenderer.java	(working copy)
@@ -375,7 +375,7 @@
         ImageFlavor.GRAPHICS2D, ImageFlavor.BUFFERED_IMAGE, ImageFlavor.RENDERED_IMAGE };
 
     /** {@inheritDoc} */
-    public void drawImage(String uri, Rectangle2D pos, Map foreignAttributes) {
+    public void drawImage(String uri, Rectangle2D pos, Map foreignAttributes, String ptr) {
         uri = URISpecification.getURL(uri);
         paintingState.setImageUri(uri);
 
@@ -506,7 +506,7 @@
 
     /** {@inheritDoc} */
     public void renderImage(Image image, Rectangle2D pos) {
-        drawImage(image.getURL(), pos, image.getForeignAttributes());
+        drawImage(image.getURL(), pos, image.getForeignAttributes(),"");
     }
 
     /** {@inheritDoc} */
Index: src/java/org/apache/fop/render/intermediate/IFConstants.java
===================================================================
--- src/java/org/apache/fop/render/intermediate/IFConstants.java	(revision 744229)
+++ src/java/org/apache/fop/render/intermediate/IFConstants.java	(working copy)
@@ -50,4 +50,6 @@
     String EL_BORDER_RECT = "border-rect";
     String EL_FONT = "font";
     String EL_TEXT = "text";
+    /** used for accessibility */
+    String EL_STRUCTURE_TREE = "structure-tree";  
 }
Index: src/java/org/apache/fop/render/intermediate/IFDocumentHandler.java
===================================================================
--- src/java/org/apache/fop/render/intermediate/IFDocumentHandler.java	(revision 744229)
+++ src/java/org/apache/fop/render/intermediate/IFDocumentHandler.java	(working copy)
@@ -20,6 +20,7 @@
 package org.apache.fop.render.intermediate;
 
 import java.awt.Dimension;
+import java.io.IOException;
 
 import javax.xml.transform.Result;
 
@@ -140,6 +141,7 @@
      * Indicates the start of a document. This method may only be called once before any other
      * event method.
      * @throws IFException if an error occurs while handling this event
+     * @throws  
      */
     void startDocument() throws IFException;
 
Index: src/java/org/apache/fop/render/intermediate/IFPainter.java
===================================================================
--- src/java/org/apache/fop/render/intermediate/IFPainter.java	(revision 744229)
+++ src/java/org/apache/fop/render/intermediate/IFPainter.java	(working copy)
@@ -153,10 +153,11 @@
      * @param wordSpacing additional spacing between words (may be 0)
      * @param dx an array of adjustment values for each character in X-direction (may be null)
      * @param text the text
+     * @param ptr used for accessibility
      * @throws IFException if an error occurs while handling this event
      */
     void drawText(int x, int y, int letterSpacing, int wordSpacing,
-            int[] dx, String text) throws IFException;
+            int[] dx, String text, String ptr) throws IFException;
 
     /**
      * Restricts the current clipping region with the given rectangle.
@@ -205,18 +206,20 @@
      * an fo:external-graphic in XSL-FO.
      * @param uri the image's URI
      * @param rect the rectangle in which the image shall be painted
+     * @param ptr used for accessibility
      * @throws IFException if an error occurs while handling this event
      */
-    void drawImage(String uri, Rectangle rect) throws IFException;
+    void drawImage(String uri, Rectangle rect, String ptr) throws IFException;
 
     /**
      * Draws an image (represented by a DOM document) inside a given rectangle. This is the
      * equivalent to an fo:instream-foreign-object in XSL-FO.
      * @param doc the DOM document containing the foreign object
      * @param rect the rectangle in which the image shall be painted
+     * @param ptr used for accessibility 
      * @throws IFException if an error occurs while handling this event
      */
-    void drawImage(Document doc, Rectangle rect) throws IFException;
+    void drawImage(Document doc, Rectangle rect, String ptr) throws IFException;
     //Note: For now, all foreign objects are handled as DOM documents. At the moment, all known
     //implementations use a DOM anyway, so optimizing this to work with SAX wouldn't result in
     //any performance benefits. The IFRenderer itself has a DOM anyway. Only the IFParser could
Index: src/java/org/apache/fop/render/intermediate/IFParser.java
===================================================================
--- src/java/org/apache/fop/render/intermediate/IFParser.java	(revision 744229)
+++ src/java/org/apache/fop/render/intermediate/IFParser.java	(working copy)
@@ -86,7 +86,7 @@
         try {
             Transformer transformer = tFactory.newTransformer();
             transformer.setErrorListener(new DefaultErrorListener(log));
-
+       
             SAXResult res = new SAXResult(getContentHandler(documentHandler, userAgent));
 
             transformer.transform(src, res);
@@ -481,7 +481,9 @@
                 s = lastAttributes.getValue("word-spacing");
                 int wordSpacing = (s != null ? Integer.parseInt(s) : 0);
                 int[] dx = XMLUtil.getAttributeAsIntArray(lastAttributes, "dx");
-                painter.drawText(x, y, letterSpacing, wordSpacing, dx, content.toString());
+                int[] dy = XMLUtil.getAttributeAsIntArray(lastAttributes, "dy");
+                String ptr = lastAttributes.getValue("ptr"); // used for accessibility
+                painter.drawText(x, y, letterSpacing, wordSpacing, dx, content.toString(), ptr);
             }
 
             public boolean ignoreCharacters() {
@@ -576,9 +578,10 @@
                 int height = Integer.parseInt(lastAttributes.getValue("height"));
                 Map foreignAttributes = getForeignAttributes(lastAttributes);
                 establishForeignAttributes(foreignAttributes);
+                String ptr = lastAttributes.getValue("ptr"); // used for accessibility
                 if (foreignObject != null) {
                     painter.drawImage(foreignObject,
-                            new Rectangle(x, y, width, height));
+                            new Rectangle(x, y, width, height), ptr);
                     foreignObject = null;
                 } else {
                     String uri = lastAttributes.getValue(
@@ -586,7 +589,7 @@
                     if (uri == null) {
                         throw new IFException("xlink:href is missing on image", null);
                     }
-                    painter.drawImage(uri, new Rectangle(x, y, width, height));
+                    painter.drawImage(uri, new Rectangle(x, y, width, height), ptr);
                 }
                 resetForeignAttributes();
                 inForeignObject = false;
Index: src/java/org/apache/fop/render/intermediate/IFRenderer.java
===================================================================
--- src/java/org/apache/fop/render/intermediate/IFRenderer.java	(revision 744229)
+++ src/java/org/apache/fop/render/intermediate/IFRenderer.java	(working copy)
@@ -121,8 +121,8 @@
 
     private boolean inPageSequence = false;
 
-    private Stack graphicContextStack = new Stack();
-    private Stack viewportDimensionStack = new Stack();
+    private final Stack graphicContextStack = new Stack();
+    private final Stack viewportDimensionStack = new Stack();
     private IFGraphicContext graphicContext = new IFGraphicContext();
     //private Stack groupStack = new Stack();
 
@@ -133,12 +133,12 @@
      * Must be used in conjunction with the page reference to fully specify the details
      * of a "go-to" action.
      */
-    private Map idPositions = new java.util.HashMap();
+    private final Map idPositions = new java.util.HashMap();
 
     /**
      * The "go-to" actions in idGoTos that are not complete yet
      */
-    private List unfinishedGoTos = new java.util.ArrayList();
+    private final List unfinishedGoTos = new java.util.ArrayList();
     // can't use a Set because PDFGoTo.equals returns true if the target is the same,
     // even if the object number differs
 
@@ -146,11 +146,11 @@
     protected Map pageIndices = new java.util.HashMap();
 
     private BookmarkTree bookmarkTree;
-    private List deferredDestinations = new java.util.ArrayList();
-    private List deferredLinks = new java.util.ArrayList();
-    private ActionSet actionSet = new ActionSet();
+    private final List deferredDestinations = new java.util.ArrayList();
+    private final List deferredLinks = new java.util.ArrayList();
+    private final ActionSet actionSet = new ActionSet();
 
-    private TextUtil textUtil = new TextUtil();
+    private final TextUtil textUtil = new TextUtil();
 
     /**
      * Main constructor
@@ -818,7 +818,7 @@
             currentIPPosition = saveIP;
             currentBPPosition = saveBP;
 
-            currentBPPosition += (int)(bv.getAllocBPD());
+            currentBPPosition += (bv.getAllocBPD());
         }
         viewportDimensionStack.pop();
     }
@@ -886,6 +886,7 @@
         // stuff we only need if a link must be created:
         Rectangle ipRect = null;
         AbstractAction action = null;
+        String ptr = (String) ip.getTrait(Trait.PTR); // used for accessibility
         // make sure the rect is determined *before* calling super!
         int ipp = currentIPPosition;
         int bpp = currentBPPosition + ip.getOffset();
@@ -898,6 +899,7 @@
 
         boolean linkTraitFound = false;
 
+
         // try INTERNAL_LINK first
         Trait.InternalLink intLink = (Trait.InternalLink) ip.getTrait(Trait.INTERNAL_LINK);
         if (intLink != null) {
@@ -929,6 +931,7 @@
 
         // warn if link trait found but not allowed, else create link
         if (linkTraitFound) {
+            action.setPtr(ptr);  // used for accessibility
             Link link = new Link(action, ipRect);
             this.deferredLinks.add(link);
         }
@@ -963,6 +966,7 @@
 
         String fontName = getInternalFontNameForArea(text);
         int size = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue();
+        String ptr = (String)text.getTrait(Trait.PTR); // used for accessibility
 
         // This assumes that *all* CIDFonts use a /ToUnicode mapping
         Typeface tf = getTypeface(fontName);
@@ -981,7 +985,7 @@
         textUtil.setStartPosition(rx, bl);
         textUtil.setSpacing(text.getTextLetterSpaceAdjust(), text.getTextWordSpaceAdjust());
         super.renderText(text);
-
+        textUtil.setPtr(ptr); // used for accessibility
         textUtil.flush();
         renderTextDecoration(tf, size, text, bl, rx);
     }
@@ -1054,15 +1058,24 @@
         private static final int INITIAL_BUFFER_SIZE = 16;
         private int[] dx = new int[INITIAL_BUFFER_SIZE];
         private int lastDXPos = 0;
-        private StringBuffer text = new StringBuffer();
+        private final StringBuffer text = new StringBuffer();
         private int startx, starty;
         private int tls, tws;
-        private boolean combined = false;
+        private final boolean combined = false;
+        private String ptr = null; // used for accessibility
 
         void addChar(char ch) {
             text.append(ch);
         }
 
+        /**
+         * used for accessibility
+         * @param inPtr to be stored
+         */
+        public void setPtr(String inPtr) {
+            ptr = inPtr;
+        }
+
         void adjust(int adjust) {
             if (adjust != 0) {
                 int idx = text.length();
@@ -1090,6 +1103,7 @@
             this.starty = y;
         }
 
+
         void setSpacing(int tls, int tws) {
             this.tls = tls;
             this.tws = tws;
@@ -1105,9 +1119,9 @@
                         System.arraycopy(dx, 0, effDX, 0, size);
                     }
                     if (combined) {
-                        painter.drawText(startx, starty, 0, 0, effDX, text.toString());
+                        painter.drawText(startx, starty, 0, 0, effDX, text.toString(), ptr);
                     } else {
-                        painter.drawText(startx, starty, tls, tws, effDX, text.toString());
+                        painter.drawText(startx, starty, tls, tws, effDX, text.toString(), ptr);
                     }
                 } catch (IFException e) {
                     handleIFException(e);
@@ -1118,12 +1132,12 @@
     }
 
     /** {@inheritDoc} */
-    public void renderImage(Image image, Rectangle2D pos) {
-        drawImage(image.getURL(), pos, image.getForeignAttributes());
+    public void renderImage(Image image, Rectangle2D pos, String ptr) {
+        drawImage(image.getURL(), pos, image.getForeignAttributes(), ptr);
     }
 
     /** {@inheritDoc} */
-    protected void drawImage(String uri, Rectangle2D pos, Map foreignAttributes) {
+    protected void drawImage(String uri, Rectangle2D pos, Map foreignAttributes, String ptr) {
         Rectangle posInt = new Rectangle(
                 currentIPPosition + (int)pos.getX(),
                 currentBPPosition + (int)pos.getY(),
@@ -1132,7 +1146,7 @@
         uri = URISpecification.getURL(uri);
         try {
             establishForeignAttributes(foreignAttributes);
-            painter.drawImage(uri, posInt);
+            painter.drawImage(uri, posInt, ptr);
             resetForeignAttributes();
         } catch (IFException ife) {
             handleIFException(ife);
@@ -1140,7 +1154,7 @@
     }
 
     /** {@inheritDoc} */
-    public void renderForeignObject(ForeignObject fo, Rectangle2D pos) {
+    public void renderForeignObject(ForeignObject fo, Rectangle2D pos, String ptr) {
         endTextObject();
         Rectangle posInt = new Rectangle(
                 currentIPPosition + (int)pos.getX(),
@@ -1150,7 +1164,7 @@
         Document doc = fo.getDocument();
         try {
             establishForeignAttributes(fo.getForeignAttributes());
-            painter.drawImage(doc, posInt);
+            painter.drawImage(doc, posInt, ptr);
             resetForeignAttributes();
         } catch (IFException ife) {
             handleIFException(ife);
Index: src/java/org/apache/fop/render/intermediate/IFSerializer.java
===================================================================
--- src/java/org/apache/fop/render/intermediate/IFSerializer.java	(revision 744229)
+++ src/java/org/apache/fop/render/intermediate/IFSerializer.java	(working copy)
@@ -25,11 +25,30 @@
 import java.awt.Point;
 import java.awt.Rectangle;
 import java.awt.geom.AffineTransform;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
 import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
 
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.AttributesImpl;
@@ -53,6 +72,8 @@
 import org.apache.fop.util.XMLConstants;
 import org.apache.fop.util.XMLUtil;
 
+
+
 /**
  * IFPainter implementation that serializes the intermediate format to XML.
  */
@@ -60,10 +81,46 @@
         implements IFConstants, IFPainter, IFDocumentNavigationHandler {
 
     private IFDocumentHandler mimicHandler;
+    private int pageSequenceCounter; // used for accessibility
+    private DocumentBuilder parser = null; // used for accessibility
+    private Document doc = null;  // used for accessibility
 
     /** Holds the intermediate format state */
     private IFState state;
 
+    private class NamespaceContextImpl implements NamespaceContext {
+
+         public String uri;
+         public String prefix;
+
+         public NamespaceContextImpl() {
+         }
+
+         public NamespaceContextImpl(String prefix, String uri) {
+             this.uri = uri;
+             this.prefix = prefix;
+            }
+
+         public String getNamespaceURI(String prefix) {
+           return uri;
+         }
+         public void setNamespaceURI(String uri) {
+           this.uri = uri;
+         }
+
+         public String getPrefix(String uri) {
+           return prefix;
+         }
+
+         public void setPrefix(String prefix) {
+           this.prefix = prefix;
+         }
+         public Iterator getPrefixes(String uri) {
+             return null;
+         }
+
+    }
+
     /**
      * Default constructor.
      */
@@ -150,9 +207,18 @@
             handler.startPrefixMapping(DocumentNavigationExtensionConstants.PREFIX,
                     DocumentNavigationExtensionConstants.NAMESPACE);
             handler.startElement(EL_DOCUMENT);
+            if (this.getUserAgent().accessibilityEnabled()) {
+                pageSequenceCounter = 0;
+                DocumentBuilderFactory  factory = DocumentBuilderFactory.newInstance();
+                factory.setNamespaceAware(true);
+                parser = factory.newDocumentBuilder();
+            }
         } catch (SAXException e) {
             throw new IFException("SAX error in startDocument()", e);
-        }
+        } catch (ParserConfigurationException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        } 
     }
 
     /** {@inheritDoc} */
@@ -202,6 +268,9 @@
         }
     }
 
+    
+    
+    
     /** {@inheritDoc} */
     public void startPageSequence(String id) throws IFException {
         try {
@@ -209,9 +278,36 @@
             if (id != null) {
                 atts.addAttribute(XML_NAMESPACE, "id", "xml:id", XMLUtil.CDATA, id);
             }
+            
             handler.startElement(EL_PAGE_SEQUENCE, atts);
+            if (this.getUserAgent().accessibilityEnabled()) {
+                if (doc == null) {
+                    doc = parser.parse( 
+                            new ByteArrayInputStream(this.getUserAgent().getResultAsByteArray()));
+                }
+                handler.startElement(EL_STRUCTURE_TREE); // add structure tree
+                String xpathExpr 
+                   = "/fo:root/fo:page-sequence[" + Integer.toString(++pageSequenceCounter) + "]/*";
+                XPath xpath = XPathFactory.newInstance().newXPath();
+                NamespaceContext namespaceContext 
+                    = new NamespaceContextImpl("fo", "http://www.w3.org/1999/XSL/Format");
+                xpath.setNamespaceContext(namespaceContext);
+                NodeList nodes = (NodeList)xpath.evaluate(xpathExpr, doc, XPathConstants.NODESET);
+                for (int i = 0, n = nodes.getLength(); i < n; i++) {
+                    Node node = nodes.item(i);
+                    new DOM2SAX(handler).writeFragment(node);
+                }
+                handler.endElement(EL_STRUCTURE_TREE);
+            }
         } catch (SAXException e) {
             throw new IFException("SAX error in startPageSequence()", e);
+        } catch (XPathExpressionException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+            throw new IFException("IO Problem.", e);
         }
     }
 
@@ -231,10 +327,9 @@
             AttributesImpl atts = new AttributesImpl();
             addAttribute(atts, "index", Integer.toString(index));
             addAttribute(atts, "name", name);
-            addAttribute(atts, "page-master-name", pageMasterName);
+            addAttribute(atts, "page-master-name", name);
             addAttribute(atts, "width", Integer.toString(size.width));
             addAttribute(atts, "height", Integer.toString(size.height));
-            addForeignAttributes(atts);
             handler.startElement(EL_PAGE, atts);
         } catch (SAXException e) {
             throw new IFException("SAX error in startPage()", e);
@@ -284,6 +379,7 @@
     public void startPageTrailer() throws IFException {
         try {
             handler.startElement(EL_PAGE_TRAILER);
+            commitNavigation();
         } catch (SAXException e) {
             throw new IFException("SAX error in startPageTrailer()", e);
         }
@@ -292,7 +388,6 @@
     /** {@inheritDoc} */
     public void endPageTrailer() throws IFException {
         try {
-            commitNavigation();
             handler.endElement(EL_PAGE_TRAILER);
         } catch (SAXException e) {
             throw new IFException("SAX error in endPageTrailer()", e);
@@ -381,7 +476,7 @@
     }
 
     /** {@inheritDoc} */
-    public void drawImage(String uri, Rectangle rect) throws IFException {
+    public void drawImage(String uri, Rectangle rect, String ptr) throws IFException {
         try {
             AttributesImpl atts = new AttributesImpl();
             addAttribute(atts, XLINK_HREF, uri);
@@ -389,33 +484,26 @@
             addAttribute(atts, "y", Integer.toString(rect.y));
             addAttribute(atts, "width", Integer.toString(rect.width));
             addAttribute(atts, "height", Integer.toString(rect.height));
-            addForeignAttributes(atts);
+            if (ptr != null) {
+                addAttribute(atts, "ptr", ptr);  // used for accessibility
+            }
             handler.element(EL_IMAGE, atts);
         } catch (SAXException e) {
             throw new IFException("SAX error in startGroup()", e);
         }
     }
 
-    private void addForeignAttributes(AttributesImpl atts) {
-        Map foreignAttributes = getContext().getForeignAttributes();
-        if (!foreignAttributes.isEmpty()) {
-            Iterator iter = foreignAttributes.entrySet().iterator();
-            while (iter.hasNext()) {
-                Map.Entry entry = (Map.Entry)iter.next();
-                addAttribute(atts, (QName)entry.getKey(), entry.getValue().toString());
-            }
-        }
-    }
-
     /** {@inheritDoc} */
-    public void drawImage(Document doc, Rectangle rect) throws IFException {
+    public void drawImage(Document doc, Rectangle rect, String ptr) throws IFException {
         try {
             AttributesImpl atts = new AttributesImpl();
             addAttribute(atts, "x", Integer.toString(rect.x));
             addAttribute(atts, "y", Integer.toString(rect.y));
             addAttribute(atts, "width", Integer.toString(rect.width));
             addAttribute(atts, "height", Integer.toString(rect.height));
-            addForeignAttributes(atts);
+            if (ptr != null) {
+                addAttribute(atts, "ptr", ptr);  // used for accessibility
+            }
             handler.startElement(EL_IMAGE, atts);
             new DOM2SAX(handler).writeDocument(doc, true);
             handler.endElement(EL_IMAGE);
@@ -504,7 +592,7 @@
             addAttribute(atts, "x2", Integer.toString(end.x));
             addAttribute(atts, "y2", Integer.toString(end.y));
             addAttribute(atts, "stroke-width", Integer.toString(width));
-            addAttribute(atts, "color", ColorUtil.colorToString(color));
+            addAttribute(atts, "color", Integer.toString(width));
             addAttribute(atts, "style", style.getName());
             handler.element(EL_LINE, atts);
         } catch (SAXException e) {
@@ -514,10 +602,9 @@
 
     /** {@inheritDoc} */
     public void drawText(int x, int y, int letterSpacing, int wordSpacing,
-            int[] dx, String text) throws IFException {
+            int[] dx, String text, String ptr) throws IFException {
         try {
             AttributesImpl atts = new AttributesImpl();
-            XMLUtil.addAttribute(atts, XMLConstants.XML_SPACE, "preserve");
             addAttribute(atts, "x", Integer.toString(x));
             addAttribute(atts, "y", Integer.toString(y));
             if (letterSpacing != 0) {
@@ -529,6 +616,9 @@
             if (dx != null) {
                 addAttribute(atts, "dx", IFUtil.toString(dx));
             }
+            if (ptr != null) {
+                addAttribute(atts, "ptr", ptr);  // used for accessibility
+            }
             handler.startElement(EL_TEXT, atts);
             char[] chars = text.toCharArray();
             handler.characters(chars, 0, chars.length);
@@ -707,8 +797,9 @@
     public void addResolvedAction(AbstractAction action) throws IFException {
         assert action.isComplete();
         assert action.hasID();
-        AbstractAction noted = (AbstractAction)incompleteActions.remove(action.getID());
+        AbstractAction noted = (AbstractAction)incompleteActions.get(action.getID());
         if (noted != null) {
+            incompleteActions.remove(action.getID());
             completeActions.add(action);
         } else {
             //ignore as it was already complete when it was first used.
Index: src/java/org/apache/fop/render/intermediate/extensions/AbstractAction.java
===================================================================
--- src/java/org/apache/fop/render/intermediate/extensions/AbstractAction.java	(revision 744229)
+++ src/java/org/apache/fop/render/intermediate/extensions/AbstractAction.java	(working copy)
@@ -27,6 +27,7 @@
 public abstract class AbstractAction implements XMLizable {
 
     private String id;
+    private String ptr; // used for accessibility
 
     /**
      * Sets an ID to make the action referencable.
@@ -43,8 +44,24 @@
     public String getID() {
         return this.id;
     }
-
+    
     /**
+     * Used for accessibility   
+     * @param s representing the ptr
+     */
+    public void setPtr(String s) {
+        this.ptr = s;
+    }
+    
+    /**
+     * Used for accessibility
+     * @return the ptr
+     */
+    public String getPtr() {
+        return this.ptr;
+    }
+    
+    /**
      * Indicates whether the action has an ID and is therefore referencable.
      * @return true if the action has an ID
      */
Index: src/java/org/apache/fop/render/java2d/Java2DPainter.java
===================================================================
--- src/java/org/apache/fop/render/java2d/Java2DPainter.java	(revision 744229)
+++ src/java/org/apache/fop/render/java2d/Java2DPainter.java	(working copy)
@@ -156,7 +156,7 @@
     }
 
     /** {@inheritDoc} */
-    public void drawImage(String uri, Rectangle rect) throws IFException {
+    public void drawImage(String uri, Rectangle rect, String ptr) throws IFException {
         drawImageUsingURI(uri, rect);
     }
 
@@ -168,7 +168,7 @@
     }
 
     /** {@inheritDoc} */
-    public void drawImage(Document doc, Rectangle rect) throws IFException {
+    public void drawImage(Document doc, Rectangle rect, String ptr) throws IFException {
         drawImageUsingDocument(doc, rect);
     }
 
@@ -208,7 +208,7 @@
     }
 
     /** {@inheritDoc} */
-    public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[] dx, String text)
+    public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[] dx, String text, String ptr)
             throws IFException {
         g2dState.updateColor(state.getTextColor());
         FontTriplet triplet = new FontTriplet(
Index: src/java/org/apache/fop/render/java2d/Java2DRenderer.java
===================================================================
--- src/java/org/apache/fop/render/java2d/Java2DRenderer.java	(revision 744229)
+++ src/java/org/apache/fop/render/java2d/Java2DRenderer.java	(working copy)
@@ -875,7 +875,7 @@
                                                       ImageFlavor.XML_DOM};
 
     /** {@inheritDoc} */
-    protected void drawImage(String uri, Rectangle2D pos, Map foreignAttributes) {
+    protected void drawImage(String uri, Rectangle2D pos, Map foreignAttributes, String ptr) {
 
         int x = currentIPPosition + (int)Math.round(pos.getX());
         int y = currentBPPosition + (int)Math.round(pos.getY());
Index: src/java/org/apache/fop/render/pcl/PCLEventProducer.xml
===================================================================
--- src/java/org/apache/fop/render/pcl/PCLEventProducer.xml	(revision 744229)
+++ src/java/org/apache/fop/render/pcl/PCLEventProducer.xml	(working copy)
@@ -1,3 +1,4 @@
-<?xml version="1.0" encoding="UTF-8"?><catalogue xml:lang="en">
+<?xml version="1.0" encoding="UTF-8"?>
+<catalogue xml:lang="en">
   <message key="org.apache.fop.render.pcl.PCLEventProducer.paperTypeUnavailable">Paper type ({pageWidth} x {pageHeight} mpt) could not be determined. Falling back to: {fallbackPaper}</message>
 </catalogue>
Index: src/java/org/apache/fop/render/pcl/PCLPainter.java
===================================================================
--- src/java/org/apache/fop/render/pcl/PCLPainter.java	(revision 744229)
+++ src/java/org/apache/fop/render/pcl/PCLPainter.java	(working copy)
@@ -154,7 +154,7 @@
     }
 
     /** {@inheritDoc} */
-    public void drawImage(String uri, Rectangle rect) throws IFException {
+    public void drawImage(String uri, Rectangle rect, String ptr) throws IFException {
         drawImageUsingURI(uri, rect);
     }
 
@@ -176,7 +176,7 @@
     }
 
     /** {@inheritDoc} */
-    public void drawImage(Document doc, Rectangle rect) throws IFException {
+    public void drawImage(Document doc, Rectangle rect, String ptr) throws IFException {
         drawImageUsingDocument(doc, rect);
     }
 
@@ -312,8 +312,9 @@
     }
 
     /** {@inheritDoc} */
-    public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[] dx, String text)
+    public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[] dx, String text, String ptr)
                 throws IFException {
+        //Note: ptr is ignored as it is only needed for accessibility
         try {
             FontTriplet triplet = new FontTriplet(
                     state.getFontFamily(), state.getFontStyle(), state.getFontWeight());
@@ -474,7 +475,7 @@
                 Java2DPainter painter = new Java2DPainter(g2d,
                         getContext(), parent.getFontInfo(), state);
                 try {
-                    painter.drawText(x, y, letterSpacing, wordSpacing, dx, text);
+                    painter.drawText(x, y, letterSpacing, wordSpacing, dx, text, "");
                 } catch (IFException e) {
                     //This should never happen with the Java2DPainter
                     throw new RuntimeException("Unexpected error while painting text", e);
Index: src/java/org/apache/fop/render/pdf/PDFConfigurationConstants.java
===================================================================
--- src/java/org/apache/fop/render/pdf/PDFConfigurationConstants.java	(revision 744229)
+++ src/java/org/apache/fop/render/pdf/PDFConfigurationConstants.java	(working copy)
@@ -49,4 +49,6 @@
      * PDF/X profile is active).
      */
     String KEY_DISABLE_SRGB_COLORSPACE = "disable-srgb-colorspace";
+    /** PDF Accessibility */
+    String ACCESSIBLITY = "accessibility";
 }
Index: src/java/org/apache/fop/render/pdf/PDFContentGenerator.java
===================================================================
--- src/java/org/apache/fop/render/pdf/PDFContentGenerator.java	(revision 744229)
+++ src/java/org/apache/fop/render/pdf/PDFContentGenerator.java	(working copy)
@@ -50,6 +50,7 @@
 
     /** the current stream to add PDF commands to */
     private PDFStream currentStream;
+    private boolean accessEnabled; // used for accessibility
 
     /** drawing state */
     protected PDFPaintingState currentState = null;
@@ -63,9 +64,10 @@
      * @param document the PDF document
      * @param out the output stream the PDF document is generated to
      * @param resourceContext the resource context
+     * @param accessibilityEnabled indicating if accessibility is enabled or not
      */
     public PDFContentGenerator(PDFDocument document, OutputStream out,
-            PDFResourceContext resourceContext) {
+            PDFResourceContext resourceContext, boolean accessibilityEnabled) {
         this.document = document;
         this.outputStream = out;
         this.resourceContext = resourceContext;
@@ -78,6 +80,7 @@
         };
 
         this.currentState = new PDFPaintingState();
+        this.accessEnabled = accessibilityEnabled;
     }
 
     /**
@@ -153,7 +156,25 @@
         currentStream.add("q\n");
     }
 
+    /** {@inheritDoc} */
+    protected void saveGraphicsState(String structElemType, int sequenceNum) {
+        endTextObject();
+        currentState.save();
+        currentStream.add(structElemType + " <</MCID " + String.valueOf(sequenceNum) + ">>\nBDC\n");
+        currentStream.add("q\n");
+    }
+    
     /**
+     * Used for accessibility
+     * @param structElemType Structure Element Type
+     * @param sequenceNum    Sequence number
+     */
+    protected void startAccessSequence(String structElemType, int sequenceNum) {
+        currentStream.add(structElemType + " <</MCID " + String.valueOf(sequenceNum) + ">>\nBDC\n");
+    }
+    
+    
+    /**
      * Restored the graphics state valid before the previous {@code #saveGraphicsState()}.
      * @param popState true if the state should also be popped, false if only the PDF command
      *           should be issued
@@ -171,6 +192,33 @@
         restoreGraphicsState(true);
     }
 
+    /** used for accessibility */
+    protected void restoreGraphicsStateAccess() {
+        endTextObject();
+        currentStream.add("Q\n");
+        currentStream.add("EMC\n");
+        currentState.restore();
+    }
+    
+    
+    /**
+     * used for accessibility, separates 2 text elements
+     * @param mcid of new text element
+     * @param structElemType of parent of new text element
+     */
+    protected void separateTextElements(int mcid, String structElemType) {
+        textutil.makeTextSeparator(mcid, structElemType);
+    }
+    
+    /**
+     * used for accessibility
+     * separates a text element from fo:leader text element
+     */
+    public void separateTextElementFromLeader() {
+        textutil.separateTextFromLeader();
+    }
+    
+    
     /** Indicates the beginning of a text object. */
     protected void beginTextObject() {
         if (!textutil.isInTextObject()) {
@@ -178,10 +226,31 @@
         }
     }
 
+    
+    /**
+     * Accessibility beginTextObject
+     * @param mcid of text element
+     * @param structElemType of parent
+     */
+    protected void beginTextObjectAccess(int mcid, String structElemType) {
+        if (!textutil.isInTextObject()) {
+            textutil.beginTextObjectAccess(mcid, structElemType);
+        }
+    }
+    
+    /**
+     * Accessibility begin of LeaderTextObject
+     */
+    public void beginLeaderTextObject() {
+        if (!textutil.isInTextObject()) {
+            textutil.beginLeaderTextObject();
+        }
+    }
+    
     /** Indicates the end of a text object. */
     protected void endTextObject() {
         if (textutil.isInTextObject()) {
-            textutil.endTextObject();
+            textutil.endTextObject(accessEnabled);
         }
     }
 
@@ -326,5 +395,30 @@
         restoreGraphicsState();
     }
 
+    /**
+     * Places a previously registered image at a certain place on the page.
+     * Accessibility version
+     * @param x X coordinate
+     * @param y Y coordinate
+     * @param w width for image
+     * @param h height for image
+     * @param xobj the image XObject
+     * @param structElemType of this image
+     * @param mcid of this image
+     */
+    public void placeImage(float x, float y, float w, float h, PDFXObject xobj, 
+            String structElemType, int mcid) {
+        saveGraphicsState(structElemType, mcid);
+        add(format(w) + " 0 0 "
+                          + format(-h) + " "
+                          + format(x) + " "
+                          + format(y + h)
+                          + " cm\n" + xobj.getName() + " Do\n");
+        restoreGraphicsStateAccess();
+    }
 
+
+
+    
+    
 }
Index: src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java
===================================================================
--- src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java	(revision 744229)
+++ src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java	(working copy)
@@ -21,9 +21,22 @@
 
 import java.awt.Dimension;
 import java.awt.geom.AffineTransform;
+import java.io.ByteArrayInputStream;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
 import java.util.Map;
 
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -32,11 +45,18 @@
 import org.apache.fop.apps.MimeConstants;
 import org.apache.fop.fo.extensions.xmp.XMPMetadata;
 import org.apache.fop.pdf.PDFAnnotList;
+import org.apache.fop.pdf.PDFArray;
+import org.apache.fop.pdf.PDFDictionary;
 import org.apache.fop.pdf.PDFDocument;
+import org.apache.fop.pdf.PDFName;
+import org.apache.fop.pdf.PDFNumsArray;
+import org.apache.fop.pdf.PDFObject;
 import org.apache.fop.pdf.PDFPage;
+import org.apache.fop.pdf.PDFParentTree;
 import org.apache.fop.pdf.PDFReference;
 import org.apache.fop.pdf.PDFResourceContext;
 import org.apache.fop.pdf.PDFResources;
+import org.apache.fop.pdf.PDFStructElem;
 import org.apache.fop.render.intermediate.AbstractBinaryWritingIFDocumentHandler;
 import org.apache.fop.render.intermediate.IFContext;
 import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator;
@@ -44,6 +64,10 @@
 import org.apache.fop.render.intermediate.IFException;
 import org.apache.fop.render.intermediate.IFPainter;
 
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
 /**
  * {@code IFDocumentHandler} implementation that produces PDF.
  */
@@ -52,6 +76,70 @@
     /** logging instance */
     private static Log log = LogFactory.getLog(PDFDocumentHandler.class);
 
+    /** the following variables are used for accessibility */
+    private int pageSequenceCounter;
+    private DocumentBuilder parser = null;
+    private Document doc = null;
+    private Map structElemType = new HashMap();
+    private boolean accessEnabled = false;
+    private int parentTreeKey = -1;
+    private int pageLinkCount = 0;
+    private int mcidKey = -1;
+    private PDFParentTree parentTree = null;
+    private Map structTreeMap = new HashMap();
+    private ArrayList parentTreeList = new ArrayList();
+
+    private class NamespaceContextImpl implements NamespaceContext {
+
+        private String uri;
+        private String prefix;
+
+        public NamespaceContextImpl() {
+        }
+
+        public NamespaceContextImpl(String prefix, String uri) {
+            this.uri = uri;
+            this.prefix = prefix;
+        }
+
+        public String getNamespaceURI(String prefix) {
+            return uri;
+        }
+
+        public void setNamespaceURI(String uri) {
+            this.uri = uri;
+        }
+
+        public String getPrefix(String uri) {
+            return prefix;
+        }
+
+        public void setPrefix(String prefix) {
+            this.prefix = prefix;
+        }
+
+        public Iterator getPrefixes(String uri) {
+            return null;
+        }
+
+    }
+
+    private static class ParentTreeEntry {
+        private final int position;
+        private final PDFObject object;
+        private ParentTreeEntry(int p, PDFObject o) {
+            position = p;
+            object = o;
+        }
+        private int getPosition() {
+            return position;
+        }
+        private PDFObject getPDFObject() {
+            return object;
+        }
+     }
+
+
     /** the PDF Document being created */
     protected PDFDocument pdfDoc;
 
@@ -79,7 +167,7 @@
     /** Used for bookmarks/outlines. */
     protected Map pageReferences = new java.util.HashMap();
 
-    private PDFDocumentNavigationHandler documentNavigationHandler
+    private final PDFDocumentNavigationHandler documentNavigationHandler
             = new PDFDocumentNavigationHandler(this);
 
     /**
@@ -90,7 +178,11 @@
 
     /** {@inheritDoc} */
     public boolean supportsPagesOutOfOrder() {
-        return true;
+        if (accessEnabled) {
+            return false; // required for accessibility
+        } else {
+            return true;
+        }
     }
 
     /** {@inheritDoc} */
@@ -129,8 +221,23 @@
                 throw new IllegalStateException("OutputStream hasn't been set through setResult()");
             }
             this.pdfDoc = pdfUtil.setupPDFDocument(this.outputStream);
+            this.accessEnabled = getUserAgent().accessibilityEnabled();
+            if (accessEnabled) {
+//TODO: make document language variable, see note on wiki page PDF Accessibility
+//TODO:                and follow-up emails on fop-dev
+                this.pdfDoc.getRoot().setLanguage("en");
+                parentTree = new PDFParentTree();
+                pageSequenceCounter = 0;
+                DocumentBuilderFactory factory = DocumentBuilderFactory
+                        .newInstance();
+                factory.setNamespaceAware(true);
+                parser = factory.newDocumentBuilder();
+            }
         } catch (IOException e) {
             throw new IFException("I/O error in startDocument()", e);
+        } catch (ParserConfigurationException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
         }
     }
 
@@ -143,10 +250,34 @@
     public void endDocument() throws IFException {
         try {
             pdfDoc.getResources().addFonts(pdfDoc, fontInfo);
-            pdfDoc.outputTrailer(this.outputStream);
-
+            if (getUserAgent().accessibilityEnabled()) {
+                PDFNumsArray nums = parentTree.getNums();
+                for (int i = 0; i <= this.parentTreeKey; i++) {
+                    PDFArray tArray = new PDFArray();
+                    for (int j = 0; j < parentTreeList.size(); j++) {
+                        if (((ParentTreeEntry)parentTreeList.get(j)).getPosition() == i) {
+                            tArray.add(((ParentTreeEntry)parentTreeList.get(j)).getPDFObject());
+                        }
+                    }
+                    if (tArray.length() == 1) {
+                        nums.put(i, tArray.get(0));
+                    } else if (tArray.length() > 1) {
+                        nums.put(i, tArray);
+                    }
+                }
+                parentTree.setNums(nums);
+                pdfUtil.getStructTreeRoot().addParentTree(parentTree);
+                pdfDoc.outputTrailer(this.outputStream);
+                parser = null;
+                doc = null;
+                structElemType = null;
+                parentTree = null;
+                structTreeMap = null;
+                parentTreeList = null;
+            } else {
+                pdfDoc.outputTrailer(this.outputStream);
+            }
             this.pdfDoc = null;
-
             pdfResources = null;
             this.generator = null;
             currentContext = null;
@@ -157,9 +288,62 @@
         super.endDocument();
     }
 
+
     /** {@inheritDoc} */
     public void startPageSequence(String id) throws IFException {
         //TODO page sequence title, country and language
+
+        if (getUserAgent().accessibilityEnabled()) {
+            try {
+                if (doc == null) {
+                    doc = parser.parse(
+                            new ByteArrayInputStream(this.getUserAgent().getResultAsByteArray()));
+                }
+                PDFStructElem structElemPart = new PDFStructElem("page-sequence",
+                        pdfUtil.getStructElemDocument());
+                this.pdfDoc.assignObjectNumber(structElemPart);
+                this.pdfDoc.addTrailerObject(structElemPart);
+                pdfUtil.getStructElemDocument().addKid(structElemPart);
+
+                String xpathExpr = "/fo:root/fo:page-sequence["
+                        + Integer.toString(++pageSequenceCounter) + "]/*";
+                XPath xpath = XPathFactory.newInstance().newXPath();
+                NamespaceContext namespaceContext = new NamespaceContextImpl("fo",
+                        "http://www.w3.org/1999/XSL/Format");
+                xpath.setNamespaceContext(namespaceContext);
+
+                NodeList nodes = (NodeList) xpath.evaluate(xpathExpr, doc,
+                        XPathConstants.NODESET);
+
+                for (int i = 0, n = nodes.getLength(); i < n; i++) {
+                    Node node = nodes.item(i);
+                    if (node.getNodeName().equals("fo:flow")
+                            || node.getNodeName().equals("fo:static-content")) {
+                        PDFStructElem structElemSect = new PDFStructElem(
+                                node.getLocalName(), structElemPart);
+                        this.pdfDoc.assignObjectNumber(structElemSect);
+                        this.pdfDoc.addTrailerObject(structElemSect);
+                        structElemPart.addKid(structElemSect);
+                        NodeList iNodes = node.getChildNodes();
+                        for (int j = 0, m = iNodes.getLength(); j < m; j++) {
+                            processContent(iNodes.item(j), structElemSect, 1);
+                        }
+                    }
+                }
+            } catch (XPathExpressionException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+                throw new IFException("XPath Problem.", e);
+            } catch (SAXException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+                throw new IFException("SAX Problem.", e);
+            } catch (IOException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+                throw new IFException("IO Problem.", e);
+            }
+        }
     }
 
     /** {@inheritDoc} */
@@ -170,22 +354,25 @@
     /** {@inheritDoc} */
     public void startPage(int index, String name, String pageMasterName, Dimension size)
                 throws IFException {
+        // used for accessibility
+        this.parentTreeKey = this.parentTreeKey + this.pageLinkCount + 1;
+        this.mcidKey = 0;
+        this.pageLinkCount = 0;
+        //
         this.pdfResources = this.pdfDoc.getResources();
 
         this.currentPage = this.pdfDoc.getFactory().makePage(
             this.pdfResources,
             (int)Math.round(size.getWidth() / 1000),
-            (int)Math.round(size.getHeight() / 1000),
-            index);
-        //pageReferences.put(new Integer(index)/*page.getKey()*/, currentPage.referencePDF());
-        //pvReferences.put(page.getKey(), page);
-
+            (int)Math.round(size.getHeight() / 1000), index,
+            parentTreeKey);   // used for accessibility
         pdfUtil.generatePageLabel(index, name);
 
         currentPageRef = new PageReference(currentPage, size);
         this.pageReferences.put(new Integer(index), currentPageRef);
 
-        this.generator = new PDFContentGenerator(this.pdfDoc, this.outputStream, this.currentPage);
+        this.generator = new PDFContentGenerator(this.pdfDoc, this.outputStream,
+                this.currentPage, this.accessEnabled);
         // Transform the PDF's default coordinate system (0,0 at lower left) to the PDFPainter's
         AffineTransform basicPageTransform = new AffineTransform(1, 0, 0, -1, 0,
                 size.height / 1000f);
@@ -240,8 +427,8 @@
 
     static final class PageReference {
 
-        private PDFReference pageRef;
-        private Dimension pageDimension;
+        private final PDFReference pageRef;
+        private final Dimension pageDimension;
 
         private PageReference(PDFPage page, Dimension dim) {
             this.pageRef = page.makeReference();
@@ -257,4 +444,192 @@
         }
     }
 
+    /**
+     * Used for accessibility
+     * @param position in parentTree
+     * @param o reference of PDFObject to be added to parentTree
+     */
+    public void addToParentTree(int position, PDFObject o) {
+        PDFNumsArray nums = parentTree.getNums();
+        nums.put(position, o);
+        parentTree.setNums(nums);
+    }
+
+
+    /**
+     * Used for accessibility
+     * @param position in parentTree
+     * @param o object to be added to parentTree
+     */
+    public void addToTempList(int position, PDFObject o) {
+        ParentTreeEntry myEntry = new ParentTreeEntry(position, o);
+        this.parentTreeList.add(myEntry);
+    }
+
+
+    /**
+     * Return the PDFObject
+     * @param ptr this is the key
+     * @return PDFObject referenced with ptr
+     */
+    public PDFObject getTrailerObject(String ptr) {
+        return (PDFObject) this.structTreeMap.get(ptr);
+    }
+
+    /**
+     * Return the parent PDFObject referenced by ptr
+     * @param ptr this is the key
+     * @return PDFObject parent of PDFObject referenced with ptr
+     */
+    public PDFObject getParentTrailerObject(String ptr) {
+        PDFStructElem tempStructElem = (PDFStructElem) this.structTreeMap.get(ptr);
+        return tempStructElem.getParentStructElem();
+    }
+
+    /**
+     * Adds a link object as child to StructElem
+     * @param ptr of PDFStructElem
+     * @param o PDFLink object
+     */
+    public void addLinkToStructElem(String ptr, PDFObject o) {
+        PDFDictionary dict = new PDFDictionary();
+        dict.put("Type", new PDFName("OBJR"));
+        dict.put("Pg", this.currentPage);
+        dict.put("Obj", o);
+        PDFStructElem tempStructElem = (PDFStructElem) structTreeMap.get(ptr);
+        tempStructElem.addKid(dict);
+    }
+
+    /**
+     * Adds a child to StructElem, called from PDFPainter.drawImage
+     * @param ptr of PDFStructElem
+     * @param mcid sequence number within page
+     */
+    public void addChildToStructElemImage(String ptr, int mcid) {
+        PDFStructElem tempStructElem = (PDFStructElem) structTreeMap.get(ptr);
+        tempStructElem.addMCIDKid(mcid);
+        tempStructElem.addPage(this.currentPage);
+        if (!tempStructElem.getLevel1()) {
+            addMeToParent(tempStructElem);
+        }
+    }
+
+
+    /**
+     * Adds a child to StructElem, called from PDFPainter.drawText
+     * @param ptr of PDFSturctElem
+     * @param mcid sequence number within page
+     */
+    public void addChildToStructElemText(String ptr, int mcid) {
+        PDFDictionary dict = new PDFDictionary();
+        dict.put("Type", new PDFName("MCR"));
+        dict.put("Pg", this.currentPage);
+        dict.put("MCID", mcid);
+        PDFStructElem tempStructElem = (PDFStructElem) structTreeMap.get(ptr);
+        tempStructElem.addKid(dict);
+        if (!tempStructElem.getLevel1()) {
+            addMeToParent(tempStructElem);
+        }
+    }
+
+    /**
+     * Add child PDFStructElem to parent child elements
+     * Repeat until level 1 or child already exists
+     * @param childStructElem to be added
+     */
+    protected void addMeToParent(PDFStructElem childStructElem) {
+        PDFStructElem parentStructElem = (PDFStructElem) childStructElem.getParentStructElem();
+        // test if child already exists or not
+        if (parentStructElem.addUniqueKid(childStructElem)) {
+            if (!parentStructElem.getLevel1()) {
+                addMeToParent(parentStructElem);
+            }
+        }
+    }
+
+    /**
+     * increment MCID value
+     */
+    public void incMCID() {
+        this.mcidKey++;
+    }
+
+    /**
+     * MCID is a sequential number per page
+     * @return MCID value
+     */
+    public int getMCID() {
+        return this.mcidKey;
+    }
+
+    /**
+     * Used for accessibility
+     * @param ptr pointer into map of all structElems
+     * @return type of found structElem
+     */
+    public String getStructElemType(String ptr) {
+        return (String) structElemType.get(ptr);
+    }
+
+    /**
+     * Used for accessibility
+     * @param me node being processed
+     * @param parent parent node in DOM of me
+     * @param depth depth level in DOM, static-content & flow are 0
+     */
+    private void processContent(Node me, PDFStructElem parent, int depth) {
+        String ptr;
+        Node attr = me.getAttributes().getNamedItem("foi:ptr");
+        if (attr != null) {
+            ptr = attr.getNodeValue();
+        } else {
+            log.error("Accessibility: missing foi:ptr");
+            ptr = "";
+        }
+        String s = me.getLocalName();
+        PDFStructElem structElem = new PDFStructElem(s, parent);
+        this.pdfDoc.assignObjectNumber(structElem);
+        this.pdfDoc.addTrailerObject(structElem);
+        if (depth == 1) {
+            parent.addKid(structElem);
+            structElem.setLevel1();
+        }
+        if (s.equals("external-graphic") || s.equals("instream-foreign-object")) {
+            Node altTextNode = me.getAttributes().getNamedItem("fox:alt-text");
+            if (altTextNode != null) {
+                structElem.put("Alt", altTextNode.getNodeValue());
+            } else {
+                log.warn("fo:" + s
+                 + " requires an alternative text attribute fox:alt-text for accessibility");
+                structElem.put("Alt", "No alternate text specified");
+            }
+        }
+        // the following map is used e.g. in PDFPainter.drawText
+        structElemType.put(ptr, structElem.get("S").toString());
+        // this map will be used for fast access of the StructElem by ptr
+        structTreeMap.put(ptr, structElem);
+        NodeList nodes = me.getChildNodes();
+        depth++;
+        for (int i = 0, n = nodes.getLength(); i < n; i++) {
+            processContent(nodes.item(i), structElem, depth);
+        }
+    }
+
+    /**
+     * used for accessibility
+     * @return mcid to be used for next link to be processed
+     */
+    public int getPageLinkCountPlusPageParentKey() {
+        this.pageLinkCount++;
+        return (this.parentTreeKey + this.pageLinkCount);
+    }
+
+    /**
+     * used for accessibility
+     * @return current parentTreeKey
+     */
+    public int getCurrentParentTreeKey() {
+        return this.parentTreeKey;
+    }
+
 }
Index: src/java/org/apache/fop/render/pdf/PDFDocumentNavigationHandler.java
===================================================================
--- src/java/org/apache/fop/render/pdf/PDFDocumentNavigationHandler.java	(revision 744229)
+++ src/java/org/apache/fop/render/pdf/PDFDocumentNavigationHandler.java	(working copy)
@@ -42,16 +42,19 @@
 import org.apache.fop.render.intermediate.extensions.URIAction;
 import org.apache.fop.render.pdf.PDFDocumentHandler.PageReference;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
 /**
  * Implementation of the {@link IFDocumentNavigationHandler} interface for PDF output.
  */
 public class PDFDocumentNavigationHandler implements IFDocumentNavigationHandler {
+    private static Log log = LogFactory.getLog(PDFDocumentHandler.class);
+    private final PDFDocumentHandler documentHandler;
 
-    private PDFDocumentHandler documentHandler;
+    private final Map incompleteActions = new java.util.HashMap();
+    private final Map completeActions = new java.util.HashMap();
 
-    private Map incompleteActions = new java.util.HashMap();
-    private Map completeActions = new java.util.HashMap();
-
     /**
      * Default constructor.
      * @param documentHandler the parent document handler
@@ -111,6 +114,14 @@
         PDFLink pdfLink = getPDFDoc().getFactory().makeLink(
                 targetRect2D, pdfAction);
         if (pdfLink != null) {
+          //accessibility: ptr has a value
+            String ptr = link.getAction().getPtr();
+            if (ptr.length() > 0) {
+                this.documentHandler.addLinkToStructElem(ptr, pdfLink);
+                int id = this.documentHandler.getPageLinkCountPlusPageParentKey();
+                pdfLink.setStructParent(id);
+                this.documentHandler.addToParentTree(id, pdfLink );
+            }
             documentHandler.currentPage.addAnnotation(pdfLink);
         }
     }
Index: src/java/org/apache/fop/render/pdf/PDFImageHandlerRawJPEG.java
===================================================================
--- src/java/org/apache/fop/render/pdf/PDFImageHandlerRawJPEG.java	(revision 744229)
+++ src/java/org/apache/fop/render/pdf/PDFImageHandlerRawJPEG.java	(working copy)
@@ -82,7 +82,17 @@
         float y = (float)pos.getY() / 1000f;
         float w = (float)pos.getWidth() / 1000f;
         float h = (float)pos.getHeight() / 1000f;
-        generator.placeImage(x, y, w, h, xobj);
+        if (context.getUserAgent().accessibilityEnabled()) {
+            String structElemType = pdfContext.getStructElemType();
+            if (structElemType.length() > 0) {
+                int sequenceNum = pdfContext.getSequenceNum();
+                generator.placeImage(x, y, w, h, xobj, structElemType, sequenceNum);
+            } else {
+                generator.placeImage(x, y, w, h, xobj);
+            }
+        } else {
+            generator.placeImage(x, y, w, h, xobj);
+        }
     }
 
     /** {@inheritDoc} */
Index: src/java/org/apache/fop/render/pdf/PDFImageHandlerRenderedImage.java
===================================================================
--- src/java/org/apache/fop/render/pdf/PDFImageHandlerRenderedImage.java	(revision 744229)
+++ src/java/org/apache/fop/render/pdf/PDFImageHandlerRenderedImage.java	(working copy)
@@ -83,7 +83,13 @@
         float y = (float)pos.getY() / 1000f;
         float w = (float)pos.getWidth() / 1000f;
         float h = (float)pos.getHeight() / 1000f;
-        generator.placeImage(x, y, w, h, xobj);
+        if (context.getUserAgent().accessibilityEnabled()) {
+            String structElemType = pdfContext.getStructElemType();
+            int sequenceNum = pdfContext.getSequenceNum();
+            generator.placeImage(x, y, w, h, xobj, structElemType, sequenceNum);
+        } else {
+            generator.placeImage(x, y, w, h, xobj);
+        }
     }
 
     /** {@inheritDoc} */
Index: src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java
===================================================================
--- src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java	(revision 744229)
+++ src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java	(working copy)
@@ -101,8 +101,8 @@
         float w = (float)ctx.getDocumentSize().getWidth() * 1000f;
         float h = (float)ctx.getDocumentSize().getHeight() * 1000f;
 
-        float sx = pos.width / (float)w;
-        float sy = pos.height / (float)h;
+        float sx = pos.width / w;
+        float sy = pos.height / h;
 
         //Scaling and translation for the bounding box of the image
         AffineTransform scaling = new AffineTransform(
@@ -119,8 +119,14 @@
          * Note: To have the svg overlay (under) a text area then use
          * an fo:block-container
          */
+
+        generator.saveGraphicsState();
         generator.comment("SVG setup");
-        generator.saveGraphicsState();
+        if (context.getUserAgent().accessibilityEnabled()) {
+            String structElemType = pdfContext.getStructElemType();
+            int sequenceNum = pdfContext.getSequenceNum();
+            generator.startAccessSequence(structElemType, sequenceNum);
+        }
         generator.setColor(Color.black, false);
         generator.setColor(Color.black, true);
 
@@ -168,7 +174,11 @@
             eventProducer.svgRenderingError(this, e, image.getInfo().getOriginalURI());
         }
         generator.getState().restore();
-        generator.restoreGraphicsState();
+        if (context.getUserAgent().accessibilityEnabled()) {
+            generator.restoreGraphicsStateAccess();
+        } else {
+            generator.restoreGraphicsState();
+        }
         generator.comment("SVG end");
     }
 
Index: src/java/org/apache/fop/render/pdf/PDFPainter.java
===================================================================
--- src/java/org/apache/fop/render/pdf/PDFPainter.java	(revision 744229)
+++ src/java/org/apache/fop/render/pdf/PDFPainter.java	(working copy)
@@ -59,13 +59,19 @@
     /** logging instance */
     private static Log log = LogFactory.getLog(PDFPainter.class);
 
-    private PDFDocumentHandler documentHandler;
+    private final PDFDocumentHandler documentHandler;
 
     /** The current content generator */
     protected PDFContentGenerator generator;
 
-    private PDFBorderPainter borderPainter;
+    private final PDFBorderPainter borderPainter;
 
+    private boolean accessEnabled = false;
+
+    private int mcid; // used for accessibility
+
+    private String structElemType; // used for accessibility
+
     /**
      * Default constructor.
      * @param documentHandler the parent document handler
@@ -76,6 +82,7 @@
         this.generator = documentHandler.generator;
         this.borderPainter = new PDFBorderPainter(this.generator);
         this.state = IFState.create();
+        accessEnabled = this.getUserAgent().accessibilityEnabled();
     }
 
     /** {@inheritDoc} */
@@ -122,15 +129,50 @@
     }
 
     /** {@inheritDoc} */
-    public void drawImage(String uri, Rectangle rect) throws IFException {
+    public void drawImage(String uri, Rectangle rect, String ptr)
+            throws IFException {
         PDFXObject xobject = getPDFDoc().getXObject(uri);
         if (xobject != null) {
-            placeImage(rect, xobject);
+            if (accessEnabled && ptr.length() > 0) {
+                mcid = this.documentHandler.getMCID();
+                mcid++;                          // fix for Acro Checker
+                this.documentHandler.incMCID();  // simulating a parent text element
+                structElemType = this.documentHandler.getStructElemType(ptr);
+                this.documentHandler.addToTempList(
+                        this.documentHandler.getCurrentParentTreeKey(),
+                        this.documentHandler.getParentTrailerObject(ptr));
+                this.documentHandler.addToTempList(
+                        this.documentHandler.getCurrentParentTreeKey(),
+                        this.documentHandler.getTrailerObject(ptr));
+                placeImageAccess(rect, xobject);
+                this.documentHandler.addChildToStructElemImage(ptr, mcid);
+                this.documentHandler.incMCID();
+            } else {
+                placeImage(rect, xobject);
+            }
             return;
         }
-
-        drawImageUsingURI(uri, rect);
-
+        if (accessEnabled && ptr.length() > 0) {
+            mcid = this.documentHandler.getMCID();
+            mcid++;                          // fix for Acro Checker
+            this.documentHandler.incMCID();  // simulating a parent text element
+            structElemType = this.documentHandler.getStructElemType(ptr);
+            this.documentHandler.addToTempList(
+                    this.documentHandler.getCurrentParentTreeKey(),
+                    this.documentHandler.getParentTrailerObject(ptr));
+            this.documentHandler.addToTempList(
+                    this.documentHandler.getCurrentParentTreeKey(),
+                    this.documentHandler.getTrailerObject(ptr));
+            //PDFRenderingContext pdfContext = new PDFRenderingContext(
+            //        getUserAgent(), generator, this.documentHandler.currentPage, getFontInfo());
+            //pdfContext.setMCID(mcid);
+            //pdfContext.setStructElemType(structElemType);
+            drawImageUsingURI(uri, rect);
+            this.documentHandler.addChildToStructElemImage(ptr, mcid);
+            this.documentHandler.incMCID();
+        } else {
+            drawImageUsingURI(uri, rect);
+        }
         flushPDFDoc();
     }
 
@@ -138,6 +180,8 @@
     protected RenderingContext createRenderingContext() {
         PDFRenderingContext pdfContext = new PDFRenderingContext(
                 getUserAgent(), generator, this.documentHandler.currentPage, getFontInfo());
+        pdfContext.setMCID(mcid);
+        pdfContext.setStructElemType(structElemType);
         return pdfContext;
     }
 
@@ -158,11 +202,45 @@
                           + " cm " + xobj.getName() + " Do\n");
         generator.restoreGraphicsState();
     }
+    /**
+     * Places a previously registered image at a certain place on the page - Accessibility version
+     * @param x X coordinate
+     * @param y Y coordinate
+     * @param w width for image
+     * @param h height for image
+     * @param xobj the image XObject
+     */
+    private void placeImageAccess(Rectangle rect, PDFXObject xobj) {
+        generator.saveGraphicsState(structElemType, mcid);
+        generator.add(format(rect.width) + " 0 0 "
+                          + format(-rect.height) + " "
+                          + format(rect.x) + " "
+                          + format(rect.y + rect.height )
+                          + " cm " + xobj.getName() + " Do\n");
+        generator.restoreGraphicsStateAccess();
+    }
 
+
+
     /** {@inheritDoc} */
-    public void drawImage(Document doc, Rectangle rect) throws IFException {
-        drawImageUsingDocument(doc, rect);
-
+    public void drawImage(Document doc, Rectangle rect, String ptr) throws IFException {
+        if (accessEnabled && ptr.length() > 0) {
+            mcid = this.documentHandler.getMCID();
+            mcid++;                          // fix for Acro Checker
+            this.documentHandler.incMCID();  // simulating a parent text element
+            structElemType = this.documentHandler.getStructElemType(ptr);
+            this.documentHandler.addToTempList(
+                    this.documentHandler.getCurrentParentTreeKey(),
+                    this.documentHandler.getParentTrailerObject(ptr));
+            this.documentHandler.addToTempList(
+                    this.documentHandler.getCurrentParentTreeKey(),
+                    this.documentHandler.getTrailerObject(ptr));
+            drawImageUsingDocument(doc, rect);
+            this.documentHandler.addChildToStructElemImage(ptr, mcid);
+            this.documentHandler.incMCID();
+        } else {
+            drawImageUsingDocument(doc, rect);
+        }
         flushPDFDoc();
     }
 
@@ -253,10 +331,46 @@
     }
 
     /** {@inheritDoc} */
-    public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[] dx, String text)
+    public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[] dx,
+            String text, String ptr)
             throws IFException {
-        generator.updateColor(state.getTextColor(), true, null);
-        generator.beginTextObject();
+        if (accessEnabled ) {
+            int mcId;
+            String structElType = "";
+            if (ptr != null) {
+                if (ptr.length() > 0) {
+                    mcId = this.documentHandler.getMCID();
+                    this.documentHandler.addToTempList(
+                            this.documentHandler.getCurrentParentTreeKey(),
+                            this.documentHandler.getTrailerObject(ptr));
+                    structElType = this.documentHandler.getStructElemType(ptr);
+                    if (generator.getTextUtil().isInTextObject()) {
+                        generator.separateTextElements(mcId, structElType);
+                    }
+                    generator.updateColor(state.getTextColor(), true, null);
+                    generator.beginTextObjectAccess(mcId, structElType);
+                    this.documentHandler.addChildToStructElemText(ptr, mcId);
+                    this.documentHandler.incMCID();
+                }
+                else {
+                    // <fo:leader leader-pattern="use-content">
+                    if (generator.getTextUtil().isInTextObject()) {
+                        generator.separateTextElementFromLeader();
+                    }
+                    generator.updateColor(state.getTextColor(), true, null);
+                    generator.beginLeaderTextObject();
+                }
+            } else {
+                generator.updateColor(state.getTextColor(), true, null);
+                generator.beginTextObject();
+            }
+        } else {
+            generator.updateColor(state.getTextColor(), true, null);
+            generator.beginTextObject();
+        }
+
+
+
         FontTriplet triplet = new FontTriplet(
                 state.getFontFamily(), state.getFontStyle(), state.getFontWeight());
         //TODO Ignored: state.getFontVariant()
@@ -277,7 +391,7 @@
         PDFTextUtil textutil = generator.getTextUtil();
         textutil.updateTf(fontKey, fontSize, tf.isMultiByte());
 
-        generator.updateCharacterSpacing((float)letterSpacing / 1000f);
+        generator.updateCharacterSpacing(letterSpacing / 1000f);
 
         textutil.writeTextMatrix(new AffineTransform(1, 0, 0, -1, x / 1000f, y / 1000f));
         int l = text.length();
Index: src/java/org/apache/fop/render/pdf/PDFRenderer.java
===================================================================
--- src/java/org/apache/fop/render/pdf/PDFRenderer.java	(revision 744229)
+++ src/java/org/apache/fop/render/pdf/PDFRenderer.java	(working copy)
@@ -433,7 +433,7 @@
         this.currentPage = this.pdfDoc.getFactory().makePage(
             this.pdfResources,
             (int) Math.round(w / 1000), (int) Math.round(h / 1000),
-            page.getPageIndex());
+            page.getPageIndex(), -1);
         pageReferences.put(page.getKey(), currentPage.referencePDF());
         //pvReferences.put(page.getKey(), page);
 
@@ -461,7 +461,8 @@
         double h = bounds.getHeight();
         pageHeight = (int) h;
 
-        this.generator = new PDFContentGenerator(this.pdfDoc, this.ostream, this.currentPage);
+        this.generator = new PDFContentGenerator(this.pdfDoc, this.ostream, this.currentPage, 
+                this.getUserAgent().accessibilityEnabled());
         this.borderPainter = new PDFBorderPainter(this.generator);
 
         // Transform the PDF's default coordinate system (0,0 at lower left) to the PDFRenderer's
@@ -1073,7 +1074,7 @@
     }
 
     /** {@inheritDoc} */
-    protected void drawImage(String url, Rectangle2D pos, Map foreignAttributes) {
+    protected void drawImage(String url, Rectangle2D pos, Map foreignAttributes, String ptr) {
         endTextObject();
         putImage(url, pos, foreignAttributes);
     }
Index: src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java
===================================================================
--- src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java	(revision 744229)
+++ src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java	(working copy)
@@ -69,6 +69,7 @@
         }
     }
 
+    
     private void configure(Configuration cfg, PDFRenderingUtil pdfUtil) throws FOPException {
         //PDF filters
         try {
Index: src/java/org/apache/fop/render/pdf/PDFRenderingContext.java
===================================================================
--- src/java/org/apache/fop/render/pdf/PDFRenderingContext.java	(revision 744229)
+++ src/java/org/apache/fop/render/pdf/PDFRenderingContext.java	(working copy)
@@ -31,10 +31,15 @@
  */
 public class PDFRenderingContext extends AbstractRenderingContext {
 
-    private PDFContentGenerator generator;
-    private FontInfo fontInfo;
-    private PDFPage page;
+    private final PDFContentGenerator generator;
+    private final FontInfo fontInfo;
+    private final PDFPage page;
+    /** Temp. val. for accessibility, used in PDFImageHandlerRenderedImage */
+    private String structElemType = "";
 
+    /** Temp. val. for accessibility, used in PDFImageHandlerRenderedImage */
+    private int mcid = -1;
+
     /**
      * Main constructor.
      * @param userAgent the user agent
@@ -79,4 +84,35 @@
         return this.fontInfo;
     }
 
+    /**
+     * Used for accessibility, used in PDFPainter.drawImage
+     * @param value to be stored
+     */
+    public void setMCID(int value) {
+        mcid = value;
+    }
+
+    /**
+     * Used for accessibility
+     * @return mcid
+     */
+    public int getSequenceNum() {
+        return mcid;
+    }
+
+    /**
+     * Used for accessibility
+     * @param s the type of the structure element
+     */
+    public void setStructElemType(String s) {
+        structElemType = s;
+    }
+
+    /**
+     * Used for accessibility
+     * @return the type of the structure element
+     */
+    public String getStructElemType() {
+        return structElemType;
+    }
 }
Index: src/java/org/apache/fop/render/pdf/PDFRenderingUtil.java
===================================================================
--- src/java/org/apache/fop/render/pdf/PDFRenderingUtil.java	(revision 744229)
+++ src/java/org/apache/fop/render/pdf/PDFRenderingUtil.java	(working copy)
@@ -52,6 +52,8 @@
 import org.apache.fop.pdf.PDFNumsArray;
 import org.apache.fop.pdf.PDFOutputIntent;
 import org.apache.fop.pdf.PDFPageLabels;
+import org.apache.fop.pdf.PDFStructElem;
+import org.apache.fop.pdf.PDFStructTreeRoot;
 import org.apache.fop.pdf.PDFXMode;
 import org.apache.fop.util.ColorProfileUtil;
 
@@ -64,7 +66,7 @@
     /** logging instance */
     private static Log log = LogFactory.getLog(PDFRenderingUtil.class);
 
-    private FOUserAgent userAgent;
+    private final FOUserAgent userAgent;
 
     /** the PDF Document being created */
     protected PDFDocument pdfDoc;
@@ -75,12 +77,21 @@
     /** the PDF/X mode (Default: disabled) */
     protected PDFXMode pdfXMode = PDFXMode.DISABLED;
 
+    /** the accessibility mode (Default: false=disabled) */
+    protected boolean accessibility = false;
+
     /** the (optional) encryption parameters */
     protected PDFEncryptionParams encryptionParams;
 
     /** Registry of PDF filters */
     protected Map filterMap;
 
+    /** used for accessibility */
+    protected PDFStructTreeRoot structTreeRoot = null;
+
+    /** used for accessibility */
+    protected PDFStructElem structElemDocument = null;
+
     /** the ICC stream used as output profile by this document for PDF/A and PDF/X functionality. */
     protected PDFICCStream outputProfile;
     /** the default sRGB color space. */
@@ -157,6 +168,8 @@
             }
             this.encryptionParams.setAllowEditAnnotations(!booleanValueOf(setting));
         }
+
+
         String s = (String)userAgent.getRendererOptions().get(PDF_A_MODE);
         if (s != null) {
             this.pdfAMode = PDFAMode.valueOf(s);
@@ -169,6 +182,12 @@
         if (s != null) {
             this.outputProfileURI = s;
         }
+        // used for accessibility
+        setting = userAgent.getRendererOptions().get(ACCESSIBLITY);
+        if (setting != null) {
+            this.accessibility = booleanValueOf(setting);
+        }
+
         setting = userAgent.getRendererOptions().get(KEY_DISABLE_SRGB_COLORSPACE);
         if (setting != null) {
             this.disableSRGBColorSpace = booleanValueOf(setting);
@@ -384,10 +403,36 @@
             log.debug("PDF/A is active. Conformance Level: " + pdfAMode);
             addPDFA1OutputIntent();
         }
+        if (this.accessibility) {
+            this.pdfDoc.getRoot().makeTagged();
+            log.info("Accessibility is enabled");
+            structTreeRoot = this.pdfDoc.getFactory().makeStructTreeRoot();
+            this.pdfDoc.getRoot().setStructTreeRoot(structTreeRoot);
+            structElemDocument = new PDFStructElem("root", structTreeRoot);
+            this.pdfDoc.assignObjectNumber(structElemDocument);
+            this.pdfDoc.addTrailerObject(structElemDocument);
+            structTreeRoot.addKid(structElemDocument);
+        }
         return this.pdfDoc;
     }
 
     /**
+     * Used for accessibility
+     * @return the Structure Tree Root element
+     */
+    public PDFStructTreeRoot getStructTreeRoot() {
+        return this.structTreeRoot;
+    }
+
+    /**
+     * Used for accessibility
+     * @return the Structure Tree Document Element
+     */
+    public PDFStructElem getStructElemDocument() {
+        return this.structElemDocument;
+    }
+
+    /**
      * Generates a page label in the PDF document.
      * @param pageIndex the index of the page
      * @param pageNumber the formatted page number
Index: src/java/org/apache/fop/render/ps/PSEventProducer.xml
===================================================================
--- src/java/org/apache/fop/render/ps/PSEventProducer.xml	(revision 744229)
+++ src/java/org/apache/fop/render/ps/PSEventProducer.xml	(working copy)
@@ -1,3 +1,4 @@
-<?xml version="1.0" encoding="UTF-8"?><catalogue xml:lang="en">
+<?xml version="1.0" encoding="UTF-8"?>
+<catalogue xml:lang="en">
   <message key="org.apache.fop.render.ps.PSEventProducer.postscriptDictionaryParseError">Failed to parse dictionary string. Reason: {e}, content = "{content}"</message>
 </catalogue>
Index: src/java/org/apache/fop/render/ps/PSPainter.java
===================================================================
--- src/java/org/apache/fop/render/ps/PSPainter.java	(revision 744229)
+++ src/java/org/apache/fop/render/ps/PSPainter.java	(working copy)
@@ -176,7 +176,7 @@
     }
 
     /** {@inheritDoc} */
-    public void drawImage(String uri, Rectangle rect) throws IFException {
+    public void drawImage(String uri, Rectangle rect, String ptr) throws IFException {
         try {
             endTextObject();
         } catch (IOException ioe) {
@@ -186,7 +186,7 @@
     }
 
     /** {@inheritDoc} */
-    public void drawImage(Document doc, Rectangle rect) throws IFException {
+    public void drawImage(Document doc, Rectangle rect, String ptr) throws IFException {
         try {
             endTextObject();
         } catch (IOException ioe) {
@@ -338,7 +338,7 @@
 
     /** {@inheritDoc} */
     public void drawText(int x, int y, int letterSpacing, int wordSpacing,
-            int[] dx, String text) throws IFException {
+            int[] dx, String text, String ptr) throws IFException {
         try {
             //Note: dy is currently ignored
             PSGenerator generator = getGenerator();
Index: src/java/org/apache/fop/render/ps/PSRenderer.java
===================================================================
--- src/java/org/apache/fop/render/ps/PSRenderer.java	(revision 744229)
+++ src/java/org/apache/fop/render/ps/PSRenderer.java	(working copy)
@@ -345,7 +345,7 @@
     }
 
     /** {@inheritDoc} */
-    protected void drawImage(String uri, Rectangle2D pos, Map foreignAttributes) {
+    protected void drawImage(String uri, Rectangle2D pos, Map foreignAttributes, String ptr) {
         endTextObject();
         int x = currentIPPosition + (int)Math.round(pos.getX());
         int y = currentBPPosition + (int)Math.round(pos.getY());
@@ -1233,7 +1233,7 @@
      * {@inheritDoc}
      */
     public void renderImage(Image image, Rectangle2D pos) {
-        drawImage(image.getURL(), pos, image.getForeignAttributes());
+        drawImage(image.getURL(), pos, image.getForeignAttributes(), "");
     }
 
     /**
Index: src/java/org/apache/fop/render/txt/TXTRenderer.java
===================================================================
--- src/java/org/apache/fop/render/txt/TXTRenderer.java	(revision 744229)
+++ src/java/org/apache/fop/render/txt/TXTRenderer.java	(working copy)
@@ -443,7 +443,7 @@
     }
 
     /** {@inheritDoc} */
-    protected void drawImage(String url, Rectangle2D pos, Map foreignAttributes) {
+    protected void drawImage(String url, Rectangle2D pos, Map foreignAttributes, String ptr) {
         //No images are painted here
     }
 
Index: src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java
===================================================================
--- src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java	(revision 744229)
+++ src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java	(working copy)
@@ -316,7 +316,7 @@
 
         PDFResources pdfResources = this.pdfDoc.getResources();
         PDFPage page = this.pdfDoc.getFactory().makePage(pdfResources,
-                width, height);
+                width, height, -1);
         resourceContext = page;
         pdfContext.setCurrentPage(page);
         pageRef = page.referencePDF();
Index: src/java/org/apache/fop/svg/PDFTextPainter.java
===================================================================
--- src/java/org/apache/fop/svg/PDFTextPainter.java	(revision 744229)
+++ src/java/org/apache/fop/svg/PDFTextPainter.java	(working copy)
@@ -145,7 +145,7 @@
 
             applyColorAndPaint(tpi, pdf);
 
-            textUtil.beginTextObject();
+            textUtil.beginTextObject(); 
             textUtil.setFonts(fonts);
             boolean stroke = (tpi.strokePaint != null)
                 && (tpi.strokeStroke != null);
@@ -239,7 +239,7 @@
                 prevVisibleCharWidth = textUtil.getCurrentFont().getCharWidth(chars.charAt(index));
             }
             textUtil.writeTJ();
-            textUtil.endTextObject();
+            textUtil.endTextObject(false);  
             textUtil.restoreGraphicsState();
             if (DEBUG) {
                 g2d.setStroke(new BasicStroke(0));
Index: src/java/org/apache/fop/util/DOM2SAX.java
===================================================================
--- src/java/org/apache/fop/util/DOM2SAX.java	(revision 744229)
+++ src/java/org/apache/fop/util/DOM2SAX.java	(working copy)
@@ -77,6 +77,18 @@
             contentHandler.endDocument();
         }
     }
+    
+    
+    /**
+     * Writes the given fragment using the given ContentHandler.
+     * @param node DOM node
+     * @throws SAXException In case of a problem while writing XML
+     */
+    public void writeFragment(Node node) throws SAXException {
+        writeNode(node);
+    }
+    
+    
 
     /**
      * Begin the scope of namespace prefix. Forward the event to the SAX handler
Index: src/sandbox/org/apache/fop/render/svg/SVGPainter.java
===================================================================
--- src/sandbox/org/apache/fop/render/svg/SVGPainter.java	(revision 744229)
+++ src/sandbox/org/apache/fop/render/svg/SVGPainter.java	(working copy)
@@ -193,7 +193,7 @@
     }
 
     /** {@inheritDoc} */
-    public void drawImage(String uri, Rectangle rect) throws IFException {
+    public void drawImage(String uri, Rectangle rect, String ptr) throws IFException {
         try {
             establish(MODE_NORMAL);
 
@@ -243,7 +243,7 @@
     }
 
     /** {@inheritDoc} */
-    public void drawImage(Document doc, Rectangle rect) throws IFException {
+    public void drawImage(Document doc, Rectangle rect, String ptr) throws IFException {
         try {
             establish(MODE_NORMAL);
 
@@ -325,8 +325,10 @@
     }
 
     /** {@inheritDoc} */
-    public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[] dx, String text)
-                throws IFException {
+
+    public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[] dx, 
+            String text, String ptr) throws IFException {
+        //Note: ptr is ignored as it is only needed for accessibility
         try {
             establish(MODE_TEXT);
             AttributesImpl atts = new AttributesImpl();
Index: src/sandbox/org/apache/fop/render/svg/SVGPainter.java.mine
===================================================================
--- src/sandbox/org/apache/fop/render/svg/SVGPainter.java.mine	(revision 0)
+++ src/sandbox/org/apache/fop/render/svg/SVGPainter.java.mine	(revision 0)
@@ -0,0 +1,409 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: SVGPainter.java 741165 2009-02-05 16:27:08Z jeremias $ */
+
+package org.apache.fop.render.svg;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Paint;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Map;
+
+import org.w3c.dom.Document;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.xmlgraphics.image.loader.ImageException;
+import org.apache.xmlgraphics.image.loader.ImageInfo;
+import org.apache.xmlgraphics.image.loader.ImageManager;
+import org.apache.xmlgraphics.image.loader.ImageSessionContext;
+import org.apache.xmlgraphics.xmp.Metadata;
+
+import org.apache.fop.apps.MimeConstants;
+import org.apache.fop.events.ResourceEventProducer;
+import org.apache.fop.render.ImageHandlerUtil;
+import org.apache.fop.render.RenderingContext;
+import org.apache.fop.render.intermediate.AbstractIFPainter;
+import org.apache.fop.render.intermediate.IFConstants;
+import org.apache.fop.render.intermediate.IFContext;
+import org.apache.fop.render.intermediate.IFException;
+import org.apache.fop.render.intermediate.IFState;
+import org.apache.fop.render.intermediate.IFUtil;
+import org.apache.fop.traits.BorderProps;
+import org.apache.fop.traits.RuleStyle;
+import org.apache.fop.util.ColorUtil;
+import org.apache.fop.util.GenerationHelperContentHandler;
+import org.apache.fop.util.XMLConstants;
+import org.apache.fop.util.XMLUtil;
+
+/**
+ * IFPainter implementation that writes SVG.
+ */
+public class SVGPainter extends AbstractIFPainter implements SVGConstants {
+
+    /** logging instance */
+    private static Log log = LogFactory.getLog(SVGPainter.class);
+
+    private AbstractSVGDocumentHandler parent;
+
+    /** The SAX content handler that receives the generated XML events. */
+    protected GenerationHelperContentHandler handler;
+
+    private static final int MODE_NORMAL = 0;
+    private static final int MODE_TEXT = 1;
+
+    private int mode = MODE_NORMAL;
+
+    /**
+     * Main constructor.
+     * @param parent the parent document handler
+     * @param contentHandler the target SAX content handler
+     */
+    public SVGPainter(AbstractSVGDocumentHandler parent,
+            GenerationHelperContentHandler contentHandler) {
+        super();
+        this.parent = parent;
+        this.handler = contentHandler;
+        this.state = IFState.create();
+    }
+
+    /** {@inheritDoc} */
+    protected IFContext getContext() {
+        return parent.getContext();
+    }
+
+    /** {@inheritDoc} */
+    public void startViewport(AffineTransform transform, Dimension size, Rectangle clipRect)
+            throws IFException {
+        startViewport(IFUtil.toString(transform), size, clipRect);
+    }
+
+    /** {@inheritDoc} */
+    public void startViewport(AffineTransform[] transforms, Dimension size, Rectangle clipRect)
+            throws IFException {
+        startViewport(IFUtil.toString(transforms), size, clipRect);
+    }
+
+    private void startViewport(String transform, Dimension size, Rectangle clipRect)
+            throws IFException {
+        try {
+            establish(MODE_NORMAL);
+            AttributesImpl atts = new AttributesImpl();
+            if (transform != null && transform.length() > 0) {
+                XMLUtil.addAttribute(atts, "transform", transform);
+            }
+            handler.startElement("g", atts);
+
+            atts.clear();
+            XMLUtil.addAttribute(atts, "width", Integer.toString(size.width));
+            XMLUtil.addAttribute(atts, "height", Integer.toString(size.height));
+            if (clipRect != null) {
+                int[] v = new int[] {
+                        clipRect.y,
+                        -clipRect.x + size.width - clipRect.width,
+                        -clipRect.y + size.height - clipRect.height,
+                        clipRect.x};
+                int sum = 0;
+                for (int i = 0; i < 4; i++) {
+                    sum += Math.abs(v[i]);
+                }
+                if (sum != 0) {
+                    StringBuffer sb = new StringBuffer("rect(");
+                    sb.append(v[0]).append(',');
+                    sb.append(v[1]).append(',');
+                    sb.append(v[2]).append(',');
+                    sb.append(v[3]).append(')');
+                    XMLUtil.addAttribute(atts, "clip", sb.toString());
+                }
+                XMLUtil.addAttribute(atts, "overflow", "hidden");
+            } else {
+                XMLUtil.addAttribute(atts, "overflow", "visible");
+            }
+            handler.startElement("svg", atts);
+        } catch (SAXException e) {
+            throw new IFException("SAX error in startBox()", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void endViewport() throws IFException {
+        try {
+            establish(MODE_NORMAL);
+            handler.endElement("svg");
+            handler.endElement("g");
+        } catch (SAXException e) {
+            throw new IFException("SAX error in endBox()", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void startGroup(AffineTransform[] transforms) throws IFException {
+        startGroup(IFUtil.toString(transforms));
+    }
+
+    /** {@inheritDoc} */
+    public void startGroup(AffineTransform transform) throws IFException {
+        startGroup(IFUtil.toString(transform));
+    }
+
+    private void startGroup(String transform) throws IFException {
+        try {
+            AttributesImpl atts = new AttributesImpl();
+            if (transform != null && transform.length() > 0) {
+                XMLUtil.addAttribute(atts, "transform", transform);
+            }
+            handler.startElement("g", atts);
+        } catch (SAXException e) {
+            throw new IFException("SAX error in startGroup()", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void endGroup() throws IFException {
+        try {
+            establish(MODE_NORMAL);
+            handler.endElement("g");
+        } catch (SAXException e) {
+            throw new IFException("SAX error in endGroup()", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void drawImage(String uri, Rectangle rect, String ptr) throws IFException {
+        try {
+            establish(MODE_NORMAL);
+
+            ImageManager manager = getUserAgent().getFactory().getImageManager();
+            ImageInfo info = null;
+            try {
+                ImageSessionContext sessionContext = getUserAgent().getImageSessionContext();
+                info = manager.getImageInfo(uri, sessionContext);
+
+                String mime = info.getMimeType();
+                Map foreignAttributes = getContext().getForeignAttributes();
+                String conversionMode = (String)foreignAttributes.get(
+                        ImageHandlerUtil.CONVERSION_MODE);
+                if ("reference".equals(conversionMode)
+                        && (MimeConstants.MIME_GIF.equals(mime)
+                        || MimeConstants.MIME_JPEG.equals(mime)
+                        || MimeConstants.MIME_PNG.equals(mime)
+                        || MimeConstants.MIME_SVG.equals(mime))) {
+                    //Just reference the image
+                    //TODO Some additional URI rewriting might be necessary
+                    AttributesImpl atts = new AttributesImpl();
+                    XMLUtil.addAttribute(atts, IFConstants.XLINK_HREF, uri);
+                    XMLUtil.addAttribute(atts, "x", Integer.toString(rect.x));
+                    XMLUtil.addAttribute(atts, "y", Integer.toString(rect.y));
+                    XMLUtil.addAttribute(atts, "width", Integer.toString(rect.width));
+                    XMLUtil.addAttribute(atts, "height", Integer.toString(rect.height));
+                    handler.element("image", atts);
+                } else {
+                    drawImageUsingImageHandler(info, rect);
+                }
+            } catch (ImageException ie) {
+                ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
+                        getUserAgent().getEventBroadcaster());
+                eventProducer.imageError(this, (info != null ? info.toString() : uri), ie, null);
+            } catch (FileNotFoundException fe) {
+                ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
+                        getUserAgent().getEventBroadcaster());
+                eventProducer.imageNotFound(this, (info != null ? info.toString() : uri), fe, null);
+            } catch (IOException ioe) {
+                ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
+                        getUserAgent().getEventBroadcaster());
+                eventProducer.imageIOError(this, (info != null ? info.toString() : uri), ioe, null);
+            }
+        } catch (SAXException e) {
+            throw new IFException("SAX error in drawImage()", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void drawImage(Document doc, Rectangle rect, String ptr) throws IFException {
+        try {
+            establish(MODE_NORMAL);
+
+            drawImageUsingDocument(doc, rect);
+        } catch (SAXException e) {
+            throw new IFException("SAX error in drawImage()", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    protected RenderingContext createRenderingContext() {
+        SVGRenderingContext svgContext = new SVGRenderingContext(
+                getUserAgent(), handler);
+        return svgContext;
+    }
+
+    private static String toString(Paint paint) {
+        //TODO Paint serialization: Fine-tune and extend!
+        if (paint instanceof Color) {
+            return ColorUtil.colorToString((Color)paint);
+        } else {
+            throw new UnsupportedOperationException("Paint not supported: " + paint);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void clipRect(Rectangle rect) throws IFException {
+        //TODO Implement me!!!
+    }
+
+    /** {@inheritDoc} */
+    public void fillRect(Rectangle rect, Paint fill) throws IFException {
+        if (fill == null) {
+            return;
+        }
+        try {
+            establish(MODE_NORMAL);
+            AttributesImpl atts = new AttributesImpl();
+            XMLUtil.addAttribute(atts, "x", Integer.toString(rect.x));
+            XMLUtil.addAttribute(atts, "y", Integer.toString(rect.y));
+            XMLUtil.addAttribute(atts, "width", Integer.toString(rect.width));
+            XMLUtil.addAttribute(atts, "height", Integer.toString(rect.height));
+            if (fill != null) {
+                XMLUtil.addAttribute(atts, "fill", toString(fill));
+            }
+            /* disabled
+            if (stroke != null) {
+                XMLUtil.addAttribute(atts, "stroke", toString(stroke));
+            }*/
+            handler.element("rect", atts);
+        } catch (SAXException e) {
+            throw new IFException("SAX error in fillRect()", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void drawBorderRect(Rectangle rect, BorderProps before, BorderProps after,
+            BorderProps start, BorderProps end) throws IFException {
+        // TODO Auto-generated method stub
+    }
+
+    /** {@inheritDoc} */
+    public void drawLine(Point start, Point end, int width, Color color, RuleStyle style)
+            throws IFException {
+        try {
+            establish(MODE_NORMAL);
+            AttributesImpl atts = new AttributesImpl();
+            XMLUtil.addAttribute(atts, "x1", Integer.toString(start.x));
+            XMLUtil.addAttribute(atts, "y1", Integer.toString(start.y));
+            XMLUtil.addAttribute(atts, "x2", Integer.toString(end.x));
+            XMLUtil.addAttribute(atts, "y2", Integer.toString(end.y));
+            XMLUtil.addAttribute(atts, "stroke-width", toString(color));
+            XMLUtil.addAttribute(atts, "fill", toString(color));
+            //TODO Handle style parameter
+            handler.element("line", atts);
+        } catch (SAXException e) {
+            throw new IFException("SAX error in drawLine()", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void drawText(int x, int y, int[] dx, int[] dy, String text, String ptr) throws IFException {
+        //Note: ptr is ignored as it is only needed for accessibility
+        try {
+            establish(MODE_TEXT);
+            AttributesImpl atts = new AttributesImpl();
+            XMLUtil.addAttribute(atts, XMLConstants.XML_SPACE, "preserve");
+            XMLUtil.addAttribute(atts, "x", Integer.toString(x));
+            XMLUtil.addAttribute(atts, "y", Integer.toString(y));
+            if (dx != null) {
+                XMLUtil.addAttribute(atts, "dx", IFUtil.toString(dx));
+            }
+            if (dy != null) {
+                XMLUtil.addAttribute(atts, "dy", IFUtil.toString(dy));
+            }
+            handler.startElement("text", atts);
+            char[] chars = text.toCharArray();
+            handler.characters(chars, 0, chars.length);
+            handler.endElement("text");
+        } catch (SAXException e) {
+            throw new IFException("SAX error in setFont()", e);
+        }
+    }
+
+    private void leaveTextMode() throws SAXException {
+        assert this.mode == MODE_TEXT;
+        handler.endElement("g");
+        this.mode = MODE_NORMAL;
+    }
+
+    private void establish(int newMode) throws SAXException {
+        switch (newMode) {
+        case MODE_TEXT:
+            enterTextMode();
+            break;
+        default:
+            if (this.mode == MODE_TEXT) {
+                leaveTextMode();
+            }
+        }
+    }
+
+    private void enterTextMode() throws SAXException {
+        if (state.isFontChanged() && this.mode == MODE_TEXT) {
+            leaveTextMode();
+        }
+        if (this.mode != MODE_TEXT) {
+            startTextGroup();
+            this.mode = MODE_TEXT;
+        }
+    }
+
+    private void startTextGroup() throws SAXException {
+        AttributesImpl atts = new AttributesImpl();
+        XMLUtil.addAttribute(atts, "font-family", state.getFontFamily());
+        XMLUtil.addAttribute(atts, "font-style", state.getFontStyle());
+        XMLUtil.addAttribute(atts, "font-weight", Integer.toString(state.getFontWeight()));
+        XMLUtil.addAttribute(atts, "font-variant", state.getFontVariant());
+        XMLUtil.addAttribute(atts, "font-size", Integer.toString(state.getFontSize()));
+        XMLUtil.addAttribute(atts, "fill", toString(state.getTextColor()));
+        handler.startElement("g", atts);
+        state.resetFontChanged();
+    }
+
+    /** {@inheritDoc} */
+    public void handleExtensionObject(Object extension) throws IFException {
+        if (extension instanceof Metadata) {
+            Metadata meta = (Metadata)extension;
+            try {
+                establish(MODE_NORMAL);
+                handler.startElement("metadata");
+                meta.toSAX(this.handler);
+                handler.endElement("metadata");
+            } catch (SAXException e) {
+                throw new IFException("SAX error while handling extension object", e);
+            }
+        } else {
+            throw new UnsupportedOperationException(
+                    "Don't know how to handle extension object: " + extension);
+        }
+    }
+
+}
Index: src/sandbox/org/apache/fop/render/svg/SVGPainter.java.r736273
===================================================================
--- src/sandbox/org/apache/fop/render/svg/SVGPainter.java.r736273	(revision 0)
+++ src/sandbox/org/apache/fop/render/svg/SVGPainter.java.r736273	(revision 0)
@@ -0,0 +1,408 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: SVGPainter.java 741165 2009-02-05 16:27:08Z jeremias $ */
+
+package org.apache.fop.render.svg;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Paint;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Map;
+
+import org.w3c.dom.Document;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.xmlgraphics.image.loader.ImageException;
+import org.apache.xmlgraphics.image.loader.ImageInfo;
+import org.apache.xmlgraphics.image.loader.ImageManager;
+import org.apache.xmlgraphics.image.loader.ImageSessionContext;
+import org.apache.xmlgraphics.xmp.Metadata;
+
+import org.apache.fop.apps.MimeConstants;
+import org.apache.fop.events.ResourceEventProducer;
+import org.apache.fop.render.ImageHandlerUtil;
+import org.apache.fop.render.RenderingContext;
+import org.apache.fop.render.intermediate.AbstractIFPainter;
+import org.apache.fop.render.intermediate.IFConstants;
+import org.apache.fop.render.intermediate.IFContext;
+import org.apache.fop.render.intermediate.IFException;
+import org.apache.fop.render.intermediate.IFState;
+import org.apache.fop.render.intermediate.IFUtil;
+import org.apache.fop.traits.BorderProps;
+import org.apache.fop.traits.RuleStyle;
+import org.apache.fop.util.ColorUtil;
+import org.apache.fop.util.GenerationHelperContentHandler;
+import org.apache.fop.util.XMLConstants;
+import org.apache.fop.util.XMLUtil;
+
+/**
+ * IFPainter implementation that writes SVG.
+ */
+public class SVGPainter extends AbstractIFPainter implements SVGConstants {
+
+    /** logging instance */
+    private static Log log = LogFactory.getLog(SVGPainter.class);
+
+    private AbstractSVGDocumentHandler parent;
+
+    /** The SAX content handler that receives the generated XML events. */
+    protected GenerationHelperContentHandler handler;
+
+    private static final int MODE_NORMAL = 0;
+    private static final int MODE_TEXT = 1;
+
+    private int mode = MODE_NORMAL;
+
+    /**
+     * Main constructor.
+     * @param parent the parent document handler
+     * @param contentHandler the target SAX content handler
+     */
+    public SVGPainter(AbstractSVGDocumentHandler parent,
+            GenerationHelperContentHandler contentHandler) {
+        super();
+        this.parent = parent;
+        this.handler = contentHandler;
+        this.state = IFState.create();
+    }
+
+    /** {@inheritDoc} */
+    protected IFContext getContext() {
+        return parent.getContext();
+    }
+
+    /** {@inheritDoc} */
+    public void startViewport(AffineTransform transform, Dimension size, Rectangle clipRect)
+            throws IFException {
+        startViewport(IFUtil.toString(transform), size, clipRect);
+    }
+
+    /** {@inheritDoc} */
+    public void startViewport(AffineTransform[] transforms, Dimension size, Rectangle clipRect)
+            throws IFException {
+        startViewport(IFUtil.toString(transforms), size, clipRect);
+    }
+
+    private void startViewport(String transform, Dimension size, Rectangle clipRect)
+            throws IFException {
+        try {
+            establish(MODE_NORMAL);
+            AttributesImpl atts = new AttributesImpl();
+            if (transform != null && transform.length() > 0) {
+                XMLUtil.addAttribute(atts, "transform", transform);
+            }
+            handler.startElement("g", atts);
+
+            atts.clear();
+            XMLUtil.addAttribute(atts, "width", Integer.toString(size.width));
+            XMLUtil.addAttribute(atts, "height", Integer.toString(size.height));
+            if (clipRect != null) {
+                int[] v = new int[] {
+                        clipRect.y,
+                        -clipRect.x + size.width - clipRect.width,
+                        -clipRect.y + size.height - clipRect.height,
+                        clipRect.x};
+                int sum = 0;
+                for (int i = 0; i < 4; i++) {
+                    sum += Math.abs(v[i]);
+                }
+                if (sum != 0) {
+                    StringBuffer sb = new StringBuffer("rect(");
+                    sb.append(v[0]).append(',');
+                    sb.append(v[1]).append(',');
+                    sb.append(v[2]).append(',');
+                    sb.append(v[3]).append(')');
+                    XMLUtil.addAttribute(atts, "clip", sb.toString());
+                }
+                XMLUtil.addAttribute(atts, "overflow", "hidden");
+            } else {
+                XMLUtil.addAttribute(atts, "overflow", "visible");
+            }
+            handler.startElement("svg", atts);
+        } catch (SAXException e) {
+            throw new IFException("SAX error in startBox()", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void endViewport() throws IFException {
+        try {
+            establish(MODE_NORMAL);
+            handler.endElement("svg");
+            handler.endElement("g");
+        } catch (SAXException e) {
+            throw new IFException("SAX error in endBox()", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void startGroup(AffineTransform[] transforms) throws IFException {
+        startGroup(IFUtil.toString(transforms));
+    }
+
+    /** {@inheritDoc} */
+    public void startGroup(AffineTransform transform) throws IFException {
+        startGroup(IFUtil.toString(transform));
+    }
+
+    private void startGroup(String transform) throws IFException {
+        try {
+            AttributesImpl atts = new AttributesImpl();
+            if (transform != null && transform.length() > 0) {
+                XMLUtil.addAttribute(atts, "transform", transform);
+            }
+            handler.startElement("g", atts);
+        } catch (SAXException e) {
+            throw new IFException("SAX error in startGroup()", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void endGroup() throws IFException {
+        try {
+            establish(MODE_NORMAL);
+            handler.endElement("g");
+        } catch (SAXException e) {
+            throw new IFException("SAX error in endGroup()", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void drawImage(String uri, Rectangle rect) throws IFException {
+        try {
+            establish(MODE_NORMAL);
+
+            ImageManager manager = getUserAgent().getFactory().getImageManager();
+            ImageInfo info = null;
+            try {
+                ImageSessionContext sessionContext = getUserAgent().getImageSessionContext();
+                info = manager.getImageInfo(uri, sessionContext);
+
+                String mime = info.getMimeType();
+                Map foreignAttributes = getContext().getForeignAttributes();
+                String conversionMode = (String)foreignAttributes.get(
+                        ImageHandlerUtil.CONVERSION_MODE);
+                if ("reference".equals(conversionMode)
+                        && (MimeConstants.MIME_GIF.equals(mime)
+                        || MimeConstants.MIME_JPEG.equals(mime)
+                        || MimeConstants.MIME_PNG.equals(mime)
+                        || MimeConstants.MIME_SVG.equals(mime))) {
+                    //Just reference the image
+                    //TODO Some additional URI rewriting might be necessary
+                    AttributesImpl atts = new AttributesImpl();
+                    XMLUtil.addAttribute(atts, IFConstants.XLINK_HREF, uri);
+                    XMLUtil.addAttribute(atts, "x", Integer.toString(rect.x));
+                    XMLUtil.addAttribute(atts, "y", Integer.toString(rect.y));
+                    XMLUtil.addAttribute(atts, "width", Integer.toString(rect.width));
+                    XMLUtil.addAttribute(atts, "height", Integer.toString(rect.height));
+                    handler.element("image", atts);
+                } else {
+                    drawImageUsingImageHandler(info, rect);
+                }
+            } catch (ImageException ie) {
+                ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
+                        getUserAgent().getEventBroadcaster());
+                eventProducer.imageError(this, (info != null ? info.toString() : uri), ie, null);
+            } catch (FileNotFoundException fe) {
+                ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
+                        getUserAgent().getEventBroadcaster());
+                eventProducer.imageNotFound(this, (info != null ? info.toString() : uri), fe, null);
+            } catch (IOException ioe) {
+                ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
+                        getUserAgent().getEventBroadcaster());
+                eventProducer.imageIOError(this, (info != null ? info.toString() : uri), ioe, null);
+            }
+        } catch (SAXException e) {
+            throw new IFException("SAX error in drawImage()", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void drawImage(Document doc, Rectangle rect) throws IFException {
+        try {
+            establish(MODE_NORMAL);
+
+            drawImageUsingDocument(doc, rect);
+        } catch (SAXException e) {
+            throw new IFException("SAX error in drawImage()", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    protected RenderingContext createRenderingContext() {
+        SVGRenderingContext svgContext = new SVGRenderingContext(
+                getUserAgent(), handler);
+        return svgContext;
+    }
+
+    private static String toString(Paint paint) {
+        //TODO Paint serialization: Fine-tune and extend!
+        if (paint instanceof Color) {
+            return ColorUtil.colorToString((Color)paint);
+        } else {
+            throw new UnsupportedOperationException("Paint not supported: " + paint);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void clipRect(Rectangle rect) throws IFException {
+        //TODO Implement me!!!
+    }
+
+    /** {@inheritDoc} */
+    public void fillRect(Rectangle rect, Paint fill) throws IFException {
+        if (fill == null) {
+            return;
+        }
+        try {
+            establish(MODE_NORMAL);
+            AttributesImpl atts = new AttributesImpl();
+            XMLUtil.addAttribute(atts, "x", Integer.toString(rect.x));
+            XMLUtil.addAttribute(atts, "y", Integer.toString(rect.y));
+            XMLUtil.addAttribute(atts, "width", Integer.toString(rect.width));
+            XMLUtil.addAttribute(atts, "height", Integer.toString(rect.height));
+            if (fill != null) {
+                XMLUtil.addAttribute(atts, "fill", toString(fill));
+            }
+            /* disabled
+            if (stroke != null) {
+                XMLUtil.addAttribute(atts, "stroke", toString(stroke));
+            }*/
+            handler.element("rect", atts);
+        } catch (SAXException e) {
+            throw new IFException("SAX error in fillRect()", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void drawBorderRect(Rectangle rect, BorderProps before, BorderProps after,
+            BorderProps start, BorderProps end) throws IFException {
+        // TODO Auto-generated method stub
+    }
+
+    /** {@inheritDoc} */
+    public void drawLine(Point start, Point end, int width, Color color, RuleStyle style)
+            throws IFException {
+        try {
+            establish(MODE_NORMAL);
+            AttributesImpl atts = new AttributesImpl();
+            XMLUtil.addAttribute(atts, "x1", Integer.toString(start.x));
+            XMLUtil.addAttribute(atts, "y1", Integer.toString(start.y));
+            XMLUtil.addAttribute(atts, "x2", Integer.toString(end.x));
+            XMLUtil.addAttribute(atts, "y2", Integer.toString(end.y));
+            XMLUtil.addAttribute(atts, "stroke-width", toString(color));
+            XMLUtil.addAttribute(atts, "fill", toString(color));
+            //TODO Handle style parameter
+            handler.element("line", atts);
+        } catch (SAXException e) {
+            throw new IFException("SAX error in drawLine()", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void drawText(int x, int y, int[] dx, int[] dy, String text) throws IFException {
+        try {
+            establish(MODE_TEXT);
+            AttributesImpl atts = new AttributesImpl();
+            XMLUtil.addAttribute(atts, XMLConstants.XML_SPACE, "preserve");
+            XMLUtil.addAttribute(atts, "x", Integer.toString(x));
+            XMLUtil.addAttribute(atts, "y", Integer.toString(y));
+            if (dx != null) {
+                XMLUtil.addAttribute(atts, "dx", IFUtil.toString(dx));
+            }
+            if (dy != null) {
+                XMLUtil.addAttribute(atts, "dy", IFUtil.toString(dy));
+            }
+            handler.startElement("text", atts);
+            char[] chars = text.toCharArray();
+            handler.characters(chars, 0, chars.length);
+            handler.endElement("text");
+        } catch (SAXException e) {
+            throw new IFException("SAX error in setFont()", e);
+        }
+    }
+
+    private void leaveTextMode() throws SAXException {
+        assert this.mode == MODE_TEXT;
+        handler.endElement("g");
+        this.mode = MODE_NORMAL;
+    }
+
+    private void establish(int newMode) throws SAXException {
+        switch (newMode) {
+        case MODE_TEXT:
+            enterTextMode();
+            break;
+        default:
+            if (this.mode == MODE_TEXT) {
+                leaveTextMode();
+            }
+        }
+    }
+
+    private void enterTextMode() throws SAXException {
+        if (state.isFontChanged() && this.mode == MODE_TEXT) {
+            leaveTextMode();
+        }
+        if (this.mode != MODE_TEXT) {
+            startTextGroup();
+            this.mode = MODE_TEXT;
+        }
+    }
+
+    private void startTextGroup() throws SAXException {
+        AttributesImpl atts = new AttributesImpl();
+        XMLUtil.addAttribute(atts, "font-family", state.getFontFamily());
+        XMLUtil.addAttribute(atts, "font-style", state.getFontStyle());
+        XMLUtil.addAttribute(atts, "font-weight", Integer.toString(state.getFontWeight()));
+        XMLUtil.addAttribute(atts, "font-variant", state.getFontVariant());
+        XMLUtil.addAttribute(atts, "font-size", Integer.toString(state.getFontSize()));
+        XMLUtil.addAttribute(atts, "fill", toString(state.getTextColor()));
+        handler.startElement("g", atts);
+        state.resetFontChanged();
+    }
+
+    /** {@inheritDoc} */
+    public void handleExtensionObject(Object extension) throws IFException {
+        if (extension instanceof Metadata) {
+            Metadata meta = (Metadata)extension;
+            try {
+                establish(MODE_NORMAL);
+                handler.startElement("metadata");
+                meta.toSAX(this.handler);
+                handler.endElement("metadata");
+            } catch (SAXException e) {
+                throw new IFException("SAX error while handling extension object", e);
+            }
+        } else {
+            throw new UnsupportedOperationException(
+                    "Don't know how to handle extension object: " + extension);
+        }
+    }
+
+}
Index: src/sandbox/org/apache/fop/render/svg/SVGPainter.java.r742750
===================================================================
--- src/sandbox/org/apache/fop/render/svg/SVGPainter.java.r742750	(revision 0)
+++ src/sandbox/org/apache/fop/render/svg/SVGPainter.java.r742750	(revision 0)
@@ -0,0 +1,412 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: SVGPainter.java 741165 2009-02-05 16:27:08Z jeremias $ */
+
+package org.apache.fop.render.svg;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Paint;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Map;
+
+import org.w3c.dom.Document;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.xmlgraphics.image.loader.ImageException;
+import org.apache.xmlgraphics.image.loader.ImageInfo;
+import org.apache.xmlgraphics.image.loader.ImageManager;
+import org.apache.xmlgraphics.image.loader.ImageSessionContext;
+import org.apache.xmlgraphics.xmp.Metadata;
+
+import org.apache.fop.apps.MimeConstants;
+import org.apache.fop.events.ResourceEventProducer;
+import org.apache.fop.render.ImageHandlerUtil;
+import org.apache.fop.render.RenderingContext;
+import org.apache.fop.render.intermediate.AbstractIFPainter;
+import org.apache.fop.render.intermediate.IFConstants;
+import org.apache.fop.render.intermediate.IFContext;
+import org.apache.fop.render.intermediate.IFException;
+import org.apache.fop.render.intermediate.IFState;
+import org.apache.fop.render.intermediate.IFUtil;
+import org.apache.fop.traits.BorderProps;
+import org.apache.fop.traits.RuleStyle;
+import org.apache.fop.util.ColorUtil;
+import org.apache.fop.util.GenerationHelperContentHandler;
+import org.apache.fop.util.XMLConstants;
+import org.apache.fop.util.XMLUtil;
+
+/**
+ * IFPainter implementation that writes SVG.
+ */
+public class SVGPainter extends AbstractIFPainter implements SVGConstants {
+
+    /** logging instance */
+    private static Log log = LogFactory.getLog(SVGPainter.class);
+
+    private AbstractSVGDocumentHandler parent;
+
+    /** The SAX content handler that receives the generated XML events. */
+    protected GenerationHelperContentHandler handler;
+
+    private static final int MODE_NORMAL = 0;
+    private static final int MODE_TEXT = 1;
+
+    private int mode = MODE_NORMAL;
+
+    /**
+     * Main constructor.
+     * @param parent the parent document handler
+     * @param contentHandler the target SAX content handler
+     */
+    public SVGPainter(AbstractSVGDocumentHandler parent,
+            GenerationHelperContentHandler contentHandler) {
+        super();
+        this.parent = parent;
+        this.handler = contentHandler;
+        this.state = IFState.create();
+    }
+
+    /** {@inheritDoc} */
+    protected IFContext getContext() {
+        return parent.getContext();
+    }
+
+    /** {@inheritDoc} */
+    public void startViewport(AffineTransform transform, Dimension size, Rectangle clipRect)
+            throws IFException {
+        startViewport(IFUtil.toString(transform), size, clipRect);
+    }
+
+    /** {@inheritDoc} */
+    public void startViewport(AffineTransform[] transforms, Dimension size, Rectangle clipRect)
+            throws IFException {
+        startViewport(IFUtil.toString(transforms), size, clipRect);
+    }
+
+    private void startViewport(String transform, Dimension size, Rectangle clipRect)
+            throws IFException {
+        try {
+            establish(MODE_NORMAL);
+            AttributesImpl atts = new AttributesImpl();
+            if (transform != null && transform.length() > 0) {
+                XMLUtil.addAttribute(atts, "transform", transform);
+            }
+            handler.startElement("g", atts);
+
+            atts.clear();
+            XMLUtil.addAttribute(atts, "width", Integer.toString(size.width));
+            XMLUtil.addAttribute(atts, "height", Integer.toString(size.height));
+            if (clipRect != null) {
+                int[] v = new int[] {
+                        clipRect.y,
+                        -clipRect.x + size.width - clipRect.width,
+                        -clipRect.y + size.height - clipRect.height,
+                        clipRect.x};
+                int sum = 0;
+                for (int i = 0; i < 4; i++) {
+                    sum += Math.abs(v[i]);
+                }
+                if (sum != 0) {
+                    StringBuffer sb = new StringBuffer("rect(");
+                    sb.append(v[0]).append(',');
+                    sb.append(v[1]).append(',');
+                    sb.append(v[2]).append(',');
+                    sb.append(v[3]).append(')');
+                    XMLUtil.addAttribute(atts, "clip", sb.toString());
+                }
+                XMLUtil.addAttribute(atts, "overflow", "hidden");
+            } else {
+                XMLUtil.addAttribute(atts, "overflow", "visible");
+            }
+            handler.startElement("svg", atts);
+        } catch (SAXException e) {
+            throw new IFException("SAX error in startBox()", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void endViewport() throws IFException {
+        try {
+            establish(MODE_NORMAL);
+            handler.endElement("svg");
+            handler.endElement("g");
+        } catch (SAXException e) {
+            throw new IFException("SAX error in endBox()", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void startGroup(AffineTransform[] transforms) throws IFException {
+        startGroup(IFUtil.toString(transforms));
+    }
+
+    /** {@inheritDoc} */
+    public void startGroup(AffineTransform transform) throws IFException {
+        startGroup(IFUtil.toString(transform));
+    }
+
+    private void startGroup(String transform) throws IFException {
+        try {
+            AttributesImpl atts = new AttributesImpl();
+            if (transform != null && transform.length() > 0) {
+                XMLUtil.addAttribute(atts, "transform", transform);
+            }
+            handler.startElement("g", atts);
+        } catch (SAXException e) {
+            throw new IFException("SAX error in startGroup()", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void endGroup() throws IFException {
+        try {
+            establish(MODE_NORMAL);
+            handler.endElement("g");
+        } catch (SAXException e) {
+            throw new IFException("SAX error in endGroup()", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void drawImage(String uri, Rectangle rect) throws IFException {
+        try {
+            establish(MODE_NORMAL);
+
+            ImageManager manager = getUserAgent().getFactory().getImageManager();
+            ImageInfo info = null;
+            try {
+                ImageSessionContext sessionContext = getUserAgent().getImageSessionContext();
+                info = manager.getImageInfo(uri, sessionContext);
+
+                String mime = info.getMimeType();
+                Map foreignAttributes = getContext().getForeignAttributes();
+                String conversionMode = (String)foreignAttributes.get(
+                        ImageHandlerUtil.CONVERSION_MODE);
+                if ("reference".equals(conversionMode)
+                        && (MimeConstants.MIME_GIF.equals(mime)
+                        || MimeConstants.MIME_JPEG.equals(mime)
+                        || MimeConstants.MIME_PNG.equals(mime)
+                        || MimeConstants.MIME_SVG.equals(mime))) {
+                    //Just reference the image
+                    //TODO Some additional URI rewriting might be necessary
+                    AttributesImpl atts = new AttributesImpl();
+                    XMLUtil.addAttribute(atts, IFConstants.XLINK_HREF, uri);
+                    XMLUtil.addAttribute(atts, "x", Integer.toString(rect.x));
+                    XMLUtil.addAttribute(atts, "y", Integer.toString(rect.y));
+                    XMLUtil.addAttribute(atts, "width", Integer.toString(rect.width));
+                    XMLUtil.addAttribute(atts, "height", Integer.toString(rect.height));
+                    handler.element("image", atts);
+                } else {
+                    drawImageUsingImageHandler(info, rect);
+                }
+            } catch (ImageException ie) {
+                ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
+                        getUserAgent().getEventBroadcaster());
+                eventProducer.imageError(this, (info != null ? info.toString() : uri), ie, null);
+            } catch (FileNotFoundException fe) {
+                ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
+                        getUserAgent().getEventBroadcaster());
+                eventProducer.imageNotFound(this, (info != null ? info.toString() : uri), fe, null);
+            } catch (IOException ioe) {
+                ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
+                        getUserAgent().getEventBroadcaster());
+                eventProducer.imageIOError(this, (info != null ? info.toString() : uri), ioe, null);
+            }
+        } catch (SAXException e) {
+            throw new IFException("SAX error in drawImage()", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void drawImage(Document doc, Rectangle rect) throws IFException {
+        try {
+            establish(MODE_NORMAL);
+
+            drawImageUsingDocument(doc, rect);
+        } catch (SAXException e) {
+            throw new IFException("SAX error in drawImage()", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    protected RenderingContext createRenderingContext() {
+        SVGRenderingContext svgContext = new SVGRenderingContext(
+                getUserAgent(), handler);
+        return svgContext;
+    }
+
+    private static String toString(Paint paint) {
+        //TODO Paint serialization: Fine-tune and extend!
+        if (paint instanceof Color) {
+            return ColorUtil.colorToString((Color)paint);
+        } else {
+            throw new UnsupportedOperationException("Paint not supported: " + paint);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void clipRect(Rectangle rect) throws IFException {
+        //TODO Implement me!!!
+    }
+
+    /** {@inheritDoc} */
+    public void fillRect(Rectangle rect, Paint fill) throws IFException {
+        if (fill == null) {
+            return;
+        }
+        try {
+            establish(MODE_NORMAL);
+            AttributesImpl atts = new AttributesImpl();
+            XMLUtil.addAttribute(atts, "x", Integer.toString(rect.x));
+            XMLUtil.addAttribute(atts, "y", Integer.toString(rect.y));
+            XMLUtil.addAttribute(atts, "width", Integer.toString(rect.width));
+            XMLUtil.addAttribute(atts, "height", Integer.toString(rect.height));
+            if (fill != null) {
+                XMLUtil.addAttribute(atts, "fill", toString(fill));
+            }
+            /* disabled
+            if (stroke != null) {
+                XMLUtil.addAttribute(atts, "stroke", toString(stroke));
+            }*/
+            handler.element("rect", atts);
+        } catch (SAXException e) {
+            throw new IFException("SAX error in fillRect()", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void drawBorderRect(Rectangle rect, BorderProps before, BorderProps after,
+            BorderProps start, BorderProps end) throws IFException {
+        // TODO Auto-generated method stub
+    }
+
+    /** {@inheritDoc} */
+    public void drawLine(Point start, Point end, int width, Color color, RuleStyle style)
+            throws IFException {
+        try {
+            establish(MODE_NORMAL);
+            AttributesImpl atts = new AttributesImpl();
+            XMLUtil.addAttribute(atts, "x1", Integer.toString(start.x));
+            XMLUtil.addAttribute(atts, "y1", Integer.toString(start.y));
+            XMLUtil.addAttribute(atts, "x2", Integer.toString(end.x));
+            XMLUtil.addAttribute(atts, "y2", Integer.toString(end.y));
+            XMLUtil.addAttribute(atts, "stroke-width", toString(color));
+            XMLUtil.addAttribute(atts, "fill", toString(color));
+            //TODO Handle style parameter
+            handler.element("line", atts);
+        } catch (SAXException e) {
+            throw new IFException("SAX error in drawLine()", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[] dx, String text)
+                throws IFException {
+        try {
+            establish(MODE_TEXT);
+            AttributesImpl atts = new AttributesImpl();
+            XMLUtil.addAttribute(atts, XMLConstants.XML_SPACE, "preserve");
+            XMLUtil.addAttribute(atts, "x", Integer.toString(x));
+            XMLUtil.addAttribute(atts, "y", Integer.toString(y));
+            if (letterSpacing != 0) {
+                XMLUtil.addAttribute(atts, "letter-spacing", Integer.toString(letterSpacing));
+            }
+            if (wordSpacing != 0) {
+                XMLUtil.addAttribute(atts, "word-spacing", Integer.toString(wordSpacing));
+            }
+            if (dx != null) {
+                XMLUtil.addAttribute(atts, "dx", IFUtil.toString(dx));
+            }
+            handler.startElement("text", atts);
+            char[] chars = text.toCharArray();
+            handler.characters(chars, 0, chars.length);
+            handler.endElement("text");
+        } catch (SAXException e) {
+            throw new IFException("SAX error in setFont()", e);
+        }
+    }
+
+    private void leaveTextMode() throws SAXException {
+        assert this.mode == MODE_TEXT;
+        handler.endElement("g");
+        this.mode = MODE_NORMAL;
+    }
+
+    private void establish(int newMode) throws SAXException {
+        switch (newMode) {
+        case MODE_TEXT:
+            enterTextMode();
+            break;
+        default:
+            if (this.mode == MODE_TEXT) {
+                leaveTextMode();
+            }
+        }
+    }
+
+    private void enterTextMode() throws SAXException {
+        if (state.isFontChanged() && this.mode == MODE_TEXT) {
+            leaveTextMode();
+        }
+        if (this.mode != MODE_TEXT) {
+            startTextGroup();
+            this.mode = MODE_TEXT;
+        }
+    }
+
+    private void startTextGroup() throws SAXException {
+        AttributesImpl atts = new AttributesImpl();
+        XMLUtil.addAttribute(atts, "font-family", state.getFontFamily());
+        XMLUtil.addAttribute(atts, "font-style", state.getFontStyle());
+        XMLUtil.addAttribute(atts, "font-weight", Integer.toString(state.getFontWeight()));
+        XMLUtil.addAttribute(atts, "font-variant", state.getFontVariant());
+        XMLUtil.addAttribute(atts, "font-size", Integer.toString(state.getFontSize()));
+        XMLUtil.addAttribute(atts, "fill", toString(state.getTextColor()));
+        handler.startElement("g", atts);
+        state.resetFontChanged();
+    }
+
+    /** {@inheritDoc} */
+    public void handleExtensionObject(Object extension) throws IFException {
+        if (extension instanceof Metadata) {
+            Metadata meta = (Metadata)extension;
+            try {
+                establish(MODE_NORMAL);
+                handler.startElement("metadata");
+                meta.toSAX(this.handler);
+                handler.endElement("metadata");
+            } catch (SAXException e) {
+                throw new IFException("SAX error while handling extension object", e);
+            }
+        } else {
+            throw new UnsupportedOperationException(
+                    "Don't know how to handle extension object: " + extension);
+        }
+    }
+
+}
Index: test/java/org/apache/fop/intermediate/IFParserTestCase.java
===================================================================
--- test/java/org/apache/fop/intermediate/IFParserTestCase.java	(revision 744587)
+++ test/java/org/apache/fop/intermediate/IFParserTestCase.java	(working copy)
@@ -88,7 +88,7 @@
 
     /** {@inheritDoc} */
     protected String getTargetMIME() {
-        return MimeConstants.MIME_PDF + ";mode=painter";
+        return MimeConstants.MIME_PDF + "mode=painter";
     }
 
     /** {@inheritDoc} */
