You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2014/05/05 19:46:50 UTC

svn commit: r1592586 - in /pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font: PDType1CFont.java PDType1Font.java

Author: lehmi
Date: Mon May  5 17:46:50 2014
New Revision: 1592586

URL: http://svn.apache.org/r1592586
Log:
PDFBOX-2058: fall back to PDFont.encode if the type1c doesn't provide a suitable mapping, readded some font magic needed for rendering

Modified:
    pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java
    pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java

Modified: pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java?rev=1592586&r1=1592585&r2=1592586&view=diff
==============================================================================
--- pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java (original)
+++ pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java Mon May  5 17:46:50 2014
@@ -23,12 +23,16 @@ import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.reflect.Field;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -38,11 +42,17 @@ import org.apache.fontbox.cff.AFMFormatt
 import org.apache.fontbox.cff.CFFFont;
 import org.apache.fontbox.cff.CFFParser;
 import org.apache.fontbox.cff.Type1FontFormatter;
+import org.apache.fontbox.cff.charset.CFFCharset;
+import org.apache.fontbox.cff.encoding.CFFEncoding;
 import org.apache.fontbox.util.BoundingBox;
 import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSBase;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSFloat;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSNumber;
 import org.apache.pdfbox.encoding.Encoding;
+import org.apache.pdfbox.encoding.EncodingManager;
 import org.apache.pdfbox.exceptions.WrappedIOException;
 import org.apache.pdfbox.pdmodel.common.PDMatrix;
 import org.apache.pdfbox.pdmodel.common.PDRectangle;
@@ -326,30 +336,102 @@ public class PDType1CFont extends PDSimp
             {
                 if (baseFontName.equals(font.getName())) 
                 {
-                    this.cffFont = font;
+                    cffFont = font;
                     break;
                 }
             }
         }
-        if (this.cffFont == null) 
+        if (cffFont == null) 
         {
-            this.cffFont = (CFFFont)fonts.get(0);
+            cffFont = (CFFFont)fonts.get(0);
         }
 
         // cache the font name
         fontname = cffFont.getName();
 
-        Number defaultWidthX = (Number) this.cffFont.getProperty("defaultWidthX");
+        Number defaultWidthX = (Number) cffFont.getProperty("defaultWidthX");
         this.glyphWidths.put(null, Float.valueOf(defaultWidthX.floatValue()));
 
-        Encoding encoding = getFontEncoding();
-        Map<String, Integer> nameToCode = encoding != null ? encoding.getNameToCodeMap() : null;
+        CFFEncoding encoding = cffFont.getEncoding();
+        PDFEncoding pdfEncoding = new PDFEncoding(encoding);
+
+        CFFCharset charset = cffFont.getCharset();
+        PDFCharset pdfCharset = new PDFCharset(charset);
+
+        Map<String,byte[]> charStringsDict = cffFont.getCharStringsDict();
+        Map<String,byte[]> pdfCharStringsDict = new LinkedHashMap<String,byte[]>();
+        pdfCharStringsDict.put(".notdef", charStringsDict.get(".notdef"));
+
+        Map<Integer,String> codeToNameMap = new LinkedHashMap<Integer,String>();
+
         Collection<CFFFont.Mapping> mappings = cffFont.getMappings();
-        Map<Integer, String> codeToNameMap = new LinkedHashMap<Integer, String>();
-        for (CFFFont.Mapping mapping : mappings)
+        for( Iterator<CFFFont.Mapping> it = mappings.iterator(); it.hasNext();)
+        {
+            CFFFont.Mapping mapping = it.next();
+            Integer code = Integer.valueOf(mapping.getCode());
+            String name = mapping.getName();
+            codeToNameMap.put(code, name);
+        }
+
+        Set<String> knownNames = new HashSet<String>(codeToNameMap.values());
+
+        Map<Integer,String> codeToNameOverride = loadOverride();
+        for( Iterator<Map.Entry<Integer, String>> it = (codeToNameOverride.entrySet()).iterator(); it.hasNext();)
         {
-            codeToNameMap.put(mapping.getCode(), mapping.getName());
+            Map.Entry<Integer, String> entry = it.next();
+            Integer code = (Integer)entry.getKey();
+            String name = (String)entry.getValue();
+            if(knownNames.contains(name))
+            {
+                codeToNameMap.put(code, name);
+            }
+        }
+
+        Map<String,String> nameToCharacter;
+        try
+        {
+            // TODO remove access by reflection
+            Field nameToCharacterField = Encoding.class.getDeclaredField("NAME_TO_CHARACTER");
+            nameToCharacterField.setAccessible(true);
+            nameToCharacter = (Map<String,String>)nameToCharacterField.get(null);
+        }
+        catch( Exception e )
+        {
+            throw new RuntimeException(e);
+        }
+
+        for( Iterator<Map.Entry<Integer,String>> it = (codeToNameMap.entrySet()).iterator(); it.hasNext();)
+        {
+            Map.Entry<Integer,String> entry = it.next();
+            Integer code = (Integer)entry.getKey();
+            String name = (String)entry.getValue();
+            String uniName = "uni";
+            String character = (String)nameToCharacter.get(name);
+            if( character != null )
+            {
+                for( int j = 0; j < character.length(); j++ )
+                {
+                    uniName += hexString(character.charAt(j), 4);
+                }
+            }
+            else
+            {
+                uniName += hexString(code.intValue(), 4);
+                character = String.valueOf((char)code.intValue());
+            }
+            pdfEncoding.register(code.intValue(), code.intValue());
+            pdfCharset.register(code.intValue(), uniName);
+            pdfCharStringsDict.put(uniName, charStringsDict.get(name));
         }
+
+        cffFont.setEncoding(pdfEncoding);
+        cffFont.setCharset(pdfCharset);
+        charStringsDict.clear();
+        charStringsDict.putAll(pdfCharStringsDict);
+
+        
+        Encoding fontEncoding = getFontEncoding();
+        Map<String, Integer> nameToCode = fontEncoding != null ? fontEncoding.getNameToCodeMap() : null;
         for (CFFFont.Mapping mapping : mappings)
         {
             int sid = mapping.getSID();
@@ -358,21 +440,19 @@ public class PDType1CFont extends PDSimp
             if (nameToCode != null && nameToCode.containsKey(name))
             {
                 sid = nameToCode.get(name);
-                character = encoding.getCharacter(name);
+                character = fontEncoding.getCharacter(name);
             }
             if (character == null)
             {
                 character = Encoding.getCharacterForName(name);
             }
-            if (character == null)
-            {
-                name = "uni" + hexString(sid, 4);
-                character = String.valueOf(Character.toChars(sid));
-            }
             sidToName.put(sid, name);
-            sidToCharacter.put(sid, character);
-            characterToSID.put(character, sid);
             codeToSID.put(mapping.getCode(), sid);
+            if (character != null)
+            {
+                sidToCharacter.put(sid, character);
+                characterToSID.put(character, sid);
+            }
         }
 
     }
@@ -454,6 +534,73 @@ public class PDType1CFont extends PDSimp
         }
     }
 
+    private Map<Integer,String> loadOverride() throws IOException
+    {
+        Map<Integer,String> result = new LinkedHashMap<Integer,String>();
+        COSBase encoding = getEncoding();
+        if( encoding instanceof COSName )
+        {
+            COSName name = (COSName)encoding;
+            result.putAll(loadEncoding(name));
+        }
+        else if( encoding instanceof COSDictionary )
+        {
+            COSDictionary encodingDic = (COSDictionary)encoding;
+            COSName baseName = (COSName)encodingDic.getDictionaryObject(COSName.BASE_ENCODING);
+            if( baseName != null )
+            {
+                result.putAll(loadEncoding(baseName));
+            }
+            COSArray differences = (COSArray)encodingDic.getDictionaryObject(COSName.DIFFERENCES);
+            if( differences != null )
+            {
+                result.putAll(loadDifferences(differences));
+            }
+        }
+
+        return result;
+    }
+
+    private Map<Integer,String> loadEncoding(COSName name) throws IOException
+    {
+        Map<Integer,String> result = new LinkedHashMap<Integer,String>();
+        Encoding encoding = EncodingManager.INSTANCE.getEncoding(name);
+        for( Iterator<Map.Entry<Integer,String>> it = (encoding.getCodeToNameMap().entrySet()).iterator();
+                    it.hasNext();)
+        {
+            Map.Entry<Integer,String> entry = it.next();
+            result.put(entry.getKey(), (entry.getValue()));
+        }
+
+        return result;
+    }
+
+    private Map<Integer,String> loadDifferences(COSArray differences)
+    {
+        Map<Integer,String> result = new LinkedHashMap<Integer,String>();
+        Integer code = null;
+        for( int i = 0; i < differences.size(); i++)
+        {
+            COSBase element = differences.get(i);
+            if( element instanceof COSNumber )
+            {
+                COSNumber number = (COSNumber)element;
+                code = Integer.valueOf(number.intValue());
+            } 
+            else 
+            {
+                if( element instanceof COSName )
+                {
+                    COSName name = (COSName)element;
+                    result.put(code, name.getName());
+                    code = Integer.valueOf(code.intValue() + 1);
+                }
+            }
+        }
+        return result;
+    }
+
+    
     private static Font prepareAwtFont( CFFFont font ) throws IOException
     {
         byte[] type1Bytes = Type1FontFormatter.format(font);
@@ -473,4 +620,49 @@ public class PDType1CFont extends PDSimp
         }
     }
 
+    /**
+     * This class represents a PDFEncoding.
+     *
+     */
+    private static class PDFEncoding extends CFFEncoding
+    {
+
+        private PDFEncoding( CFFEncoding parent )
+        {
+            Iterator<Entry> parentEntries = parent.getEntries().iterator();
+            while(parentEntries.hasNext())
+            {
+                addEntry(parentEntries.next());
+            }
+        }
+
+        public boolean isFontSpecific()
+        {
+            return true;
+        }
+
+    }
+
+    /**
+     * This class represents a PDFCharset.
+     *
+     */
+    private static class PDFCharset extends CFFCharset
+    {
+        private PDFCharset( CFFCharset parent )
+        {
+            Iterator<Entry> parentEntries = parent.getEntries().iterator();
+            while(parentEntries.hasNext())
+            {
+                addEntry(parentEntries.next());
+            }
+        }
+
+        public boolean isFontSpecific()
+        {
+            return true;
+        }
+
+    }
+
 }

Modified: pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java?rev=1592586&r1=1592585&r2=1592586&view=diff
==============================================================================
--- pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java (original)
+++ pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java Mon May  5 17:46:50 2014
@@ -463,12 +463,13 @@ public class PDType1Font extends PDSimpl
     {
         if (type1CFont != null && getFontEncoding() == null)
         {
-            return type1CFont.encode(c, offset, length);
-        }
-        else
-        {
-            return super.encode(c, offset, length);
+            String character = type1CFont.encode(c, offset, length);
+            if (character != null)
+            {
+                return character;
+            }
         }
+        return super.encode(c, offset, length);
     }
     
     /**