You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by fo...@apache.org on 2001/02/27 13:28:21 UTC

cvs commit: xml-fop/src/org/apache/fop/render/pdf Font.java FontSetup.java PDFRenderer.java

fotis       01/02/27 04:28:21

  Modified:    conf     config.xml userconfig.xml
               src/org/apache/fop/configuration Configuration.java
                        ConfigurationParser.java ConfigurationReader.java
               src/org/apache/fop/fonts Glyphs.java PFMFile.java
                        TTFCmapEntry.java TTFDirTabEntry.java TTFFile.java
                        TTFMtxEntry.java
               src/org/apache/fop/fonts/apps PFMReader.java TTFReader.java
               src/org/apache/fop/layout FontInfo.java FontState.java
                        LineArea.java
               src/org/apache/fop/pdf PDFCIDFont.java
                        PDFCIDFontDescriptor.java PDFCMap.java
                        PDFDocument.java PDFFont.java
                        PDFFontDescriptor.java PDFFontType0.java
                        PDFWArray.java
               src/org/apache/fop/render/pdf Font.java FontSetup.java
                        PDFRenderer.java
  Log:
  enabling CID keyed truetype fonts; this gives support
           for other encodings than WinAnsiEncoding (eg japanese, chinese, arabic,
           iso-whatever, etc). Also makes font inclusion easier Tore Engvig
  
  Revision  Changes    Path
  1.6       +55 -53    xml-fop/conf/config.xml
  
  Index: config.xml
  ===================================================================
  RCS file: /home/cvs/xml-fop/conf/config.xml,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- config.xml	2001/02/23 16:48:01	1.5
  +++ config.xml	2001/02/27 12:28:14	1.6
  @@ -1,53 +1,55 @@
  -<!--<!DOCTYPE configuration SYSTEM "config.dtd">-->
  -<!-- to developers: have a look at the config.dtd to 
  -     see how to structure your config entries -->
  -
  -<configuration>
  -  <entry>
  -    <key>version</key>
  -    <value>FOP 0.17.0 DEV</value>
  -  </entry>
  -
  -  <!-- default values for commandline options -->
  -  <!-- suppress all progress information, error message are still displayed -->
  -  <entry>
  -    <key>quiet</key>
  -    <value>false</value>
  -  </entry>
  -<!-- sets debug mode on/off; debug mode hasm more progress 
  -     information and a stacktrace in case of a fatal exception -->
  -  <entry>
  -    <key>debugMode</key>
  -    <value>false</value>
  -  </entry>
  -  <!-- displays all configuration  settings and then exits -->
  -  <entry>
  -    <key>dumpConfiguration</key>
  -    <value>false</value>
  -  </entry>
  -  <!--  -->
  -  <entry>
  -    <key>debugMode</key>
  -    <value>false</value>
  -  </entry>
  -
  -
  -  <!-- stream-filter-list provides the default filters that are applied to all
  -       stream objects within the PDF file. These are normally used for 
  -       compression -->
  -  <entry role="pdf">
  -    <key>stream-filter-list</key>
  -    <list>
  -      <!-- provides compression using zlib flate (default is on)-->
  -      <value>flate</value>
  -      
  -      <!-- encodes binary data into printable ascii characters (default off)
  -           This provides about a 4:5 expansion of data size -->
  -      <value>ascii-85</value>
  -
  -      <!-- encodes binary data with hex representation (default off)
  -           This filter is not recommended as it doubles the data size -->
  -      <!-- <value>ascii-hex</value> -->
  -    </list>
  -  </entry>
  -</configuration>
  +<!--<!DOCTYPE configuration SYSTEM "config.dtd">-->
  +<!-- to developers: have a look at the config.dtd to 
  +     see how to structure your config entries -->
  +
  +<configuration>
  +  <entry>
  +    <key>version</key>
  +    <value>FOP 0.17.0 DEV</value>
  +  </entry>
  +
  +  <!-- default values for commandline options -->
  +  <!-- suppress all progress information, error message are still displayed -->
  +  <entry>
  +    <key>quiet</key>
  +    <value>false</value>
  +  </entry>
  +<!-- sets debug mode on/off; debug mode hasm more progress 
  +     information and a stacktrace in case of a fatal exception -->
  +  <entry>
  +    <key>debugMode</key>
  +    <value>false</value>
  +  </entry>
  +  <!-- displays all configuration  settings and then exits -->
  +  <entry>
  +    <key>dumpConfiguration</key>
  +    <value>false</value>
  +  </entry>
  +  <!--  -->
  +  <entry>
  +    <key>debugMode</key>
  +    <value>false</value>
  +  </entry>
  +
  +
  +  <!-- stream-filter-list provides the default filters that are applied to all
  +       stream objects within the PDF file. These are normally used for 
  +       compression -->
  +  <entry role="pdf">
  +    <key>stream-filter-list</key>
  +    <list>
  +      <!-- provides compression using zlib flate (default is on)-->
  +      <value>flate</value>
  +      
  +      <!-- encodes binary data into printable ascii characters (default off)
  +           This provides about a 4:5 expansion of data size -->
  +      <value>ascii-85</value>
  +
  +      <!-- encodes binary data with hex representation (default off)
  +           This filter is not recommended as it doubles the data size -->
  +      <!-- <value>ascii-hex</value> -->
  +    </list>
  +  </entry>
  +  <fonts>
  +  </fonts>
  +</configuration>
  
  
  
  1.3       +22 -20    xml-fop/conf/userconfig.xml
  
  Index: userconfig.xml
  ===================================================================
  RCS file: /home/cvs/xml-fop/conf/userconfig.xml,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- userconfig.xml	2001/02/05 08:35:23	1.2
  +++ userconfig.xml	2001/02/27 12:28:14	1.3
  @@ -42,30 +42,32 @@
   
   <!--
   ************************************************************************
  -  Use kerning, default is to noe use kerning, uncomment to use kerning
  +  Add fonts here
   ************************************************************************
   -->
   
  -  <entry>
  -    <key>use-kerning</key>
  -    <value>yes</value>
  -  </entry>
  +<fonts>
  + <!-- example -->
  + <!--
  + <font metrics-file="arial.xml" kerning="yes" embed-file="arial.ttf">
  +    <font-triplet name="Arial" style="normal" weight="normal"/>
  +    <font-triplet name="ArialMT" style="normal" weight="normal"/>
  + </font>
  + <font metrics-file="arialb.xml" kerning="yes" embed-file="arialb.ttf">
  +    <font-triplet name="Arial" style="normal" weight="bold"/>
  +    <font-triplet name="ArialMT" style="normal" weight="bold"/>
  + </font>
  + <font metrics-file="ariali.xml" kerning="yes" embed-file="ariali.ttf">
  +    <font-triplet name="Arial" style="italics" weight="normal"/>
  +    <font-triplet name="ArialMT" style="italics" weight="normal"/>
  + </font>
  + <font metrics-file="arialbi.xml" kerning="yes" embed-file="arialbi.ttf">
  +    <font-triplet name="Arial" style="italics" weight="bold"/>
  +    <font-triplet name="ArialMT" style="italics" weight="bold"/>
  + </font>
  + -->
  +</fonts>
   
  -
  -<!--
  -************************************************************************
  -   Font embedding, only the fonts mentioned here is embedded 
  -   The value is the name of the font (the name is what is returned by
  -   the font's fontName() method
  -************************************************************************
  --->
  -  <entry>
  -    <key>embed-fonts</key>
  -    <list>
  -       <value>Perpetua</value>
  -       <value>Perpetua,Bold</value>
  -    </list>
  -  </entry>
   
   </configuration>
   
  
  
  
  1.4       +11 -0     xml-fop/src/org/apache/fop/configuration/Configuration.java
  
  Index: Configuration.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/configuration/Configuration.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- Configuration.java	2001/02/21 01:09:16	1.3
  +++ Configuration.java	2001/02/27 12:28:14	1.4
  @@ -220,6 +220,17 @@
   
   
       /**
  +       *  method to access fonts values in the standard configuration
  +       *
  +       *  @param key a string containing the key value for the configuration value
  +       *  @return Hashtable a Hashtable containing the values
  +       *          null   if the key is not defined.
  +       */
  +	public static Vector getFonts() {
  +		return (Vector) Configuration.getValue("fonts", Configuration.STANDARD);
  +	}
  +	
  +    /**
          * initializes this configuration
          * @param config contains the configuration information
          */
  
  
  
  1.7       +68 -14    xml-fop/src/org/apache/fop/configuration/ConfigurationParser.java
  
  Index: ConfigurationParser.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/configuration/ConfigurationParser.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- ConfigurationParser.java	2001/02/21 01:09:21	1.6
  +++ ConfigurationParser.java	2001/02/27 12:28:14	1.7
  @@ -7,14 +7,19 @@
   
   package org.apache.fop.configuration;
   
  +//sax
   import org.xml.sax.helpers.DefaultHandler;
   import org.xml.sax.Attributes;
   import org.xml.sax.Locator;
  +
  +//java
   import java.util.Hashtable;
   import java.util.Vector;
   
  +//fop
   import org.apache.fop.messaging.MessageHandler;
   
  +
   /**
    * SAX2 Handler which retrieves the configuration information and stores them in Configuration.
    * Normally this class doesn't need to be accessed directly.
  @@ -28,6 +33,8 @@
       private final int IN_LIST = 8;
       private final int IN_SUBENTRY = 16;
       private final int IN_SUBKEY = 32;
  +	private final int IN_FONTS = 64;
  +	private final int IN_FONT = 128;
   
       private final int STRING = 0;
       private final int LIST = 1;
  @@ -62,6 +69,23 @@
       /** determines role / target of configuration information, default is standard */
       private String role = "standard";
   
  +    //stores fonts
  +    private Vector fontList = null;
  +	
  +    //stores information on one font
  +    private FontInfo fontInfo = null;
  +
  +	//stores information on a font triplet
  +	private FontTriplet fontTriplet = null;
  +	
  +	//information on a font
  +	private String fontName, metricsFile, embedFile, kerningAsString;
  +	private boolean kerning;
  +	private Vector fontTriplets;
  +	
  +	//information on a font triplet
  +	private String fontTripletName, weight, style;
  +	
       public void startDocument() {
           configuration = Configuration.getConfiguration();
       }
  @@ -93,6 +117,25 @@
                   role = attributes.getValue("role");
               }
           } else if (localName.equals("configuration") ) {
  +		} else if (localName.equals("fonts") ) {  //list of fonts starts
  +			fontList = new Vector (10);
  +		} else if (localName.equals("font") ) {
  +			kerningAsString = attributes.getValue("kerning");
  +			if (kerningAsString.equalsIgnoreCase("yes")) {
  +				kerning = true;
  +			} else {
  +				kerning = false;
  +			}
  +			metricsFile = attributes.getValue("metrics-file");
  +			embedFile = attributes.getValue("embed-file");
  +			fontName = attributes.getValue("name");
  +			fontTriplets = new Vector(5);
  +		} else if (localName.equals("font-triplet") ) {			
  +			fontTripletName = attributes.getValue("name");
  +			weight = attributes.getValue("weight"); 
  +			style = attributes.getValue("style");
  +			fontTriplet = new FontTriplet(fontTripletName,weight,style);
  +			fontTriplets.addElement(fontTriplet);
           } else {
               //to make sure that user knows about false tag
               MessageHandler.errorln(
  @@ -117,20 +160,31 @@
               }
               status = OUT;
               role = "standard";
  -	    key = "";
  -	    value = "";
  -	} else if (localName.equals("subentry")) {
  -            map.put(subkey, value);
  -            status -= IN_SUBENTRY;
  -	    key = "";
  -	    value = "";
  -        } else if (localName.equals("key")) {
  -            status -= IN_KEY;
  -        } else if (localName.equals("list")) {
  -            status -= IN_LIST;
  -	    value = "";
  -	} else if (localName.equals("value")) {
  -            status -= IN_VALUE;
  +		    key = "";
  +		    value = "";
  +		} else if (localName.equals("subentry")) {
  +	            map.put(subkey, value);
  +	            status -= IN_SUBENTRY;
  +		    key = "";
  +		    value = "";
  +	        } else if (localName.equals("key")) {
  +	            status -= IN_KEY;
  +	        } else if (localName.equals("list")) {
  +	            status -= IN_LIST;
  +		    value = "";
  +		} else if (localName.equals("value")) {
  +	            status -= IN_VALUE;
  +		} else if (localName.equals("fonts") ) {
  +			this.store("standard", "fonts", fontList);
  +		} else if (localName.equals("font") ) {			
  +			fontInfo = new FontInfo(fontName,metricsFile,kerning,fontTriplets,embedFile);
  +			fontList.addElement(fontInfo);
  +			fontTriplets = null;
  +			metricsFile = null;
  +			embedFile = null;
  +			fontName = null;
  +			kerningAsString = "";			
  +		} else if (localName.equals("font-triplet") ) {			
           }
       }
   
  
  
  
  1.5       +51 -7     xml-fop/src/org/apache/fop/configuration/ConfigurationReader.java
  
  Index: ConfigurationReader.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/configuration/ConfigurationReader.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- ConfigurationReader.java	2001/02/21 01:09:25	1.4
  +++ ConfigurationReader.java	2001/02/27 12:28:14	1.5
  @@ -1,9 +1,53 @@
  -/* 
  - * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
  - * For details on use and redistribution please refer to the 
  - * LICENSE file included with these sources."
  - */
  +/*
  +
  + ============================================================================
  +                   The Apache Software License, Version 1.1
  + ============================================================================
  +
  +    Copyright (C) 1999 The Apache Software Foundation. All rights reserved.
  +
  + Redistribution and use in source and binary forms, with or without modifica-
  + tion, 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. The end-user documentation included with the redistribution, if any, must
  +    include  the following  acknowledgment:  "This product includes  software
  +    developed  by the  Apache Software Foundation  (http://www.apache.org/)."
  +    Alternately, this  acknowledgment may  appear in the software itself,  if
  +    and wherever such third-party acknowledgments normally appear.
  +
  + 4. The names "Fop" and  "Apache Software Foundation"  must not be used to
  +    endorse  or promote  products derived  from this  software without  prior
  +    written permission. For written permission, please contact
  +    apache@apache.org.
  +
  + 5. Products  derived from this software may not  be called "Apache", nor may
  +    "Apache" appear  in their name,  without prior written permission  of the
  +    Apache Software Foundation.
  +
  + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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
  + APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
  + INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
  + DING, 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.
  +
  + This software  consists of voluntary contributions made  by many individuals
  + on  behalf of the Apache Software  Foundation and was  originally created by
  + James Tauber <jt...@jtauber.com>. For more  information on the Apache
  + Software Foundation, please see <http://www.apache.org/>.
   
  + */
   
   package org.apache.fop.configuration;
   
  @@ -31,7 +75,7 @@
    *     }
    *  </code>
    *  Once the configuration has been setup, the information can be accessed with
  - *  the methods of Configuration.
  + *  the methods of StandardConfiguration.
    */
   
   public class ConfigurationReader {
  @@ -103,7 +147,7 @@
          *
          * @return the created SAX parser
          */
  -    static XMLReader createParser() {
  +    public static XMLReader createParser() {
           String parserClassName = System.getProperty("org.xml.sax.parser");
           if (parserClassName == null) {
               parserClassName = "org.apache.xerces.parsers.SAXParser";
  
  
  
  1.2       +249 -2    xml-fop/src/org/apache/fop/fonts/Glyphs.java
  
  Index: Glyphs.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/fonts/Glyphs.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Glyphs.java	2001/02/05 08:35:27	1.1
  +++ Glyphs.java	2001/02/27 12:28:15	1.2
  @@ -1,4 +1,4 @@
  -/* -- $Id: Glyphs.java,v 1.1 2001/02/05 08:35:27 kellyc Exp $ --
  +/* -- $Id: Glyphs.java,v 1.2 2001/02/27 12:28:15 fotis Exp $ --
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -604,7 +604,254 @@
         "yacute",
         "thorn",
         "ydieresis"};
  -      
  +
  +        /** The characters in WinAnsiEncoding */
  +    public static char[] winAnsiEncoding = {
  +            // not used until char 32
  +        0,0,0,0,0,0,0,0,
  +        0,0,0,0,0,0,0,0,
  +        0,0,0,0,0,0,0,0,
  +        0,0,0,0,0,0,0,0,
  +            // 0x20
  +        ' ',
  +        '\u0021',
  +        '\"',
  +        '\u0023',
  +        '$',
  +        '%',
  +        '&',
  +        '\'',
  +        '(',
  +        ')',
  +        '*',
  +        '+',
  +        ',',
  +        '\u002d',
  +        '\u002e',
  +        '/',
  +            // 0x30
  +        '0',
  +        '1',
  +        '2',
  +        '3',
  +        '4',
  +        '5',
  +        '6',
  +        '7',
  +        '8',
  +        '9',
  +        ':',
  +        ';',
  +        '<',
  +        '=',
  +        '>',
  +        '?',
  +        '@',
  +            // 0x40
  +        'A',
  +        'B',
  +        'C',
  +        'D',
  +        'E',
  +        'F',
  +        'G',
  +        'H',
  +        'I',
  +        'J',
  +        'K',
  +        'L',
  +        'M',
  +        'N',
  +        'O',
  +            // 0x50
  +        'P',
  +        'Q',
  +        'R',
  +        'S',
  +        'T',
  +        'U',
  +        'V',
  +        'W',
  +        'X',
  +        'Y',
  +        'Z',
  +        '\u005b',
  +        '\\',
  +        '\u005d',
  +        '\u005e',
  +        '_',
  +            // 0x60
  +        '\u2018',
  +        'a',
  +        'b',
  +        'c',
  +        'd',
  +        'e',
  +        'f',
  +        'g',
  +        'h',
  +        'i',
  +        'j',
  +        'k',
  +        'l',
  +        'm',
  +        'n',
  +        'o',
  +            // 0x70
  +        'p',
  +        'q',
  +        'r',
  +        's',
  +        't',
  +        'u',
  +        'v',
  +        'w',
  +        'x',
  +        'y',
  +        'z',
  +        '\u007b',
  +        '\u007c',
  +        '\u007d',
  +        '\u007e',
  +        '\u2022',
  +            // 0x80
  +        '\u20ac',
  +        '\u2022',
  +        '\u201a',
  +        '\u0192',
  +        '\u201e',
  +        '\u2026',
  +        '\u2020',
  +        '\u2021',
  +        '\u02c6',
  +        '\u2030',
  +        '\u0160',
  +        '\u2039',
  +        '\u0152',
  +        '\u2022',
  +        '\u017d',
  +        '\u2022',
  +            // 0x90
  +        '\u2022',
  +        '\u2018', // quoteleft
  +        '\u2019', // quoteright
  +        '\u201c', // quotedblleft
  +        '\u201d', // quotedblright
  +        '\u2022', // bullet
  +        '\u2013', // endash
  +        '\u2014', // emdash
  +        '~',
  +        '\u2022', // bullet
  +        '\u0161',
  +        '\u203a',
  +        '\u0153',
  +        '\u2022',
  +        '\u017e',
  +        '\u0178',
  +            // 0xA0
  +        ' ',
  +        '\u00a1',
  +        '\u00a2',
  +        '�',
  +        '\u00a4',
  +        '\u00a5',
  +        '\u00a6',
  +        '\u00a7',
  +        '\u00a8',
  +        '\u00a9',
  +        '\u00aa',
  +        '\u00ab',
  +        '\u00ac',
  +        '\u00ad',
  +        '\u00ae',
  +        '\u00af',
  +            // 0xb0
  +        '\u00b0',
  +        '\u00b1',
  +        '\u00b2',
  +        '\u00b3',
  +        '\u00b4',
  +        '\u00b5', // This is hand-coded, the rest is assumption
  +        '\u00b6', // and *might* not be correct...
  +        '\u00b7',
  +        '\u00b8',
  +        '\u00b9',
  +        '\u00ba',
  +        '\u00bb',
  +        '\u00bc',
  +        '\u00bd',
  +        '\u00be',
  +        '\u00bf',
  +            // 0xc0
  +        '\u00c0',
  +        '\u00c1',
  +        '\u00c2',
  +        '\u00c3',
  +        '\u00c4',
  +        '\u00c5', // Aring
  +        '\u00c6', // AE
  +        '\u00c7',
  +        '\u00c8',
  +        '\u00c9',
  +        '\u00ca',
  +        '\u00cb',
  +        '\u00cc',
  +        '\u00cd',
  +        '\u00ce',
  +        '\u00cf',
  +            // 0xd0
  +        '\u00d0',
  +        '\u00d1',
  +        '\u00d2',
  +        '\u00d3',
  +        '\u00d4',
  +        '\u00d5',
  +        '\u00d6',
  +        '\u00d7',
  +        '\u00d8', // Oslash
  +        '\u00d9',
  +        '\u00da',
  +        '\u00db',
  +        '\u00dc',
  +        '\u00dd',
  +        '\u00de',
  +        '\u00df',
  +            // 0xe0
  +        '\u00e0',
  +        '\u00e1',
  +        '\u00e2',
  +        '\u00e3',
  +        '\u00e4',
  +        '\u00e5', // aring
  +        '\u00e6', // ae
  +        '\u00e7',
  +        '\u00e8',
  +        '\u00e9',
  +        '\u00ea',
  +        '\u00eb',
  +        '\u00ec',
  +        '\u00ed',
  +        '\u00ee',
  +        '\u00ef',
  +            // 0xf0
  +        '\u00f0',
  +        '\u00f1',
  +        '\u00f2',
  +        '\u00f3',
  +        '\u00f4',
  +        '\u00f5',
  +        '\u00f6',
  +        '\u00f7',
  +        '\u00f8',
  +        '\u00f9',
  +        '\u00fa',
  +        '\u00fb',
  +        '\u00fc',
  +        '\u00fd',
  +        '\u00fe',
  +        '\u00ff'
  +    };
  +    
      static String[] unicode_glyphs={
           "\u0041", "A",
           "\u00C6", "AE",
  
  
  
  1.3       +4 -4      xml-fop/src/org/apache/fop/fonts/PFMFile.java
  
  Index: PFMFile.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/fonts/PFMFile.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- PFMFile.java	2001/02/05 08:35:27	1.2
  +++ PFMFile.java	2001/02/27 12:28:15	1.3
  @@ -1,4 +1,4 @@
  -/*-- $Id: PFMFile.java,v 1.2 2001/02/05 08:35:27 kellyc Exp $ --
  +/*-- $Id: PFMFile.java,v 1.3 2001/02/27 12:28:15 fotis Exp $ --
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -203,11 +203,11 @@
              String glyph1=Glyphs.tex8r[g1];
              String glyph2=Glyphs.tex8r[g2];
   
  -           Hashtable adjTab=(Hashtable)kerningTab.get(glyph1);
  +           Hashtable adjTab=(Hashtable)kerningTab.get(new Integer(g1));
              if (adjTab==null)
                 adjTab=new Hashtable();
  -           adjTab.put(glyph2, new Integer(adj));
  -           kerningTab.put(glyph1, adjTab);
  +           adjTab.put(new Integer(g2), new Integer(adj));
  +           kerningTab.put(new Integer(g1), adjTab);
           }
       }
   
  
  
  
  1.2       +35 -8     xml-fop/src/org/apache/fop/fonts/TTFCmapEntry.java
  
  Index: TTFCmapEntry.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/fonts/TTFCmapEntry.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TTFCmapEntry.java	2001/02/05 08:35:27	1.1
  +++ TTFCmapEntry.java	2001/02/27 12:28:15	1.2
  @@ -1,4 +1,4 @@
  -/* -- $Id: TTFCmapEntry.java,v 1.1 2001/02/05 08:35:27 kellyc Exp $ --
  +/* -- $Id: TTFCmapEntry.java,v 1.2 2001/02/27 12:28:15 fotis Exp $ --
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -50,11 +50,38 @@
    */
   package org.apache.fop.fonts;
   
  -class TTFCmapEntry {
  -   int platform_id;
  -   int encoding_id;
  -   long offset;
  -   
  -   TTFCmapEntry() {
  -   }
  +/**
  + * The CMap entry contains information of a Unicode range and the
  + * the glyph indexes related to the range
  + */
  +public class TTFCmapEntry {
  +    public int unicodeStart;
  +    public int unicodeEnd;
  +    public int glyphStartIndex;
  +    
  +    TTFCmapEntry() {
  +        unicodeStart = 0;
  +        unicodeEnd = 0;
  +        glyphStartIndex = 0;
  +    }
  +
  +    TTFCmapEntry (int unicodeStart,
  +                  int unicodeEnd,
  +                  int glyphStartIndex) {
  +        this.unicodeStart = unicodeStart;
  +        this.unicodeEnd = unicodeEnd;
  +        this.glyphStartIndex = glyphStartIndex;
  +    }
  +
  +    public boolean equals (Object o) {
  +        if (o instanceof TTFCmapEntry) {
  +            TTFCmapEntry ce = (TTFCmapEntry)o;
  +            if (ce.unicodeStart == this.unicodeStart &&
  +                ce.unicodeEnd == this.unicodeEnd &&
  +                ce.glyphStartIndex == this.glyphStartIndex)
  +                return true;
  +        }
  +        return false;
  +    }
  +                    
   }
  
  
  
  1.2       +33 -31    xml-fop/src/org/apache/fop/fonts/TTFDirTabEntry.java
  
  Index: TTFDirTabEntry.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/fonts/TTFDirTabEntry.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TTFDirTabEntry.java	2001/02/05 08:35:27	1.1
  +++ TTFDirTabEntry.java	2001/02/27 12:28:15	1.2
  @@ -1,4 +1,4 @@
  -/* -- $Id: TTFDirTabEntry.java,v 1.1 2001/02/05 08:35:27 kellyc Exp $ --
  +/* -- $Id: TTFDirTabEntry.java,v 1.2 2001/02/27 12:28:15 fotis Exp $ --
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -52,34 +52,36 @@
   import java.io.*;
   
   class TTFDirTabEntry {
  -   byte[] tag;
  -   int checksum;
  -   long offset;
  -   long length;
  -
  -   TTFDirTabEntry() {
  -      tag = new byte[4];
  -   }
  -
  -       /** Read Dir Tab, return tag name */ 
  -   public String read(FontFileReader in) throws IOException {
  -      tag[0]=in.readTTFByte();
  -      tag[1]=in.readTTFByte();
  -      tag[2]=in.readTTFByte();
  -      tag[3]=in.readTTFByte();
  -
  -      in.skip(4); // Skip checksum
  -      
  -      offset=in.readTTFULong();
  -      length=in.readTTFULong();
  -
  -      System.out.println ("Read dir tab [" + tag[0]+
  -                          " "+tag[1] +
  -                          " "+tag[2] +
  -                          " "+tag[3] +
  -                          "] offset: " + offset +
  -                          " length: " + length +
  -                          " name: " + new String(tag)); 
  -      return new String(tag, "ISO-8859-1");
  -   }
  +    byte[] tag;
  +    int checksum;
  +    long offset;
  +    long length;
  +    
  +    TTFDirTabEntry() {
  +        tag = new byte[4];
  +    }
  +    
  +        /** Read Dir Tab, return tag name */ 
  +    public String read(FontFileReader in) throws IOException {
  +        tag[0]=in.readTTFByte();
  +        tag[1]=in.readTTFByte();
  +        tag[2]=in.readTTFByte();
  +        tag[3]=in.readTTFByte();
  +        
  +        in.skip(4); // Skip checksum
  +        
  +        offset=in.readTTFULong();
  +        length=in.readTTFULong();
  +        
  +            /*
  +              System.out.println ("Read dir tab [" + tag[0]+
  +              " "+tag[1] +
  +              " "+tag[2] +
  +              " "+tag[3] +
  +              "] offset: " + offset +
  +              " length: " + length +
  +              " name: " + new String(tag));
  +            */
  +        return new String(tag, "ISO-8859-1");
  +    }
   }
  
  
  
  1.2       +1018 -456 xml-fop/src/org/apache/fop/fonts/TTFFile.java
  
  Index: TTFFile.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/fonts/TTFFile.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TTFFile.java	2001/02/05 08:35:28	1.1
  +++ TTFFile.java	2001/02/27 12:28:15	1.2
  @@ -1,4 +1,4 @@
  -/* -- $Id: TTFFile.java,v 1.1 2001/02/05 08:35:28 kellyc Exp $ --
  +/* -- $Id: TTFFile.java,v 1.2 2001/02/27 12:28:15 fotis Exp $ --
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -50,274 +50,823 @@
    */
   package org.apache.fop.fonts;
   import java.io.*;
  +import java.util.Enumeration;
   import java.util.Hashtable;
  +import java.util.Vector;
   
  +/**
  + * Reads a TrueType file or a TrueType Collection.
  + * The TrueType spec can be found at the Microsoft
  + * Typography site: http://www.microsoft.com/truetype/
  + */
   public class TTFFile {
  -   static final byte NTABS = 24;
  -   static final int NMACGLYPHS = 258;
  -   static final int MAX_CHAR_CODE = 255;
  -   static final int ENC_BUF_SIZE = 1024;
  -   
  -   boolean is_embeddable=true;
  -   boolean hasSerifs=true;
  -   Hashtable dirTabs;
  -   Hashtable kerningTab;
  -   
  -       /** Position inputstream to position indicated
  -           in the dirtab offset + offset */
  -   void seek_tab(FontFileReader in, String name, long offset)
  -      throws IOException {
  -      TTFDirTabEntry dt=(TTFDirTabEntry)dirTabs.get(name);
  -      if (dt==null) {
  -         System.out.println("Dirtab " + name + " not found.");
  -         return;
  -      }
  -
  -      in.seek_set(dt.offset+offset);
  -   }
  -   
  -   int get_ttf_funit(int n) {
  -      int ret;
  -      if (n < 0) {
  -         long rest1=n % upem;
  -         long storrest=1000*rest1;
  -         long ledd2=rest1/storrest;
  -         ret = -((-1000*n)/upem - (int)ledd2);
  -      } else {
  -         ret = (n/upem)*1000 + ((n % upem)*1000)/upem;
  -      }
  -      
  -      return ret;
  -   }
  +    static final byte NTABS = 24;
  +    static final int NMACGLYPHS = 258;
  +    static final int MAX_CHAR_CODE = 255;
  +    static final int ENC_BUF_SIZE = 1024;
  +    
  +    static String encoding="WinAnsiEncoding"; // Deafult encoding
  +    short firstChar=0;
  +    boolean is_embeddable=true;
  +    boolean hasSerifs=true;
  +    Hashtable dirTabs;   // Table directory
  +    Hashtable kerningTab; // for CIDs
  +    Hashtable ansiKerningTab; // For winAnsiEncoding
  +    Vector cmaps;
  +    Vector unicodeMapping; //
  +    
  +    int upem;  // unitsPerEm from "head" table
  +    int nhmtx; // Number of horizontal metrics
  +    int post_format;
  +    int loca_format;
  +    int nglyphs; // Number of glyphs in font (read from "maxp" table)
  +    int nmglyphs; // Used in fixWidths - remove?
  +    
  +    TTFMtxEntry mtx_tab[]; // Contains glyph data
  +    int[] mtx_encoded=null;
  +    
  +    String fontName="";
  +    String fullName="";
  +    String notice="";
  +    String familyName="";
  +    String subFamilyName="";
  +    
  +    long italicAngle = 0;
  +    long isFixedPitch = 0;
  +    int fontBBox1 = 0;
  +    int fontBBox2 = 0;
  +    int fontBBox3 = 0;
  +    int fontBBox4 = 0;
  +    int capHeight = 0;
  +    int underlinePosition = 0;
  +    int underlineThickness = 0;
  +    int xHeight = 0;
  +    int ascender = 0;
  +    int descender = 0;
  +
  +    short lastChar = 0;
  +
  +    int ansiWidth[];
  +    Hashtable ansiIndex;
  +    
  +        /** Position inputstream to position indicated
  +            in the dirtab offset + offset */
  +    void seek_tab(FontFileReader in, String name, long offset)
  +        throws IOException {
  +        TTFDirTabEntry dt=(TTFDirTabEntry)dirTabs.get(name);
  +        if (dt==null) {
  +            System.out.println("Dirtab " + name + " not found.");
  +            return;
  +        }
  +        
  +        in.seek_set(dt.offset+offset);
  +    }
  +    
  +        /** Convert from truetype unit to pdf unit based on the
  +         * unitsPerEm field in the "head" table
  +         @param n truetype unit
  +         @return pdf unit
  +        */
  +    int get_ttf_funit(int n) {
  +        int ret;
  +        if (n < 0) {
  +            long rest1=n % upem;
  +            long storrest=1000*rest1;
  +            long ledd2=rest1/storrest;
  +            ret = -((-1000*n)/upem - (int)ledd2);
  +        } else {
  +            ret = (n/upem)*1000 + ((n % upem)*1000)/upem;
  +        }
  +        
  +        return ret;
  +    }
  +    
  +        /** Read the cmap table,
  +         * return false if the table is not present or only unsupported
  +         * tables are present. Currently only unicode cmaps are supported.
  +         * Set the unicodeIndex in the TTFMtxEntries and fills in the
  +         * cmaps vector.
  +         */
  +    private boolean readCMAP(FontFileReader in)
  +        throws IOException {
  +
  +        unicodeMapping = new Vector();
  +        
  +            /** Read CMAP table and correct mtx_tab.index*/
  +        int mtxPtr=0;
  +        
  +        seek_tab(in, "cmap", 2);
  +        int num_cmap=in.readTTFUShort(); // Number of cmap subtables
  +        long cmap_unioffset=0;
  +        
  +            //System.out.println(num_cmap+" cmap tables");
  +        
  +            /* Read offset for all tables
  +               We are only interested in the unicode table
  +            */
  +        for (int i=0; i< num_cmap; i++) {
  +            int cmap_pid=in.readTTFUShort();
  +            int cmap_eid=in.readTTFUShort();
  +            long cmap_offset=in.readTTFULong();
  +            
  +                //System.out.println("Platform ID: "+cmap_pid+
  +                //               " Encoding: "+cmap_eid);
  +            
  +            if (cmap_pid==3 && cmap_eid==1)
  +                cmap_unioffset=cmap_offset;
  +        }
  +        
  +        if (cmap_unioffset <= 0) {
  +            System.out.println("Unicode cmap table not present");
  +            return false;
  +        }
  +        
  +            // Read unicode cmap
  +        seek_tab(in, "cmap", cmap_unioffset);
  +        int cmap_format=in.readTTFUShort();
  +        int cmap_length=in.readTTFUShort();
  +        
  +            //System.out.println("CMAP format: "+cmap_format);
  +        if (cmap_format==4) {
  +            in.skip(2); // Skip version number
  +            int cmap_segCountX2=in.readTTFUShort();
  +            int cmap_searchRange=in.readTTFUShort();
  +            int cmap_entrySelector=in.readTTFUShort();
  +            int cmap_rangeShift=in.readTTFUShort();
  +
  +                /*
  +                  System.out.println("segCountX2   : "+cmap_segCountX2);
  +                  System.out.println("searchRange  : "+cmap_searchRange);
  +                  System.out.println("entrySelector: "+cmap_entrySelector);
  +                  System.out.println("rangeShift   : "+cmap_rangeShift);
  +                */
  +            
  +            int cmap_endCounts[]=new int[cmap_segCountX2/2];
  +            int cmap_startCounts[]=new int[cmap_segCountX2/2];
  +            int cmap_deltas[]=new int[cmap_segCountX2/2];
  +            int cmap_rangeOffsets[]=new int[cmap_segCountX2/2];
  +            
  +            for (int i=0; i < (cmap_segCountX2/2); i++) {
  +                cmap_endCounts[i]=in.readTTFUShort();
  +            }
  +            
  +            in.skip(2); // Skip reservedPad
  +            
  +            for (int i=0; i < (cmap_segCountX2/2); i++) {
  +                cmap_startCounts[i]=in.readTTFUShort();
  +            }
  +            
  +            for (int i=0; i < (cmap_segCountX2/2); i++) {
  +                cmap_deltas[i]=in.readTTFShort();
  +            }
  +            
  +            int startRangeOffset=in.getCurrentPos();
  +            
  +            for (int i=0; i < (cmap_segCountX2/2); i++) {
  +                cmap_rangeOffsets[i]=in.readTTFShort();
  +            }
  +            
  +            int glyphIdArrayOffset=in.getCurrentPos();
  +            
  +                // Insert the unicode id for the glyphs in mtx_tab
  +                // and fill in the cmaps Vector
  +            
  +            for (int i = 0; i < cmap_startCounts.length; i++) {
  +                    /*
  +                      System.out.println(i+ ": "+cmap_startCounts[i]+
  +                      " - "+cmap_endCounts[i]);
  +                    */
  +                for (int j=cmap_startCounts[i];
  +                     j <= cmap_endCounts[i]; j++) {
  +                    
  +                        // Update lastChar
  +                    if (j < 256 && j > lastChar) 
  +                        lastChar = (short)j;
  +                                    
  +                    if (mtxPtr < mtx_tab.length) {
  +                        if (cmap_rangeOffsets[i] != 0) {
  +                            int glyphOffset = glyphIdArrayOffset+
  +                                ((cmap_rangeOffsets[i]/2)+
  +                                 (j-cmap_startCounts[i])+
  +                                 (i)-
  +                                 cmap_segCountX2/2)*2;
  +                            in.seek_set(glyphOffset);
  +                            int glyphIdx=(in.readTTFUShort()+
  +                                          cmap_deltas[i]) & 0xffff;
  +
  +                            unicodeMapping.addElement(
  +                                new UnicodeMapping(glyphIdx, j));
  +                            mtx_tab[glyphIdx].unicodeIndex.addElement(new Integer(j));
  +
  +
  +                                // Also add winAnsiWidth
  +                            if (false) {
  +                                int d = j;
  +                                if (j > 127)
  +                                    d = (int)
  +                                        org.apache.fop.render.pdf.CodePointMapping.map[j];
  +                                if (d < ansiWidth.length)
  +                                    ansiWidth[d] = mtx_tab[glyphIdx].wx;
  +                            } else {
  +                                Vector v=
  +                                    (Vector)ansiIndex.get(new Integer(j));
  +                                if (v != null) {
  +                                    for (Enumeration e=v.elements();
  +                                         e.hasMoreElements();) {
  +                                        Integer aIdx = (Integer)e.nextElement();
  +                                        ansiWidth[aIdx.intValue()]=
  +                                            mtx_tab[glyphIdx].wx;
  +                                            /*
  +                                              System.out.println("Added width "+
  +                                              mtx_tab[glyphIdx].wx +
  +                                              " uni: " + j +
  +                                              " ansi: " + aIdx.intValue());
  +                                            */             
  +                                    }
  +                                }
  +                            }
  +                                /*
  +                                  System.out.println("Idx: "+
  +                                  glyphIdx +
  +                                  " Delta: " + cmap_deltas[i]+
  +                                  " Unicode: " + j +
  +                                  " name: " +
  +                                  mtx_tab[glyphIdx].name);
  +                                */
  +
  +                        } else {
  +                            int glyphIdx=(j+cmap_deltas[i]) & 0xffff;
  +
  +                            mtx_tab[glyphIdx].unicodeIndex.addElement(new Integer(j));
  +                                
  +                            unicodeMapping.addElement(
  +                                new UnicodeMapping(glyphIdx,
  +                                                   j));
  +
  +                                // Also add winAnsiWidth
  +                            if (false) {
  +                                int d = j;
  +                                if (j > 127)
  +                                    d = (int)
  +                                        org.apache.fop.render.pdf.CodePointMapping.map[j];
  +                                
  +                                if (d < ansiWidth.length)
  +                                    ansiWidth[d] = mtx_tab[glyphIdx].wx;
  +                            } else {
  +                                Vector v=
  +                                    (Vector)ansiIndex.get(new Integer(j));
  +                                if (v != null) {
  +                                    for (Enumeration e=v.elements();
  +                                         e.hasMoreElements();) {
  +                                        Integer aIdx = (Integer)e.nextElement();
  +                                        ansiWidth[aIdx.intValue()]=
  +                                            mtx_tab[glyphIdx].wx;
  +                                    }
  +                                }
  +                            }
  +                            
  +                                /*
  +                                  System.out.println("IIdx: "+
  +                                  mtxPtr +
  +                                  " Delta: " + cmap_deltas[i]+
  +                                  " Unicode: " + j +
  +                                  " name: " +
  +                                  mtx_tab[(j+cmap_deltas[i]) & 0xffff].name);
  +                                */
  +                        }
  +                        mtxPtr++;
  +                    }
  +                }
  +            }
  +        }
  +        return true;
  +    }
  +    
  +    
  +    
  +        /**
  +         * Print first char/last char
  +         */
  +    private void print_max_min() {
  +        int min=255;
  +        int max=0;
  +        for (int i=0; i < mtx_tab.length; i++) {
  +            if (mtx_tab[i].index < min)
  +                min = mtx_tab[i].index;
  +            if (mtx_tab[i].index > max)
  +                max = mtx_tab[i].index;
  +        }
  +        System.out.println("Min: "+min);
  +        System.out.println("Max: "+max);
  +    }
  +
  +    public void readFont(FontFileReader in) throws IOException {
  +        readFont(in, (String)null);
  +    }
  +
  +        /** initialize the ansiWidths array (for winAnsiEncoding)
  +         * and fill with the missingwidth
  +         */
  +    private void initAnsiWidths() {
  +        ansiWidth=new int[256];
  +        for (int i = 0; i < 256; i++)
  +            ansiWidth[i] = mtx_tab[0].wx;
  +
  +            // Create an index hash to the ansiWidth
  +            // Can't just index the winAnsiEncoding when inserting widths
  +            // same char (eg bullet) is repeated more than one place
  +        ansiIndex=new Hashtable();
  +        for (int i=32; i < Glyphs.winAnsiEncoding.length; i++) {
  +            Integer ansi = new Integer(i);
  +            Integer uni = new Integer((int)Glyphs.winAnsiEncoding[i]);
  +            
  +            Vector v = (Vector)ansiIndex.get(uni);
  +            if (v == null) {
  +                v = new Vector();
  +                ansiIndex.put(uni, v);
  +            }
  +            v.addElement(ansi);
  +        }
  +    }
  +
  +    
  +        /**
  +         * Read the font data
  +         * If the fontfile is a TrueType Collection (.ttf file)
  +         * The name of the font to read data for must be supplied,
  +         * else the name is ignored
  +         */
  +    public void readFont(FontFileReader in, String name) throws IOException {
  +
  +            /* Check if TrueType collection, and that the name
  +               exists in the collection
  +            */
  +        if (!checkTTC(in, name))
  +            throw new IOException("Failed to read font");
  +        
  +        readDirTabs(in);
  +        readFontHeader(in);
  +        readHorizontalHeader(in);
  +        readHorizontalMetrics(in);
  +        initAnsiWidths();
  +        readPostscript(in);
  +        readOS2(in);
  +        readIndexToLocation(in);
  +        readGlyf(in);
  +        readName(in);
  +        readPCLT(in);
  +        readCMAP(in); // Read cmap table and fill in ansiwidths
  +        createCMaps(); // Create cmaps for bfentries
  +            //print_max_min();
  +        
  +        readKerning(in);
  +    }
  +
  +    private void createCMaps() {
  +        cmaps = new Vector();
  +        TTFCmapEntry tce = new TTFCmapEntry();
  +
  +        Enumeration e = unicodeMapping.elements();
  +        UnicodeMapping um = (UnicodeMapping)e.nextElement();
  +        UnicodeMapping lastMapping = um;
  +        
  +        tce.unicodeStart = um.uIdx;
  +        tce.glyphStartIndex = um.gIdx;
  +
  +        while (e.hasMoreElements()) {
  +            um = (UnicodeMapping)e.nextElement();
  +            if (((lastMapping.uIdx+1) != um.uIdx) ||
  +                ((lastMapping.gIdx+1) != um.gIdx)) {
  +                tce.unicodeEnd = lastMapping.uIdx;
  +                cmaps.addElement(tce);
  +                
  +                tce = new TTFCmapEntry();
  +                tce.unicodeStart = um.uIdx;
  +                tce.glyphStartIndex = um.gIdx;
  +            }
  +            lastMapping = um;
  +        }
  +        
  +        tce.unicodeEnd = um.uIdx;
  +        cmaps.addElement(tce);
  +    }
  +
  +    public void printStuff() {
  +        System.out.println("Font name: " + fontName);
  +        System.out.println("Full name: " + fullName);
  +        System.out.println("Family name: " + familyName);
  +        System.out.println("Subfamily name: " + subFamilyName);
  +        System.out.println("Notice:    " + notice);
  +        System.out.println("xHeight:   " + (int)get_ttf_funit(xHeight));
  +        System.out.println("capheight: " + (int)get_ttf_funit(capHeight));
  +        
  +        int italic=(int)(italicAngle>>16);
  +        System.out.println("Italic: " + italic);
  +        System.out.print("ItalicAngle: " + (short)(italicAngle/0x10000));
  +        if ((italicAngle % 0x10000) > 0 )
  +            System.out.print("."+(short)((italicAngle % 0x10000)*1000)/0x10000);
  +        System.out.println();
  +        System.out.println("Ascender:    " + get_ttf_funit(ascender));
  +        System.out.println("Descender:   " + get_ttf_funit(descender));
  +        System.out.println("FontBBox:    [" + (int)get_ttf_funit(fontBBox1) +
  +                           " " + (int)get_ttf_funit(fontBBox2) +
  +                           " " + (int)get_ttf_funit(fontBBox3) +
  +                           " " + (int)get_ttf_funit(fontBBox4)+"]");
  +    }
  +    
  +    public static void main(String[] args) {
  +        try {
  +            TTFFile ttfFile=new TTFFile();
  +            FontFileReader reader=
  +                new FontFileReader(args[0]);
  +
  +            String name=null;
  +            if (args.length >= 2)
  +                name=args[1];
  +            
  +            ttfFile.readFont(reader, name);
  +            ttfFile.printStuff();
  +            
  +        } catch (IOException ioe) {
  +            System.out.println(ioe.toString());
  +        }
  +    }
  +    
  +    public String getWindowsName() {
  +        return new String(familyName+","+subFamilyName);
  +    }
  +    
  +    public String getPostscriptName() {
  +        if ("Regular".equals(subFamilyName) ||
  +            "Roman".equals(subFamilyName))
  +            return familyName;
  +        else
  +            return familyName+","+subFamilyName;
  +    }
  +    public String getFamilyName() {
  +        return familyName;
  +    }
  +    public String getCharSetName() {
  +        return encoding;
  +    }
  +    public int getCapHeight() {
  +        return (int)get_ttf_funit(capHeight);
  +    }
  +    public int getXHeight() {
  +        return (int)get_ttf_funit(xHeight);
  +    }
  +    
  +    public int getFlags() {
  +        int flags=32; // Use Adobe Standard charset
  +        if (italicAngle != 0)
  +            flags = flags | 64;
  +        if (isFixedPitch != 0)
  +            flags = flags | 2;
  +        if (hasSerifs)
  +            flags = flags | 1;
  +        return flags;
  +    }
  +
  +    
  +    public String getStemV() {
  +        return "0";
  +    }
  +    
  +    public String getItalicAngle() {
  +        String ia=Short.toString((short)(italicAngle/0x10000));
  +        if ((italicAngle % 0x10000) > 0 )
  +            ia=ia+("."+Short.toString((short)((short)((italicAngle % 0x10000)*1000)/0x10000)));
  +        
  +        return ia;
  +    }
  +    
  +    public int[] getFontBBox() {
  +        int[] fbb=new int[4];
  +        fbb[0]=(int)get_ttf_funit(fontBBox1);
  +        fbb[1]=(int)get_ttf_funit(fontBBox2);
  +        fbb[2]=(int)get_ttf_funit(fontBBox3);
  +        fbb[3]=(int)get_ttf_funit(fontBBox4);
  +        
  +        return fbb;
  +    }
  +    
  +    public int getLowerCaseAscent() {
  +        return (int)get_ttf_funit(ascender);
  +    }
  +    
  +    public int getLowerCaseDescent() {
  +        return (int)get_ttf_funit(descender);
  +    }
  +    
  +        // This is only for WinAnsiEncoding, so the last char is
  +        // the last char < 256
  +    public short getLastChar() {
  +        return lastChar;
  +    }
  +
  +    public short getFirstChar() {
  +        return firstChar;
  +    }
  +
  +    public int[] getWidths() {
  +        int[] wx = new int[mtx_tab.length];
  +        for (int i = 0; i < wx.length; i++)
  +            wx[i] = (int)get_ttf_funit(mtx_tab[i].wx);
  +
  +        return wx;
  +    }
  +    
  +    public int getCharWidth(int idx) {
  +        return (int)get_ttf_funit(ansiWidth[idx]);
  +    }
  +    
  +    public Hashtable getKerning() {
  +        return kerningTab;
  +    }
  +    
  +    public Hashtable getAnsiKerning() {
  +        return ansiKerningTab;
  +    }
  +    
  +    public boolean isEmbeddable() {
  +        return is_embeddable;
  +    }
  +    
  +    
  +        /**
  +         * Read Table Directory from the current position in the
  +         * FontFileReader and fill the global Hashtable dirTabs
  +         * with the table name (String) as key and a TTFDirTabEntry
  +         * as value.
  +         */
  +    private void readDirTabs(FontFileReader in) throws IOException {
  +        in.skip(4); // TTF_FIXED_SIZE
  +        int ntabs=in.readTTFUShort();
  +        in.skip(6); // 3xTTF_USHORT_SIZE
  +        
  +        dirTabs=new Hashtable();
  +        TTFDirTabEntry[] pd=new TTFDirTabEntry[ntabs];
  +            //System.out.println("Reading " + ntabs + " dir tables");
  +        for (int i=0; i < ntabs; i++) {
  +            pd[i]=new TTFDirTabEntry();
  +            dirTabs.put(pd[i].read(in),
  +                        pd[i]);
  +        }
  +    }
  +
  +        /**
  +         * Read the "head" table, this reads the bounding box and
  +         * sets the upem (unitsPerEM) variable
  +         */
  +    private void readFontHeader(FontFileReader in) throws IOException {
  +        seek_tab(in, "head", 2*4 + 2*4 + 2);
  +        upem=in.readTTFUShort();
  +
  +        in.skip(16);
  +        
  +        fontBBox1=in.readTTFShort();
  +        fontBBox2=in.readTTFShort();
  +        fontBBox3=in.readTTFShort();
  +        fontBBox4=in.readTTFShort();
  +        
  +        in.skip(2+2+2);
  +        
  +        loca_format=in.readTTFShort();
  +    }
  +
  +        /**
  +         * Read the number of glyphs from the "maxp" table
  +         */
  +    private void getNumGlyphs(FontFileReader in) throws IOException {
  +        seek_tab(in, "maxp", 4);
  +        nglyphs=in.readTTFUShort();
  +        System.out.println("Number of glyphs in font: " + nglyphs); 
  +    }
  +
  +
  +        /** Read the "hhea" table to find the ascender and descender and
  +         * size of "hmtx" table, i.e. a fixed size font might have only
  +         * one width
  +         */
  +    private void readHorizontalHeader(FontFileReader in) throws IOException {
  +        seek_tab(in, "hhea", 4);
  +        ascender=in.readTTFShort(); // Use sTypoAscender in "OS/2" table?
  +        descender=in.readTTFShort(); // Use sTypoDescender in "OS/2" table?
  +        
  +        in.skip(2+2+3*2+8*2);
  +        nhmtx=in.readTTFUShort();
  +            //System.out.println("Number of horizontal metrics: " + nhmtx);
  +    }
  +
  +        /**
  +         * Read "hmtx" table and put the horizontal metrics
  +         * in the mtx_tab array. If the number of metrics is less
  +         * than the number of glyphs (eg fixed size fonts), extend
  +         * the mtx_tab array and fill in the missing widths
  +         */
  +    private void readHorizontalMetrics(FontFileReader in) throws IOException {
  +        seek_tab(in, "hmtx", 0);
  +        
  +        int mtx_size=(nglyphs > nhmtx) ? nglyphs : nhmtx;
  +        mtx_tab=new TTFMtxEntry[mtx_size];
  +        
  +            //System.out.println("*** Widths array: \n");
  +        for (int i=0; i < mtx_size; i++)
  +            mtx_tab[i]=new TTFMtxEntry();
  +        for (int i=0; i < nhmtx; i++) {
  +            mtx_tab[i].wx=in.readTTFUShort();
  +                /*
  +                  System.out.println("   width["+i+"] = "+
  +                  get_ttf_funit(mtx_tab[i].wx)+";");
  +                */
  +            in.skip(2); // Skip left side bearing
  +        }
  +
  +        if (nhmtx < mtx_size) {
  +                // Fill in the missing widths
  +            int lastWidth=mtx_tab[nhmtx-1].wx;
  +            for (int i=nhmtx; i < mtx_size; i++) {
  +                mtx_tab[i].wx=lastWidth;
  +            }
  +        }
  +    }
   
  -   int upem;
  -   int ntabs;
  -   int nhmtx;
  -   int post_format;
  -   int loca_format;
  -   int nglyphs;
  -   int nmglyphs;
  -   int names_count;
  -
  -   
  -
  -   TTFDirTabEntry dir_tab;
  -   TTFMtxEntry mtx_tab[];
  -   int[] mtx_encoded=null;
  -   boolean reencoded=false;
  -   String enc_names;
  -
  -   String fontName="";
  -   String fullName="";
  -   String notice="";
  -   String familyName="";
  -   String subFamilyName="";
  -   
  -   long italicAngle = 0;
  -   long isFixedPitch = 0;
  -   int fontBBox1 = 0;
  -   int fontBBox2 = 0;
  -   int fontBBox3 = 0;
  -   int fontBBox4 = 0;
  -   int capHeight = 0;
  -   int underlinePosition = 0;
  -   int underlineThickness = 0;
  -   int xHeight = 0;
  -   int ascender = 0;
  -   int descender = 0;
  -
  -   public void readFont(FontFileReader in) throws IOException {
  -      int i, j, k, l, platform_id, encoding_id, language_id;
  -      long n;
  -      TTFDirTabEntry[] pd;
  -      TTFMtxEntry[] pm;
  -      String[] ps_glyphs_buf;
  -      
  -      in.skip(4); // TTF_FIXED_SIZE
  -      ntabs=in.readTTFUShort();
  -      in.skip(6); // 3xTTF_USHORT_SIZE;
  -
  -          // Read Dir tabs
  -      dirTabs=new Hashtable();
  -      pd=new TTFDirTabEntry[ntabs];
  -          //System.out.println("Reading " + ntabs + " dir tables");
  -      for (i=0; i < ntabs; i++) {
  -         pd[i]=new TTFDirTabEntry();
  -         dirTabs.put(pd[i].read(in),
  -                     pd[i]);
  -      }
  -
  -      seek_tab(in, "head", 2*4 + 2*4 + 2);
  -      upem=in.readTTFUShort();
  -
  -      in.skip(16);
  -
  -      fontBBox1=in.readTTFShort();
  -      fontBBox2=in.readTTFShort();
  -      fontBBox3=in.readTTFShort();
  -      fontBBox4=in.readTTFShort();
  -
  -      in.skip(2+2+2);
  -
  -      loca_format=in.readTTFShort();
  -
  -      seek_tab(in, "maxp", 4);
  -      nglyphs=in.readTTFUShort();
  -          //System.out.println("nglyphs= " + nglyphs); 
  -      mtx_tab=new TTFMtxEntry[nglyphs];
  -
  -      for (i=0; i < nglyphs; i++)
  -         mtx_tab[i]=new TTFMtxEntry();
  -
  -      seek_tab(in, "hhea", 4);
  -      ascender=in.readTTFShort(); // Use sTypoAscender in "OS/2" table?
  -      descender=in.readTTFShort(); // Use sTypoDescender in "OS/2" table?
  -
  -      in.skip(2+2+3*2+8*2);
  -      nhmtx=in.readTTFUShort();
  -          //System.out.println("nhmtx: " + nhmtx);
  -      seek_tab(in, "hmtx", 0);
  -      for (i=0; i < nhmtx; i++) {
  -         mtx_tab[i].wx=in.readTTFUShort();
  -         in.skip(2);
  -      }
  -          // NB: Her skal det settes mer wx.
  -      
  -      seek_tab(in, "post", 0);
  -      post_format=in.readTTFLong();
  -      italicAngle=in.readTTFULong();
  -          //System.out.println("Italic angle: " + italicAngle);
  -      underlinePosition=in.readTTFShort();
  -      underlineThickness=in.readTTFShort();
  -      isFixedPitch=in.readTTFULong();
  -
  -      in.skip(4*4);
  -
  -      switch (post_format) {
  -          case 0x00010000:
  -                 //System.out.println("Postscript format 1");
  -             for (i=0; i<Glyphs.mac_glyph_names.length; i++) {
  -                mtx_tab[i].name=Glyphs.mac_glyph_names[i];
  -             }
  -             break;
  -          case 0x00020000: 
  -                 //System.out.println("Postscript format 2");
  -             l = in.readTTFUShort();
  -             for (i=0; i < l ; i++) {
  -                mtx_tab[i].index=in.readTTFUShort();
  -             }
  -             
  -             TTFDirTabEntry dirTab=
  -                (TTFDirTabEntry)dirTabs.get("post");
  -             if (dirTab==null)
  -                System.out.println("Can't find table 'post'");
  -
  -             n=dirTab.length - (in.getCurrentPos() - dirTab.offset);
  -             ps_glyphs_buf=new String[(int)n];
  -             int nn=(ps_glyphs_buf.length < nglyphs) ?
  -                ps_glyphs_buf.length : nglyphs;
  -                 //System.out.println("Reading " + n + " glyphnames");
  -             for (i=0; i < nn; i++) {
  -                ps_glyphs_buf[i]=in.readTTFString(in.readTTFUByte());
  -             }
  -
  -             for (i=0; i < l; i++) {
  -                if (mtx_tab[i].index < NMACGLYPHS) {
  -                   mtx_tab[i].name = Glyphs.mac_glyph_names[mtx_tab[i].index];
  -                } else {
  -                   k = mtx_tab[i].index - NMACGLYPHS ;
  -                   mtx_tab[i].name=ps_glyphs_buf[k];
  +
  +        /**
  +         * Read the "post" table
  +         * containing the postscript names of the glyphs.
  +         */
  +    private final void readPostscript(FontFileReader in) throws IOException {
  +        String[] ps_glyphs_buf;
  +        int i, k, l;
  +        
  +        seek_tab(in, "post", 0);
  +        post_format=in.readTTFLong();
  +        italicAngle=in.readTTFULong();
  +        underlinePosition=in.readTTFShort();
  +        underlineThickness=in.readTTFShort();
  +        isFixedPitch=in.readTTFULong();
  +        
  +        in.skip(4*4);
  +        
  +            //System.out.println("Post format: "+post_format);
  +        switch (post_format) {
  +            case 0x00010000:
  +                    //System.out.println("Postscript format 1");
  +                for (i=0; i < Glyphs.mac_glyph_names.length; i++) {
  +                    mtx_tab[i].name=Glyphs.mac_glyph_names[i];
  +                }
  +                break;
  +            case 0x00020000: 
  +                    //System.out.println("Postscript format 2");
  +                int numGlyphStrings=0;
  +                l = in.readTTFUShort(); // Num Glyphs
  +                    //short minIndex=256;
  +                for (i=0; i < l ; i++) { // Read indexes
  +                    mtx_tab[i].index=in.readTTFUShort();
  +                        //if (minIndex > mtx_tab[i].index)
  +                        //minIndex=(short)mtx_tab[i].index;
  +                    
  +                    if (mtx_tab[i].index > 257)
  +                        numGlyphStrings++;
  +                    
  +                        //System.out.println("Post index: "+mtx_tab[i].index);
  +                }
  +                    //firstChar=minIndex;
  +                ps_glyphs_buf=new String[numGlyphStrings];
  +                    //System.out.println("Reading " + numGlyphStrings +
  +                    //              " glyphnames"+
  +                    //               ", was n num glyphs="+l);
  +                for (i=0; i < ps_glyphs_buf.length; i++) {
  +                    ps_glyphs_buf[i]=in.readTTFString(in.readTTFUByte());
  +                }
  +                
  +                for (i=0; i < l; i++) {
  +                    if (mtx_tab[i].index < NMACGLYPHS) {
  +                        mtx_tab[i].name = Glyphs.mac_glyph_names[mtx_tab[i].index];
  +                    } else {
  +                        k = mtx_tab[i].index - NMACGLYPHS ;
  +                            /*
  +                              System.out.println(k+" i="+i+" mtx="+mtx_tab.length+
  +                              " ps="+ps_glyphs_buf.length);
  +                            */
  +                        mtx_tab[i].name=ps_glyphs_buf[k];
  +                    }
                   }
  -             }
  -             
  -             break;
  -          case 0x00030000:
  -                 //System.out.println("Postscript format 3 - index");
  -             break;
  -          default:
  -                 //System.out.println("Unknown format : " + post_format);
  -      }
  -
  -          // Check if font is embeddable
  -      if (dirTabs.get("OS/2") != null) {
  -         seek_tab(in, "OS/2", 2*4);
  -         int fsType=in.readTTFUShort();
  -         if ((fsType & 2) == 0)
  -            is_embeddable=false;
  -         else
  +                
  +                break;
  +            case 0x00030000:
  +                    // Postscript format 3 contains no glyph names
  +                System.out.println("Postscript format 3");
  +                break;
  +            default:
  +                System.out.println("Unknown Postscript format : " +
  +                                   post_format);
  +        }
  +    }
  +
  +
  +        /**
  +         * Read the "OS/2" table
  +         */
  +    private final void readOS2(FontFileReader in) throws IOException {
  +            // Check if font is embeddable
  +        if (dirTabs.get("OS/2") != null) {
  +            seek_tab(in, "OS/2", 2*4);
  +            int fsType=in.readTTFUShort();
  +            if ((fsType & 2) == fsType)
  +                is_embeddable=false;
  +            else
  +                is_embeddable=true;
  +        } else
               is_embeddable=true;
  -      } else
  -         is_embeddable=true;
  -      
  -         
  +    }
   
  -      seek_tab(in, "loca", 0);
  -      for (i=0; i < nglyphs ; i++) {
  -         mtx_tab[i].offset = (loca_format == 1 ? in.readTTFULong() :
  -                              (in.readTTFUShort() << 1));
  -      }
  -
  -      TTFDirTabEntry dirTab =
  -         (TTFDirTabEntry)dirTabs.get("glyf");
  -      for (i=0; i < (nglyphs-1); i++) {
  -         if (mtx_tab[i].offset != mtx_tab[i+1].offset) {
  -            in.seek_set(dirTab.offset + mtx_tab[i].offset);
  -            in.skip(2);
  -            mtx_tab[i].bbox[0]=in.readTTFShort();
  -            mtx_tab[i].bbox[1]=in.readTTFShort();
  -            mtx_tab[i].bbox[2]=in.readTTFShort();
  -            mtx_tab[i].bbox[3]=in.readTTFShort();
  -         } else {
  -            mtx_tab[i].bbox[0]=mtx_tab[0].bbox[0];
  -            mtx_tab[i].bbox[1]=mtx_tab[0].bbox[1];
  -            mtx_tab[i].bbox[2]=mtx_tab[0].bbox[2];
  -            mtx_tab[i].bbox[3]=mtx_tab[0].bbox[3];
  -         }
  -      }
  -      
  -          //System.out.println("nglyf="+nglyphs+" mtx="+mtx_tab.length);
  +        /**
  +         * Read the "loca" table
  +         */
  +    private final void readIndexToLocation(FontFileReader in)
  +        throws IOException {
  +        seek_tab(in, "loca", 0);
  +        for (int i=0; i < nglyphs ; i++) {
  +            mtx_tab[i].offset = (loca_format == 1 ? in.readTTFULong() :
  +                                 (in.readTTFUShort() << 1));
  +        }
  +    }
  +
  +        /**
  +         * Read the "glyf" table to find the bounding boxes
  +         */
  +    private final void readGlyf(FontFileReader in) throws IOException {
  +        TTFDirTabEntry dirTab =
  +            (TTFDirTabEntry)dirTabs.get("glyf");
  +        for (int i=0; i < (nglyphs-1); i++) {
  +            if (mtx_tab[i].offset != mtx_tab[i+1].offset) {
  +                in.seek_set(dirTab.offset + mtx_tab[i].offset);
  +                in.skip(2);
  +                mtx_tab[i].bbox[0]=in.readTTFShort();
  +                mtx_tab[i].bbox[1]=in.readTTFShort();
  +                mtx_tab[i].bbox[2]=in.readTTFShort();
  +                mtx_tab[i].bbox[3]=in.readTTFShort();
  +            } else {
  +                mtx_tab[i].bbox[0]=mtx_tab[0].bbox[0];
  +                mtx_tab[i].bbox[1]=mtx_tab[0].bbox[1];
  +                mtx_tab[i].bbox[2]=mtx_tab[0].bbox[2];
  +                mtx_tab[i].bbox[3]=mtx_tab[0].bbox[3];
  +            }
  +        }
         
  -         
  -      n=((TTFDirTabEntry)dirTabs.get("glyf")).offset;
  -      for (i=0; i < nglyphs; i++) {
  -         if ((i+1) >= mtx_tab.length ||
  -             mtx_tab[i].offset != mtx_tab[i+1].offset) {
  -            in.seek_set(n+mtx_tab[i].offset);
  -            in.skip(2);
  -            mtx_tab[i].bbox[0]=in.readTTFShort();
  -            mtx_tab[i].bbox[1]=in.readTTFShort();
  -            mtx_tab[i].bbox[2]=in.readTTFShort();
  -            mtx_tab[i].bbox[3]=in.readTTFShort();
  -         } else {
  -            mtx_tab[i].bbox[0]=mtx_tab[0].bbox[0];
  -            mtx_tab[i].bbox[1]=mtx_tab[0].bbox[0];
  -            mtx_tab[i].bbox[2]=mtx_tab[0].bbox[0];
  -            mtx_tab[i].bbox[3]=mtx_tab[0].bbox[0];
  -         }
  -             //System.out.println(mtx_tab[i].toString(this));
  -      }
  -
  -      seek_tab(in, "name", 2);
  -      i = in.getCurrentPos();
  -      n = in.readTTFUShort();
  -      j = in.readTTFUShort() + i - 2;
  -      i += 2*2;
  -
  -      while (n-- > 0) {
  -         in.seek_set(i);
  -         platform_id=in.readTTFUShort();
  -         encoding_id=in.readTTFUShort();
  -         language_id=in.readTTFUShort();
  -             //System.out.println("Platform id: " + language_id);
  -             //System.out.println("Encoding id: " + language_id);
  -             //System.out.println("Language id: " + language_id);
  -         k=in.readTTFUShort();
  -         l=in.readTTFUShort();
  -
  -         if ((platform_id==1 && encoding_id==0) &&
  -             (k==1 || k==2 || k==0 || k==4 || k==6)) {
  -            in.seek_set(j+in.readTTFUShort());
  -            String txt = in.readTTFString(l);
  +        
  +        long n=((TTFDirTabEntry)dirTabs.get("glyf")).offset;
  +        for (int i=0; i < nglyphs; i++) {
  +            if ((i+1) >= mtx_tab.length ||
  +                mtx_tab[i].offset != mtx_tab[i+1].offset) {
  +                in.seek_set(n+mtx_tab[i].offset);
  +                in.skip(2);
  +                mtx_tab[i].bbox[0]=in.readTTFShort();
  +                mtx_tab[i].bbox[1]=in.readTTFShort();
  +                mtx_tab[i].bbox[2]=in.readTTFShort();
  +                mtx_tab[i].bbox[3]=in.readTTFShort();
  +            } else {
  +                mtx_tab[i].bbox[0]=mtx_tab[0].bbox[0];
  +                mtx_tab[i].bbox[1]=mtx_tab[0].bbox[0];
  +                mtx_tab[i].bbox[2]=mtx_tab[0].bbox[0];
  +                mtx_tab[i].bbox[3]=mtx_tab[0].bbox[0];
  +            }
  +                //System.out.println(mtx_tab[i].toString(this));
  +        }
  +    }
  +
  +        /**
  +         * Read the "name" table
  +         */
  +    private final void readName(FontFileReader in) throws IOException {
  +        int platform_id, encoding_id, language_id;
  +        
  +        seek_tab(in, "name", 2);
  +        int i = in.getCurrentPos();
  +        int n = in.readTTFUShort();
  +        int j = in.readTTFUShort() + i - 2;
  +        i += 2*2;
  +
  +        while (n-- > 0) {
  +                //System.out.println("Iteration: "+n);
  +            in.seek_set(i);
  +            platform_id=in.readTTFUShort();
  +            encoding_id=in.readTTFUShort();
  +            language_id=in.readTTFUShort();
  +            
  +            int k=in.readTTFUShort();
  +            int l=in.readTTFUShort();
  +            
  +            if (((platform_id==1 || platform_id==3) &&
  +                 (encoding_id==0 || encoding_id==1)) && 
  +                (k==1 || k==2 || k==0 || k==4 || k==6)) {
  +//            if (k==1 || k==2 || k==0 || k==4 || k==6) {
  +                in.seek_set(j+in.readTTFUShort());
  +                String txt = in.readTTFString(l);
  +                    //System.out.println(platform_id+" "+encoding_id+
  +                    //" "+k+" "+txt);
               switch (k) {
                   case 0: notice=txt; break;
                   case 1: familyName=txt; break;
  @@ -327,202 +876,215 @@
               }
               if (!notice.equals("") && !fullName.equals("") &&
                   !fontName.equals("") && !familyName.equals("") &&
  -                !subFamilyName.equals(""))
  -               break;
  -         }
  -         i+=6*2;
  -      }
  -      
  -      dirTab=
  -         (TTFDirTabEntry)dirTabs.get("PCLT");
  -      if (dirTab!=null) {
  -         in.seek_set(dirTab.offset + 4 + 4 + 2);
  -         xHeight=in.readTTFUShort();
  -         in.skip(2*2);
  -         capHeight=in.readTTFUShort();
  -         in.skip(2+16+8+6+1+1);
  -         
  -         int serifStyle=in.readTTFUByte();
  -         serifStyle=serifStyle >> 6;
  -         serifStyle=serifStyle & 3;
  -         if (serifStyle == 1)
  -            hasSerifs=false;
  -         else
  -            hasSerifs=true;
  -         
  -      } else {
  -             // Approximate capHeight from height of "H"
  -         for (i=0; i < mtx_tab.length; i++) {
  -            if ("H".equals(mtx_tab[i].name))
  -               capHeight=mtx_tab[i].bbox[3]-
  -                  mtx_tab[i].bbox[1];
  -         }
  -      }
  -
  -          // Read kerning
  -      kerningTab=new Hashtable();
  -      dirTab=
  -         (TTFDirTabEntry)dirTabs.get("kern");
  -      if (dirTab!=null) {
  -         seek_tab(in, "kern", 2);
  -         for (n=in.readTTFUShort(); n>0 ; n--) {
  +                !subFamilyName.equals("")) {
  +                break;
  +            }
  +            }
  +            i+=6*2;
  +        }
  +    }
  +
  +        /**
  +         * Read the "PCLT" table to find xHeight and capHeight
  +         */
  +    private final void readPCLT(FontFileReader in) throws IOException {
  +        TTFDirTabEntry dirTab=
  +            (TTFDirTabEntry)dirTabs.get("PCLT");
  +        if (dirTab!=null) {
  +            in.seek_set(dirTab.offset + 4 + 4 + 2);
  +            xHeight=in.readTTFUShort();
               in.skip(2*2);
  -            k=in.readTTFUShort();
  -            if (!((k & 1)!=0) || (k & 2)!=0 || (k & 4)!=0)
  -               return;
  -            if ((k >> 8) !=0)
  -               continue;
  -
  -            k=in.readTTFUShort();
  -            in.skip(3 * 2);
  -            while (k-- > 0) {
  -               i=in.readTTFUShort();
  -               j=in.readTTFUShort();
  -               int kpx=in.readTTFShort();
  -               if (kpx != 0) {
  -                  Hashtable adjTab=(Hashtable)kerningTab.get(mtx_tab[i].name);
  -                  if (adjTab==null)
  -                     adjTab=new java.util.Hashtable();
  -                  adjTab.put(mtx_tab[j].name, new Integer((int)get_ttf_funit(kpx)));
  -                  kerningTab.put(mtx_tab[i].name, adjTab);
  -               }
  -            }
  -         }
  -             //System.out.println(kerningTab.toString());
  -      }
  -   }
  -
  -
  -   public void printStuff() {
  -      System.out.println("Font name: " + fontName);
  -      System.out.println("Full name: " + fullName);
  -      System.out.println("Family name: " + familyName);
  -      System.out.println("Subfamily name: " + subFamilyName);
  -      System.out.println("Notice:    " + notice);
  -      System.out.println("xHeight:   " + (int)get_ttf_funit(xHeight));
  -      System.out.println("capheight: " + (int)get_ttf_funit(capHeight));
  -      
  -      int italic=(int)(italicAngle>>16);
  -      System.out.println("Italic: " + italic);
  -      System.out.print("ItalicAngle: " + (short)(italicAngle/0x10000));
  -      if ((italicAngle % 0x10000) > 0 )
  -         System.out.print("."+(short)((italicAngle % 0x10000)*1000)/0x10000);
  -      System.out.println();
  -      System.out.println("Ascender:    " + get_ttf_funit(ascender));
  -      System.out.println("Descender:   " + get_ttf_funit(descender));
  -      System.out.println("FontBBox:    [" + (int)get_ttf_funit(fontBBox1) +
  -                         " " + (int)get_ttf_funit(fontBBox2) +
  -                         " " + (int)get_ttf_funit(fontBBox3) +
  -                         " " + (int)get_ttf_funit(fontBBox4)+"]");
  -   }
  -   
  -   public static void main(String[] args) {
  -      try {
  -         TTFFile ttfFile=new TTFFile();
  -         FontFileReader reader=
  -            new FontFileReader(args[0]);
  -
  -         ttfFile.readFont(reader);
  -         ttfFile.printStuff();
  -
  -      } catch (IOException ioe) {
  -         System.out.println(ioe.toString());
  -      }
  -   }
  -
  -   public String getWindowsName() {
  -      return new String(familyName+","+subFamilyName);
  -   }
  -   public String getPostscriptName() {
  -      return fontName;
  -   }
  -   public String getCharSetName() {
  -      return "WinAnsi";
  -   }
  -   public int getCapHeight() {
  -      return (int)get_ttf_funit(capHeight);
  -   }
  -   public int getXHeight() {
  -      return (int)get_ttf_funit(xHeight);
  -   }
  -   public int getFlags() {
  -      int flags=32; // Use Adobe Standard charset
  -      if (italicAngle != 0)
  -         flags = flags | 64;
  -      if (isFixedPitch != 0)
  -         flags = flags | 2;
  -      if (hasSerifs)
  -         flags = flags | 1;
  -      return flags;
  -   }
  -   public String getStemV() {
  -      return "0";
  -   }
  -   public String getItalicAngle() {
  -      String ia=Short.toString((short)(italicAngle/0x10000));
  -      if ((italicAngle % 0x10000) > 0 )
  -         ia=ia+("."+Short.toString((short)((short)((italicAngle % 0x10000)*1000)/0x10000)));
  -      
  -      return ia;
  -   }
  -   public int[] getFontBBox() {
  -      int[] fbb=new int[4];
  -      fbb[0]=(int)get_ttf_funit(fontBBox1);
  -      fbb[1]=(int)get_ttf_funit(fontBBox2);
  -      fbb[2]=(int)get_ttf_funit(fontBBox3);
  -      fbb[3]=(int)get_ttf_funit(fontBBox4);
  -      
  -      return fbb;
  -   }
  -   public int getLowerCaseAscent() {
  -      return (int)get_ttf_funit(ascender);
  -   }
  -   public int getLowerCaseDescent() {
  -      return (int)get_ttf_funit(descender);
  -   }
  -   public short getLastChar() {
  -      fixWidth();
  -      return (short)(nmglyphs-1);
  -   }
  -   public short getFirstChar() {
  -      return 0;
  -   }
  -
  -   public int getCharWidth(int idx) {
  -      fixWidth();
  -
  -      return (int)get_ttf_funit(mtx_encoded[idx]);
  -   }
  -
  -   public Hashtable getKerning() {
  -      return kerningTab;
  -   }
  -
  -   public boolean isEmbeddable() {
  -      return is_embeddable;
  -   }
  -   private void fixWidth() {
  -      if (reencoded)
  -         return;
  -      reencoded=true;
  -          //System.out.println("Reencoding widths");
  -      nmglyphs=0;
  -      mtx_encoded=new int[Glyphs.tex8r.length];
  -      
  -      Hashtable existingGlyphs=new java.util.Hashtable();
  -      
  -      for (int i=0; i < mtx_tab.length; i++) 
  -         existingGlyphs.put(mtx_tab[i].name, new Integer(mtx_tab[i].wx));
  +            capHeight=in.readTTFUShort();
  +            in.skip(2+16+8+6+1+1);
  +            
  +            int serifStyle=in.readTTFUByte();
  +            serifStyle=serifStyle >> 6;
  +            serifStyle=serifStyle & 3;
  +            if (serifStyle == 1)
  +                hasSerifs=false;
  +            else
  +                hasSerifs=true;
  +            
  +        } else {
  +                // Approximate capHeight from height of "H"
  +                // It's most unlikly that a font misses the PCLT table
  +                // This also assumes that psocriptnames exists ("H")
  +                // Should look it up int the cmap (that wouldn't help
  +                // for charsets without H anyway...)
  +            for (int i=0; i < mtx_tab.length; i++) {
  +                if ("H".equals(mtx_tab[i].name))
  +                    capHeight=mtx_tab[i].bbox[3]-
  +                        mtx_tab[i].bbox[1];
  +            }
  +        }
  +    }
   
  -      
  -      for (int i=0; i < Glyphs.tex8r.length; i++) {
  -         nmglyphs++;
  -         Integer wx=(Integer)existingGlyphs.get(Glyphs.tex8r[i]);
  -         if (wx==null)
  -            mtx_encoded[i]=0;
  -         else
  -            mtx_encoded[i]=wx.intValue();
  -      }
  -   }
  +        /**
  +         * Read the kerning table, create a table for both CIDs and
  +         * winAnsiEncoding
  +         */
  +    private final void readKerning(FontFileReader in) throws IOException {
  +            // Read kerning
  +        kerningTab=new Hashtable();
  +        TTFDirTabEntry dirTab=
  +            (TTFDirTabEntry)dirTabs.get("kern");
  +        if (dirTab!=null) {
  +            seek_tab(in, "kern", 2);
  +            for (int n=in.readTTFUShort(); n > 0 ; n--) {
  +                in.skip(2*2);
  +                int k=in.readTTFUShort();
  +                if (!((k & 1)!=0) || (k & 2)!=0 || (k & 4)!=0)
  +                    return;
  +                if ((k >> 8) !=0)
  +                    continue;
  +                
  +                k=in.readTTFUShort();
  +                in.skip(3 * 2);
  +                while (k-- > 0) {
  +                    int i=in.readTTFUShort();
  +                    int j=in.readTTFUShort();
  +                    int kpx=in.readTTFShort();
  +                    if (kpx != 0) {
  +                            // CID table
  +                        Integer iObj=new Integer(i);
  +                        Hashtable adjTab=
  +                            (Hashtable)kerningTab.get(iObj);
  +                        if (adjTab==null)
  +                            adjTab=new java.util.Hashtable();
  +                        adjTab.put(new Integer(j),
  +                                   new Integer((int)get_ttf_funit(kpx)));
  +                        kerningTab.put(iObj, adjTab);
  +                    }
  +                }
  +            }
  +                //System.out.println(kerningTab.toString());
  +                        
  +                // Create winAnsiEncoded kerning table
  +            
  +            ansiKerningTab = new Hashtable();
  +            for (Enumeration ae = kerningTab.keys();
  +                 ae.hasMoreElements();) {
  +                Integer cidKey = (Integer)ae.nextElement();
  +                Hashtable akpx = new Hashtable();
  +                Hashtable ckpx = (Hashtable)kerningTab.get(cidKey);
  +
  +                for (Enumeration aee = ckpx.keys();
  +                     aee.hasMoreElements();) {
  +                    Integer cidKey2 = (Integer)aee.nextElement();
  +                    Integer kern = (Integer)ckpx.get(cidKey2);
  +
  +                    for (Enumeration uniMap = mtx_tab[cidKey2.intValue()].unicodeIndex.elements();
  +                         uniMap.hasMoreElements();) {
  +                        Integer unicodeKey = (Integer)uniMap.nextElement();
  +                        Integer[] ansiKeys = unicodeToWinAnsi(unicodeKey.intValue());
  +                        for (int u = 0; u < ansiKeys.length; u++) {
  +                            akpx.put(ansiKeys[u], kern);
  +                        }
  +                    }
  +                }
  +
  +                if (akpx.size() > 0) 
  +                    for (Enumeration uniMap = mtx_tab[cidKey.intValue()].unicodeIndex.elements();
  +                         uniMap.hasMoreElements();) {
  +                        Integer unicodeKey = (Integer)uniMap.nextElement();
  +                        Integer[] ansiKeys = unicodeToWinAnsi(unicodeKey.intValue());
  +                        for (int u = 0; u < ansiKeys.length; u++) {
  +                            ansiKerningTab.put(ansiKeys[u], akpx);
  +                    }
  +                }
  +            }
  +        }
  +    }
  +
  +        /** Return a vector with TTFCmapEntry
  +         */
  +    public Vector getCMaps() {
  +        return cmaps;
  +    }
  +
  +        /**
  +         * Check if this is a TrueType collection and that the given
  +         * name exists in the collection.
  +         * If it does, set offset in fontfile to the beginning of
  +         * the Table Directory for that font
  +         @ return true if not collection or font name present, false
  +         otherwise
  +         */
  +    private final boolean checkTTC(FontFileReader in, String name)
  +        throws IOException {
  +        String tag=in.readTTFString(4);
  +        
  +        if ("ttcf".equals(tag)) {
  +                // This is a TrueType Collection
  +            in.skip(4);
  +            
  +                // Read directory offsets
  +            int numDirectories=(int)in.readTTFULong();
  +                //int numDirectories=in.readTTFUShort();
  +            long[] dirOffsets=new long[numDirectories];
  +            for (int i=0; i < numDirectories; i++) {
  +                dirOffsets[i]=in.readTTFULong();
  +            }
  +
  +            System.out.println("This is a TrueType collection file with"+
  +                               numDirectories + " fonts"); 
  +            System.out.println("Containing the following fonts: ");
  +                // Read all the directories and name tables to check
  +                // If the font exists - this is a bit ugly, but...
  +            boolean found=false;
  +
  +                // Iterate through all name tables even if font
  +                // Is found, just to show all the names
  +            for (int i=0; (i < numDirectories); i++) {
  +                in.seek_set(dirOffsets[i]);
  +                readDirTabs(in);
  +                readName(in);
  +                
  +                if (fullName.equals(name)) {
  +                    found=true;
  +                    in.seek_set(dirOffsets[i]);
  +                    System.out.println("* " + fullName);
  +                } else {
  +                    System.out.println(fullName);
  +                }
  +                
  +                    // Reset names
  +                notice="";
  +                fullName="";
  +                familyName="";
  +                fontName="";
  +                subFamilyName="";
  +            }
  +
  +            return found;
  +        } else {
  +            in.seek_set(0);
  +            return true;
  +        }
  +    }
  +
  +        /* Helper classes, they are not very efficient, but that really
  +           doesn't matter... */
  +    private Integer[] unicodeToWinAnsi(int unicode) {
  +        Vector ret=new Vector();
  +        for (int i=32; i < Glyphs.winAnsiEncoding.length; i++)
  +            if (unicode == Glyphs.winAnsiEncoding[i])
  +                ret.addElement(new Integer(i));
  +        Integer[] itg = new Integer[ret.size()];
  +        ret.copyInto(itg);
  +        return itg;
  +    }
   }
   
  +
  +/**
  + * Key-value helper class
  + */
  +class UnicodeMapping {
  +    int uIdx;
  +    int gIdx;
  +    UnicodeMapping(int gIdx, int uIdx) {
  +        this.uIdx = uIdx;
  +        this.gIdx = gIdx;
  +    }
  +}
  
  
  
  1.2       +25 -22    xml-fop/src/org/apache/fop/fonts/TTFMtxEntry.java
  
  Index: TTFMtxEntry.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/fonts/TTFMtxEntry.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TTFMtxEntry.java	2001/02/05 08:35:28	1.1
  +++ TTFMtxEntry.java	2001/02/27 12:28:15	1.2
  @@ -1,4 +1,4 @@
  -/* -- $Id: TTFMtxEntry.java,v 1.1 2001/02/05 08:35:28 kellyc Exp $ --
  +/* -- $Id: TTFMtxEntry.java,v 1.2 2001/02/27 12:28:15 fotis Exp $ --
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -51,27 +51,30 @@
   package org.apache.fop.fonts;
   
   import java.io.*;
  +import java.util.Vector;
   
   class TTFMtxEntry {
  -   int wx;
  -   String name;
  -   int index;
  -   int[] bbox;
  -   long offset;
  -   byte found;
  -   
  -   TTFMtxEntry() {
  -      name="";
  -      found=0;
  -      bbox=new int[4];
  -   }
  -
  -   public String toString(TTFFile t) {
  -      return new String("Glyph "+name+ " index: " + index +
  -                        " bbox [ "+t.get_ttf_funit(bbox[0])+
  -                        " " + t.get_ttf_funit(bbox[1]) +
  -                        " " + t.get_ttf_funit(bbox[2]) +
  -                        " " + t.get_ttf_funit(bbox[3]) + "]" +
  -                        "wx: "+t.get_ttf_funit(wx));
  -   }
  +    int wx;
  +    String name;
  +    int index;
  +    Vector unicodeIndex;
  +    int[] bbox;
  +    long offset;
  +    byte found;
  +    
  +    TTFMtxEntry() {
  +        name="";
  +        found=0;
  +        unicodeIndex = new Vector();
  +        bbox=new int[4];
  +    }
  +    
  +    public String toString(TTFFile t) {
  +        return new String("Glyph "+name+ " index: " + index +
  +                          " bbox [ "+t.get_ttf_funit(bbox[0])+
  +                          " " + t.get_ttf_funit(bbox[1]) +
  +                          " " + t.get_ttf_funit(bbox[2]) +
  +                          " " + t.get_ttf_funit(bbox[3]) + "]" +
  +                          "wx: "+t.get_ttf_funit(wx));
  +    }
   }
  
  
  
  1.4       +77 -155   xml-fop/src/org/apache/fop/fonts/apps/PFMReader.java
  
  Index: PFMReader.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/fonts/apps/PFMReader.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- PFMReader.java	2001/02/05 08:35:30	1.3
  +++ PFMReader.java	2001/02/27 12:28:15	1.4
  @@ -1,4 +1,4 @@
  -/*-- $Id: PFMReader.java,v 1.3 2001/02/05 08:35:30 kellyc Exp $ --
  +/*-- $Id: PFMReader.java,v 1.4 2001/02/27 12:28:15 fotis Exp $ --
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -67,10 +67,6 @@
    * @author  jeremias.maerki@outline.ch
    */
   public class PFMReader {
  -
  -    static private final String XSL_POSTPROCESS = "FontPostProcess.xsl";
  -    static private final String XSL_SORT        = "FontPostProcessSort.xsl";
  -
       private boolean invokedStandalone = false;
   
       public PFMReader() {
  @@ -88,13 +84,14 @@
         Vector arguments=new Vector();
         for (int i=0; i < args.length; i++) {
            if (args[i].startsWith("-")) {
  -            i++;
  -            if (i < args.length)
  -               options.put(args[i-1], args[i]);
  -            else
  -               options.put(args[i-1], "");
  +             if ((i+1) < args.length && !args[i+1].startsWith("-")) {
  +                 options.put(args[i], args[i+1]);
  +                 i++;
  +             } else {
  +               options.put(args[i], "");
  +             }
            } else {
  -            arguments.addElement(args[i]);
  +             arguments.addElement(args[i]);
            }
         }
         
  @@ -107,18 +104,10 @@
         System.out.println(" java org.apache.fop.fonts.apps.PFMReader [options] metricfile.pfm xmlfile.xml\n");
         System.out.println(" where options can be:\n");
         System.out.println(" -fn <fontname>\n");
  -      System.out.println("     default is to use the fontname in the .pfm file, but you can override\n");
  -      System.out.println("     that name to make sure that the embedded font is used instead of installed\n");
  -      System.out.println("     fonts when viewing documents with Acrobat Reader.\n");
  -      System.out.println(" -cn <classname>\n");
  -      System.out.println("     default is to use the fontname\n");
  -      System.out.println(" -ef <path to the Type1 .pfb fontfile>\n");
  -      System.out.println("     will add the possibility to embed the font. When running fop, fop will look\n");
  -      System.out.println("     for this file to embed it\n");
  -      System.out.println(" -er <path to Type1 fontfile relative to org/apache/fop/render/pdf/fonts>\n");
  -      System.out.println("     you can also include the fontfile in the fop.jar file when building fop.\n");
  -      System.out.println("     You can use both -ef and -er. The file specified in -ef will be searched first,\n");
  -      System.out.println("     then the -er file.\n");
  +      System.out.println("     default is to use the fontname in the .ttf file, but\n"+
  +                         "     you can override that name to make sure that the\n");
  +      System.out.println("     embedded font is used (if you're embedding fonts)\n");
  +      System.out.println("     instead of installed fonts when viewing documents with Acrobat Reader.\n");
      }
         
      
  @@ -142,56 +131,54 @@
        *     then the -er file.
        */
       public static void main(String[] args) {
  -       String embFile=null;
  -       String embResource=null;
  -       String className=null;
  -       String fontName=null;
  -       
  -       Hashtable options=new Hashtable();
  -       String[] arguments=parseArguments(options, args);
  -       
  -       PFMReader app = new PFMReader();
  -       app.invokedStandalone = true;
  -       
  -       System.out.println("PFM Reader v1.1");
  -       System.out.println();
  -
  -       if (options.get("-ef") != null)
  -          embFile=(String)options.get("-ef");
  -       
  -       if (options.get("-er") != null)
  -          embResource=(String)options.get("-er");
  -       
  -       if (options.get("-fn") != null)
  -          fontName=(String)options.get("-fn");
  -       
  -       if (options.get("-cn") != null)
  -          className=(String)options.get("-cn");
  -
  -       if (arguments.length != 2 ||
  -           options.get("-h") != null ||
  -           options.get("-help") != null ||
  -           options.get("--help") != null)
  -          displayUsage();
  -       else {
  -          PFMFile pfm = app.loadPFM(arguments[0]);
  -          if (pfm != null) {
  -             app.preview(pfm);
  -
  -             org.w3c.dom.Document doc = app.constructFontXML(pfm,
  -                                                             fontName,
  -                                                             className,
  -                                                             embResource,
  -                                                             embFile);
  -
  -             doc = app.postProcessXML(doc);
  -             if (doc != null) {
  +        String embFile=null;
  +        String embResource=null;
  +        String className=null;
  +        String fontName=null;
  +        
  +        Hashtable options=new Hashtable();
  +        String[] arguments=parseArguments(options, args);
  +        
  +        PFMReader app = new PFMReader();
  +        app.invokedStandalone = true;
  +        
  +        System.out.println("PFM Reader v1.1");
  +        System.out.println();
  +        
  +        if (options.get("-ef") != null)
  +            embFile=(String)options.get("-ef");
  +        
  +        if (options.get("-er") != null)
  +            embResource=(String)options.get("-er");
  +        
  +        if (options.get("-fn") != null)
  +            fontName=(String)options.get("-fn");
  +        
  +        if (options.get("-cn") != null)
  +            className=(String)options.get("-cn");
  +        
  +        if (arguments.length != 2 ||
  +            options.get("-h") != null ||
  +            options.get("-help") != null ||
  +            options.get("--help") != null)
  +            displayUsage();
  +        else {
  +            PFMFile pfm = app.loadPFM(arguments[0]);
  +            if (pfm != null) {
  +                app.preview(pfm);
  +                
  +                org.w3c.dom.Document doc = app.constructFontXML(pfm,
  +                                                                fontName,
  +                                                                className,
  +                                                                embResource,
  +                                                                embFile);
  +                
                   app.writeFontXML(doc, arguments[1]);
  -             }
  -          }
  -       }
  +            }
  +        }
       }
   
  +
       /**
        * Read a PFM file and returns it as an object.
        *
  @@ -286,7 +273,8 @@
           Document doc = new DocumentImpl();
           Element root = doc.createElement("font-metrics");
           doc.appendChild(root);
  -
  +        root.setAttribute("type", "TYPE1");
  +        
           Element el = doc.createElement("font-name");
           root.appendChild(el);
           el.appendChild(doc.createTextNode(pfm.getPostscriptName()));
  @@ -300,30 +288,12 @@
               s = new String(sb);
           }
   
  -        el = doc.createElement("class-name");
  -        root.appendChild(el);
  -        if (className != null)
  -           el.appendChild(doc.createTextNode(className));
  -        else
  -           el.appendChild(doc.createTextNode(s));
  -
  -        el = doc.createElement("embedFile");
  -        root.appendChild(el);
  -        if (file==null)
  -           el.appendChild(doc.createTextNode("null"));
  -        else
  -           el.appendChild(doc.createTextNode("\""+escapeString(file)+"\""));
  -        
  -        el = doc.createElement("embedResource");
  +        el = doc.createElement("embed");
           root.appendChild(el);
  -        if (resource==null)
  -           el.appendChild(doc.createTextNode("null"));
  -        else
  -           el.appendChild(doc.createTextNode("\""+escapeString(resource)+"\""));
  -        
  -        el = doc.createElement("subtype");
  -        root.appendChild(el);
  -        el.appendChild(doc.createTextNode("Type1"));
  +        if (file!=null)
  +           el.setAttribute("file", file);
  +        if (resource!=null)
  +           el.setAttribute("class", resource);
   
           el = doc.createElement("encoding");
           root.appendChild(el);
  @@ -391,8 +361,8 @@
           for (short i = pfm.getFirstChar(); i < pfm.getLastChar(); i++) {
               el = doc.createElement("char");
               widths.appendChild(el);
  -            el.setAttribute("ansichar", "0x00" + Integer.toHexString(i).toUpperCase());
  -            el.setAttribute("width", new Integer(pfm.getCharWidth(i)).toString());
  +            el.setAttribute("idx", Integer.toString(i));
  +            el.setAttribute("wdt", new Integer(pfm.getCharWidth(i)).toString());
           }
   
   
  @@ -403,72 +373,20 @@
              el.setAttribute("kpx1", kpx1);
              root.appendChild(el);
              Element el2=null;
  -           
  +
              Hashtable h2=(Hashtable)pfm.getKerning().get(kpx1);
              for (Enumeration enum2=h2.keys(); enum2.hasMoreElements(); ) {
  -              String kpx2=(String)enum2.nextElement();
  -              el2=doc.createElement("pair");
  -              el2.setAttribute("kpx2", kpx2);
  -              Integer val=(Integer)h2.get(kpx2);
  -              el2.setAttribute("kern", val.toString());
  -              el.appendChild(el2);
  +               Integer kpx2=(Integer)enum2.nextElement();
  +               el2=doc.createElement("pair");
  +               el2.setAttribute("kpx2", kpx2.toString());
  +               Integer val=(Integer)h2.get(kpx2);
  +               el2.setAttribute("kern", val.toString());
  +               el.appendChild(el2);
              }
           }
           return doc;
       }
   
  -    /**
  -     * Modifies the generated font metrics file. First, it processes the
  -     * character mmappings, then it sorts them.
  -     * 
  -     * @param   doc The DOM document representing the font metrics file.
  -     * @return  A DOM document representing the processed font metrics file.
  -     */
  -    public org.w3c.dom.Document postProcessXML(org.w3c.dom.Document doc) {
  - try {
  -            OutputFormat format = new OutputFormat(doc);     //Serialize DOM
  -            XMLSerializer serial = new XMLSerializer(System.out, format);
  -            serial.asDOMSerializer();                        // As a DOM Serializer
  -            serial.serialize(doc.getDocumentElement());
  -            
  -            System.out.println("Postprocessing...");
  -            System.out.println();
  -
  -           
  -
  -            InputStream xsl = this.getClass().getResourceAsStream(XSL_POSTPROCESS);
  -            if (xsl == null) {
  -                throw new Exception("Resource " + XSL_POSTPROCESS + " not found");
  -            }
  -           
  -            Document targetDoc = new DocumentImpl();
  -	    org.apache.fop.tools.xslt.XSLTransform.transform(doc, xsl, targetDoc);
  -	    
  -
  -            System.out.println("Sorting...");
  -            System.out.println();
  -
  -            // Sort the whole thing
  -            
  -
  -            xsl = this.getClass().getResourceAsStream(XSL_SORT);
  -            if (xsl == null) {
  -                throw new Exception("Resource " + XSL_SORT + " not found");
  -            }
  -            
  -
  -            org.w3c.dom.Document targetDocSorted = new DocumentImpl();
  -
  -	    org.apache.fop.tools.xslt.XSLTransform.transform(targetDoc, xsl, targetDocSorted);
  -
  -            return targetDocSorted;
  -
  -        } catch (Exception e) {
  -            e.printStackTrace();
  -            return null;
  -        }
  -    }
  -
      
      private String escapeString(String str) {
         StringBuffer esc=new StringBuffer();
  @@ -483,3 +401,7 @@
         return esc.toString();
      }
   }
  +
  +
  +
  +
  
  
  
  1.2       +186 -206  xml-fop/src/org/apache/fop/fonts/apps/TTFReader.java
  
  Index: TTFReader.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/fonts/apps/TTFReader.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TTFReader.java	2001/02/05 08:35:31	1.1
  +++ TTFReader.java	2001/02/27 12:28:15	1.2
  @@ -1,4 +1,4 @@
  -/* -- $Id: TTFReader.java,v 1.1 2001/02/05 08:35:31 kellyc Exp $ --
  +/* -- $Id: TTFReader.java,v 1.2 2001/02/27 12:28:15 fotis Exp $ --
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -66,9 +66,6 @@
    */
   public class TTFReader {
   
  -    static private final String XSL_POSTPROCESS = "TTFPostProcess.xsl";
  -    static private final String XSL_SORT        = "TTFPostProcessSort.xsl";
  -
       private boolean invokedStandalone = false;
   
       public TTFReader() {
  @@ -86,13 +83,14 @@
         Vector arguments=new Vector();
         for (int i=0; i < args.length; i++) {
            if (args[i].startsWith("-")) {
  -            i++;
  -            if (i < args.length)
  -               options.put(args[i-1], args[i]);
  -            else
  -               options.put(args[i-1], "");
  +             if ((i+1) < args.length && !args[i+1].startsWith("-")) {
  +                 options.put(args[i], args[i+1]);
  +                 i++;
  +             } else {
  +               options.put(args[i], "");
  +             }
            } else {
  -            arguments.addElement(args[i]);
  +             arguments.addElement(args[i]);
            }
         }
   
  @@ -105,19 +103,22 @@
      private final static void displayUsage() {
         System.out.println(" java org.apache.fop.fonts.apps.TTFReader [options] fontfile.ttf xmlfile.xml\n");
         System.out.println(" where options can be:\n");
  +      System.out.println("-enc cid");
  +      System.out.println("     With this option you create a CID keyed font.");
  +      System.out.println("     If you're going to use characters outside the");
  +      System.out.println("     pdfencoding range (almost the same as iso-8889-1)");
  +      System.out.println("     you must add this option.");
  +      System.out.println("-ttcname <fontname>");
  +      System.out.println("     If you're reading data from a TrueType Collection");
  +      System.out.println("     (.ttc file) you must specify which font from the");
  +      System.out.println("     collection you will read metrics from. If you read");
  +      System.out.println("     from a .ttc file without this option, the fontnames");
  +      System.out.println("      will be listed for you.");
         System.out.println(" -fn <fontname>\n");
  -      System.out.println("     default is to use the fontname in the .ttf file, but you can override\n");
  -      System.out.println("     that name to make sure that the embedded font is used instead of installed\n");
  -      System.out.println("     fonts when viewing documents with Acrobat Reader.\n");
  -      System.out.println(" -cn <classname>\n");
  -      System.out.println("     default is to use the fontname\n");
  -      System.out.println(" -ef <path to the truetype fontfile>\n");
  -      System.out.println("     will add the possibility to embed the font. When running fop, fop will look\n");
  -      System.out.println("     for this file to embed it\n");
  -      System.out.println(" -er <path to truetype fontfile relative to org/apache/fop/render/pdf/fonts>\n");
  -      System.out.println("     you can also include the fontfile in the fop.jar file when building fop.\n");
  -      System.out.println("     You can use both -ef and -er. The file specified in -ef will be searched first,\n");
  -      System.out.println("     then the -er file.\n");
  +      System.out.println("     default is to use the fontname in the .ttf file, but\n"+
  +                         "     you can override that name to make sure that the\n");
  +      System.out.println("     embedded font is used (if you're embedding fonts)\n");
  +      System.out.println("     instead of installed fonts when viewing documents with Acrobat Reader.\n");
      }
         
         
  @@ -145,6 +146,8 @@
          String embResource=null;
          String className=null;
          String fontName=null;
  +       String ttcName=null;
  +       boolean isCid=false;
          
          Hashtable options=new Hashtable();
          String[] arguments=parseArguments(options, args);
  @@ -152,9 +155,18 @@
          TTFReader app = new TTFReader();
          app.invokedStandalone = true;
          
  -       System.out.println("TTF Reader v1.0");
  +       System.out.println("TTF Reader v1.1");
          System.out.println();
   
  +       if (options.get("-enc") != null) {
  +           String enc = (String)options.get("-enc");
  +           if ("cid".equals(enc))
  +               isCid=true;
  +       }
  +           
  +       if (options.get("-ttcname") != null) 
  +           ttcName=(String)options.get("-ttcname");
  +           
          if (options.get("-ef") != null)
             embFile=(String)options.get("-ef");
          
  @@ -173,20 +185,26 @@
              options.get("--help") != null)
             displayUsage();
          else {
  -          TTFFile ttf = app.loadTTF(arguments[0]);
  +          TTFFile ttf = app.loadTTF(arguments[0], ttcName);
             if (ttf != null) {
  -             app.preview(ttf);
  -             
                org.w3c.dom.Document doc = app.constructFontXML(ttf,
                                                                fontName,
                                                                className,
                                                                embResource,
  -                                                             embFile);
  +                                                             embFile,
  +                                                             isCid,
  +                                                             ttcName);
                
  -             doc = app.postProcessXML(doc);
                if (doc != null) {
                   app.writeFontXML(doc, arguments[1]);
                }
  +             
  +             if (ttf.isEmbeddable())
  +                 System.out.println("This font contains no embedding license restrictions");
  +             else
  +                 System.out.println("** Note: This font contains license retrictions for\n"+
  +                                    "         embedding. This font can't be embedded.");
  +             
             }
          }
       }
  @@ -195,16 +213,16 @@
           * Read a TTF file and returns it as an object.
           *
           * @param   filename The filename of the PFM file.
  -        * @return  The PFM as an object.
  +        * @return  The TTF as an object.
           */
  -   public TTFFile loadTTF(String filename) {
  +   public TTFFile loadTTF(String fileName, String fontName) {
         TTFFile ttfFile=new TTFFile();
         try {
  -         System.out.println("Reading " + filename + "...");
  +         System.out.println("Reading " + fileName + "...");
            System.out.println();
   
  -         FontFileReader reader = new FontFileReader(filename);
  -         ttfFile.readFont(reader);
  +         FontFileReader reader = new FontFileReader(fileName);
  +         ttfFile.readFont(reader, fontName);
         } catch (Exception e) {
            e.printStackTrace();
            return null;
  @@ -212,45 +230,6 @@
         return ttfFile;
       }
   
  -    /**
  -     * Displays a preview of the TTF file on the console.
  -     * 
  -     * @param   ttf The TTF file to preview.
  -     */
  -    public void preview(TTFFile ttf) {
  -        PrintStream out = System.out;
  -
  -        out.print("Font: ");
  -        out.println(ttf.getWindowsName());
  -        out.print("Name: ");
  -        out.println(ttf.getPostscriptName());
  -        out.print("CharSet: ");
  -        out.println(ttf.getCharSetName());
  -        out.print("CapHeight: ");
  -        out.println(ttf.getCapHeight());
  -        out.print("XHeight: ");
  -        out.println(ttf.getXHeight());
  -        out.print("LowerCaseAscent: ");
  -        out.println(ttf.getLowerCaseAscent());
  -        out.print("LowerCaseDescent: ");
  -        out.println(ttf.getLowerCaseDescent());
  -        out.print("Having widths for ");
  -        out.print(ttf.getLastChar()-ttf.getFirstChar());
  -        out.print(" characters (");
  -        out.print(ttf.getFirstChar());
  -        out.print("-");
  -        out.print(ttf.getLastChar());
  -        out.println(").");
  -        out.print("for example: Char ");
  -        out.print(ttf.getFirstChar());
  -        out.print(" has a width of ");
  -        out.println(ttf.getCharWidth(ttf.getFirstChar()));
  -        out.println();
  -        if (ttf.isEmbeddable())
  -           out.println("This font might be embedded");
  -        else
  -           out.println("This font might not be embedded");
  -    }
   
       /**
        * Writes the generated DOM Document to a file.
  @@ -276,21 +255,26 @@
       }
   
       /**
  -     * Generates the font metrics file from the PFM file.
  +     * Generates the font metrics file from the TTF/TTC file.
        * 
  -     * @param   pfm The PFM file to generate the font metrics from.
  +     * @param   ttf The PFM file to generate the font metrics from.
        * @return  The DOM document representing the font metrics file.
        */
       public org.w3c.dom.Document constructFontXML(TTFFile ttf, String fontName,
                                                    String className, String resource,
  -                                                 String file) {
  +                                                 String file, boolean isCid,
  +                                                 String ttcName) {
           System.out.println("Creating xml font file...");
           System.out.println();
   
           Document doc = new DocumentImpl();
           Element root = doc.createElement("font-metrics");
           doc.appendChild(root);
  -
  +        if (isCid)
  +            root.setAttribute("type", "TYPE0");
  +        else
  +            root.setAttribute("type", "TRUETYPE");
  +        
           Element el = doc.createElement("font-name");
           root.appendChild(el);
   
  @@ -298,51 +282,19 @@
               // "Perpetua-Bold", but the TrueType spec says that in the ttf file
               // it should be "Perpetua,Bold".
   
  -        String s = ttf.getPostscriptName();
  +        String s = stripWhiteSpace(ttf.getPostscriptName());
   
           if (fontName != null)
  -           el.appendChild(doc.createTextNode(fontName));
  -        else
  -           el.appendChild(doc.createTextNode(s.replace('-', ',')));
  -
  -        int pos = s.indexOf("-");
  -        if (pos >= 0) {
  -           char sb[] = new char[s.length() - 1];
  -           s.getChars(0, pos, sb, 0);
  -           s.getChars(pos + 1, s.length(), sb, pos);
  -           s = new String(sb);
  -        }
  -        
  -        el = doc.createElement("class-name");
  -        root.appendChild(el);
  -        if (className != null)
  -           el.appendChild(doc.createTextNode(className));
  -        else
  -           el.appendChild(doc.createTextNode(s));
  -
  -        el = doc.createElement("embedFile");
  -        root.appendChild(el);
  -            //if (file==null || !ttf.isEmbeddable())
  -        if (file==null)
  -           el.appendChild(doc.createTextNode("null"));
  -        else
  -           el.appendChild(doc.createTextNode("\""+escapeString(file)+"\""));
  -        
  -        el = doc.createElement("embedResource");
  -        root.appendChild(el);
  -            //if (resource==null || !ttf.isEmbeddable())
  -        if (resource==null)
  -           el.appendChild(doc.createTextNode("null"));
  +           el.appendChild(doc.createTextNode(stripWhiteSpace(fontName)));
           else
  -           el.appendChild(doc.createTextNode("\""+escapeString(resource)+"\""));
  -
  -        el = doc.createElement("subtype");
  -        root.appendChild(el);
  -        el.appendChild(doc.createTextNode("TRUETYPE"));
  +            el.appendChild(doc.createTextNode(s));
   
  -        el = doc.createElement("encoding");
  +        el = doc.createElement("embed");
           root.appendChild(el);
  -        el.appendChild(doc.createTextNode(ttf.getCharSetName()+"Encoding"));
  +        if (file != null && ttf.isEmbeddable())
  +            el.setAttribute("file", file);
  +        if (resource != null && ttf.isEmbeddable())
  +            el.setAttribute("class", resource);
   
           el = doc.createElement("cap-height");
           root.appendChild(el);
  @@ -353,12 +305,12 @@
           root.appendChild(el);
           value = new Integer(ttf.getXHeight());
           el.appendChild(doc.createTextNode(value.toString()));
  -
  +        
           el = doc.createElement("ascender");
           root.appendChild(el);
           value = new Integer(ttf.getLowerCaseAscent());
           el.appendChild(doc.createTextNode(value.toString()));
  -
  +        
           el = doc.createElement("descender");
           root.appendChild(el);
           value = new Integer(ttf.getLowerCaseDescent());
  @@ -379,115 +331,143 @@
           root.appendChild(el);
           value = new Integer(ttf.getFlags());
           el.appendChild(doc.createTextNode(value.toString()));
  -
  +        
           el = doc.createElement("stemv");
           root.appendChild(el);
           value = new Integer(ttf.getStemV());
           el.appendChild(doc.createTextNode(value.toString()));
  -
  +        
           el = doc.createElement("italicangle");
           root.appendChild(el);
           value = new Integer(ttf.getItalicAngle());
           el.appendChild(doc.createTextNode(value.toString()));
  -
  -        el = doc.createElement("first-char");
  -        root.appendChild(el);
  -        value = new Integer(ttf.getFirstChar());
  -        el.appendChild(doc.createTextNode(value.toString()));
   
  -        el = doc.createElement("last-char");
  +        if (ttcName != null) {
  +            el = doc.createElement("ttc-name");
  +            root.appendChild(el);
  +            el.appendChild(doc.createTextNode(ttcName));
  +        }
  +        
  +        el = doc.createElement("subtype");
           root.appendChild(el);
  -        value = new Integer(ttf.getLastChar());
  -        el.appendChild(doc.createTextNode(value.toString()));
  +        
  +            // Fill in extras for CID keyed fonts
  +        if (isCid) {
  +            el.appendChild(doc.createTextNode("TYPE0"));
   
  -        Element widths = doc.createElement("widths");
  -        root.appendChild(widths);
  +            Element mel = doc.createElement("multibyte-extras");
  +            root.appendChild(mel);
  +            
  +            el = doc.createElement("cid-type");
  +            mel.appendChild(el);
  +            el.appendChild(doc.createTextNode("CIDFontType2"));
  +
  +            el = doc.createElement("default-width");
  +            mel.appendChild(el);
  +            el.appendChild(doc.createTextNode("0"));
  +
  +            el = doc.createElement("bfranges");
  +            mel.appendChild(el);
  +            for (Enumeration e=ttf.getCMaps().elements(); e.hasMoreElements();) {
  +                TTFCmapEntry ce = (TTFCmapEntry)e.nextElement();
  +                Element el2=doc.createElement("bf");
  +                el.appendChild(el2);
  +                el2.setAttribute("us", Integer.toString(ce.unicodeStart));
  +                el2.setAttribute("ue", Integer.toString(ce.unicodeEnd));
  +                el2.setAttribute("gi", Integer.toString(ce.glyphStartIndex));
  +            }
  +            
  +            el = doc.createElement("cid-widths");
  +            el.setAttribute("start-index", "0");
  +            mel.appendChild(el);
  +
  +            int[] wx = ttf.getWidths();
  +            for (int i = 0; i < wx.length; i++) {
  +                Element wxel=doc.createElement("wx");
  +                wxel.setAttribute("w", Integer.toString(wx[i]));
  +                el.appendChild(wxel);
  +            }
  +        } else {
  +                // Fill in extras for singlebyte fonts
  +            el.appendChild(doc.createTextNode("TRUETYPE"));
   
  -        for (short i = ttf.getFirstChar(); i < ttf.getLastChar(); i++) {
  -            el = doc.createElement("char");
  -            widths.appendChild(el);
  -                //el.setAttribute("ansichar", "0x00" + Integer.toHexString(i).toUpperCase());
  -            el.setAttribute("name", "0x00" +
  -                            Integer.toHexString(i).toUpperCase());
  -            el.setAttribute("width",
  -                            new Integer(ttf.getCharWidth(i)).toString());
  +            Element sel=doc.createElement("singlebyte-extras");
  +            root.appendChild(sel);
  +            
  +            el = doc.createElement("encoding");
  +            sel.appendChild(el);
  +            el.appendChild(doc.createTextNode(ttf.getCharSetName()));
  +
  +            el = doc.createElement("first-char");
  +            sel.appendChild(el);
  +            value = new Integer(ttf.getFirstChar());
  +            el.appendChild(doc.createTextNode(value.toString()));
  +            
  +            el = doc.createElement("last-char");
  +            sel.appendChild(el);
  +            value = new Integer(ttf.getLastChar());
  +            el.appendChild(doc.createTextNode(value.toString()));
  +            
  +            Element widths = doc.createElement("widths");
  +            sel.appendChild(widths);
  +            
  +            for (short i = ttf.getFirstChar(); i < ttf.getLastChar(); i++) {
  +                el = doc.createElement("char");
  +                widths.appendChild(el);
  +                el.setAttribute("idx", Integer.toString(i));
  +                el.setAttribute("wdt", Integer.toString(ttf.getCharWidth(i)));
  +            }
           }
  -
  +        
               // Get kerning
  -        for (Enumeration enum=ttf.getKerning().keys(); enum.hasMoreElements();) {
  -           String kpx1=(String)enum.nextElement();
  -           el=doc.createElement("kerning");
  -           el.setAttribute("kpx1", kpx1);
  -           root.appendChild(el);
  -           Element el2=null;
  -           
  -           Hashtable h2=(Hashtable)ttf.getKerning().get(kpx1);
  -           for (Enumeration enum2=h2.keys(); enum2.hasMoreElements(); ) {
  -              String kpx2=(String)enum2.nextElement();
  -              el2=doc.createElement("pair");
  -              el2.setAttribute("kpx2", kpx2);
  -              Integer val=(Integer)h2.get(kpx2);
  -              el2.setAttribute("kern", val.toString());
  -              el.appendChild(el2);
  -           }
  -        }
  -        return doc;
  -    }
  +        Enumeration enum;
  +        if (isCid)
  +            enum=ttf.getKerning().keys();
  +        else
  +            enum=ttf.getAnsiKerning().keys();
  +        
  +        while (enum.hasMoreElements()) {
  +            Integer kpx1=(Integer)enum.nextElement();
   
  -    /**
  -     * Modifies the generated font metrics file. First, it processes the
  -     * character mmappings, then it sorts them.
  -     * 
  -     * @param   doc The DOM document representing the font metrics file.
  -     * @return  A DOM document representing the processed font metrics file.
  -     */
  -    public org.w3c.dom.Document postProcessXML(org.w3c.dom.Document doc) {
  -       if (true)
  -          return doc;
  -        try {
  -            OutputFormat format = new OutputFormat(doc);     //Serialize DOM
  -            XMLSerializer serial = new XMLSerializer(System.out, format);
  -            serial.asDOMSerializer();                        // As a DOM Serializer
  -            serial.serialize(doc.getDocumentElement());
  +            el=doc.createElement("kerning");
  +            el.setAttribute("kpx1", kpx1.toString());
  +            root.appendChild(el);
  +            Element el2=null;
               
  -            System.out.println("Postprocessing...");
  -            System.out.println();
  -
  -           
  -
  -            InputStream xsl = this.getClass().getResourceAsStream(XSL_POSTPROCESS);
  -            if (xsl == null) {
  -                throw new Exception("Resource " + XSL_POSTPROCESS + " not found");
  -            }
  -           
  -            Document targetDoc = new DocumentImpl();
  -	    org.apache.fop.tools.xslt.XSLTransform.transform(doc, xsl, targetDoc);
  -	    
  -
  -            System.out.println("Sorting...");
  -            System.out.println();
  -
  -            // Sort the whole thing
  +            Hashtable h2;
  +            if (isCid)
  +                h2 = (Hashtable)ttf.getKerning().get(kpx1);
  +            else
  +                h2 = (Hashtable)ttf.getAnsiKerning().get(kpx1);
               
  -
  -            xsl = this.getClass().getResourceAsStream(XSL_SORT);
  -            if (xsl == null) {
  -                throw new Exception("Resource " + XSL_SORT + " not found");
  +            for (Enumeration enum2=h2.keys(); enum2.hasMoreElements(); ) {
  +                Integer kpx2=(Integer)enum2.nextElement();
  +                if (isCid || kpx2.intValue() < 256) {
  +                    el2=doc.createElement("pair");
  +                    el2.setAttribute("kpx2", kpx2.toString());
  +                    Integer val=(Integer)h2.get(kpx2);
  +                    el2.setAttribute("kern", val.toString());
  +                    el.appendChild(el2);
  +                }
               }
  -            
  -
  -            org.w3c.dom.Document targetDocSorted = new DocumentImpl();
  -
  -	    org.apache.fop.tools.xslt.XSLTransform.transform(targetDoc, xsl, targetDocSorted);
  -
  -            return targetDocSorted;
  -
  -        } catch (Exception e) {
  -            e.printStackTrace();
  -            return null;
           }
  +        
  +        return doc;
       }
  +        
  +    
  +    private String stripWhiteSpace(String s) {
  +        char[] ch = new char[s.length()];
  +        s.getChars(0, s.length(), ch, 0);
  +        StringBuffer stb = new StringBuffer();
  +        for (int i = 0; i < ch.length; i++)
  +            if (ch[i] != ' ' && ch[i] != '\r' &&
  +                ch[i] != '\n' && ch[i] != '\t')
  +                stb.append(ch[i]);
   
  +        return stb.toString();
  +    }
  +        
      private String escapeString(String str) {
         StringBuffer esc=new StringBuffer();
         
  
  
  
  1.7       +13 -6     xml-fop/src/org/apache/fop/layout/FontInfo.java
  
  Index: FontInfo.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/layout/FontInfo.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- FontInfo.java	2000/06/27 22:14:09	1.6
  +++ FontInfo.java	2001/02/27 12:28:16	1.7
  @@ -1,4 +1,4 @@
  -/*-- $Id: FontInfo.java,v 1.6 2000/06/27 22:14:09 fotis Exp $ -- 
  +/*-- $Id: FontInfo.java,v 1.7 2001/02/27 12:28:16 fotis Exp $ -- 
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -57,13 +57,14 @@
   import org.apache.fop.apps.FOPException;
   
   public class FontInfo {
  -
  +  Hashtable usedFonts;
     Hashtable triplets; // look up a font-triplet to find a font-name
     Hashtable fonts; // look up a font-name to get a font (that implements FontMetric at least)
   
     public FontInfo() {
       this.triplets = new Hashtable(); 
  -    this.fonts = new Hashtable(); 
  +    this.fonts = new Hashtable();
  +    this.usedFonts = new Hashtable();
     }
   
     public void addFontProperties(String name, String family, String style, String weight) {
  @@ -109,6 +110,8 @@
         }
         MessageHandler.errorln("WARNING: unknown font "+family+" so defaulted font to any");
       }
  +
  +    usedFonts.put(f, fonts.get(f)); 
       return f;
     }
   
  @@ -116,13 +119,17 @@
       return this.fonts;
     }
   
  +  public Hashtable getUsedFonts() {
  +    return this.usedFonts;
  +  }
  +
     public FontMetric getMetricsFor(String fontName) throws FOPException {
  -    return (FontMetric)fonts.get(fontName);
  +      usedFonts.put(fontName, fonts.get(fontName));
  +      return (FontMetric)fonts.get(fontName);
     }
   
     public FontMetric getMetricsFor(String family, String style, String weight) throws FOPException {
       // given a family, style and weight, return the metric
  -
  -    return (FontMetric)fonts.get(fontLookup(family,style,weight));
  +      return (FontMetric)fonts.get(fontLookup(family,style,weight));
     }
   }
  
  
  
  1.11      +95 -61    xml-fop/src/org/apache/fop/layout/FontState.java
  
  Index: FontState.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/layout/FontState.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- FontState.java	2001/02/05 08:35:32	1.10
  +++ FontState.java	2001/02/27 12:28:16	1.11
  @@ -1,4 +1,4 @@
  -/*-- $Id: FontState.java,v 1.10 2001/02/05 08:35:32 kellyc Exp $ --
  +/*-- $Id: FontState.java,v 1.11 2001/02/27 12:28:16 fotis Exp $ --
   
    ============================================================================
   									 The Apache Software License, Version 1.1
  @@ -54,17 +54,17 @@
   import org.apache.fop.fo.properties.FontVariant;
   
   public class FontState {
  -
  -		protected FontInfo fontInfo;
  -		private String fontName;
  -		private int fontSize;
  -		private String fontFamily;
  -		private String fontStyle;
  -		private String fontWeight;
  -		private FontMetric metric;
  -		private int fontVariant;
  -
  -		public FontState(FontInfo fontInfo, String fontFamily, String fontStyle, String fontWeight, int fontSize, int fontVariant) throws FOPException {
  +    
  +    protected FontInfo fontInfo;
  +    private String fontName;
  +    private int fontSize;
  +    private String fontFamily;
  +    private String fontStyle;
  +    private String fontWeight;
  +    private FontMetric metric;
  +    private int fontVariant;
  +    
  +    public FontState(FontInfo fontInfo, String fontFamily, String fontStyle, String fontWeight, int fontSize, int fontVariant) throws FOPException {
   	this.fontInfo = fontInfo;
   	this.fontFamily = fontFamily;
   	this.fontStyle = fontStyle;
  @@ -73,65 +73,99 @@
   	this.fontName = fontInfo.fontLookup(fontFamily,fontStyle,fontWeight);
   	this.metric = fontInfo.getMetricsFor(fontName);
   	this.fontVariant = fontVariant;
  -		}
  -
  -		public int getAscender() {
  +    }
  +    
  +    public int getAscender() {
   	return  metric.getAscender(fontSize) / 1000;
  -		}
  -
  -		public int getCapHeight() {
  +    }
  +    
  +    public int getCapHeight() {
   	return metric.getCapHeight(fontSize) / 1000;
  -		}
  -
  -		public int getDescender() {
  +    }
  +    
  +    public int getDescender() {
   	return metric.getDescender(fontSize) / 1000;
  -		}
  -
  -		public String getFontName() {
  +    }
  +    
  +    public String getFontName() {
   	return this.fontName;
  -		}
  -
  -		public int getFontSize() {
  +    }
  +    
  +    public int getFontSize() {
   	return this.fontSize;
  -		}
  -
  -		public String getFontWeight() {
  +    }
  +    
  +    public String getFontWeight() {
   	return this.fontWeight;
  -		}
  -
  -		public String getFontFamily() {
  +    }
  +    
  +    public String getFontFamily() {
   	return this.fontFamily;
  -		}
  -
  -		public String getFontStyle() {
  +    }
  +    
  +    public String getFontStyle() {
   	return this.fontStyle;
  -		}
  -
  -		public int getFontVariant() {
  +    }
  +    
  +    public int getFontVariant() {
   	return this.fontVariant;
  -		}
  -
  -		public FontInfo getFontInfo() {
  +    }
  +    
  +    public FontInfo getFontInfo() {
   	return this.fontInfo;
  -		}
  -
  -		public int getXHeight() {
  +    }
  +    
  +    public int getXHeight() {
   	return metric.getXHeight(fontSize) / 1000;
  -		}
  -   public java.util.Hashtable getKerning() {
  -      java.util.Hashtable ret=new java.util.Hashtable();
  -      try {
  -         FontMetric fm=fontInfo.getMetricsFor(fontFamily, fontStyle, fontWeight);
  -         if (fm instanceof org.apache.fop.layout.FontDescriptor) {
  -            org.apache.fop.layout.FontDescriptor fdes=(org.apache.fop.layout.FontDescriptor)fm;
  -            ret=fdes.getKerningInfo();
  -         }
  -      } catch (Exception e) {}
  -      return ret;
  -   }
  -
  -		public int width(int charnum) {
  -	// returns width of given character number in millipoints
  +    }
  +    
  +    public java.util.Hashtable getKerning() {
  +        java.util.Hashtable ret=new java.util.Hashtable();
  +        try {
  +            FontMetric fm=fontInfo.getMetricsFor(fontFamily, fontStyle,
  +                                                 fontWeight);
  +            if (fm instanceof org.apache.fop.layout.FontDescriptor) {
  +                org.apache.fop.layout.FontDescriptor fdes=
  +                    (org.apache.fop.layout.FontDescriptor)fm;
  +                ret=fdes.getKerningInfo();
  +            }
  +        } catch (Exception e) {}
  +        return ret;
  +    }
  +    
  +    public int width(int charnum) {
  +            // returns width of given character number in millipoints
   	return (metric.width(charnum, fontSize) / 1000);
  -		}
  +    }
  +    
  +        /**
  +         * Map a java character (unicode) to a font character
  +         * Default uses CodePointMapping
  +         */
  +    public char mapChar(char c) {
  +        try {
  +            FontMetric fm=fontInfo.getMetricsFor(fontFamily, fontStyle,
  +                                                 fontWeight);
  +            if (fm instanceof org.apache.fop.render.pdf.Font) {
  +                org.apache.fop.render.pdf.Font f=
  +                    (org.apache.fop.render.pdf.Font)fm;
  +                return f.mapChar(c);
  +            }
  +        } catch (Exception e) {}
  +
  +            // Use default CodePointMapping
  +        if (c > 127) {
  +            char d = org.apache.fop.render.pdf.CodePointMapping.map[c];
  +            if (d != 0) {
  +                c = d;
  +            } else {
  +                c = '#';
  +            }
  +        }
  +        
  +        return c;
  +    }
   }
  +
  +
  +
  
  
  
  1.35      +17 -19    xml-fop/src/org/apache/fop/layout/LineArea.java
  
  Index: LineArea.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/layout/LineArea.java,v
  retrieving revision 1.34
  retrieving revision 1.35
  diff -u -r1.34 -r1.35
  --- LineArea.java	2001/02/20 19:14:37	1.34
  +++ LineArea.java	2001/02/27 12:28:16	1.35
  @@ -1,4 +1,4 @@
  -/*-- $Id: LineArea.java,v 1.34 2001/02/20 19:14:37 fotis Exp $ --
  +/*-- $Id: LineArea.java,v 1.35 2001/02/27 12:28:16 fotis Exp $ --
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -184,8 +184,10 @@
           */
   
           //Space must be alloted to the page number, so currently we give it 3 spaces
  -        int width = currentFontState.width(32) * 3;
  +        
  +        int width = currentFontState.width(currentFontState.mapChar(' '));
   
  +
           PageNumberInlineArea pia =
             new PageNumberInlineArea(currentFontState, this.red,
                                      this.green, this.blue, refid, width);
  @@ -214,6 +216,10 @@
           int wordStart = start;
           int wordLength = 0;
           int wordWidth = 0;
  +            // With CID fonts, space isn't neccecary currentFontState.width(32)
  +        int whitespaceWidth =
  +            currentFontState.width(currentFontState.mapChar(' '));
  +        
           char[] data = new char[odata.length];
           for (int count = 0; count < odata.length; count++) {
               data[count] = odata[count];
  @@ -224,18 +230,10 @@
               int charWidth;
               /* get the character */
               char c = data[i];
  -
  -            if (c > 127) {
  -                /* this class shouldn't be hard coded */
  -                char d = org.apache.fop.render.pdf.CodePointMapping.map[c];
  -                if (d != 0) {
  -                    c = data[i] = d;
  -                } else {
  -                    MessageHandler.error("ch" + (int) c + "?");
  -                    c = data[i] = '#';
  -                }
  -            }
  -
  +            if (!((c == ' ') || (c == '\n') || (c == '\r') ||
  +                (c == '\t')))
  +                c = data[i] = currentFontState.mapChar(c);
  +            
               charWidth = currentFontState.width(c);
   
               if ((c == ' ') || (c == '\n') || (c == '\r') ||
  @@ -248,12 +246,12 @@
                       if (this.whiteSpaceCollapse ==
                               WhiteSpaceCollapse.FALSE) {
                           if (c == ' ') {
  -                            spaceWidth += currentFontState.width(32);
  +                            spaceWidth += whitespaceWidth;
                           } else if (c == '\n') {
                               // force line break
                               return i;
                           } else if (c == '\t') {
  -                            spaceWidth += 8 * currentFontState.width(32);
  +                            spaceWidth += 8 * whitespaceWidth;
                           }
                       } // else ignore it
   
  @@ -339,7 +337,7 @@
   
                       embeddedLinkStart = 0; //reset embeddedLinkStart since a space was encountered
   
  -                    spaceWidth = currentFontState.width(32);
  +                    spaceWidth = whitespaceWidth;
   
                       /*
                       here is the place for space-treatment value 'ignore':
  @@ -359,7 +357,7 @@
                               // force a line break
                               return i;
                           } else if (c == '\t') {
  -                            spaceWidth = currentFontState.width(32);
  +                            spaceWidth = whitespaceWidth;
                           }
                       }
   
  @@ -370,7 +368,7 @@
                       if (this.whiteSpaceCollapse ==
                               WhiteSpaceCollapse.FALSE) {
                           prev = WHITESPACE;
  -                        spaceWidth = currentFontState.width(32);
  +                        spaceWidth = whitespaceWidth;
                       } else {
                           // skip over it
                           start++;
  
  
  
  1.2       +28 -11    xml-fop/src/org/apache/fop/pdf/PDFCIDFont.java
  
  Index: PDFCIDFont.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/pdf/PDFCIDFont.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- PDFCIDFont.java	2001/02/05 08:35:35	1.1
  +++ PDFCIDFont.java	2001/02/27 12:28:16	1.2
  @@ -1,4 +1,4 @@
  -/*-- $Id: PDFCIDFont.java,v 1.1 2001/02/05 08:35:35 kellyc Exp $ --
  +/*-- $Id: PDFCIDFont.java,v 1.2 2001/02/27 12:28:16 fotis Exp $ --
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -69,6 +69,7 @@
   	protected PDFWArray w2;
   	protected PDFCIDSystemInfo systemInfo;
   	protected PDFCIDFontDescriptor descriptor;
  +        protected PDFCMap cmap;
   	/**
   	 * /CIDToGIDMap (only for CIDFontType2, see p 212)
   	 * can be either "Identity" (default) or a PDFStream
  @@ -79,14 +80,15 @@
   	/**
   	 * create the /Font object
   	 */
  -	public PDFCIDFont(int number, String basefont, String cidtype,
  -			int dw, int[] w, String registry, String ordering, int supplement,
  -			PDFCIDFontDescriptor descriptor) {
  +	public PDFCIDFont(int number, String basefont, byte cidtype,
  +                          int dw, int[] w,
  +                          String registry, String ordering, int supplement,
  +                          PDFCIDFontDescriptor descriptor) {
   
   		super(number);
   
   		this.basefont = basefont;
  -		this.cidtype = cidtype;
  +		this.cidtype = TYPE_NAMES[(int)cidtype];
   		this.dw = new Integer(dw);
   		this.w = new PDFWArray();
   		this.w.addEntry(0, w);
  @@ -95,19 +97,20 @@
   		this.systemInfo = new PDFCIDSystemInfo(registry, ordering, supplement);
   		this.descriptor = descriptor;
   		this.cidMap = null;
  +                this.cmap = null;
   	}
   
   	/**
   	 * create the /Font object
   	 */
  -	public PDFCIDFont(int number, String basefont, String cidtype,
  +	public PDFCIDFont(int number, String basefont, byte cidtype,
   			int dw, PDFWArray w, PDFCIDSystemInfo systemInfo,
   			PDFCIDFontDescriptor descriptor) {
   
   		super(number);
   
   		this.basefont = basefont;
  -		this.cidtype = cidtype;
  +		this.cidtype = TYPE_NAMES[(int)cidtype];
   		this.dw = new Integer(dw);
   		this.w = w;
   		this.dw2 = null;
  @@ -115,6 +118,7 @@
   		this.systemInfo = systemInfo;
   		this.descriptor = descriptor;
   		this.cidMap = null;
  +                this.cmap = null;
   	}
   
   	/** set the /DW attribute */
  @@ -137,6 +141,13 @@
   		this.dw2 = new int[] {posY, displacementY};
   	}
   
  +        /**
  +         * Set the CMap used as /ToUnicode cmap
  +         */
  +    public void setCMAP(PDFCMap cmap) {
  +        this.cmap = cmap;
  +    }
  +    
   	/** set the /W2 array */
   	public void setW2(PDFWArray w2) {
   	    this.w2 = w2;
  @@ -172,16 +183,20 @@
   			p.append(cidMap.referencePDF());
   		}
   		p.append(" \n/Subtype /"); p.append(this.cidtype);
  -		p.append("\n"); p.append(systemInfo.toPDF());
  +		p.append("\n"); p.append(systemInfo.toPDFString());
   		p.append("\n/FontDescriptor ");
   		p.append(this.descriptor.referencePDF());
  +
  +                if (cmap != null) {
  +                    p.append("\n/ToUnicode ");
  +                    p.append(cmap.referencePDF());
  +                }
   		if (dw != null) {
   			p.append("\n/DW "); p.append(this.dw);
   		}
   		if (w != null) {
   			p.append("\n/W ");
  -			p.append(w.toPDF());
  -			p.append(" \n>>\nendobj\n");
  +			p.append(w.toPDFString());
   		}
   		if (dw2 != null) {
   			p.append("\n/DW2 ["); // always two values, see p 211
  @@ -191,9 +206,11 @@
   		}
   		if (w2 != null) {
   			p.append("\n/W2 ");
  -			p.append(w2.toPDF());
  +			p.append(w2.toPDFString());
   			p.append(" \n>>\nendobj\n");
   		}
  +                p.append(" \n>>\nendobj\n");
   		return p.toString();
   	}
   }
  +
  
  
  
  1.2       +2 -1      xml-fop/src/org/apache/fop/pdf/PDFCIDFontDescriptor.java
  
  Index: PDFCIDFontDescriptor.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/pdf/PDFCIDFontDescriptor.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- PDFCIDFontDescriptor.java	2001/02/05 08:35:35	1.1
  +++ PDFCIDFontDescriptor.java	2001/02/27 12:28:16	1.2
  @@ -1,4 +1,4 @@
  -/*-- $Id: PDFCIDFontDescriptor.java,v 1.1 2001/02/05 08:35:35 kellyc Exp $ --
  +/*-- $Id: PDFCIDFontDescriptor.java,v 1.2 2001/02/27 12:28:16 fotis Exp $ --
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -92,6 +92,7 @@
       }
   
       protected void fillInPDF(StringBuffer p) {
  +        p.append("\n/MissingWidth 500\n");
   	if (lang != null) {
   	    p.append("\n/Lang /"); p.append(lang);
   	}
  
  
  
  1.2       +61 -12    xml-fop/src/org/apache/fop/pdf/PDFCMap.java
  
  Index: PDFCMap.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/pdf/PDFCMap.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- PDFCMap.java	2001/02/05 08:35:35	1.1
  +++ PDFCMap.java	2001/02/27 12:28:16	1.2
  @@ -1,4 +1,4 @@
  -/*-- $Id: PDFCMap.java,v 1.1 2001/02/05 08:35:35 kellyc Exp $ --
  +/*-- $Id: PDFCMap.java,v 1.2 2001/02/27 12:28:16 fotis Exp $ --
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -150,6 +150,12 @@
   		this.wMode = mode;
   	}
   
  +    public void addContents() {
  +        StringBuffer p=new StringBuffer();
  +        fillInPDF(p);
  +        add(p.toString());
  +    }
  +    
   	/**
   	 * set the base CMap
   	 *
  @@ -169,16 +175,59 @@
   	}
   
   	public void fillInPDF(StringBuffer p) {
  -		p.append(" /Type /CMap\n/CMapName /" + name);
  -		p.append("\n"); p.append(sysInfo.toPDF());
  -		p.append("\n/WMode "); p.append(wMode);
  -		if (base != null) {
  -			p.append("\n/UseCMap ");
  -			if (base instanceof String) {
  -				p.append("/"+base);
  -			} else {	// base instanceof PDFStream
  -				p.append(((PDFStream)base).referencePDF());
  -			}
  -		}
  +                //p.append("/Type /CMap\n");
  +                //p.append(sysInfo.toPDFString());
  +                //p.append("/CMapName /" + name);
  +                //p.append("\n");
  +            p.append("%!PS-Adobe-3.0 Resource-CMap\n");
  +            p.append("%%DocumentNeededResources: ProcSet (CIDInit)\n");
  +            p.append("%%IncludeResource: ProcSet (CIDInit)\n");
  +            p.append("%%BeginResource: CMap (" + name + ")\n");
  +            p.append("%%EndComments\n");
  +            
  +            p.append("/CIDInit /ProcSet findresource begin\n");
  +            p.append("12 dict begin\n");
  +            p.append("begincmap\n");
  +            
  +            p.append("/CIDSystemInfo 3 dict dup begin\n");
  +            p.append("  /Registry (Adobe) def\n");
  +            p.append("  /Ordering (Identity) def\n");
  +            p.append("  /Supplement 0 def\n");
  +            p.append("end def\n");
  +
  +            p.append("/CMapVersion 1 def\n");
  +            p.append("/CMapType 1 def\n");
  +            p.append("/CMapName /" + name + " def\n");
  +
  +            p.append("1 begincodespacerange\n");
  +            p.append("<0000> <FFFF>\n");
  +            p.append("endcodespacerange\n");
  +            p.append("1 begincidrange\n");
  +            p.append("<0000> <FFFF> 0\n");
  +            p.append("endcidrange\n");
  +            
  +                //p.append("1 beginbfrange\n");
  +                //p.append("<0020> <0100> <0000>\n");
  +                //p.append("endbfrange\n");
  +            
  +            p.append("endcmap\n");
  +            p.append("CMapName currentdict /CMap defineresource pop\n");
  +            p.append("end\n");
  +            p.append("end\n");
  +            p.append("%%EndResource\n");
  +            p.append("%%EOF\n");
  +                /*
  +            p.append(" /Type /CMap\n/CMapName /" + name);
  +            p.append("\n"); 
  +            p.append("\n/WMode "); p.append(wMode);
  +            if (base != null) {
  +                p.append("\n/UseCMap ");
  +                if (base instanceof String) {
  +                    p.append("/"+base);
  +                } else {	// base instanceof PDFStream
  +                    p.append(((PDFStream)base).referencePDF());
  +                }
  +            }
  +            */
   	}
   }
  
  
  
  1.19      +101 -39   xml-fop/src/org/apache/fop/pdf/PDFDocument.java
  
  Index: PDFDocument.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/pdf/PDFDocument.java,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- PDFDocument.java	2001/02/06 07:34:48	1.18
  +++ PDFDocument.java	2001/02/27 12:28:16	1.19
  @@ -1,4 +1,4 @@
  -/*-- $Id: PDFDocument.java,v 1.18 2001/02/06 07:34:48 kellyc Exp $ --
  +/*-- $Id: PDFDocument.java,v 1.19 2001/02/27 12:28:16 fotis Exp $ --
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -61,6 +61,8 @@
   import org.apache.fop.layout.LinkSet;
   import org.apache.fop.datatypes.ColorSpace;
   
  +import org.apache.fop.render.pdf.CIDFont; 
  +
   import org.apache.fop.datatypes.IDReferences;
   import org.apache.fop.layout.Page;
   import org.apache.fop.layout.FontMetric;
  @@ -751,59 +753,119 @@
           /* create a PDFFont with the next object number and add to the
              list of objects */
           if (descriptor == null) {
  -            PDFFont font = new PDFFont(++this.objectcount, fontname, PDFFont.TYPE1,
  -                    basefont, encoding);
  +            PDFFont font = new PDFFont(++this.objectcount, fontname,
  +                                       PDFFont.TYPE1,
  +                                       basefont, encoding);
               this.objects.addElement(font);
               return font;
           } else {
  -           byte subtype=PDFFont.TYPE1;
  -           if (metrics instanceof org.apache.fop.render.pdf.Font)
  -              subtype=((org.apache.fop.render.pdf.Font)metrics).getSubType();
  -           
  -            PDFFontNonBase14 font = (PDFFontNonBase14)PDFFont.createFont(
  +            byte subtype=PDFFont.TYPE1;
  +            if (metrics instanceof org.apache.fop.render.pdf.Font)
  +                subtype=((org.apache.fop.render.pdf.Font)metrics).getSubType();
  +            
  +            PDFFontDescriptor pdfdesc = makeFontDescriptor(descriptor,
  +                                                           subtype);
  +                
  +            PDFFontNonBase14 font = null;
  +            if (subtype == PDFFont.TYPE0) {
  +                PDFCMap cmap = new PDFCMap(++this.objectcount,
  +                                           "fop-ucs-H",
  +                                           new PDFCIDSystemInfo("Adobe",
  +                                                                "Identity",
  +                                                                0));
  +                cmap.addContents();
  +                this.objects.addElement(cmap);
  +            
  +                font = (PDFFontNonBase14)PDFFont.createFont(
  +                    ++this.objectcount, fontname,
  +                    subtype, basefont, cmap);
  +            } else {
  +            
  +                font = (PDFFontNonBase14)PDFFont.createFont(
                       ++this.objectcount, fontname,
                       subtype, basefont, encoding);
  +            }
               this.objects.addElement(font);
  -            PDFFontDescriptor pdfdesc = makeFontDescriptor(descriptor);
  +            
               font.setDescriptor(pdfdesc);
  -            font.setWidthMetrics(metrics.getFirstChar(), metrics.getLastChar(),
  -                    makeArray(metrics.getWidths(1)));
  +            
  +            if (subtype == PDFFont.TYPE0) {
  +                CIDFont cidMetrics = (CIDFont)metrics;
  +                PDFCIDSystemInfo sysInfo =
  +                    new PDFCIDSystemInfo(cidMetrics.getRegistry(),
  +                                         cidMetrics.getOrdering(),
  +                                         cidMetrics.getSupplement());
  +                PDFCIDFont cidFont =
  +                    new PDFCIDFont(++this.objectcount, basefont,
  +                                   cidMetrics.getCidType(),
  +                                   cidMetrics.getDefaultWidth(),
  +                                   cidMetrics.getWidths(),
  +                                   sysInfo, (PDFCIDFontDescriptor)pdfdesc);
  +                this.objects.addElement(cidFont);
  +                
  +                    //((PDFFontType0)font).setCMAP(cmap);
  +                
  +                ((PDFFontType0)font).setDescendantFonts(cidFont);
  +            } else {
  +                font.setWidthMetrics(metrics.getFirstChar(),
  +                                     metrics.getLastChar(),
  +                                     makeArray(metrics.getWidths(1)));
  +            }
  +            
               return font;
           }
       }
   
   
   	/**
  -	 * make a /FontDescriptor object for a CID font
  +	 * make a /FontDescriptor object
   	 */
  -	public PDFFontDescriptor makeFontDescriptor(FontDescriptor desc) {
  -
  -    	/* create a PDFFontDescriptor with the next object number and add to
  -           the list of objects */
  -           PDFFontDescriptor font =
  -              new PDFFontDescriptor(++this.objectcount,
  -                                    desc.fontName(), desc.getAscender(), desc.getDescender(),
  -                                    desc.getCapHeight(), desc.getFlags(),
  -                                    new PDFRectangle(desc.getFontBBox()), desc.getStemV(),
  -                                    desc.getItalicAngle());
  -           
  -               // Check if embedding of this font is enabled in the configurationfile
  -               // and that the font is embeddable
  -           java.util.Vector cfgv=
  -              org.apache.fop.configuration.Configuration.getListValue("embed-fonts", 0);
  -           if (cfgv!=null && cfgv.contains(desc.fontName()) && desc.isEmbeddable()) {
  -              PDFStream stream=desc.getFontFile(this.objectcount+1);
  -              if (stream!=null) {
  -                 this.objectcount++;
  -                 font.setFontFile(desc.getSubType(), stream);
  -                 this.objects.addElement(font);
  -                 this.objects.addElement(stream);
  -              }
  -           } else {
  -              this.objects.addElement(font);
  -           }
  +    public PDFFontDescriptor makeFontDescriptor(FontDescriptor desc,
  +                                                byte subtype) {
  +        PDFFontDescriptor font = null;
  +        
  +        if (subtype == PDFFont.TYPE0) {
  +                // CID Font
  +            font =
  +                new PDFCIDFontDescriptor(++this.objectcount,
  +                                         desc.fontName(),
  +                                         desc.getFontBBox(),
  +                                             //desc.getAscender(),
  +                                             //desc.getDescender(),
  +                                         desc.getCapHeight(),
  +                                         desc.getFlags(),
  +                                             //new PDFRectangle(desc.getFontBBox()),
  +                                         desc.getItalicAngle(),
  +                                         desc.getStemV(),
  +                                         null); //desc.getLang(),
  +                //null);//desc.getPanose());
  +        } else {
  +                // Create normal FontDescriptor
  +            font =
  +                new PDFFontDescriptor(++this.objectcount,
  +                                      desc.fontName(),
  +                                      desc.getAscender(),
  +                                      desc.getDescender(),
  +                                      desc.getCapHeight(),
  +                                      desc.getFlags(),
  +                                      new PDFRectangle(desc.getFontBBox()),
  +                                      desc.getStemV(),
  +                                      desc.getItalicAngle());
  +        }
  +            // Check if the font is embeddable
  +        if (desc.isEmbeddable()) {
  +            PDFStream stream=desc.getFontFile(this.objectcount+1);
  +            if (stream!=null) {
  +                this.objectcount++;
  +                font.setFontFile(desc.getSubType(), stream);
  +                this.objects.addElement(font);
  +                this.objects.addElement(stream);
  +            }
  +        } else {
  +            this.objects.addElement(font);
  +        }
       	return font;
  -	}
  +    }
   
   
   	/**
  
  
  
  1.9       +7 -5      xml-fop/src/org/apache/fop/pdf/PDFFont.java
  
  Index: PDFFont.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/pdf/PDFFont.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- PDFFont.java	2001/02/05 08:35:36	1.8
  +++ PDFFont.java	2001/02/27 12:28:16	1.9
  @@ -1,4 +1,4 @@
  -/*-- $Id: PDFFont.java,v 1.8 2001/02/05 08:35:36 kellyc Exp $ --
  +/*-- $Id: PDFFont.java,v 1.9 2001/02/27 12:28:16 fotis Exp $ --
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -136,10 +136,9 @@
       public static PDFFont createFont(int number, String fontname,
               byte subtype, String basefont, Object encoding) {
           switch (subtype) {
  -            /*
               case TYPE0 :
  -                return new PDFFontType0(number, fontname, subtype, basefont, encoding);
  -            */
  +                return new PDFFontType0(number, fontname, subtype,
  +                                        basefont, encoding);
               case TYPE1 :
               case MMTYPE1 :
                   return new PDFFontType1(number, fontname, subtype, basefont, encoding);
  @@ -175,7 +174,10 @@
           PDFFontNonBase14 font;
           switch (subtype) {
               case TYPE0 :
  -                return null;    // should not happend
  +                font = new PDFFontType0(number, fontname, subtype,
  +                                        basefont, encoding);
  +                font.setDescriptor(descriptor);
  +                return font;
               case TYPE1 :
               case MMTYPE1 :
                   font = new PDFFontType1(number, fontname, subtype, basefont, encoding);
  
  
  
  1.4       +5 -2      xml-fop/src/org/apache/fop/pdf/PDFFontDescriptor.java
  
  Index: PDFFontDescriptor.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/pdf/PDFFontDescriptor.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- PDFFontDescriptor.java	2001/02/05 08:35:37	1.3
  +++ PDFFontDescriptor.java	2001/02/27 12:28:17	1.4
  @@ -1,4 +1,4 @@
  -/*-- $Id: PDFFontDescriptor.java,v 1.3 2001/02/05 08:35:37 kellyc Exp $ --
  +/*-- $Id: PDFFontDescriptor.java,v 1.4 2001/02/27 12:28:17 fotis Exp $ --
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -180,10 +180,13 @@
   					p.append("\n/FontFile ");
   				break;
   				case PDFFont.TRUETYPE:
  +                                    p.append("\n/FontFile2 ");
  +                                    break;
  +				case PDFFont.TYPE0:
   					p.append("\n/FontFile2 ");
   				break;
   				default:
  -					p.append("\n/FontFile3 ");
  +					p.append("\n/FontFile2 ");
   			}
   			p.append(fontfile.referencePDF());
   		}
  
  
  
  1.2       +17 -9     xml-fop/src/org/apache/fop/pdf/PDFFontType0.java
  
  Index: PDFFontType0.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/pdf/PDFFontType0.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- PDFFontType0.java	2001/02/05 08:35:38	1.1
  +++ PDFFontType0.java	2001/02/27 12:28:17	1.2
  @@ -1,4 +1,4 @@
  -/*-- $Id: PDFFontType0.java,v 1.1 2001/02/05 08:35:38 kellyc Exp $ --
  +/*-- $Id: PDFFontType0.java,v 1.2 2001/02/27 12:28:17 fotis Exp $ --
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -49,17 +49,18 @@
   
    */
   package org.apache.fop.pdf;
  -
   /**
    * class representing a Type0 font.
    *
    * Type0 fonts are specified on page 208 and onwards of the PDF 1.3 spec.
    */
  -public class PDFFontType0 extends PDFFont {
  +public class PDFFontType0 extends PDFFontNonBase14 {
   
   	/** this should be an array of CIDFont but only the first one is used */
   	protected PDFCIDFont descendantFonts;
   
  +    protected PDFCMap cmap;
  +    
   	/**
   	 * create the /Font object
   	 *
  @@ -78,6 +79,7 @@
   
   		/* set fields using paramaters */
   		this.descendantFonts = null;
  +                cmap=null;
   	}
   
   	/**
  @@ -111,13 +113,19 @@
   		this.descendantFonts = descendantFonts;
   	}
   
  +    public void setCMAP(PDFCMap cmap) {
  +        this.cmap=cmap;
  +    }
   	/**
   	 * fill in the specifics for the font's subtype
   	 */
  -	protected void fillInPDF(StringBuffer p) {
  -		if (descendantFonts != null) {
  -			p.append("\n/DescendantFonts [ "+ this.descendantFonts.referencePDF() + " ] ");
  -		}
  -
  -	}
  +    protected void fillInPDF(StringBuffer p) {
  +        if (descendantFonts != null) {
  +            p.append("\n/DescendantFonts [ " +
  +                     this.descendantFonts.referencePDF() + " ] ");
  +        }
  +        if (cmap != null) {
  +            p.append("\n/ToUnicode "+cmap.referencePDF());
  +        }
  +    }
   }
  
  
  
  1.3       +2 -2      xml-fop/src/org/apache/fop/pdf/PDFWArray.java
  
  Index: PDFWArray.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/pdf/PDFWArray.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- PDFWArray.java	2001/02/09 02:45:58	1.2
  +++ PDFWArray.java	2001/02/27 12:28:17	1.3
  @@ -1,4 +1,4 @@
  -/*-- $Id: PDFWArray.java,v 1.2 2001/02/09 02:45:58 kellyc Exp $ --
  +/*-- $Id: PDFWArray.java,v 1.3 2001/02/27 12:28:17 fotis Exp $ --
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -132,7 +132,7 @@
   			metrics = m;
   		}
   		public void fillInPDF(StringBuffer p) {
  -			p.setLength(0);
  +			//p.setLength(0);
   			p.append(start); p.append(" [");
   			for (int i = 0; i < metrics.length; i++) {
   				p.append(this.metrics[i]);
  
  
  
  1.8       +30 -14    xml-fop/src/org/apache/fop/render/pdf/Font.java
  
  Index: Font.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/render/pdf/Font.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- Font.java	2001/02/05 08:35:42	1.7
  +++ Font.java	2001/02/27 12:28:19	1.8
  @@ -1,4 +1,4 @@
  -/*-- $Id: Font.java,v 1.7 2001/02/05 08:35:42 kellyc Exp $ -- 
  +/*-- $Id: Font.java,v 1.8 2001/02/27 12:28:19 fotis Exp $ -- 
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -58,22 +58,38 @@
    */
   public abstract class Font implements FontMetric {
   
  -    /**
  -     * get the encoding of the font
  -     */
  +        /**
  +         * get the encoding of the font
  +         */
       public abstract String encoding();
   
  -    /**
  -     * get the base font name
  -     */
  +        /**
  +         * get the base font name
  +         */
       public abstract String fontName();
  -
  -       /**
  -        * get the subtype of the font, default is TYPE1
  -        */
  -   public byte getSubType() {
  -      return org.apache.fop.pdf.PDFFont.TYPE1;
  -   }
  +    
  +        /**
  +         * get the subtype of the font, default is TYPE1
  +         */
  +    public byte getSubType() {
  +        return org.apache.fop.pdf.PDFFont.TYPE1;
  +    }
  +
  +        /**
  +         * Provide a default mapping
  +         */
  +    public char mapChar(char c) {
  +            // Use default CodePointMapping
  +        if (c > 127) {
  +            char d = org.apache.fop.render.pdf.CodePointMapping.map[c];
  +            if (d != 0) {
  +                c = d;
  +            } else {
  +                c = '#';
  +            }
  +        }
  +        return c;
  +    }
   }
   
   
  
  
  
  1.10      +51 -3     xml-fop/src/org/apache/fop/render/pdf/FontSetup.java
  
  Index: FontSetup.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/render/pdf/FontSetup.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- FontSetup.java	2000/11/02 13:02:45	1.9
  +++ FontSetup.java	2001/02/27 12:28:19	1.10
  @@ -1,4 +1,4 @@
  -/*-- $Id: FontSetup.java,v 1.9 2000/11/02 13:02:45 fotis Exp $ -- 
  +/*-- $Id: FontSetup.java,v 1.10 2001/02/27 12:28:19 fotis Exp $ -- 
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -57,10 +57,13 @@
   import org.apache.fop.layout.FontDescriptor;
   import org.apache.fop.pdf.PDFDocument;
   import org.apache.fop.pdf.PDFResources;
  +import org.apache.fop.configuration.Configuration;
  +import org.apache.fop.configuration.FontTriplet;
   
   // Java
   import java.util.Enumeration;
   import java.util.Hashtable;
  +import java.util.Vector;
   
   /**
    * sets up the PDF fonts.
  @@ -95,7 +98,7 @@
       fontInfo.addMetrics("F12", new CourierBoldOblique());
       fontInfo.addMetrics("F13", new Symbol());
       fontInfo.addMetrics("F14", new ZapfDingbats());
  -
  +    
       //Custom type 1 fonts step 1/2
   //    fontInfo.addMetrics("F15", new OMEP());
   //    fontInfo.addMetrics("F16", new GaramondLightCondensed());
  @@ -209,8 +212,53 @@
                      "bold"); 
       fontInfo.addFontProperties("F9", "Computer-Modern-Typewriter",
                      "normal", "normal");
  +
  +        /* Add configured fonts */
  +    addConfiguredFonts(fontInfo, 15);
       }
   
  +        /**
  +         * Add fonts from configuration file starting with
  +         * internalnames F<num>
  +         */
  +    public static void addConfiguredFonts(FontInfo fontInfo, int num) {
  +
  +        String internalName=null;
  +        FontReader reader = null;
  +
  +        Vector fontInfos = Configuration.getFonts();
  +        for (Enumeration e = fontInfos.elements(); e.hasMoreElements();) {
  +            org.apache.fop.configuration.FontInfo configFontInfo =
  +                (org.apache.fop.configuration.FontInfo)e.nextElement();
  +            
  +        try {
  +            String metricsFile = configFontInfo.getMetricsFile();
  +            if (metricsFile != null) {
  +                internalName = "F"+num;
  +                num++;
  +                reader = new FontReader(metricsFile);
  +                reader.useKerning(configFontInfo.getKerning());
  +                reader.setFontEmbedPath(configFontInfo.getEmbedFile());
  +                fontInfo.addMetrics(internalName, reader.getFont());
  +                
  +                Vector triplets = configFontInfo.getFontTriplets();
  +                for (Enumeration t = triplets.elements(); t.hasMoreElements();) {
  +                    FontTriplet triplet = (FontTriplet)t.nextElement();
  +                    
  +                    fontInfo.addFontProperties(internalName,
  +                                               triplet.getName(),
  +                                               triplet.getStyle(),
  +                                               triplet.getWeight());
  +                }
  +            }
  +        } catch (Exception ex) {
  +            MessageHandler.error("Failed to read font metrics file " +
  +                                 configFontInfo.getMetricsFile() +
  +                                 " : " + ex.getMessage());
  +        }
  +        }
  +    }
  +    
       /**
        * add the fonts in the font info to the PDF document
        *
  @@ -218,7 +266,7 @@
        * @param fontInfo font info object to get font information from
        */
       public static void addToResources(PDFDocument doc, FontInfo fontInfo) {
  -    Hashtable fonts = fontInfo.getFonts();
  +    Hashtable fonts = fontInfo.getUsedFonts();
       Enumeration e = fonts.keys();
       PDFResources resources = doc.getResources();
       while (e.hasMoreElements()) {
  
  
  
  1.55      +91 -39    xml-fop/src/org/apache/fop/render/pdf/PDFRenderer.java
  
  Index: PDFRenderer.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/render/pdf/PDFRenderer.java,v
  retrieving revision 1.54
  retrieving revision 1.55
  diff -u -r1.54 -r1.55
  --- PDFRenderer.java	2001/02/11 22:52:57	1.54
  +++ PDFRenderer.java	2001/02/27 12:28:19	1.55
  @@ -1,4 +1,4 @@
  -/*-- $Id: PDFRenderer.java,v 1.54 2001/02/11 22:52:57 keiron Exp $ --
  +/*-- $Id: PDFRenderer.java,v 1.55 2001/02/27 12:28:19 fotis Exp $ --
   
    ============================================================================
   				   The Apache Software License, Version 1.1
  @@ -147,6 +147,8 @@
       /** the current colour for use in svg */
       private PDFColor currentColour = new PDFColor(0, 0, 0);
   
  +    private FontInfo fontInfo;
  +    
       // previous values used for text-decoration drawing
       int prevUnderlineXEndPos;
       int prevUnderlineYEndPos;
  @@ -175,8 +177,6 @@
       /** The  width of the previous word. Used to calculate space between */
       int prevWordWidth = 0;
   
  -    boolean useKerning;
  -    
       private PDFOutline rootOutline;
   	
       /**
  @@ -184,10 +184,6 @@
        */
       public PDFRenderer() {
           this.pdfDoc = new PDFDocument();
  -
  -	String cfgKern = Configuration.getStringValue("use-kerning");
  -	useKerning = ("yes".equals(cfgKern) || "true".equals(cfgKern));
  -
       }
   
       /**
  @@ -224,6 +220,8 @@
           }
   	renderRootExtensions(areaTree);
   	
  +        FontSetup.addToResources(this.pdfDoc, fontInfo);
  +        
           MessageHandler.logln("writing out PDF");
           this.pdfDoc.output(stream);
       }
  @@ -653,17 +651,24 @@
   
   	Hashtable kerning = null;
   	boolean kerningAvailable = false;
  -	
  -	if (useKerning) {
  -	     kerning = area.getFontState().getKerning();
  -	     if (kerning != null && !kerning.isEmpty()) {
  -		 kerningAvailable = true;
  -	     }
  -	}
   	
  +        kerning = area.getFontState().getKerning();
  +        if (kerning != null && !kerning.isEmpty()) {
  +            kerningAvailable = true;
  +        }
  +
           String name = area.getFontState().getFontName();
           int size = area.getFontState().getFontSize();
   
  +            // This assumes that *all* CIDFonts use a /ToUnicode mapping
  +        boolean useMultiByte = false;
  +        Font f = (Font)area.getFontState().getFontInfo().getFonts().get(name);
  +        if (f instanceof CIDFont)
  +            useMultiByte=true;
  +            //String startText = useMultiByte ? "<FEFF" : "(";
  +        String startText = useMultiByte ? "<" : "(";
  +        String endText = useMultiByte ? ">" : ")";
  +        
           PDFColor theAreaColor = new PDFColor((double) area.getRed(),
                                                (double) area.getGreen(), 
   					     (double) area.getBlue());
  @@ -726,7 +731,7 @@
   		closeText();
   		
   		pdf.append("1 0 0 1 " +(rx / 1000f) + " " + 
  -			   (bl / 1000f) + " Tm [(");
  +			   (bl / 1000f) + " Tm [" + startText);
   		prevWordY = bl;
   		textOpen = true;
   	    }
  @@ -734,7 +739,7 @@
   		// express the space between words in thousandths of an em
   		int space = prevWordX - rx + prevWordWidth;
   		float emDiff = (float)space / (float)currentFontSize * 1000f;
  -		pdf.append(emDiff + " (");
  +		pdf.append(emDiff + " " + startText);
   	    }
   	    prevWordWidth = area.getContentWidth();
   	    prevWordX = rx;
  @@ -745,10 +750,10 @@
   	    // for every word.
   	    pdf.append("1 0 0 1 " +(rx / 1000f) + " " + (bl / 1000f) + " Tm ");
   	    if (kerningAvailable) {
  -		pdf.append(" [(");
  +		pdf.append(" [" + startText);
   	    }
   	    else {
  -		pdf.append(" (");
  +		pdf.append(" " + startText);
   	    }
   	}
   	
  @@ -768,27 +773,33 @@
               char ch = s.charAt(i);
   	    String prepend = "";
   	    
  -            if (ch > 127) {
  -		pdf.append("\\");
  -                pdf.append(Integer.toOctalString((int) ch));
  -            } else {
  -                switch (ch) {
  -		case '(':
  -		case ')':
  -		case '\\':
  -		    prepend = "\\";
  -		    break;
  +            if (!useMultiByte) {
  +                if(ch > 127) {
  +                    pdf.append("\\");
  +                    pdf.append(Integer.toOctalString((int) ch));
  +                } else {
  +                    switch (ch) {
  +                        case '(':
  +                        case ')':
  +                        case '\\':
  +                            prepend = "\\";
  +                            break;
  +                    }
  +                    pdf.append(getUnicodeString(prepend+ch, useMultiByte));
                   }
  -		pdf.append(prepend+ch);
  -	    }
  +	    } else {
  +                    pdf.append(getUnicodeString(prepend+ch, useMultiByte));
  +            }                
  +
   	    if (kerningAvailable && (i+1) < l) {
  -		pdf.append(addKerning((new Character(ch)).toString(),
  -				      (new Character(s.charAt(i+1))).toString(),
  -				      kerning));
  -	    }
  -	    
  +		pdf.append(addKerning((new Integer((int)ch)),
  +                                                       (new Integer((int)s.charAt(i+1))),
  +                                                       kerning,
  +                                                       startText, endText));
  +            }
  +            
           }
  -	pdf.append(") ");
  +        pdf.append(endText + " ");
   	if (!OPTIMIZE_TEXT) {
   	    if (kerningAvailable) {
   		pdf.append("] TJ\n");
  @@ -807,6 +818,45 @@
   	
       }
   
  +
  +        /**
  +         * Convert a string to a unicode hex representation
  +         */
  +    private String getUnicodeString(StringBuffer str, boolean useMultiByte) {
  +        return getUnicodeString(str.toString(), useMultiByte);
  +    }
  +    
  +        /**
  +         * Convert a string to a multibyte hex representation
  +         */
  +    private String getUnicodeString(String str, boolean useMultiByte) {
  +        if (!useMultiByte) {
  +            return str;
  +        } else {
  +            StringBuffer buf = new StringBuffer(str.length()*4);
  +            byte[] uniBytes = null;
  +            try {
  +                uniBytes = str.getBytes("UnicodeBigUnmarked");
  +            } catch (Exception e) {
  +                    // This should never fail
  +            }
  +            
  +            for (int i = 0; i < uniBytes.length; i++) {
  +                int b = (uniBytes[i] < 0) ? (int)(256+uniBytes[i])
  +                    : (int)uniBytes[i];
  +                
  +                String hexString=Integer.toHexString(b);
  +                if (hexString.length()==1)
  +                    buf=buf.append("0"+hexString);
  +                else
  +                    buf=buf.append(hexString);
  +            }
  +
  +            return buf.toString();
  +        }
  +    }
  +    
  +    
       /** Checks to see if we have some text rendering commands open
        * still and writes out the TJ command to the stream if we do
        */
  @@ -886,7 +936,9 @@
       }
   
   
  -   private StringBuffer addKerning(String ch1, String ch2, Hashtable kerning) {
  +   private StringBuffer addKerning(Integer ch1, Integer ch2,
  +                                   Hashtable kerning, String startText,
  +                                   String endText) {
         Hashtable h2=(Hashtable)kerning.get(ch1);
         int pwdt=0;
         StringBuffer buf=new StringBuffer("");
  @@ -895,7 +947,7 @@
            Integer wdt=(Integer)h2.get(ch2);
            if (wdt!=null) {
               pwdt=-wdt.intValue();
  -            buf=buf.append(") " + pwdt + " (");
  +            buf=buf.append(endText + " " + pwdt + " " + startText);
            }
         }
         return buf;
  @@ -1021,8 +1073,8 @@
          * @param fontInfo font info to set up
          */
       public void setupFontInfo(FontInfo fontInfo) {
  +        this.fontInfo = fontInfo;
           FontSetup.setup(fontInfo);
  -        FontSetup.addToResources(this.pdfDoc, fontInfo);
       }
   
       /**