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 2015/11/29 15:03:20 UTC

svn commit: r1717066 - /pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java

Author: lehmi
Date: Sun Nov 29 14:03:20 2015
New Revision: 1717066

URL: http://svn.apache.org/viewvc?rev=1717066&view=rev
Log:
PDFBOX-3131: reduce amount of intermediate data and objects

Modified:
    pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java

Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java?rev=1717066&r1=1717065&r2=1717066&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java Sun Nov 29 14:03:20 2015
@@ -19,6 +19,7 @@ package org.apache.fontbox.cff;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
@@ -37,9 +38,9 @@ public class CFFParser
     private CFFDataInput input = null;
     @SuppressWarnings("unused")
     private Header header = null;
-    private List<byte[]> nameIndex = null;
+    private List<String> nameIndex = null;
     private List<byte[]> topDictIndex = null;
-    private List<byte[]> stringIndex = null;
+    private List<String> stringIndex = null;
     
     // for debugging only
     private String debugFontName; 
@@ -104,9 +105,9 @@ public class CFFParser
         }
 
         header = readHeader(input);
-        nameIndex = readIndexData(input);
+        nameIndex = readStringIndexData(input);
         topDictIndex = readIndexData(input);
-        stringIndex = readIndexData(input);
+        stringIndex = readStringIndexData(input);
         List<byte[]> globalSubrIndex = readIndexData(input);
 
         List<CFFFont> fonts = new ArrayList<CFFFont>();
@@ -141,13 +142,12 @@ public class CFFParser
         return cffHeader;
     }
 
-    private static List<byte[]> readIndexData(CFFDataInput input) throws IOException
+    private static int[] readIndexDataOffsets(CFFDataInput input) throws IOException
     {
-        List<byte[]> indexDataValues = new ArrayList<byte[]>();
         int count = input.readCard16();
         if (count == 0)
         {
-            return indexDataValues;
+            return null;
         }
         int offSize = input.readOffSize();
         int[] offsets = new int[count+1];
@@ -160,6 +160,18 @@ public class CFFParser
             }
             offsets[i] = offset;
         }
+        return offsets;
+    }
+
+    private static List<byte[]> readIndexData(CFFDataInput input) throws IOException
+    {
+        int[] offsets = readIndexDataOffsets(input);
+        if (offsets == null)
+        {
+            return new ArrayList<byte[]>(0);
+        }
+        int count = offsets.length-1;
+        List<byte[]> indexDataValues = new ArrayList<byte[]>(count);
         for (int i = 0; i < count; i++)
         {
             int length = offsets[i + 1] - offsets[i];
@@ -168,14 +180,29 @@ public class CFFParser
         return indexDataValues;
     }
 
+    private static List<String> readStringIndexData(CFFDataInput input) throws IOException
+    {
+        int[] offsets = readIndexDataOffsets(input);
+        if (offsets == null)
+        {
+            return new ArrayList<String>(0);
+        }
+        int count = offsets.length-1;
+        List<String> indexDataValues = new ArrayList<String>(count);
+        for (int i = 0; i < count; i++)
+        {
+            int length = offsets[i + 1] - offsets[i];
+            indexDataValues.add(new String(input.readBytes(length), "ISO-8859-1"));
+        }
+        return indexDataValues;
+    }
+
     private static DictData readDictData(CFFDataInput input) throws IOException
     {
         DictData dict = new DictData();
-        dict.entries = new ArrayList<DictData.Entry>();
         while (input.hasRemaining())
         {
-            DictData.Entry entry = readEntry(input);
-            dict.entries.add(entry);
+            dict.add(readEntry(input));
         }
         return dict;
     }
@@ -183,12 +210,10 @@ public class CFFParser
     private static DictData readDictData(CFFDataInput input, int dictSize) throws IOException
     {
         DictData dict = new DictData();
-        dict.entries = new ArrayList<DictData.Entry>();
         int endPosition = input.getPosition() + dictSize;
         while (input.getPosition() < endPosition)
         {
-            DictData.Entry entry = readEntry(input);
-            dict.entries.add(entry);
+            dict.add(readEntry(input));
         }
         return dict;
     }
@@ -282,7 +307,7 @@ public class CFFParser
      */
     private static Double readRealNumber(CFFDataInput input, int b0) throws IOException
     {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         boolean done = false;
         boolean exponentMissing = false;
         while (!done)
@@ -343,8 +368,7 @@ public class CFFParser
     private CFFFont parseFont(int index) throws IOException
     {
         // name index
-        DataInput nameInput = new DataInput(nameIndex.get(index));
-        String name = nameInput.getString();
+        String name = nameIndex.get(index);
 
         // top dict
         CFFDataInput topDictInput = new CFFDataInput(topDictIndex.get(index));
@@ -384,20 +408,20 @@ public class CFFParser
         font.addValueToTopDict("FullName", getString(topDict, "FullName"));
         font.addValueToTopDict("FamilyName", getString(topDict, "FamilyName"));
         font.addValueToTopDict("Weight", getString(topDict, "Weight"));
-        font.addValueToTopDict("isFixedPitch", getBoolean(topDict, "isFixedPitch", false));
-        font.addValueToTopDict("ItalicAngle", getNumber(topDict, "ItalicAngle", 0));
-        font.addValueToTopDict("UnderlinePosition", getNumber(topDict, "UnderlinePosition", -100));
-        font.addValueToTopDict("UnderlineThickness", getNumber(topDict, "UnderlineThickness", 50));
-        font.addValueToTopDict("PaintType", getNumber(topDict, "PaintType", 0));
-        font.addValueToTopDict("CharstringType", getNumber(topDict, "CharstringType", 2));
-        font.addValueToTopDict("FontMatrix", getArray(topDict, "FontMatrix", Arrays.<Number>asList(
+        font.addValueToTopDict("isFixedPitch", topDict.getBoolean("isFixedPitch", false));
+        font.addValueToTopDict("ItalicAngle", topDict.getNumber("ItalicAngle", 0));
+        font.addValueToTopDict("UnderlinePosition", topDict.getNumber("UnderlinePosition", -100));
+        font.addValueToTopDict("UnderlineThickness", topDict.getNumber("UnderlineThickness", 50));
+        font.addValueToTopDict("PaintType", topDict.getNumber("PaintType", 0));
+        font.addValueToTopDict("CharstringType", topDict.getNumber("CharstringType", 2));
+        font.addValueToTopDict("FontMatrix", topDict.getArray("FontMatrix", Arrays.<Number>asList(
                                                       0.001, (double) 0, (double) 0, 0.001,
                                                       (double) 0, (double) 0)));
-        font.addValueToTopDict("UniqueID", getNumber(topDict, "UniqueID", null));
-        font.addValueToTopDict("FontBBox", getArray(topDict, "FontBBox",
+        font.addValueToTopDict("UniqueID", topDict.getNumber("UniqueID", null));
+        font.addValueToTopDict("FontBBox", topDict.getArray("FontBBox",
                                                     Arrays.<Number> asList(0, 0, 0, 0)));
-        font.addValueToTopDict("StrokeWidth", getNumber(topDict, "StrokeWidth", 0));
-        font.addValueToTopDict("XUID", getArray(topDict, "XUID", null));
+        font.addValueToTopDict("StrokeWidth", topDict.getNumber("StrokeWidth", 0));
+        font.addValueToTopDict("XUID", topDict.getArray("XUID", null));
 
         // charstrings index
         DictData.Entry charStringsEntry = topDict.getEntry("CharStrings");
@@ -463,7 +487,7 @@ public class CFFParser
                 else
                 {
                     // default
-                    font.addValueToTopDict("FontMatrix", getArray(topDict, "FontMatrix",
+                    font.addValueToTopDict("FontMatrix", topDict.getArray("FontMatrix",
                             Arrays.<Number>asList(0.001, (double) 0, (double) 0, 0.001,
                                     (double) 0, (double) 0)));
                 }
@@ -506,11 +530,11 @@ public class CFFParser
             DictData fontDict = readDictData(fontDictInput);
 
             // font dict
-            Map<String, Object> fontDictMap = new LinkedHashMap<String, Object>();
+            Map<String, Object> fontDictMap = new LinkedHashMap<String, Object>(4);
             fontDictMap.put("FontName", getString(fontDict, "FontName"));
-            fontDictMap.put("FontType", getNumber(fontDict, "FontType", 0));
-            fontDictMap.put("FontBBox", getDelta(fontDict, "FontBBox", null));
-            fontDictMap.put("FontMatrix", getDelta(fontDict, "FontMatrix", null));
+            fontDictMap.put("FontType", fontDict.getNumber("FontType", 0));
+            fontDictMap.put("FontBBox", fontDict.getArray("FontBBox", null));
+            fontDictMap.put("FontMatrix", fontDict.getArray("FontMatrix", null));
             // TODO OD-4 : Add here other keys
             fontDictionaries.add(fontDictMap);
 
@@ -531,7 +555,7 @@ public class CFFParser
             privateDictionaries.add(privDict);
 
             // local subrs
-            int localSubrOffset = (Integer) getNumber(privateDict, "Subrs", 0);
+            int localSubrOffset = (Integer) privateDict.getNumber("Subrs", 0);
             if (localSubrOffset == 0)
             {
                 privDict.put("Subrs", new ArrayList<byte[]>());
@@ -560,24 +584,24 @@ public class CFFParser
 
     private Map<String, Object> readPrivateDict(DictData privateDict)
     {
-        Map<String, Object> privDict = new LinkedHashMap<String, Object>();
-        privDict.put("BlueValues", getDelta(privateDict, "BlueValues", null));
-        privDict.put("OtherBlues", getDelta(privateDict, "OtherBlues", null));
-        privDict.put("FamilyBlues", getDelta(privateDict, "FamilyBlues", null));
-        privDict.put("FamilyOtherBlues", getDelta(privateDict, "FamilyOtherBlues", null));
-        privDict.put("BlueScale", getNumber(privateDict, "BlueScale", 0.039625));
-        privDict.put("BlueShift", getNumber(privateDict, "BlueShift", 7));
-        privDict.put("BlueFuzz", getNumber(privateDict, "BlueFuzz", 1));
-        privDict.put("StdHW", getNumber(privateDict, "StdHW", null));
-        privDict.put("StdVW", getNumber(privateDict, "StdVW", null));
-        privDict.put("StemSnapH", getDelta(privateDict, "StemSnapH", null));
-        privDict.put("StemSnapV", getDelta(privateDict, "StemSnapV", null));
-        privDict.put("ForceBold", getBoolean(privateDict, "ForceBold", false));
-        privDict.put("LanguageGroup", getNumber(privateDict, "LanguageGroup", 0));
-        privDict.put("ExpansionFactor", getNumber(privateDict, "ExpansionFactor", 0.06));
-        privDict.put("initialRandomSeed", getNumber(privateDict, "initialRandomSeed", 0));
-        privDict.put("defaultWidthX", getNumber(privateDict, "defaultWidthX", 0));
-        privDict.put("nominalWidthX", getNumber(privateDict, "nominalWidthX", 0));
+        Map<String, Object> privDict = new LinkedHashMap<String, Object>(17);
+        privDict.put("BlueValues", privateDict.getArray("BlueValues", null));
+        privDict.put("OtherBlues", privateDict.getArray("OtherBlues", null));
+        privDict.put("FamilyBlues", privateDict.getArray("FamilyBlues", null));
+        privDict.put("FamilyOtherBlues", privateDict.getArray("FamilyOtherBlues", null));
+        privDict.put("BlueScale", privateDict.getNumber("BlueScale", 0.039625));
+        privDict.put("BlueShift", privateDict.getNumber("BlueShift", 7));
+        privDict.put("BlueFuzz", privateDict.getNumber("BlueFuzz", 1));
+        privDict.put("StdHW", privateDict.getNumber("StdHW", null));
+        privDict.put("StdVW", privateDict.getNumber("StdVW", null));
+        privDict.put("StemSnapH", privateDict.getArray("StemSnapH", null));
+        privDict.put("StemSnapV", privateDict.getArray("StemSnapV", null));
+        privDict.put("ForceBold", privateDict.getBoolean("ForceBold", false));
+        privDict.put("LanguageGroup", privateDict.getNumber("LanguageGroup", 0));
+        privDict.put("ExpansionFactor", privateDict.getNumber("ExpansionFactor", 0.06));
+        privDict.put("initialRandomSeed", privateDict.getNumber("initialRandomSeed", 0));
+        privDict.put("defaultWidthX", privateDict.getNumber("defaultWidthX", 0));
+        privDict.put("nominalWidthX", privateDict.getNumber("nominalWidthX", 0));
         return privDict;
     }
 
@@ -625,7 +649,7 @@ public class CFFParser
         }
 
         // local subrs
-        int localSubrOffset = (Integer) getNumber(privateDict, "Subrs", 0);
+        int localSubrOffset = (Integer) privateDict.getNumber("Subrs", 0);
         if (localSubrOffset == 0)
         {
             font.addToPrivateDict("Subrs", new ArrayList<byte[]>());
@@ -645,8 +669,7 @@ public class CFFParser
         }
         if (index - 391 < stringIndex.size())
         {
-            DataInput dataInput = new DataInput(stringIndex.get(index - 391));
-            return dataInput.getString();
+            return stringIndex.get(index - 391);
         }
         else
         {
@@ -661,32 +684,6 @@ public class CFFParser
         return entry != null ? readString(entry.getNumber(0).intValue()) : null;
     }
 
-    private static Boolean getBoolean(DictData dict, String name, boolean defaultValue)
-    {
-        DictData.Entry entry = dict.getEntry(name);
-        return entry != null ? entry.getBoolean(0) : defaultValue;
-    }
-
-    private static Number getNumber(DictData dict, String name, Number defaultValue)
-    {
-        DictData.Entry entry = dict.getEntry(name);
-        return entry != null ? entry.getNumber(0) : defaultValue;
-    }
-
-    // TODO Where is the difference to getDelta??
-    private static List<Number> getArray(DictData dict, String name, List<Number> defaultValue)
-    {
-        DictData.Entry entry = dict.getEntry(name);
-        return entry != null ? entry.getArray() : defaultValue;
-    }
-
-    // TODO Where is the difference to getArray??
-    private static List<Number> getDelta(DictData dict, String name, List<Number> defaultValue)
-    {
-        DictData.Entry entry = dict.getEntry(name);
-        return entry != null ? entry.getArray() : defaultValue;
-    }
-
     private CFFEncoding readEncoding(CFFDataInput dataInput, CFFCharset charset) throws IOException
     {
         int format = dataInput.readCard8();
@@ -1094,28 +1091,44 @@ public class CFFParser
      */
     private static class DictData
     {
+        private Map<String, Entry> entries = new HashMap<String, Entry>();
 
-        private List<Entry> entries = null;
-
-        public Entry getEntry(CFFOperator.Key key)
+        public void add(Entry entry)
         {
-            return getEntry(CFFOperator.getOperator(key));
+            if (entry.operator != null)
+            {
+                entries.put(entry.operator.getName(), entry);
+            }
         }
-
+        
         public Entry getEntry(String name)
         {
             return getEntry(CFFOperator.getOperator(name));
         }
 
+        public Boolean getBoolean(String name, boolean defaultValue)
+        {
+            Entry entry = getEntry(name);
+            return entry != null ? entry.getBoolean(0) : defaultValue;
+        }
+
+        public List<Number> getArray(String name, List<Number> defaultValue)
+        {
+            Entry entry = getEntry(name);
+            return entry != null ? entry.getArray() : defaultValue;
+        }
+
+        public Number getNumber(String name, Number defaultValue)
+        {
+            Entry entry = getEntry(name);
+            return entry != null ? entry.getNumber(0) : defaultValue;
+        }
+
         private Entry getEntry(CFFOperator operator)
         {
-            for (Entry entry : entries)
+            if (operator != null && entries.containsKey(operator.getName()))
             {
-                // Check for null entry before comparing the Font
-                if (entry != null && entry.operator != null && entry.operator.equals(operator))
-                {
-                    return entry;
-                }
+                return entries.get(operator.getName());
             }
             return null;
         }
@@ -1160,7 +1173,6 @@ public class CFFParser
                 throw new IllegalArgumentException();
             }
 
-            // TODO Where is the difference to getDelta??
             public List<Number> getArray()
             {
                 return operands;