You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ti...@apache.org on 2015/07/23 20:53:22 UTC

svn commit: r1692428 - in /pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools: PDFDebugger.java pdfdebugger/streampane/OperatorMarker.java pdfdebugger/streampane/StreamPane.java

Author: tilman
Date: Thu Jul 23 18:53:21 2015
New Revision: 1692428

URL: http://svn.apache.org/r1692428
Log:
PDFBOX-2530: color for certain operators in content streams (page content streams, but also appearance streams, form, pattern and type3 font streams), as done by Khyrul Bashar in GSoC2015
PDFBOX-2900: restore missing inline image content, as done by Khyrul Bashar in GSoC2015

Added:
    pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/OperatorMarker.java   (with props)
Modified:
    pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/PDFDebugger.java
    pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamPane.java

Modified: pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/PDFDebugger.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/PDFDebugger.java?rev=1692428&r1=1692427&r2=1692428&view=diff
==============================================================================
--- pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/PDFDebugger.java (original)
+++ pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/PDFDebugger.java Thu Jul 23 18:53:21 2015
@@ -499,7 +499,7 @@ public class PDFDebugger extends javax.s
                 }
                 if (isStream(selectedNode))
                 {
-                    showStream(selectedNode, path);
+                    showStream((COSStream)getUnderneathObject(selectedNode), path);
                     return;
                 }
                 if (!jSplitPane1.getRightComponent().equals(jScrollPane2))
@@ -583,28 +583,42 @@ public class PDFDebugger extends javax.s
     private boolean isFontDescriptor(Object obj)
     {
         Object underneathObject = getUnderneathObject(obj);
-        if (underneathObject instanceof COSDictionary)
-        {
-            return ((COSDictionary) underneathObject).containsKey(COSName.TYPE)
-                && ((COSDictionary) underneathObject).getCOSName(COSName.TYPE).equals(COSName.FONT_DESC);
-        }
-        return false;
+        return underneathObject instanceof COSDictionary &&
+                ((COSDictionary) underneathObject).containsKey(COSName.TYPE) &&
+                ((COSDictionary) underneathObject).getCOSName(COSName.TYPE).equals(COSName.FONT_DESC);
     }
 
     private boolean isAnnot(Object obj)
     {
         Object underneathObject = getUnderneathObject(obj);
-        if (underneathObject instanceof COSDictionary)
+        return underneathObject instanceof COSDictionary &&
+                ((COSDictionary) underneathObject).containsKey(COSName.TYPE) &&
+                ((COSDictionary) underneathObject).getCOSName(COSName.TYPE).equals(COSName.ANNOT);
+    }
+
+    private boolean isStream(Object selectedNode)
+    {
+        return getUnderneathObject(selectedNode) instanceof COSStream;
+    }
+
+    private boolean isFont(Object selectedNode)
+    {
+        selectedNode = getUnderneathObject(selectedNode);
+        if (selectedNode instanceof COSDictionary)
         {
-            return ((COSDictionary) underneathObject).containsKey(COSName.TYPE)
-                && ((COSDictionary) underneathObject).getCOSName(COSName.TYPE).equals(COSName.ANNOT);
+            COSDictionary dic = (COSDictionary)selectedNode;
+            return  dic.containsKey(COSName.TYPE) &&
+                    dic.getCOSName(COSName.TYPE).equals(COSName.FONT) &&
+                    !isCIDFont(dic);
         }
         return false;
     }
 
-    private boolean isStream(Object selectedNode)
+    private boolean isCIDFont(COSDictionary dic)
     {
-        return getUnderneathObject(selectedNode) instanceof COSStream;
+        return dic.containsKey(COSName.SUBTYPE) &&
+                (dic.getCOSName(COSName.SUBTYPE).equals(COSName.CID_FONT_TYPE0)
+                || dic.getCOSName(COSName.SUBTYPE).equals(COSName.CID_FONT_TYPE2));
     }
 
     /**
@@ -676,24 +690,43 @@ public class PDFDebugger extends javax.s
         }
     }
 
-    private void showStream(Object selectedNode, TreePath path)
+    private void showStream(COSStream stream, TreePath path)
     {
-        COSName key = getNodeKey(selectedNode);
-        selectedNode = getUnderneathObject(selectedNode);
+        boolean isContentStream = false;
+
+        COSName key = getNodeKey(path.getLastPathComponent());
+        COSName parentKey = getNodeKey(path.getParentPath().getLastPathComponent());
         COSDictionary resourcesDic = null;
-        if (selectedNode instanceof COSStream && COSName.CONTENTS.equals(key))
+
+        if (COSName.CONTENTS.equals(key))
         {
             Object pageObj = path.getParentPath().getLastPathComponent();
             COSDictionary page = (COSDictionary) getUnderneathObject(pageObj);
             resourcesDic = (COSDictionary) page.getDictionaryObject(COSName.RESOURCES);
+            isContentStream = true;
+        }
+        else if (COSName.CONTENTS.equals(parentKey) || COSName.CHAR_PROCS.equals(parentKey))
+        {
+            Object pageObj = path.getParentPath().getParentPath().getLastPathComponent();
+            COSDictionary page = (COSDictionary) getUnderneathObject(pageObj);
+            resourcesDic = (COSDictionary) page.getDictionaryObject(COSName.RESOURCES);
+            isContentStream = true;
+        }
+        else if (COSName.FORM.equals(stream.getCOSName(COSName.SUBTYPE)) ||
+                COSName.PATTERN.equals(stream.getCOSName(COSName.TYPE)))
+        {
+            if (stream.containsKey(COSName.RESOURCES))
+            {
+                resourcesDic = (COSDictionary) stream.getDictionaryObject(COSName.RESOURCES);
+            }
+            isContentStream = true;
         }
-        else if (selectedNode instanceof COSStream &&
-                COSName.IMAGE.equals(((COSStream) selectedNode).getCOSName(COSName.SUBTYPE)))
+        else if (COSName.IMAGE.equals((stream).getCOSName(COSName.SUBTYPE)))
         {
             Object resourcesObj = path.getParentPath().getParentPath().getLastPathComponent();
             resourcesDic = (COSDictionary) getUnderneathObject(resourcesObj);
         }
-        StreamPane streamPane = new StreamPane((COSStream)selectedNode, key, resourcesDic);
+        StreamPane streamPane = new StreamPane(stream, isContentStream, resourcesDic);
         jSplitPane1.setRightComponent(streamPane.getPanel());
     }
 

Added: pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/OperatorMarker.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/OperatorMarker.java?rev=1692428&view=auto
==============================================================================
--- pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/OperatorMarker.java (added)
+++ pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/OperatorMarker.java Thu Jul 23 18:53:21 2015
@@ -0,0 +1,73 @@
+package org.apache.pdfbox.tools.pdfdebugger.streampane;
+
+import java.awt.Color;
+import java.util.HashMap;
+import java.util.Map;
+import javax.swing.text.Style;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.StyleContext;
+
+/**
+ * @author Khyrul Bashar
+ */
+final class OperatorMarker
+{
+    private Map<String, Style> operatorStyleMap;
+
+    OperatorMarker()
+    {
+        operatorStyleMap = new HashMap<String, Style>();
+        initOperatorStyles();
+    }
+
+    private void initOperatorStyles()
+    {
+        StyleContext styleContext = StyleContext.getDefaultStyleContext();
+
+        Style common = styleContext.addStyle("common", null);
+        StyleConstants.setBold(common, true);
+
+        Style textObjectStyle = styleContext.addStyle("text_object", common);
+        StyleConstants.setForeground(textObjectStyle, new Color(0, 100, 0));
+
+        Style graphicsStyle = styleContext.addStyle("graphics", common);
+        StyleConstants.setForeground(graphicsStyle, new Color(255, 68, 68));
+
+        Style concatStyle = styleContext.addStyle("cm", common);
+        StyleConstants.setForeground(concatStyle, new Color(1, 169, 219));
+
+        Style inlineImage = styleContext.addStyle("inline_image", common);
+        StyleConstants.setForeground(inlineImage, new Color(71, 117, 163));
+
+        Style imageData = styleContext.addStyle("ID", common);
+        StyleConstants.setForeground(imageData, new Color(255, 165, 0));
+
+        final String BEGIN_TEXT_OBJECT = "BT";
+        final String END_TEXT_OBJECT = "ET";
+        final String SAVE_GRAPHICS_STATE = "q";
+        final String RESTORE_GRAPHICS_STATE = "Q";
+        final String CONCAT = "cm";
+        final String INLINE_IMAGE_BEGIN = "BI";
+        final String IMAGE_DATA = "ID";
+        final String INLINE_IMAGE_END = "EI";
+
+
+        operatorStyleMap.put(BEGIN_TEXT_OBJECT, textObjectStyle);
+        operatorStyleMap.put(END_TEXT_OBJECT, textObjectStyle);
+        operatorStyleMap.put(SAVE_GRAPHICS_STATE, graphicsStyle);
+        operatorStyleMap.put(RESTORE_GRAPHICS_STATE, graphicsStyle);
+        operatorStyleMap.put(CONCAT, concatStyle);
+        operatorStyleMap.put(INLINE_IMAGE_BEGIN, inlineImage);
+        operatorStyleMap.put(IMAGE_DATA, imageData);
+        operatorStyleMap.put(INLINE_IMAGE_END, inlineImage);
+    }
+
+    Style getStyle(String operator)
+    {
+        if (operatorStyleMap.containsKey(operator))
+        {
+            return operatorStyleMap.get(operator);
+        }
+        return null;
+    }
+}

Propchange: pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/OperatorMarker.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamPane.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamPane.java?rev=1692428&r1=1692427&r2=1692428&view=diff
==============================================================================
--- pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamPane.java (original)
+++ pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamPane.java Thu Jul 23 18:53:21 2015
@@ -33,6 +33,7 @@ import javax.swing.text.StyledDocument;
 import org.apache.pdfbox.contentstream.operator.Operator;
 import org.apache.pdfbox.cos.COSArray;
 import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSBoolean;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSName;
 import org.apache.pdfbox.cos.COSStream;
@@ -44,6 +45,7 @@ import org.apache.pdfbox.tools.pdfdebugg
 
 /**
  * @author Khyrul Bashar
+ * 
  * A class that shows the COSStream.
  */
 public class StreamPane implements ActionListener
@@ -56,13 +58,14 @@ public class StreamPane implements Actio
 
     /**
      * Constructor.
-     * @param cosStream COSStream instance.
-     * @param streamKey COSName instance. This is the type .
-     * @param resourcesDic COSDictionary instance that holds the resource dictionary for the stream.
+     *
+     * @param cosStream       COSStream instance.
+     * @param isContentStream boolean instance. This says if a stream is content stream or not.
+     * @param resourcesDic    COSDictionary instance that holds the resource dictionary for the stream.
      */
-    public StreamPane(COSStream cosStream, COSName streamKey, COSDictionary resourcesDic)
+    public StreamPane(COSStream cosStream, boolean isContentStream, COSDictionary resourcesDic)
     {
-        isContentStream = COSName.CONTENTS.equals(streamKey);
+        this.isContentStream = isContentStream;
 
         this.stream = new Stream(cosStream);
         if (resourcesDic != null)
@@ -125,6 +128,8 @@ public class StreamPane implements Actio
     {
 
         private final String filterKey;
+        private StyledDocument docu;
+        OperatorMarker marker;
 
         private DocumentCreator(String filterKey)
         {
@@ -195,21 +200,22 @@ public class StreamPane implements Actio
         private StyledDocument getDocument(InputStream inputStream)
         {
             String data = getStringOfStream(inputStream);
-            StyledDocument document = new DefaultStyledDocument();
+            docu = new DefaultStyledDocument();
             try
             {
-                document.insertString(0, data, null);
+                docu.insertString(0, data, null);
             }
             catch (BadLocationException e)
             {
                 e.printStackTrace();
             }
-            return document;
+            return docu;
         }
 
         private StyledDocument getContentStreamDocument(InputStream inputStream)
         {
-            StyledDocument docu = new DefaultStyledDocument();
+            docu = new DefaultStyledDocument();
+            marker = new OperatorMarker();
 
             PDFStreamParser parser;
             try
@@ -222,61 +228,90 @@ public class StreamPane implements Actio
                 return null;
             }
 
+            for (Object obj : parser.getTokens())
+            {
+                writeObject(obj);
+            }
+            return docu;
+        }
+
+        private void writeObject(Object obj)
+        {
             try
             {
-                for (Object obj : parser.getTokens())
+                if (obj instanceof Operator)
                 {
-                    if (obj instanceof Operator)
+                    Operator op = (Operator) obj;
+                    if (op.getName().equals("BI"))
                     {
-                        docu.insertString(docu.getLength(), ((Operator) obj).getName() + "\n", null);
+                        docu.insertString(docu.getLength(), "BI" + "\n", marker.getStyle("BI"));
+                        COSDictionary dic = op.getImageParameters();
+                        for (COSName key : dic.keySet())
+                        {
+                            Object value = dic.getDictionaryObject(key);
+                            docu.insertString(docu.getLength(), "/" + key.getName() + " ", null);
+                            writeObject(value);
+                            docu.insertString(docu.getLength(), "\n", null);
+                        }
+                        docu.insertString(docu.getLength(), "ID\n", marker.getStyle("ID"));
+                        docu.insertString(docu.getLength(), new String(op.getImageData()), null);
+                        docu.insertString(docu.getLength(), "\n", null);
+                        docu.insertString(docu.getLength(), "EI\n", marker.getStyle("EI"));
                     }
                     else
                     {
-                        String str;
-                        if (obj instanceof COSName)
-                        {
-                            str = "/" + ((COSName) obj).getName();
-                        }
-                        else if (obj instanceof COSArray)
+                        String operator = ((Operator) obj).getName();
+                        docu.insertString(docu.getLength(), operator + "\n", marker.getStyle(operator));
+                    }
+                }
+                else
+                {
+                    String str;
+                    if (obj instanceof COSName)
+                    {
+                        str = "/" + ((COSName) obj).getName();
+                    }
+                    else if (obj instanceof COSBoolean)
+                    {
+                        str = obj.toString();
+                    }
+                    else if (obj instanceof COSArray)
+                    {
+                        StringBuilder builder = new StringBuilder("[ ");
+                        for (COSBase base : (COSArray) obj)
                         {
-                            StringBuilder builder = new StringBuilder("[ ");
-                            for (COSBase base : (COSArray) obj)
-                            {
-                                builder.append(getCOSVlaue(base));
-                                builder.append(", ");
-                            }
-                            if (((COSArray) obj).size() > 0)
-                            {
-                                builder.delete(builder.lastIndexOf(","), builder.length());
-                            }
-                            builder.append("]");
-                            str = builder.toString();
+                            builder.append(getCOSValue(base));
+                            builder.append(", ");
                         }
-                        else
+                        if (((COSArray) obj).size() > 0)
                         {
-                            str = getCOSVlaue(obj);
+                            builder.delete(builder.lastIndexOf(","), builder.length());
                         }
-                        docu.insertString(docu.getLength(), str+" ", null);
+                        builder.append("]");
+                        str = builder.toString();
                     }
+                    else
+                    {
+                        str = getCOSValue(obj);
+                    }
+                    docu.insertString(docu.getLength(), str + " ", null);
                 }
             }
-            catch (BadLocationException e1)
+            catch (BadLocationException e)
             {
-                e1.printStackTrace();
+                e.printStackTrace();
             }
-            return docu;
         }
 
-        private String getCOSVlaue(Object obj)
+        private String getCOSValue(Object obj)
         {
             String str = obj.toString();
             str = str.substring(str.indexOf('{')+1, str.length()-1);
             if (obj instanceof COSString)
             {
-                str = "("+str+")";
+                str = "(" + str + ")";
             }
             return str;
         }
-
     }
 }