You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ju...@apache.org on 2008/07/22 19:20:56 UTC

svn commit: r678810 [2/6] - in /incubator/pdfbox/trunk/fontbox: ./ Resources/ lib/ licenses/ licenses/checkstyle/ licenses/fontbox/ licenses/junit/ src/ src/org/ src/org/fontbox/ src/org/fontbox/afm/ src/org/fontbox/cmap/ src/org/fontbox/encoding/ src/...

Added: incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/AFMParser.java
URL: http://svn.apache.org/viewvc/incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/AFMParser.java?rev=678810&view=auto
==============================================================================
--- incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/AFMParser.java (added)
+++ incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/AFMParser.java Tue Jul 22 10:20:54 2008
@@ -0,0 +1,1076 @@
+/**
+ * Copyright (c) 2005, www.fontbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. Neither the name of fontbox; nor the names of its
+ *    contributors may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.fontbox.org
+ *
+ */
+package org.fontbox.afm;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+import java.util.StringTokenizer;
+
+import org.fontbox.util.BoundingBox;
+
+/**
+ * This class is used to parse AFM(Adobe Font Metrics) documents.
+ *
+ * @see <A href="http://partners.adobe.com/asn/developer/type/">AFM Documentation</A>
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class AFMParser
+{
+    /**
+     * This is a comment in a AFM file.
+     */
+    public static final String COMMENT = "Comment";
+    /**
+     * This is the constant used in the AFM file to start a font metrics item.
+     */
+    public static final String START_FONT_METRICS = "StartFontMetrics";
+    /**
+     * This is the constant used in the AFM file to end a font metrics item.
+     */
+    public static final String END_FONT_METRICS = "EndFontMetrics";
+    /**
+     * This is the font name.
+     */
+    public static final String FONT_NAME = "FontName";
+    /**
+     * This is the full name.
+     */
+    public static final String FULL_NAME = "FullName";
+    /**
+     * This is the Family name.
+     */
+    public static final String FAMILY_NAME = "FamilyName";
+    /**
+     * This is the weight.
+     */
+    public static final String WEIGHT = "Weight";
+    /**
+     * This is the font bounding box.
+     */
+    public static final String FONT_BBOX = "FontBBox";
+    /**
+     * This is the version of the font.
+     */
+    public static final String VERSION = "Version";
+    /**
+     * This is the notice.
+     */
+    public static final String NOTICE = "Notice";
+    /**
+     * This is the encoding scheme.
+     */
+    public static final String ENCODING_SCHEME = "EncodingScheme";
+    /**
+     * This is the mapping scheme.
+     */
+    public static final String MAPPING_SCHEME = "MappingScheme";
+    /**
+     * This is the escape character.
+     */
+    public static final String ESC_CHAR = "EscChar";
+    /**
+     * This is the character set.
+     */
+    public static final String CHARACTER_SET = "CharacterSet";
+    /**
+     * This is the characters attribute.
+     */
+    public static final String CHARACTERS = "Characters";
+    /**
+     * This will determine if this is a base font.
+     */
+    public static final String IS_BASE_FONT = "IsBaseFont";
+    /**
+     * This is the V Vector attribute.
+     */
+    public static final String V_VECTOR = "VVector";
+    /**
+     * This will tell if the V is fixed.
+     */
+    public static final String IS_FIXED_V = "IsFixedV";
+    /**
+     * This is the cap height attribute.
+     */
+    public static final String CAP_HEIGHT = "CapHeight";
+    /**
+     * This is the X height.
+     */
+    public static final String X_HEIGHT = "XHeight";
+    /**
+     * This is ascender attribute.
+     */
+    public static final String ASCENDER = "Ascender";
+    /**
+     * This is the descender attribute.
+     */
+    public static final String DESCENDER = "Descender";
+
+    /**
+     * The underline position.
+     */
+    public static final String UNDERLINE_POSITION = "UnderlinePosition";
+    /**
+     * This is the Underline thickness.
+     */
+    public static final String UNDERLINE_THICKNESS = "UnderlineThickness";
+    /**
+     * This is the italic angle.
+     */
+    public static final String ITALIC_ANGLE = "ItalicAngle";
+    /**
+     * This is the char width.
+     */
+    public static final String CHAR_WIDTH = "CharWidth";
+    /**
+     * This will determine if this is fixed pitch.
+     */
+    public static final String IS_FIXED_PITCH = "IsFixedPitch";
+    /**
+     * This is the start of character metrics.
+     */
+    public static final String START_CHAR_METRICS = "StartCharMetrics";
+    /**
+     * This is the end of character metrics.
+     */
+    public static final String END_CHAR_METRICS = "EndCharMetrics";
+    /**
+     * The character metrics c value.
+     */
+    public static final String CHARMETRICS_C = "C";
+    /**
+     * The character metrics c value.
+     */
+    public static final String CHARMETRICS_CH = "CH";
+    /**
+     * The character metrics value.
+     */
+    public static final String CHARMETRICS_WX = "WX";
+    /**
+     * The character metrics value.
+     */
+    public static final String CHARMETRICS_W0X = "W0X";
+    /**
+     * The character metrics value.
+     */
+    public static final String CHARMETRICS_W1X = "W1X";
+    /**
+     * The character metrics value.
+     */
+    public static final String CHARMETRICS_WY = "WY";
+    /**
+     * The character metrics value.
+     */
+    public static final String CHARMETRICS_W0Y = "W0Y";
+    /**
+     * The character metrics value.
+     */
+    public static final String CHARMETRICS_W1Y = "W1Y";
+    /**
+     * The character metrics value.
+     */
+    public static final String CHARMETRICS_W = "W";
+    /**
+     * The character metrics value.
+     */
+    public static final String CHARMETRICS_W0 = "W0";
+    /**
+     * The character metrics value.
+     */
+    public static final String CHARMETRICS_W1 = "W1";
+    /**
+     * The character metrics value.
+     */
+    public static final String CHARMETRICS_VV = "VV";
+    /**
+     * The character metrics value.
+     */
+    public static final String CHARMETRICS_N = "N";
+    /**
+     * The character metrics value.
+     */
+    public static final String CHARMETRICS_B = "B";
+    /**
+     * The character metrics value.
+     */
+    public static final String CHARMETRICS_L = "L";
+    /**
+     * The character metrics value.
+     */
+    public static final String STD_HW = "StdHW";
+    /**
+     * The character metrics value.
+     */
+    public static final String STD_VW = "StdVW";
+    /**
+     * This is the start of track kern data.
+     */
+    public static final String START_TRACK_KERN = "StartTrackKern";
+    /**
+     * This is the end of track kern data.
+     */
+    public static final String END_TRACK_KERN = "EndTrackKern";
+    /**
+     * This is the start of kern data.
+     */
+    public static final String START_KERN_DATA = "StartKernData";
+    /**
+     * This is the end of kern data.
+     */
+    public static final String END_KERN_DATA = "EndKernData";
+    /**
+     * This is the start of kern pairs data.
+     */
+    public static final String START_KERN_PAIRS = "StartKernPairs";
+    /**
+     * This is the end of kern pairs data.
+     */
+    public static final String END_KERN_PAIRS = "EndKernPairs";
+    /**
+     * This is the start of kern pairs data.
+     */
+    public static final String START_KERN_PAIRS0 = "StartKernPairs0";
+    /**
+     * This is the start of kern pairs data.
+     */
+    public static final String START_KERN_PAIRS1 = "StartKernPairs1";
+    /**
+     * This is the start compisites data section.
+     */
+    public static final String START_COMPOSITES = "StartComposites";
+    /**
+     * This is the end compisites data section.
+     */
+    public static final String END_COMPOSITES = "EndComposites";
+    /**
+     * This is a composite character.
+     */
+    public static final String CC = "CC";
+    /**
+     * This is a composite charater part.
+     */
+    public static final String PCC = "PCC";
+    /**
+     * This is a kern pair.
+     */
+    public static final String KERN_PAIR_KP = "KP";
+    /**
+     * This is a kern pair.
+     */
+    public static final String KERN_PAIR_KPH = "KPH";
+    /**
+     * This is a kern pair.
+     */
+    public static final String KERN_PAIR_KPX = "KPX";
+    /**
+     * This is a kern pair.
+     */
+    public static final String KERN_PAIR_KPY = "KPY";
+
+    private static final int BITS_IN_HEX = 16;
+
+
+    private InputStream input;
+    private FontMetric result;
+
+    /**
+     * A method to test parsing of all AFM documents in the resources
+     * directory.
+     *
+     * @param args Ignored.
+     *
+     * @throws IOException If there is an error parsing one of the documents.
+     */
+    public static void main( String[] args ) throws IOException
+    {
+        java.io.File afmDir = new java.io.File( "Resources/afm" );
+        java.io.File[] files = afmDir.listFiles();
+        for( int i=0; i< files.length; i++ )
+        {
+            if( files[i].getPath().toUpperCase().endsWith( ".AFM" ) )
+            {
+                long start = System.currentTimeMillis();
+                java.io.FileInputStream input = new java.io.FileInputStream( files[i] );
+                AFMParser parser = new AFMParser( input );
+                parser.parse();
+                long stop = System.currentTimeMillis();
+                System.out.println( "Parsing:" + files[i].getPath() + " " + (stop-start) );
+            }
+        }
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param in The input stream to read the AFM document from.
+     */
+    public AFMParser( InputStream in )
+    {
+        input = in;
+    }
+
+    /**
+     * This will parse the AFM document.  This will close the Input stream
+     * when the parsing is finished.
+     *
+     * @throws IOException If there is an IO error reading the document.
+     */
+    public void parse() throws IOException
+    {
+        result = parseFontMetric();
+    }
+
+    /**
+     * This will get the result of the parsing.
+     *
+     * @return The parsed java object.
+     */
+    public FontMetric getResult()
+    {
+        return result;
+    }
+
+    /**
+     * This will parse a font metrics item.
+     *
+     * @return The parse font metrics item.
+     *
+     * @throws IOException If there is an error reading the AFM file.
+     */
+    private FontMetric parseFontMetric() throws IOException
+    {
+        FontMetric fontMetrics = new FontMetric();
+        String startFontMetrics = readString();
+        if( !START_FONT_METRICS.equals( startFontMetrics ) )
+        {
+            throw new IOException( "Error: The AFM file should start with " + START_FONT_METRICS +
+                                   " and not '" + startFontMetrics + "'" );
+        }
+        fontMetrics.setAFMVersion( readFloat() );
+        String nextCommand = null;
+        while( !END_FONT_METRICS.equals( (nextCommand = readString() ) ) )
+        {
+            if( FONT_NAME.equals( nextCommand ) )
+            {
+                fontMetrics.setFontName( readLine() );
+            }
+            else if( FULL_NAME.equals( nextCommand ) )
+            {
+                fontMetrics.setFullName( readLine() );
+            }
+            else if( FAMILY_NAME.equals( nextCommand ) )
+            {
+                fontMetrics.setFamilyName( readLine() );
+            }
+            else if( WEIGHT.equals( nextCommand ) )
+            {
+                fontMetrics.setWeight( readLine() );
+            }
+            else if( FONT_BBOX.equals( nextCommand ) )
+            {
+                BoundingBox bBox = new BoundingBox();
+                bBox.setLowerLeftX( readFloat() );
+                bBox.setLowerLeftY( readFloat() );
+                bBox.setUpperRightX( readFloat() );
+                bBox.setUpperRightY( readFloat() );
+                fontMetrics.setFontBBox( bBox );
+            }
+            else if( VERSION.equals( nextCommand ) )
+            {
+                fontMetrics.setFontVersion( readLine() );
+            }
+            else if( NOTICE.equals( nextCommand ) )
+            {
+                fontMetrics.setNotice( readLine() );
+            }
+            else if( ENCODING_SCHEME.equals( nextCommand ) )
+            {
+                fontMetrics.setEncodingScheme( readLine() );
+            }
+            else if( MAPPING_SCHEME.equals( nextCommand ) )
+            {
+                fontMetrics.setMappingScheme( readInt() );
+            }
+            else if( ESC_CHAR.equals( nextCommand ) )
+            {
+                fontMetrics.setEscChar( readInt() );
+            }
+            else if( CHARACTER_SET.equals( nextCommand ) )
+            {
+                fontMetrics.setCharacterSet( readLine() );
+            }
+            else if( CHARACTERS.equals( nextCommand ) )
+            {
+                fontMetrics.setCharacters( readInt() );
+            }
+            else if( IS_BASE_FONT.equals( nextCommand ) )
+            {
+                fontMetrics.setIsBaseFont( readBoolean() );
+            }
+            else if( V_VECTOR.equals( nextCommand ) )
+            {
+                float[] vector = new float[2];
+                vector[0] = readFloat();
+                vector[1] = readFloat();
+                fontMetrics.setVVector( vector );
+            }
+            else if( IS_FIXED_V.equals( nextCommand ) )
+            {
+                fontMetrics.setIsFixedV( readBoolean() );
+            }
+            else if( CAP_HEIGHT.equals( nextCommand ) )
+            {
+                fontMetrics.setCapHeight( readFloat() );
+            }
+            else if( X_HEIGHT.equals( nextCommand ) )
+            {
+                fontMetrics.setXHeight( readFloat() );
+            }
+            else if( ASCENDER.equals( nextCommand ) )
+            {
+                fontMetrics.setAscender( readFloat() );
+            }
+            else if( DESCENDER.equals( nextCommand ) )
+            {
+                fontMetrics.setDescender( readFloat() );
+            }
+            else if( STD_HW.equals( nextCommand ) )
+            {
+                fontMetrics.setStandardHorizontalWidth( readFloat() );
+            }
+            else if( STD_VW.equals( nextCommand ) )
+            {
+                fontMetrics.setStandardVerticalWidth( readFloat() );
+            }
+            else if( COMMENT.equals( nextCommand ) )
+            {
+                fontMetrics.addComment( readLine() );
+            }
+            else if( UNDERLINE_POSITION.equals( nextCommand ) )
+            {
+                fontMetrics.setUnderlinePosition( readFloat() );
+            }
+            else if( UNDERLINE_THICKNESS.equals( nextCommand ) )
+            {
+                fontMetrics.setUnderlineThickness( readFloat() );
+            }
+            else if( ITALIC_ANGLE.equals( nextCommand ) )
+            {
+                fontMetrics.setItalicAngle( readFloat() );
+            }
+            else if( CHAR_WIDTH.equals( nextCommand ) )
+            {
+                float[] widths = new float[2];
+                widths[0] = readFloat();
+                widths[1] = readFloat();
+                fontMetrics.setCharWidth( widths );
+            }
+            else if( IS_FIXED_PITCH.equals( nextCommand ) )
+            {
+                fontMetrics.setFixedPitch( readBoolean() );
+            }
+            else if( START_CHAR_METRICS.equals( nextCommand ) )
+            {
+                int count = readInt();
+                for( int i=0; i<count; i++ )
+                {
+                    CharMetric charMetric = parseCharMetric();
+                    fontMetrics.addCharMetric( charMetric );
+                }
+                String end = readString();
+                if( !end.equals( END_CHAR_METRICS ) )
+                {
+                    throw new IOException( "Error: Expected '" + END_CHAR_METRICS + "' actual '" +
+                                                end + "'" );
+                }
+            }
+            else if( START_COMPOSITES.equals( nextCommand ) )
+            {
+                int count = readInt();
+                for( int i=0; i<count; i++ )
+                {
+                    Composite part = parseComposite();
+                    fontMetrics.addComposite( part );
+                }
+                String end = readString();
+                if( !end.equals( END_COMPOSITES ) )
+                {
+                    throw new IOException( "Error: Expected '" + END_COMPOSITES + "' actual '" +
+                                                end + "'" );
+                }
+            }
+            else if( START_KERN_DATA.equals( nextCommand ) )
+            {
+                parseKernData( fontMetrics );
+            }
+            else
+            {
+                throw new IOException( "Unknown AFM key '" + nextCommand + "'" );
+            }
+        }
+        return fontMetrics;
+    }
+
+    /**
+     * This will parse the kern data.
+     *
+     * @param fontMetrics The metrics class to put the parsed data into.
+     *
+     * @throws IOException If there is an error parsing the data.
+     */
+    private void parseKernData( FontMetric fontMetrics ) throws IOException
+    {
+        String nextCommand = null;
+        while( !(nextCommand = readString()).equals( END_KERN_DATA ) )
+        {
+            if( START_TRACK_KERN.equals( nextCommand ) )
+            {
+                int count = readInt();
+                for( int i=0; i<count; i++ )
+                {
+                    TrackKern kern = new TrackKern();
+                    kern.setDegree( readInt() );
+                    kern.setMinPointSize( readFloat() );
+                    kern.setMinKern( readFloat() );
+                    kern.setMaxPointSize( readFloat() );
+                    kern.setMaxKern( readFloat() );
+                    fontMetrics.addTrackKern( kern );
+                }
+                String end = readString();
+                if( !end.equals( END_TRACK_KERN ) )
+                {
+                    throw new IOException( "Error: Expected '" + END_TRACK_KERN + "' actual '" +
+                                                end + "'" );
+                }
+            }
+            else if( START_KERN_PAIRS.equals( nextCommand ) )
+            {
+                int count = readInt();
+                for( int i=0; i<count; i++ )
+                {
+                    KernPair pair = parseKernPair();
+                    fontMetrics.addKernPair( pair );
+                }
+                String end = readString();
+                if( !end.equals( END_KERN_PAIRS ) )
+                {
+                    throw new IOException( "Error: Expected '" + END_KERN_PAIRS + "' actual '" +
+                                                end + "'" );
+                }
+            }
+            else if( START_KERN_PAIRS0.equals( nextCommand ) )
+            {
+                int count = readInt();
+                for( int i=0; i<count; i++ )
+                {
+                    KernPair pair = parseKernPair();
+                    fontMetrics.addKernPair0( pair );
+                }
+                String end = readString();
+                if( !end.equals( END_KERN_PAIRS ) )
+                {
+                    throw new IOException( "Error: Expected '" + END_KERN_PAIRS + "' actual '" +
+                                                end + "'" );
+                }
+            }
+            else if( START_KERN_PAIRS1.equals( nextCommand ) )
+            {
+                int count = readInt();
+                for( int i=0; i<count; i++ )
+                {
+                    KernPair pair = parseKernPair();
+                    fontMetrics.addKernPair1( pair );
+                }
+                String end = readString();
+                if( !end.equals( END_KERN_PAIRS ) )
+                {
+                    throw new IOException( "Error: Expected '" + END_KERN_PAIRS + "' actual '" +
+                                                end + "'" );
+                }
+            }
+            else
+            {
+                throw new IOException( "Unknown kerning data type '" + nextCommand + "'" );
+            }
+        }
+    }
+
+    /**
+     * This will parse a kern pair from the data stream.
+     *
+     * @return The kern pair that was parsed from the stream.
+     *
+     * @throws IOException If there is an error reading from the stream.
+     */
+    private KernPair parseKernPair() throws IOException
+    {
+        KernPair kernPair = new KernPair();
+        String cmd = readString();
+        if( KERN_PAIR_KP.equals( cmd ) )
+        {
+            String first = readString();
+            String second = readString();
+            float x = readFloat();
+            float y = readFloat();
+            kernPair.setFirstKernCharacter( first );
+            kernPair.setSecondKernCharacter( second );
+            kernPair.setX( x );
+            kernPair.setY( y );
+        }
+        else if( KERN_PAIR_KPH.equals( cmd ) )
+        {
+            String first = hexToString( readString() );
+            String second = hexToString( readString() );
+            float x = readFloat();
+            float y = readFloat();
+            kernPair.setFirstKernCharacter( first );
+            kernPair.setSecondKernCharacter( second );
+            kernPair.setX( x );
+            kernPair.setY( y );
+        }
+        else if( KERN_PAIR_KPX.equals( cmd ) )
+        {
+            String first = readString();
+            String second = readString();
+            float x = readFloat();
+            kernPair.setFirstKernCharacter( first );
+            kernPair.setSecondKernCharacter( second );
+            kernPair.setX( x );
+            kernPair.setY( 0 );
+        }
+        else if( KERN_PAIR_KPY.equals( cmd ) )
+        {
+            String first = readString();
+            String second = readString();
+            float y = readFloat();
+            kernPair.setFirstKernCharacter( first );
+            kernPair.setSecondKernCharacter( second );
+            kernPair.setX( 0 );
+            kernPair.setY( y );
+        }
+        else
+        {
+            throw new IOException( "Error expected kern pair command actual='" + cmd + "'" );
+        }
+        return kernPair;
+    }
+
+    /**
+     * This will convert and angle bracket hex string to a string.
+     *
+     * @param hexString An angle bracket string.
+     *
+     * @return The bytes of the hex string.
+     *
+     * @throws IOException If the string is in an invalid format.
+     */
+    private String hexToString( String hexString ) throws IOException
+    {
+        if( hexString.length() < 2 )
+        {
+            throw new IOException( "Error: Expected hex string of length >= 2 not='" + hexString );
+        }
+        if( hexString.charAt( 0 ) != '<' ||
+            hexString.charAt( hexString.length() -1 ) != '>' )
+        {
+            throw new IOException( "String should be enclosed by angle brackets '" + hexString+ "'" );
+        }
+        hexString = hexString.substring( 1, hexString.length() -1 );
+        byte[] data = new byte[ (hexString.length() / 2) ];
+        for( int i=0; i<hexString.length(); i+=2 )
+        {
+            String hex = "" + hexString.charAt( i ) + hexString.charAt( i+1 );
+            try
+            {
+                data[ i / 2 ] = (byte)Integer.parseInt( hex, BITS_IN_HEX );
+            }
+            catch( NumberFormatException e )
+            {
+                throw new IOException( "Error parsing AFM file:" + e );
+            }
+        }
+        return new String( data );
+    }
+
+    /**
+     * This will parse a composite part from the stream.
+     *
+     * @return The composite.
+     *
+     * @throws IOException If there is an error parsing the composite.
+     */
+    private Composite parseComposite() throws IOException
+    {
+        Composite composite = new Composite();
+        String partData = readLine();
+        StringTokenizer tokenizer = new StringTokenizer( partData, " ;" );
+
+
+        String cc = tokenizer.nextToken();
+        if( !cc.equals( CC ) )
+        {
+            throw new IOException( "Expected '" + CC + "' actual='" + cc + "'" );
+        }
+        String name = tokenizer.nextToken();
+        composite.setName( name );
+
+        int partCount;
+        try
+        {
+            partCount = Integer.parseInt( tokenizer.nextToken() );
+        }
+        catch( NumberFormatException e )
+        {
+            throw new IOException( "Error parsing AFM document:" + e );
+        }
+        for( int i=0; i<partCount; i++ )
+        {
+            CompositePart part = new CompositePart();
+            String pcc = tokenizer.nextToken();
+            if( !pcc.equals( PCC ) )
+            {
+                throw new IOException( "Expected '" + PCC + "' actual='" + pcc + "'" );
+            }
+            String partName = tokenizer.nextToken();
+            try
+            {
+                int x = Integer.parseInt( tokenizer.nextToken() );
+                int y = Integer.parseInt( tokenizer.nextToken() );
+
+                part.setName( partName );
+                part.setXDisplacement( x );
+                part.setYDisplacement( y );
+                composite.addPart( part );
+            }
+            catch( NumberFormatException e )
+            {
+                throw new IOException( "Error parsing AFM document:" + e );
+            }
+        }
+        return composite;
+    }
+
+    /**
+     * This will parse a single CharMetric object from the stream.
+     *
+     * @return The next char metric in the stream.
+     *
+     * @throws IOException If there is an error reading from the stream.
+     */
+    private CharMetric parseCharMetric() throws IOException
+    {
+        CharMetric charMetric = new CharMetric();
+        String metrics = readLine();
+        StringTokenizer metricsTokenizer = new StringTokenizer( metrics );
+        try
+        {
+            while( metricsTokenizer.hasMoreTokens() )
+            {
+                String nextCommand = metricsTokenizer.nextToken();
+                if( nextCommand.equals( CHARMETRICS_C ) )
+                {
+                    String charCode = metricsTokenizer.nextToken();
+                    charMetric.setCharacterCode( Integer.parseInt( charCode ) );
+                    verifySemicolon( metricsTokenizer );
+                }
+                else if( nextCommand.equals( CHARMETRICS_CH ) )
+                {
+                    //Is the hex string <FF> or FF, the spec is a little
+                    //unclear, wait and see if it breaks anything.
+                    String charCode = metricsTokenizer.nextToken();
+                    charMetric.setCharacterCode( Integer.parseInt( charCode, BITS_IN_HEX ) );
+                    verifySemicolon( metricsTokenizer );
+                }
+                else if( nextCommand.equals( CHARMETRICS_WX ) )
+                {
+                    String wx = metricsTokenizer.nextToken();
+                    charMetric.setWx( Float.parseFloat( wx ) );
+                    verifySemicolon( metricsTokenizer );
+                }
+                else if( nextCommand.equals( CHARMETRICS_W0X ) )
+                {
+                    String w0x = metricsTokenizer.nextToken();
+                    charMetric.setW0x( Float.parseFloat( w0x ) );
+                    verifySemicolon( metricsTokenizer );
+                }
+                else if( nextCommand.equals( CHARMETRICS_W1X ) )
+                {
+                    String w1x = metricsTokenizer.nextToken();
+                    charMetric.setW0x( Float.parseFloat( w1x ) );
+                    verifySemicolon( metricsTokenizer );
+                }
+                else if( nextCommand.equals( CHARMETRICS_WY ) )
+                {
+                    String wy = metricsTokenizer.nextToken();
+                    charMetric.setWy( Float.parseFloat( wy ) );
+                    verifySemicolon( metricsTokenizer );
+                }
+                else if( nextCommand.equals( CHARMETRICS_W0Y ) )
+                {
+                    String w0y = metricsTokenizer.nextToken();
+                    charMetric.setW0y( Float.parseFloat( w0y ) );
+                    verifySemicolon( metricsTokenizer );
+                }
+                else if( nextCommand.equals( CHARMETRICS_W1Y ) )
+                {
+                    String w1y = metricsTokenizer.nextToken();
+                    charMetric.setW0y( Float.parseFloat( w1y ) );
+                    verifySemicolon( metricsTokenizer );
+                }
+                else if( nextCommand.equals( CHARMETRICS_W ) )
+                {
+                    String w0 = metricsTokenizer.nextToken();
+                    String w1 = metricsTokenizer.nextToken();
+                    float[] w = new float[2];
+                    w[0] = Float.parseFloat( w0 );
+                    w[1] = Float.parseFloat( w1 );
+                    charMetric.setW( w );
+                    verifySemicolon( metricsTokenizer );
+                }
+                else if( nextCommand.equals( CHARMETRICS_W0 ) )
+                {
+                    String w00 = metricsTokenizer.nextToken();
+                    String w01 = metricsTokenizer.nextToken();
+                    float[] w0 = new float[2];
+                    w0[0] = Float.parseFloat( w00 );
+                    w0[1] = Float.parseFloat( w01 );
+                    charMetric.setW0( w0 );
+                    verifySemicolon( metricsTokenizer );
+                }
+                else if( nextCommand.equals( CHARMETRICS_W1 ) )
+                {
+                    String w10 = metricsTokenizer.nextToken();
+                    String w11 = metricsTokenizer.nextToken();
+                    float[] w1 = new float[2];
+                    w1[0] = Float.parseFloat( w10 );
+                    w1[1] = Float.parseFloat( w11 );
+                    charMetric.setW1( w1 );
+                    verifySemicolon( metricsTokenizer );
+                }
+                else if( nextCommand.equals( CHARMETRICS_VV ) )
+                {
+                    String vv0 = metricsTokenizer.nextToken();
+                    String vv1 = metricsTokenizer.nextToken();
+                    float[] vv = new float[2];
+                    vv[0] = Float.parseFloat( vv0 );
+                    vv[1] = Float.parseFloat( vv1 );
+                    charMetric.setVv( vv );
+                    verifySemicolon( metricsTokenizer );
+                }
+                else if( nextCommand.equals( CHARMETRICS_N ) )
+                {
+                    String name = metricsTokenizer.nextToken();
+                    charMetric.setName( name );
+                    verifySemicolon( metricsTokenizer );
+                }
+                else if( nextCommand.equals( CHARMETRICS_B ) )
+                {
+                    String llx = metricsTokenizer.nextToken();
+                    String lly = metricsTokenizer.nextToken();
+                    String urx = metricsTokenizer.nextToken();
+                    String ury = metricsTokenizer.nextToken();
+                    BoundingBox box = new BoundingBox();
+                    box.setLowerLeftX( Float.parseFloat( llx ) );
+                    box.setLowerLeftY( Float.parseFloat( lly ) );
+                    box.setUpperRightX( Float.parseFloat( urx ) );
+                    box.setUpperRightY( Float.parseFloat( ury ) );
+                    charMetric.setBoundingBox( box );
+                    verifySemicolon( metricsTokenizer );
+                }
+                else if( nextCommand.equals( CHARMETRICS_L ) )
+                {
+                    String successor = metricsTokenizer.nextToken();
+                    String ligature = metricsTokenizer.nextToken();
+                    Ligature lig = new Ligature();
+                    lig.setSuccessor( successor );
+                    lig.setLigature( ligature );
+                    charMetric.addLigature( lig );
+                    verifySemicolon( metricsTokenizer );
+                }
+                else
+                {
+                    throw new IOException( "Unknown CharMetrics command '" + nextCommand + "'" );
+                }
+            }
+        }
+        catch( NumberFormatException e )
+        {
+            throw new IOException( "Error: Corrupt AFM document:"  + e );
+        }
+        return charMetric;
+    }
+
+    /**
+     * This is used to verify that a semicolon is the next token in the stream.
+     *
+     * @param tokenizer The tokenizer to read from.
+     *
+     * @throws IOException If the semicolon is missing.
+     */
+    private void verifySemicolon( StringTokenizer tokenizer ) throws IOException
+    {
+        if( tokenizer.hasMoreTokens() )
+        {
+            String semicolon = tokenizer.nextToken();
+            if( !semicolon.equals( ";" ) )
+            {
+                throw new IOException( "Error: Expected semicolon in stream actual='" +
+                                            semicolon + "'" );
+            }
+        }
+        else
+        {
+            throw new IOException( "CharMetrics is missing a semicolon after a command" );
+        }
+    }
+
+    /**
+     * This will read a boolean from the stream.
+     *
+     * @return The boolean in the stream.
+     */
+    private boolean readBoolean() throws IOException
+    {
+        String theBoolean = readString();
+        return Boolean.valueOf( theBoolean ).booleanValue();
+    }
+
+    /**
+     * This will read an integer from the stream.
+     *
+     * @return The integer in the stream.
+     */
+    private int readInt() throws IOException
+    {
+        String theInt = readString();
+        try
+        {
+            return Integer.parseInt( theInt );
+        }
+        catch( NumberFormatException e )
+        {
+            throw new IOException( "Error parsing AFM document:" + e );
+        }
+    }
+
+    /**
+     * This will read a float from the stream.
+     *
+     * @return The float in the stream.
+     */
+    private float readFloat() throws IOException
+    {
+        String theFloat = readString();
+        return Float.parseFloat( theFloat );
+    }
+
+    /**
+     * This will read until the end of a line.
+     *
+     * @return The string that is read.
+     */
+    private String readLine() throws IOException
+    {
+        //First skip the whitespace
+        StringBuffer buf = new StringBuffer();
+        int nextByte = input.read();
+        while( isWhitespace( nextByte ) )
+        {
+            nextByte = input.read();
+            //do nothing just skip the whitespace.
+        }
+        buf.append( (char)nextByte );
+
+        //now read the data
+        while( !isEOL(nextByte = input.read()) )
+        {
+            buf.append( (char)nextByte );
+        }
+        return buf.toString();
+    }
+
+    /**
+     * This will read a string from the input stream and stop at any whitespace.
+     *
+     * @return The string read from the stream.
+     *
+     * @throws IOException If an IO error occurs when reading from the stream.
+     */
+    private String readString() throws IOException
+    {
+        //First skip the whitespace
+        StringBuffer buf = new StringBuffer();
+        int nextByte = input.read();
+        while( isWhitespace( nextByte ) )
+        {
+            nextByte = input.read();
+            //do nothing just skip the whitespace.
+        }
+        buf.append( (char)nextByte );
+
+        //now read the data
+        while( !isWhitespace(nextByte = input.read()) )
+        {
+            buf.append( (char)nextByte );
+        }
+        return buf.toString();
+    }
+
+    /**
+     * This will determine if the byte is a whitespace character or not.
+     *
+     * @param character The character to test for whitespace.
+     *
+     * @return true If the character is whitespace as defined by the AFM spec.
+     */
+    private boolean isEOL( int character )
+    {
+        return character == 0x0D ||
+               character == 0x0A;
+    }
+
+    /**
+     * This will determine if the byte is a whitespace character or not.
+     *
+     * @param character The character to test for whitespace.
+     *
+     * @return true If the character is whitespace as defined by the AFM spec.
+     */
+    private boolean isWhitespace( int character )
+    {
+        return character == ' ' ||
+               character == '\t' ||
+               character == 0x0D ||
+               character == 0x0A;
+    }
+}
\ No newline at end of file

Added: incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/CharMetric.java
URL: http://svn.apache.org/viewvc/incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/CharMetric.java?rev=678810&view=auto
==============================================================================
--- incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/CharMetric.java (added)
+++ incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/CharMetric.java Tue Jul 22 10:20:54 2008
@@ -0,0 +1,299 @@
+/**
+ * Copyright (c) 2005, www.fontbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. Neither the name of fontbox; nor the names of its
+ *    contributors may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.fontbox.org
+ *
+ */
+package org.fontbox.afm;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.fontbox.util.BoundingBox;
+
+/**
+ * This class represents a single character metric.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class CharMetric
+{
+    private int characterCode;
+
+    private float wx;
+    private float w0x;
+    private float w1x;
+
+    private float wy;
+    private float w0y;
+    private float w1y;
+
+    private float[] w;
+    private float[] w0;
+    private float[] w1;
+    private float[] vv;
+
+    private String name;
+    private BoundingBox boundingBox;
+    private List ligatures = new ArrayList();
+
+    /** Getter for property boundingBox.
+     * @return Value of property boundingBox.
+     */
+    public BoundingBox getBoundingBox()
+    {
+        return boundingBox;
+    }
+
+    /** Setter for property boundingBox.
+     * @param bBox New value of property boundingBox.
+     */
+    public void setBoundingBox(BoundingBox bBox)
+    {
+        boundingBox = bBox;
+    }
+
+    /** Getter for property characterCode.
+     * @return Value of property characterCode.
+     */
+    public int getCharacterCode()
+    {
+        return characterCode;
+    }
+
+    /** Setter for property characterCode.
+     * @param cCode New value of property characterCode.
+     */
+    public void setCharacterCode(int cCode)
+    {
+        characterCode = cCode;
+    }
+
+    /**
+     * This will add an entry to the list of ligatures.
+     *
+     * @param ligature The ligature to add.
+     */
+    public void addLigature( Ligature ligature )
+    {
+        ligatures.add( ligature );
+    }
+
+    /** Getter for property ligatures.
+     * @return Value of property ligatures.
+     */
+    public List getLigatures()
+    {
+        return ligatures;
+    }
+
+    /** Setter for property ligatures.
+     * @param lig New value of property ligatures.
+     */
+    public void setLigatures(List lig)
+    {
+        this.ligatures = lig;
+    }
+
+    /** Getter for property name.
+     * @return Value of property name.
+     */
+    public String getName()
+    {
+        return name;
+    }
+
+    /** Setter for property name.
+     * @param n New value of property name.
+     */
+    public void setName(String n)
+    {
+        this.name = n;
+    }
+
+    /** Getter for property vv.
+     * @return Value of property vv.
+     */
+    public float[] getVv()
+    {
+        return this.vv;
+    }
+
+    /** Setter for property vv.
+     * @param vvValue New value of property vv.
+     */
+    public void setVv(float[] vvValue)
+    {
+        this.vv = vvValue;
+    }
+
+    /** Getter for property w.
+     * @return Value of property w.
+     */
+    public float[] getW()
+    {
+        return this.w;
+    }
+
+    /** Setter for property w.
+     * @param wValue New value of property w.
+     */
+    public void setW(float[] wValue)
+    {
+        this.w = wValue;
+    }
+
+    /** Getter for property w0.
+     * @return Value of property w0.
+     */
+    public float[] getW0()
+    {
+        return this.w0;
+    }
+
+    /** Setter for property w0.
+     * @param w0Value New value of property w0.
+     */
+    public void setW0(float[] w0Value)
+    {
+        w0 = w0Value;
+    }
+
+    /** Getter for property w0x.
+     * @return Value of property w0x.
+     */
+    public float getW0x()
+    {
+        return w0x;
+    }
+
+    /** Setter for property w0x.
+     * @param w0xValue New value of property w0x.
+     */
+    public void setW0x(float w0xValue)
+    {
+        w0x = w0xValue;
+    }
+
+    /** Getter for property w0y.
+     * @return Value of property w0y.
+     */
+    public float getW0y()
+    {
+        return w0y;
+    }
+
+    /** Setter for property w0y.
+     * @param w0yValue New value of property w0y.
+     */
+    public void setW0y(float w0yValue)
+    {
+        w0y = w0yValue;
+    }
+
+    /** Getter for property w1.
+     * @return Value of property w1.
+     */
+    public float[] getW1()
+    {
+        return this.w1;
+    }
+
+    /** Setter for property w1.
+     * @param w1Value New value of property w1.
+     */
+    public void setW1(float[] w1Value)
+    {
+        w1 = w1Value;
+    }
+
+    /** Getter for property w1x.
+     * @return Value of property w1x.
+     */
+    public float getW1x()
+    {
+        return w1x;
+    }
+
+    /** Setter for property w1x.
+     * @param w1xValue New value of property w1x.
+     */
+    public void setW1x(float w1xValue)
+    {
+        w1x = w1xValue;
+    }
+
+    /** Getter for property w1y.
+     * @return Value of property w1y.
+     */
+    public float getW1y()
+    {
+        return w1y;
+    }
+
+    /** Setter for property w1y.
+     * @param w1yValue New value of property w1y.
+     */
+    public void setW1y(float w1yValue)
+    {
+        w1y = w1yValue;
+    }
+
+    /** Getter for property wx.
+     * @return Value of property wx.
+     */
+    public float getWx()
+    {
+        return wx;
+    }
+
+    /** Setter for property wx.
+     * @param wxValue New value of property wx.
+     */
+    public void setWx(float wxValue)
+    {
+        wx = wxValue;
+    }
+
+    /** Getter for property wy.
+     * @return Value of property wy.
+     */
+    public float getWy()
+    {
+        return wy;
+    }
+
+    /** Setter for property wy.
+     * @param wyValue New value of property wy.
+     */
+    public void setWy(float wyValue)
+    {
+        this.wy = wyValue;
+    }
+
+}
\ No newline at end of file

Added: incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/Composite.java
URL: http://svn.apache.org/viewvc/incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/Composite.java?rev=678810&view=auto
==============================================================================
--- incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/Composite.java (added)
+++ incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/Composite.java Tue Jul 22 10:20:54 2008
@@ -0,0 +1,89 @@
+/**
+ * Copyright (c) 2005, www.fontbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. Neither the name of fontbox; nor the names of its
+ *    contributors may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.fontbox.org
+ *
+ */
+package org.fontbox.afm;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class represents composite character data.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class Composite
+{
+    private String name;
+    private List parts = new ArrayList();
+
+    /** Getter for property name.
+     * @return Value of property name.
+     */
+    public String getName()
+    {
+        return name;
+    }
+
+    /** Setter for property name.
+     * @param nameValue New value of property name.
+     */
+    public void setName(String nameValue)
+    {
+        this.name = nameValue;
+    }
+
+    /**
+     * This will add a composite part.
+     *
+     * @param part The composite part to add.
+     */
+    public void addPart( CompositePart part )
+    {
+        parts.add( part );
+    }
+
+    /** Getter for property parts.
+     * @return Value of property parts.
+     */
+    public List getParts()
+    {
+        return parts;
+    }
+
+    /** Setter for property parts.
+     * @param partsList New value of property parts.
+     */
+    public void setParts(List partsList)
+    {
+        this.parts = partsList;
+    }
+
+}
\ No newline at end of file

Added: incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/CompositePart.java
URL: http://svn.apache.org/viewvc/incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/CompositePart.java?rev=678810&view=auto
==============================================================================
--- incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/CompositePart.java (added)
+++ incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/CompositePart.java Tue Jul 22 10:20:54 2008
@@ -0,0 +1,93 @@
+/**
+ * Copyright (c) 2005, www.fontbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. Neither the name of fontbox; nor the names of its
+ *    contributors may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.fontbox.org
+ *
+ */
+package org.fontbox.afm;
+
+/**
+ * This class represents a part of composite character data.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class CompositePart
+{
+    private String name;
+    private int xDisplacement;
+    private int yDisplacement;
+
+    /** Getter for property name.
+     * @return Value of property name.
+     */
+    public java.lang.String getName()
+    {
+        return name;
+    }
+
+    /** Setter for property name.
+     * @param nameValue New value of property name.
+     */
+    public void setName(String nameValue)
+    {
+        name = nameValue;
+    }
+
+    /** Getter for property xDisplacement.
+     * @return Value of property xDisplacement.
+     */
+    public int getXDisplacement()
+    {
+        return xDisplacement;
+    }
+
+    /** Setter for property xDisplacement.
+     * @param xDisp New value of property xDisplacement.
+     */
+    public void setXDisplacement(int xDisp)
+    {
+        xDisplacement = xDisp;
+    }
+
+    /** Getter for property yDisplacement.
+     * @return Value of property yDisplacement.
+     */
+    public int getYDisplacement()
+    {
+        return yDisplacement;
+    }
+
+    /** Setter for property yDisplacement.
+     * @param yDisp New value of property yDisplacement.
+     */
+    public void setYDisplacement(int yDisp)
+    {
+        yDisplacement = yDisp;
+    }
+
+}
\ No newline at end of file

Added: incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/FontMetric.java
URL: http://svn.apache.org/viewvc/incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/FontMetric.java?rev=678810&view=auto
==============================================================================
--- incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/FontMetric.java (added)
+++ incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/FontMetric.java Tue Jul 22 10:20:54 2008
@@ -0,0 +1,925 @@
+/**
+ * Copyright (c) 2005, www.fontbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. Neither the name of fontbox; nor the names of its
+ *    contributors may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.fontbox.org
+ *
+ */
+package org.fontbox.afm;
+
+import java.io.IOException;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.fontbox.util.BoundingBox;
+
+/**
+ * This is the outermost AFM type.  This can be created by the afmparser with a valid
+ * AFM document.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.3 $
+ */
+public class FontMetric
+{
+    /**
+     * This is the version of the FontMetrics.
+     */
+    private float afmVersion;
+    private int metricSets = 0;
+    private String fontName;
+    private String fullName;
+    private String familyName;
+    private String weight;
+    private BoundingBox fontBBox;
+    private String fontVersion;
+    private String notice;
+    private String encodingScheme;
+    private int mappingScheme;
+    private int escChar;
+    private String characterSet;
+    private int characters;
+    private boolean isBaseFont;
+    private float[] vVector;
+    private boolean isFixedV;
+    private float capHeight;
+    private float xHeight;
+    private float ascender;
+    private float descender;
+    private List comments = new ArrayList();
+
+    private float underlinePosition;
+    private float underlineThickness;
+    private float italicAngle;
+    private float[] charWidth;
+    private boolean isFixedPitch;
+    private float standardHorizontalWidth;
+    private float standardVerticalWidth;
+
+    private List charMetrics = new ArrayList();
+    private Map charMetricsMap = new HashMap();
+    private List trackKern = new ArrayList();
+    private List composites = new ArrayList();
+    private List kernPairs = new ArrayList();
+    private List kernPairs0 = new ArrayList();
+    private List kernPairs1 = new ArrayList();
+
+    /**
+     * Constructor.
+     */
+    public FontMetric()
+    {
+    }
+
+    /**
+     * This will get the width of a character.
+     *
+     * @param name The character to get the width for.
+     *
+     * @return The width of the character.
+     *
+     * @throws IOException If this AFM file does not handle the character.
+     */
+    public float getCharacterWidth( String name ) throws IOException
+    {
+        float result = 0;
+        CharMetric metric = (CharMetric)charMetricsMap.get( name );
+        if( metric == null )
+        {
+            result=0;
+            //don't throw an exception right away.
+            //throw new IOException( "Unknown AFM(" + getFullName() + ") characer '" + name + "'" );
+        }
+        else
+        {
+            result = metric.getWx();
+        }
+        return result;
+    }
+    
+    /**
+     * This will get the width of a character.
+     *
+     * @param name The character to get the width for.
+     *
+     * @return The width of the character.
+     *
+     * @throws IOException If this AFM file does not handle the character.
+     */
+    public float getCharacterHeight( String name ) throws IOException
+    {
+        float result = 0;
+        CharMetric metric = (CharMetric)charMetricsMap.get( name );
+        if( metric == null )
+        {
+            result=0;
+            //don't throw an exception right away.
+            //throw new IOException( "Unknown AFM(" + getFullName() + ") characer '" + name + "'" );
+        }
+        else
+        {
+            if( metric.getWy() == 0 )
+            {
+                result = metric.getBoundingBox().getHeight();
+            }
+            else
+            {
+                result = metric.getWy();
+            }
+        }
+        return result;
+    }
+
+
+    /**
+     * This will get the average width of a character.
+     *
+     * @return The width of the character.
+     *
+     * @throws IOException If this AFM file does not handle the character.
+     */
+    public float getAverageCharacterWidth() throws IOException
+    {
+        float average = 0;
+        float totalWidths = 0;
+        float characterCount = 0;
+        Iterator iter = charMetricsMap.values().iterator();
+        while( iter.hasNext() )
+        {
+            CharMetric metric = (CharMetric)iter.next();
+            if( metric.getWx() > 0 )
+            {
+                totalWidths += metric.getWx();
+                characterCount += 1;
+            }
+        }
+        if( totalWidths > 0 )
+        {
+            average = totalWidths / characterCount;
+        }
+
+        return average;
+    }
+
+    /**
+     * This will add a new comment.
+     *
+     * @param comment The comment to add to this metric.
+     */
+    public void addComment( String comment )
+    {
+        comments.add( comment );
+    }
+
+    /**
+     * This will get all comments.
+     *
+     * @return The list of all comments.
+     */
+    public List getComments()
+    {
+        return comments;
+    }
+
+    /**
+     * This will get the version of the AFM document.
+     *
+     * @return The version of the document.
+     */
+    public float getAFMVersion()
+    {
+        return afmVersion;
+    }
+
+    /**
+     * This will get the metricSets attribute.
+     *
+     * @return The value of the metric sets.
+     */
+    public int getMetricSets()
+    {
+        return metricSets;
+    }
+
+    /**
+     * This will set the version of the AFM document.
+     *
+     * @param afmVersionValue The version of the document.
+     */
+    public void setAFMVersion( float afmVersionValue )
+    {
+        afmVersion = afmVersionValue;
+    }
+
+    /**
+     * This will set the metricSets attribute.  This value must be 0,1, or 2.
+     *
+     * @param metricSetsValue The new metric sets attribute.
+     */
+    public void setMetricSets( int metricSetsValue )
+    {
+        if( metricSetsValue < 0 || metricSetsValue > 2 )
+        {
+            throw new RuntimeException( "The metricSets attribute must be in the " +
+                                        "set {0,1,2} and not '" + metricSetsValue + "'" );
+        }
+        metricSets = metricSetsValue;
+    }
+
+    /**
+     * Getter for property fontName.
+     *
+     * @return Value of property fontName.
+     */
+    public String getFontName()
+    {
+        return fontName;
+    }
+
+    /**
+     * Setter for property fontName.
+     *
+     * @param name New value of property fontName.
+     */
+    public void setFontName(String name)
+    {
+        fontName = name;
+    }
+
+    /**
+     * Getter for property fullName.
+     *
+     * @return Value of property fullName.
+     */
+    public String getFullName()
+    {
+        return fullName;
+    }
+
+    /**
+     * Setter for property fullName.
+     *
+     * @param fullNameValue New value of property fullName.
+     */
+    public void setFullName(String fullNameValue)
+    {
+        fullName = fullNameValue;
+    }
+
+    /**
+     * Getter for property familyName.
+     *
+     * @return Value of property familyName.
+     */
+    public String getFamilyName()
+    {
+        return familyName;
+    }
+
+    /**
+     * Setter for property familyName.
+     *
+     * @param familyNameValue New value of property familyName.
+     */
+    public void setFamilyName(String familyNameValue)
+    {
+        familyName = familyNameValue;
+    }
+
+    /**
+     * Getter for property weight.
+     *
+     * @return Value of property weight.
+     */
+    public String getWeight()
+    {
+        return weight;
+    }
+
+    /**
+     * Setter for property weight.
+     *
+     * @param weightValue New value of property weight.
+     */
+    public void setWeight(String weightValue)
+    {
+        weight = weightValue;
+    }
+
+    /**
+     * Getter for property fontBBox.
+     *
+     * @return Value of property fontBBox.
+     */
+    public BoundingBox getFontBBox()
+    {
+        return fontBBox;
+    }
+
+    /**
+     * Setter for property fontBBox.
+     *
+     * @param bBox New value of property fontBBox.
+     */
+    public void setFontBBox(BoundingBox bBox)
+    {
+        this.fontBBox = bBox;
+    }
+
+    /**
+     * Getter for property notice.
+     *
+     * @return Value of property notice.
+     */
+    public String getNotice()
+    {
+        return notice;
+    }
+
+    /**
+     * Setter for property notice.
+     *
+     * @param noticeValue New value of property notice.
+     */
+    public void setNotice(String noticeValue)
+    {
+        notice = noticeValue;
+    }
+
+    /**
+     * Getter for property encodingScheme.
+     *
+     * @return Value of property encodingScheme.
+     */
+    public String getEncodingScheme()
+    {
+        return encodingScheme;
+    }
+
+    /**
+     * Setter for property encodingScheme.
+     *
+     * @param encodingSchemeValue New value of property encodingScheme.
+     */
+    public void setEncodingScheme(String encodingSchemeValue)
+    {
+        encodingScheme = encodingSchemeValue;
+    }
+
+    /**
+     * Getter for property mappingScheme.
+     *
+     * @return Value of property mappingScheme.
+     */
+    public int getMappingScheme()
+    {
+        return mappingScheme;
+    }
+
+    /**
+     * Setter for property mappingScheme.
+     *
+     * @param mappingSchemeValue New value of property mappingScheme.
+     */
+    public void setMappingScheme(int mappingSchemeValue)
+    {
+        mappingScheme = mappingSchemeValue;
+    }
+
+    /**
+     * Getter for property escChar.
+     *
+     * @return Value of property escChar.
+     */
+    public int getEscChar()
+    {
+        return escChar;
+    }
+
+    /**
+     * Setter for property escChar.
+     *
+     * @param escCharValue New value of property escChar.
+     */
+    public void setEscChar(int escCharValue)
+    {
+        escChar = escCharValue;
+    }
+
+    /**
+     * Getter for property characterSet.
+     *
+     * @return Value of property characterSet.
+     */
+    public String getCharacterSet()
+    {
+        return characterSet;
+    }
+
+    /**
+     * Setter for property characterSet.
+     *
+     * @param characterSetValue New value of property characterSet.
+     */
+    public void setCharacterSet(String characterSetValue)
+    {
+        characterSet = characterSetValue;
+    }
+
+    /**
+     * Getter for property characters.
+     *
+     * @return Value of property characters.
+     */
+    public int getCharacters()
+    {
+        return characters;
+    }
+
+    /**
+     * Setter for property characters.
+     *
+     * @param charactersValue New value of property characters.
+     */
+    public void setCharacters(int charactersValue)
+    {
+        characters = charactersValue;
+    }
+
+    /**
+     * Getter for property isBaseFont.
+     *
+     * @return Value of property isBaseFont.
+     */
+    public boolean isBaseFont()
+    {
+        return isBaseFont;
+    }
+
+    /**
+     * Setter for property isBaseFont.
+     *
+     * @param isBaseFontValue New value of property isBaseFont.
+     */
+    public void setIsBaseFont(boolean isBaseFontValue)
+    {
+        isBaseFont = isBaseFontValue;
+    }
+
+    /**
+     * Getter for property vVector.
+     *
+     * @return Value of property vVector.
+     */
+    public float[] getVVector()
+    {
+        return this.vVector;
+    }
+
+    /**
+     * Setter for property vVector.
+     *
+     * @param vVectorValue New value of property vVector.
+     */
+    public void setVVector(float[] vVectorValue)
+    {
+        vVector = vVectorValue;
+    }
+
+    /**
+     * Getter for property isFixedV.
+     *
+     * @return Value of property isFixedV.
+     */
+    public boolean isFixedV()
+    {
+        return isFixedV;
+    }
+
+    /**
+     * Setter for property isFixedV.
+     *
+     * @param isFixedVValue New value of property isFixedV.
+     */
+    public void setIsFixedV(boolean isFixedVValue)
+    {
+        isFixedV = isFixedVValue;
+    }
+
+    /**
+     * Getter for property capHeight.
+     *
+     * @return Value of property capHeight.
+     */
+    public float getCapHeight()
+    {
+        return capHeight;
+    }
+
+    /**
+     * Setter for property capHeight.
+     *
+     * @param capHeightValue New value of property capHeight.
+     */
+    public void setCapHeight(float capHeightValue)
+    {
+        capHeight = capHeightValue;
+    }
+
+    /**
+     * Getter for property xHeight.
+     *
+     * @return Value of property xHeight.
+     */
+    public float getXHeight()
+    {
+        return xHeight;
+    }
+
+    /**
+     * Setter for property xHeight.
+     *
+     * @param xHeightValue New value of property xHeight.
+     */
+    public void setXHeight( float xHeightValue )
+    {
+        xHeight = xHeightValue;
+    }
+
+    /**
+     * Getter for property ascender.
+     *
+     * @return Value of property ascender.
+     */
+    public float getAscender()
+    {
+        return ascender;
+    }
+
+    /**
+     * Setter for property ascender.
+     *
+     * @param ascenderValue New value of property ascender.
+     */
+    public void setAscender( float ascenderValue )
+    {
+        ascender = ascenderValue;
+    }
+
+    /**
+     * Getter for property descender.
+     *
+     * @return Value of property descender.
+     */
+    public float getDescender()
+    {
+        return descender;
+    }
+
+    /**
+     * Setter for property descender.
+     *
+     * @param descenderValue New value of property descender.
+     */
+    public void setDescender( float descenderValue )
+    {
+        descender = descenderValue;
+    }
+
+    /**
+     * Getter for property fontVersion.
+     *
+     * @return Value of property fontVersion.
+     */
+    public String getFontVersion()
+    {
+        return fontVersion;
+    }
+
+    /**
+     * Setter for property fontVersion.
+     *
+     * @param fontVersionValue New value of property fontVersion.
+     */
+    public void setFontVersion(String fontVersionValue)
+    {
+        fontVersion = fontVersionValue;
+    }
+
+    /**
+     * Getter for property underlinePosition.
+     *
+     * @return Value of property underlinePosition.
+     */
+    public float getUnderlinePosition()
+    {
+        return underlinePosition;
+    }
+
+    /**
+     * Setter for property underlinePosition.
+     *
+     * @param underlinePositionValue New value of property underlinePosition.
+     */
+    public void setUnderlinePosition(float underlinePositionValue)
+    {
+        underlinePosition = underlinePositionValue;
+    }
+
+    /**
+     * Getter for property underlineThickness.
+     *
+     * @return Value of property underlineThickness.
+     */
+    public float getUnderlineThickness()
+    {
+        return underlineThickness;
+    }
+
+    /**
+     * Setter for property underlineThickness.
+     *
+     * @param underlineThicknessValue New value of property underlineThickness.
+     */
+    public void setUnderlineThickness(float underlineThicknessValue)
+    {
+        underlineThickness = underlineThicknessValue;
+    }
+
+    /**
+     * Getter for property italicAngle.
+     *
+     * @return Value of property italicAngle.
+     */
+    public float getItalicAngle()
+    {
+        return italicAngle;
+    }
+
+    /**
+     * Setter for property italicAngle.
+     *
+     * @param italicAngleValue New value of property italicAngle.
+     */
+    public void setItalicAngle(float italicAngleValue)
+    {
+        italicAngle = italicAngleValue;
+    }
+
+    /**
+     * Getter for property charWidth.
+     *
+     * @return Value of property charWidth.
+     */
+    public float[] getCharWidth()
+    {
+        return this.charWidth;
+    }
+
+    /**
+     * Setter for property charWidth.
+     *
+     * @param charWidthValue New value of property charWidth.
+     */
+    public void setCharWidth(float[] charWidthValue)
+    {
+        charWidth = charWidthValue;
+    }
+
+    /**
+     * Getter for property isFixedPitch.
+     *
+     * @return Value of property isFixedPitch.
+     */
+    public boolean isFixedPitch()
+    {
+        return isFixedPitch;
+    }
+
+    /**
+     * Setter for property isFixedPitch.
+     *
+     * @param isFixedPitchValue New value of property isFixedPitch.
+     */
+    public void setFixedPitch(boolean isFixedPitchValue)
+    {
+        isFixedPitch = isFixedPitchValue;
+    }
+
+    /** Getter for property charMetrics.
+     * @return Value of property charMetrics.
+     */
+    public List getCharMetrics()
+    {
+        return charMetrics;
+    }
+
+    /** Setter for property charMetrics.
+     * @param charMetricsValue New value of property charMetrics.
+     */
+    public void setCharMetrics(List charMetricsValue)
+    {
+        charMetrics = charMetricsValue;
+    }
+
+    /**
+     * This will add another character metric.
+     *
+     * @param metric The character metric to add.
+     */
+    public void addCharMetric( CharMetric metric )
+    {
+        charMetrics.add( metric );
+        charMetricsMap.put( metric.getName(), metric );
+    }
+
+    /** Getter for property trackKern.
+     * @return Value of property trackKern.
+     */
+    public List getTrackKern()
+    {
+        return trackKern;
+    }
+
+    /** Setter for property trackKern.
+     * @param trackKernValue New value of property trackKern.
+     */
+    public void setTrackKern(List trackKernValue)
+    {
+        trackKern = trackKernValue;
+    }
+
+    /**
+     * This will add another track kern.
+     *
+     * @param kern The track kerning data.
+     */
+    public void addTrackKern( TrackKern kern )
+    {
+        trackKern.add( kern );
+    }
+
+    /** Getter for property composites.
+     * @return Value of property composites.
+     */
+    public List getComposites()
+    {
+        return composites;
+    }
+
+    /** Setter for property composites.
+     * @param compositesList New value of property composites.
+     */
+    public void setComposites(List compositesList)
+    {
+        composites = compositesList;
+    }
+
+    /**
+     * This will add a single composite part to the picture.
+     *
+     * @param composite The composite info to add.
+     */
+    public void addComposite( Composite composite )
+    {
+        composites.add( composite );
+    }
+
+    /** Getter for property kernPairs.
+     * @return Value of property kernPairs.
+     */
+    public java.util.List getKernPairs()
+    {
+        return kernPairs;
+    }
+
+    /**
+     * This will add a kern pair.
+     *
+     * @param kernPair The kern pair to add.
+     */
+    public void addKernPair( KernPair kernPair )
+    {
+        kernPairs.add( kernPair );
+    }
+
+    /** Setter for property kernPairs.
+     * @param kernPairsList New value of property kernPairs.
+     */
+    public void setKernPairs(java.util.List kernPairsList)
+    {
+        kernPairs = kernPairsList;
+    }
+
+    /** Getter for property kernPairs0.
+     * @return Value of property kernPairs0.
+     */
+    public java.util.List getKernPairs0()
+    {
+        return kernPairs0;
+    }
+
+    /**
+     * This will add a kern pair.
+     *
+     * @param kernPair The kern pair to add.
+     */
+    public void addKernPair0( KernPair kernPair )
+    {
+        kernPairs0.add( kernPair );
+    }
+
+    /** Setter for property kernPairs0.
+     * @param kernPairs0List New value of property kernPairs0.
+     */
+    public void setKernPairs0(java.util.List kernPairs0List)
+    {
+        kernPairs0 = kernPairs0List;
+    }
+
+    /** Getter for property kernPairs1.
+     * @return Value of property kernPairs1.
+     */
+    public java.util.List getKernPairs1()
+    {
+        return kernPairs1;
+    }
+
+    /**
+     * This will add a kern pair.
+     *
+     * @param kernPair The kern pair to add.
+     */
+    public void addKernPair1( KernPair kernPair )
+    {
+        kernPairs1.add( kernPair );
+    }
+
+    /** Setter for property kernPairs1.
+     * @param kernPairs1List New value of property kernPairs1.
+     */
+    public void setKernPairs1(java.util.List kernPairs1List)
+    {
+        kernPairs1 = kernPairs1List;
+    }
+
+    /** Getter for property standardHorizontalWidth.
+     * @return Value of property standardHorizontalWidth.
+     */
+    public float getStandardHorizontalWidth()
+    {
+        return standardHorizontalWidth;
+    }
+
+    /** Setter for property standardHorizontalWidth.
+     * @param standardHorizontalWidthValue New value of property standardHorizontalWidth.
+     */
+    public void setStandardHorizontalWidth(float standardHorizontalWidthValue)
+    {
+        standardHorizontalWidth = standardHorizontalWidthValue;
+    }
+
+    /** Getter for property standardVerticalWidth.
+     * @return Value of property standardVerticalWidth.
+     */
+    public float getStandardVerticalWidth()
+    {
+        return standardVerticalWidth;
+    }
+
+    /** Setter for property standardVerticalWidth.
+     * @param standardVerticalWidthValue New value of property standardVerticalWidth.
+     */
+    public void setStandardVerticalWidth(float standardVerticalWidthValue)
+    {
+        standardVerticalWidth = standardVerticalWidthValue;
+    }
+
+}
\ No newline at end of file

Added: incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/KernPair.java
URL: http://svn.apache.org/viewvc/incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/KernPair.java?rev=678810&view=auto
==============================================================================
--- incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/KernPair.java (added)
+++ incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/KernPair.java Tue Jul 22 10:20:54 2008
@@ -0,0 +1,110 @@
+/**
+ * Copyright (c) 2005, www.fontbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. Neither the name of fontbox; nor the names of its
+ *    contributors may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.fontbox.org
+ *
+ */
+package org.fontbox.afm;
+
+/**
+ * This represents some kern pair data.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class KernPair
+{
+    private String firstKernCharacter;
+    private String secondKernCharacter;
+    private float x;
+    private float y;
+
+    /** Getter for property firstKernCharacter.
+     * @return Value of property firstKernCharacter.
+     */
+    public java.lang.String getFirstKernCharacter()
+    {
+        return firstKernCharacter;
+    }
+
+    /** Setter for property firstKernCharacter.
+     * @param firstKernCharacterValue New value of property firstKernCharacter.
+     */
+    public void setFirstKernCharacter(String firstKernCharacterValue)
+    {
+        firstKernCharacter = firstKernCharacterValue;
+    }
+
+    /** Getter for property secondKernCharacter.
+     * @return Value of property secondKernCharacter.
+     */
+    public java.lang.String getSecondKernCharacter()
+    {
+        return secondKernCharacter;
+    }
+
+    /** Setter for property secondKernCharacter.
+     * @param secondKernCharacterValue New value of property secondKernCharacter.
+     */
+    public void setSecondKernCharacter(String secondKernCharacterValue)
+    {
+        secondKernCharacter = secondKernCharacterValue;
+    }
+
+    /** Getter for property x.
+     * @return Value of property x.
+     */
+    public float getX()
+    {
+        return x;
+    }
+
+    /** Setter for property x.
+     * @param xValue New value of property x.
+     */
+    public void setX(float xValue)
+    {
+        x = xValue;
+    }
+
+    /** Getter for property y.
+     * @return Value of property y.
+     */
+    public float getY()
+    {
+        return y;
+    }
+
+    /** Setter for property y.
+     * @param yValue New value of property y.
+     */
+    public void setY(float yValue)
+    {
+        y = yValue;
+    }
+
+}
\ No newline at end of file

Added: incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/Ligature.java
URL: http://svn.apache.org/viewvc/incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/Ligature.java?rev=678810&view=auto
==============================================================================
--- incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/Ligature.java (added)
+++ incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/Ligature.java Tue Jul 22 10:20:54 2008
@@ -0,0 +1,76 @@
+/**
+ * Copyright (c) 2005, www.fontbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. Neither the name of fontbox; nor the names of its
+ *    contributors may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.fontbox.org
+ *
+ */
+package org.fontbox.afm;
+
+/**
+ * This class represents a ligature, which is an entry of the CharMetrics.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class Ligature
+{
+    private String successor;
+    private String ligature;
+
+    /** Getter for property ligature.
+     * @return Value of property ligature.
+     */
+    public String getLigature()
+    {
+        return ligature;
+    }
+
+    /** Setter for property ligature.
+     * @param lig New value of property ligature.
+     */
+    public void setLigature(String lig)
+    {
+        ligature = lig;
+    }
+
+    /** Getter for property successor.
+     * @return Value of property successor.
+     */
+    public String getSuccessor()
+    {
+        return successor;
+    }
+
+    /** Setter for property successor.
+     * @param successorValue New value of property successor.
+     */
+    public void setSuccessor(String successorValue)
+    {
+        successor = successorValue;
+    }
+
+}
\ No newline at end of file

Added: incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/TrackKern.java
URL: http://svn.apache.org/viewvc/incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/TrackKern.java?rev=678810&view=auto
==============================================================================
--- incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/TrackKern.java (added)
+++ incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/TrackKern.java Tue Jul 22 10:20:54 2008
@@ -0,0 +1,127 @@
+/**
+ * Copyright (c) 2005, www.fontbox.org
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. Neither the name of fontbox; nor the names of its
+ *    contributors may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://www.fontbox.org
+ *
+ */
+package org.fontbox.afm;
+
+/**
+ * This class represents a piece of track kerning data.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class TrackKern
+{
+    private int degree;
+    private float minPointSize;
+    private float minKern;
+    private float maxPointSize;
+    private float maxKern;
+
+    /** Getter for property degree.
+     * @return Value of property degree.
+     */
+    public int getDegree()
+    {
+        return degree;
+    }
+
+    /** Setter for property degree.
+     * @param degreeValue New value of property degree.
+     */
+    public void setDegree(int degreeValue)
+    {
+        degree = degreeValue;
+    }
+
+    /** Getter for property maxKern.
+     * @return Value of property maxKern.
+     */
+    public float getMaxKern()
+    {
+        return maxKern;
+    }
+
+    /** Setter for property maxKern.
+     * @param maxKernValue New value of property maxKern.
+     */
+    public void setMaxKern(float maxKernValue)
+    {
+        maxKern = maxKernValue;
+    }
+
+    /** Getter for property maxPointSize.
+     * @return Value of property maxPointSize.
+     */
+    public float getMaxPointSize()
+    {
+        return maxPointSize;
+    }
+
+    /** Setter for property maxPointSize.
+     * @param maxPointSizeValue New value of property maxPointSize.
+     */
+    public void setMaxPointSize(float maxPointSizeValue)
+    {
+        maxPointSize = maxPointSizeValue;
+    }
+
+    /** Getter for property minKern.
+     * @return Value of property minKern.
+     */
+    public float getMinKern()
+    {
+        return minKern;
+    }
+
+    /** Setter for property minKern.
+     * @param minKernValue New value of property minKern.
+     */
+    public void setMinKern(float minKernValue)
+    {
+        minKern = minKernValue;
+    }
+
+    /** Getter for property minPointSize.
+     * @return Value of property minPointSize.
+     */
+    public float getMinPointSize()
+    {
+        return minPointSize;
+    }
+
+    /** Setter for property minPointSize.
+     * @param minPointSizeValue New value of property minPointSize.
+     */
+    public void setMinPointSize(float minPointSizeValue)
+    {
+        minPointSize = minPointSizeValue;
+    }
+
+}
\ No newline at end of file

Added: incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/package.html
URL: http://svn.apache.org/viewvc/incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/package.html?rev=678810&view=auto
==============================================================================
--- incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/package.html (added)
+++ incubator/pdfbox/trunk/fontbox/src/org/fontbox/afm/package.html Tue Jul 22 10:20:54 2008
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+
+</head>
+<body>
+This package holds classes used to parse AFM(Adobe Font Metrics) files.
+<br/>
+More information about AFM files can be found at
+<a href="http://partners.adobe.com/asn/developer/type/">http://partners.adobe.com/asn/developer/type/</a>
+</body>
+</html>