You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by ss...@apache.org on 2015/02/06 17:23:26 UTC

svn commit: r1657884 - in /xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF: lib/ lib/build/ src/java/org/apache/fop/render/pdf/pdfbox/ test/java/org/apache/fop/render/pdf/ test/resources/

Author: ssteiner
Date: Fri Feb  6 16:23:25 2015
New Revision: 1657884

URL: http://svn.apache.org/r1657884
Log:
FOP-2436: Merging of Tagged (Accessible) PDF

Added:
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/mockito-core-1.8.5.LICENCE.txt   (with props)
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/mockito-core-1.8.5.NOTICE.txt   (with props)
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/mockito-core-1.8.5.jar   (with props)
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/objenesis-1.0.0.LICENSE.txt   (with props)
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/objenesis-1.0.0.jar   (with props)
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/DocumentRootModifier.java   (with props)
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/PageParentTreeFinder.java   (with props)
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/StructureTreeMerger.java   (with props)
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/StructureTreeMergerUtil.java   (with props)
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/TaggedPDFConductor.java   (with props)
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/DocumentRootModifierTestCase.java   (with props)
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/PageParentTreeFinderTestCase.java   (with props)
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/StructureTreeMergerTestCase.java   (with props)
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/TaggedPDFConductorTestCase.java   (with props)
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/resources/NoParentTree.pdf   (with props)
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/resources/emptyRowTable.pdf   (with props)
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/resources/helloWorld.pdf   (with props)
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/resources/linkTagged.pdf   (with props)
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/resources/otf.pdf   (with props)
Modified:
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/fop.jar
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/AbstractPDFBoxHandler.java
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/MergeFontsPDFWriter.java
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/PDFBoxAdapter.java
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/PDFBoxImageHandler.java
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/PDFWriter.java
    xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java

Added: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/mockito-core-1.8.5.LICENCE.txt
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/mockito-core-1.8.5.LICENCE.txt?rev=1657884&view=auto
==============================================================================
--- xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/mockito-core-1.8.5.LICENCE.txt (added)
+++ xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/mockito-core-1.8.5.LICENCE.txt Fri Feb  6 16:23:25 2015
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2007 Mockito contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file

Propchange: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/mockito-core-1.8.5.LICENCE.txt
------------------------------------------------------------------------------
    svn:eol-style = native

Added: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/mockito-core-1.8.5.NOTICE.txt
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/mockito-core-1.8.5.NOTICE.txt?rev=1657884&view=auto
==============================================================================
--- xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/mockito-core-1.8.5.NOTICE.txt (added)
+++ xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/mockito-core-1.8.5.NOTICE.txt Fri Feb  6 16:23:25 2015
@@ -0,0 +1,11 @@
+Mockito license - MIT.
+
+Libraries used:
+
+Cglib - Apache License 2.0
+ASM - BSD license
+
+Mockito all distribution:
+
+Objenesis - MIT license
+Hamcrest - BSD license
\ No newline at end of file

Propchange: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/mockito-core-1.8.5.NOTICE.txt
------------------------------------------------------------------------------
    svn:eol-style = native

Added: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/mockito-core-1.8.5.jar
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/mockito-core-1.8.5.jar?rev=1657884&view=auto
==============================================================================
Binary file - no diff available.

Propchange: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/mockito-core-1.8.5.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/objenesis-1.0.0.LICENSE.txt
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/objenesis-1.0.0.LICENSE.txt?rev=1657884&view=auto
==============================================================================
--- xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/objenesis-1.0.0.LICENSE.txt (added)
+++ xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/objenesis-1.0.0.LICENSE.txt Fri Feb  6 16:23:25 2015
@@ -0,0 +1,18 @@
+Copyright (c) 2003-2008, Objenesis Team and all contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of 
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file

Propchange: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/objenesis-1.0.0.LICENSE.txt
------------------------------------------------------------------------------
    svn:eol-style = native

Added: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/objenesis-1.0.0.jar
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/objenesis-1.0.0.jar?rev=1657884&view=auto
==============================================================================
Binary file - no diff available.

Propchange: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/build/objenesis-1.0.0.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/fop.jar
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/lib/fop.jar?rev=1657884&r1=1657883&r2=1657884&view=diff
==============================================================================
Binary files - no diff available.

Modified: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/AbstractPDFBoxHandler.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/AbstractPDFBoxHandler.java?rev=1657884&r1=1657883&r2=1657884&view=diff
==============================================================================
--- xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/AbstractPDFBoxHandler.java (original)
+++ xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/AbstractPDFBoxHandler.java Fri Feb  6 16:23:25 2015
@@ -40,7 +40,9 @@ import org.apache.fop.pdf.PDFArray;
 import org.apache.fop.pdf.PDFDocument;
 import org.apache.fop.pdf.PDFPage;
 import org.apache.fop.pdf.PDFResources;
+import org.apache.fop.pdf.PDFStructElem;
 import org.apache.fop.pdf.Version;
+import org.apache.fop.render.pdf.PDFLogicalStructureHandler;
 import org.apache.fop.render.pdf.pdfbox.Cache.ValueMaker;
 
 /**
@@ -67,8 +69,11 @@ public abstract class AbstractPDFBoxHand
         = Collections.synchronizedMap(new WeakHashMap<Object, Cache<String, Map<Object, Object>>>());
 
     protected String createStreamForPDF(ImagePDF image, PDFPage targetPage, FOUserAgent userAgent,
-            AffineTransform at, FontInfo fontinfo, Rectangle pos, Map<Integer, PDFArray> pageNumbers)
-        throws IOException {
+                                        AffineTransform at, FontInfo fontinfo, Rectangle pos,
+                                        Map<Integer, PDFArray> pageNumbers,
+                                        PDFLogicalStructureHandler handler,
+                                        PDFStructElem curentSessionElem) throws IOException {
+
         EventBroadcaster eventBroadcaster = null;
         if (userAgent != null) {
             eventBroadcaster = userAgent.getEventBroadcaster();
@@ -117,7 +122,15 @@ public abstract class AbstractPDFBoxHand
         }
 
         PDFBoxAdapter adapter = new PDFBoxAdapter(targetPage, objectCache, pageNumbers);
-        String stream = adapter.createStreamFromPDFBoxPage(pddoc, page, originalImageUri, at, fontinfo, pos);
+        if (handler != null) {
+            adapter.setCurrentMCID(handler.getPageParentTree().length());
+        }
+        String stream = adapter.createStreamFromPDFBoxPage(pddoc, page, originalImageUri,
+                 at, fontinfo, pos);
+        if (userAgent.isAccessibilityEnabled()) {
+            TaggedPDFConductor conductor = new TaggedPDFConductor(curentSessionElem, handler, page, adapter);
+            conductor.handleLogicalStructure(pddoc);
+        }
         return stream;
     }
 

Added: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/DocumentRootModifier.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/DocumentRootModifier.java?rev=1657884&view=auto
==============================================================================
--- xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/DocumentRootModifier.java (added)
+++ xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/DocumentRootModifier.java Fri Feb  6 16:23:25 2015
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+package org.apache.fop.render.pdf.pdfbox;
+
+import java.io.IOException;
+
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+
+import org.apache.fop.pdf.PDFDictionary;
+import org.apache.fop.pdf.PDFDocument;
+import org.apache.fop.pdf.PDFStructTreeRoot;
+
+public class DocumentRootModifier {
+
+    private PDFBoxAdapter adapter;
+    private PDFDocument pdfDoc;
+
+    public DocumentRootModifier(PDFBoxAdapter adapter, PDFDocument pdfDoc) {
+        this.adapter = adapter;
+        this.pdfDoc = pdfDoc;
+    }
+
+    public void structTreeRootEntriesToCopy(COSDictionary structRootDict) throws IOException {
+        checkForMap(structRootDict, COSName.ROLE_MAP.getName());
+        checkForMap(structRootDict, "CLASS_MAP");
+    }
+
+    private void checkForMap(COSDictionary structRootDict, String mapName) throws IOException {
+        if (structRootDict.containsKey(mapName)) {
+            COSDictionary addedMapDict = (COSDictionary)structRootDict.getDictionaryObject(mapName);
+            PDFDictionary temp = (PDFDictionary) adapter.cloneForNewDocument(addedMapDict);
+            PDFStructTreeRoot structTreeRoot = pdfDoc.getRoot().getStructTreeRoot();
+            if (!structTreeRoot.containsKey(mapName)) {
+                structTreeRoot.put(mapName, temp);
+            } else {
+                PDFDictionary rootMap = (PDFDictionary)structTreeRoot.get(mapName);
+                addMapToStructTreeRoot(rootMap, temp, mapName);
+            }
+        }
+    }
+
+    private void mergeMapClass(PDFDictionary main, PDFDictionary addition) {
+        for (String key : addition.keySet()) {
+            main.put(key, addition.get(key));
+        }
+    }
+
+    private void mergeRoleMaps(PDFDictionary structRoot, PDFDictionary addition) {
+        for (String key : addition.keySet()) {
+            if (!structRoot.containsKey(key)) {
+                structRoot.put(key, addition.get(key));
+            }
+        }
+    }
+
+    private void addMapToStructTreeRoot(PDFDictionary rootMap, PDFDictionary map, String mapName) {
+        if (mapName.equals(COSName.ROLE_MAP.getName())) {
+            mergeRoleMaps(rootMap, map);
+        } else {
+            mergeMapClass(rootMap, map);
+        }
+    }
+}

Propchange: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/DocumentRootModifier.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/MergeFontsPDFWriter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/MergeFontsPDFWriter.java?rev=1657884&r1=1657883&r2=1657884&view=diff
==============================================================================
--- xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/MergeFontsPDFWriter.java (original)
+++ xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/MergeFontsPDFWriter.java Fri Feb  6 16:23:25 2015
@@ -68,7 +68,7 @@ public class MergeFontsPDFWriter extends
     private Collection<String> parentFonts;
 
     public MergeFontsPDFWriter(COSDictionary fonts, FontInfo fontInfo, String key, List<COSName> resourceNames) {
-        super(key, resourceNames);
+        super(key, resourceNames, 0);
         this.fonts = fonts;
         this.fontInfo = fontInfo;
     }

Modified: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/PDFBoxAdapter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/PDFBoxAdapter.java?rev=1657884&r1=1657883&r2=1657884&view=diff
==============================================================================
--- xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/PDFBoxAdapter.java (original)
+++ xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/PDFBoxAdapter.java Fri Feb  6 16:23:25 2015
@@ -100,6 +100,8 @@ public class PDFBoxAdapter {
     private Map<COSName, String> newXObj = new HashMap<COSName, String>();
     private Map<Integer, PDFArray> pageNumbers;
 
+    private int currentMCID;
+
     /**
      * Creates a new PDFBoxAdapter.
      * @param targetPage The target FOP PDF page object
@@ -113,15 +115,27 @@ public class PDFBoxAdapter {
         this.pageNumbers = pageNumbers;
     }
 
-    private Object cloneForNewDocument(Object base) throws IOException {
+    public PDFPage getTargetPage() {
+        return targetPage;
+    }
+
+    public int getCurrentMCID() {
+        return currentMCID;
+    }
+
+    public void setCurrentMCID(int currentMCID) {
+        this.currentMCID = currentMCID;
+    }
+
+    protected Object cloneForNewDocument(Object base) throws IOException {
         return cloneForNewDocument(base, base);
     }
 
-    private Object cloneForNewDocument(Object base, Object keyBase) throws IOException {
+    protected Object cloneForNewDocument(Object base, Object keyBase) throws IOException {
         return cloneForNewDocument(base, keyBase, Collections.EMPTY_LIST);
     }
 
-    private Object cloneForNewDocument(Object base, Object keyBase, Collection exclude) throws IOException {
+    protected Object cloneForNewDocument(Object base, Object keyBase, Collection exclude) throws IOException {
         if (base == null) {
             return null;
         }
@@ -262,11 +276,11 @@ public class PDFBoxAdapter {
         return cacheClonedObject(keyBase, stream);
     }
 
-    private Object getCachedClone(Object base) {
+    protected Object getCachedClone(Object base) {
         return clonedVersion.get(getBaseKey(base));
     }
 
-    private Object cacheClonedObject(Object base, Object cloned) {
+    protected Object cacheClonedObject(Object base, Object cloned) {
         Object key = getBaseKey(base);
         if (key == null) {
             return cloned;
@@ -276,7 +290,7 @@ public class PDFBoxAdapter {
             pdfDoc.registerObject(pdfobj);
             if (log.isTraceEnabled()) {
                 log.trace(key + ": " + pdfobj.getClass().getName() + " registered as "
-                            + pdfobj.getObjectNumber() + " " + pdfobj.getGeneration());
+                        + pdfobj.getObjectNumber() + " " + pdfobj.getGeneration());
             }
         }
         clonedVersion.put(key, cloned);
@@ -292,13 +306,12 @@ public class PDFBoxAdapter {
         }
     }
 
-    private void transferDict(COSDictionary orgDict, PDFStream targetDict,
-            Set filter) throws IOException {
+    private void transferDict(COSDictionary orgDict, PDFStream targetDict, Set filter) throws IOException {
         transferDict(orgDict, targetDict, filter, false);
     }
 
-    private void transferDict(COSDictionary orgDict, PDFStream targetDict,
-            Set filter, boolean inclusive) throws IOException {
+    private void transferDict(COSDictionary orgDict, PDFStream targetDict, Set filter, boolean inclusive)
+        throws IOException {
         Set<COSName> keys = orgDict.keySet();
         for (COSName key : keys) {
             if (inclusive && !filter.contains(key.getName())) {
@@ -354,8 +367,11 @@ public class PDFBoxAdapter {
 //            }
         }
         if (newStream == null) {
-            newStream = new PDFWriter(uniqueName,
-                    getResourceNames(sourcePageResources.getCOSDictionary())).writeText(pdStream);
+            PDFWriter writer = new PDFWriter(uniqueName, getResourceNames(sourcePageResources.getCOSDictionary()),
+                    currentMCID);
+            newStream = writer.writeText(pdStream);
+            currentMCID = writer.getCurrentMCID();
+
         }
         pdStream = new PDStream(sourceDoc, new ByteArrayInputStream(newStream.getBytes("ISO-8859-1")));
         mergeXObj(sourcePageResources.getCOSDictionary(), fontinfo, uniqueName);

Modified: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/PDFBoxImageHandler.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/PDFBoxImageHandler.java?rev=1657884&r1=1657883&r2=1657884&view=diff
==============================================================================
--- xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/PDFBoxImageHandler.java (original)
+++ xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/PDFBoxImageHandler.java Fri Feb  6 16:23:25 2015
@@ -70,7 +70,9 @@ public class PDFBoxImageHandler extends
         }
         FontInfo fontinfo = (FontInfo)context.getHint("fontinfo");
         String stream = createStreamForPDF(pdfImage, pdfContext.getPage(), pdfContext.getUserAgent(),
-                pageAdjust, fontinfo, pos, pdfContext.getPageNumbers());
+                pageAdjust, fontinfo, pos, pdfContext.getPageNumbers(),
+                pdfContext.getPdfLogicalStructureHandler(), pdfContext.getCurrentSessionStructElem());
+
         if (stream == null) {
             return;
         }

Modified: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/PDFWriter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/PDFWriter.java?rev=1657884&r1=1657883&r2=1657884&view=diff
==============================================================================
--- xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/PDFWriter.java (original)
+++ xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/PDFWriter.java Fri Feb  6 16:23:25 2015
@@ -40,10 +40,12 @@ public class PDFWriter {
     protected StringBuilder s = new StringBuilder();
     private String key;
     private List<COSName> resourceNames;
+    private int currentMCID;
 
-    public PDFWriter(String key, List<COSName> resourceNames) {
+    public PDFWriter(String key, List<COSName> resourceNames, int currentMCID) {
         this.key = key;
         this.resourceNames = resourceNames;
+        this.currentMCID = currentMCID;
     }
 
     public String writeText(PDStream pdStream) throws IOException {
@@ -100,9 +102,20 @@ public class PDFWriter {
             s.append("] ");
         } else if (c instanceof COSDictionary) {
             Collection<COSBase> dictArgs = new ArrayList<COSBase>();
-            for (Map.Entry<COSName, COSBase> cn : ((COSDictionary)c).entrySet()) {
-                dictArgs.add(cn.getKey());
-                dictArgs.add(cn.getValue());
+            if (currentMCID != 0 && op.getOperation().equals("BDC")) {
+                for (Map.Entry<COSName, COSBase> cn : ((COSDictionary)c).entrySet()) {
+                    if (cn.getKey().getName().equals("MCID")) {
+                        updateMCID(cn, dictArgs);
+                    } else {
+                        dictArgs.add(cn.getKey());
+                        dictArgs.add(cn.getValue());
+                    }
+                }
+            } else {
+                for (Map.Entry<COSName, COSBase> cn : ((COSDictionary)c).entrySet()) {
+                    dictArgs.add(cn.getKey());
+                    dictArgs.add(cn.getValue());
+                }
             }
             s.append("<<");
             readPDFArguments(op, dictArgs);
@@ -114,9 +127,21 @@ public class PDFWriter {
         }
     }
 
+    private void updateMCID(Map.Entry<COSName, COSBase> cn, Collection<COSBase> dictArgs) {
+        COSBase cosMCID = cn.getValue();
+        assert cosMCID instanceof COSInteger;
+        COSInteger mcid = (COSInteger) cosMCID;
+        COSInteger updatedID = COSInteger.get(mcid.intValue() + currentMCID);
+        dictArgs.add(cn.getKey());
+        dictArgs.add(updatedID);
+    }
+
     protected void addKey(COSName cn) {
         if (resourceNames.contains(cn)) {
             s.append(key);
         }
     }
+    protected int getCurrentMCID() {
+        return currentMCID;
+    }
 }

Added: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/PageParentTreeFinder.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/PageParentTreeFinder.java?rev=1657884&view=auto
==============================================================================
--- xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/PageParentTreeFinder.java (added)
+++ xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/PageParentTreeFinder.java Fri Feb  6 16:23:25 2015
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ */
+
+package org.apache.fop.render.pdf.pdfbox;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSInteger;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSObject;
+
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.common.PDNumberTreeNode;
+import org.apache.pdfbox.pdmodel.graphics.PDXObject;
+
+public class PageParentTreeFinder {
+
+    PDPage srcPage;
+    public PageParentTreeFinder(PDPage srcPage) {
+        this.srcPage = srcPage;
+    }
+
+    public COSArray getPageParentTreeArray(PDDocument srcDoc) {
+        int position = srcPage.getCOSDictionary().getInt(COSName.STRUCT_PARENTS);
+        if (position == -1) {
+            position = findXObjectStructParent();
+        }
+        if (position != -1) {
+            PDNumberTreeNode srcNumberTreeNode = srcDoc.getDocumentCatalog().getStructureTreeRoot().getParentTree();
+            COSArray parentTreeKids = traverseParentTree(srcNumberTreeNode.getCOSDictionary(), position);
+            return removeNonCOSObjects(parentTreeKids);
+        }
+        return new COSArray();
+    }
+    //TODO handle structural hierarchy in xboject stream
+    private int findXObjectStructParent() {
+        int position = -1;
+        Map<String, PDXObject> mapXObject = srcPage.findResources().getXObjects();
+        for (PDXObject t : mapXObject.values()) {
+            COSDictionary xObjectDict = (COSDictionary)t.getCOSObject();
+            position = xObjectDict.getInt(COSName.STRUCT_PARENTS);
+            if (position != -1) {
+                return position;
+            }
+        }
+        return position;
+    }
+
+    private COSArray traverseParentTree(COSDictionary numberTreeNodeDict, int position) {
+        COSArray numberTree;
+        COSArray parentTree;
+        List<COSArray> nums = new ArrayList<COSArray>();
+        if (numberTreeNodeDict.containsKey(COSName.NUMS)) {
+            numberTree = (COSArray)numberTreeNodeDict.getItem(COSName.NUMS);
+            return extractMarkedContentParents(numberTree, position);
+        } else {
+            parentTree = (COSArray) numberTreeNodeDict.getDictionaryObject(COSName.KIDS);
+            traverseKids(parentTree, position, nums);
+        }
+        return nums.get(0);
+    }
+
+    private void traverseKids(COSBase kids, int position, List<COSArray> numList) {
+        COSArray pageParentTree;
+        if (!numList.isEmpty()) {
+            return;
+        }
+        if (kids instanceof COSArray) {
+            COSArray kidsArray = (COSArray)kids;
+            for (COSBase kid : kidsArray) {
+                COSObject kidCOSObj = (COSObject) kid;
+                traverseKids(kidCOSObj, position, numList);
+            }
+        } else if (kids instanceof COSObject) {
+            COSObject kidCOSObj = (COSObject) kids;
+            if (kidCOSObj.getDictionaryObject(COSName.NUMS) == null) {
+                traverseKids(kidCOSObj.getDictionaryObject(COSName.KIDS), position, numList);
+
+            } else {
+                if (kidCOSObj.getDictionaryObject(COSName.LIMITS) != null) {
+                    COSArray kidCOSArray = (COSArray) kidCOSObj.getDictionaryObject(COSName.LIMITS);
+                    int lowerLimit = ((COSInteger) kidCOSArray.get(0)).intValue();
+                    int upperLimit = ((COSInteger) kidCOSArray.get(1)).intValue();
+                    if (lowerLimit <= position && position <= upperLimit) {
+                        COSArray nums = (COSArray) kidCOSObj.getDictionaryObject(COSName.NUMS);
+                        pageParentTree = (COSArray) nums.getObject(((position - lowerLimit) * 2) + 1);
+                        numList.add(pageParentTree);
+                        return;
+                    }
+                } else {
+                    COSArray nums = (COSArray) kidCOSObj.getDictionaryObject(COSName.NUMS);
+                    numList.add(extractMarkedContentParents(nums, position));
+                }
+            }
+        }
+    }
+
+    private COSArray extractMarkedContentParents(COSArray numberTree, int position) {
+        COSBase tempObject;
+        boolean keyFlag = false;
+        for (COSBase kid : numberTree) {
+            if (keyFlag) {
+                if (kid instanceof COSObject) {
+                    tempObject = ((COSObject)kid).getObject();
+                    return (COSArray)tempObject;
+                } else if (kid instanceof COSArray) {
+                    return (COSArray)kid;
+                }
+            }
+            if (kid instanceof COSInteger) {
+                int temp = ((COSInteger)kid).intValue();
+                if (temp == position) {
+                    keyFlag = true;
+                }
+            }
+        }
+        return new COSArray();
+    }
+    private COSArray removeNonCOSObjects(COSArray pageParentTreeArray) {
+        COSArray objectList = new COSArray();
+        for (COSBase entry : pageParentTreeArray) {
+            if (entry instanceof COSObject) {
+                COSObject entryObj = (COSObject)entry;
+                objectList.add(entryObj);
+            }
+        }
+        return objectList;
+    }
+}

Propchange: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/PageParentTreeFinder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/StructureTreeMerger.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/StructureTreeMerger.java?rev=1657884&view=auto
==============================================================================
--- xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/StructureTreeMerger.java (added)
+++ xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/StructureTreeMerger.java Fri Feb  6 16:23:25 2015
@@ -0,0 +1,450 @@
+/*
+ * 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.
+ */
+package org.apache.fop.render.pdf.pdfbox;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSInteger;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSObject;
+
+import org.apache.pdfbox.pdmodel.PDPage;
+
+import org.apache.fop.pdf.PDFDictionary;
+import org.apache.fop.pdf.PDFDocument;
+import org.apache.fop.pdf.PDFNumber;
+import org.apache.fop.pdf.PDFObject;
+import org.apache.fop.pdf.PDFPage;
+import org.apache.fop.pdf.PDFReference;
+import org.apache.fop.pdf.PDFStructElem;
+import org.apache.fop.render.pdf.PDFLogicalStructureHandler;
+
+public class StructureTreeMerger {
+
+    PDFBoxAdapter adapter;
+    PDFPage targetPage;
+    PDFDocument pdfDoc;
+    private PDPage srcPage;
+    private COSDictionary roleMap;
+    protected PDFStructElem currentSessionElem;
+    private PDFLogicalStructureHandler logicalStructHandler;
+    private Map<Integer, PDFStructElem> structElemCache = new HashMap<Integer, PDFStructElem>();
+    private Map<Integer, PDFStructElem> markedContentMap = new TreeMap<Integer, PDFStructElem>();
+    private int currentMCID;
+    private List<COSObject> topElems = new ArrayList<COSObject>();
+    private COSArray extra = new COSArray();
+
+    public StructureTreeMerger(PDFStructElem currentSessionElem, PDFLogicalStructureHandler logicalStructHandler,
+                               PDFBoxAdapter adapter, PDPage srcPage) {
+        this.adapter = adapter;
+        this.srcPage = srcPage;
+        this.targetPage = adapter.getTargetPage();
+        this.pdfDoc = targetPage.getDocument();
+        this.currentMCID = adapter.getCurrentMCID();
+        this.logicalStructHandler = logicalStructHandler;
+        this.currentSessionElem = currentSessionElem;
+    }
+
+    public void setRoleMap(COSDictionary roleMap) {
+        this.roleMap = roleMap;
+    }
+
+    public void copyStructure(COSArray pageParentTreeArray) throws IOException {
+        for (COSBase entry : pageParentTreeArray) {
+            COSObject entryObj = (COSObject)entry;
+            createPageStructElements(entryObj);
+        }
+        createParents(pageParentTreeArray);
+        for (COSObject top : topElems) {
+            findLeafNodesInPageFromStructElemObjects(top);
+        }
+        createParents(extra);
+        addToPageParentTreeArray();
+        removeNullPlaceholders();
+    }
+
+    public void createDirectDescendants(COSBase base, PDFStructElem parent) throws IOException {
+        if (base instanceof COSDictionary) {
+            COSDictionary baseDict = (COSDictionary)base;
+            if (baseDict.keySet().contains(COSName.K)) {
+                createDirectDescendants(baseDict.getItem(COSName.K), parent);
+            }
+        } else if (base instanceof COSArray) {
+            COSArray array = (COSArray)base;
+            for (int i = 0; i < array.size(); i++) {
+                createDirectDescendants(array.get(i), parent);
+            }
+        } else {
+            assert base instanceof COSObject;
+            COSObject obj = (COSObject)base;
+            createAndRegisterStructElem(obj);
+            PDFStructElem elem = structElemCache.get(obj.getObjectNumber().intValue());
+            copyElemEntries(obj, elem);
+            parent.addKid(elem);
+            elem.setParent(parent);
+            COSBase objKid = obj.getItem(COSName.K);
+            if (objKid != null) {
+                createDirectDescendants(objKid, elem);
+            }
+        }
+    }
+
+    public void setCurrentSessionElem() {
+        if (currentSessionElem == null) {
+            currentSessionElem = pdfDoc.getStructureTreeElements()
+                    .get(pdfDoc.getStructureTreeElements().size() - 1);
+        }
+    }
+
+    private void createParents(COSArray markedContentParents) throws IOException {
+        for (COSBase entry : markedContentParents) {
+            COSObject elemCos = (COSObject)entry;
+            COSObject elemParent = (COSObject)elemCos.getItem(COSName.P);
+            PDFStructElem elem = structElemCache.get(elemCos.getObjectNumber().intValue());
+            createParents(elemCos, elemParent, elem);
+        }
+    }
+
+    private PDFStructElem createAndRegisterStructElem(COSObject entry) {
+        PDFStructElem elem = new PDFStructElem();
+        pdfDoc.registerStructureElement(elem);
+        structElemCache.put(entry.getObjectNumber().intValue(), elem);
+        return elem;
+    }
+
+    private void copyElemEntries(COSBase base, PDFStructElem elem) throws IOException {
+        assert base instanceof COSObject;
+        COSObject baseObj = (COSObject) base;
+        COSDictionary baseDic = (COSDictionary) baseObj.getObject();
+        COSName[] names = {COSName.TYPE, COSName.S, COSName.PG, COSName.ALT, COSName.LANG, COSName.A,
+            COSName.ACTUAL_TEXT, COSName.T, COSName.E, COSName.C };
+        for (COSName name : names) {
+            if (baseDic.keySet().contains(name)) {
+                if (name.equals(COSName.PG)) {
+                    elem.put("Pg", targetPage.makeReference());
+                } else {
+                    elem.put(name.getName(), adapter.cloneForNewDocument(baseDic.getItem(name)));
+                }
+            }
+        }
+        adapter.cacheClonedObject(base, elem);
+    }
+
+    private PDFStructElem createPageStructElements(COSObject entry) throws IOException {
+        int objID = entry.getObjectNumber().intValue();
+        if (structElemCache.containsKey(objID)) {
+            return null;
+        }
+        PDFStructElem elem = createAndRegisterStructElem(entry);
+        copyElemEntries(entry, elem);
+        COSDictionary baseDict = (COSDictionary) entry.getObject();
+        COSBase kid = baseDict.getItem(COSName.K);
+        createKids(kid, baseDict, elem, false);
+        return elem;
+    }
+
+    private void createParents(COSObject cosElem, COSObject cosParentElem, PDFStructElem elem) throws IOException {
+        int elemObjectID = cosParentElem.getObjectNumber().intValue();
+        COSDictionary parentElemDictionary = (COSDictionary)cosParentElem.getObject();
+        PDFStructElem elemParent = structElemCache.get(elemObjectID);
+        if (isStructureTreeRoot(parentElemDictionary)) {
+            elem.setParent(currentSessionElem);
+            currentSessionElem.addKid(elem);
+            topElems.add(cosElem);
+            return;
+        } else if (elemParent != null) {
+            checkIlfStructureTypeIsPresent(parentElemDictionary, "TR");
+            if (!checkIlfStructureTypeIsPresent(parentElemDictionary, "TR")) {
+                elem.setParent(elemParent);
+                int position = StructureTreeMergerUtil.findObjectPositionInKidsArray(cosElem);
+                elemParent.addKidInSpecificOrder(position, elem);
+            }
+        } else if (!checkIlfStructureTypeIsPresent(parentElemDictionary, "Document")) {
+            elemParent = createAndRegisterStructElem(cosParentElem);
+            copyElemEntries(cosParentElem, elemParent);
+            elem.setParent(elemParent);
+            fillKidsWithNull(elemParent, (COSDictionary)cosParentElem.getObject());
+            if (((COSName)parentElemDictionary.getDictionaryObject(COSName.S)).getName().equals("TR")) {
+                COSBase rowKids = parentElemDictionary.getItem(COSName.K);
+                createKids(rowKids, parentElemDictionary, elemParent, true);
+            } else {
+                int position = StructureTreeMergerUtil.findObjectPositionInKidsArray(cosElem);
+                elemParent.addKidInSpecificOrder(position, elem);
+            }
+            COSObject parentObj = (COSObject)parentElemDictionary.getItem(COSName.P);
+            createParents(cosParentElem, parentObj, elemParent);
+        } else {
+            elem.setParent(currentSessionElem);
+            int position = StructureTreeMergerUtil.findObjectPositionInKidsArray(cosElem);
+            currentSessionElem.addKidInSpecificOrder(position, elem);
+            topElems.add(cosElem);
+        }
+    }
+
+    private void createKids(COSBase baseKid, COSDictionary parentDict, PDFStructElem parent,
+                            boolean originatedFromTableRow) throws IOException {
+        if (baseKid instanceof COSArray) {
+            COSArray baseArray = (COSArray) baseKid;
+            for (COSBase entry : baseArray) {
+                createKids(entry, parentDict, parent, originatedFromTableRow);
+            }
+        } else if (baseKid instanceof COSObject) {
+            COSObject kid = (COSObject)baseKid;
+            createKidFromCOSObject(kid, parentDict, parent, originatedFromTableRow);
+        } else if (baseKid instanceof COSInteger) {
+            if (checkPageEntryInAncestorsRecursively(parentDict)) {
+                PDFNumber num = (PDFNumber)adapter.cloneForNewDocument(baseKid);
+                createKidEntryFromInt(num, parent);
+            }
+        } else if (baseKid instanceof COSDictionary) {
+            COSDictionary mcrDict = (COSDictionary)baseKid;
+            createKidFromCOSDictionary(mcrDict, parent, parentDict);
+        }
+    }
+
+    private void createKidFromCOSObject(COSObject baseObj, COSDictionary parentDict, PDFStructElem parent,
+                                        boolean originatedFromTableRow) throws IOException {
+        COSBase baseKid = baseObj.getObject();
+        if (baseKid instanceof COSInteger) {
+            COSInteger number = (COSInteger) baseKid;
+            createKids(number, parentDict, parent, originatedFromTableRow);
+        } else {
+            COSDictionary unwrappedDict = (COSDictionary)baseKid;
+            if (unwrappedDict.getDictionaryObject(COSName.S) == null) {
+                COSDictionary mcrDict = (COSDictionary)baseKid;
+                createKidFromCOSDictionary(mcrDict, parent, parentDict);
+            } else if (originatedFromTableRow) {
+                int objID = baseObj.getObjectNumber().intValue();
+                if (structElemCache.get(objID) != null) {
+                    PDFStructElem kidElem = structElemCache.get(objID);
+                    parent.addKid(kidElem);
+                    kidElem.setParent(parent);
+                } else {
+                    createkidEntryFromCosObjectForRow(baseObj, parent);
+                }
+            } else {
+                parent.addKid(null);
+            }
+        }
+    }
+
+    private void createkidEntryFromCosObjectForRow(COSObject entree, PDFStructElem parent) throws IOException {
+        int entreeObjID = entree.getObjectNumber().intValue();
+        PDFStructElem elemRef = structElemCache.get(entreeObjID);
+        if (elemRef == null) {
+            elemRef = createAndRegisterStructElem(entree);
+            copyElemEntries(entree, elemRef);
+            COSDictionary baseDict = (COSDictionary) entree.getObject();
+            COSBase kid = baseDict.getItem(COSName.K);
+            createKids(kid, baseDict, elemRef, true);
+            parent.addKid(elemRef);
+        } else {
+            parent.addKid(elemRef);
+        }
+        elemRef.setParent(parent);
+    }
+
+    private boolean checkPageEntryInAncestorsRecursively(COSDictionary elem) {
+        if (elem.containsKey(COSName.PG)) {
+            COSDictionary pageDict = (COSDictionary)elem.getDictionaryObject(COSName.PG);
+            return srcPage.getCOSObject() == pageDict;
+        } else if (elem.containsKey(COSName.P)) {
+            COSDictionary parent = (COSDictionary)elem.getDictionaryObject(COSName.P);
+            return checkPageEntryInAncestorsRecursively(parent);
+        } else {
+            return true;
+        }
+    }
+
+    private boolean isElementFromSourcePage(COSDictionary mrcDict, COSDictionary parentDict) {
+        if (mrcDict.containsKey(COSName.PG)) {
+            COSDictionary page = (COSDictionary)mrcDict.getDictionaryObject(COSName.PG);
+            return srcPage.getCOSObject() == page;
+        } else {
+            return checkPageEntryInAncestorsRecursively(parentDict);
+        }
+    }
+
+    private void createKidFromCOSDictionary(COSDictionary mcrDict, PDFStructElem parent, COSDictionary baseDict)
+        throws IOException {
+        Collection<COSName> exclude = Arrays.asList(COSName.PG);
+        if (isElementFromSourcePage(mcrDict, baseDict)) {
+            PDFDictionary contentItem = (PDFDictionary)adapter.cloneForNewDocument(mcrDict, mcrDict, exclude);
+            if (mcrDict.keySet().contains(COSName.TYPE)) {
+                String type = ((COSName) mcrDict.getDictionaryObject(COSName.TYPE)).getName();
+                if (type.equals("OBJR")) {
+                    COSObject obj = (COSObject) mcrDict.getItem(COSName.OBJ);
+                    PDFReference referenceObj = ((PDFObject) adapter.getCachedClone(obj)).makeReference();
+                    contentItem.put("Obj", referenceObj);
+                    updateStructParentAndAddToPageParentTree(referenceObj, parent);
+                } else if (type.equals("MCR")) {
+                    updateMCIDEntry(contentItem);
+                    markedContentMap.put((((PDFNumber)contentItem.get(COSName.MCID.getName())).getNumber())
+                            .intValue(), parent);
+                }
+            }
+            if (mcrDict.keySet().contains(COSName.PG)) {
+                contentItem.put("Pg", targetPage.makeReference());
+            } else {
+                parent.put("Pg", targetPage.makeReference());
+            }
+            parent.addKid(contentItem);
+        } else {
+            parent.addKid(null);
+        }
+    }
+
+    private void createKidEntryFromInt(PDFNumber num, PDFStructElem parent) {
+        num.setNumber(num.getNumber().intValue() + currentMCID);
+        parent.addKid(num);
+        markedContentMap.put(num.getNumber().intValue(), parent);
+    }
+
+    private void updateMCIDEntry(PDFDictionary mcrDictionary) {
+        if (currentMCID > 0) {
+            int oldMCID = (((PDFNumber)mcrDictionary.get("MCID")).getNumber()).intValue();
+            PDFNumber number = new PDFNumber();
+            number.setNumber(oldMCID + currentMCID);
+            mcrDictionary.put("MCID", number);
+        }
+    }
+
+    private void removeNullPlaceholders() {
+        List<PDFStructElem> list = new ArrayList<PDFStructElem>(structElemCache.values());
+        for (PDFStructElem elem : list) {
+            List<PDFObject> kids = elem.getKids();
+            if (kids != null) {
+                kids.removeAll(Collections.singleton(null));
+            }
+        }
+    }
+
+    private boolean isStructureTreeRoot(COSDictionary elem) {
+        if (elem.keySet().contains(COSName.TYPE)) {
+            COSName type = (COSName)elem.getDictionaryObject(COSName.TYPE);
+            return type.equals(COSName.STRUCT_TREE_ROOT);
+        }
+        return false;
+    }
+
+    public void addToPageParentTreeArray() {
+        for (PDFStructElem entry : markedContentMap.values()) {
+            logicalStructHandler.getPageParentTree().add(entry);
+        }
+    }
+
+    private void updateStructParentAndAddToPageParentTree(PDFReference obj, PDFStructElem elem) {
+        PDFObject referenceObj = obj.getObject();
+        assert referenceObj instanceof PDFDictionary;
+        int nextParentTreeKey;
+        PDFDictionary objDict = (PDFDictionary)referenceObj;
+        nextParentTreeKey = logicalStructHandler.getNextParentTreeKey();
+        objDict.put("StructParent", nextParentTreeKey);
+        logicalStructHandler.getParentTree().addToNums(nextParentTreeKey, elem);
+    }
+
+    public void setCurrentSessionElemKid() {
+        PDFNumber num = new PDFNumber();
+        createKidEntryFromInt(num, currentSessionElem);
+        addToPageParentTreeArray();
+    }
+
+    private void findLeafNodesInPageFromStructElemObjects(COSBase entry) throws IOException {
+        if (entry instanceof COSObject) {
+            COSObject entryObj = (COSObject) entry;
+            COSDictionary structElemDictionary = (COSDictionary) entryObj.getObject();
+            COSBase kid = structElemDictionary.getItem(COSName.K);
+            findLeafKids(kid, entryObj);
+        }
+    }
+
+    private void findLeafKids(COSBase kid, COSObject parent) throws IOException {
+        if (kid instanceof COSArray) {
+            COSArray arrayKid = (COSArray)kid;
+            for (COSBase arrayEntry : arrayKid) {
+                findLeafKids(arrayEntry, parent);
+            }
+        } else if (kid instanceof COSObject) {
+            COSObject kidObject = (COSObject)kid;
+            COSBase base = kidObject.getObject();
+            COSDictionary temp = (COSDictionary)base;
+            if (temp.getDictionaryObject(COSName.S) != null && temp.getItem(COSName.K) != null) {
+
+                COSBase tempKids = temp.getItem(COSName.K);
+                findLeafKids(tempKids, kidObject);
+            } else {
+                findLeafKids(temp, parent);
+            }
+        } else if (kid instanceof COSDictionary) {
+            COSDictionary kidDictionary = (COSDictionary)kid;
+            COSDictionary parentDict = (COSDictionary)parent.getObject();
+            if (isElementFromSourcePage(kidDictionary, parentDict)) {
+                PDFStructElem elem = structElemCache.get(parent.getObjectNumber().intValue());
+                if (elem == null) {
+                    elem = createAndRegisterStructElem(parent);
+                    copyElemEntries(parent, elem);
+                    extra.add(parent);
+                    createKids(kid, parentDict, elem, false);
+                }
+            }
+        } else {
+            assert kid instanceof COSInteger;
+            COSDictionary parentDict = (COSDictionary)parent.getObject();
+            if (checkPageEntryInAncestorsRecursively(parentDict)) {
+                PDFStructElem elem = structElemCache.get(parent.getObjectNumber().intValue());
+                if (elem == null) {
+                    elem = createAndRegisterStructElem(parent);
+                    copyElemEntries(parent, elem);
+                    createKids(kid, parentDict, elem, false);
+                }
+            }
+        }
+    }
+
+    private void fillKidsWithNull(PDFStructElem elem, COSDictionary baseElem) {
+        COSBase baseArray = baseElem.getItem(COSName.K);
+        if (baseArray instanceof COSArray) {
+            COSArray array = (COSArray)baseArray;
+            int size = array.size();
+            for (int i = 0; i < size; i++) {
+                elem.addKid(null);
+            }
+        }
+    }
+
+    private boolean checkIlfStructureTypeIsPresent(COSDictionary elemDictionary, String type) {
+        String potentialCustomElemType = ((COSName)elemDictionary.getDictionaryObject(COSName.S)).getName();
+        if (type.equals(potentialCustomElemType)) {
+            return true;
+        } else {
+            List<String> rolemapValues = StructureTreeMergerUtil.findRoleMapKeyByValue(type, roleMap);
+            return rolemapValues.contains(potentialCustomElemType);
+        }
+    }
+
+}

Propchange: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/StructureTreeMerger.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/StructureTreeMergerUtil.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/StructureTreeMergerUtil.java?rev=1657884&view=auto
==============================================================================
--- xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/StructureTreeMergerUtil.java (added)
+++ xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/StructureTreeMergerUtil.java Fri Feb  6 16:23:25 2015
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+package org.apache.fop.render.pdf.pdfbox;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map.Entry;
+
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSObject;
+
+public final class StructureTreeMergerUtil {
+
+    private StructureTreeMergerUtil() { }
+
+    public static int findObjectPositionInKidsArray(COSObject kid) {
+        COSObject parent = (COSObject) kid.getItem(COSName.P);
+        COSBase kids = parent.getItem(COSName.K);
+        if (kids instanceof COSArray) {
+            COSArray kidsArray = (COSArray)kids;
+            return kidsArray.indexOfObject(kid);
+        } else {
+            return 0;
+        }
+    }
+
+    public static List<String> findRoleMapKeyByValue(String type, COSDictionary roleMap) {
+        List<String> keys = new ArrayList<String>();
+        if (roleMap != null) {
+            for (Entry<COSName, COSBase> entry : roleMap.entrySet()) {
+                String value = ((COSName)entry.getValue()).getName();
+                String key = entry.getKey().getName();
+                if (type.equals(value)) {
+                    keys.add(key);
+                }
+            }
+        }
+        return keys;
+    }
+}

Propchange: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/StructureTreeMergerUtil.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/TaggedPDFConductor.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/TaggedPDFConductor.java?rev=1657884&view=auto
==============================================================================
--- xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/TaggedPDFConductor.java (added)
+++ xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/TaggedPDFConductor.java Fri Feb  6 16:23:25 2015
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+
+package org.apache.fop.render.pdf.pdfbox;
+
+import java.io.IOException;
+
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.documentinterchange.logicalstructure.PDMarkInfo;
+
+import org.apache.fop.pdf.PDFDocument;
+import org.apache.fop.pdf.PDFName;
+import org.apache.fop.pdf.PDFPage;
+import org.apache.fop.pdf.PDFStructElem;
+import org.apache.fop.render.pdf.PDFLogicalStructureHandler;
+
+public class TaggedPDFConductor {
+
+    private PDPage srcPage;
+    private PDFDocument pdfDoc;
+    private PDFPage targetPage;
+    private DocumentRootModifier rootMod;
+    private StructureTreeMerger merger;
+
+    public TaggedPDFConductor(PDFStructElem currentSessionElem,
+                              PDFLogicalStructureHandler logicalStructHandler, PDPage srcPage,
+                              PDFBoxAdapter adapter) {
+        this.srcPage = srcPage;
+        this.targetPage = adapter.getTargetPage();
+        this.pdfDoc = targetPage.getDocument();
+        this.rootMod = new DocumentRootModifier(adapter, pdfDoc);
+        merger = new StructureTreeMerger(currentSessionElem, logicalStructHandler, adapter, srcPage);
+    }
+
+    public void handleLogicalStructure(PDDocument srcDoc) throws IOException {
+        if (isInputPDFTagged(srcDoc) && isStructureTreeRootNull(srcDoc)) {
+            merger.setCurrentSessionElem();
+            COSDictionary strucRootDict = (COSDictionary)srcDoc.getDocumentCatalog().getStructureTreeRoot()
+                .getCOSObject();
+            rootMod.structTreeRootEntriesToCopy(strucRootDict);
+            if (!isParentTreeIsPresent(strucRootDict)) {
+                merger.createDirectDescendants(strucRootDict, merger.currentSessionElem);
+            } else {
+                PageParentTreeFinder markedContentsParentFinder = new PageParentTreeFinder(srcPage);
+                COSArray markedContentsParents = markedContentsParentFinder.getPageParentTreeArray(srcDoc);
+                COSDictionary roleMap = (COSDictionary)strucRootDict.getDictionaryObject(COSName.ROLE_MAP);
+                if (roleMap != null) {
+                    merger.setRoleMap(roleMap);
+                }
+                merger.copyStructure(markedContentsParents);
+            }
+        }
+        configureCurrentSessionElem(srcDoc);
+    }
+
+    private void configureCurrentSessionElem(PDDocument srcDoc) {
+        if (!(isInputPDFTagged(srcDoc) && isStructureTreeRootNull(srcDoc))) {
+            merger.setCurrentSessionElemKid();
+            merger.currentSessionElem.put(COSName.PG.getName(), targetPage.makeReference());
+        } else {
+            merger.currentSessionElem.put("S", new PDFName("Div"));
+        }
+    }
+    private boolean isInputPDFTagged(PDDocument srcDoc) {
+        PDMarkInfo mark = srcDoc.getDocumentCatalog().getMarkInfo();
+        return mark != null && mark.isMarked();
+    }
+
+    private boolean isStructureTreeRootNull(PDDocument srcDoc) {
+        return srcDoc.getDocumentCatalog().getStructureTreeRoot() != null;
+    }
+
+    private boolean isParentTreeIsPresent(COSDictionary strucRootDict) {
+        return strucRootDict.keySet().contains(COSName.PARENT_TREE);
+    }
+}

Propchange: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/src/java/org/apache/fop/render/pdf/pdfbox/TaggedPDFConductor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/DocumentRootModifierTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/DocumentRootModifierTestCase.java?rev=1657884&view=auto
==============================================================================
--- xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/DocumentRootModifierTestCase.java (added)
+++ xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/DocumentRootModifierTestCase.java Fri Feb  6 16:23:25 2015
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+package org.apache.fop.render.pdf;
+
+import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+import java.util.HashMap;
+
+import org.junit.Test;
+
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+
+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.PDFPage;
+import org.apache.fop.pdf.PDFResources;
+import org.apache.fop.pdf.PDFStructTreeRoot;
+import org.apache.fop.render.pdf.pdfbox.DocumentRootModifier;
+import org.apache.fop.render.pdf.pdfbox.PDFBoxAdapter;
+
+import junit.framework.Assert;
+
+public class DocumentRootModifierTestCase {
+
+    @Test
+    public void testStructTreeRootEntriesToCopy() throws IOException {
+        Rectangle2D r = new Rectangle2D.Double();
+        PDFPage page = new PDFPage(new PDFResources(0), 0, r, r, r, r);
+        page.setObjectNumber(1);
+        PDFDocument pdfDoc = new PDFDocument("");
+        page.setDocument(pdfDoc);
+        pdfDoc.makeStructTreeRoot(null);
+        PDFStructTreeRoot structTreeRoot = pdfDoc.getRoot().getStructTreeRoot();
+        PDFDictionary rootBaseRoleMap = new PDFDictionary();
+        PDFName para = new PDFName("P");
+        rootBaseRoleMap.put("MyPara", para);
+        structTreeRoot.put("RoleMap", rootBaseRoleMap);
+        PDFBoxAdapter adapter = new PDFBoxAdapter(page, new HashMap(),  new HashMap<Integer, PDFArray>());
+        COSDictionary root = new COSDictionary();
+        COSDictionary mapRole = new COSDictionary();
+        mapRole.setName("Icon", "Figure");
+        root.setItem(COSName.ROLE_MAP, mapRole);
+        DocumentRootModifier modifier = new DocumentRootModifier(adapter, pdfDoc);
+        modifier.structTreeRootEntriesToCopy(root);
+        structTreeRoot = pdfDoc.getRoot().getStructTreeRoot();
+        PDFDictionary baseRoot = (PDFDictionary) structTreeRoot.get("RoleMap");
+        PDFName nameIcon = (PDFName) baseRoot.get("Icon");
+        PDFName myPara = (PDFName)baseRoot.get("MyPara");
+        String test = nameIcon.getName();
+        String expected = "Figure";
+        Assert.assertEquals(test, expected);
+        test = myPara.getName();
+        expected = "P";
+        Assert.assertEquals(test, expected);
+    }
+}

Propchange: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/DocumentRootModifierTestCase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java?rev=1657884&r1=1657883&r2=1657884&view=diff
==============================================================================
--- xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java (original)
+++ xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java Fri Feb  6 16:23:25 2015
@@ -42,6 +42,9 @@ import org.apache.fop.render.pdf.pdfbox.
 import org.apache.fop.render.pdf.pdfbox.PDFBoxImageHandler;
 import org.junit.Test;
 
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
 import org.apache.commons.io.IOUtils;
 import org.apache.fontbox.cff.CFFFont;
 import org.apache.fontbox.cff.CFFParser;
@@ -57,6 +60,7 @@ import org.apache.xmlgraphics.image.load
 import org.apache.xmlgraphics.image.loader.ImageSource;
 import org.apache.xmlgraphics.image.loader.impl.DefaultImageContext;
 
+import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.fonts.CustomFont;
 import org.apache.fop.fonts.FontInfo;
 import org.apache.fop.fonts.FontType;
@@ -312,7 +316,6 @@ public class PDFBoxAdapterTestCase {
         Assert.assertTrue(pageNumbers.size() == 4);
         PDFAnnotList annots = (PDFAnnotList) pdfpage.get("Annots");
         Assert.assertEquals(annots.toPDFString(), "[\n9 0 R\n12 0 R\n]");
-//        pdfdoc.output(System.out);
         doc.close();
     }
 
@@ -335,7 +338,9 @@ public class PDFBoxAdapterTestCase {
         pdfdoc.assignObjectNumber(g);
         pdfpage.addGState(g);
         PDFContentGenerator con = new PDFContentGenerator(pdfdoc, null, null);
-        PDFRenderingContext c = new PDFRenderingContext(null, con, pdfpage, null);
+        FOUserAgent mockedAgent = mock(FOUserAgent.class);
+        when(mockedAgent.isAccessibilityEnabled()).thenReturn(false);
+        PDFRenderingContext c = new PDFRenderingContext(mockedAgent, con, pdfpage, null);
         c.setPageNumbers(new HashMap<Integer, PDFArray>());
         new PDFBoxImageHandler().handleImage(c, img, new Rectangle());
         PDFResources res = c.getPage().getPDFResources();

Added: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/PageParentTreeFinderTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/PageParentTreeFinderTestCase.java?rev=1657884&view=auto
==============================================================================
--- xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/PageParentTreeFinderTestCase.java (added)
+++ xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/PageParentTreeFinderTestCase.java Fri Feb  6 16:23:25 2015
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+package org.apache.fop.render.pdf;
+
+import java.io.IOException;
+
+import org.junit.Test;
+
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSObject;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+
+import org.apache.fop.render.pdf.pdfbox.PageParentTreeFinder;
+
+import junit.framework.Assert;
+
+public class PageParentTreeFinderTestCase {
+    private static final String LINK = "test/resources/linkTagged.pdf";
+
+    @Test
+    public void testGetPageParentTreeArray() throws IOException {
+        PDDocument doc = PDDocument.load(LINK);
+        PDPage srcPage = doc.getPage(0);
+        PageParentTreeFinder finder = new PageParentTreeFinder(srcPage);
+        COSArray markedContentParents = finder.getPageParentTreeArray(doc);
+        Assert.assertEquals(markedContentParents.size(), 3);
+        COSObject firstObj = (COSObject)markedContentParents.get(0);
+        COSObject secObj = (COSObject)markedContentParents.get(1);
+        COSArray firstKids = (COSArray)firstObj.getDictionaryObject(COSName.K);
+        COSDictionary firstKid = (COSDictionary) firstKids.get(0);
+        int test = firstKid.getInt("MCID");
+        int expected = 0;
+        Assert.assertEquals(test, expected);
+        COSDictionary firstKidBrother = (COSDictionary)firstKids.get(2);
+        test = firstKidBrother.getInt("MCID");
+        expected = 2;
+        Assert.assertEquals(test, expected);
+        COSArray secKidsArray = (COSArray)secObj.getDictionaryObject(COSName.K);
+        COSDictionary secondKid = (COSDictionary)secKidsArray.get(0);
+        test = secondKid.getInt("MCID");
+        expected = 1;
+        Assert.assertEquals(test, expected);
+    }
+}

Propchange: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/PageParentTreeFinderTestCase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/StructureTreeMergerTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/StructureTreeMergerTestCase.java?rev=1657884&view=auto
==============================================================================
--- xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/StructureTreeMergerTestCase.java (added)
+++ xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/StructureTreeMergerTestCase.java Fri Feb  6 16:23:25 2015
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ */
+
+package org.apache.fop.render.pdf;
+
+import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSDictionary;
+
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+
+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.PDFNumber;
+import org.apache.fop.pdf.PDFPage;
+import org.apache.fop.pdf.PDFReference;
+import org.apache.fop.pdf.PDFResources;
+import org.apache.fop.pdf.PDFStructElem;
+
+import org.apache.fop.render.pdf.pdfbox.PDFBoxAdapter;
+import org.apache.fop.render.pdf.pdfbox.PageParentTreeFinder;
+import org.apache.fop.render.pdf.pdfbox.StructureTreeMerger;
+
+import junit.framework.Assert;
+
+public class StructureTreeMergerTestCase {
+    private static final String LINK = "test/resources/linkTagged.pdf";
+    private static final String NoParentTree = "test/resources/NoParentTree.pdf";
+    private PDFPage pdfPage;
+    private PDFDocument pdfDoc;
+    private PDFBoxAdapter adapter;
+
+    @Test
+    public void testCopyStructure() throws IOException {
+        setUp();
+        PDDocument doc = PDDocument.load(LINK);
+        PDPage srcPage = doc.getPage(0);
+        PageParentTreeFinder finder = new PageParentTreeFinder(srcPage);
+        COSArray markedContentParents = finder.getPageParentTreeArray(doc);
+        PDFStructElem elem = new PDFStructElem();
+        elem.setObjectNumber(2);
+        adapter = new PDFBoxAdapter(pdfPage, new HashMap(), new HashMap<Integer, PDFArray>());
+        PDFLogicalStructureHandler handler = setUpPDFLogicalStructureHandler();
+        StructureTreeMerger merger = new StructureTreeMerger(elem, handler, adapter, srcPage);
+        merger.copyStructure(markedContentParents);
+        PDFArray array = handler.getPageParentTree();
+        checkMarkedContentsParentsForLinkTest(array);
+        PDFStructElem first = (PDFStructElem)array.get(0);
+        checkParentForLinkTest(first, 0);
+    }
+
+    @Test
+    public void testCreateDirectDescendants() throws IOException {
+        setUp();
+        PDDocument doc = PDDocument.load(NoParentTree);
+        PDPage srcPage = doc.getPage(0);
+        PDFStructElem elem = new PDFStructElem();
+        elem.setObjectNumber(2);
+        adapter = new PDFBoxAdapter(pdfPage, new HashMap(), new HashMap<Integer, PDFArray>());
+        PDFLogicalStructureHandler handler = setUpPDFLogicalStructureHandler();
+        StructureTreeMerger merger = new StructureTreeMerger(elem, handler, adapter, srcPage);
+        COSDictionary strucRootDict = (COSDictionary)doc.getDocumentCatalog().getStructureTreeRoot()
+            .getCOSObject();
+        merger.createDirectDescendants(strucRootDict, elem);
+        checkNoParentTree(elem, 0);
+    }
+
+    private void checkMarkedContentsParentsForLinkTest(PDFArray array) {
+        PDFStructElem first = (PDFStructElem)array.get(0);
+        List firstKids = first.getKids();
+        PDFDictionary firstKid = (PDFDictionary) firstKids.get(0);
+        int test = ((PDFNumber)firstKid.get("MCID")).getNumber().intValue();
+        int expected = 0;
+        Assert.assertEquals(test, expected);
+        PDFDictionary firstKidSibling = (PDFDictionary) firstKids.get(2);
+        test = ((PDFNumber)firstKidSibling.get("MCID")).getNumber().intValue();
+        expected = 2;
+        Assert.assertEquals(test, expected);
+        PDFStructElem second = (PDFStructElem)array.get(1);
+        List secondKids = second.getKids();
+        PDFDictionary secKid = (PDFDictionary) secondKids.get(0);
+        test = ((PDFNumber)secKid.get("MCID")).getNumber().intValue();
+        expected = 1;
+        Assert.assertEquals(test, expected);
+    }
+
+    private void checkParentForLinkTest(PDFStructElem elem, int index) {
+        String [] types = {"Sect", "Part"};
+        PDFStructElem parent = (PDFStructElem)((PDFReference)elem.get("P")).getObject();
+        if (index != 2) {
+            String test = ((PDFName)parent.get("S")).getName();
+            String expected = types[index];
+            Assert.assertEquals(test, expected);
+            index++;
+            checkParentForLinkTest(parent, index);
+        }
+    }
+
+    private void setUp() {
+        Rectangle2D r = new Rectangle2D.Double();
+        pdfPage = new PDFPage(new PDFResources(0), 0, r, r, r, r);
+        pdfDoc = new PDFDocument(" ");
+        pdfDoc.makeStructTreeRoot(null);
+        pdfPage.setObjectNumber(1);
+        pdfPage.setDocument(pdfDoc);
+    }
+
+    private PDFLogicalStructureHandler setUpPDFLogicalStructureHandler() {
+        PDFLogicalStructureHandler handler = new PDFLogicalStructureHandler(pdfDoc);
+        handler.getParentTree().setDocument(pdfDoc);
+        handler.startPage(pdfPage);
+        return handler;
+    }
+
+    private void checkNoParentTree(PDFStructElem elem, int index) {
+        String [] types = {"Document", "Part"};
+        if (index != 2) {
+            PDFStructElem kid = (PDFStructElem)elem.getKids().get(0);
+            String test = ((PDFName)kid.get("S")).getName();
+            String expected = types[index];
+            Assert.assertEquals(test, expected);
+            index++;
+            checkNoParentTree(kid, index);
+        }
+    }
+}

Propchange: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/StructureTreeMergerTestCase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/TaggedPDFConductorTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/TaggedPDFConductorTestCase.java?rev=1657884&view=auto
==============================================================================
--- xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/TaggedPDFConductorTestCase.java (added)
+++ xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/TaggedPDFConductorTestCase.java Fri Feb  6 16:23:25 2015
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ */
+
+package org.apache.fop.render.pdf;
+
+import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+
+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.PDFNumber;
+import org.apache.fop.pdf.PDFObject;
+import org.apache.fop.pdf.PDFPage;
+import org.apache.fop.pdf.PDFResources;
+import org.apache.fop.pdf.PDFStructElem;
+import org.apache.fop.render.pdf.pdfbox.PDFBoxAdapter;
+import org.apache.fop.render.pdf.pdfbox.TaggedPDFConductor;
+
+import junit.framework.Assert;
+
+public class TaggedPDFConductorTestCase {
+    private static final String LINK = "test/resources/linkTagged.pdf";
+    private static final String HELLO = "test/resources/helloWorld.pdf";
+    private static final String TABLE = "test/resources/emptyRowTable.pdf";
+    private static final String OTF = "test/resources/otf.pdf";
+    private PDFPage pdfPage;
+    private PDFDocument pdfDoc;
+
+    @Test
+    public void testHandleLogicalStructure() throws IOException {
+        PDFStructElem elem = new PDFStructElem();
+        runConductor(LINK, elem);
+        checkStructure(elem, 0);
+
+        elem = new PDFStructElem();
+        runConductor(HELLO, elem);
+        PDFNumber mcid = (PDFNumber)elem.getKids().get(0);
+        int test = mcid.getNumber().intValue();
+        Assert.assertEquals(test, 0);
+
+        elem = new PDFStructElem();
+        runConductor(TABLE, elem);
+        Assert.assertEquals(print(elem), "/Div/Part/Sect/Table/TBody/TR/TD/P/TD/P/TR/TD/TD");
+
+        elem = new PDFStructElem();
+        runConductor(OTF, elem);
+        Assert.assertEquals(print(elem), "/Div/Part/Art/P/Span");
+    }
+
+    private String print(PDFStructElem x) throws IOException {
+        StringBuilder sb = new StringBuilder(x.get("S").toString());
+        for (PDFObject k : x.getKids()) {
+            if (k instanceof PDFStructElem) {
+                sb.append(print((PDFStructElem) k));
+            }
+        }
+        return sb.toString();
+    }
+
+    private void runConductor(String pdf, PDFStructElem elem) throws IOException {
+        setUp();
+        PDDocument doc = PDDocument.load(pdf);
+        PDPage srcPage = doc.getPage(0);
+        elem.setObjectNumber(2);
+        PDFBoxAdapter adapter = new PDFBoxAdapter(
+                pdfPage, new HashMap(),  new HashMap<Integer, PDFArray>());
+        PDFLogicalStructureHandler handler = setUpPDFLogicalStructureHandler();
+        new TaggedPDFConductor(elem, handler, srcPage, adapter).handleLogicalStructure(doc);
+    }
+
+    private void setUp() {
+        Rectangle2D r = new Rectangle2D.Double();
+        pdfPage = new PDFPage(new PDFResources(0), 0, r, r, r, r);
+        pdfDoc = new PDFDocument(" ");
+        pdfDoc.makeStructTreeRoot(null);
+        pdfPage.setObjectNumber(1);
+        pdfPage.setDocument(pdfDoc);
+    }
+
+    private PDFLogicalStructureHandler setUpPDFLogicalStructureHandler() {
+        PDFLogicalStructureHandler handler = new PDFLogicalStructureHandler(pdfDoc);
+        handler.getParentTree().setDocument(pdfDoc);
+        handler.startPage(pdfPage);
+        return handler;
+    }
+
+    private void checkStructure(PDFStructElem elem, int index) {
+        String [] types = {"Part", "Sect", "P"};
+        List<PDFObject> list = elem.getKids();
+        if (index != 3) {
+            PDFStructElem kid = (PDFStructElem)list.get(0);
+            String test = ((PDFName)kid.get("S")).getName();
+            String expected = types[index];
+            Assert.assertEquals(test, expected);
+            index++;
+            checkStructure(kid, index);
+        } else {
+            PDFDictionary firstKid = (PDFDictionary) list.get(0);
+            int test = ((PDFNumber)firstKid.get("MCID")).getNumber().intValue();
+            int expected = 0;
+            Assert.assertEquals(test, expected);
+            PDFDictionary firstKidSibling = (PDFDictionary) list.get(2);
+            test = ((PDFNumber)firstKidSibling.get("MCID")).getNumber().intValue();
+            expected = 2;
+            Assert.assertEquals(test, expected);
+            PDFStructElem second = (PDFStructElem)list.get(1);
+            List secondKids = second.getKids();
+            PDFStructElem secKid = (PDFStructElem) secondKids.get(0);
+            List secondKidKids = secKid.getKids();
+            PDFDictionary leafElem = (PDFDictionary)secondKidKids.get(0);
+            test = ((PDFNumber)leafElem.get("MCID")).getNumber().intValue();
+            expected = 1;
+            Assert.assertEquals(test, expected);
+        }
+    }
+}

Propchange: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/java/org/apache/fop/render/pdf/TaggedPDFConductorTestCase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/resources/NoParentTree.pdf
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/resources/NoParentTree.pdf?rev=1657884&view=auto
==============================================================================
Binary file - no diff available.

Propchange: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/resources/NoParentTree.pdf
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/resources/emptyRowTable.pdf
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/resources/emptyRowTable.pdf?rev=1657884&view=auto
==============================================================================
Binary file - no diff available.

Propchange: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/resources/emptyRowTable.pdf
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/resources/helloWorld.pdf
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/resources/helloWorld.pdf?rev=1657884&view=auto
==============================================================================
Binary file - no diff available.

Propchange: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/resources/helloWorld.pdf
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/resources/linkTagged.pdf
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/resources/linkTagged.pdf?rev=1657884&view=auto
==============================================================================
Binary file - no diff available.

Propchange: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/resources/linkTagged.pdf
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/resources/otf.pdf
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/resources/otf.pdf?rev=1657884&view=auto
==============================================================================
Binary file - no diff available.

Propchange: xmlgraphics/fop-pdf-images/branches/Temp_MergeTaggedPDF/test/resources/otf.pdf
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream



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