Index: fontbox/src/main/java/org/apache/fontbox/cff/CharStringHandler.java
===================================================================
--- fontbox/src/main/java/org/apache/fontbox/cff/CharStringHandler.java	(revision 1054253)
+++ fontbox/src/main/java/org/apache/fontbox/cff/CharStringHandler.java	(working copy)
@@ -16,6 +16,8 @@
  */
 package org.apache.fontbox.cff;
 
+import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -27,32 +29,43 @@
 public abstract class CharStringHandler
 {
 
+	private List<CharStringCommand> commandList = new ArrayList<CharStringCommand>();
+	private List<List<Integer>> numbersList = new ArrayList<List<Integer>>();
+	
     /**
      * Handler for a sequence of CharStringCommands.
      * 
      * @param sequence of CharStringCommands
      */
     @SuppressWarnings(value = { "unchecked" })
-    public void handleSequence(List<Object> sequence)
+    public List<Integer> handleSequence(List<Object> sequence) throws IOException
     {
+     	List<Integer> numbers = new ArrayList<Integer>();
         int offset = 0;
-        for (int i = 0; i < sequence.size(); i++)
+        int i = 0;
+        for (; i < sequence.size(); i++)
         {
             Object object = sequence.get(i);
             if (object instanceof CharStringCommand)
             {
-                List<Integer> numbers = (List) sequence.subList(offset, i);
+                numbers.addAll((List) sequence.subList(offset, i)); 
                 CharStringCommand command = (CharStringCommand) object;
-                handleCommand(numbers, command);
+                commandList.add(command);
+                numbersList.add(numbers);
+                List<Integer> stack = handleCommand(numbers, command);
+                numbers = stack;
                 offset = i + 1;
             }
         }
+        numbers.addAll(0, (List) sequence.subList(offset, i));
+        return numbers;
     }
     /**
      * Handler for CharStringCommands.
      *  
      * @param numbers a list of numbers
      * @param command the CharStringCommand
+     * @throws IOException 
      */
-    public abstract void handleCommand(List<Integer> numbers, CharStringCommand command);
+    public abstract List<Integer> handleCommand(List<Integer> numbers, CharStringCommand command) throws IOException;
 }
\ No newline at end of file
Index: fontbox/src/main/java/org/apache/fontbox/cff/Type2CharStringParser.java
===================================================================
--- fontbox/src/main/java/org/apache/fontbox/cff/Type2CharStringParser.java	(revision 1054253)
+++ fontbox/src/main/java/org/apache/fontbox/cff/Type2CharStringParser.java	(working copy)
@@ -54,7 +54,10 @@
 
             if (b0 >= 0 && b0 <= 27)
             {
-                sequence.add(readCommand(b0));
+            	CharStringCommand command = readCommand(b0);
+            	if (CharStringCommand.TYPE2_VOCABULARY.keySet().contains(command.getKey()) ||
+            		CharStringCommand.TYPE2_VOCABULARY.keySet().contains(command.getKey()))
+                sequence.add(command);
             } 
             else if (b0 == 28)
             {
Index: fontbox/src/main/java/org/apache/fontbox/cff/CFFFontROS.java
===================================================================
--- fontbox/src/main/java/org/apache/fontbox/cff/CFFFontROS.java	(revision 1054253)
+++ fontbox/src/main/java/org/apache/fontbox/cff/CFFFontROS.java	(working copy)
@@ -172,7 +172,7 @@
 					csr = new CharStringRenderer(false);
 					csr.render(lSeq);
 				} else {
-					List<Object> lSeq = m.toType1Sequence();
+					List<Object> lSeq = m.toType1Sequence(getGlobalSubrIndex());
 					csr = new CharStringRenderer();
 					csr.render(lSeq);
 				}
Index: fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java
===================================================================
--- fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java	(revision 1054253)
+++ fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java	(working copy)
@@ -70,6 +70,7 @@
         for (int i = 0; i < nameIndex.count; i++)
         {
             CFFFont font = parseFont(i);
+            font.setGlobalSubrIndex(globalSubrIndex);
             fonts.add(font);
         }
         return fonts;
@@ -425,6 +426,17 @@
     	        privDict.put("initialRandomSeed", getNumber(privateDict, "initialRandomSeed", Integer.valueOf(0)));
     	        privDict.put("defaultWidthX", getNumber(privateDict, "defaultWidthX", Integer.valueOf(0)));
     	        privDict.put("nominalWidthX", getNumber(privateDict, "nominalWidthX", Integer.valueOf(0)));
+    	        
+    	        int localSubrOffset = (Integer)getNumber(privateDict, "Subrs", Integer.valueOf(0));
+    	        if (localSubrOffset == 0)
+    	        {
+    	        	font.setLocalSubrIndex(new IndexData());
+    	        }
+    	        else
+    	        {
+    	        	input.setPosition(privateOffset + localSubrOffset);
+    	        	font.setLocalSubrIndex(readIndexData(input));
+    	        }
 
     	        privateDictionaries.add(privDict);
         	}
@@ -466,6 +478,17 @@
 	        font.addValueToPrivateDict("initialRandomSeed", getNumber(privateDict, "initialRandomSeed", Integer.valueOf(0)));
 	        font.addValueToPrivateDict("defaultWidthX", getNumber(privateDict, "defaultWidthX", Integer.valueOf(0)));
 	        font.addValueToPrivateDict("nominalWidthX", getNumber(privateDict, "nominalWidthX", Integer.valueOf(0)));
+	        
+	        int localSubrOffset = (Integer)getNumber(privateDict, "Subrs", Integer.valueOf(0));
+	        if (localSubrOffset == 0)
+	        {
+	        	font.setLocalSubrIndex(new IndexData());
+	        }
+	        else
+	        {
+	        	input.setPosition(privateOffset + localSubrOffset);
+	        	font.setLocalSubrIndex(readIndexData(input));
+	        }
         }
 
         return font;
@@ -879,36 +902,6 @@
     }
 
     /**
-     * Inner class holding the IndexData of a CFF font. 
-     */
-    private static class IndexData
-    {
-        private int count;
-        private int offSize;
-        private int[] offset;
-        private int[] data;
-
-        public byte[] getBytes(int index)
-        {
-            int length = offset[index + 1] - offset[index];
-            byte[] bytes = new byte[length];
-            for (int i = 0; i < length; i++)
-            {
-                bytes[i] = (byte) data[offset[index] - 1 + i];
-            }
-            return bytes;
-        }
-
-        @Override
-        public String toString()
-        {
-            return getClass().getName() + "[count=" + count + ", offSize="
-                    + offSize + ", offset=" + Arrays.toString(offset)
-                    + ", data=" + Arrays.toString(data) + "]";
-        }
-    }
-
-    /**
      * Inner class holding the DictData of a CFF font. 
      */
     private static class DictData
Index: fontbox/src/main/java/org/apache/fontbox/cff/Type1FontFormatter.java
===================================================================
--- fontbox/src/main/java/org/apache/fontbox/cff/Type1FontFormatter.java	(revision 1054253)
+++ fontbox/src/main/java/org/apache/fontbox/cff/Type1FontFormatter.java	(working copy)
@@ -174,7 +174,7 @@
 
         for (CFFFont.Mapping mapping : mappings)
         {
-            byte[] type1Bytes = formatter.format(mapping.toType1Sequence());
+            byte[] type1Bytes = formatter.format(mapping.toType1Sequence(font.getGlobalSubrIndex()));
 
             byte[] charstringBytes = Type1FontUtil.charstringEncrypt(
                     type1Bytes, 4);
Index: fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java
===================================================================
--- fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java	(revision 1054253)
+++ fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java	(working copy)
@@ -25,6 +25,7 @@
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.fontbox.cff.IndexData;
 import org.apache.fontbox.cff.charset.CFFCharset;
 import org.apache.fontbox.cff.encoding.CFFEncoding;
 
@@ -43,6 +44,8 @@
     private CFFEncoding fontEncoding = null;
     private CFFCharset fontCharset = null;
     private Map<String, byte[]> charStringsDict = new LinkedHashMap<String, byte[]>();
+    private IndexData globalSubrIndex = null;
+    private IndexData localSubrIndex = null;
 
     /**
      * The name of the font.
@@ -224,7 +227,7 @@
 					csr = new CharStringRenderer(false);
 					csr.render(lSeq);
 				} else {
-					List<Object> lSeq = m.toType1Sequence();
+					List<Object> lSeq = m.toType1Sequence(globalSubrIndex);
 					csr = new CharStringRenderer();
 					csr.render(lSeq);
 				}
@@ -288,12 +291,12 @@
      * Creates a CharStringConverter for this font.
      * @return the new CharStringConverter
      */
-    public CharStringConverter createConverter()
+    public CharStringConverter createConverter(IndexData globalSubrIndex)
     {
         Number defaultWidthX = (Number) getProperty("defaultWidthX");
         Number nominalWidthX = (Number) getProperty("nominalWidthX");
         return new CharStringConverter(defaultWidthX.intValue(), nominalWidthX
-                .intValue());
+                .intValue(), globalSubrIndex, getLocalSubrIndex());
     }
 
     /**
@@ -316,7 +319,23 @@
                 + charStringsDict + "]";
     }
 
-    /**
+    public void setGlobalSubrIndex(IndexData globalSubrIndex) {
+		this.globalSubrIndex = globalSubrIndex;
+	}
+
+	public IndexData getGlobalSubrIndex() {
+		return globalSubrIndex;
+	}
+	
+	public IndexData getLocalSubrIndex() {
+		return localSubrIndex;
+	}
+	
+	public void setLocalSubrIndex(IndexData readIndexData) {
+		localSubrIndex = readIndexData;	
+	}
+
+	/**
      * This class is used for the font mapping.
      *
      */
@@ -332,9 +351,9 @@
          * @return the Type1-sequence
          * @throws IOException if an error occurs during reading
          */
-        public List<Object> toType1Sequence() throws IOException
+        public List<Object> toType1Sequence(IndexData globalSubrIndex) throws IOException
         {
-            CharStringConverter converter = createConverter();
+            CharStringConverter converter = createConverter(globalSubrIndex);
             return converter.convert(toType2Sequence());
         }
 
@@ -405,4 +424,5 @@
             this.mappedBytes = bytes;
         }
     }
+
 }
\ No newline at end of file
Index: fontbox/src/main/java/org/apache/fontbox/cff/AFMFormatter.java
===================================================================
--- fontbox/src/main/java/org/apache/fontbox/cff/AFMFormatter.java	(revision 1054253)
+++ fontbox/src/main/java/org/apache/fontbox/cff/AFMFormatter.java	(working copy)
@@ -123,7 +123,7 @@
             CharMetric metric = new CharMetric();
             metric.code = mapping.getCode();
             metric.name = mapping.getName();
-            renderer.render(mapping.toType1Sequence());
+            renderer.render(mapping.toType1Sequence(font.getGlobalSubrIndex()));
             metric.width = renderer.getWidth();
             metric.bounds = renderer.getBounds();
             metrics.add(metric);
Index: fontbox/src/main/java/org/apache/fontbox/cff/CharStringRenderer.java
===================================================================
--- fontbox/src/main/java/org/apache/fontbox/cff/CharStringRenderer.java	(revision 1054253)
+++ fontbox/src/main/java/org/apache/fontbox/cff/CharStringRenderer.java	(working copy)
@@ -19,6 +19,8 @@
 import java.awt.geom.GeneralPath;
 import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -50,7 +52,7 @@
      * @param sequence the given charstring sequence
      * @return the rendered GeneralPath 
      */
-    public GeneralPath render(List<Object> sequence)
+    public GeneralPath render(List<Object> sequence) throws IOException
     {
         path = new GeneralPath();
         sidebearingPoint = new Point2D.Float(0, 0);
@@ -63,13 +65,14 @@
     /**
      * {@inheritDoc}
      */
-    public void handleCommand(List<Integer> numbers, CharStringCommand command)
+    public List<Integer> handleCommand(List<Integer> numbers, CharStringCommand command)
     {
         if (isCharstringType1) {
             handleCommandType1(numbers, command);
         } else {
             handleCommandType2(numbers, command);
         }
+        return new ArrayList<Integer>();
     }
  
     /**
@@ -208,6 +211,7 @@
         }
  
         if (isFirstCommand) {  isFirstCommand = false; }
+        
     }
  
     /**
Index: fontbox/src/main/java/org/apache/fontbox/cff/CharStringConverter.java
===================================================================
--- fontbox/src/main/java/org/apache/fontbox/cff/CharStringConverter.java	(revision 1054253)
+++ fontbox/src/main/java/org/apache/fontbox/cff/CharStringConverter.java	(working copy)
@@ -16,6 +16,7 @@
  */
 package org.apache.fontbox.cff;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -34,6 +35,8 @@
     private int nominalWidthX = 0;
     private List<Object> sequence = null;
     private int pathCount = 0;
+    IndexData globalSubrIndex = null;
+    IndexData localSubrIndex = null;
 
     /**
      * Constructor.
@@ -41,10 +44,12 @@
      * @param defaultWidth default width
      * @param nominalWidth nominal width
      */
-    public CharStringConverter(int defaultWidth, int nominalWidth)
+    public CharStringConverter(int defaultWidth, int nominalWidth, IndexData fontGlobalSubrIndex, IndexData fontLocalSubrIndex)
     {
         defaultWidthX = defaultWidth;
         nominalWidthX = nominalWidth;
+        globalSubrIndex = fontGlobalSubrIndex;
+        localSubrIndex = fontLocalSubrIndex;
     }
 
     /**
@@ -52,7 +57,7 @@
      * @param commandSequence the type1/type2 sequence
      * @return the CHarStringCommandSequence
      */
-    public List<Object> convert(List<Object> commandSequence)
+    public List<Object> convert(List<Object> commandSequence) throws IOException
     {
         sequence = new ArrayList<Object>();
         pathCount = 0;
@@ -64,20 +69,25 @@
      * {@inheritDoc}
      */
     @Override
-    public void handleCommand(List<Integer> numbers, CharStringCommand command)
+    public List<Integer> handleCommand(List<Integer> numbers, CharStringCommand command) throws IOException
     {
 
         if (CharStringCommand.TYPE1_VOCABULARY.containsKey(command.getKey()))
         {
-            handleType1Command(numbers, command);
+            return handleType1Command(numbers, command);
         } 
+        else if (CharStringCommand.TYPE2_VOCABULARY.containsKey(command.getKey()))
+        {
+            return handleType2Command(numbers, command);
+        }
         else
         {
-            handleType2Command(numbers, command);
+        	System.out.println("Unknown command: " + command);
         }
+        return new ArrayList<Integer>();
     }
 
-    private void handleType1Command(List<Integer> numbers,
+    private List<Integer> handleType1Command(List<Integer> numbers,
             CharStringCommand command)
     {
         String name = CharStringCommand.TYPE1_VOCABULARY.get(command.getKey());
@@ -140,15 +150,48 @@
         {
             drawAlternatingCurve(numbers, true);
         } 
+        else if ("callsubr".equals(name))
+        {
+        	//get subrbias
+        	int bias = 0;
+        	int nSubrs = localSubrIndex.count;
+        	
+        	if (nSubrs < 1240) bias = 107;
+        	else if (nSubrs < 33900) bias = 1131;
+        	else bias = 32768;
+        	
+        	List<Integer> result = null;
+        	int subrNumber = bias+numbers.get(numbers.size()-1);
+        	if (subrNumber < localSubrIndex.count)
+        	{
+	        	Type2CharStringParser parser = new Type2CharStringParser();
+	        	byte[] bytes = localSubrIndex.getBytes(subrNumber);
+	        	List<Object> parsed = null;
+				try {
+					parsed = parser.parse(bytes);
+		        	parsed.addAll(0,numbers.subList(0, numbers.size()-1));
+		        	result = handleSequence(parsed);
+				} catch (IOException e) {
+					e.printStackTrace();
+				}
+        	}
+        	return (result != null) ? result : new ArrayList<Integer>();
+        }
+        else if ("return".equals(name))
+        {
+        	return numbers;
+        }
         else
             addCommand(numbers, command);
         }
+        return new ArrayList<Integer>();
     }
 
     @SuppressWarnings(value = { "unchecked" })
-    private void handleType2Command(List<Integer> numbers,
-            CharStringCommand command)
+    private List<Integer> handleType2Command(List<Integer> numbers,
+            CharStringCommand command) throws IOException
     {
         String name = CharStringCommand.TYPE2_VOCABULARY.get(command.getKey());
         if ("hflex".equals(name))
@@ -228,11 +271,40 @@
         {
             drawCurve(numbers, true);
         } 
+        else if ("callgsubr".equals(name))
+        {
+        	//get subrbias
+        	int bias = 0;
+        	int nSubrs = globalSubrIndex.count;
+        	
+        	if (nSubrs < 1240) bias = 107;
+        	else if (nSubrs < 33900) bias = 1131;
+        	else bias = 32768;
+        	
+        	List<Integer> result = null;
+        	int subrNumber = bias+numbers.get(numbers.size()-1);
+        	if (subrNumber < nSubrs)
+        	{
+	        	Type2CharStringParser parser = new Type2CharStringParser();
+	        	byte[] bytes = globalSubrIndex.getBytes(subrNumber);
+	        	List<Object> parsed = null;
+				try {
+					parsed = parser.parse(bytes);
+		        	parsed.addAll(0,numbers.subList(0, numbers.size()-1));
+		        	result = handleSequence(parsed);
+				} catch (IOException e) {
+					e.printStackTrace();
+				}
+        	}
+        	return (result != null) ? result : new ArrayList<Integer>();
+        }
         else
         {
-            // System.out.println("Not implemented: numbers=" + numbers +
-            // " command=" +command+ " (" +name+ ")");
+            addCommand(numbers, command);
         }
+        return new ArrayList<Integer>();
     }
 
     private List<Integer> clearStack(List<Integer> numbers, boolean flag)
