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 2016/07/27 16:43:48 UTC

svn commit: r1754315 - in /pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane: FontEncodingPaneController.java FontEncodingView.java SimpleFont.java Type0Font.java Type3Font.java

Author: tilman
Date: Wed Jul 27 16:43:48 2016
New Revision: 1754315

URL: http://svn.apache.org/viewvc?rev=1754315&view=rev
Log:
PDFBOX-2941: Show all CID fonts with glyphs; use vertical bounds for all glyphs; copy old SimpleFont pane for type3 fonts

Added:
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/Type3Font.java   (with props)
Modified:
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/FontEncodingPaneController.java
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/FontEncodingView.java
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/SimpleFont.java
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/Type0Font.java

Modified: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/FontEncodingPaneController.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/FontEncodingPaneController.java?rev=1754315&r1=1754314&r2=1754315&view=diff
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/FontEncodingPaneController.java (original)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/FontEncodingPaneController.java Wed Jul 27 16:43:48 2016
@@ -16,19 +16,47 @@
 
 package org.apache.pdfbox.debugger.fontencodingpane;
 
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Rectangle2D;
 import java.io.IOException;
 import javax.swing.JPanel;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSName;
 import org.apache.pdfbox.pdmodel.PDResources;
-import org.apache.pdfbox.pdmodel.font.PDCIDFontType2;
 import org.apache.pdfbox.pdmodel.font.PDFont;
 import org.apache.pdfbox.pdmodel.font.PDSimpleFont;
 import org.apache.pdfbox.pdmodel.font.PDType0Font;
+import org.apache.pdfbox.pdmodel.font.PDType3Font;
 
-interface FontPane
+abstract class FontPane
 {
-    JPanel getPanel();
+    abstract JPanel getPanel();
+
+    /**
+     * Calculate vertical bounds common to all rendered glyphs.
+     *
+     * @param tableData
+     * @param glyphIndex the table index that has glyphs.
+     * @return an array with two elements: min lower bound (but max 0), and max upper bound (but min
+     * 0).
+     */
+    double[] getYBounds(Object[][] tableData, int glyphIndex)
+    {
+        double minY = 0;
+        double maxY = 0;
+        for (int i = 0; i < tableData.length; ++i)
+        {
+            GeneralPath path = (GeneralPath) tableData[i][glyphIndex];
+            Rectangle2D bounds2D = path.getBounds2D();
+            if (bounds2D.isEmpty())
+            {
+                continue;
+            }
+            minY = Math.min(minY, bounds2D.getMinY());
+            maxY = Math.max(maxY, bounds2D.getMaxY());
+        }
+        return new double[]{minY, maxY};
+    }
 }
 
 /**
@@ -52,14 +80,17 @@ public class FontEncodingPaneController
         try
         {
             PDFont font = resources.getFont(fontName);
-            if (font instanceof PDSimpleFont)
+            if (font instanceof PDType3Font)
+            {
+                fontPane = new Type3Font((PDType3Font) font);
+            }
+            else if (font instanceof PDSimpleFont)
             {
                 fontPane = new SimpleFont((PDSimpleFont) font);
             }
-            else if (font instanceof PDType0Font
-                    && ((PDType0Font) font).getDescendantFont() instanceof PDCIDFontType2)
+            else if (font instanceof PDType0Font)
             {
-                fontPane = new Type0Font((PDCIDFontType2) ((PDType0Font) font).getDescendantFont(), font);
+                fontPane = new Type0Font(((PDType0Font) font).getDescendantFont(), (PDType0Font) font);
             }
         }
         catch (IOException e)

Modified: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/FontEncodingView.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/FontEncodingView.java?rev=1754315&r1=1754314&r2=1754315&view=diff
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/FontEncodingView.java (original)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/FontEncodingView.java Wed Jul 27 16:43:48 2016
@@ -25,7 +25,6 @@ import java.awt.GridBagConstraints;
 import java.awt.GridBagLayout;
 import java.awt.Rectangle;
 import java.awt.RenderingHints;
-import java.awt.geom.AffineTransform;
 import java.awt.geom.GeneralPath;
 import java.awt.geom.Rectangle2D;
 import java.awt.image.BufferedImage;
@@ -41,6 +40,7 @@ import javax.swing.table.TableCellRender
 
 /**
  * @author Khyrul Bashar
+ * @author Tilman Hausherr
  * A class that creates the UI for font encoding pane.
  */
 class FontEncodingView
@@ -53,10 +53,11 @@ class FontEncodingView
      * @param headerAttributes Map<String, String> instance which contains info for showing in header
      *                         panel. Here keys will be info type.
      * @param columnNames String array containing the columns name.
+     * @param yBounds min low and max high bound of all glyphs.
      */
-    FontEncodingView(Object[][] tableData, Map<String, String> headerAttributes, String[] columnNames)
+    FontEncodingView(Object[][] tableData, Map<String, String> headerAttributes, String[] columnNames, double[] yBounds)
     {
-        createView(getHeaderPanel(headerAttributes), getTable(tableData, columnNames));
+        createView(getHeaderPanel(headerAttributes), getTable(tableData, columnNames, yBounds));
     }
 
     private void createView(JPanel headerPanel, JTable table)
@@ -86,11 +87,11 @@ class FontEncodingView
         panel.add(scrollPane, gbc);
     }
 
-    private JTable getTable(Object[][] tableData, String[] columnNames)
+    private JTable getTable(Object[][] tableData, String[] columnNames, double[] yBounds)
     {
         JTable table = new JTable(tableData, columnNames);
         table.setRowHeight(40);
-        table.setDefaultRenderer(Object.class, new GlyphCellRenderer());
+        table.setDefaultRenderer(Object.class, new GlyphCellRenderer(yBounds));
         return table;
     }
 
@@ -103,7 +104,6 @@ class FontEncodingView
             Iterator<String> keys = attributes.keySet().iterator();
             int row = 0;
             while (keys.hasNext())
-
             {
                 String key = keys.next();
                 JLabel encodingNameLabel = new JLabel(key + ": " + attributes.get(key));
@@ -116,7 +116,6 @@ class FontEncodingView
                 gbc.anchor = GridBagConstraints.LINE_START;
 
                 headerPanel.add(encodingNameLabel, gbc);
-
             }
         }
         return headerPanel;
@@ -129,6 +128,12 @@ class FontEncodingView
 
     private static final class GlyphCellRenderer implements TableCellRenderer
     {
+        private final double[] yBounds;
+
+        private GlyphCellRenderer(double[] yBounds)
+        {
+            this.yBounds = yBounds;
+        }
 
         @Override
         public Component getTableCellRendererComponent(JTable jTable, Object o, boolean b, boolean b1, int row, int col)
@@ -147,8 +152,6 @@ class FontEncodingView
                 Rectangle cellRect = jTable.getCellRect(row, col, false);
                 BufferedImage bim = renderGlyph(path, bounds2D, cellRect);
                 return new JLabel(new ImageIcon(bim));
-
-                //TODO possible improvement? render all glyphs with the same scale in the same bounding box
             }
             if (o != null)
             {
@@ -166,23 +169,26 @@ class FontEncodingView
 
         private BufferedImage renderGlyph(GeneralPath path, Rectangle2D bounds2D, Rectangle cellRect)
         {
-            path.transform(AffineTransform.getTranslateInstance(-bounds2D.getMinX(), -bounds2D.getMinY()));
-            double scaleX = bounds2D.getWidth() / cellRect.getWidth();
-            double scaleY = bounds2D.getHeight() / cellRect.getHeight();
-            double scale = 1 / Math.ceil(Math.max(scaleX, scaleY)) / 2;
             BufferedImage bim = new BufferedImage((int) cellRect.getWidth(), (int) cellRect.getHeight(), BufferedImage.TYPE_INT_RGB);
             Graphics2D g = (Graphics2D) bim.getGraphics();
             g.setBackground(Color.white);
             g.clearRect(0, 0, bim.getWidth(), bim.getHeight());
 
+            double scale = 1 / ((yBounds[1] - yBounds[0]) / cellRect.getHeight());
+
             // flip
             g.scale(1, -1);
             g.translate(0, -bim.getHeight());
 
-            // center
-            g.translate((cellRect.getWidth() - bounds2D.getWidth() * scale) / 2, cellRect.getHeight() / 4);
+            // horizontal center
+            g.translate((cellRect.getWidth() - bounds2D.getWidth() * scale) / 2, 0);
 
+            // scale from the glyph to the cell
             g.scale(scale, scale);
+
+            // Adjust for negative y min bound
+            g.translate(0, -yBounds[0]);
+
             g.setColor(Color.black);
             g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
             g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);

Modified: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/SimpleFont.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/SimpleFont.java?rev=1754315&r1=1754314&r2=1754315&view=diff
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/SimpleFont.java (original)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/SimpleFont.java Wed Jul 27 16:43:48 2016
@@ -26,7 +26,7 @@ import org.apache.pdfbox.pdmodel.font.PD
  * @author Khyrul Bashar
  * A class that shows the glyph table along with unicode characters for SimpleFont.
  */
-class SimpleFont implements FontPane
+class SimpleFont extends FontPane
 {
     public static final String NO_GLYPH = "No glyph";
     private int totalAvailableGlyph = 0;
@@ -40,13 +40,16 @@ class SimpleFont implements FontPane
     SimpleFont(PDSimpleFont font) throws IOException
     {
         Object[][] tableData = getGlyphs(font);
+        
+        double[] yBounds = getYBounds(tableData, 3);
 
         Map<String, String> attributes = new LinkedHashMap<String, String>();
         attributes.put("Encoding", getEncodingName(font));
         attributes.put("Font", font.getName());
         attributes.put("Glyph count", Integer.toString(totalAvailableGlyph));
 
-        view = new FontEncodingView(tableData, attributes, new String[] {"Code", "Glyph Name","Unicode Character","Glyph"});
+        view = new FontEncodingView(tableData, attributes, 
+                new String[] {"Code", "Glyph Name", "Unicode Character", "Glyph"}, yBounds);
     }
 
     private Object[][] getGlyphs(PDSimpleFont font) throws IOException
@@ -74,7 +77,6 @@ class SimpleFont implements FontPane
         return glyphs;
     }
 
-
     private String getEncodingName(PDSimpleFont font)
     {
         return font.getEncoding().getClass().getSimpleName();

Modified: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/Type0Font.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/Type0Font.java?rev=1754315&r1=1754314&r2=1754315&view=diff
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/Type0Font.java (original)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/Type0Font.java Wed Jul 27 16:43:48 2016
@@ -17,6 +17,7 @@
 package org.apache.pdfbox.debugger.fontencodingpane;
 
 import java.awt.Dimension;
+import java.awt.geom.GeneralPath;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.LinkedHashMap;
@@ -27,25 +28,28 @@ import org.apache.pdfbox.cos.COSDictiona
 import org.apache.pdfbox.cos.COSName;
 import org.apache.pdfbox.cos.COSStream;
 import org.apache.pdfbox.io.IOUtils;
-import org.apache.pdfbox.pdmodel.font.PDCIDFontType2;
+import org.apache.pdfbox.pdmodel.font.PDCIDFont;
 import org.apache.pdfbox.pdmodel.font.PDFont;
+import org.apache.pdfbox.pdmodel.font.PDType0Font;
 
 /**
  * @author Khyrul Bashar
  * A class that shows the CIDToGID table along with unicode characters for Type0Fonts when descendent
  * font is of type PDCIDFontType2.
  */
-class Type0Font implements FontPane
+class Type0Font extends FontPane
 {
-    private FontEncodingView view;
-
+    private final FontEncodingView view;
+    public static final String NO_GLYPH = "No glyph";
+    private int totalAvailableGlyph = 0;
+    
     /**
      * Constructor.
      * @param descendantFont PDCIDFontType2 instance.
      * @param parentFont PDFont instance.
      * @throws IOException If fails to parse cidtogid map.
      */
-    Type0Font(PDCIDFontType2 descendantFont, PDFont parentFont) throws IOException
+    Type0Font(PDCIDFont descendantFont, PDType0Font parentFont) throws IOException
     {
         Object[][] cidtogid = readCIDToGIDMap(descendantFont, parentFont);
         if (cidtogid != null)
@@ -54,11 +58,55 @@ class Type0Font implements FontPane
             attributes.put("Font", descendantFont.getName());
             attributes.put("CID count", Integer.toString(cidtogid.length));
 
-            view = new FontEncodingView(cidtogid, attributes, new String[]{"CID", "GID", "Unicode Character"});
+            view = new FontEncodingView(cidtogid, attributes, 
+                    new String[]{"CID", "GID", "Unicode Character", "Glyph"}, getYBounds(cidtogid, 3));
+        }
+        else
+        {
+            Object[][] tab = readMap(descendantFont, parentFont);
+            Map<String, String> attributes = new LinkedHashMap<String, String>();
+            attributes.put("Font", descendantFont.getName());
+            attributes.put("CID count", Integer.toString(tab.length));
+            attributes.put("Glyph count", Integer.toString(totalAvailableGlyph));
+            
+            view = new FontEncodingView(tab, attributes, 
+                    new String[]{"Code", "CID", "GID", "Unicode Character", "Glyph"}, getYBounds(tab, 4));
+        }
+    }
+
+    private Object[][] readMap(PDCIDFont descendantFont, PDType0Font parentFont) throws IOException
+    {
+        int codes = 0;
+        for (int code = 0; code < 65535; ++code)
+        {
+            if (descendantFont.hasGlyph(code))
+            {
+                ++codes;
+            }
         }
+        Object[][] tab = new Object[codes][5];
+        int index = 0;
+        for (int code = 0; code < 65535; ++code)
+        {
+            if (descendantFont.hasGlyph(code))
+            {
+                tab[index][0] = code;
+                tab[index][1] = descendantFont.codeToCID(code);
+                tab[index][2] = descendantFont.codeToGID(code);
+                tab[index][3] = parentFont.toUnicode(code);
+                GeneralPath path = descendantFont.getPath(code);
+                tab[index][4] = path;
+                if (!path.getBounds2D().isEmpty())
+                {
+                    ++totalAvailableGlyph;
+                }
+                ++index;
+            }
+        }
+        return tab;
     }
 
-    private Object[][] readCIDToGIDMap(PDCIDFontType2 font, PDFont parentFont) throws IOException
+    private Object[][] readCIDToGIDMap(PDCIDFont font, PDFont parentFont) throws IOException
     {
         Object[][] cid2gid = null;
         COSDictionary dict = font.getCOSObject();
@@ -71,7 +119,7 @@ class Type0Font implements FontPane
             byte[] mapAsBytes = IOUtils.toByteArray(is);
             IOUtils.closeQuietly(is);
             int numberOfInts = mapAsBytes.length / 2;
-            cid2gid = new Object[numberOfInts][3];
+            cid2gid = new Object[numberOfInts][4];
             int offset = 0;
             for (int index = 0; index < numberOfInts; index++)
             {
@@ -82,14 +130,18 @@ class Type0Font implements FontPane
                 {
                     cid2gid[index][2] = parentFont.toUnicode(index);
                 }
+                GeneralPath path = font.getPath(index);
+                cid2gid[index][3] = path;
+                if (!path.getBounds2D().isEmpty())
+                {
+                    ++totalAvailableGlyph;
+                }
                 offset += 2;
             }
         }
         return cid2gid;
     }
 
-
-
     @Override
     public JPanel getPanel()
     {

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/Type3Font.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/Type3Font.java?rev=1754315&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/Type3Font.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/Type3Font.java Wed Jul 27 16:43:48 2016
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2015 The Apache Software Foundation.
+ *
+ * Licensed 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.pdfbox.debugger.fontencodingpane;
+
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import javax.swing.JPanel;
+import org.apache.pdfbox.pdmodel.common.PDRectangle;
+import org.apache.pdfbox.pdmodel.font.PDSimpleFont;
+import org.apache.pdfbox.pdmodel.font.PDType3CharProc;
+import org.apache.pdfbox.pdmodel.font.PDType3Font;
+
+/**
+ * @author Khyrul Bashar
+ * A class that shows the glyph table along with unicode characters for SimpleFont.
+ */
+class Type3Font extends FontPane
+{
+    public static final String NO_GLYPH = "No glyph";
+    private int totalAvailableGlyph = 0;
+    private final FontEncodingView view;
+
+    /**
+     * Constructor.
+     * @param font PDSimpleFont instance.
+     * @throws IOException If fails to parse unicode characters.
+     */
+    Type3Font(PDType3Font font) throws IOException
+    {
+        Object[][] tableData = getGlyphs(font);
+
+        Map<String, String> attributes = new LinkedHashMap<String, String>();
+        attributes.put("Encoding", getEncodingName(font));
+        attributes.put("Font", font.getName());
+        attributes.put("Glyph count", Integer.toString(totalAvailableGlyph));
+
+        view = new FontEncodingView(tableData, attributes, new String[] {"Code", "Glyph Name", "Unicode Character"}, null);
+    }
+
+    private Object[][] getGlyphs(PDType3Font font) throws IOException
+    {
+        Object[][] glyphs = new Object[256][3];
+
+        for (int index = 0; index <= 255; index++)
+        {
+            glyphs[index][0] = index;
+            if (font.getEncoding().contains(index))
+            {
+                glyphs[index][1] = font.getEncoding().getName(index);
+                glyphs[index][2] = font.toUnicode(index);
+                totalAvailableGlyph++;
+            }
+            else
+            {
+                glyphs[index][1] = NO_GLYPH;
+                glyphs[index][2] = NO_GLYPH;
+            }
+        }
+        return glyphs;
+    }
+
+    private String getEncodingName(PDSimpleFont font)
+    {
+        return font.getEncoding().getClass().getSimpleName();
+    }
+
+    @Override
+    public JPanel getPanel()
+    {
+        return view.getPanel();
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/Type3Font.java
------------------------------------------------------------------------------
    svn:eol-style = native