---
 src/java/org/apache/fop/fo/FONode.java             |   12 ++++
 src/java/org/apache/fop/fo/FOText.java             |   21 +++++++-
 src/java/org/apache/fop/fo/FObj.java               |   12 ----
 .../fop/layoutmgr/inline/TextLayoutManager.java    |    2 +-
 src/java/org/apache/fop/pdf/PDFArray.java          |    7 +++
 src/java/org/apache/fop/pdf/PDFFactory.java        |    4 +-
 src/java/org/apache/fop/pdf/PDFStructElem.java     |   54 +++++++++++++++-----
 .../org/apache/fop/render/pdf/FOToPDFRoleMap.java  |   30 +++++++++++
 .../fop/render/pdf/PDFLogicalStructureHandler.java |   19 ++++---
 9 files changed, 125 insertions(+), 36 deletions(-)

diff --git a/src/java/org/apache/fop/fo/FONode.java b/src/java/org/apache/fop/fo/FONode.java
index 9c0effe..12a2b0f 100644
--- a/src/java/org/apache/fop/fo/FONode.java
+++ b/src/java/org/apache/fop/fo/FONode.java
@@ -72,6 +72,9 @@ public abstract class FONode implements Cloneable {
     /** Logger for fo-tree related messages **/
     protected static final Log log = LogFactory.getLog(FONode.class);
 
+    /** Counter for creating ptr Ids */
+    private static long ptrNo = 0;
+
     /**
      * Base constructor
      *
@@ -402,6 +405,15 @@ public abstract class FONode implements Cloneable {
     }
 
     /**
+     * Generates a new ID for the Ptr attribute
+     *
+     * @return new ID for Ptr attribute
+     */
+    protected String newPtrId() {
+        return "N" + (ptrNo++);
+    }
+
+    /**
      * Add structure tree of this elements and all childs to parent.
      * @param parent Parent Element of the structure tree
      */
diff --git a/src/java/org/apache/fop/fo/FOText.java b/src/java/org/apache/fop/fo/FOText.java
index 3e1a857..8c078e7 100644
--- a/src/java/org/apache/fop/fo/FOText.java
+++ b/src/java/org/apache/fop/fo/FOText.java
@@ -25,6 +25,7 @@ import java.util.NoSuchElementException;
 
 import org.xml.sax.Locator;
 
+import org.apache.fop.accessibility.StructureElement;
 import org.apache.fop.apps.FOPException;
 import org.apache.fop.datatypes.Length;
 import org.apache.fop.fo.flow.Block;
@@ -34,12 +35,13 @@ import org.apache.fop.fo.properties.CommonTextDecoration;
 import org.apache.fop.fo.properties.KeepProperty;
 import org.apache.fop.fo.properties.Property;
 import org.apache.fop.fo.properties.SpaceProperty;
+import org.apache.fop.fo.properties.StructurePointerPropertySet;
 import org.apache.fop.util.CharUtilities;
 
 /**
  * A text node (PCDATA) in the formatting object tree.
  */
-public class FOText extends FONode implements CharSequence {
+public class FOText extends FONode implements CharSequence, StructurePointerPropertySet {
 
     /** the <code>CharBuffer</code> containing the text */
     private CharBuffer charBuffer;
@@ -57,6 +59,7 @@ public class FOText extends FONode implements CharSequence {
     private Property wordSpacing;
     private int wrapOption;
     private Length baselineShift;
+    private String ptr;  //used for accessibility
 
     /**
      * Points to the previous FOText object created within the current
@@ -171,6 +174,7 @@ public class FOText extends FONode implements CharSequence {
         this.wrapOption = pList.get(Constants.PR_WRAP_OPTION).getEnum();
         this.textDecoration = pList.getTextDecorationProps();
         this.baselineShift = pList.get(Constants.PR_BASELINE_SHIFT).getLength();
+        ptr = newPtrId();
     }
 
     /** {@inheritDoc} */
@@ -670,4 +674,19 @@ public class FOText extends FONode implements CharSequence {
             this.charBuffer.rewind();
         }
     }
+
+    /** {@inheritDoc} */
+    public void addStructureElements(StructureElement parent) {
+        StructureElement structure = new StructureElement("text");
+        structure.setRole("#text");
+        structure.setPtr(ptr);
+        parent.addChild(structure);
+        super.addStructureElements(structure); //??
+    }
+
+    /** {@inheritDoc} */
+    public String getPtr() {
+        return ptr;
+    }
+
 }
diff --git a/src/java/org/apache/fop/fo/FObj.java b/src/java/org/apache/fop/fo/FObj.java
index 6d42ff8..9261c39 100644
--- a/src/java/org/apache/fop/fo/FObj.java
+++ b/src/java/org/apache/fop/fo/FObj.java
@@ -72,9 +72,6 @@ public abstract class FObj extends FONode implements Constants {
     private String id = null;
     // End of property values
     
-    /** Counter for creating ptr Ids */
-    private static long ptrNo = 0;
-
     /**
      * Create a new formatting object.
      *
@@ -809,15 +806,6 @@ public abstract class FObj extends FONode implements Constants {
     }
 
     /**
-     * Generates a new ID for the Ptr attribute
-     *
-     * @return new ID for Ptr attribute
-     */
-    protected String newPtrId() {
-        return "N" + (ptrNo++);
-    }
-
-    /**
      * Creates structure element skelton for the current element
      *
      * @return structure element
diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
index bb433eb..996346e 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
@@ -438,7 +438,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
             setText();
             TraitSetter.addFontTraits(textArea, font);
             textArea.addTrait(Trait.COLOR, foText.getColor());
-            TraitSetter.addPtr(textArea, getPtr()); // used for accessibility
+            TraitSetter.addPtr(textArea, foText.getPtr()); // used for accessibility
             TraitSetter.addTextDecoration(textArea, foText.getTextDecoration());
             TraitSetter.addFontTraits(textArea, font);
             return textArea;
diff --git a/src/java/org/apache/fop/pdf/PDFArray.java b/src/java/org/apache/fop/pdf/PDFArray.java
index f412ae2..0c87f35 100644
--- a/src/java/org/apache/fop/pdf/PDFArray.java
+++ b/src/java/org/apache/fop/pdf/PDFArray.java
@@ -173,6 +173,13 @@ public class PDFArray extends PDFObject implements PDFClearable {
     }
 
     /**
+     * Insert obj before afterObject.
+     */
+    public void insertBefore(Object obj, Object afterObject) {
+        this.values.add(this.values.indexOf(afterObject), obj);
+    }
+
+    /**
      * Clears the PDF array.
      */
     public void clear() {
diff --git a/src/java/org/apache/fop/pdf/PDFFactory.java b/src/java/org/apache/fop/pdf/PDFFactory.java
index 7fc60d4..78c44ba 100644
--- a/src/java/org/apache/fop/pdf/PDFFactory.java
+++ b/src/java/org/apache/fop/pdf/PDFFactory.java
@@ -931,8 +931,8 @@ public class PDFFactory {
      * hierarchy
      * @return the newly created element
      */
-    public PDFStructElem makeStructureElement(PDFName structureType, PDFObject parent) {
-        PDFStructElem structElem = new PDFStructElem(parent, structureType);
+    public PDFStructElem makeStructureElement(PDFName structureType, PDFObject parent, boolean trim) {
+        PDFStructElem structElem = new PDFStructElem(parent, structureType, trim);
         getDocument().lazyAssignObjectNumber(structElem);
         return structElem;
     }
diff --git a/src/java/org/apache/fop/pdf/PDFStructElem.java b/src/java/org/apache/fop/pdf/PDFStructElem.java
index dda81d0..a5f7093 100644
--- a/src/java/org/apache/fop/pdf/PDFStructElem.java
+++ b/src/java/org/apache/fop/pdf/PDFStructElem.java
@@ -30,6 +30,9 @@ import org.apache.fop.util.XMLUtil;
 public class PDFStructElem extends PDFDictionary {
 
     private PDFStructElem parentElement;
+    private boolean trim;
+
+    public static final PDFName TextName = new PDFName("#text");
 
     /**
      * Creates a new structure element.
@@ -37,12 +40,17 @@ public class PDFStructElem extends PDFDictionary {
      * @param parent parent of this element
      * @param structureType the structure type of this element
      */
-    PDFStructElem(PDFObject parent, PDFName structureType) {
+    PDFStructElem(PDFObject parent, PDFName structureType, boolean trim) {
         if (parent instanceof PDFStructElem) {
             parentElement = (PDFStructElem) parent;
         }
         put("S", structureType);
-        setParent(parent);
+        put("P", parent);
+        put("K", new PDFArray());
+        this.trim = trim;
+        if (parentElement != null && !parentElement.containsKid(this)) {
+            parentElement.addKid(this);
+        }
     }
 
     /**
@@ -57,9 +65,16 @@ public class PDFStructElem extends PDFDictionary {
 
     /** {@inheritDoc} */
     public void setParent(PDFObject parent) {
-        if (parent != null) {
-           put("P", parent);
+    }
+
+    protected void insertBefore(PDFObject kid, PDFStructElem parent) {
+        PDFArray kids = getKids();
+        /* check should be not neccessary */
+        if (kids == null) {
+            kids = new PDFArray();
+            put("K", kids);
         }
+        kids.insertBefore(kid, parent);
     }
 
     /**
@@ -79,13 +94,23 @@ public class PDFStructElem extends PDFDictionary {
      * @param kid element to be added
      */
     public void addKid(PDFObject kid) {
+        if (TextName == get("S")) {
+            parentElement.insertBefore(kid, this);
+            return;
+        }
         PDFArray kids = getKids();
+        /* check should be not neccessary */
         if (kids == null) {
             kids = new PDFArray();
             put("K", kids);
         }
         kids.add(kid);
-        joinHierarchy();
+    }
+
+    public PDFStructElem getTreeParent() {
+        if (TextName == get("S"))
+            return parentElement;
+        return this;
     }
 
     private boolean containsKid(PDFObject kid) {
@@ -93,11 +118,6 @@ public class PDFStructElem extends PDFDictionary {
         return kids != null && kids.contains(kid);
     }
 
-    private void joinHierarchy() {
-        if (parentElement != null && !parentElement.containsKid(this)) {
-            parentElement.addKid(this);
-        }
-    }
 
     /**
      * Sets the given mcid as the kid of this structure element. This element
@@ -108,8 +128,13 @@ public class PDFStructElem extends PDFDictionary {
      * structure element's kid
      */
     public void setMCIDKid(int mcid) {
-        put("K", mcid);
-        joinHierarchy();
+        PDFArray kids = getKids();
+        /* check should be not neccessary */
+        if (kids == null) {
+            kids = new PDFArray();
+            put("K", kids);
+        }
+        kids.add(mcid);
     }
 
     /**
@@ -168,8 +193,10 @@ public class PDFStructElem extends PDFDictionary {
 
         if (k instanceof PDFArray)
             kids = (PDFArray) k;
+        /* check should be not neccessary */
         else if (k == null)
             kids = new PDFArray();
+        /* check should be not neccessary */
         else {
             kids = new PDFArray();
             kids.add(k);
@@ -207,7 +234,8 @@ public class PDFStructElem extends PDFDictionary {
             put("K", kids.get(0));
         if (kids.length() == 0) {
             remove("K");
-            return false;
+            if (trim)
+                return false;
         }
         getDocument().addObject(this, true);
         return true;
diff --git a/src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java b/src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java
index 2f4d77a..5958ea4 100644
--- a/src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java
+++ b/src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java
@@ -179,6 +179,15 @@ final class FOToPDFRoleMap {
         }
     }
 
+    public static boolean mapTrimAllowed(String fo, PDFObject parent) {
+        Mapper mapper = (Mapper)DEFAULT_MAPPINGS.get(fo);
+        if (mapper != null) {
+            return mapper.getTrimAllowed(parent);
+        } else {
+            return true;
+        }
+    }
+
     public static PDFName mapFormattingObject(StructureElement fo, PDFObject parent,
             EventBroadcaster eventBroadcaster) {
         PDFName type = null;
@@ -198,8 +207,23 @@ final class FOToPDFRoleMap {
         return type;
     }
 
+    public static boolean mapTrimAllowed(StructureElement fo, PDFObject parent,
+            EventBroadcaster eventBroadcaster) {
+        boolean result = true;
+        String role = fo.getRole();
+        if (role == null) {
+            result = mapTrimAllowed(fo.getName(), parent);
+        } else {
+            if (role.equals("TD"))
+              result = false;
+            // ????
+        }
+        return result;
+    }
+
     private static interface Mapper {
         PDFName getStructureType(PDFObject parent);
+        boolean getTrimAllowed(PDFObject parent); 
     }
 
     private static class SimpleMapper implements Mapper {
@@ -214,6 +238,9 @@ final class FOToPDFRoleMap {
             return structureType;
         }
 
+        public boolean getTrimAllowed(PDFObject parent) {
+            return true;
+        }
     }
 
     private static class TableCellMapper implements Mapper {
@@ -232,6 +259,9 @@ final class FOToPDFRoleMap {
             return type;
         }
 
+        public boolean getTrimAllowed(PDFObject parent) {
+            return false;
+        }
     }
 
     private FOToPDFRoleMap() { }
diff --git a/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java b/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java
index 80e1596..c2dd713 100644
--- a/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java
+++ b/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java
@@ -117,7 +117,8 @@ class PDFLogicalStructureHandler {
         this.eventBroadcaster = eventBroadcaster;
         PDFStructTreeRoot structTreeRoot = pdfDoc.getFactory().makeStructTreeRoot(parentTree);
         rootStructureElement = pdfDoc.getFactory().makeStructureElement(
-                FOToPDFRoleMap.mapFormattingObject("root", structTreeRoot), structTreeRoot);
+            FOToPDFRoleMap.mapFormattingObject("root", structTreeRoot), structTreeRoot,
+            FOToPDFRoleMap.mapTrimAllowed("root", structTreeRoot));
         pdfDoc.addTrailerObject (rootStructureElement);
         structTreeRoot.addKid(rootStructureElement);
     }
@@ -132,7 +133,8 @@ class PDFLogicalStructureHandler {
         pdfDoc.enforceLanguageOnRoot();
         PDFStructElem structElemPart = pdfDoc.getFactory().makeStructureElement(
                 FOToPDFRoleMap.mapFormattingObject(structureTree, rootStructureElement, eventBroadcaster),
-                rootStructureElement);
+                rootStructureElement,
+                FOToPDFRoleMap.mapTrimAllowed(structureTree, rootStructureElement, eventBroadcaster));
         rootStructureElement.addKid(structElemPart);
         if (language != null) {
             structElemPart.setLanguage(language);
@@ -156,9 +158,14 @@ class PDFLogicalStructureHandler {
 
         if ("hidden".equals(role))
             return;
-        if (!"inherit".equals(role)) {
+	if ("#text".equals(role))
+            structElem = pdfDoc.getFactory().makeStructureElement(PDFStructElem.TextName, parent, true);
+	else if ("inherit".equals(role))
+            structElem = parent;
+	else {
             structElem = pdfDoc.getFactory().makeStructureElement(
-                FOToPDFRoleMap.mapFormattingObject(node, parent, eventBroadcaster), parent);
+                FOToPDFRoleMap.mapFormattingObject(node, parent, eventBroadcaster), parent,
+                FOToPDFRoleMap.mapTrimAllowed(node, parent, eventBroadcaster));
 
             String nodeName = node.getName();
             if (nodeName.equals("external-graphic") || nodeName.equals("instream-foreign-object")) {
@@ -170,8 +177,6 @@ class PDFLogicalStructureHandler {
                 }
             }
         }
-        else
-            structElem = parent;
         
         if (isStatic)
             structStaticTreeMap.put(ptr, structElem);
@@ -236,7 +241,7 @@ class PDFLogicalStructureHandler {
         if (parent == null) {
             return ARTIFACT;
         } else {
-            pageParentTreeArray.add(parent);
+            pageParentTreeArray.add(parent.getTreeParent());
             String type = parent.getStructureType().toString();
             int mcid = pageParentTreeArray.length() - 1;
             return new MarkedContentInfo(type, mcid, parent);
-- 
1.6.4.2

