You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ja...@apache.org on 2014/09/04 03:52:27 UTC

svn commit: r1622392 - in /pdfbox/trunk: fontbox/src/main/java/org/apache/fontbox/ttf/ pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/ pdfbox/src/main/java/org/apache/pdfbox/rendering/font/

Author: jahewson
Date: Thu Sep  4 01:52:27 2014
New Revision: 1622392

URL: http://svn.apache.org/r1622392
Log:
PDFBOX-2307: More robust Type 1 name mapping for external fonts

Modified:
    pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/TrueTypeFont.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Equivalent.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/font/Type1Glyph2D.java

Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/TrueTypeFont.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/TrueTypeFont.java?rev=1622392&r1=1622391&r2=1622392&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/TrueTypeFont.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/TrueTypeFont.java Thu Sep  4 01:52:27 2014
@@ -450,13 +450,19 @@ public class TrueTypeFont implements Typ
         readPostScriptNames();
 
         Integer gid = postScriptNames.get(name);
-        int width = getAdvanceWidth(gid);
-        int unitsPerEM = getUnitsPerEm();
-        if (unitsPerEM != 1000)
+
+        if (gid != null)
         {
-            width *= 1000f / unitsPerEM;
+            int width = getAdvanceWidth(gid);
+            int unitsPerEM = getUnitsPerEm();
+            if (unitsPerEM != 1000)
+            {
+                width *= 1000f / unitsPerEM;
+            }
+            return width;
         }
-        return width;
+
+        throw new IOException(name + " is not in the 'post' table");
     }
 
     @Override

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java?rev=1622392&r1=1622391&r2=1622392&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java Thu Sep  4 01:52:27 2014
@@ -138,12 +138,6 @@ public class PDType1CFont extends PDSimp
     }
 
     @Override
-    public boolean hasGlyph(String name) throws IOException
-    {
-        return type1Equivalent.hasGlyph(name);
-    }
-
-    @Override
     public String codeToName(int code)
     {
         return getEncoding().getName(code);

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Equivalent.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Equivalent.java?rev=1622392&r1=1622391&r2=1622392&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Equivalent.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Equivalent.java Thu Sep  4 01:52:27 2014
@@ -33,17 +33,12 @@ public interface PDType1Equivalent
     public String getName();
 
     /**
-     * Returns true if the font contains a glyph with the given name.
-     */
-    public boolean hasGlyph(String name) throws IOException;
-
-    /**
      * Returns the glyph name for the given character code.
      *
      * @param code character code
      * @return PostScript glyph name
      */
-    public String codeToName(int code);
+    public String codeToName(int code) throws IOException;
 
     /**
      * Returns the glyph path for the given character code.

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java?rev=1622392&r1=1622391&r2=1622392&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java Thu Sep  4 01:52:27 2014
@@ -34,6 +34,7 @@ import org.apache.pdfbox.cos.COSDictiona
 import org.apache.pdfbox.cos.COSName;
 import org.apache.pdfbox.cos.COSStream;
 import org.apache.pdfbox.encoding.Encoding;
+import org.apache.pdfbox.encoding.GlyphList;
 import org.apache.pdfbox.encoding.StandardEncoding;
 import org.apache.pdfbox.encoding.Type1Encoding;
 import org.apache.pdfbox.encoding.WinAnsiEncoding;
@@ -100,6 +101,33 @@ public class PDType1Font extends PDSimpl
         }
     }
 
+    // alternative names for glyphs which are commonly encountered
+    private static final Map<String, String> ALT_NAMES = new HashMap<String, String>();
+    static
+    {
+        ALT_NAMES.put("ff", "f_f");
+        ALT_NAMES.put("ffi", "f_f_i");
+        ALT_NAMES.put("ffl", "f_f_l");
+        ALT_NAMES.put("fi", "f_i");
+        ALT_NAMES.put("fl", "f_l");
+        ALT_NAMES.put("st", "s_t");
+        ALT_NAMES.put("IJ", "I_J");
+        ALT_NAMES.put("ij", "i_j");
+        ALT_NAMES.put("ellipsis", "elipsis"); // misspelled in ArialMT
+    }
+
+    // unicode names for ligatures, needed to undo mapping in org.apache.pdfbox.Encoding
+    private static final Map<String, String> LIGATURE_UNI_NAMES = new HashMap<String, String>();
+    static
+    {
+        LIGATURE_UNI_NAMES.put("ff", "uniFB00");
+        LIGATURE_UNI_NAMES.put("fi", "uniFB01");
+        LIGATURE_UNI_NAMES.put("fl", "uniFB02");
+        LIGATURE_UNI_NAMES.put("ffi", "uniFB03");
+        LIGATURE_UNI_NAMES.put("ffl", "uniFB04");
+        LIGATURE_UNI_NAMES.put("pi", "uni03C0");
+    }
+
     // todo: replace with enum? or getters?
     public static final PDType1Font TIMES_ROMAN = new PDType1Font("Times-Roman");
     public static final PDType1Font TIMES_BOLD = new PDType1Font("Times-Bold");
@@ -273,7 +301,7 @@ public class PDType1Font extends PDSimpl
     @Override
     public float getHeight(int code) throws IOException
     {
-        String name = getEncoding().getName(code);
+        String name = codeToName(code);
         if (afm != null)
         {
             return afm.getCharacterHeight(name); // todo: isn't this the y-advance, not the height?
@@ -377,23 +405,46 @@ public class PDType1Font extends PDSimpl
     }
 
     @Override
-    public boolean hasGlyph(String name) throws IOException
-    {
-        return type1Equivalent.hasGlyph(name);
-    }
-
-    @Override
-    public String codeToName(int code)
+    public String codeToName(int code) throws IOException
     {
         String name = getEncoding().getName(code);
-        if (name != null)
+        if (isEmbedded() || type1Equivalent.hasGlyph(name))
         {
             return name;
         }
         else
         {
-            return ".notdef";
+            // try alternative name
+            String altName = ALT_NAMES.get(name);
+            if (altName != null && !name.equals(".notdef") && type1Equivalent.hasGlyph(altName))
+            {
+                return altName;
+            }
+            else
+            {
+                // try unicode name
+                String unicodes = GlyphList.toUnicode(name);
+                if (unicodes != null)
+                {
+                    if (unicodes.length() == 1)
+                    {
+                        String uniName = String.format("uni%04X", unicodes.codePointAt(0));
+                        if (type1Equivalent.hasGlyph(uniName))
+                        {
+                            return uniName;
+                        }
+                    }
+                    else if (unicodes.length() > 1)
+                    {
+                        if (LIGATURE_UNI_NAMES.containsKey(name))
+                        {
+                           return LIGATURE_UNI_NAMES.get(name);
+                        }
+                    }
+                }
+            }
         }
+        return ".notdef";
     }
 
     @Override

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/font/Type1Glyph2D.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/font/Type1Glyph2D.java?rev=1622392&r1=1622391&r2=1622392&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/font/Type1Glyph2D.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/font/Type1Glyph2D.java Thu Sep  4 01:52:27 2014
@@ -19,12 +19,9 @@ package org.apache.pdfbox.rendering.font
 import java.awt.geom.GeneralPath;
 import java.io.IOException;
 import java.util.HashMap;
-import java.util.Map;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.pdfbox.encoding.Encoding;
-import org.apache.pdfbox.encoding.GlyphList;
 import org.apache.pdfbox.pdmodel.font.PDType1Equivalent;
 
 /**
@@ -34,32 +31,6 @@ public class Type1Glyph2D implements Gly
 {
     private static final Log LOG = LogFactory.getLog(Type1Glyph2D.class);
 
-    // alternative names for glyphs which are commonly encountered
-    private static final Map<String, String> ALT_NAMES = new HashMap<String, String>();
-    static
-    {
-        ALT_NAMES.put("ff", "f_f");
-        ALT_NAMES.put("ffi", "f_f_i");
-        ALT_NAMES.put("ffl", "f_f_l");
-        ALT_NAMES.put("fi", "f_i");
-        ALT_NAMES.put("fl", "f_l");
-        ALT_NAMES.put("st", "s_t");
-        ALT_NAMES.put("IJ", "I_J");
-        ALT_NAMES.put("ij", "i_j");
-    }
-
-    // unicode names for ligatures, needed to undo mapping in org.apache.pdfbox.Encoding
-    private static final Map<String, String> LIGATURE_UNI_NAMES = new HashMap<String, String>();
-    static
-    {
-        LIGATURE_UNI_NAMES.put("ff", "uniFB00");
-        LIGATURE_UNI_NAMES.put("fi", "uniFB01");
-        LIGATURE_UNI_NAMES.put("fl", "uniFB02");
-        LIGATURE_UNI_NAMES.put("ffi", "uniFB03");
-        LIGATURE_UNI_NAMES.put("ffl", "uniFB04");
-        LIGATURE_UNI_NAMES.put("pi", "uni03C0");
-    }
-
     private final HashMap<Integer, GeneralPath> cache = new HashMap<Integer, GeneralPath>();
     private final PDType1Equivalent font;
 
@@ -86,44 +57,15 @@ public class Type1Glyph2D implements Gly
         try
         {
             String name = font.codeToName(code);
-            GeneralPath path = null;
-            if (!name.equals(".notdef") && font.hasGlyph(name))
-            {
-                path = font.getPath(name);
-            }
-            else
+            if (name.equals(".notdef"))
             {
-                // try alternative name
-                String altName = ALT_NAMES.get(name);
-                if (altName != null && !name.equals(".notdef") && font.hasGlyph(altName))
-                {
-                    path = font.getPath(altName);
-                }
-                else
-                {
-                    // try unicode name
-                    String unicodes = GlyphList.toUnicode(name);
-                    if (unicodes != null)
-                    {
-                        if (unicodes.length() == 1)
-                        {
-                            String uniName = String.format("uni%04X", unicodes.codePointAt(0));
-                            path = font.getPath(uniName);
-                        }
-                        else if (unicodes.length() > 1)
-                        {
-                            if (LIGATURE_UNI_NAMES.containsKey(name))
-                            {
-                                path = font.getPath(LIGATURE_UNI_NAMES.get(name));
-                            }
-                        }
-                    }
-                }
+                LOG.warn("No glyph for " + code + " (" + name + ") in font " + font.getName());
             }
 
+            // todo: can this happen? should it be encapsulated?
+            GeneralPath path = font.getPath(name);
             if (path == null)
             {
-                LOG.warn("No glyph for " + code + " (" + name + ") in font " + font.getName());
                 path = font.getPath(".notdef");
             }