diff -b -r -N --unified fontbox-1.0.0/src/main/java/org/apache/fontbox/cff/CFFFont.java fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java
--- fontbox-1.0.0/src/main/java/org/apache/fontbox/cff/CFFFont.java	2010-02-26 18:04:51.000000000 +0100
+++ fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java	2010-03-19 14:56:26.000000000 +0100
@@ -20,7 +20,6 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -33,17 +32,17 @@
  * This class represents a CFF/Type2 Font.
  * 
  * @author Villu Russmann
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.3 $
  */
 public class CFFFont
 {
 
-    private String fontname = null;
+    protected String fontname = null;
     private Map<String, Object> topDict = new LinkedHashMap<String, Object>();
     private Map<String, Object> privateDict = new LinkedHashMap<String, Object>();
-    private CFFEncoding fontEncoding = null;
-    private CFFCharset fontCharset = null;
-    private Map<String, byte[]> charStringsDict = new LinkedHashMap<String, byte[]>();
+    protected CFFEncoding fontEncoding = null;
+    protected CFFCharset fontCharset = null;
+    protected Map<String, byte[]> charStringsDict = new LinkedHashMap<String, byte[]>();
 
     /**
      * The name of the font.
@@ -133,12 +132,9 @@
     {
         List<Mapping> mappings = new ArrayList<Mapping>();
         Set<String> mappedNames = new HashSet<String>();
-        Iterator<Integer> codes = fontEncoding.getCodes();
-        while (codes.hasNext())
+        for (CFFEncoding.Entry entry : fontEncoding.getEntries())
         {
-            int code = codes.next();
-            int sid = fontEncoding.getSID(code);
-            String charName = fontCharset.getName(sid);
+            String charName = fontCharset.getName(entry.getSID());
             // Predefined encoding
             if (charName == null)
             {
@@ -150,13 +146,38 @@
                 continue;
             }
             Mapping mapping = new Mapping();
-            mapping.setCode(code);
-            mapping.setSID(sid);
+            mapping.setCode(entry.getCode());
+            mapping.setSID(entry.getSID());
             mapping.setName(charName);
             mapping.setBytes(bytes);
             mappings.add(mapping);
             mappedNames.add(charName);
         }
+        if (fontEncoding instanceof CFFParser.EmbeddedEncoding)
+        {
+            CFFParser.EmbeddedEncoding embeddedEncoding = (CFFParser.EmbeddedEncoding)fontEncoding;
+
+            for (CFFParser.EmbeddedEncoding.Supplement supplement : embeddedEncoding.getSupplements())
+            {
+                String charName = fontCharset.getName(supplement.getGlyph());
+                if (charName == null)
+                {
+                    continue;
+                }
+                byte[] bytes = charStringsDict.get(charName);
+                if (bytes == null)
+                {
+                    continue;
+                }
+                Mapping mapping = new Mapping();
+                mapping.setCode(supplement.getCode());
+                mapping.setSID(supplement.getGlyph());
+                mapping.setName(charName);
+                mapping.setBytes(bytes);
+                mappings.add(mapping);
+                mappedNames.add(charName);
+            }
+        }
         // XXX
         int code = 256;
         for (CFFCharset.Entry entry : fontCharset.getEntries())
@@ -185,6 +206,40 @@
     }
 
     /**
+	 * Return the Width value of the given Glyph identifier
+	 * 
+	 * @param SID
+	 * @return -1 if the SID is missing from the Font.
+	 * @throws IOException
+	 */
+	public int getWidth(int SID) throws IOException {
+		int nominalWidth = privateDict.containsKey("nominalWidthX") ? ((Number)privateDict.get("nominalWidthX")).intValue() : 0;
+		int defaultWidth = privateDict.containsKey("defaultWidthX") ? ((Number)privateDict.get("defaultWidthX")).intValue() : 1000 ;
+		for (Mapping m : getMappings() ){
+			if (m.getSID() == SID) {
+
+				CharStringRenderer csr = null;
+				if (((Number)getProperty("CharstringType")).intValue() == 2 ) {
+					List<Object> lSeq = m.toType2Sequence();
+					csr = new CharStringRenderer(false);
+					csr.render(lSeq);
+				} else {
+					List<Object> lSeq = m.toType1Sequence();
+					csr = new CharStringRenderer();
+					csr.render(lSeq);
+				}
+
+				// ---- If the CharString has a Width nominalWidthX must be added, 
+				//	    otherwise it is the default width.
+				return csr.getWidth() != 0 ? csr.getWidth() + nominalWidth : defaultWidth;
+			}
+		}
+
+		// ---- Width not found, return the default width
+		return defaultWidth;
+	}
+    
+    /**
      * Returns the CFFEncoding of the font.
      * @return the encoding
      */
diff -b -r -N --unified fontbox-1.0.0/src/main/java/org/apache/fontbox/cff/CFFFontROS.java fontbox/src/main/java/org/apache/fontbox/cff/CFFFontROS.java
--- fontbox-1.0.0/src/main/java/org/apache/fontbox/cff/CFFFontROS.java	1970-01-01 01:00:00.000000000 +0100
+++ fontbox/src/main/java/org/apache/fontbox/cff/CFFFontROS.java	2010-03-19 14:56:26.000000000 +0100
@@ -0,0 +1,149 @@
+package org.apache.fontbox.cff;
+
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+public class CFFFontROS extends CFFFont {
+	private String registry;
+	private String ordering;
+	private int supplement;
+
+	private List<Map<String, Object>> fontDictionaries = new LinkedList<Map<String,Object>>();
+	private List<Map<String, Object>> privateDictionaries = new LinkedList<Map<String,Object>>();
+	private CIDKeyedFDSelect fdSelect = null;
+
+	/**
+	 * @return the registry
+	 */
+	public String getRegistry() {
+		return registry;
+	}
+
+	/**
+	 * @param registry the registry to set
+	 */
+	public void setRegistry(String registry) {
+		this.registry = registry;
+	}
+
+	/**
+	 * @return the ordering
+	 */
+	public String getOrdering() {
+		return ordering;
+	}
+
+	/**
+	 * @param ordering the ordering to set
+	 */
+	public void setOrdering(String ordering) {
+		this.ordering = ordering;
+	}
+
+	/**
+	 * @return the supplement
+	 */
+	public int getSupplement() {
+		return supplement;
+	}
+
+	/**
+	 * @param supplement the supplement to set
+	 */
+	public void setSupplement(int supplement) {
+		this.supplement = supplement;
+	}
+
+	/**
+	 * @return the fontDict
+	 */
+	public List<Map<String, Object>> getFontDict() {
+		return fontDictionaries;
+	}
+
+	/**
+	 * @param fontDict the fontDict to set
+	 */
+	public void setFontDict(List<Map<String, Object>> fontDict) {
+		this.fontDictionaries = fontDict;
+	}
+
+	/**
+	 * @return the privDict
+	 */
+	public List<Map<String, Object>> getPrivDict() {
+		return privateDictionaries;
+	}
+
+	/**
+	 * @param privDict the privDict to set
+	 */
+	public void setPrivDict(List<Map<String, Object>> privDict) {
+		this.privateDictionaries = privDict;
+	}
+
+	/**
+	 * @return the fdSelect
+	 */
+	public CIDKeyedFDSelect getFdSelect() {
+		return fdSelect;
+	}
+
+	/**
+	 * @param fdSelect the fdSelect to set
+	 */
+	public void setFdSelect(CIDKeyedFDSelect fdSelect) {
+		this.fdSelect = fdSelect;
+	}
+
+	/**
+	 * Return the Width value of the given Glyph identifier
+	 * 
+	 * @param SID
+	 * @return -1 if the SID is missing from the Font.
+	 * @throws IOException
+	 */
+	public int getWidth(int SID) throws IOException {
+		// ---- search the right FDArray index in the FDSelect according to the Character identifier
+		// 		this index will be used to access the private dictionary which contains useful values 
+		//		to compute width.
+		int fdArrayIndex = this.fdSelect.getFd(SID);
+		if (fdArrayIndex == -1 && SID == 0 ) { // --- notdef char
+			return super.getWidth(SID);
+		} else if (fdArrayIndex == -1) {
+			return 1000;
+		}
+
+		Map<String, Object> fontDict = this.fontDictionaries.get(fdArrayIndex);
+		Map<String, Object> privDict = this.privateDictionaries.get(fdArrayIndex);
+
+		int nominalWidth = privDict.containsKey("nominalWidthX") ? ((Number)privDict.get("nominalWidthX")).intValue() : 0;
+		int defaultWidth = privDict.containsKey("defaultWidthX") ? ((Number)privDict.get("defaultWidthX")).intValue() : 1000 ;
+
+		for (Mapping m : getMappings() ){
+			if (m.getSID() == SID) {
+
+				CharStringRenderer csr = null;
+				Number charStringType = (Number)getProperty("CharstringType");
+				if ( charStringType.intValue() == 2 ) {
+					List<Object> lSeq = m.toType2Sequence();
+					csr = new CharStringRenderer(false);
+					csr.render(lSeq);
+				} else {
+					List<Object> lSeq = m.toType1Sequence();
+					csr = new CharStringRenderer();
+					csr.render(lSeq);
+				}
+
+				// ---- If the CharString has a Width nominalWidthX must be added, 
+				//	    otherwise it is the default width.
+				return csr.getWidth() != 0 ? csr.getWidth() + nominalWidth : defaultWidth;
+			}
+		}
+
+		// ---- Width not found, return the default width
+		return defaultWidth;
+	}
+}
diff -b -r -N --unified fontbox-1.0.0/src/main/java/org/apache/fontbox/cff/CFFParser.java fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java
--- fontbox-1.0.0/src/main/java/org/apache/fontbox/cff/CFFParser.java	2010-02-26 18:04:51.000000000 +0100
+++ fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java	2010-03-19 14:56:26.000000000 +0100
@@ -19,8 +19,14 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
+import org.apache.fontbox.cff.CFFFont.Mapping;
 import org.apache.fontbox.cff.charset.CFFCharset;
 import org.apache.fontbox.cff.charset.CFFExpertCharset;
 import org.apache.fontbox.cff.charset.CFFExpertSubsetCharset;
@@ -32,7 +38,7 @@
 /**
  * This class represents a parser for a CFF font. 
  * @author Villu Russmann
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.3 $
  */
 public class CFFParser
 {
@@ -254,23 +260,33 @@
 
     private CFFFont parseFont(int index) throws IOException
     {
-        CFFFont font = new CFFFont();
+        CFFFont font = null;
         DataInput nameInput = new DataInput(nameIndex.getBytes(index));
         String name = nameInput.getString();
-        font.setName(name);
-        CFFDataInput topDictInput = new CFFDataInput(topDictIndex
-                .getBytes(index));
+
+        CFFDataInput topDictInput = new CFFDataInput(topDictIndex.getBytes(index));
         DictData topDict = readDictData(topDictInput);
         DictData.Entry syntheticBaseEntry = topDict.getEntry("SyntheticBase");
         if (syntheticBaseEntry != null)
         {
             throw new IOException("Synthetic Fonts are not supported");
         }
+
         DictData.Entry rosEntry = topDict.getEntry("ROS");
-        if (rosEntry != null)
-        {
-            throw new IOException("CID-keyed Fonts are not supported");
+        if (rosEntry != null) {
+        	font = new CFFFontROS();
+        	((CFFFontROS)font).setRegistry(readString(rosEntry.getNumber(0).intValue()));
+        	((CFFFontROS)font).setOrdering(readString(rosEntry.getNumber(1).intValue()));
+        	((CFFFontROS)font).setSupplement(rosEntry.getNumber(2).intValue());
+        }
+
+        if (font == null) {
+        	// -- No specific behavior for this font
+        	font = new CFFFont();
         }
+        
+        font.setName(name);
+
         font.addValueToTopDict("version", getString(topDict,"version"));
         font.addValueToTopDict("Notice", getString(topDict,"Notice"));
         font.addValueToTopDict("Copyright", getString(topDict,"Copyright"));
@@ -293,6 +309,7 @@
                         Integer.valueOf(0), Integer.valueOf(0))));
         font.addValueToTopDict("StrokeWidth", getNumber(topDict, "StrokeWidth", 0));
         font.addValueToTopDict("XUID", getArray(topDict, "XUID", null));
+
         DictData.Entry charStringsEntry = topDict.getEntry("CharStrings");
         int charStringsOffset = charStringsEntry.getNumber(0).intValue();
         input.setPosition(charStringsOffset);
@@ -328,11 +345,12 @@
             gids[i] = glyphEntry.getSID();
             font.getCharStringsDict().put(glyphEntry.getName(), charStringsIndex.getBytes(i + 1));
         }
+
+
         DictData.Entry encodingEntry = topDict.getEntry("Encoding");
         CFFEncoding encoding;
-        int encodingId = encodingEntry != null ? encodingEntry.getNumber(0)
-                .intValue() : 0;
-        if (encodingId == 0)
+        int encodingId = encodingEntry != null ? encodingEntry.getNumber(0).intValue() : 0;
+        if (encodingId == 0 || rosEntry != null) // --- ROS uses StandardEncoding
         {
             encoding = CFFStandardEncoding.getInstance();
         } 
@@ -346,6 +364,86 @@
             encoding = readEncoding(input, gids);
         }
         font.setEncoding(encoding);
+        
+
+        if (rosEntry != null) {
+
+        	// ---- It is a CIDKeyed Font, The Private Dictionary isn't in the Top Dict But in the Font Dict
+        	// ---- Font Dict can be accessed by the FDArray and FDSelect
+        	DictData.Entry fdArrayEntry = topDict.getEntry("FDArray");
+        	if (fdArrayEntry == null) {
+        		throw new IOException("FDArray is missing for a CIDKeyed Font.");
+        	}
+
+        	int fontDictOffset = fdArrayEntry.getNumber(0).intValue();
+        	input.setPosition(fontDictOffset);
+        	IndexData fdIndex = readIndexData(input);
+
+            List<Map<String, Object>> privateDictionaries = new LinkedList<Map<String, Object>>();
+            List<Map<String, Object>> fontDictionaries = new LinkedList<Map<String, Object>>();
+    		CFFFontROS fontRos = (CFFFontROS)font;
+
+        	for (int i = 0; i < fdIndex.count; ++i) {
+        		byte[] b = fdIndex.getBytes(i);
+        		CFFDataInput fontDictInput = new CFFDataInput(b);
+        		DictData fontDictData = readDictData(fontDictInput);
+
+        		Map<String, Object> fontDictMap = new LinkedHashMap<String, Object>();
+        		fontDictMap.put("FontName", getString(fontDictData, "FontName"));
+        		fontDictMap.put("FontType", getNumber(fontDictData, "FontType", 0));
+        		fontDictMap.put("FontBBox", getDelta(fontDictData, "FontBBox", null));
+        		fontDictMap.put("FontMatrix", getDelta(fontDictData, "FontMatrix", null));
+        		// TODO OD-PDFA-4 : Add here other keys
+        		fontDictionaries.add(fontDictMap);
+        		
+        		DictData.Entry privateEntry = fontDictData.getEntry("Private");
+        		// --- Font DICT is invalid without "Private" entry
+        		if ( privateEntry == null) {
+        			throw new IOException("Missing Private Dictionary");
+        		}
+
+    	        int privateOffset = privateEntry.getNumber(1).intValue();
+    	        input.setPosition(privateOffset);
+    	        int privateSize = privateEntry.getNumber(0).intValue();
+    	        CFFDataInput privateDictData = new CFFDataInput(input.readBytes(privateSize));
+    	        DictData privateDict = readDictData(privateDictData);
+
+    	        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", Double.valueOf(0.039625)));
+    	        privDict.put("BlueShift", getNumber(privateDict, "BlueShift", Integer.valueOf(7)));
+    	        privDict.put("BlueFuzz", getNumber(privateDict, "BlueFuzz", Integer.valueOf(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", Integer.valueOf(0)));
+    	        privDict.put("ExpansionFactor", getNumber(privateDict, "ExpansionFactor", Double.valueOf(0.06)));
+    	        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)));
+
+    	        privateDictionaries.add(privDict);
+        	}
+
+        	fontRos.setFontDict(fontDictionaries);
+        	fontRos.setPrivDict(privateDictionaries);
+        	
+        	DictData.Entry fdSelectEntry = topDict.getEntry("FDSelect");
+        	int fdSelectPos = fdSelectEntry.getNumber(0).intValue();
+        	input.setPosition(fdSelectPos);
+        	CIDKeyedFDSelect fdSelect = readFDSelect(input, charStringsIndex.count, fontRos);
+
+	        font.addValueToPrivateDict("defaultWidthX", Integer.valueOf(1000));
+	        font.addValueToPrivateDict("nominalWidthX", Integer.valueOf(0));
+        	
+        	fontRos.setFdSelect(fdSelect);
+
+        } else {
         DictData.Entry privateEntry = topDict.getEntry("Private");
         int privateOffset = privateEntry.getNumber(1).intValue();
         input.setPosition(privateOffset);
@@ -369,6 +467,8 @@
         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)));
+        }
+
         return font;
     }
 
@@ -494,6 +594,186 @@
         }
     }
 
+    /**
+     * Read the FDSelect Data according to the format.
+     * @param dataInput
+     * @param nGlyphs
+     * @param ros
+     * @return
+     * @throws IOException
+     */
+    private CIDKeyedFDSelect readFDSelect(CFFDataInput dataInput, int nGlyphs, CFFFontROS ros)
+    throws IOException
+	{
+		int format = dataInput.readCard8();
+		if (format == 0)
+		{
+		    return readFormat0FDSelect(dataInput, format, nGlyphs, ros);
+		} 
+		else if (format == 3)
+		{
+		    return readFormat3FDSelect(dataInput, format, nGlyphs, ros);
+		} 
+		else
+		{
+		    throw new IllegalArgumentException();
+		}
+	}
+
+    /**
+     * Read the Format 0 of the FDSelect data structure.
+     * @param dataInput
+     * @param format
+     * @param nGlyphs
+     * @param ros
+     * @return
+     * @throws IOException
+     */
+    private Format0FDSelect readFormat0FDSelect(CFFDataInput dataInput, int format, int nGlyphs, CFFFontROS ros) throws IOException
+    {
+    	Format0FDSelect fdselect = new Format0FDSelect(ros);
+    	fdselect.format = format;
+        fdselect.fds = new int[nGlyphs];
+        for (int i = 0; i < fdselect.fds.length; i++)
+        {
+        	fdselect.fds[i] = dataInput.readCard8();
+
+        }
+        return fdselect;
+    }
+
+    /**
+     * Read the Format 3 of the FDSelect data structure.
+     * 
+     * @param dataInput
+     * @param format
+     * @param nGlyphs
+     * @param ros
+     * @return
+     * @throws IOException
+     */
+    private Format3FDSelect readFormat3FDSelect(CFFDataInput dataInput, int format, int nGlyphs, CFFFontROS ros) throws IOException
+    {
+    	Format3FDSelect fdselect = new Format3FDSelect(ros);
+    	fdselect.format = format;
+    	fdselect.nbRanges = dataInput.readCard16();
+
+    	fdselect.range3 = new Range3[fdselect.nbRanges];
+        for (int i = 0; i < fdselect.nbRanges; i++)
+        {
+        	Range3 r3 = new Range3();
+        	r3.first = dataInput.readCard16();
+        	r3.fd = dataInput.readCard8();
+        	fdselect.range3[i] = r3;
+
+        }
+
+        fdselect.sentinel = dataInput.readCard16();
+        return fdselect;
+    }
+    
+    /**
+     *  Container of a Format 3 FDSelect data (see "The Compact Font Format Specification" chapter "FDSelect" ) 
+     */
+    private static class Format3FDSelect extends CIDKeyedFDSelect {
+        private int format;
+        private int nbRanges;
+        private Range3[] range3;
+        private int sentinel;
+
+        private Format3FDSelect(CFFFontROS _owner) {
+			super(_owner);
+		}
+
+		/* (non-Javadoc)
+		 * @see org.apache.fontbox.cff.CIDKeyedFDSelect#getFd(int)
+		 */
+		@Override
+		public int getFd(int glyph) {
+			for (int i = 0 ; i < nbRanges; ++i) {
+				if (range3[i].first >= glyph) {
+					if (i + 1 < nbRanges ) {
+						if (range3[i+1].first > glyph ) {
+							return range3[i].fd;
+						} else {
+							// go to next range
+						}
+					} else {
+						// last range reach, the sentinel must be greater than glyph
+						if (sentinel > glyph) {
+							return range3[i].fd;
+						}  else {
+							return -1;
+						}
+					}
+				}
+			}
+			return 0;
+		}
+
+		@Override
+        public String toString()
+        {
+            return getClass().getName() + "[format=" + format + " nbRanges=" + nbRanges + ", range3="
+                    + Arrays.toString(range3) + " sentinel=" + sentinel + "]";
+        }
+    }
+
+    /**
+     * Structure of a Range3 element
+     */
+    private static class Range3 {
+    	private int first;
+    	private int fd;
+    	
+    	@Override
+        public String toString() {
+    		return getClass().getName() + "[first=" + first + ", fd=" + fd + "]";
+    	}
+    }
+    
+    /**
+     *  Container of a Format 0 FDSelect data (see "The Compact Font Format Specification" chapter "FDSelect" ) 
+     */
+    private static class Format0FDSelect extends CIDKeyedFDSelect {
+        private int format;
+        private int[] fds;
+
+        private Format0FDSelect(CFFFontROS _owner) {
+			super(_owner);
+		}
+
+		/* (non-Javadoc)
+		 * @see org.apache.fontbox.cff.CIDKeyedFDSelect#getFd(int)
+		 */
+		@Override
+		public int getFd(int glyph) {
+			// ---- search the position of the given glyph
+			for (Mapping mapping: this.owner.getMappings()) {
+				if (mapping.getSID() == glyph) {
+					int index = 0;
+					Map<String, byte[]> charString = this.owner.getCharStringsDict();
+					Set<String> keys = charString.keySet();
+					for (String str : keys) {
+						if (mapping.getName().equals(str)) {
+							return fds[index];
+						}
+						++index;
+					}
+				}
+			}
+
+			return -1;
+		}
+
+		@Override
+        public String toString()
+        {
+            return getClass().getName() + "[format=" + format + ", fds="
+                    + Arrays.toString(fds) + "]";
+        }
+    }
+    
     private CFFCharset readCharset(CFFDataInput dataInput, int nGlyphs)
             throws IOException
     {
@@ -506,6 +786,10 @@
         {
             return readFormat1Charset(dataInput, format, nGlyphs);
         } 
+        else if (format == 2)
+        {
+            return readFormat2Charset(dataInput, format, nGlyphs);
+        }
         else
         {
             throw new IllegalArgumentException();
@@ -551,6 +835,31 @@
         return charset;
     }
 
+    private Format2Charset readFormat2Charset(CFFDataInput dataInput, int format,
+            int nGlyphs) throws IOException
+    {
+    	Format2Charset charset = new Format2Charset();
+        charset.format = format;
+        charset.range = new Format2Charset.Range2[0];
+        for (int i = 0; i < nGlyphs - 1;)
+        {
+        	Format2Charset.Range2[] newRange = new Format2Charset.Range2[charset.range.length + 1];
+            System.arraycopy(charset.range, 0, newRange, 0,
+                    charset.range.length);
+            charset.range = newRange;
+            Format2Charset.Range2 range = new Format2Charset.Range2();
+            range.first = dataInput.readSID();
+            range.nLeft = dataInput.readCard16();
+            charset.range[charset.range.length - 1] = range;
+            for (int j = 0; j < 1 + range.nLeft; j++)
+            {
+                charset.register(range.first + j, readString(range.first + j));
+            }
+            i += 1 + range.nLeft;
+        }
+        return charset;
+    }
+
     /**
      * Inner class holding the header of a CFF font. 
      */
@@ -704,7 +1013,7 @@
     /**
      * Inner class representing an embedded CFF encoding. 
      */
-    private abstract static class EmbeddedEncoding extends CFFEncoding
+    abstract static class EmbeddedEncoding extends CFFEncoding
     {
 
         private int nSups;
@@ -716,14 +1025,30 @@
             return true;
         }
 
+        List<Supplement> getSupplements()
+        {
+            if(supplement == null){
+                return Collections.<Supplement>emptyList();
+            }
+            return Arrays.asList(supplement);
+        }
+
         /**
          * Inner class representing a supplement for an encoding. 
          */
-        private static class Supplement
+        static class Supplement
         {
             private int code;
             private int glyph;
 
+            int getCode(){
+                return code;
+            }
+
+            int getGlyph(){
+                return glyph;
+            }
+
             @Override
             public String toString()
             {
@@ -788,7 +1113,7 @@
     /**
      * Inner class representing an embedded CFF charset. 
      */
-    private abstract static class EmbeddedCharset extends CFFCharset
+    abstract static class EmbeddedCharset extends CFFCharset
     {
         @Override
         public boolean isFontSpecific()
@@ -844,4 +1169,36 @@
             }
         }
     }
+
+    /**
+     * Inner class representing a Format2 charset. 
+     */
+    private static class Format2Charset extends EmbeddedCharset
+    {
+        private int format;
+        private Range2[] range;
+
+        @Override
+        public String toString()
+        {
+            return getClass().getName() + "[format=" + format + ", range="
+                    + Arrays.toString(range) + "]";
+        }
+
+        /**
+         * Inner class representing a range of a charset. 
+         */
+        private static class Range2
+        {
+            private int first;
+            private int nLeft;
+
+            @Override
+            public String toString()
+            {
+                return getClass().getName() + "[first=" + first + ", nLeft="
+                        + nLeft + "]";
+            }
+        }
+    }
 }
\ Pas de fin de ligne à la fin du fichier.
diff -b -r -N --unified fontbox-1.0.0/src/main/java/org/apache/fontbox/cff/charset/CFFCharset.java fontbox/src/main/java/org/apache/fontbox/cff/charset/CFFCharset.java
--- fontbox-1.0.0/src/main/java/org/apache/fontbox/cff/charset/CFFCharset.java	2010-02-26 18:04:51.000000000 +0100
+++ fontbox/src/main/java/org/apache/fontbox/cff/charset/CFFCharset.java	2010-03-16 15:22:10.000000000 +0100
@@ -23,7 +23,7 @@
  * This is the superclass for all CFFFont charsets.
  * 
  * @author Villu Russmann
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.2 $
  */
 public abstract class CFFCharset
 {
@@ -92,7 +92,7 @@
     }
 
     /**
-     * This class represents a single name/SID mapping of the charset.
+     * This class represents a single SID/name mapping of the charset.
      *
      */
     public static class Entry
diff -b -r -N --unified fontbox-1.0.0/src/main/java/org/apache/fontbox/cff/CharStringRenderer.java fontbox/src/main/java/org/apache/fontbox/cff/CharStringRenderer.java
--- fontbox-1.0.0/src/main/java/org/apache/fontbox/cff/CharStringRenderer.java	2010-02-26 18:04:51.000000000 +0100
+++ fontbox/src/main/java/org/apache/fontbox/cff/CharStringRenderer.java	2010-03-19 14:56:26.000000000 +0100
@@ -24,16 +24,27 @@
 /**
  * This class represents a renderer for a charstring.
  * @author Villu Russmann
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.2 $
  */
 public class CharStringRenderer extends CharStringHandler
 {
+	// TODO CharStringRenderer as abstract Class with two inherited classes according to the Charsstring type....
+	private boolean isCharstringType1 = true;
+	private boolean isFirstCommand = true;
 
     private GeneralPath path = null;
     private Point2D sidebearingPoint = null;
     private Point2D referencePoint = null;
     private int width = 0;
 
+	public CharStringRenderer() {
+		isCharstringType1 = true;
+	}
+
+	public CharStringRenderer(boolean isType1) {
+		isCharstringType1 = isType1;
+	}
+
     /**
      * Renders the given sequence and returns the result as a GeneralPath.
      * @param sequence the given charstring sequence
@@ -54,6 +65,157 @@
      */
     public void handleCommand(List<Integer> numbers, CharStringCommand command)
     {
+		if (isCharstringType1) {
+			handleCommandType1(numbers, command);
+		} else {
+			handleCommandType2(numbers, command);
+		}
+	}
+
+	/**
+	 * 
+	 * @param numbers
+	 * @param command
+	 */
+	private void handleCommandType2(List<Integer> numbers, CharStringCommand command) {
+		String name = CharStringCommand.TYPE2_VOCABULARY.get(command.getKey());
+
+		if ("vmoveto".equals(name)) //
+		{
+			if (isFirstCommand && numbers.size() == 2) {
+				setWidth(numbers.get(0));
+				rmoveTo(Integer.valueOf(0), numbers.get(1));	 
+			} else {
+				rmoveTo(Integer.valueOf(0), numbers.get(0));
+			}
+		} 
+		else if ("rlineto".equals(name)) //
+		{
+			if (isFirstCommand && numbers.size() == 3) {
+				setWidth(numbers.get(0));
+				rlineTo(numbers.get(1), numbers.get(2));
+			} else {
+				rlineTo(numbers.get(0), numbers.get(1));
+			}
+		} 
+		else if ("hlineto".equals(name))//
+		{
+			if (isFirstCommand && numbers.size() == 2) {
+				setWidth(numbers.get(0));	
+				rlineTo(numbers.get(1), Integer.valueOf(0));	
+			} else {
+				rlineTo(numbers.get(0), Integer.valueOf(0));
+			}
+		} 
+		else if ("vlineto".equals(name))//
+		{
+			if (isFirstCommand && numbers.size() == 2) {
+				setWidth(numbers.get(0));
+				rlineTo(Integer.valueOf(0), numbers.get(1));
+			} else {
+				rlineTo(Integer.valueOf(0), numbers.get(0));
+			}
+		} 
+		else if ("rrcurveto".equals(name))//
+		{
+			if (isFirstCommand && numbers.size() == 7) {
+				setWidth(numbers.get(0));
+				rrcurveTo(numbers.get(1), numbers.get(2), numbers.get(3), numbers
+						.get(4), numbers.get(5), numbers.get(6));
+			} else {
+				rrcurveTo(numbers.get(0), numbers.get(1), numbers.get(2), numbers
+						.get(3), numbers.get(4), numbers.get(5));
+			}
+		}
+		else if ("closepath".equals(name))
+		{
+			closePath();
+		} 
+		else if ("rmoveto".equals(name))//
+		{
+			if (isFirstCommand && numbers.size() == 3) {
+				setWidth(numbers.get(0));
+				rmoveTo(numbers.get(1), numbers.get(2));
+			} else {
+				rmoveTo(numbers.get(0), numbers.get(1));
+			}
+		} 
+		else if ("hmoveto".equals(name)) //
+		{
+			if (isFirstCommand && numbers.size() == 2) {
+				setWidth(numbers.get(0));
+				rmoveTo(numbers.get(1), Integer.valueOf(0));
+			} else { 
+				rmoveTo(numbers.get(0), Integer.valueOf(0));
+			}        	
+		} 
+		else if ("vhcurveto".equals(name))
+		{
+			if (isFirstCommand && numbers.size() == 5) {
+				setWidth(numbers.get(0));
+				rrcurveTo(Integer.valueOf(0), numbers.get(1), numbers.get(2),
+						numbers.get(3), numbers.get(4), Integer.valueOf(0));
+			} else {
+				rrcurveTo(Integer.valueOf(0), numbers.get(0), numbers.get(1),
+						numbers.get(2), numbers.get(3), Integer.valueOf(0));
+			}
+
+		} 
+		else if ("hvcurveto".equals(name))
+		{
+			if (isFirstCommand && numbers.size() == 5) {
+				setWidth(numbers.get(0));            
+				rrcurveTo(numbers.get(1), Integer.valueOf(0), numbers.get(2),
+						numbers.get(3), Integer.valueOf(0), numbers.get(4));
+			} else {
+				rrcurveTo(numbers.get(0), Integer.valueOf(0), numbers.get(1),
+						numbers.get(2), Integer.valueOf(0), numbers.get(3));
+			}
+		}
+		else if ("hstem".equals(name)) {
+			if (numbers.size() % 2 == 1 ) {
+				setWidth(numbers.get(0));
+			}
+		}
+		else if ("vstem".equals(name)) {
+			if (numbers.size() % 2 == 1 ) {
+				setWidth(numbers.get(0));
+			}	
+		}
+		else if ("hstemhm".equals(name)) {
+			if (numbers.size() % 2 == 1 ) {
+				setWidth(numbers.get(0));
+			}
+		}
+		else if ("hstemhm".equals(name)) {
+			if (numbers.size() % 2 == 1) {
+				setWidth(numbers.get(0));
+			}
+		}
+		else if ("cntrmask".equals(name)) {
+			if (numbers.size() == 1 ) {
+				setWidth(numbers.get(0));
+			}
+		}
+		else if ("hintmask".equals(name)) {
+			if (numbers.size() == 1 ) {
+				setWidth(numbers.get(0));
+			}
+		}else if ("endchar".equals(name)) {
+			if (numbers.size() == 1 ) {
+				setWidth(numbers.get(0));
+			}
+		}
+
+		if (isFirstCommand) {  isFirstCommand = false; }
+	}
+
+	/**
+	 * 
+	 * @param numbers
+	 * @param command
+	 */
+	private void handleCommandType1(List<Integer> numbers, CharStringCommand command) {
         String name = CharStringCommand.TYPE1_VOCABULARY.get(command.getKey());
 
         if ("vmoveto".equals(name))
diff -b -r -N --unified fontbox-1.0.0/src/main/java/org/apache/fontbox/cff/CIDKeyedFDSelect.java fontbox/src/main/java/org/apache/fontbox/cff/CIDKeyedFDSelect.java
--- fontbox-1.0.0/src/main/java/org/apache/fontbox/cff/CIDKeyedFDSelect.java	1970-01-01 01:00:00.000000000 +0100
+++ fontbox/src/main/java/org/apache/fontbox/cff/CIDKeyedFDSelect.java	2010-03-19 14:56:26.000000000 +0100
@@ -0,0 +1,17 @@
+package org.apache.fontbox.cff;
+
+public abstract class CIDKeyedFDSelect {
+	
+	protected CFFFontROS owner = null;
+	
+	public CIDKeyedFDSelect(CFFFontROS _owner) {
+		this.owner = _owner;
+	}
+	/**
+	 * Returns the Font DICT index for the given glyph identifier
+	 *  
+	 * @param glyph
+	 * @return -1 if the glyph isn't define, otherwise the FD index value
+	 */
+	public abstract int getFd(int glyph);
+}
diff -b -r -N --unified fontbox-1.0.0/src/main/java/org/apache/fontbox/cff/encoding/CFFEncoding.java fontbox/src/main/java/org/apache/fontbox/cff/encoding/CFFEncoding.java
--- fontbox-1.0.0/src/main/java/org/apache/fontbox/cff/encoding/CFFEncoding.java	2010-02-26 18:04:51.000000000 +0100
+++ fontbox/src/main/java/org/apache/fontbox/cff/encoding/CFFEncoding.java	2010-03-16 15:22:10.000000000 +0100
@@ -16,20 +16,19 @@
  */
 package org.apache.fontbox.cff.encoding;
 
-import java.util.HashMap;
-import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * This is the superclass for all CFFFont encodings.
  * 
  * @author Villu Russmann
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.2 $
  */
 public abstract class CFFEncoding
 {
 
-    private static HashMap<Integer,Integer> code2sid = new HashMap<Integer,Integer>();
-    private static HashMap<Integer,Integer> sid2code = new HashMap<Integer,Integer>();
+    private List<Entry> entries = new ArrayList<Entry>();
 
     /**
      * Determines if the encoding is font specific or not.
@@ -47,9 +46,12 @@
      */
     public int getCode(int sid)
     {
-        if (sid2code.containsKey(sid)) 
+        for(Entry entry : entries)
         {
-            return sid2code.get(sid);
+            if(entry.entrySID == sid)
+            {
+                return entry.entryCode;
+            }
         }
         return -1;
     }
@@ -61,9 +63,12 @@
      */
     public int getSID(int code)
     {
-        if (code2sid.containsKey(code)) 
+        for(Entry entry : entries)
         {
-            return code2sid.get(code);
+            if(entry.entryCode == code)
+            {
+                return entry.entrySID;
+            }
         }
         return -1;
     }
@@ -75,18 +80,62 @@
      */
     public void register(int code, int sid)
     {
-        // TODO check if mapping already exists
-        sid2code.put(sid,code);
-        code2sid.put(code,sid);
+        entries.add(new Entry(code, sid));
     }
 
     /**
-     * Returns an iterator for all codes of this encoding.
+     * A list of all entries within this encoding.
+     * @return a list of all entries
+     */
+    public List<Entry> getEntries()
+    {
+        return entries;
+    }
+
+    /**
+     * This class represents a single code/SID mapping of the encoding.
      * 
-     * @return the iterator for all codes of this encoding
      */
-    public Iterator<Integer> getCodes() 
+    public static class Entry
     {
-        return code2sid.keySet().iterator();
+        private int entryCode;
+        private int entrySID;
+
+        /**
+         * Create a new instance of Entry with the given values.
+         * @param code the code
+         * @param sid the SID
+         */
+        protected Entry(int code, int sid)
+        {
+            this.entryCode = code;
+            this.entrySID = sid;
+        }
+
+        /**
+         * The code of the entry.
+         * @return the code
+         */
+        public int getCode()
+        {
+            return this.entryCode;
+        }
+
+        /**
+         * The SID of the entry.
+         * @return the SID
+         */
+        public int getSID()
+        {
+            return this.entrySID;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public String toString()
+        {
+            return "[code=" + entryCode + ", sid=" + entrySID + "]";
+        }
     }
 }
\ Pas de fin de ligne à la fin du fichier.
diff -b -r -N --unified fontbox-1.0.0/src/main/java/org/apache/fontbox/cmap/CMap.java fontbox/src/main/java/org/apache/fontbox/cmap/CMap.java
--- fontbox-1.0.0/src/main/java/org/apache/fontbox/cmap/CMap.java	2010-03-01 15:18:48.000000000 +0100
+++ fontbox/src/main/java/org/apache/fontbox/cmap/CMap.java	2010-03-01 15:24:32.000000000 +0100
@@ -28,7 +28,7 @@
  * This class represents a CMap file.
  *
  * @author Ben Litchfield (ben@benlitchfield.com)
- * @version $Revision: 1.2 $
+ * @version $Revision: 1.3 $
  */
 public class CMap
 {
@@ -36,6 +36,8 @@
     private Map<Integer,String> singleByteMappings = new HashMap<Integer,String>();
     private Map<Integer,String> doubleByteMappings = new HashMap<Integer,String>();
 
+    private Map<String, Object> cmapEntries = new HashMap<String, Object>();
+    
     /**
      * Creates a new instance of CMap.
      */
@@ -191,4 +193,19 @@
         }
         return false;
      }
+   
+
+	/**
+	 * @return the cmapEntries
+	 */
+	public Object getCmapEntry(String name) {
+		return cmapEntries.get(name);
+	}
+
+	/**
+	 * @param cmapEntries the cmapEntries to set
+	 */
+	public void addCMapEntry(String name, Object value) {
+		this.cmapEntries.put(name, value);
+	}
 }
\ Pas de fin de ligne à la fin du fichier.
diff -b -r -N --unified fontbox-1.0.0/src/main/java/org/apache/fontbox/cmap/CMapParser.java fontbox/src/main/java/org/apache/fontbox/cmap/CMapParser.java
--- fontbox-1.0.0/src/main/java/org/apache/fontbox/cmap/CMapParser.java	2010-03-01 15:18:48.000000000 +0100
+++ fontbox/src/main/java/org/apache/fontbox/cmap/CMapParser.java	2010-03-01 15:24:32.000000000 +0100
@@ -33,7 +33,7 @@
  * This will parser a CMap stream.
  *
  * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
- * @version $Revision: 1.2 $
+ * @version $Revision: 1.3 $
  */
 public class CMapParser
 {
@@ -203,6 +203,11 @@
                         }
                     }
                 }
+            } else {
+            	if (previousToken != null && previousToken instanceof LiteralName) {
+            		String name = ((LiteralName)previousToken).name;
+            		result.addCMapEntry(name, token instanceof LiteralName ? ((LiteralName)token).name : token);
+            	}
             }
             previousToken = token;
         }
diff -b -r -N --unified fontbox-1.0.0/src/main/java/org/apache/fontbox/encoding/MacRomanEncoding.java fontbox/src/main/java/org/apache/fontbox/encoding/MacRomanEncoding.java
--- fontbox-1.0.0/src/main/java/org/apache/fontbox/encoding/MacRomanEncoding.java	2010-02-26 18:04:51.000000000 +0100
+++ fontbox/src/main/java/org/apache/fontbox/encoding/MacRomanEncoding.java	2010-04-21 18:37:17.000000000 +0200
@@ -20,7 +20,7 @@
  * This is an interface to a text encoder.
  *
  * @author Ben Litchfield
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.2 $
  */
 public class MacRomanEncoding extends Encoding
 {
@@ -116,7 +116,7 @@
         addCharacterEncoding( 072, "colon" );
         addCharacterEncoding( 054, "comma" );
         addCharacterEncoding( 0251, "copyright" );
-        addCharacterEncoding( 0333, "currency1" );
+        addCharacterEncoding( 0333, "currency" );
         addCharacterEncoding( 0144, "d" );
         addCharacterEncoding( 0240, "dagger" );
         addCharacterEncoding( 0340, "daggerdbl" );
diff -b -r -N --unified fontbox-1.0.0/src/main/java/org/apache/fontbox/ttf/AbstractTTFParser.java fontbox/src/main/java/org/apache/fontbox/ttf/AbstractTTFParser.java
--- fontbox-1.0.0/src/main/java/org/apache/fontbox/ttf/AbstractTTFParser.java	1970-01-01 01:00:00.000000000 +0100
+++ fontbox/src/main/java/org/apache/fontbox/ttf/AbstractTTFParser.java	2010-04-26 18:30:37.000000000 +0200
@@ -0,0 +1,145 @@
+package org.apache.fontbox.ttf;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+abstract class AbstractTTFParser {
+	protected boolean isEmbedded = false;
+
+	public AbstractTTFParser(boolean isEmbedded) {
+		this.isEmbedded = isEmbedded;
+	}
+	
+    /**
+     * Parse a file and get a true type font.
+     * @param ttfFile The TTF file.
+     * @return A true type font.
+     * @throws IOException If there is an error parsing the true type font.
+     */
+    public TrueTypeFont parseTTF( String ttfFile ) throws IOException
+    {
+        RAFDataStream raf = new RAFDataStream( ttfFile, "r" );
+        return parseTTF( raf );
+    }
+    
+    /**
+     * Parse a file and get a true type font.
+     * @param ttfFile The TTF file.
+     * @return A true type font.
+     * @throws IOException If there is an error parsing the true type font.
+     */
+    public TrueTypeFont parseTTF( File ttfFile ) throws IOException
+    {
+        RAFDataStream raf = new RAFDataStream( ttfFile, "r" );
+        return parseTTF( raf );
+    }
+    
+    /**
+     * Parse a file and get a true type font.
+     * @param ttfData The TTF data to parse.
+     * @return A true type font.
+     * @throws IOException If there is an error parsing the true type font.
+     */
+    public TrueTypeFont parseTTF( InputStream ttfData ) throws IOException
+    {
+        return parseTTF( new MemoryTTFDataStream( ttfData ));
+    }
+    
+    /**
+     * Parse a file and get a true type font.
+     * @param raf The TTF file.
+     * @return A true type font.
+     * @throws IOException If there is an error parsing the true type font.
+     */
+    public TrueTypeFont parseTTF( TTFDataStream raf ) throws IOException
+    {
+        TrueTypeFont font = new TrueTypeFont( raf );
+        font.setVersion( raf.read32Fixed() );
+        int numberOfTables = raf.readUnsignedShort();
+        int searchRange = raf.readUnsignedShort();
+        int entrySelector = raf.readUnsignedShort();
+        int rangeShift = raf.readUnsignedShort();
+        for( int i=0; i<numberOfTables; i++ )
+        {
+            TTFTable table = readTableDirectory( raf );   
+            font.addTable( table );
+        }
+
+        //need to initialize a couple tables in a certain order
+        parseTables(font, raf);
+
+        return font;
+    }
+
+    protected abstract void parseTables(TrueTypeFont font, TTFDataStream raf)
+    throws IOException ;
+
+    private TTFTable readTableDirectory( TTFDataStream raf ) throws IOException
+    {
+        TTFTable retval = null;
+        String tag = raf.readString( 4 );
+        if( tag.equals( CMAPTable.TAG ) )
+        {
+            retval = new CMAPTable();
+        }
+        else if( tag.equals( GlyphTable.TAG ) )
+        {
+            retval = new GlyphTable();
+        }
+        else if( tag.equals( HeaderTable.TAG ) )
+        {
+            retval = new HeaderTable();
+        }
+        else if( tag.equals( HorizontalHeaderTable.TAG ) )
+        {
+            retval = new HorizontalHeaderTable();
+        }
+        else if( tag.equals( HorizontalMetricsTable.TAG ) )
+        {
+            retval = new HorizontalMetricsTable();
+        }
+        else if( tag.equals( IndexToLocationTable.TAG ) )
+        {
+            retval = new IndexToLocationTable();
+        }
+        else if( tag.equals( MaximumProfileTable.TAG ) )
+        {
+            retval = new MaximumProfileTable();
+        }
+        else if( tag.equals( NamingTable.TAG ) )
+        {
+            retval = new NamingTable();
+        }
+        else if( tag.equals( OS2WindowsMetricsTable.TAG ) )
+        {
+            retval = new OS2WindowsMetricsTable();
+        }
+        else if( tag.equals( PostScriptTable.TAG ) )
+        {
+            retval = new PostScriptTable();
+        }
+        else if( tag.equals( GlyphTable.TAG ) )
+        {
+            retval = new GlyphTable();
+        }
+        else if( tag.equals( GlyphTable.TAG ) )
+        {
+            retval = new GlyphTable();
+        }
+        else if( tag.equals( DigitalSignatureTable.TAG ) )
+        {
+            retval = new DigitalSignatureTable();
+        }
+        else
+        {
+            //unknown table type but read it anyway.
+            retval = new TTFTable();
+        }
+        retval.setTag( tag );
+        retval.setCheckSum( raf.readUnsignedInt() );
+        retval.setOffset( raf.readUnsignedInt() );
+        retval.setLength( raf.readUnsignedInt() );
+        return retval;
+    }
+}
diff -b -r -N --unified fontbox-1.0.0/src/main/java/org/apache/fontbox/ttf/CIDFontType2Parser.java fontbox/src/main/java/org/apache/fontbox/ttf/CIDFontType2Parser.java
--- fontbox-1.0.0/src/main/java/org/apache/fontbox/ttf/CIDFontType2Parser.java	1970-01-01 01:00:00.000000000 +0100
+++ fontbox/src/main/java/org/apache/fontbox/ttf/CIDFontType2Parser.java	2010-04-26 18:30:37.000000000 +0200
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.fontbox.ttf;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class CIDFontType2Parser extends AbstractTTFParser
+{   
+	public CIDFontType2Parser() {
+		super(false);
+	}
+
+	public CIDFontType2Parser(boolean isEmbedded) {
+		super(isEmbedded);
+	}
+
+	protected void parseTables(TrueTypeFont font, TTFDataStream raf) 
+	throws IOException {
+		List<TTFTable> initialized = new ArrayList<TTFTable>();
+		HeaderTable head = font.getHeader();
+		if (head == null) {
+			throw new IOException("head is mandatory");
+		}
+		raf.seek( head.getOffset() );
+		head.initData( font, raf );
+		initialized.add( head );
+
+		HorizontalHeaderTable hh = font.getHorizontalHeader();
+		if (hh == null) {
+			throw new IOException("hhead is mandatory");
+		}
+		raf.seek( hh.getOffset() );
+		hh.initData( font, raf );
+		initialized.add( hh );
+
+		MaximumProfileTable maxp = font.getMaximumProfile();
+		if (maxp != null) {
+			raf.seek( maxp.getOffset() );
+			maxp.initData( font, raf );
+			initialized.add( maxp );
+		} else {
+			throw new IOException("maxp is mandatory");
+		}
+
+		PostScriptTable post = font.getPostScript();
+		if (post != null) {
+			raf.seek( post.getOffset() );
+			post.initData( font, raf );
+			initialized.add( post );
+		} else if ( !isEmbedded ) {
+			// in an embedded font this table is optional
+			throw new IOException("post is mandatory");
+		}
+
+		IndexToLocationTable loc = font.getIndexToLocation();
+		if (loc == null) {
+			throw new IOException("loca is mandatory");
+		}
+		raf.seek( loc.getOffset() );
+		loc.initData( font, raf );
+		initialized.add( loc );
+
+		boolean cvt = false, prep = false, fpgm = false;
+		Iterator<TTFTable> iter = font.getTables().iterator();
+		while( iter.hasNext() )
+		{
+			TTFTable table = iter.next();
+			if( !initialized.contains( table ) )
+			{
+				raf.seek( table.getOffset() );
+				table.initData( font, raf );
+			}
+			if (table.getTag().startsWith("cvt")) {
+				cvt = true;
+			} else if ("prep".equals(table.getTag())) {
+				prep = true;
+			} else if ("fpgm".equals(table.getTag())) {
+				fpgm = true;
+			}
+		}   
+
+		// check others mandatory tables
+		if ( font.getGlyph() == null ){
+			throw new IOException("glyf is mandatory");
+		}
+		if ( font.getNaming() == null && !isEmbedded ){
+			throw new IOException("name is mandatory");
+		}
+		if ( font.getHorizontalMetrics() == null ){
+			throw new IOException("hmtx is mandatory");
+		}
+
+		if (isEmbedded) {
+			// in a embedded truetype font prep, cvt_ and fpgm tables 
+			// are mandatory
+			if (!fpgm) throw new IOException("fpgm is mandatory");
+			if (!prep) throw new IOException("prep is mandatory");
+			if (!cvt) throw new IOException("cvt_ is mandatory");
+		}
+	}
+}
\ Pas de fin de ligne à la fin du fichier.
diff -b -r -N --unified fontbox-1.0.0/src/main/java/org/apache/fontbox/ttf/CMAPEncodingEntry.java fontbox/src/main/java/org/apache/fontbox/ttf/CMAPEncodingEntry.java
--- fontbox-1.0.0/src/main/java/org/apache/fontbox/ttf/CMAPEncodingEntry.java	2010-02-26 18:04:51.000000000 +0100
+++ fontbox/src/main/java/org/apache/fontbox/ttf/CMAPEncodingEntry.java	2010-04-26 18:30:37.000000000 +0200
@@ -17,12 +17,14 @@
 package org.apache.fontbox.ttf;
 
 import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * An encoding entry for a cmap.
  * 
  * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.6 $
  */
 public class CMAPEncodingEntry
 {
@@ -30,7 +32,10 @@
     private int platformId;
     private int platformEncodingId;
     private long subTableOffset;
+
     private int[] glyphIdToCharacterCode;
+	private Map<Integer, Integer> characterCodeToGlyphId = new HashMap<Integer, Integer>();
+
     /**
      * This will read the required data from the stream.
      * 
@@ -56,37 +61,278 @@
     {
         data.seek( ttf.getCMAP().getOffset() + subTableOffset );
         int subtableFormat = data.readUnsignedShort();
-        int length = data.readUnsignedShort();
-        int version = data.readUnsignedShort();
-        int numGlyphs = ttf.getMaximumProfile().getNumGlyphs();
-        if( subtableFormat == 0 )
-        {
-            byte[] glyphMapping = data.read( 256 );
-            glyphIdToCharacterCode = new int[256];
-            for( int i=0;i<glyphMapping.length; i++ )
+		long length;
+		long version;
+		int numGlyphs;
+		if (subtableFormat < 8) {
+			length = data.readUnsignedShort();
+			version = data.readUnsignedShort();
+			numGlyphs = ttf.getMaximumProfile().getNumGlyphs();
+		} else {
+			// read an other UnsignedShort to read a Fixed32
+			data.readUnsignedShort();
+			length = data.readUnsignedInt();
+			version = data.readUnsignedInt();
+			numGlyphs = ttf.getMaximumProfile().getNumGlyphs();			
+		}
+
+		switch (subtableFormat) {
+		case 0:
+			processSubtype0(ttf, data);
+			break;
+		case 2:
+			processSubtype2(ttf, data, numGlyphs);
+			break;
+		case 4:
+			processSubtype4(ttf, data, numGlyphs);
+			break;
+		case 6:
+			processSubtype6(ttf, data, numGlyphs);
+			break;
+		case 8:
+			processSubtype8(ttf, data, numGlyphs);
+			break;
+		case 10:
+			processSubtype10(ttf, data, numGlyphs);
+			break;
+		case 12:
+			processSubtype12(ttf, data, numGlyphs);
+			break;
+		case 13:
+			processSubtype13(ttf, data, numGlyphs);	
+			break;
+		case 14:
+			processSubtype14(ttf, data, numGlyphs);
+			break;
+		default:
+			throw new IOException( "Unknown cmap format:" + subtableFormat );	
+		}
+	}
+
+	/**
+	 * 
+	 * @param ttf
+	 * @param data
+	 * @param numGlyphs
+	 * @throws IOException
+	 */
+	protected void processSubtype8( TrueTypeFont ttf, TTFDataStream data, int numGlyphs ) 
+	throws IOException {
+		// --- is32 is a 65536 BITS array ( = 8192 BYTES) 
+		int[] is32 = data.readUnsignedByteArray(8192);
+		long nbGroups = data.readUnsignedInt();
+
+		// --- nbGroups shouldn't be greater than 65536
+		if (nbGroups > 65536) {
+			throw new IOException("CMap ( Subtype8 ) is invalid");
+		}
+
+		glyphIdToCharacterCode = new int[numGlyphs];
+		// -- Read all sub header
+		for (long i = 0; i <= nbGroups ; ++i ) 
             {
-                glyphIdToCharacterCode[i]=(glyphMapping[i]+256)%256;
+			long firstCode = data.readUnsignedInt();
+			long endCode = data.readUnsignedInt();
+			long startGlyph = data.readUnsignedInt();
+
+			// -- process simple validation
+			if (firstCode > endCode || 0 > firstCode) {
+				throw new IOException("Range invalid");
+			}
+
+			for (long j = firstCode; j <= endCode; ++j) {
+				// -- Convert the Character code in decimal
+				if (j > Integer.MAX_VALUE) {
+					throw new IOException("[Sub Format 8] Invalid Character code");
+				}
+
+				int currentCharCode;
+				if ( (is32[ (int)j / 8 ] & (1 << ((int)j % 8 ))) == 0) {
+					currentCharCode = (int)j;
+				} else {
+					// the character code uses a 32bits format 
+					// convert it in decimal : see http://www.unicode.org/faq//utf_bom.html#utf16-4
+					long LEAD_OFFSET = 0xD800 - (0x10000 >> 10);
+				    long SURROGATE_OFFSET = 0x10000 - (0xD800 << 10) - 0xDC00;
+				    long lead = LEAD_OFFSET + (j >> 10);
+				    long trail = 0xDC00 + (j & 0x3FF);
+
+				    long codepoint = (lead << 10) + trail + SURROGATE_OFFSET;
+				    if (codepoint > Integer.MAX_VALUE) {
+						throw new IOException("[Sub Format 8] Invalid Character code");
+					}
+				    currentCharCode = (int)codepoint;
+				}
+
+				long glyphIndex = startGlyph + (j-firstCode);
+				if (glyphIndex > numGlyphs || glyphIndex > Integer.MAX_VALUE) {
+					throw new IOException("CMap contains an invalid glyph index");
+				}
+
+				glyphIdToCharacterCode[(int)glyphIndex] = currentCharCode;
+				characterCodeToGlyphId.put(currentCharCode, (int)glyphIndex);
+			}
+		}
+	}
+
+	/**
+	 * 
+	 * @param ttf
+	 * @param data
+	 * @param numGlyphs
+	 * @throws IOException
+	 */
+	protected void processSubtype10( TrueTypeFont ttf, TTFDataStream data, int numGlyphs ) 
+	throws IOException {
+		long startCode = data.readUnsignedInt();
+		long numChars = data.readUnsignedInt();
+		if (numChars > Integer.MAX_VALUE) {
+			throw new IOException("Invalid number of Characters");
+		}
+
+		if ( startCode < 0 || startCode > 0x0010FFFF 
+				|| (startCode + numChars) > 0x0010FFFF
+				|| ((startCode + numChars) >= 0x0000D800 && (startCode + numChars) <= 0x0000DFFF)) {
+			throw new IOException("Invalid Characters codes");
             }
+
+		glyphIdToCharacterCode = new int[numGlyphs];
+		int[] glyphs = data.readUnsignedShortArray((int)numChars);
+		for (int i = 0; i < numChars; ++i) {
+			int glyphIndex = glyphs[i];
+			if (glyphIndex > numGlyphs) {
+				throw new IOException("Invalid GlyphId");	
+			}
+			this.glyphIdToCharacterCode[glyphIndex] = (int)(startCode+i);
+			this.characterCodeToGlyphId.put((int)(startCode+i), glyphIndex);
         }
-        else if( subtableFormat == 2 )
+	}
+
+	/**
+	 * 
+	 * @param ttf
+	 * @param data
+	 * @param numGlyphs
+	 * @throws IOException
+	 */
+	protected void processSubtype12( TrueTypeFont ttf, TTFDataStream data, int numGlyphs ) 
+	throws IOException {
+		long nbGroups = data.readUnsignedInt();
+		glyphIdToCharacterCode = new int[numGlyphs];
+		for (long i = 0; i <= nbGroups ; ++i ) 
         {
-            int[] subHeaderKeys = new int[256];
-            for( int i=0; i<256; i++)
+			long firstCode = data.readUnsignedInt();
+			long endCode = data.readUnsignedInt();
+			long startGlyph = data.readUnsignedInt();
+
+			if ( firstCode < 0 || firstCode > 0x0010FFFF 
+					|| ( firstCode >= 0x0000D800 && firstCode <= 0x0000DFFF ) ) {
+				throw new IOException("Invalid Characters codes");
+			}
+			
+			if ( endCode > 0 && (endCode < firstCode || endCode > 0x0010FFFF 
+					|| ( endCode >= 0x0000D800 && endCode <= 0x0000DFFF ) ) ) {
+				throw new IOException("Invalid Characters codes");
+			}
+			
+			for (long j = 0; j <= (endCode - firstCode); ++j) {
+
+				if ( (firstCode + j) > Integer.MAX_VALUE ) {
+					throw new IOException("Character Code greater than Integer.MAX_VALUE");					
+				}
+				
+				long glyphIndex = (startGlyph + j);
+				if (glyphIndex > numGlyphs || glyphIndex > Integer.MAX_VALUE) {
+					throw new IOException("CMap contains an invalid glyph index");
+				}
+				glyphIdToCharacterCode[(int)glyphIndex] = (int)(firstCode + j);
+				characterCodeToGlyphId.put((int)(firstCode + j), (int)glyphIndex);
+			}
+		}
+	}
+
+	/**
+	 * 
+	 * @param ttf
+	 * @param data
+	 * @param numGlyphs
+	 * @throws IOException
+	 */
+	protected void processSubtype13( TrueTypeFont ttf, TTFDataStream data, int numGlyphs ) 
+	throws IOException {
+		long nbGroups = data.readUnsignedInt();
+		for (long i = 0; i <= nbGroups ; ++i ) 
             {
-                subHeaderKeys[i] = data.readUnsignedShort();
+			long firstCode = data.readUnsignedInt();
+			long endCode = data.readUnsignedInt();
+			long glyphId = data.readUnsignedInt();
+
+			if (glyphId > numGlyphs) {
+				throw new IOException("CMap contains an invalid glyph index");	
+			}
+			
+			if ( firstCode < 0 || firstCode > 0x0010FFFF 
+					|| ( firstCode >= 0x0000D800 && firstCode <= 0x0000DFFF ) ) {
+				throw new IOException("Invalid Characters codes");
+			}
+			
+			if ( endCode > 0 && (endCode < firstCode || endCode > 0x0010FFFF 
+					|| ( endCode >= 0x0000D800 && endCode <= 0x0000DFFF )) ) {
+				throw new IOException("Invalid Characters codes");
+			}
+			
+			for (long j = 0; j <= (endCode - firstCode); ++j) {
+
+				if ( (firstCode + j) > Integer.MAX_VALUE ) {
+					throw new IOException("Character Code greater than Integer.MAX_VALUE");					
+				}
+				glyphIdToCharacterCode[(int)glyphId] = (int)(firstCode + j);
+				characterCodeToGlyphId.put((int)(firstCode + j), (int)glyphId);
+			}
+		}
+	}
+
+	/**
+	 * 
+	 * @param ttf
+	 * @param data
+	 * @param numGlyphs
+	 * @throws IOException
+	 */
+	protected void processSubtype14( TrueTypeFont ttf, TTFDataStream data, int numGlyphs ) 
+	throws IOException {
+		throw new IOException("CMap subtype 14 not yet implemented");
             }
+
+	/**
+	 * 
+	 * @param ttf
+	 * @param data
+	 * @param numGlyphs
+	 * @throws IOException
+	 */
+	protected void processSubtype6( TrueTypeFont ttf, TTFDataStream data, int numGlyphs ) 
+	throws IOException {
             int firstCode = data.readUnsignedShort();
             int entryCount = data.readUnsignedShort();
-            short idDelta = data.readSignedShort();
-            int idRangeOffset = data.readUnsignedShort();
-            //BJL
-            //HMM the TTF spec is not very clear about what is suppose to
-            //happen here.  If you know please submit a patch or point
-            //me to some better documentation.
-            throw new IOException( "Not yet implemented:" + subtableFormat );
-        }
-        else if( subtableFormat == 4 )
+		glyphIdToCharacterCode = new int[numGlyphs];
+		int[] glyphIdArray = data.readUnsignedShortArray( entryCount );
+		for( int i=0; i<entryCount; i++)
         {
+			glyphIdToCharacterCode[glyphIdArray[i]] = firstCode+i;
+			characterCodeToGlyphId.put((firstCode+i), glyphIdArray[i]);
+		}
+	}
+
+	/**
+	 * 
+	 * @param ttf
+	 * @param data
+	 * @param numGlyphs
+	 * @throws IOException
+	 */
+	protected void processSubtype4( TrueTypeFont ttf, TTFDataStream data, int numGlyphs ) 
+	throws IOException {
             int segCountX2 = data.readUnsignedShort();
             int segCount = segCountX2/2;
             int searchRange = data.readUnsignedShort();
@@ -117,6 +363,7 @@
                         if( rangeOffset == 0 )
                         {
                             glyphIdToCharacterCode[ ((j+delta)%65536) ]=j;
+						characterCodeToGlyphId.put(j, ((j+delta)%65536));
                         }
                         else
                         {
@@ -133,6 +380,7 @@
                                 if( glyphIdToCharacterCode[glyphIndex] == 0 )
                                 {
                                     glyphIdToCharacterCode[glyphIndex] = j;
+										characterCodeToGlyphId.put(j, glyphIndex);
                                 }
                             }
                             
@@ -141,24 +389,82 @@
                 }
             }
         }
-        else if( subtableFormat == 6 )
+	
+	/**
+	 * 
+	 * @param ttf
+	 * @param data
+	 * @param numGlyphs
+	 * @throws IOException
+	 */
+	protected void processSubtype2( TrueTypeFont ttf, TTFDataStream data, int numGlyphs ) 
+	throws IOException {
+		int[] subHeaderKeys = new int[256];
+		// ---- keep the Max Index of the SubHeader array to know its length
+		int maxSubHeaderIndex = 0;
+		for( int i=0; i<256; i++)
+		{
+			subHeaderKeys[i] = data.readUnsignedShort();
+			maxSubHeaderIndex = Math.max(maxSubHeaderIndex, (int)(subHeaderKeys[i]/8));
+		}
+
+		// ---- Read all SubHeaders to avoid useless seek on DataSource
+		SubHeader[] subHeaders = new SubHeader[maxSubHeaderIndex + 1]; 
+		for (int i = 0; i <= maxSubHeaderIndex ; ++i ) 
         {
             int firstCode = data.readUnsignedShort();
             int entryCount = data.readUnsignedShort();
+			short idDelta = data.readSignedShort();
+			int idRangeOffset = data.readUnsignedShort();
+			subHeaders[i] = new SubHeader(firstCode, entryCount, idDelta, idRangeOffset);
+		}
+
+		long startGlyphIndexOffset = data.getCurrentPosition();
             glyphIdToCharacterCode = new int[numGlyphs];
-            int[] glyphIdArray = data.readUnsignedShortArray( entryCount );
-            for( int i=0; i<entryCount; i++)
+		for ( int i = 0; i <= maxSubHeaderIndex ; ++i )
             {
-                glyphIdToCharacterCode[glyphIdArray[i]] = firstCode+i;
+			SubHeader sh = subHeaders[i];
+			int firstCode = sh.getFirstCode();
+			for ( int j = 0 ; j < sh.getEntryCount() ; ++j)
+			{
+				// ---- compute the Character Code
+				int charCode = ( i * 8 );
+				charCode = (charCode << 8 ) + (firstCode + j);
+
+				// ---- Go to the CharacterCOde position in the Sub Array 
+				// 		of the glyphIndexArray 
+				// 		glyphIndexArray contains Unsigned Short so add (j * 2) bytes 
+				//      at the index position
+				data.seek(startGlyphIndexOffset + sh.getIdRangeOffset() + (j*2));
+				int p = data.readUnsignedShort();
+				// ---- compute the glyphIndex 
+				p = p + sh.getIdDelta() % 65536;
+
+				glyphIdToCharacterCode[p] = charCode;
+				characterCodeToGlyphId.put(charCode, p);
             }
         }
-        else
+	}
+	
+	/**
+	 * Initialize the CMapEntry when it is a subtype 0
+	 * 
+	 * @param ttf
+	 * @param data
+	 * @throws IOException
+	 */
+	protected void processSubtype0( TrueTypeFont ttf, TTFDataStream data ) 
+	throws IOException {
+		byte[] glyphMapping = data.read( 256 );
+		glyphIdToCharacterCode = new int[256];
+		for( int i=0;i < glyphMapping.length; i++ )
         {
-            throw new IOException( "Unknown cmap format:" + subtableFormat );
+			int glyphIndex = (glyphMapping[i]+256)%256;
+			glyphIdToCharacterCode[glyphIndex]=i;
+			characterCodeToGlyphId.put(i, glyphIndex);
         }
     }
     
-
     /**
      * @return Returns the glyphIdToCharacterCode.
      */
@@ -202,4 +508,73 @@
     {
         this.platformId = platformIdValue;
     }
+
+	/**
+	 * Returns the GlyphId linked with the given character code. 
+	 * @param characterCode
+	 * @return
+	 */
+	public int getGlyphId(int characterCode) {
+		if (this.characterCodeToGlyphId.containsKey(characterCode)) {
+			return this.characterCodeToGlyphId.get(characterCode);
+		} else {
+			return 0;
+		}
+	}
+
+
+	/**
+	 * Class used to manage CMap - Format 2
+	 */
+	private class SubHeader {
+
+		private int firstCode;
+		private int entryCount;
+		/**
+		 * used to compute the GlyphIndex :
+		 * P = glyphIndexArray.SubArray[pos]
+		 * GlyphIndex = P + idDelta % 65536
+		 */
+		private short idDelta;
+		/**
+		 * Number of bytes to skip to reach the firstCode in the 
+		 * glyphIndexArray 
+		 */
+		private int idRangeOffset;
+
+		private SubHeader(int firstCode, int entryCount, short idDelta, int idRangeOffset) {
+			this.firstCode = firstCode;
+			this.entryCount = entryCount;
+			this.idDelta = idDelta;
+			this.idRangeOffset = idRangeOffset;
+		}
+
+		/**
+		 * @return the firstCode
+		 */
+		private int getFirstCode() {
+			return firstCode;
+		}
+
+		/**
+		 * @return the entryCount
+		 */
+		private int getEntryCount() {
+			return entryCount;
+		}
+
+		/**
+		 * @return the idDelta
+		 */
+		private short getIdDelta() {
+			return idDelta;
+		}
+
+		/**
+		 * @return the idRangeOffset
+		 */
+		private int getIdRangeOffset() {
+			return idRangeOffset;
+		}
+	}
 }
diff -b -r -N --unified fontbox-1.0.0/src/main/java/org/apache/fontbox/ttf/GlyphTable.java fontbox/src/main/java/org/apache/fontbox/ttf/GlyphTable.java
--- fontbox-1.0.0/src/main/java/org/apache/fontbox/ttf/GlyphTable.java	2010-02-26 18:04:51.000000000 +0100
+++ fontbox/src/main/java/org/apache/fontbox/ttf/GlyphTable.java	2010-04-13 17:41:23.000000000 +0200
@@ -22,7 +22,7 @@
  * A table in a true type font.
  * 
  * @author Ben Litchfield (ben@benlitchfield.com)
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.2 $
  */
 public class GlyphTable extends TTFTable
 {
@@ -44,11 +44,11 @@
     {
         MaximumProfileTable maxp = ttf.getMaximumProfile();
         IndexToLocationTable loc = ttf.getIndexToLocation();
-        PostScriptTable post = ttf.getPostScript();
+//        PostScriptTable post = ttf.getPostScript();
         long[] offsets = loc.getOffsets();
         int numGlyphs = maxp.getNumGlyphs();
         glyphs = new GlyphData[numGlyphs];
-        String[] glyphNames = post.getGlyphNames(); 
+//        String[] glyphNames = post.getGlyphNames(); 
         for( int i=0; i<numGlyphs-1; i++ )
         {
             GlyphData glyph = new GlyphData();
diff -b -r -N --unified fontbox-1.0.0/src/main/java/org/apache/fontbox/ttf/TTFDataStream.java fontbox/src/main/java/org/apache/fontbox/ttf/TTFDataStream.java
--- fontbox-1.0.0/src/main/java/org/apache/fontbox/ttf/TTFDataStream.java	2010-02-26 18:04:51.000000000 +0100
+++ fontbox/src/main/java/org/apache/fontbox/ttf/TTFDataStream.java	2010-04-26 18:30:37.000000000 +0200
@@ -27,7 +27,7 @@
  * An interface into a data stream.
  * 
  * @author Ben Litchfield (ben@benlitchfield.com)
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.2 $
  */
 public abstract class TTFDataStream 
 {
@@ -126,6 +126,23 @@
      * Read an unsigned short array.
      * 
      * @param length The length of the array to read.
+     * @return An unsigned byte array.
+     * @throws IOException If there is an error reading the data.
+     */
+    public int[] readUnsignedByteArray( int length ) throws IOException
+    {
+        int[] array = new int[ length ];
+        for( int i=0; i<length; i++ )
+        {
+            array[i] = read();
+        }
+        return array;
+    }
+    
+    /**
+     * Read an unsigned short array.
+     * 
+     * @param length The length of the array to read.
      * @return An unsigned short array.
      * @throws IOException If there is an error reading the data.
      */
diff -b -r -N --unified fontbox-1.0.0/src/main/java/org/apache/fontbox/ttf/TTFParser.java fontbox/src/main/java/org/apache/fontbox/ttf/TTFParser.java
--- fontbox-1.0.0/src/main/java/org/apache/fontbox/ttf/TTFParser.java	2010-02-26 18:04:51.000000000 +0100
+++ fontbox/src/main/java/org/apache/fontbox/ttf/TTFParser.java	2010-04-26 18:30:37.000000000 +0200
@@ -16,22 +16,24 @@
  */
 package org.apache.fontbox.ttf;
 
-import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
 
 /**
  * A true type font file parser.
  * 
  * @author Ben Litchfield (ben@benlitchfield.com)
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.5 $
  */
-public class TTFParser
+public class TTFParser extends CIDFontType2Parser
 {   
+	public TTFParser() {
+		super(false);
+	}
+
+	public TTFParser(boolean isEmbedded) {
+		super(isEmbedded);
+	}
+
     /**
      * A simple command line program to test parsing of a TTF file. <br/>
      * usage: java org.pdfbox.ttf.TTFParser &lt;ttf-file&gt;
@@ -52,166 +54,15 @@
         System.out.println( "Font:" + font );
     }
     
-    /**
-     * Parse a file and get a true type font.
-     * @param ttfFile The TTF file.
-     * @return A true type font.
-     * @throws IOException If there is an error parsing the true type font.
-     */
-    public TrueTypeFont parseTTF( String ttfFile ) throws IOException
-    {
-        RAFDataStream raf = new RAFDataStream( ttfFile, "r" );
-        return parseTTF( raf );
-    }
     
-    /**
-     * Parse a file and get a true type font.
-     * @param ttfFile The TTF file.
-     * @return A true type font.
-     * @throws IOException If there is an error parsing the true type font.
-     */
-    public TrueTypeFont parseTTF( File ttfFile ) throws IOException
-    {
-        RAFDataStream raf = new RAFDataStream( ttfFile, "r" );
-        return parseTTF( raf );
-    }
-    
-    /**
-     * Parse a file and get a true type font.
-     * @param ttfData The TTF data to parse.
-     * @return A true type font.
-     * @throws IOException If there is an error parsing the true type font.
-     */
-    public TrueTypeFont parseTTF( InputStream ttfData ) throws IOException
-    {
-        return parseTTF( new MemoryTTFDataStream( ttfData ));
-    }
-    
-    /**
-     * Parse a file and get a true type font.
-     * @param raf The TTF file.
-     * @return A true type font.
-     * @throws IOException If there is an error parsing the true type font.
-     */
-    public TrueTypeFont parseTTF( TTFDataStream raf ) throws IOException
-    {
-        TrueTypeFont font = new TrueTypeFont( raf );
-        font.setVersion( raf.read32Fixed() );
-        int numberOfTables = raf.readUnsignedShort();
-        int searchRange = raf.readUnsignedShort();
-        int entrySelector = raf.readUnsignedShort();
-        int rangeShift = raf.readUnsignedShort();
-        for( int i=0; i<numberOfTables; i++ )
-        {
-            TTFTable table = readTableDirectory( raf );   
-            font.addTable( table );
-        }
-        List<TTFTable> initialized = new ArrayList<TTFTable>();
-        //need to initialize a couple tables in a certain order
-        HeaderTable head = font.getHeader();
-        raf.seek( head.getOffset() );
-        head.initData( font, raf );
-        initialized.add( head );
-        
-        
-        HorizontalHeaderTable hh = font.getHorizontalHeader();
-        raf.seek( hh.getOffset() );
-        hh.initData( font, raf );
-        initialized.add( hh );
-        
-        MaximumProfileTable maxp = font.getMaximumProfile();
-        raf.seek( maxp.getOffset() );
-        maxp.initData( font, raf );
-        initialized.add( maxp );
-        
-        PostScriptTable post = font.getPostScript();
-        raf.seek( post.getOffset() );
-        post.initData( font, raf );
-        initialized.add( post );
-        
-        IndexToLocationTable loc = font.getIndexToLocation();
-        raf.seek( loc.getOffset() );
-        loc.initData( font, raf );
-        initialized.add( loc );
-        
-        Iterator<TTFTable> iter = font.getTables().iterator();
-        while( iter.hasNext() )
-        {
-            TTFTable table = iter.next();
-            if( !initialized.contains( table ) )
-            {
-                raf.seek( table.getOffset() );
-                table.initData( font, raf );
-            }
-        }
-        return font;
+	protected void parseTables(TrueTypeFont font, TTFDataStream raf) 
+	throws IOException {
+		super.parseTables(font, raf);
+
+		// check others mandatory tables
+		if ( font.getCMAP() == null ){
+			throw new IOException("cmap is mandatory");
     }
     
-    private TTFTable readTableDirectory( TTFDataStream raf ) throws IOException
-    {
-        TTFTable retval = null;
-        String tag = raf.readString( 4 );
-        if( tag.equals( CMAPTable.TAG ) )
-        {
-            retval = new CMAPTable();
-        }
-        else if( tag.equals( GlyphTable.TAG ) )
-        {
-            retval = new GlyphTable();
-        }
-        else if( tag.equals( HeaderTable.TAG ) )
-        {
-            retval = new HeaderTable();
-        }
-        else if( tag.equals( HorizontalHeaderTable.TAG ) )
-        {
-            retval = new HorizontalHeaderTable();
-        }
-        else if( tag.equals( HorizontalMetricsTable.TAG ) )
-        {
-            retval = new HorizontalMetricsTable();
-        }
-        else if( tag.equals( IndexToLocationTable.TAG ) )
-        {
-            retval = new IndexToLocationTable();
-        }
-        else if( tag.equals( MaximumProfileTable.TAG ) )
-        {
-            retval = new MaximumProfileTable();
-        }
-        else if( tag.equals( NamingTable.TAG ) )
-        {
-            retval = new NamingTable();
-        }
-        else if( tag.equals( OS2WindowsMetricsTable.TAG ) )
-        {
-            retval = new OS2WindowsMetricsTable();
-        }
-        else if( tag.equals( PostScriptTable.TAG ) )
-        {
-            retval = new PostScriptTable();
-        }
-        else if( tag.equals( GlyphTable.TAG ) )
-        {
-            retval = new GlyphTable();
-        }
-        else if( tag.equals( GlyphTable.TAG ) )
-        {
-            retval = new GlyphTable();
-        }
-        else if( tag.equals( DigitalSignatureTable.TAG ) )
-        {
-            retval = new DigitalSignatureTable();
-        }
-        else
-        {
-            //unknown table type but read it anyway.
-            retval = new TTFTable();
-        }
-        retval.setTag( tag );
-        retval.setCheckSum( raf.readUnsignedInt() );
-        retval.setOffset( raf.readUnsignedInt() );
-        retval.setLength( raf.readUnsignedInt() );
-        return retval;
     }
 }
\ Pas de fin de ligne à la fin du fichier.
