]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
subset fonts embedding (submitted by Tore Engvig)
authorfotis <fotis@unknown>
Thu, 22 Mar 2001 18:17:02 +0000 (18:17 +0000)
committerfotis <fotis@unknown>
Thu, 22 Mar 2001 18:17:02 +0000 (18:17 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@194168 13f79535-47bb-0310-9956-ffa450edef68

15 files changed:
src/org/apache/fop/fonts/FontFileReader.java
src/org/apache/fop/fonts/PFMFile.java
src/org/apache/fop/fonts/TTFCmapEntry.java
src/org/apache/fop/fonts/TTFDirTabEntry.java
src/org/apache/fop/fonts/TTFFile.java
src/org/apache/fop/fonts/TTFMtxEntry.java
src/org/apache/fop/fonts/TTFSegEntry.java
src/org/apache/fop/fonts/apps/FontPostProcess.xsl
src/org/apache/fop/fonts/apps/PFMReader.java
src/org/apache/fop/fonts/apps/TTFReader.java
src/org/apache/fop/layout/LineArea.java
src/org/apache/fop/render/pdf/FontReader.java
src/org/apache/fop/render/pdf/PDFRenderer.java
src/org/apache/fop/render/pdf/fonts/MultiByteFont.java
src/org/apache/fop/render/pdf/fonts/SingleByteFont.java

index f6bc3cff9e03b609baf761bbc4782b479ee01a36..e6c7ce859bc15082609dc4e173aa243561b320cd 100644 (file)
@@ -1,52 +1,8 @@
 /* -- $Id$ --
-
- ============================================================================
-                   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 <jtauber@jtauber.com>. For more  information on the Apache
- Software Foundation, please see <http://www.apache.org/>.
-
+ *
+ * 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."
  */
 package org.apache.fop.fonts;
 import java.io.FileInputStream;
@@ -58,170 +14,220 @@ import java.io.IOException;
     provides file like functions for array access.
 */
 public class FontFileReader {
-   private int fsize; // file size
-   private int current; // current position in file
-   private byte[] file;
-       /**
-        * Initialisez class and reads stream. Init does not close stream
-        * @param stream InputStream to read from
-        * @param start initial size av array to read to
-        * @param inc if initial size isn't enough, create
-        new array with size + inc
+    private int fsize; // file size
+    private int current; // current position in file
+    private byte[] file;
+    /**
+     * Initialisez class and reads stream. Init does not close stream
+     * @param stream InputStream to read from
+     * @param start initial size av array to read to
+     * @param inc if initial size isn't enough, create
+     new array with size + inc
+    */
+    private void init(InputStream stream, int start,
+                      int inc) throws java.io.IOException {
+        fsize = 0;
+        current = 0;
+
+        file = new byte[start];
+
+        int l = stream.read(file, 0, start);
+        fsize += l;
+
+        if (l == start) {
+            // More to read - needs to extend
+            byte[] tmpbuf;
+
+            while (l > 0) {
+                tmpbuf = new byte[file.length + inc];
+                System.arraycopy(file, 0, tmpbuf, 0, file.length);
+                l = stream.read(tmpbuf, file.length, inc);
+                fsize += l;
+                file = tmpbuf;
+
+                if (l < inc)// whole file read. No need to loop again
+
+
+                    l = 0;
+            }
+        }
+    }
+
+    /**
+       * Constructor
+       * @param fileName filename to read
        */
-   private void init(InputStream stream, int start, int inc)
-      throws java.io.IOException {
-      fsize=0;
-      current=0;
-
-      file=new byte[start];
-
-      int l=stream.read(file, 0, start);
-      fsize+=l;
-      
-      if (l==start) {
-             // More to read - needs to extend
-         byte[] tmpbuf;
-         
-         while (l>0) {
-            tmpbuf=new byte[file.length + inc];
-            System.arraycopy(file, 0, tmpbuf, 0, file.length);
-            l=stream.read(tmpbuf, file.length, inc);
-            fsize+=l;
-            file=tmpbuf;
-            
-            if (l<inc) // whole file read. No need to loop again
-               l=0;
-         }
-      }
-   }
-
-       /**
-        * Constructor
-        * @param fileName filename to read
-        */
-   public FontFileReader(String fileName)
-      throws java.io.IOException {
-
-          // Get estimates for file size and increment
-      File f=new File(fileName);
-      FileInputStream ins = new FileInputStream(fileName);
-      init(ins, (int)(f.length()+1), (int)(f.length()/10));
-      ins.close();
-   }
-
-
-       /** Set current file position to offset */
-   public void seek_set(long offset) throws IOException {
-      if (offset > fsize || offset < 0)
-         throw new java.io.EOFException("Reached EOF, file size="+fsize+
-                                        " offset="+offset);
-      current=(int)offset;
-   }
-
-       /** Set current file position to offset */
-   public void seek_add(long add) throws IOException {
-      seek_set(current+add);
-   }
-
-   public void skip(long add) throws IOException {
-      seek_add(add);
-   }
-   
-       /** return current file position */
-   public int getCurrentPos() {
-      return current;
-   }
-
-   public int getFileSize() {
-      return fsize;
-   }
-   
-
-       /** Read 1 byte, throws EOFException on end of file */
-   public byte read() throws IOException {
-      if (current>fsize)
-         throw new java.io.EOFException("Reached EOF, file size="+fsize);
-      
-      byte ret=file[current++];
-      return ret;
-   }
-      
-
-         
-       /** Read 1 signed byte from InputStream */
-   public final byte readTTFByte() throws IOException {
-      return read();
-   }
-   
-       /** Read 1 unsigned byte from InputStream */
-   public final int readTTFUByte() throws IOException {
-      byte buf=read();
-
-      if (buf < 0)
-         return (int)(256+buf);
-      else
-         return (int)buf;
-   }
-
-       /** Read 2 bytes signed from InputStream */
-   public final short readTTFShort() throws IOException {
-      int ret=(readTTFUByte() << 8) +
-         readTTFUByte();
-      short sret=(short)ret;
-
-      return sret;
-   }
-
-       /** Read 2 bytes unsigned from InputStream */
-   public final int readTTFUShort() throws IOException {
-      int ret=(readTTFUByte() << 8) +
-         readTTFUByte();
-
-      return (int)ret;
-   }
-
-       /** Read 4 bytes from InputStream */
-   public final int readTTFLong() throws IOException {
-      long ret=readTTFUByte();// << 8;
-      ret=(ret << 8) + readTTFUByte();
-      ret=(ret << 8) + readTTFUByte();
-      ret=(ret << 8) + readTTFUByte();
-      
-      return (int)ret;
-   }
-
-       /** Read 4 bytes from InputStream */
-   public final long readTTFULong() throws IOException {
-      long ret=readTTFUByte();
-      ret=(ret << 8) + readTTFUByte();
-      ret=(ret << 8) + readTTFUByte();
-      ret=(ret << 8) + readTTFUByte();
-
-      return ret;
-   }
-
-       /** Read a 0 terminatet ISO-8859-1 string */
-   public final String readTTFString() throws IOException {
-      int i=current;
-      while (file[i++]!=0) {
-         if (i > fsize)
-            throw new java.io.EOFException("Reached EOF, file size="+fsize);
-      }
-
-      byte[] tmp=new byte[i-current];
-      System.arraycopy(file, current, tmp, 0, i-current);
-      return new String(tmp, "ISO-8859-1");
-   }
-
-   
-       /** Read an ISO-8859-1 string of len bytes*/
-   public final String readTTFString(int len) throws IOException {
-      if ((len+current) > fsize)
-         throw new java.io.EOFException("Reached EOF, file size="+fsize);
-
-      byte[] tmp=new byte[len];
-      System.arraycopy(file, current, tmp, 0, len);
-      current+=len;
-      return new String(tmp, "ISO-8859-1");
-   }
+    public FontFileReader(String fileName) throws java.io.IOException {
+
+        // Get estimates for file size and increment
+        File f = new File(fileName);
+        FileInputStream ins = new FileInputStream(fileName);
+        init(ins, (int)(f.length() + 1), (int)(f.length() / 10));
+        ins.close();
+    }
+
+
+    /** Set current file position to offset */
+    public void seek_set(long offset) throws IOException {
+        if (offset > fsize || offset < 0)
+            throw new java.io.EOFException("Reached EOF, file size="+
+                                           fsize + " offset="+offset);
+        current = (int) offset;
+    }
+
+    /** Set current file position to offset */
+    public void seek_add(long add) throws IOException {
+        seek_set(current + add);
+    }
+
+    public void skip(long add) throws IOException {
+        seek_add(add);
+    }
+
+    /** return current file position */
+    public int getCurrentPos() {
+        return current;
+    }
+
+    public int getFileSize() {
+        return fsize;
+    }
+
+
+    /** Read 1 byte, throws EOFException on end of file */
+    public byte read() throws IOException {
+        if (current > fsize)
+            throw new java.io.EOFException("Reached EOF, file size="+
+                                           fsize);
+
+        byte ret = file[current++];
+        return ret;
+    }
+
+
+
+    /** Read 1 signed byte from InputStream */
+    public final byte readTTFByte() throws IOException {
+        return read();
+    }
+
+    /** Read 1 unsigned byte from InputStream */
+    public final int readTTFUByte() throws IOException {
+        byte buf = read();
+
+        if (buf < 0)
+            return (int)(256 + buf);
+        else
+            return (int) buf;
+    }
+
+    /** Read 2 bytes signed from InputStream */
+    public final short readTTFShort() throws IOException {
+        int ret = (readTTFUByte() << 8) + readTTFUByte();
+        short sret = (short) ret;
+
+        return sret;
+    }
+
+    /** Read 2 bytes unsigned from InputStream */
+    public final int readTTFUShort() throws IOException {
+        int ret = (readTTFUByte() << 8) + readTTFUByte();
+
+        return (int) ret;
+    }
+
+    /**
+       * Write a USHort at a given position
+       */
+    public final void writeTTFUShort(int pos, int val) throws IOException {
+        if ((pos + 2) > fsize)
+            throw new java.io.EOFException("Reached EOF");
+        byte b1 = (byte)((val >> 8) & 0xff);
+        byte b2 = (byte)(val & 0xff);
+        file[pos] = b1;
+        file[pos + 1] = b2;
+    }
+
+    /** Read 2 bytes signed from InputStream at position pos
+       without changing current position */
+    public final short readTTFShort(long pos) throws IOException {
+        long cp = getCurrentPos();
+        seek_set(pos);
+        short ret = readTTFShort();
+        seek_set(cp);
+        return ret;
+    }
+
+    /** Read 2 bytes unsigned from InputStream at position pos
+       without changing current position */
+    public final int readTTFUShort(long pos) throws IOException {
+        long cp = getCurrentPos();
+        seek_set(pos);
+        int ret = readTTFUShort();
+        seek_set(cp);
+        return ret;
+    }
+
+    /** Read 4 bytes from InputStream */
+    public final int readTTFLong() throws IOException {
+        long ret = readTTFUByte();// << 8;
+        ret = (ret << 8) + readTTFUByte();
+        ret = (ret << 8) + readTTFUByte();
+        ret = (ret << 8) + readTTFUByte();
+
+        return (int) ret;
+    }
+
+    /** Read 4 bytes from InputStream */
+    public final long readTTFULong() throws IOException {
+        long ret = readTTFUByte();
+        ret = (ret << 8) + readTTFUByte();
+        ret = (ret << 8) + readTTFUByte();
+        ret = (ret << 8) + readTTFUByte();
+
+        return ret;
+    }
+
+    /** Read a 0 terminatet ISO-8859-1 string */
+    public final String readTTFString() throws IOException {
+        int i = current;
+        while (file[i++] != 0) {
+            if (i > fsize)
+                throw new java.io.EOFException("Reached EOF, file size="+
+                                               fsize);
+        }
+
+        byte[] tmp = new byte[i - current];
+        System.arraycopy(file, current, tmp, 0, i - current);
+        return new String(tmp, "ISO-8859-1");
+    }
+
+
+    /** Read an ISO-8859-1 string of len bytes*/
+    public final String readTTFString(int len) throws IOException {
+        if ((len + current) > fsize)
+            throw new java.io.EOFException("Reached EOF, file size="+
+                                           fsize);
+
+        byte[] tmp = new byte[len];
+        System.arraycopy(file, current, tmp, 0, len);
+        current += len;
+        return new String(tmp, "ISO-8859-1");
+    }
+
+    /**
+       * Return a copy of the internal array
+       * @throws IOException if out of bounds
+       */
+    public byte[] getBytes(int offset,
+                           int length) throws java.io.IOException {
+        if ((offset + length) > fsize)
+            throw new java.io.IOException("Reached EOF");
+
+        byte[] ret = new byte[length];
+        System.arraycopy(file, offset, ret, 0, length);
+        return ret;
+    }
+
+
 }
index f1cae42d3bb96947b20443db2ad215ba5831a5cd..83c26543790a4b635b56cb4bfec693ae5c9ceacf 100644 (file)
@@ -1,52 +1,8 @@
 /*-- $Id$ --
-
- ============================================================================
-                   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 <jtauber@jtauber.com>. For more  information on the Apache
- Software Foundation, please see <http://www.apache.org/>.
-
+ *
+ * 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."
  */
 package org.apache.fop.fonts;
 
@@ -61,40 +17,40 @@ import java.util.Hashtable;
 public class PFMFile {
 
     //Header stuff
-    private String  windowsName;
-    private String  postscriptName;
-    private short   dfItalic;
-    private int     dfWeight;
-    private short   dfCharSet;
-    private short   dfPitchAndFamily;
-    private int     dfAvgWidth;
-    private int     dfMaxWidth;
-    private int     dfMinWidth;
-    private short   dfFirstChar;
-    private short   dfLastChar;
+    private String windowsName;
+    private String postscriptName;
+    private short dfItalic;
+    private int dfWeight;
+    private short dfCharSet;
+    private short dfPitchAndFamily;
+    private int dfAvgWidth;
+    private int dfMaxWidth;
+    private int dfMinWidth;
+    private short dfFirstChar;
+    private short dfLastChar;
 
     //Extension stuff
     //---
 
     //Extend Text Metrics
-    private int     etmCapHeight;
-    private int     etmXHeight;
-    private int     etmLowerCaseAscent;
-    private int     etmLowerCaseDescent;
+    private int etmCapHeight;
+    private int etmXHeight;
+    private int etmLowerCaseAscent;
+    private int etmLowerCaseDescent;
 
     //Extent table
-    private int[]   extentTable;
+    private int[] extentTable;
 
-   private Hashtable kerningTab;
+    private Hashtable kerningTab;
     public PFMFile() {
-       kerningTab=new Hashtable();
+        kerningTab = new Hashtable();
     }
 
     /**
-     * Parses a PFM file
-     * 
-     * @param     inStream The stream from which to read the PFM file.
-     */
+      * Parses a PFM file
+      *
+      * @param     inStream The stream from which to read the PFM file.
+      */
     public void load(InputStream inStream) throws IOException {
         InputStream bufin = new BufferedInputStream(inStream, 1024);
         bufin.mark(1024);
@@ -103,8 +59,8 @@ public class PFMFile {
         long filesize = in.readInt();
         bufin.reset();
 
-        byte[] buf = new byte[(int)filesize];
-        bufin.read(buf, 0, (int)filesize);
+        byte[] buf = new byte[(int) filesize];
+        bufin.read(buf, 0, (int) filesize);
 
         bufin = new ByteArrayInputStream(buf);
         in = new PFMInputStream(bufin);
@@ -113,10 +69,10 @@ public class PFMFile {
     }
 
     /**
-     * Parses the header of the PFM file.
-     *
-     * @param     inStream The stream from which to read the PFM file.
-     */
+      * Parses the header of the PFM file.
+      *
+      * @param     inStream The stream from which to read the PFM file.
+      */
     private void loadHeader(PFMInputStream inStream) throws IOException {
         inStream.skip(80);
         dfItalic = inStream.readByte();
@@ -128,9 +84,9 @@ public class PFMFile {
         dfAvgWidth = inStream.readShort();
         dfMaxWidth = inStream.readShort();
         dfFirstChar = inStream.readByte();
-        dfLastChar  = inStream.readByte();
+        dfLastChar = inStream.readByte();
         inStream.skip(8);
-        long faceOffset   = inStream.readInt();
+        long faceOffset = inStream.readInt();
 
         inStream.reset();
         inStream.skip(faceOffset);
@@ -141,10 +97,10 @@ public class PFMFile {
     }
 
     /**
-     * Parses the extension part of the PFM file.
-     * 
-     * @param     inStream The stream from which to read the PFM file.
-     */
+      * Parses the extension part of the PFM file.
+      *
+      * @param     inStream The stream from which to read the PFM file.
+      */
     private void loadExtension(PFMInputStream inStream) throws IOException {
         int size = inStream.readShort();
         long extMetricsOffset = inStream.readInt();
@@ -155,11 +111,11 @@ public class PFMFile {
         long driverInfoOffset = inStream.readInt();
 
         if (kernPairOffset > 0) {
-           inStream.reset();
-           inStream.skip(kernPairOffset);
-           loadKernPairs(inStream);
+            inStream.reset();
+            inStream.skip(kernPairOffset);
+            loadKernPairs(inStream);
         }
-        
+
         inStream.reset();
         inStream.skip(driverInfoOffset);
         postscriptName = inStream.readString();
@@ -178,190 +134,195 @@ public class PFMFile {
     }
 
     /**
-     * Parses the kernPairs part of the pfm file
-     * 
-     * @param     inStream The stream from which to read the PFM file.
-     */
+      * Parses the kernPairs part of the pfm file
+      *
+      * @param     inStream The stream from which to read the PFM file.
+      */
     private void loadKernPairs(PFMInputStream inStream) throws IOException {
         int i = inStream.readShort();
 
-        
+
         System.out.println(i + " kerning pairs");
         while (i > 0) {
-           int g1 = (int)inStream.readByte();
-           i--;
-               //System.out.print ("Char no: ("+g1+", ");
-           
-           int g2 = (int)inStream.readByte();
-               //System.out.print (g2+") kern");
-           
-           int adj = inStream.readShort();
-           if (adj > 0x8000)
-              adj=-(0x10000-adj);
-               //System.out.println (": " + adj);
-
-           String glyph1=Glyphs.tex8r[g1];
-           String glyph2=Glyphs.tex8r[g2];
-
-           Hashtable adjTab=(Hashtable)kerningTab.get(new Integer(g1));
-           if (adjTab==null)
-              adjTab=new Hashtable();
-           adjTab.put(new Integer(g2), new Integer(adj));
-           kerningTab.put(new Integer(g1), adjTab);
+            int g1 = (int) inStream.readByte();
+            i--;
+            //System.out.print ("Char no: ("+g1+", ");
+
+            int g2 = (int) inStream.readByte();
+            //System.out.print (g2+") kern");
+
+            int adj = inStream.readShort();
+            if (adj > 0x8000)
+                adj = -(0x10000 - adj);
+            //System.out.println (": " + adj);
+
+            String glyph1 = Glyphs.tex8r[g1];
+            String glyph2 = Glyphs.tex8r[g2];
+
+            Hashtable adjTab = (Hashtable) kerningTab.get(new Integer(g1));
+            if (adjTab == null)
+                adjTab = new Hashtable();
+            adjTab.put(new Integer(g2), new Integer(adj));
+            kerningTab.put(new Integer(g1), adjTab);
         }
     }
 
     /**
-     * Parses the extended metrics part of the PFM file.
-     * 
-     * @param     inStream The stream from which to read the PFM file.
-     */
-    private void loadExtMetrics(PFMInputStream inStream) throws IOException {
+      * Parses the extended metrics part of the PFM file.
+      *
+      * @param     inStream The stream from which to read the PFM file.
+      */
+    private void loadExtMetrics(PFMInputStream inStream)
+    throws IOException {
         int size = inStream.readShort();
         inStream.skip(12);
-        etmCapHeight        = inStream.readShort();
-        etmXHeight          = inStream.readShort();
-        etmLowerCaseAscent  = inStream.readShort();
+        etmCapHeight = inStream.readShort();
+        etmXHeight = inStream.readShort();
+        etmLowerCaseAscent = inStream.readShort();
         etmLowerCaseDescent = inStream.readShort();
     }
 
     /**
-     * Parses the extent table of the PFM file.
-     * 
-     * @param     inStream The stream from which to read the PFM file.
-     */
-    private void loadExtentTable(PFMInputStream inStream) throws IOException {
-        extentTable = new int[dfLastChar-dfFirstChar];
+      * Parses the extent table of the PFM file.
+      *
+      * @param     inStream The stream from which to read the PFM file.
+      */
+    private void loadExtentTable(PFMInputStream inStream)
+    throws IOException {
+        extentTable = new int[dfLastChar - dfFirstChar + 1];
         dfMinWidth = dfMaxWidth;
-        for (short i = dfFirstChar; i < dfLastChar; i++) {
-            extentTable[i-dfFirstChar] = inStream.readShort();
-            if (extentTable[i-dfFirstChar] < dfMinWidth) {
-                dfMinWidth = extentTable[i-dfFirstChar];
+        for (short i = dfFirstChar; i <= dfLastChar; i++) {
+            extentTable[i - dfFirstChar] = inStream.readShort();
+            if (extentTable[i - dfFirstChar] < dfMinWidth) {
+                dfMinWidth = extentTable[i - dfFirstChar];
             }
         }
     }
 
     /**
-     * Returns the Windows name of the font.
-     * 
-     * @return The Windows name.
-     */
+      * Returns the Windows name of the font.
+      *
+      * @return The Windows name.
+      */
     public String getWindowsName() {
         return windowsName;
     }
 
-       /**
-        * Return the kerning table. The kerning table is a hastable with
-        * strings with glyphnames as keys, containing hashtables as value.
-        * The value hashtable contain a glyph name string key and an Integer value
-        */
-   public Hashtable getKerning() {
-      return kerningTab;
-   }
-        
     /**
-     * Returns the Postscript name of the font.
-     * 
-     * @return The Postscript name.
-     */
+      * Return the kerning table. The kerning table is a hastable with
+      * strings with glyphnames as keys, containing hashtables as value.
+      * The value hashtable contain a glyph name string key and an Integer value
+      */
+    public Hashtable getKerning() {
+        return kerningTab;
+    }
+
+    /**
+      * Returns the Postscript name of the font.
+      *
+      * @return The Postscript name.
+      */
     public String getPostscriptName() {
         return postscriptName;
     }
 
     /**
-     * Returns the charset used for the font.
-     * 
-     * @return The charset (0=WinAnsi).
-     */
+      * Returns the charset used for the font.
+      *
+      * @return The charset (0=WinAnsi).
+      */
     public short getCharSet() {
         return dfCharSet;
     }
 
     /**
-     * Returns the charset of the font as a string.
-     * 
-     * @return The name of the charset.
-     */
+      * Returns the charset of the font as a string.
+      *
+      * @return The name of the charset.
+      */
     public String getCharSetName() {
         switch (dfCharSet) {
-            case 0:     return "WinAnsi";
-            case 128:   return "Shift-JIS (Japanese)";
-            default:    return "Unknown";
+            case 0:
+                return "WinAnsi";
+            case 128:
+                return "Shift-JIS (Japanese)";
+            default:
+                return "Unknown";
         }
     }
 
     /**
-     * Returns the number of the character that defines
-     * the first entry in the widths list.
-     * 
-     * @return The number of the first character.
-     */
+      * Returns the number of the character that defines
+      * the first entry in the widths list.
+      *
+      * @return The number of the first character.
+      */
     public short getFirstChar() {
         return dfFirstChar;
     }
 
     /**
-     * Returns the number of the character that defines
-     * the last entry in the widths list.
-     * 
-     * @return The number of the last character.
-     */
+      * Returns the number of the character that defines
+      * the last entry in the widths list.
+      *
+      * @return The number of the last character.
+      */
     public short getLastChar() {
         return dfLastChar;
     }
 
     /**
-     * Returns the CapHeight parameter for the font (height of uppercase H).
-     * 
-     * @return The CapHeight parameter.
-     */
+      * Returns the CapHeight parameter for the font (height of uppercase H).
+      *
+      * @return The CapHeight parameter.
+      */
     public int getCapHeight() {
         return etmCapHeight;
     }
 
     /**
-     * Returns the XHeight parameter for the font (height of lowercase x).
-     * 
-     * @return The CapHeight parameter.
-     */
+      * Returns the XHeight parameter for the font (height of lowercase x).
+      *
+      * @return The CapHeight parameter.
+      */
     public int getXHeight() {
         return etmXHeight;
     }
 
     /**
-     * Returns the LowerCaseAscent parameter for the font (height of lowercase d).
-     * 
-     * @return The LowerCaseAscent parameter.
-     */
+      * Returns the LowerCaseAscent parameter for the font (height of lowercase d).
+      *
+      * @return The LowerCaseAscent parameter.
+      */
     public int getLowerCaseAscent() {
         return etmLowerCaseAscent;
     }
 
     /**
-     * Returns the LowerCaseDescent parameter for the font (height of lowercase p).
-     * 
-     * @return The LowerCaseDescent parameter.
-     */
+      * Returns the LowerCaseDescent parameter for the font (height of lowercase p).
+      *
+      * @return The LowerCaseDescent parameter.
+      */
     public int getLowerCaseDescent() {
         return etmLowerCaseDescent;
     }
 
     /**
-     * Tells whether the font has proportional character spacing.
-     * 
-     * @return ex. true for Times, false for Courier.
-     */
+      * Tells whether the font has proportional character spacing.
+      *
+      * @return ex. true for Times, false for Courier.
+      */
     public boolean getIsProportional() {
         return ((dfPitchAndFamily & 1) == 1);
     }
 
     /**
-     * Returns the bounding box for the font.
-     * Note: this value is just an approximation,
-     * it does not really exist in the PFM file.
-     * 
-     * @return The calculated Font BBox.
-     */
+      * Returns the bounding box for the font.
+      * Note: this value is just an approximation,
+      * it does not really exist in the PFM file.
+      *
+      * @return The calculated Font BBox.
+      */
     public int[] getFontBBox() {
         int[] bbox = new int[4];
 
@@ -378,44 +339,54 @@ public class PFMFile {
     }
 
     /**
-     * Returns the characteristics flags for the font as
-     * needed for a PDF font descriptor (See PDF specs).
-     * 
-     * @return The characteristics flags.
-     */
+      * Returns the characteristics flags for the font as
+      * needed for a PDF font descriptor (See PDF specs).
+      *
+      * @return The characteristics flags.
+      */
     public int getFlags() {
         int flags = 0;
-        if (!getIsProportional()) { flags |= 1; }
-        if ((dfPitchAndFamily & 16) == 16) { flags |= 2; }
-        if ((dfPitchAndFamily & 64) == 64) { flags |= 4; }
-        if (dfCharSet == 0) { flags |= 6; }
-        if (dfItalic != 0) { flags |= 7; }
+        if (!getIsProportional()) {
+            flags |= 1;
+        }
+        if ((dfPitchAndFamily & 16) == 16) {
+            flags |= 2;
+        }
+        if ((dfPitchAndFamily & 64) == 64) {
+            flags |= 4;
+        }
+        if (dfCharSet == 0) {
+            flags |= 6;
+        }
+        if (dfItalic != 0) {
+            flags |= 7;
+        }
         return flags;
     }
 
     /**
-     * Returns the width of the dominant vertical stems of the font.
-     * Note: this value is just an approximation,
-     * it does not really exist in the PFM file.
-     * 
-     * @return The vertical stem width.
-     */
+      * Returns the width of the dominant vertical stems of the font.
+      * Note: this value is just an approximation,
+      * it does not really exist in the PFM file.
+      *
+      * @return The vertical stem width.
+      */
     public int getStemV() {
         //Just guessing....
         if (dfItalic != 0) {
-            return (int)Math.round(dfMinWidth * 0.25);
+            return (int) Math.round(dfMinWidth * 0.25);
         } else {
-            return (int)Math.round(dfMinWidth * 0.6);
+            return (int) Math.round(dfMinWidth * 0.6);
         }
     }
 
     /**
-     * Returns the italic angle of the font.
-     * Note: this value is just an approximation,
-     * it does not really exist in the PFM file.
-     * 
-     * @return The italic angle.
-     */
+      * Returns the italic angle of the font.
+      * Note: this value is just an approximation,
+      * it does not really exist in the PFM file.
+      *
+      * @return The italic angle.
+      */
     public int getItalicAngle() {
         if (dfItalic != 0) {
             return -16; //Just guessing....
@@ -425,12 +396,12 @@ public class PFMFile {
     }
 
     /**
-     * Returns the width of a character
-     * 
-     * @param  which The number of the character for which the width is requested.
-     * @return The width of a character.
-     */
+      * Returns the width of a character
+      *
+      * @param  which The number of the character for which the width is requested.
+      * @return The width of a character.
+      */
     public int getCharWidth(short which) {
-        return extentTable[which-dfFirstChar];
+        return extentTable[which - dfFirstChar];
     }
 }
index 3e8dd746a5557fdda498afb5e6ca92725296af3e..b4a9c3bbc40103ebe0ad8a984f549296eacd79f6 100644 (file)
@@ -1,52 +1,8 @@
 /* -- $Id$ --
-
- ============================================================================
-                   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 <jtauber@jtauber.com>. For more  information on the Apache
- Software Foundation, please see <http://www.apache.org/>.
-
+ *
+ * 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."
  */
 package org.apache.fop.fonts;
 
@@ -58,16 +14,14 @@ 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) {
+    TTFCmapEntry (int unicodeStart, int unicodeEnd, int glyphStartIndex) {
         this.unicodeStart = unicodeStart;
         this.unicodeEnd = unicodeEnd;
         this.glyphStartIndex = glyphStartIndex;
@@ -75,13 +29,13 @@ public class TTFCmapEntry {
 
     public boolean equals (Object o) {
         if (o instanceof TTFCmapEntry) {
-            TTFCmapEntry ce = (TTFCmapEntry)o;
+            TTFCmapEntry ce = (TTFCmapEntry) o;
             if (ce.unicodeStart == this.unicodeStart &&
-                ce.unicodeEnd == this.unicodeEnd &&
-                ce.glyphStartIndex == this.glyphStartIndex)
+                    ce.unicodeEnd == this.unicodeEnd &&
+                    ce.glyphStartIndex == this.glyphStartIndex)
                 return true;
         }
         return false;
     }
-                    
+
 }
index 30f0c4cfef50da928d6c81f213b61dd33f85a6ba..9a2b0ea129f17c8d2d2bbbc69fd90944a0bcbc72 100644 (file)
@@ -1,52 +1,8 @@
 /* -- $Id$ --
-
- ============================================================================
-                   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 <jtauber@jtauber.com>. For more  information on the Apache
- Software Foundation, please see <http://www.apache.org/>.
-
+ *
+ * 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."
  */
 package org.apache.fop.fonts;
 import java.io.*;
@@ -56,32 +12,32 @@ class TTFDirTabEntry {
     int checksum;
     long offset;
     long length;
-    
+
     TTFDirTabEntry() {
         tag = new byte[4];
     }
-    
-        /** Read Dir Tab, return tag name */ 
+
+    /** 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();
-        
+        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));
-            */
+
+        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");
     }
 }
index 02c49bfe14eddc8a90a8420e8c2b2ffd7eeb2b19..682233dbcdb75714d7227b88114153d15144f198 100644 (file)
@@ -1,52 +1,8 @@
 /* -- $Id$ --
-
- ============================================================================
-                   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 <jtauber@jtauber.com>. For more  information on the Apache
- Software Foundation, please see <http://www.apache.org/>.
-
+ *
+ * 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."
  */
 package org.apache.fop.fonts;
 import java.io.*;
@@ -64,33 +20,34 @@ public class TTFFile {
     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
+
+    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 upem; // unitsPerEm from "head" table
     int nhmtx; // Number of horizontal metrics
     int post_format;
     int loca_format;
+    long lastLoca = 0; // offset to last loca
     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="";
-    
+    int[] mtx_encoded = null;
+
+    String fontName = "";
+    String fullName = "";
+    String notice = "";
+    String familyName = "";
+    String subFamilyName = "";
+
     long italicAngle = 0;
     long isFixedPitch = 0;
     int fontBBox1 = 0;
@@ -108,158 +65,157 @@ public class TTFFile {
 
     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) {
+
+    /** 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);
+
+        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
-        */
+
+    /** 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);
+            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;
+            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 {
+
+    /** 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;
-        
+
+        /** 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;
+        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
+
+        // 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) {
+        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();
+            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);
+            */
 
-                /*
-                  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();
+            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_startCounts[i] = in.readTTFUShort();
             }
-            
-            for (int i=0; i < (cmap_segCountX2/2); i++) {
-                cmap_deltas[i]=in.readTTFShort();
+
+            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 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
-            
+
+            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;
-                                    
+                /*
+                    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;
+                            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;
+                            int glyphIdx = (in.readTTFUShort() +
+                                            cmap_deltas[i]) & 0xffff;
 
                             unicodeMapping.addElement(
-                                new UnicodeMapping(glyphIdx, j));
-                            mtx_tab[glyphIdx].unicodeIndex.addElement(new Integer(j));
+                              new UnicodeMapping(glyphIdx, j));
+                            mtx_tab[glyphIdx].unicodeIndex.addElement(
+                              new Integer(j));
 
 
-                                // Also add winAnsiWidth
+                            // Also add winAnsiWidth
                             if (false) {
                                 int d = j;
                                 if (j > 127)
@@ -268,71 +224,89 @@ public class TTFFile {
                                 if (d < ansiWidth.length)
                                     ansiWidth[d] = mtx_tab[glyphIdx].wx;
                             } else {
-                                Vector v=
-                                    (Vector)ansiIndex.get(new Integer(j));
+                                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());
-                                            */             
+                                    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));
-                                
+                            /*
+                                System.out.println("Idx: "+
+                                glyphIdx +
+                                " Delta: " + cmap_deltas[i]+
+                                " Unicode: " + j +
+                                " name: " +
+                                mtx_tab[glyphIdx].name);
+                              */
+
+                        }
+                        else {
+
+                            int glyphIdx = (j + cmap_deltas[i]) & 0xffff;
+
+                            if (glyphIdx < mtx_tab.length)
+                                mtx_tab[glyphIdx] .unicodeIndex.addElement(
+                                  new Integer(j));
+                            else
+                                System.out.println("Glyph " +
+                                                   glyphIdx + " out of range: " +
+                                                   mtx_tab.length);
+
                             unicodeMapping.addElement(
-                                new UnicodeMapping(glyphIdx,
-                                                   j));
+                              new UnicodeMapping(glyphIdx, j));
+                            if (glyphIdx < mtx_tab.length)
+                                mtx_tab[glyphIdx] .unicodeIndex.addElement(
+                                  new Integer(j));
+                            else
+                                System.out.println("Glyph " +
+                                                   glyphIdx + " out of range: " +
+                                                   mtx_tab.length);
+
 
-                                // Also add winAnsiWidth
+
+                            // 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));
+                                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;
+                                    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);
-                                */
+
+                            /*
+                                System.out.println("IIdx: "+
+                                mtxPtr +
+                                " Delta: " + cmap_deltas[i]+
+                                " Unicode: " + j +
+                                " name: " +
+                                mtx_tab[(j+cmap_deltas[i]) & 0xffff].name);
+                              */
                         }
                         mtxPtr++;
                     }
@@ -341,16 +315,16 @@ public class TTFFile {
         }
         return true;
     }
-    
-    
-    
-        /**
-         * Print first char/last char
-         */
+
+
+
+    /**
+       * 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++) {
+        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)
@@ -361,26 +335,26 @@ public class TTFFile {
     }
 
     public void readFont(FontFileReader in) throws IOException {
-        readFont(in, (String)null);
+        readFont(in, (String) null);
     }
 
-        /** initialize the ansiWidths array (for winAnsiEncoding)
-         * and fill with the missingwidth
-         */
+    /** initialize the ansiWidths array (for winAnsiEncoding)
+       * and fill with the missingwidth
+       */
     private void initAnsiWidths() {
-        ansiWidth=new int[256];
+        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++) {
+        // 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);
+            Integer uni = new Integer((int) Glyphs.winAnsiEncoding[i]);
+
+            Vector v = (Vector) ansiIndex.get(uni);
             if (v == null) {
                 v = new Vector();
                 ansiIndex.put(uni, v);
@@ -389,23 +363,26 @@ public class TTFFile {
         }
     }
 
-    
-        /**
-         * 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))
+
+    /**
+       * Read the font data
+       * If the fontfile is a TrueType Collection (.ttc 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, true))
             throw new IOException("Failed to read font");
-        
+
         readDirTabs(in);
         readFontHeader(in);
+        getNumGlyphs(in);
+        System.out.println("Number of glyphs in font: " + nglyphs);
         readHorizontalHeader(in);
         readHorizontalMetrics(in);
         initAnsiWidths();
@@ -417,8 +394,8 @@ public class TTFFile {
         readPCLT(in);
         readCMAP(in); // Read cmap table and fill in ansiwidths
         createCMaps(); // Create cmaps for bfentries
-            //print_max_min();
-        
+        //print_max_min();
+
         readKerning(in);
     }
 
@@ -427,26 +404,26 @@ public class TTFFile {
         TTFCmapEntry tce = new TTFCmapEntry();
 
         Enumeration e = unicodeMapping.elements();
-        UnicodeMapping um = (UnicodeMapping)e.nextElement();
+        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)) {
+            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);
     }
@@ -457,51 +434,52 @@ public class TTFFile {
         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("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.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)+"]");
+        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 ttfFile = new TTFFile();
+            FontFileReader reader = new FontFileReader(args[0]);
 
-            String name=null;
+            String name = null;
             if (args.length >= 2)
-                name=args[1];
-            
+                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);
+        return new String(familyName + ","+subFamilyName);
     }
-    
+
     public String getPostscriptName() {
         if ("Regular".equals(subFamilyName) ||
-            "Roman".equals(subFamilyName))
+                "Roman".equals(subFamilyName))
             return familyName;
         else
-            return familyName+","+subFamilyName;
+            return familyName + ","+subFamilyName;
     }
     public String getFamilyName() {
         return familyName;
@@ -510,14 +488,14 @@ public class TTFFile {
         return encoding;
     }
     public int getCapHeight() {
-        return (int)get_ttf_funit(capHeight);
+        return (int) get_ttf_funit(capHeight);
     }
     public int getXHeight() {
-        return (int)get_ttf_funit(xHeight);
+        return (int) get_ttf_funit(xHeight);
     }
-    
+
     public int getFlags() {
-        int flags=32; // Use Adobe Standard charset
+        int flags = 32; // Use Adobe Standard charset
         if (italicAngle != 0)
             flags = flags | 64;
         if (isFixedPitch != 0)
@@ -527,39 +505,43 @@ public class TTFFile {
         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)));
-        
+        String ia = Short.toString((short)(italicAngle / 0x10000));
+
+        // This is the correct italic angle, however only int italic
+        // angles are supported at the moment so this is commented out.
+        /*
+          if ((italicAngle % 0x10000) > 0 )
+          ia=ia+(comma+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);
-        
+        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);
+        return (int) get_ttf_funit(ascender);
     }
-    
+
     public int getLowerCaseDescent() {
-        return (int)get_ttf_funit(descender);
+        return (int) get_ttf_funit(descender);
     }
-    
-        // This is only for WinAnsiEncoding, so the last char is
-        // the last char < 256
+
+    // This is only for WinAnsiEncoding, so the last char is
+    // the last char < 256
     public short getLastChar() {
         return lastChar;
     }
@@ -571,192 +553,195 @@ public class TTFFile {
     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);
+            wx[i] = (int) get_ttf_funit(mtx_tab[i].wx);
 
         return wx;
     }
-    
+
     public int getCharWidth(int idx) {
-        return (int)get_ttf_funit(ansiWidth[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 {
+
+
+    /**
+       * 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.
+       */
+    protected void readDirTabs(FontFileReader in) throws IOException {
         in.skip(4); // TTF_FIXED_SIZE
-        int ntabs=in.readTTFUShort();
+        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]);
+
+        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();
+    /**
+       * Read the "head" table, this reads the bounding box and
+       * sets the upem (unitsPerEM) variable
+       */
+    protected 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();
+
+        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 {
+    /**
+       * Read the number of glyphs from the "maxp" table
+       */
+    protected void getNumGlyphs(FontFileReader in) throws IOException {
         seek_tab(in, "maxp", 4);
-        nglyphs=in.readTTFUShort();
-        System.out.println("Number of glyphs in font: " + nglyphs); 
+        nglyphs = in.readTTFUShort();
     }
 
 
-        /** 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 {
+    /** 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
+       */
+    protected 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);
+        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 {
+    /**
+       * 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
+       */
+    protected 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
+
+        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();
+            mtx_tab[i].lsb = in.readTTFUShort();
+            /*
+                System.out.println("   width["+i+"] = "+
+                get_ttf_funit(mtx_tab[i].wx)+";");
+              */
         }
 
         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;
+            // 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;
+                mtx_tab[i].lsb = in.readTTFUShort();
             }
         }
     }
 
 
-        /**
-         * Read the "post" table
-         * containing the postscript names of the glyphs.
-         */
-    private final void readPostscript(FontFileReader in) throws IOException {
+    /**
+       * 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);
+        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];
+                //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;
+            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;
-                    
+                //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);
+
+                    //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());
+                //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++) {
+
+                for (i = 0; i < l; i++) {
                     if (mtx_tab[i].index < NMACGLYPHS) {
-                        mtx_tab[i].name = Glyphs.mac_glyph_names[mtx_tab[i].index];
+                        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];
+                        /*
+                            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:
-                    // Postscript format 3 contains no glyph names
+                // Postscript format 3 contains no glyph names
                 System.out.println("Postscript format 3");
                 break;
             default:
@@ -766,308 +751,327 @@ public class TTFFile {
     }
 
 
-        /**
-         * Read the "OS/2" table
-         */
+    /**
+       * Read the "OS/2" table
+       */
     private final void readOS2(FontFileReader in) throws IOException {
-            // Check if font is embeddable
+        // 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;
+            seek_tab(in, "OS/2", 2 * 4);
+            int fsType = in.readTTFUShort();
+            if (fsType == 2)
+                is_embeddable = false;
             else
-                is_embeddable=true;
+                is_embeddable = true;
         } else
-            is_embeddable=true;
+            is_embeddable = true;
     }
 
-        /**
-         * Read the "loca" table
-         */
-    private final void readIndexToLocation(FontFileReader in)
-        throws IOException {
+    /**
+       * Read the "loca" table
+       */
+    protected final void readIndexToLocation(FontFileReader in)
+    throws IOException {
         seek_tab(in, "loca", 0);
-        for (int i=0; i < nglyphs ; i++) {
+        for (int i = 0; i < nglyphs ; i++) {
             mtx_tab[i].offset = (loca_format == 1 ? in.readTTFULong() :
                                  (in.readTTFUShort() << 1));
         }
+        lastLoca = (loca_format == 1 ? in.readTTFULong() :
+                    (in.readTTFUShort() << 1));
     }
 
-        /**
-         * Read the "glyf" table to find the bounding boxes
-         */
+    /**
+       * 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) {
+        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();
+                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];
+                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];
             }
         }
-      
-        
-        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);
+
+
+        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();
+                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];
+                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));
+            //System.out.println(mtx_tab[i].toString(this));
         }
     }
 
-        /**
-         * Read the "name" table
-         */
+    /**
+       * 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;
+        i += 2 * 2;
 
         while (n-- > 0) {
-                //System.out.println("Iteration: "+n);
+            //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());
+            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;
-                case 2: subFamilyName=txt;break;
-                case 4: fullName=txt; break;
-                case 6: fontName=txt; break;
-            }
-            if (!notice.equals("") && !fullName.equals("") &&
-                !fontName.equals("") && !familyName.equals("") &&
-                !subFamilyName.equals("")) {
-                break;
-            }
+                //System.out.println(platform_id+" "+encoding_id+
+                //" "+k+" "+txt);
+                switch (k) {
+                    case 0:
+                        notice = txt;
+                        break;
+                    case 1:
+                        familyName = txt;
+                        break;
+                    case 2:
+                        subFamilyName = txt;
+                        break;
+                    case 4:
+                        fullName = txt;
+                        break;
+                    case 6:
+                        fontName = txt;
+                        break;
+                }
+                if (!notice.equals("") && !fullName.equals("") &&
+                        !fontName.equals("") && !familyName.equals("") &&
+                        !subFamilyName.equals("")) {
+                    break;
+                }
             }
-            i+=6*2;
+            i += 6 * 2;
         }
     }
 
-        /**
-         * Read the "PCLT" table to find xHeight and capHeight
-         */
+    /**
+       * 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) {
+        TTFDirTabEntry 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;
+            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;
+                hasSerifs = false;
             else
-                hasSerifs=true;
-            
+                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++) {
+            // 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];
+                    capHeight = mtx_tab[i].bbox[3] - mtx_tab[i].bbox[1];
             }
         }
     }
 
-        /**
-         * Read the kerning table, create a table for both CIDs and
-         * winAnsiEncoding
-         */
+    /**
+       * 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) {
+        // Read kerning
+        kerningTab = new Hashtable();
+        ansiKerningTab = 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)
+            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)
+                if ((k >> 8) != 0)
                     continue;
-                
-                k=in.readTTFUShort();
+
+                k = in.readTTFUShort();
                 in.skip(3 * 2);
                 while (k-- > 0) {
-                    int i=in.readTTFUShort();
-                    int j=in.readTTFUShort();
-                    int kpx=in.readTTFShort();
+                    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();
+                        // 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)));
+                                   new Integer((int) get_ttf_funit(kpx)));
                         kerningTab.put(iObj, adjTab);
                     }
                 }
             }
-                //System.out.println(kerningTab.toString());
-                        
-                // Create winAnsiEncoded kerning table
-            
-            ansiKerningTab = new Hashtable();
+            //System.out.println(kerningTab.toString());
+
+            // Create winAnsiEncoded kerning table
+
             for (Enumeration ae = kerningTab.keys();
-                 ae.hasMoreElements();) {
-                Integer cidKey = (Integer)ae.nextElement();
+                    ae.hasMoreElements();) {
+                Integer cidKey = (Integer) ae.nextElement();
                 Hashtable akpx = new Hashtable();
-                Hashtable ckpx = (Hashtable)kerningTab.get(cidKey);
+                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());
+                        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());
+                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
-         */
+    /** 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);
-        
+    /**
+       * 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
+       */
+    protected final boolean checkTTC(FontFileReader in, String name,
+                                     boolean verbose) throws IOException {
+        String tag = in.readTTFString(4);
+
         if ("ttcf".equals(tag)) {
-                // This is a TrueType Collection
+            // 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;
+            // 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();
+            }
 
-                // Iterate through all name tables even if font
-                // Is found, just to show all the names
-            for (int i=0; (i < numDirectories); i++) {
+            if (verbose) {
+                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
+            long dirTabOffset = 0;
+            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);
+                    found = true;
+                    dirTabOffset = dirOffsets[i];
+                    if (verbose)
+                        System.out.println("* " + fullName);
                 } else {
-                    System.out.println(fullName);
+                    if (verbose)
+                        System.out.println(fullName);
                 }
-                
-                    // Reset names
-                notice="";
-                fullName="";
-                familyName="";
-                fontName="";
-                subFamilyName="";
+
+                // Reset names
+                notice = "";
+                fullName = "";
+                familyName = "";
+                fontName = "";
+                subFamilyName = "";
             }
 
+            in.seek_set(dirTabOffset);
             return found;
-        } else {
+        }
+        else {
             in.seek_set(0);
             return true;
         }
     }
 
-        /* Helper classes, they are not very efficient, but that really
-           doesn't matter... */
+    /* 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++)
+        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()];
@@ -1078,8 +1082,8 @@ public class TTFFile {
 
 
 /**
- * Key-value helper class
- */
  * Key-value helper class
  */
 class UnicodeMapping {
     int uIdx;
     int gIdx;
index e1333bd240aafd3061043e182888815d9af23dcc..56b27e62e193e40546d038eeaefdd4f37363a051 100644 (file)
@@ -1,52 +1,8 @@
 /* -- $Id$ --
-
- ============================================================================
-                   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 <jtauber@jtauber.com>. For more  information on the Apache
- Software Foundation, please see <http://www.apache.org/>.
-
+ *
+ * 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."
  */
 package org.apache.fop.fonts;
 
@@ -55,26 +11,27 @@ import java.util.Vector;
 
 class TTFMtxEntry {
     int wx;
+    int lsb;
     String name;
     int index;
     Vector unicodeIndex;
     int[] bbox;
     long offset;
     byte found;
-    
+
     TTFMtxEntry() {
-        name="";
-        found=0;
+        name = "";
+        found = 0;
         unicodeIndex = new Vector();
-        bbox=new int[4];
+        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));
+        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));
     }
 }
index 9c7cbad8c369e1c3c04885a4a4e3c2173f9fe99f..e63c024bd3687906d5732f9f74c643b1fa5caa74 100644 (file)
@@ -1,61 +1,17 @@
 /* -- $Id$ --
-
- ============================================================================
-                   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 <jtauber@jtauber.com>. For more  information on the Apache
- Software Foundation, please see <http://www.apache.org/>.
-
+ *
+ * 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."
  */
 package org.apache.fop.fonts;
 
 class TTFSegEntry {
-   int endCode;
-   int startCode;
-   int idDelta;
-   int idRangeOffset;
-   
-   TTFSegEntry() {
-   }
+    int endCode;
+    int startCode;
+    int idDelta;
+    int idRangeOffset;
+
+    TTFSegEntry() {
+    }
 }
index 5739a07e7ead0281f8b0fb5aef97fa874fb70cb9..120fd36a37ec20bdcb384b25b43de4dd1005ee5b 100644 (file)
@@ -13,7 +13,7 @@
        <xsl:element name="widths">
                <xsl:for-each select="char">
                        <xsl:variable name="char-num" select="@ansichar"/>
-                       <xsl:variable name="char-name" select="document('charlist.xml')/font-mappings/map[@win-ansi=$char-num]/@adobe-name"/>
+                       <xsl:variable name="char-name" select="document('file:charlist.xml')/font-mappings/map[@win-ansi=$char-num]/@adobe-name"/>
                        <xsl:if test="$char-name!=''">
                                <xsl:element name="char">
                                        <xsl:attribute name="name"><xsl:value-of select="$char-name"/></xsl:attribute>
index 581ba20dbfaae2a19010358e1b38fb4516244e2d..cf98ce434b01ca929d7b6e1785824892564ffcf1 100644 (file)
@@ -1,52 +1,8 @@
 /*-- $Id$ --
-
- ============================================================================
-                   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 <jtauber@jtauber.com>. For more  information on the Apache
- Software Foundation, please see <http://www.apache.org/>.
-
+ *
+ * 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."
  */
 package org.apache.fop.fonts.apps;
 
@@ -73,106 +29,104 @@ public class PFMReader {
     }
 
 
-       /**
-        * Parse commandline arguments. put options in the Hashtable and return
-        * arguments in the String array
-        * the arguments: -fn Perpetua,Bold -cn PerpetuaBold per.ttf Perpetua.xml
-        * returns a String[] with the per.ttf and Perpetua.xml. The hash
-        * will have the (key, value) pairs: (-fn, Perpetua) and (-cn, PerpetuaBold)
-        */
-   private static String[] parseArguments(Hashtable options, String[] args) {
-      Vector arguments=new Vector();
-      for (int i=0; i < args.length; i++) {
-         if (args[i].startsWith("-")) {
-             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]);
-         }
-      }
-      
-      String[] argStrings=new String[arguments.size()];
-      arguments.copyInto(argStrings);
-      return argStrings;
-   }
-
-   private final static void displayUsage() {
-      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 .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");
-   }
-      
-   
     /**
-     * The main method for the PFM reader tool.
-     * 
-     * @param  args Command-line arguments: [options] metricfile.pfm xmlfile.xml
-     * where options can be:
-     * -fn <fontname>
-     *     default is to use the fontname in the .pfm file, but you can override
-     *     that name to make sure that the embedded font is used instead of installed
-     *     fonts when viewing documents with Acrobat Reader.
-     * -cn <classname>
-     *     default is to use the fontname
-     * -ef <path to the Type1 .pfb fontfile>
-     *     will add the possibility to embed the font. When running fop, fop will look
-     *     for this file to embed it
-     * -er <path to Type1 fontfile relative to org/apache/fop/render/pdf/fonts>
-     *     you can also include the fontfile in the fop.jar file when building fop.
-     *     You can use both -ef and -er. The file specified in -ef will be searched first,
-     *     then the -er file.
-     */
+      * Parse commandline arguments. put options in the Hashtable and return
+      * arguments in the String array
+      * the arguments: -fn Perpetua,Bold -cn PerpetuaBold per.ttf Perpetua.xml
+      * returns a String[] with the per.ttf and Perpetua.xml. The hash
+      * will have the (key, value) pairs: (-fn, Perpetua) and (-cn, PerpetuaBold)
+      */
+    private static String[] parseArguments(Hashtable options,
+                                           String[] args) {
+        Vector arguments = new Vector();
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].startsWith("-")) {
+                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]);
+            }
+        }
+
+        String[] argStrings = new String[arguments.size()];
+        arguments.copyInto(argStrings);
+        return argStrings;
+    }
+
+    private final static void displayUsage() {
+        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 .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");
+    }
+
+
+    /**
+      * The main method for the PFM reader tool.
+      *
+      * @param  args Command-line arguments: [options] metricfile.pfm xmlfile.xml
+      * where options can be:
+      * -fn <fontname>
+      *     default is to use the fontname in the .pfm file, but you can override
+      *     that name to make sure that the embedded font is used instead of installed
+      *     fonts when viewing documents with Acrobat Reader.
+      * -cn <classname>
+      *     default is to use the fontname
+      * -ef <path to the Type1 .pfb fontfile>
+      *     will add the possibility to embed the font. When running fop, fop will look
+      *     for this file to embed it
+      * -er <path to Type1 fontfile relative to org/apache/fop/render/pdf/fonts>
+      *     you can also include the fontfile in the fop.jar file when building fop.
+      *     You can use both -ef and -er. The file specified in -ef will be searched first,
+      *     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);
-        
+        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");
-        
+            embFile = (String) options.get("-ef");
+
         if (options.get("-er") != null)
-            embResource=(String)options.get("-er");
-        
+            embResource = (String) options.get("-er");
+
         if (options.get("-fn") != null)
-            fontName=(String)options.get("-fn");
-        
+            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)
+            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);
-                
+
+                org.w3c.dom.Document doc =
+                  app.constructFontXML(pfm, fontName, className,
+                                       embResource, embFile);
+
                 app.writeFontXML(doc, arguments[1]);
             }
         }
@@ -180,11 +134,11 @@ public class PFMReader {
 
 
     /**
-     * Read a PFM file and returns it as an object.
-     *
-     * @param   filename The filename of the PFM file.
-     * @return  The PFM as an object.
-     */
+      * Read a PFM file and returns it as an object.
+      *
+      * @param   filename The filename of the PFM file.
+      * @return  The PFM as an object.
+      */
     public PFMFile loadPFM(String filename) {
         try {
             System.out.println("Reading " + filename + "...");
@@ -200,10 +154,10 @@ public class PFMReader {
     }
 
     /**
-     * Displays a preview of the PFM file on the console.
-     * 
-     * @param   pfm The PFM file to preview.
-     */
+      * Displays a preview of the PFM file on the console.
+      *
+      * @param   pfm The PFM file to preview.
+      */
     public void preview(PFMFile pfm) {
         PrintStream out = System.out;
 
@@ -222,7 +176,7 @@ public class PFMReader {
         out.print("LowerCaseDescent: ");
         out.println(pfm.getLowerCaseDescent());
         out.print("Having widths for ");
-        out.print(pfm.getLastChar()-pfm.getFirstChar());
+        out.print(pfm.getLastChar() - pfm.getFirstChar());
         out.print(" characters (");
         out.print(pfm.getFirstChar());
         out.print("-");
@@ -236,20 +190,20 @@ public class PFMReader {
     }
 
     /**
-     * Writes the generated DOM Document to a file.
-     * 
-     * @param   doc The DOM Document to save.
-     * @param   target The target filename for the XML file.
-     */
+      * Writes the generated DOM Document to a file.
+      *
+      * @param   doc The DOM Document to save.
+      * @param   target The target filename for the XML file.
+      */
     public void writeFontXML(org.w3c.dom.Document doc, String target) {
         System.out.println("Writing xml font file " + target + "...");
         System.out.println();
 
         try {
-            OutputFormat format = new OutputFormat(doc);     //Serialize DOM
-            FileWriter out = new FileWriter(target);         //Writer will be a String
+            OutputFormat format = new OutputFormat(doc); //Serialize DOM
+            FileWriter out = new FileWriter(target); //Writer will be a String
             XMLSerializer serial = new XMLSerializer(out, format);
-            serial.asDOMSerializer();                        // As a DOM Serializer
+            serial.asDOMSerializer(); // As a DOM Serializer
 
             serial.serialize(doc.getDocumentElement());
             out.close();
@@ -259,14 +213,14 @@ public class PFMReader {
     }
 
     /**
-     * Generates the font metrics file from the PFM file.
-     * 
-     * @param   pfm The PFM file to generate the font metrics from.
-     * @return  The DOM document representing the font metrics file.
-     */
-    public org.w3c.dom.Document constructFontXML(PFMFile pfm, String fontName,
-                                                 String className, String resource,
-                                                 String file) {
+      * Generates the font metrics file from the PFM file.
+      *
+      * @param   pfm The PFM file to generate the font metrics from.
+      * @return  The DOM document representing the font metrics file.
+      */
+    public org.w3c.dom.Document constructFontXML(PFMFile pfm,
+            String fontName, String className, String resource,
+            String file) {
         System.out.println("Creating xml font file...");
         System.out.println();
 
@@ -274,7 +228,7 @@ public class PFMReader {
         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()));
@@ -282,22 +236,22 @@ public class PFMReader {
         String s = pfm.getPostscriptName();
         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);
+            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("embed");
         root.appendChild(el);
-        if (file!=null)
-           el.setAttribute("file", file);
-        if (resource!=null)
-           el.setAttribute("class", resource);
+        if (file != null)
+            el.setAttribute("file", file);
+        if (resource != null)
+            el.setAttribute("class", resource);
 
         el = doc.createElement("encoding");
         root.appendChild(el);
-        el.appendChild(doc.createTextNode(pfm.getCharSetName()+"Encoding"));
+        el.appendChild(doc.createTextNode(pfm.getCharSetName() + "Encoding"));
 
         el = doc.createElement("cap-height");
         root.appendChild(el);
@@ -323,7 +277,7 @@ public class PFMReader {
         root.appendChild(bbox);
         int[] bb = pfm.getFontBBox();
         String[] names = {"left","bottom","right","top"};
-        for (int i=0; i<4; i++) {
+        for (int i = 0; i < 4; i++) {
             el = doc.createElement(names[i]);
             bbox.appendChild(el);
             value = new Integer(bb[i]);
@@ -358,48 +312,50 @@ public class PFMReader {
         Element widths = doc.createElement("widths");
         root.appendChild(widths);
 
-        for (short i = pfm.getFirstChar(); i < pfm.getLastChar(); i++) {
+        for (short i = pfm.getFirstChar(); i <= pfm.getLastChar(); i++) {
             el = doc.createElement("char");
             widths.appendChild(el);
             el.setAttribute("idx", Integer.toString(i));
-            el.setAttribute("wdt", new Integer(pfm.getCharWidth(i)).toString());
+            el.setAttribute("wdt",
+                            new Integer(pfm.getCharWidth(i)).toString());
         }
 
 
-            // Get kerning
-        for (Enumeration enum=pfm.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)pfm.getKerning().get(kpx1);
-           for (Enumeration enum2=h2.keys(); enum2.hasMoreElements(); ) {
-               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);
-           }
+        // Get kerning
+        for (Enumeration enum = pfm.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) pfm.getKerning().get(kpx1);
+            for (Enumeration enum2 = h2.keys(); enum2.hasMoreElements();) {
+                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;
     }
 
-   
-   private String escapeString(String str) {
-      StringBuffer esc=new StringBuffer();
-      
-      for (int i=0; i < str.length(); i++) {
-         if (str.charAt(i)=='\\')
-            esc.append("\\\\");
-         else
-            esc.append(str.charAt(i));
-      }
-
-      return esc.toString();
-   }
+
+    private String escapeString(String str) {
+        StringBuffer esc = new StringBuffer();
+
+        for (int i = 0; i < str.length(); i++) {
+            if (str.charAt(i) == '\\')
+                esc.append("\\\\");
+            else
+                esc.append(str.charAt(i));
+        }
+
+        return esc.toString();
+    }
 }
 
 
index e4ff7774bd7355f3c179f244ee023e54c9293f80..61b3b01f6b097c433bc882a3b135da708559b169 100644 (file)
@@ -1,52 +1,8 @@
 /* -- $Id$ --
-
- ============================================================================
-                   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 <jtauber@jtauber.com>. For more  information on the Apache
- Software Foundation, please see <http://www.apache.org/>.
-
+ *
+ * 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."
  */
 package org.apache.fop.fonts.apps;
 
@@ -72,180 +28,182 @@ public class TTFReader {
     }
 
 
-       /**
-        * Parse commandline arguments. put options in the Hashtable and return
-        * arguments in the String array
-        * the arguments: -fn Perpetua,Bold -cn PerpetuaBold per.ttf Perpetua.xml
-        * returns a String[] with the per.ttf and Perpetua.xml. The hash
-        * will have the (key, value) pairs: (-fn, Perpetua) and (-cn, PerpetuaBold)
-        */
-   private static String[] parseArguments(Hashtable options, String[] args) {
-      Vector arguments=new Vector();
-      for (int i=0; i < args.length; i++) {
-         if (args[i].startsWith("-")) {
-             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]);
-         }
-      }
-
-      String[] argStrings=new String[arguments.size()];
-      arguments.copyInto(argStrings);
-      return argStrings;
-   }
-
-
-   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\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");
-   }
-      
-      
     /**
-     * The main method for the PFM reader tool.
-     * 
-     * @param  args Command-line arguments: [options] fontfile.ttf xmlfile.xml
-     * where options can be:
-     * -fn <fontname>
-     *     default is to use the fontname in the .ttf file, but you can override
-     *     that name to make sure that the embedded font is used instead of installed
-     *     fonts when viewing documents with Acrobat Reader.
-     * -cn <classname>
-     *     default is to use the fontname
-     * -ef <path to the truetype fontfile>
-     *     will add the possibility to embed the font. When running fop, fop will look
-     *     for this file to embed it
-     * -er <path to truetype fontfile relative to org/apache/fop/render/pdf/fonts>
-     *     you can also include the fontfile in the fop.jar file when building fop.
-     *     You can use both -ef and -er. The file specified in -ef will be searched first,
-     *     then the -er file.
-     */
+       * Parse commandline arguments. put options in the Hashtable and return
+       * arguments in the String array
+       * the arguments: -fn Perpetua,Bold -cn PerpetuaBold per.ttf Perpetua.xml
+       * returns a String[] with the per.ttf and Perpetua.xml. The hash
+       * will have the (key, value) pairs: (-fn, Perpetua) and (-cn, PerpetuaBold)
+       */
+    private static String[] parseArguments(Hashtable options,
+                                           String[] args) {
+        Vector arguments = new Vector();
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].startsWith("-")) {
+                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]);
+            }
+        }
+
+        String[] argStrings = new String[arguments.size()];
+        arguments.copyInto(argStrings);
+        return argStrings;
+    }
+
+
+    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 ansi");
+        System.out.println("     With this option you create a WinAnsi encoded font.\n");
+        System.out.println("     The default is to create a CID keyed font.");
+        System.out.println("     If you're not going to use characters outside the");
+        System.out.println("     pdfencoding range (almost the same as iso-8889-1)");
+        System.out.println("     you can 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\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");
+    }
+
+
+    /**
+       * The main method for the TTFReader tool.
+       *
+       * @param  args Command-line arguments: [options] fontfile.ttf xmlfile.xml
+       * where options can be:
+       * -fn <fontname>
+       *     default is to use the fontname in the .ttf file, but you can override
+       *     that name to make sure that the embedded font is used instead of installed
+       *     fonts when viewing documents with Acrobat Reader.
+       * -cn <classname>
+       *     default is to use the fontname
+       * -ef <path to the truetype fontfile>
+       *     will add the possibility to embed the font. When running fop, fop will look
+       *     for this file to embed it
+       * -er <path to truetype fontfile relative to org/apache/fop/render/pdf/fonts>
+       *     you can also include the fontfile in the fop.jar file when building fop.
+       *     You can use both -ef and -er. The file specified in -ef will be searched first,
+       *     then the -er file.
+       */
     public static void main(String[] args) {
-       String embFile=null;
-       String embResource=null;
-       String className=null;
-       String fontName=null;
-       String ttcName=null;
-       boolean isCid=false;
-       
-       Hashtable options=new Hashtable();
-       String[] arguments=parseArguments(options, args);
-       
-       TTFReader app = new TTFReader();
-       app.invokedStandalone = true;
-       
-       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");
-       
-       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 {
-          TTFFile ttf = app.loadTTF(arguments[0], ttcName);
-          if (ttf != null) {
-             org.w3c.dom.Document doc = app.constructFontXML(ttf,
-                                                             fontName,
-                                                             className,
-                                                             embResource,
-                                                             embFile,
-                                                             isCid,
-                                                             ttcName);
-             
-             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.");
-             
-          }
-       }
+        String embFile = null;
+        String embResource = null;
+        String className = null;
+        String fontName = null;
+        String ttcName = null;
+        boolean isCid = true;
+
+        Hashtable options = new Hashtable();
+        String[] arguments = parseArguments(options, args);
+
+        TTFReader app = new TTFReader();
+        app.invokedStandalone = true;
+
+        System.out.println("TTF Reader v1.1.1");
+        System.out.println();
+
+        if (options.get("-enc") != null) {
+            String enc = (String) options.get("-enc");
+            if ("ansi".equals(enc))
+                isCid = false;
+        }
+
+        if (options.get("-ttcname") != null)
+            ttcName = (String) options.get("-ttcname");
+
+        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 {
+            TTFFile ttf = app.loadTTF(arguments[0], ttcName);
+            if (ttf != null) {
+                org.w3c.dom.Document doc =
+                  app.constructFontXML(ttf, fontName, className,
+                                       embResource, embFile, isCid, ttcName);
+
+                if (isCid)
+                    System.out.println("Creating CID encoded metrics");
+                else
+                    System.out.println("Creating WinAnsi encoded metrics");
+
+                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 shouldn't be embedded.");
+
+            }
+        }
     }
-   
-       /**
-        * Read a TTF file and returns it as an object.
-        *
-        * @param   filename The filename of the PFM file.
-        * @return  The TTF as an object.
-        */
-   public TTFFile loadTTF(String fileName, String fontName) {
-      TTFFile ttfFile=new TTFFile();
-      try {
-         System.out.println("Reading " + fileName + "...");
-         System.out.println();
-
-         FontFileReader reader = new FontFileReader(fileName);
-         ttfFile.readFont(reader, fontName);
-      } catch (Exception e) {
-         e.printStackTrace();
-         return null;
-      }
-      return ttfFile;
+
+    /**
+       * Read a TTF file and returns it as an object.
+       *
+       * @param   filename The filename of the PFM file.
+       * @return  The TTF as an object.
+       */
+    public TTFFile loadTTF(String fileName, String fontName) {
+        TTFFile ttfFile = new TTFFile();
+        try {
+            System.out.println("Reading " + fileName + "...");
+            System.out.println();
+
+            FontFileReader reader = new FontFileReader(fileName);
+            ttfFile.readFont(reader, fontName);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+        return ttfFile;
     }
 
 
     /**
-     * Writes the generated DOM Document to a file.
-     * 
-     * @param   doc The DOM Document to save.
-     * @param   target The target filename for the XML file.
-     */
+       * Writes the generated DOM Document to a file.
+       *
+       * @param   doc The DOM Document to save.
+       * @param   target The target filename for the XML file.
+       */
     public void writeFontXML(org.w3c.dom.Document doc, String target) {
         System.out.println("Writing xml font file " + target + "...");
         System.out.println();
 
         try {
-            OutputFormat format = new OutputFormat(doc);     //Serialize DOM
-            FileWriter out = new FileWriter(target);         //Writer will be a String
+            OutputFormat format = new OutputFormat(doc); //Serialize DOM
+            FileWriter out = new FileWriter(target); //Writer will be a String
             XMLSerializer serial = new XMLSerializer(out, format);
-            serial.asDOMSerializer();                        // As a DOM Serializer
+            serial.asDOMSerializer(); // As a DOM Serializer
 
             serial.serialize(doc.getDocumentElement());
             out.close();
@@ -255,15 +213,14 @@ public class TTFReader {
     }
 
     /**
-     * Generates the font metrics file from the TTF/TTC file.
-     * 
-     * @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, boolean isCid,
-                                                 String ttcName) {
+       * Generates the font metrics file from the TTF/TTC file.
+       *
+       * @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, boolean isCid, String ttcName) {
         System.out.println("Creating xml font file...");
         System.out.println();
 
@@ -274,18 +231,18 @@ public class TTFReader {
             root.setAttribute("type", "TYPE0");
         else
             root.setAttribute("type", "TRUETYPE");
-        
+
         Element el = doc.createElement("font-name");
         root.appendChild(el);
 
-            // Note that the PostScript name usually is something like
-            // "Perpetua-Bold", but the TrueType spec says that in the ttf file
-            // it should be "Perpetua,Bold".
+        // Note that the PostScript name usually is something like
+        // "Perpetua-Bold", but the TrueType spec says that in the ttf file
+        // it should be "Perpetua,Bold".
 
         String s = stripWhiteSpace(ttf.getPostscriptName());
 
         if (fontName != null)
-           el.appendChild(doc.createTextNode(stripWhiteSpace(fontName)));
+            el.appendChild(doc.createTextNode(stripWhiteSpace(fontName)));
         else
             el.appendChild(doc.createTextNode(s));
 
@@ -298,66 +255,62 @@ public class TTFReader {
 
         el = doc.createElement("cap-height");
         root.appendChild(el);
-        Integer value = new Integer(ttf.getCapHeight());
-        el.appendChild(doc.createTextNode(value.toString()));
+        el.appendChild(
+          doc.createTextNode(String.valueOf(ttf.getCapHeight())));
 
         el = doc.createElement("x-height");
         root.appendChild(el);
-        value = new Integer(ttf.getXHeight());
-        el.appendChild(doc.createTextNode(value.toString()));
-        
+        el.appendChild(
+          doc.createTextNode(String.valueOf(ttf.getXHeight())));
+
         el = doc.createElement("ascender");
         root.appendChild(el);
-        value = new Integer(ttf.getLowerCaseAscent());
-        el.appendChild(doc.createTextNode(value.toString()));
-        
+        el.appendChild( doc.createTextNode(
+                          String.valueOf(ttf.getLowerCaseAscent())));
+
         el = doc.createElement("descender");
         root.appendChild(el);
-        value = new Integer(ttf.getLowerCaseDescent());
-        el.appendChild(doc.createTextNode(value.toString()));
+        el.appendChild( doc.createTextNode(
+                          String.valueOf(ttf.getLowerCaseDescent())));
 
         Element bbox = doc.createElement("bbox");
         root.appendChild(bbox);
         int[] bb = ttf.getFontBBox();
         String[] names = {"left","bottom","right","top"};
-        for (int i=0; i<4; i++) {
+        for (int i = 0; i < 4; i++) {
             el = doc.createElement(names[i]);
             bbox.appendChild(el);
-            value = new Integer(bb[i]);
-            el.appendChild(doc.createTextNode(value.toString()));
+            el.appendChild(doc.createTextNode(String.valueOf(bb[i])));
         }
 
         el = doc.createElement("flags");
         root.appendChild(el);
-        value = new Integer(ttf.getFlags());
-        el.appendChild(doc.createTextNode(value.toString()));
-        
+        el.appendChild(doc.createTextNode(String.valueOf(ttf.getFlags())));
+
         el = doc.createElement("stemv");
         root.appendChild(el);
-        value = new Integer(ttf.getStemV());
-        el.appendChild(doc.createTextNode(value.toString()));
-        
+        el.appendChild(doc.createTextNode(ttf.getStemV()));
+
         el = doc.createElement("italicangle");
         root.appendChild(el);
-        value = new Integer(ttf.getItalicAngle());
-        el.appendChild(doc.createTextNode(value.toString()));
+        el.appendChild(doc.createTextNode(ttf.getItalicAngle()));
 
         if (ttcName != null) {
             el = doc.createElement("ttc-name");
             root.appendChild(el);
             el.appendChild(doc.createTextNode(ttcName));
         }
-        
+
         el = doc.createElement("subtype");
         root.appendChild(el);
-        
-            // Fill in extras for CID keyed fonts
+
+        // Fill in extras for CID keyed fonts
         if (isCid) {
             el.appendChild(doc.createTextNode("TYPE0"));
 
             Element mel = doc.createElement("multibyte-extras");
             root.appendChild(mel);
-            
+
             el = doc.createElement("cid-type");
             mel.appendChild(el);
             el.appendChild(doc.createTextNode("CIDFontType2"));
@@ -368,117 +321,119 @@ public class TTFReader {
 
             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");
+            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));
+                el2.setAttribute("us", String.valueOf(ce.unicodeStart));
+                el2.setAttribute("ue", String.valueOf(ce.unicodeEnd));
+                el2.setAttribute("gi", String.valueOf(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]));
+                Element wxel = doc.createElement("wx");
+                wxel.setAttribute("w", String.valueOf(wx[i]));
                 el.appendChild(wxel);
             }
         } else {
-                // Fill in extras for singlebyte fonts
+            // Fill in extras for singlebyte fonts
             el.appendChild(doc.createTextNode("TRUETYPE"));
 
-            Element sel=doc.createElement("singlebyte-extras");
+            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.appendChild(
+              doc.createTextNode(String.valueOf(ttf.getFirstChar())));
+
             el = doc.createElement("last-char");
             sel.appendChild(el);
-            value = new Integer(ttf.getLastChar());
-            el.appendChild(doc.createTextNode(value.toString()));
-            
+            el.appendChild(
+              doc.createTextNode(String.valueOf(ttf.getLastChar())));
+
             Element widths = doc.createElement("widths");
             sel.appendChild(widths);
-            
-            for (short i = ttf.getFirstChar(); i < ttf.getLastChar(); i++) {
+
+            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)));
+                el.setAttribute("idx", String.valueOf(i));
+                el.setAttribute("wdt", String.valueOf(ttf.getCharWidth(i)));
             }
         }
-        
-            // Get kerning
+
+        // Get kerning
         Enumeration enum;
         if (isCid)
-            enum=ttf.getKerning().keys();
+            enum = ttf.getKerning().keys();
         else
-            enum=ttf.getAnsiKerning().keys();
-        
+            enum = ttf.getAnsiKerning().keys();
+
         while (enum.hasMoreElements()) {
-            Integer kpx1=(Integer)enum.nextElement();
+            Integer kpx1 = (Integer) enum.nextElement();
 
-            el=doc.createElement("kerning");
+            el = doc.createElement("kerning");
             el.setAttribute("kpx1", kpx1.toString());
             root.appendChild(el);
-            Element el2=null;
-            
+            Element el2 = null;
+
             Hashtable h2;
             if (isCid)
-                h2 = (Hashtable)ttf.getKerning().get(kpx1);
+                h2 = (Hashtable) ttf.getKerning().get(kpx1);
             else
-                h2 = (Hashtable)ttf.getAnsiKerning().get(kpx1);
-            
-            for (Enumeration enum2=h2.keys(); enum2.hasMoreElements(); ) {
-                Integer kpx2=(Integer)enum2.nextElement();
+                h2 = (Hashtable) ttf.getAnsiKerning().get(kpx1);
+
+            for (Enumeration enum2 = h2.keys(); enum2.hasMoreElements();) {
+                Integer kpx2 = (Integer) enum2.nextElement();
                 if (isCid || kpx2.intValue() < 256) {
-                    el2=doc.createElement("pair");
+                    el2 = doc.createElement("pair");
                     el2.setAttribute("kpx2", kpx2.toString());
-                    Integer val=(Integer)h2.get(kpx2);
+                    Integer val = (Integer) h2.get(kpx2);
                     el2.setAttribute("kern", val.toString());
                     el.appendChild(el2);
                 }
             }
         }
-        
+
         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')
+            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();
-      
-      for (int i=0; i < str.length(); i++) {
-         if (str.charAt(i)=='\\')
-            esc.append("\\\\");
-         else
-            esc.append(str.charAt(i));
-      }
-
-      return esc.toString();
-   }
+
+    private String escapeString(String str) {
+        StringBuffer esc = new StringBuffer();
+
+        for (int i = 0; i < str.length(); i++) {
+            if (str.charAt(i) == '\\')
+                esc.append("\\\\");
+            else
+                esc.append(str.charAt(i));
+        }
+
+        return esc.toString();
+    }
 }
 
index bbdc6f66f99c4c371c16833b0b1a16a3e0002534..1c0a94f3f8423a45031c7a1e0c74d790133c607d 100644 (file)
@@ -1,52 +1,8 @@
 /*-- $Id$ --
-
- ============================================================================
-                   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 <jtauber@jtauber.com>. For more  information on the Apache
- Software Foundation, please see <http://www.apache.org/>.
-
+ *
+ * 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."
  */
 
 package org.apache.fop.layout;
@@ -220,6 +176,8 @@ public class LineArea extends Area {
             data[count] = odata[count];
         }
 
+        boolean isText = false;
+
         /* iterate over each character */
         for (int i = start; i < end; i++) {
             int charWidth;
@@ -229,14 +187,12 @@ public class LineArea extends Area {
                   (c == '\t'))) {
                c = data[i] = currentFontState.mapChar(c);
                charWidth = currentFontState.width(c);
+               isText = true;
                if (charWidth <= 0)
                   charWidth = whitespaceWidth;
             } else {
                charWidth = whitespaceWidth;
-            }
-
-            if ((c == ' ') || (c == '\n') || (c == '\r') ||
-                    (c == '\t')) { // whitespace
+               isText = false;
 
                 if (prev == WHITESPACE) {
 
@@ -370,11 +326,12 @@ public class LineArea extends Area {
                         spaceWidth = whitespaceWidth;
                     } else {
                         // skip over it
-                        start++;
+                        wordStart++;
                     }
                 }
 
-            } else { // current is TEXT
+            }
+            if(isText) { // current is TEXT
 
                 if (prev == WHITESPACE) {
 
index 153ab4a36220c09149e22f1f890cc235752469a4..ce79dce42c767afaab084a765d50272b1eb651dd 100644 (file)
@@ -1,52 +1,8 @@
-/*-- $Id$ -- 
-
- ============================================================================
-                   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 <jtauber@jtauber.com>. For more  information on the Apache 
- Software Foundation, please see <http://www.apache.org/>.
+/*-- $Id$ --
+ *
+ * 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."
  */
 
 package org.apache.fop.render.pdf;
@@ -81,7 +37,7 @@ public class FontReader extends DefaultHandler {
     private MultiByteFont multiFont = null;
     private SingleByteFont singleFont = null;
     private Font returnFont = null;
-        //private SingleByteFont singleFont = null;
+    //private SingleByteFont singleFont = null;
     private String text = null;
 
     private Vector cidWidths = null;
@@ -90,7 +46,7 @@ public class FontReader extends DefaultHandler {
     private Hashtable currentKerning = null;
 
     private Vector bfranges = null;
-    
+
     private void createFont(String path) throws IOException {
         XMLReader parser = ConfigurationReader.createParser();
         if (parser == null)
@@ -100,8 +56,8 @@ public class FontReader extends DefaultHandler {
             parser.setFeature("http://xml.org/sax/features/namespace-prefixes",
                               false);
         } catch (SAXException e) {
-            throw new IOException ("You need a SAX parser which supports " +
-                                   "SAX version 2");
+            throw new IOException (
+              "You need a SAX parser which supports " + "SAX version 2");
         }
 
         parser.setContentHandler(this);
@@ -113,38 +69,38 @@ public class FontReader extends DefaultHandler {
         }
     }
 
-        /**
-         * Sets the path to embed a font. a null value disables font embedding
-         */
+    /**
+      * Sets the path to embed a font. a null value disables font embedding
+      */
     public void setFontEmbedPath(String path) {
         if (isCID)
-            multiFont.embedFileName=path;
+            multiFont.embedFileName = path;
         else
-            singleFont.embedFileName=path;
+            singleFont.embedFileName = path;
     }
-    
-        /**
-         * Enable/disable use of kerning for the font
-         */
+
+    /**
+      * Enable/disable use of kerning for the font
+      */
     public void useKerning(boolean kern) {
         if (isCID)
             multiFont.useKerning = true;
         else
             singleFont.useKerning = true;
     }
-    
-        
-        /**
-         * Get the generated font object
-         */
+
+
+    /**
+      * Get the generated font object
+      */
     public Font getFont() {
         return returnFont;
     }
 
-        /**
-         * Construct a FontReader object from a path to a metric.xml file
-         * and read metric data
-         */
+    /**
+      * Construct a FontReader object from a path to a metric.xml file
+      * and read metric data
+      */
     public FontReader(String path) throws IOException {
         createFont(path);
     }
@@ -176,25 +132,27 @@ public class FontReader extends DefaultHandler {
             }
         } else if ("embed".equals(localName)) {
             if (isCID) {
-                    // This *is* annoying... should create a common
-                    // interface for sing/multibytefonts...
+                // This *is* annoying... should create a common
+                // interface for sing/multibytefonts...
                 multiFont.embedFileName = attributes.getValue("file");
                 multiFont.embedResourceName = attributes.getValue("class");
             } else {
                 singleFont.embedFileName = attributes.getValue("file");
                 singleFont.embedResourceName = attributes.getValue("class");
-            }   
+            }
         } else if ("cid-widths".equals(localName)) {
             cidWidthIndex = getInt(attributes.getValue("start-index"));
             cidWidths = new Vector();
         } else if ("kerning".equals(localName)) {
             currentKerning = new Hashtable();
             if (isCID)
-                multiFont.kerning.put(new Integer(attributes.getValue("kpx1")),
-                                      currentKerning);
+                multiFont.kerning.put(
+                  new Integer(attributes.getValue("kpx1")),
+                  currentKerning);
             else
-                singleFont.kerning.put(new Integer(attributes.getValue("kpx1")),
-                                       currentKerning);
+                singleFont.kerning.put(
+                  new Integer(attributes.getValue("kpx1")),
+                  currentKerning);
         } else if ("bfranges".equals(localName)) {
             bfranges = new Vector();
         } else if ("bf".equals(localName)) {
@@ -209,15 +167,16 @@ public class FontReader extends DefaultHandler {
             singleFont.width = new int[256];
         } else if ("char".equals(localName)) {
             try {
-                singleFont.width[Integer.parseInt(attributes.getValue("idx"))] =
+                singleFont.width[
+                  Integer.parseInt(attributes.getValue("idx"))] =
                     Integer.parseInt(attributes.getValue("wdt"));
             } catch (NumberFormatException ne) {
                 System.out.println("Malformed width in metric file: " +
                                    ne.getMessage());
             }
         } else if ("pair".equals(localName)) {
-            currentKerning.put(new Integer(attributes.getValue("kpx2")),
-                               new Integer(attributes.getValue("kern")));
+            currentKerning.put( new Integer(attributes.getValue("kpx2")),
+                                new Integer(attributes.getValue("kern")));
         }
     }
 
@@ -228,13 +187,15 @@ public class FontReader extends DefaultHandler {
         } catch (Exception e) {}
         return ret;
     }
-    
+
     public void endElement(String uri, String localName, String qName) {
         if ("font-name".equals(localName))
             if (isCID)
                 multiFont.fontName = text;
             else
                 singleFont.fontName = text;
+        if ("ttc-name".equals(localName) && isCID)
+            multiFont.ttcName = text;
         else if ("cap-height".equals(localName))
             if (isCID)
                 multiFont.capHeight = getInt(text);
@@ -307,14 +268,15 @@ public class FontReader extends DefaultHandler {
         } else if ("cid-widths".equals(localName)) {
             int[] wds = new int[cidWidths.size()];
             int j = 0;
-            for (Enumeration e = cidWidths.elements(); e.hasMoreElements();) {
-                Integer i = (Integer)e.nextElement();
+            for (Enumeration e = cidWidths.elements();
+                    e.hasMoreElements();) {
+                Integer i = (Integer) e.nextElement();
                 wds[j++] = i.intValue();
             }
 
             multiFont.warray.addEntry(cidWidthIndex, wds);
             multiFont.width = wds;
-            
+
         } else if ("bfranges".equals(localName)) {
             BFEntry[] entries = new BFEntry[bfranges.size()];
             bfranges.copyInto(entries);
@@ -328,7 +290,7 @@ public class FontReader extends DefaultHandler {
         System.arraycopy(ch, start, c, 0, length);
         text = new String(c);
     }
-    
+
 }
 
 
index fabbb180287b6b0670c46b10305cd4b721867631..eb4ab80e36fbf56442307c98708e8605cd12f47f 100644 (file)
@@ -37,7 +37,7 @@ import java.util.Hashtable;
 public class PDFRenderer extends PrintRenderer {
 
     private static final boolean OPTIMIZE_TEXT = true;
-    
+
     /** the PDF Document being created */
     protected PDFDocument pdfDoc;
 
@@ -68,7 +68,7 @@ public class PDFRenderer extends PrintRenderer {
     int prevWordWidth = 0;
 
     private PDFOutline rootOutline;
-       
+
     /**
      * create the PDF renderer
      */
@@ -77,20 +77,20 @@ public class PDFRenderer extends PrintRenderer {
     }
 
     /**
-       * set the PDF document's producer
-       *
-       * @param producer string indicating application producing PDF
-       */
+        * set the PDF document's producer
+        *
+        * @param producer string indicating application producing PDF
+        */
     public void setProducer(String producer) {
         this.pdfDoc.setProducer(producer);
     }
 
     /**
-       * render the areas into PDF
-       *
-       * @param areaTree the laid-out area tree
-       * @param stream the OutputStream to write the PDF to
-       */
+        * render the areas into PDF
+        *
+        * @param areaTree the laid-out area tree
+        * @param stream the OutputStream to write the PDF to
+        */
     public void render(AreaTree areaTree,
                        OutputStream stream) throws IOException, FOPException {
         MessageHandler.logln("rendering areas to PDF");
@@ -108,14 +108,36 @@ public class PDFRenderer extends PrintRenderer {
                                    idReferences.getInvalidIds() + "\n");
 
         }
-               renderRootExtensions(areaTree);
-       
+        renderRootExtensions(areaTree);
+
         FontSetup.addToResources(this.pdfDoc, fontInfo);
-        
+
         MessageHandler.logln("writing out PDF");
         this.pdfDoc.output(stream);
     }
 
+    /**
+        * add a line to the current stream
+        *
+        * @param x1 the start x location in millipoints
+        * @param y1 the start y location in millipoints
+        * @param x2 the end x location in millipoints
+        * @param y2 the end y location in millipoints
+        * @param th the thickness in millipoints
+        * @param r the red component
+        * @param g the green component
+        * @param b the blue component
+        */
+    protected void addLine(int x1, int y1, int x2, int y2, int th,
+                           PDFPathPaint stroke) {
+        closeText();
+
+        currentStream.add("ET\nq\n" + stroke.getColorSpaceOut(false) +
+                          (x1 / 1000f) + " "+ (y1 / 1000f) + " m " +
+                          (x2 / 1000f) + " "+ (y2 / 1000f) + " l " +
+                          (th / 1000f) + " w S\n" + "Q\nBT\n");
+    }
+
     /**
        * add a line to the current stream
        *
@@ -124,72 +146,50 @@ public class PDFRenderer extends PrintRenderer {
        * @param x2 the end x location in millipoints
        * @param y2 the end y location in millipoints
        * @param th the thickness in millipoints
+       * @param rs the rule style
        * @param r the red component
        * @param g the green component
        * @param b the blue component
        */
-    protected void addLine(int x1, int y1, int x2, int y2, int th,
-                           PDFPathPaint stroke) {
-               closeText();
-       
-        currentStream.add("ET\nq\n" + stroke.getColorSpaceOut(false) +
-                          (x1 / 1000f) + " "+ (y1 / 1000f) + " m " +
-                          (x2 / 1000f) + " "+ (y2 / 1000f) + " l " +
-                          (th / 1000f) + " w S\n" + "Q\nBT\n");
-    }
-
-    /**
-      * add a line to the current stream
-      *
-      * @param x1 the start x location in millipoints
-      * @param y1 the start y location in millipoints
-      * @param x2 the end x location in millipoints
-      * @param y2 the end y location in millipoints
-      * @param th the thickness in millipoints
-      * @param rs the rule style
-      * @param r the red component
-      * @param g the green component
-      * @param b the blue component
-      */
     protected void addLine(int x1, int y1, int x2, int y2, int th,
                            int rs, PDFPathPaint stroke) {
-       closeText();
+        closeText();
         currentStream.add("ET\nq\n" + stroke.getColorSpaceOut(false) +
-                          setRuleStylePattern(rs) + (x1 / 1000f) + " "+ (y1 / 1000f) + " m " +
-                          (x2 / 1000f) + " "+ (y2 / 1000f) + " l " +
-                          (th / 1000f) + " w S\n" + "Q\nBT\n");
+                          setRuleStylePattern(rs) + (x1 / 1000f) + " "+
+                          (y1 / 1000f) + " m " + (x2 / 1000f) + " "+
+                          (y2 / 1000f) + " l " + (th / 1000f) + " w S\n" + "Q\nBT\n");
     }
 
     /**
-       * add a rectangle to the current stream
-       *
-       * @param x the x position of left edge in millipoints
-       * @param y the y position of top edge in millipoints
-       * @param w the width in millipoints
-       * @param h the height in millipoints
-       * @param stroke the stroke color/gradient
-       */
+        * add a rectangle to the current stream
+        *
+        * @param x the x position of left edge in millipoints
+        * @param y the y position of top edge in millipoints
+        * @param w the width in millipoints
+        * @param h the height in millipoints
+        * @param stroke the stroke color/gradient
+        */
     protected void addRect(int x, int y, int w, int h,
                            PDFPathPaint stroke) {
-       closeText();
+        closeText();
         currentStream.add("ET\nq\n" + stroke.getColorSpaceOut(false) +
                           (x / 1000f) + " " + (y / 1000f) + " " + (w / 1000f) +
                           " " + (h / 1000f) + " re s\n" + "Q\nBT\n");
     }
 
     /**
-       * add a filled rectangle to the current stream
-       *
-       * @param x the x position of left edge in millipoints
-       * @param y the y position of top edge in millipoints
-       * @param w the width in millipoints
-       * @param h the height in millipoints
-       * @param fill the fill color/gradient
-       * @param stroke the stroke color/gradient
-       */
+        * add a filled rectangle to the current stream
+        *
+        * @param x the x position of left edge in millipoints
+        * @param y the y position of top edge in millipoints
+        * @param w the width in millipoints
+        * @param h the height in millipoints
+        * @param fill the fill color/gradient
+        * @param stroke the stroke color/gradient
+        */
     protected void addRect(int x, int y, int w, int h,
                            PDFPathPaint stroke, PDFPathPaint fill) {
-       closeText();
+        closeText();
         currentStream.add("ET\nq\n" + fill.getColorSpaceOut(true) +
                           stroke.getColorSpaceOut(false) + (x / 1000f) + " " +
                           (y / 1000f) + " " + (w / 1000f) + " " + (h / 1000f) +
@@ -197,10 +197,10 @@ public class PDFRenderer extends PrintRenderer {
     }
 
     /**
-       * render image area to PDF
-       *
-       * @param area the image area to render
-       */
+        * render image area to PDF
+        *
+        * @param area the image area to render
+        */
     public void renderImageArea(ImageArea area) {
         // adapted from contribution by BoBoGi
         int x = this.currentAreaContainerXPosition + area.getXOffset();
@@ -213,8 +213,8 @@ public class PDFRenderer extends PrintRenderer {
         FopImage img = area.getImage();
         if (img instanceof SVGImage) {
             try {
-               closeText();
-               
+                closeText();
+
                 SVGSVGElement svg =
                   ((SVGImage) img).getSVGDocument().getRootElement();
                 currentStream.add("ET\nq\n" + (((float) w) / 1000f) +
@@ -227,8 +227,8 @@ public class PDFRenderer extends PrintRenderer {
             }
         } else {
             int xObjectNum = this.pdfDoc.addImage(img);
-           closeText();
-           
+            closeText();
+
             currentStream.add("ET\nq\n" + (((float) w) / 1000f) +
                               " 0 0 " + (((float) h) / 1000f) + " " +
                               (((float) x) / 1000f) + " " +
@@ -269,8 +269,8 @@ public class PDFRenderer extends PrintRenderer {
             case VerticalAlign.BOTTOM:
                 break;
         }
-       closeText();
-       
+        closeText();
+
         // in general the content will not be text
         currentStream.add("ET\n");
         // align and scale
@@ -296,64 +296,66 @@ public class PDFRenderer extends PrintRenderer {
         currentStream.add("Q\n");
         currentStream.add("BT\n");
         this.currentXPosition += area.getEffectiveWidth();
-//        this.currentYPosition -= area.getEffectiveHeight();
+        //        this.currentYPosition -= area.getEffectiveHeight();
     }
 
     /**
-       * render SVG area to PDF
-       *
-       * @param area the SVG area to render
-       */
+        * render SVG area to PDF
+        *
+        * @param area the SVG area to render
+        */
     public void renderSVGArea(SVGArea area) {
         // place at the current instream offset
         int x = this.currentXPosition;
-       // Buggy: Method getXOffset() not found in class org.apache.fop.dom.svg.SVGArea
+        // Buggy: Method getXOffset() not found in class org.apache.fop.dom.svg.SVGArea
         //int x = this.currentAreaContainerXPosition + area.getXOffset();
         int y = this.currentYPosition;
         SVGSVGElement svg = area.getSVGDocument().getRootElement();
         int w = (int)(svg.getWidth().getBaseVal().getValue() * 1000);
         int h = (int)(svg.getHeight().getBaseVal().getValue() * 1000);
-       float sx = 1, sy = -1;
-       int xOffset = x, yOffset = y;
-
-       // translate and scale according to viewbox.
-       if (svg.getViewBox () != null) {
-           SVGRect view = svg.getViewBox().getBaseVal();
-
-           // TODO take aspect constraints (attribute preserveAspectRatio)
-           // into account.
-           // Viewbox coordinates are all relative to the viewport
-           // (ie. the x,y,w and h values calculated above).
-           sx = svg.getWidth().getBaseVal().getValue() / view.getWidth ();
-           sy = svg.getHeight().getBaseVal().getValue() / view.getHeight ();
-
-           // move the origin
-           xOffset -= (int)(sx * view.getX () * 1000f);
-           yOffset -= (int)(sy * view.getY () * 1000f);
-
-           sy = -sy;
-       }
+        float sx = 1, sy = -1;
+        int xOffset = x, yOffset = y;
+
+        // translate and scale according to viewbox.
+        if (svg.getViewBox () != null) {
+            SVGRect view = svg.getViewBox().getBaseVal();
+
+            // TODO take aspect constraints (attribute preserveAspectRatio)
+            // into account.
+            // Viewbox coordinates are all relative to the viewport
+            // (ie. the x,y,w and h values calculated above).
+            sx = svg.getWidth().getBaseVal().getValue() / view.getWidth ();
+            sy = svg.getHeight().getBaseVal().getValue() /
+                 view.getHeight ();
+
+            // move the origin
+            xOffset -= (int)(sx * view.getX () * 1000f);
+            yOffset -= (int)(sy * view.getY () * 1000f);
+
+            sy = -sy;
+        }
 
         /*
-         * Clip to the svg area.
-         * Note: To have the svg overlay (under) a text area then use
-         * an fo:block-container
-         */
+          * Clip to the svg area.
+          * Note: To have the svg overlay (under) a text area then use
+          * an fo:block-container
+          */
         currentStream.add("q\n");
-       if (w != 0 && h != 0) {
-        currentStream.add(x / 1000f + " " + y / 1000f + " m\n");
-        currentStream.add((x + w) / 1000f + " " + y / 1000f + " l\n");
-        currentStream.add((x + w) / 1000f + " " + (y - h) / 1000f + " l\n");
-        currentStream.add(x / 1000f + " " + (y - h) / 1000f + " l\n");
-        currentStream.add("h\n");
-        currentStream.add("W\n");
-        currentStream.add("n\n");
-       }
+        if (w != 0 && h != 0) {
+            currentStream.add(x / 1000f + " " + y / 1000f + " m\n");
+            currentStream.add((x + w) / 1000f + " " + y / 1000f + " l\n");
+            currentStream.add((x + w) / 1000f + " " + (y - h) / 1000f +
+                              " l\n");
+            currentStream.add(x / 1000f + " " + (y - h) / 1000f + " l\n");
+            currentStream.add("h\n");
+            currentStream.add("W\n");
+            currentStream.add("n\n");
+        }
         // transform so that the coordinates (0,0) is from the top left
         // and positive is down and to the right. (0,0) is where the
-       // viewBox puts it.
-        currentStream.add(sx + " 0 0 " + sy + " " +
-                          xOffset / 1000f + " " + yOffset / 1000f + " cm\n");
+        // viewBox puts it.
+        currentStream.add(sx + " 0 0 " + sy + " " + xOffset / 1000f +
+                          " " + yOffset / 1000f + " cm\n");
 
         SVGRenderer svgRenderer =
           new SVGRenderer(area.getFontState(), pdfDoc,
@@ -366,17 +368,17 @@ public class PDFRenderer extends PrintRenderer {
     }
 
     /**
-       * render inline area to PDF
-       *
-       * @param area inline area to render
-       */
+        * render inline area to PDF
+        *
+        * @param area inline area to render
+        */
     public void renderWordArea(WordArea area) {
-       //  char ch;
+        //  char ch;
         StringBuffer pdf = new StringBuffer();
 
-       Hashtable kerning = null;
-       boolean kerningAvailable = false;
-       
+        Hashtable kerning = null;
+        boolean kerningAvailable = false;
+
         kerning = area.getFontState().getKerning();
         if (kerning != null && !kerning.isEmpty()) {
             kerningAvailable = true;
@@ -385,23 +387,23 @@ public class PDFRenderer extends PrintRenderer {
         String name = area.getFontState().getFontName();
         int size = area.getFontState().getFontSize();
 
-            // This assumes that *all* CIDFonts use a /ToUnicode mapping
+        // This assumes that *all* CIDFonts use a /ToUnicode mapping
         boolean useMultiByte = false;
-        Font f = (Font)area.getFontState().getFontInfo().getFonts().get(name);
+        Font f = (Font) area.getFontState().getFontInfo().getFonts().get(
+                   name);
         if (f instanceof CIDFont)
-            useMultiByte=true;
-            //String startText = useMultiByte ? "<FEFF" : "(";
+            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());
+                                             (double) area.getGreen(), (double) area.getBlue());
 
         if ((!name.equals(this.currentFontName)) ||
                 (size != this.currentFontSize)) {
-           closeText();
-           
+            closeText();
+
             this.currentFontName = name;
             this.currentFontSize = size;
             pdf = pdf.append("/" + name + " " + (size / 1000) + " Tf\n");
@@ -409,48 +411,47 @@ public class PDFRenderer extends PrintRenderer {
 
 
         if (!(theAreaColor.equals(this.currentFill))) {
-           closeText();
-           this.currentFill = theAreaColor;
-           pdf.append(this.currentFill.getColorSpaceOut(true));
+            closeText();
+            this.currentFill = theAreaColor;
+            pdf.append(this.currentFill.getColorSpaceOut(true));
         }
 
 
         int rx = this.currentXPosition;
         int bl = this.currentYPosition;
 
-               addWordLines(area, rx, bl, size, theAreaColor);
-
-       if (OPTIMIZE_TEXT) {
-           if (!textOpen || bl != prevWordY) {
-               closeText();
-               
-               pdf.append("1 0 0 1 " +(rx / 1000f) + " " + 
-                          (bl / 1000f) + " Tm [" + startText);
-               prevWordY = bl;
-               textOpen = true;
-           }
-           else {
-               // 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 + " " + startText);
-           }
-           prevWordWidth = area.getContentWidth();
-           prevWordX = rx;
-
-       }
-       else {
-           // original text render code sets the text transformation matrix
-           // for every word.
-           pdf.append("1 0 0 1 " +(rx / 1000f) + " " + (bl / 1000f) + " Tm ");
-           if (kerningAvailable) {
-               pdf.append(" [" + startText);
-           }
-           else {
-               pdf.append(" " + startText);
-           }
-       }
-       
+        addWordLines(area, rx, bl, size, theAreaColor);
+
+        if (OPTIMIZE_TEXT) {
+            if (!textOpen || bl != prevWordY) {
+                closeText();
+
+                pdf.append("1 0 0 1 " +(rx / 1000f) + " " +
+                           (bl / 1000f) + " Tm [" + startText);
+                prevWordY = bl;
+                textOpen = true;
+            } else {
+                // 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 + " " + startText);
+            }
+            prevWordWidth = area.getContentWidth();
+            prevWordX = rx;
+
+        } else {
+            // original text render code sets the text transformation matrix
+            // for every word.
+            pdf.append("1 0 0 1 " +(rx / 1000f) + " " + (bl / 1000f) +
+                       " Tm ");
+            if (kerningAvailable) {
+                pdf.append(" [" + startText);
+            } else {
+                pdf.append(" " + startText);
+            }
+        }
+
         String s;
         if (area.getPageNumberID() != null) { // this text is a page number, so resolve it
             s = idReferences.getPageNumber(area.getPageNumberID());
@@ -465,10 +466,10 @@ public class PDFRenderer extends PrintRenderer {
 
         for (int i = 0; i < l; i++) {
             char ch = s.charAt(i);
-           String prepend = "";
-           
+            String prepend = "";
+
             if (!useMultiByte) {
-                if(ch > 127) {
+                if (ch > 127) {
                     pdf.append("\\");
                     pdf.append(Integer.toOctalString((int) ch));
                 } else {
@@ -479,115 +480,110 @@ public class PDFRenderer extends PrintRenderer {
                             prepend = "\\";
                             break;
                     }
-                    pdf.append(getUnicodeString(prepend+ch, useMultiByte));
+                    pdf.append(
+                      getUnicodeString(prepend + ch, useMultiByte));
                 }
-           } else {
-                    pdf.append(getUnicodeString(prepend+ch, useMultiByte));
-            }                
-
-           if (kerningAvailable && (i+1) < l) {
-               pdf.append(addKerning((new Integer((int)ch)),
-                                                       (new Integer((int)s.charAt(i+1))),
-                                                       kerning,
-                                                       startText, endText));
+            } else {
+                pdf.append(getUnicodeString(prepend + ch, useMultiByte));
+            }
+
+            if (kerningAvailable && (i + 1) < l) {
+                addKerning(pdf, (new Integer((int) ch)),
+                           (new Integer((int) s.charAt(i + 1))), kerning,
+                           startText, endText);
             }
-            
+
         }
         pdf.append(endText + " ");
-       if (!OPTIMIZE_TEXT) {
-           if (kerningAvailable) {
-               pdf.append("] TJ\n");
-           }
-           else {
-               pdf.append("Tj\n");
-           }
-           
-       }
-       
+        if (!OPTIMIZE_TEXT) {
+            if (kerningAvailable) {
+                pdf.append("] TJ\n");
+            } else {
+                pdf.append("Tj\n");
+            }
+
+        }
+
 
 
         currentStream.add(pdf.toString());
 
         this.currentXPosition += area.getContentWidth();
-       
+
     }
 
 
-        /**
-         * Convert a string to a unicode hex representation
-         */
-    private String getUnicodeString(StringBuffer str, boolean useMultiByte) {
+    /**
+      * 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
-         */
+
+    /**
+      * 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);
+            StringBuffer buf = new StringBuffer(str.length() * 4);
             byte[] uniBytes = null;
             try {
                 uniBytes = str.getBytes("UnicodeBigUnmarked");
             } catch (Exception e) {
-                    // This should never fail
+                // 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);
+                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);
+                    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
-     */
-    private void closeText() 
-    {
-       if (OPTIMIZE_TEXT && textOpen) {
-           currentStream.add("] TJ\n");
-           textOpen = false;
-           prevWordX = 0;
-           prevWordY = 0;
-       }
+      * still and writes out the TJ command to the stream if we do
+      */
+    private void closeText() {
+        if (OPTIMIZE_TEXT && textOpen) {
+            currentStream.add("] TJ\n");
+            textOpen = false;
+            prevWordX = 0;
+            prevWordY = 0;
+        }
     }
 
-   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("");
-
-      if (h2!=null) {
-         Integer wdt=(Integer)h2.get(ch2);
-         if (wdt!=null) {
-            pwdt=-wdt.intValue();
-            buf=buf.append(endText + " " + pwdt + " " + startText);
-         }
-      }
-      return buf;
-   }
+    private void addKerning(StringBuffer buf, Integer ch1, Integer ch2,
+                            Hashtable kerning, String startText, String endText) {
+        Hashtable h2 = (Hashtable) kerning.get(ch1);
+
+        if (h2 != null) {
+            Integer wdt = (Integer) h2.get(ch2);
+            if (wdt != null) {
+                buf.append(endText).append(' ').append(-
+                                                       wdt.intValue()).append(' ').append(startText);
+            }
+        }
+    }
 
     /**
-       * render page into PDF
-       *
-       * @param page page to render
-       */
+        * render page into PDF
+        *
+        * @param page page to render
+        */
     public void renderPage(Page page) {
-               BodyAreaContainer body;
+        BodyAreaContainer body;
         AreaContainer before, after, start, end;
 
         currentStream = this.pdfDoc.makeStream();
@@ -600,7 +596,7 @@ public class PDFRenderer extends PrintRenderer {
         this.currentFontName = "";
         this.currentFontSize = 0;
 
-               currentStream.add("BT\n");
+        currentStream.add("BT\n");
 
         renderBodyAreaContainer(body);
 
@@ -612,20 +608,19 @@ public class PDFRenderer extends PrintRenderer {
             renderAreaContainer(after);
         }
 
-               if (start != null) {
+        if (start != null) {
             renderAreaContainer(start);
         }
 
-               if (end != null) {
+        if (end != null) {
             renderAreaContainer(end);
         }
-               closeText();
-       
+        closeText();
+
         currentStream.add("ET\n");
 
         currentPage = this.pdfDoc.makePage(this.pdfResources, currentStream,
-                                           page.getWidth() / 1000,
-                                          page.getHeight() / 1000, page);
+                                           page.getWidth() / 1000, page.getHeight() / 1000, page);
 
         if (page.hasLinks()) {
             currentAnnotList = this.pdfDoc.makeAnnotList();
@@ -654,8 +649,8 @@ public class PDFRenderer extends PrintRenderer {
     }
 
     /**
-       * defines a string containing dashArray and dashPhase for the rule style
-       */
+        * defines a string containing dashArray and dashPhase for the rule style
+        */
     private String setRuleStylePattern (int style) {
         String rs = "";
         switch (style) {
@@ -677,52 +672,49 @@ public class PDFRenderer extends PrintRenderer {
         return rs;
     }
 
-    protected void renderRootExtensions(AreaTree areaTree) 
-    {
-       Vector v = areaTree.getExtensions();
-       if (v != null) {
-           Enumeration e = v.elements();
-           while (e.hasMoreElements()) {
-               ExtensionObj ext = (ExtensionObj)e.nextElement();
-               if (ext instanceof Outline) {
-                   renderOutline((Outline)ext);
-               }
-           }
-       }
-       
+    protected void renderRootExtensions(AreaTree areaTree) {
+        Vector v = areaTree.getExtensions();
+        if (v != null) {
+            Enumeration e = v.elements();
+            while (e.hasMoreElements()) {
+                ExtensionObj ext = (ExtensionObj) e.nextElement();
+                if (ext instanceof Outline) {
+                    renderOutline((Outline) ext);
+                }
+            }
+        }
+
     }
 
-    private void renderOutline(Outline outline) 
-    {
-       if (rootOutline == null) {
-           rootOutline = this.pdfDoc.makeOutlineRoot();
-       }
-       PDFOutline pdfOutline = null;
-       Outline parent = outline.getParentOutline();
-       if (parent == null) {
-           pdfOutline = this.pdfDoc.makeOutline(rootOutline, 
-                                                outline.getLabel().toString(),
-                                                outline.getInternalDestination());
-       }
-       else {
-           PDFOutline pdfParentOutline = (PDFOutline)parent.getRendererObject();
-           if (pdfParentOutline == null) {
-               MessageHandler.errorln("Error: pdfParentOutline is null");
-           }
-           else {
-               pdfOutline = this.pdfDoc.makeOutline(pdfParentOutline, 
-                                                    outline.getLabel().toString(),
-                                                    outline.getInternalDestination());
-           }
-          
-       }
-       outline.setRendererObject(pdfOutline);
-       
-       // handle sub outlines  
-       Vector v = outline.getOutlines();
-       Enumeration e = v.elements();
-       while (e.hasMoreElements()) {
-           renderOutline((Outline)e.nextElement());
-       }
+    private void renderOutline(Outline outline) {
+        if (rootOutline == null) {
+            rootOutline = this.pdfDoc.makeOutlineRoot();
+        }
+        PDFOutline pdfOutline = null;
+        Outline parent = outline.getParentOutline();
+        if (parent == null) {
+            pdfOutline = this.pdfDoc.makeOutline(rootOutline,
+                                                 outline.getLabel().toString(),
+                                                 outline.getInternalDestination());
+        } else {
+            PDFOutline pdfParentOutline =
+              (PDFOutline) parent.getRendererObject();
+            if (pdfParentOutline == null) {
+                MessageHandler.errorln("Error: pdfParentOutline is null");
+            } else {
+                pdfOutline = this.pdfDoc.makeOutline(pdfParentOutline,
+                                                     outline.getLabel().toString(),
+                                                     outline.getInternalDestination());
+            }
+
+        }
+        outline.setRendererObject(pdfOutline);
+
+        // handle sub outlines
+        Vector v = outline.getOutlines();
+        Enumeration e = v.elements();
+        while (e.hasMoreElements()) {
+            renderOutline((Outline) e.nextElement());
+        }
     }
 }
index 7b55e843ded9829613b84a2194d504e0a213782d..f8305c3d66c6f55612d8237ead27e12fd4b56a73 100644 (file)
@@ -1,17 +1,26 @@
-
+/* $Id$
+ *
+ * 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."
+ */
 
 package org.apache.fop.render.pdf.fonts;
 
 import org.apache.fop.render.pdf.Font;
 import org.apache.fop.layout.FontDescriptor;
 import org.apache.fop.fonts.Glyphs;
+import org.apache.fop.fonts.TTFSubSetFile;
+import org.apache.fop.fonts.FontFileReader;
 import org.apache.fop.pdf.PDFStream;
 import org.apache.fop.pdf.PDFWArray;
 import org.apache.fop.pdf.PDFCIDFont;
 import org.apache.fop.render.pdf.CIDFont;
 import org.apache.fop.render.pdf.CMap;
 import org.apache.fop.pdf.PDFTTFStream;
+import org.apache.fop.messaging.MessageHandler;
 import java.io.InputStream;
+import java.io.IOException;
 import java.io.FileInputStream;
 import java.io.File;
 import java.io.BufferedInputStream;
@@ -22,143 +31,185 @@ import java.util.Hashtable;
  */
 public class MultiByteFont extends CIDFont implements FontDescriptor {
     public String fontName = null;
+    public String ttcName = null;
     public String encoding = "Identity-H";
-    
+
     public int capHeight = 0;
     public int xHeight = 0;
     public int ascender = 0;
     public int descender = 0;
     public int[] fontBBox = {0, 0, 0, 0};
-    
+
     public String embedFileName = null;
     public String embedResourceName = null;
-    public PDFTTFStream embeddedFont=null;
-    
+    public PDFTTFStream embeddedFont = null;
+
     public int flags = 4;
     public int stemV = 0;
     public int italicAngle = 0;
     public int missingWidth = 0;
     public int defaultWidth = 0;
     public byte cidType = PDFCIDFont.CID_TYPE2;
-    
-    public Hashtable kerning=new Hashtable();
+
+    public Hashtable kerning = new Hashtable();
     public boolean useKerning = true;
-    
-    public PDFWArray warray=new PDFWArray();
+    private String namePrefix = null; // Quasi unique prefix
+    private static int uniqueCounter = 1;
+    public PDFWArray warray = new PDFWArray();
     public int width[] = null;
 
     public BFEntry[] bfentries = null;
-    
 
-    public MultiByteFont() {}
-    
+
+    /** usedGlyphs contains orginal, new glyph index */
+    private Hashtable usedGlyphs = new Hashtable();
+    /** usedGlyphsIndex contains new glyph, original index */
+    private Hashtable usedGlyphsIndex = new Hashtable();
+    int usedGlyphsCount = 0;
+
+    public MultiByteFont() {
+        // Make sure that the 3 first glyphs are included
+        usedGlyphs.put(new Integer(0), new Integer(0));
+        usedGlyphsIndex.put(new Integer(0), new Integer(0));
+        usedGlyphsCount++;
+        usedGlyphs.put(new Integer(1), new Integer(1));
+        usedGlyphsIndex.put(new Integer(1), new Integer(1));
+        usedGlyphsCount++;
+        usedGlyphs.put(new Integer(2), new Integer(2));
+        usedGlyphsIndex.put(new Integer(2), new Integer(2));
+        usedGlyphsCount++;
+
+        // Create a quasiunique prefix for fontname
+        int cnt = 0;
+        synchronized (this.getClass()) {
+            cnt = uniqueCounter++;
+        }
+        int ctm = (int)(System.currentTimeMillis() & 0xffff);
+        namePrefix = new String(cnt + "E"+ Integer.toHexString(ctm));
+    }
+
     public final boolean hasKerningInfo() {
         return (useKerning & kerning.isEmpty());
     }
-    public final java.util.Hashtable getKerningInfo() {return kerning;}
+    public final java.util.Hashtable getKerningInfo() {
+        if (useKerning)
+            return kerning;
+        else
+            return new Hashtable();
+    }
 
     public byte getSubType() {
         return org.apache.fop.pdf.PDFFont.TYPE0;
     }
 
-    public String getLang() {return null;}
-    public String getPanose() {return null;}
-    public int getAvgWidth() {return -1;}
-    public int getMinWidth() {return -1;}
-    public int getMaxWidth() {return -1;}
-    public int getleading() {return -1;}
-    public int getStemH() {return 0;}
-    public int getMissingWidth() {return missingWidth;}
-    public int getDefaultWidth() {return defaultWidth;}
-    public String getRegistry() {return "Adobe";}
-    public String getOrdering() {return "UCS";}
-    public int getSupplement() {return 0;}
-    public byte getCidType() {return cidType;}
-    public String getCidBaseFont() {return fontName;}
-    public String getCharEncoding() {return "Identity-H";}
+    public String getLang() {
+        return null;
+    }
+    public String getPanose() {
+        return null;
+    }
+    public int getAvgWidth() {
+        return -1;
+    }
+    public int getMinWidth() {
+        return -1;
+    }
+    public int getMaxWidth() {
+        return -1;
+    }
+    public int getleading() {
+        return -1;
+    }
+    public int getStemH() {
+        return 0;
+    }
+    public int getMissingWidth() {
+        return missingWidth;
+    }
+    public int getDefaultWidth() {
+        return defaultWidth;
+    }
+    public String getRegistry() {
+        return "Adobe";
+    }
+    public String getOrdering() {
+        return "UCS";
+    }
+    public int getSupplement() {
+        return 0;
+    }
+    public byte getCidType() {
+        return cidType;
+    }
+    public String getCidBaseFont() {
+        return isEmbeddable() ? namePrefix + fontName : fontName;
+    }
+
+    public String getCharEncoding() {
+        return "Identity-H";
+    }
 
     public PDFWArray getWidths() {
+        if (isEmbeddable()) {
+            // Create widths for reencoded chars
+            warray = new PDFWArray();
+            int[] tmpWidth = new int[usedGlyphsCount];
+
+            for (int i = 0; i < usedGlyphsCount; i++) {
+                Integer nw = (Integer) usedGlyphsIndex.get(new Integer(i));
+                int nwx = (nw == null) ? 0 : nw.intValue();
+                tmpWidth[i] = width[nwx];
+            }
+            warray.addEntry(0, tmpWidth);
+        }
         return warray;
     }
 
     public boolean isEmbeddable() {
-        return (embedFileName==null && embedResourceName==null) ? false : true;
+        return (embedFileName == null && embedResourceName == null) ?
+               false : true;
     }
 
-    
-    public PDFStream getFontFile(int i) {
-        InputStream instream=null;
 
-        int iniSize = 256000;
-        int incSize = 128000;
-        // Get file first
-        if (embedFileName!=null)
-        try {
-            File ef = new File(embedFileName);
-            iniSize = (int)ef.length()+1;
-            incSize = (int)ef.length()/10;
-           instream=new FileInputStream(embedFileName);
-        } catch (Exception e) {
-           System.out.println("Failed to embed fontfile: "+embedFileName);
-        }
-   
-        // Get resource
-        if (instream==null && embedResourceName!=null)
+    public PDFStream getFontFile(int i) {
         try {
-           instream=new BufferedInputStream(this.getClass().getResourceAsStream(embedResourceName));
-        } catch (Exception e) {
-           System.out.println("Failed to embed fontresource: "+embedResourceName);
+            FontFileReader reader = new FontFileReader(embedFileName);
+            TTFSubSetFile subset = new TTFSubSetFile();
+
+            byte[] subsetFont =
+              subset.readFont(reader, ttcName, usedGlyphs);
+            // Only TrueType CID fonts are supported now
+
+            embeddedFont = new PDFTTFStream(i, subsetFont.length);
+            embeddedFont.addFilter("flate");
+            embeddedFont.addFilter("ascii-85");
+            embeddedFont.setData(subsetFont, subsetFont.length);
+        } catch (IOException ioe) {
+            MessageHandler.error("Failed to embed font " + fontName +
+                                 ": " + ioe.getMessage());
+            return (PDFStream) null;
         }
-        
-        if (instream==null)
-            return (PDFStream)null;
-        
-        // Read fontdata
-        byte[] file = new byte[iniSize];
-        int fsize = 0;
-
-        try {
-          int l = instream.read(file, 0, iniSize);
-          fsize += l;
-      
-          if (l==iniSize) {
-                 // More to read - needs to extend
-             byte[] tmpbuf;
-         
-             while (l > 0) {
-                 tmpbuf = new byte[file.length + incSize];
-                 System.arraycopy(file, 0, tmpbuf, 0, file.length);
-                 l=instream.read(tmpbuf, file.length, incSize);
-                 fsize += l;
-                 file = tmpbuf;
-            
-                 if (l < incSize) // whole file read. No need to loop again
-                    l=0;
-             }
-          }
-
-              // Only TrueType CID fonts are supported now
-          embeddedFont=new PDFTTFStream(i, fsize);
-          embeddedFont.addFilter("flate");
-          embeddedFont.addFilter("ascii-85");
-          embeddedFont.setData(file, fsize);
-          instream.close();
-        } catch (Exception e) {}  
 
         return (PDFStream) embeddedFont;
     }
-    
+
     public String encoding() {
         return encoding;
     }
-    
+
     public String fontName() {
-        return fontName;
+        return isEmbeddable() ? namePrefix + fontName : fontName;
     }
 
-    public int getAscender() {return ascender;}
-    public int getDescender() {return descender;}
-    public int getCapHeight() {return capHeight;}
+    public int getAscender() {
+        return ascender;
+    }
+    public int getDescender() {
+        return descender;
+    }
+    public int getCapHeight() {
+        return capHeight;
+    }
 
     public int getAscender(int size) {
         return size * ascender;
@@ -201,36 +252,73 @@ public class MultiByteFont extends CIDFont implements FontDescriptor {
     }
 
     public int width(int i, int size) {
-        return size * width[i];
+        if (isEmbeddable()) {
+            Integer idx = (Integer) usedGlyphsIndex.get(new Integer(i));
+            return size * width[idx.intValue()];
+        } else {
+            return size * width[i];
+        }
     }
 
     public int[] getWidths(int size) {
         int[] arr = new int[width.length];
-        System.arraycopy(width, 0, arr, 0, width.length-1);
-        for( int i = 0; i < arr.length; i++) arr[i] *= size;
+        System.arraycopy(width, 0, arr, 0, width.length - 1);
+        for (int i = 0; i < arr.length; i++)
+            arr[i] *= size;
         return arr;
     }
 
+    public Integer reMap(Integer i) {
+        if (isEmbeddable()) {
+            Integer ret = (Integer) usedGlyphsIndex.get(i);
+            if (ret == null)
+                ret = i;
+            return ret;
+        } else {
+            return i;
+        }
+
+    }
+
     public char mapChar(char c) {
-        int idx = (int)c;
+        int idx = (int) c;
         int retIdx = 0;
 
         for (int i = 0; (i < bfentries.length) && retIdx == 0; i++) {
-
-                /*
-                  System.out.println("us: "+bfentries[i].unicodeStart +
-                  " ue: "+bfentries[i].unicodeEnd+
-                  " gi: "+bfentries[i].glyphStartIndex);
-                */
             if (bfentries[i].unicodeStart <= idx &&
-                bfentries[i].unicodeEnd >= idx) {
-                retIdx=bfentries[i].glyphStartIndex + idx -
-                    bfentries[i].unicodeStart;
+                                             bfentries[i].unicodeEnd >= idx) {
+                retIdx = bfentries[i].glyphStartIndex + idx -
+                         bfentries[i].unicodeStart;
+            }
+        }
+
+        if (isEmbeddable()) {
+            // Reencode to a new subset font or get
+            // the reencoded value
+            Integer newIdx = (Integer) usedGlyphs.get(new Integer(retIdx));
+            if (newIdx == null) {
+                usedGlyphs.put(new Integer(retIdx),
+                               new Integer(usedGlyphsCount));
+                usedGlyphsIndex.put(new Integer(usedGlyphsCount),
+                                    new Integer(retIdx));
+                retIdx = usedGlyphsCount;
+                //System.out.println(c+"("+(int)c+") = "+retIdx);
+                usedGlyphsCount++;
+            } else {
+                retIdx = newIdx.intValue();
             }
         }
 
-            //System.out.println("Map: "+ c + " (" + idx + ") = " + retIdx);
-        return (char)retIdx;
+        return (char) retIdx;
     }
 }
 
+
+
+
+
+
+
+
+
+
index 413d2e7d3485fdaf08822e6ea6af53e155d8acab..8a847e2c54a48895c70b1404282188d67080c8ad 100644 (file)
@@ -1,4 +1,9 @@
-
+/* $Id$
+ *
+ * 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."
+ */
 
 package org.apache.fop.render.pdf.fonts;
 
@@ -47,7 +52,12 @@ public class SingleByteFont extends Font implements FontDescriptor {
         return (useKerning & kerning.isEmpty());
     }
     
-    public final java.util.Hashtable getKerningInfo() {return kerning;}
+    public final java.util.Hashtable getKerningInfo() {
+       if (useKerning)
+          return kerning;
+       else
+          return new Hashtable();
+    }
 
     public byte getSubType() {
         return subType;