]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Moved PFM classes to type1 subpackage
authorJeremias Maerki <jeremias@apache.org>
Mon, 2 Dec 2002 14:27:58 +0000 (14:27 +0000)
committerJeremias Maerki <jeremias@apache.org>
Mon, 2 Dec 2002 14:27:58 +0000 (14:27 +0000)
Style and javadocs
Remove dependencies on Xerces (using JAXP instead)
PFMReader uses Avalon Logging
Setting logger now following Avalon lifecycle

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@195710 13f79535-47bb-0310-9956-ffa450edef68

src/org/apache/fop/fonts/Glyphs.java
src/org/apache/fop/fonts/PFMFile.java [deleted file]
src/org/apache/fop/fonts/PFMInputStream.java [deleted file]
src/org/apache/fop/fonts/TTFFile.java
src/org/apache/fop/fonts/apps/PFMReader.java
src/org/apache/fop/fonts/apps/TTFReader.java

index 9f5da3b75845e7c093a286f7336e267b37c64ae3..0b584d56f80be4284f07624c541ba167f7fc733f 100644 (file)
@@ -1,18 +1,28 @@
 /*
  * $Id$
- * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
+ * Copyright (C) 2001-2002 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;
 
+/**
+ * This class provides a number of constants for glyph management.
+ */
 public class Glyphs {
-    static String notdef = ".notdef";
 
-    static String mac_glyph_names[] = {
+    /**
+     * Glyph name for the "notdef" glyph
+     */
+    public static final String NOTDEF = ".notdef";
+
+    /**
+     * Glyph names for Mac encoding
+     */
+    public static final String MAC_GLYPH_NAMES[] = {
         /* 0x00 */
-        notdef, ".null", "CR", "space", "exclam", "quotedbl", "numbersign",
+        NOTDEF, ".null", "CR", "space", "exclam", "quotedbl", "numbersign",
                 "dollar", "percent", "ampersand", "quotesingle", "parenleft",
                 "parenright", "asterisk", "plus", "comma", /* 0x10 */
         "hyphen", "period", "slash", "zero", "one", "two", "three", "four",
@@ -68,9 +78,12 @@ public class Glyphs {
         "ccaron", "dmacron"
     };
 
-    static String[] tex8r = {
+    /**
+     * Glyph names for tex8r encoding
+     */
+    public static final String[] TEX8R_GLYPH_NAMES = {
         // 0x00
-        ".notdef", "dotaccent", "fi", "fl", "fraction", "hungarumlaut",
+        NOTDEF, "dotaccent", "fi", "fl", "fraction", "hungarumlaut",
                    "Lslash", "lslash", "ogonek", "ring", ".notdef", "breve",
                    "minus", ".notdef", "Zcaron", "zcaron", // 0x10
         "caron", "dotlessi", "dotlessj", "ff", "ffi", "ffl", ".notdef",
@@ -127,7 +140,7 @@ public class Glyphs {
     /**
      * The characters in WinAnsiEncoding
      */
-    public static char[] winAnsiEncoding = {
+    public static final char[] WINANSI_ENCODING = {
         // not used until char 32
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x20
@@ -143,7 +156,8 @@ public class Glyphs {
              'n', 'o', // 0x70
         'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '\u007b', '\u007c', '\u007d',
              '\u007e', '\u2022', // 0x80
-        '\u20ac', '\u2022', '\u201a', '\u0192', '\u201e', '\u2026', '\u2020', '\u2021', '\u02c6', '\u2030', '\u0160', '\u2039', '\u0152', '\u2022',
+        '\u20ac', '\u2022', '\u201a', '\u0192', '\u201e', '\u2026', '\u2020',
+             '\u2021', '\u02c6', '\u2030', '\u0160', '\u2039', '\u0152', '\u2022',
              '\u017d', '\u2022', // 0x90
         '\u2022', '\u2018',                             // quoteleft
         '\u2019',                                       // quoteright
@@ -158,8 +172,8 @@ public class Glyphs {
              '\u00a6', '\u00a7', '\u00a8', '\u00a9', '\u00aa', '\u00ab',
              '\u00ac', '\u00ad',  '\u00ae', '\u00af', // 0xb0
         '\u00b0', '\u00b1', '\u00b2', '\u00b3', '\u00b4',
-             '\u00b5',                                  // This is hand-coded, the rest is assumption
-        '\u00b6',                                       // and *might* not be correct...
+             '\u00b5',                      // This is hand-coded, the rest is assumption
+        '\u00b6',                           // and *might* not be correct...
         '\u00b7', '\u00b8', '\u00b9', '\u00ba', '\u00bb', '\u00bc', '\u00bd',
              '\u00be', '\u00bf', // 0xc0
         '\u00c0', '\u00c1', '\u00c2', '\u00c3', '\u00c4', '\u00c5', // Aring
@@ -179,8 +193,11 @@ public class Glyphs {
              '\u00fc', '\u00fd', '\u00fe', '\u00ff'
     };
 
-    static String[] unicode_glyphs = {
-              "\u0041", "A",
+    /**
+     * List of unicode glyphs
+     */
+    public static final String[] UNICODE_GLYPHS = {
+        "\u0041", "A",
         "\u00C6", "AE",
         "\u01FC", "AEacute",
         "\uF7E6", "AEsmall",
@@ -1233,39 +1250,38 @@ public class Glyphs {
         "\uF730", "zerooldstyle",
         "\u2070", "zerosuperior",
         "\u03B6", "zeta"
-
     };
 
     /**
      * Return the glyphname from a string,
      * eg, glyphToString("\\") returns "backslash"
+     *
+     * @param name glyph to evaluate
+     * @return the name of the glyph
      */
-    public static String glyphToString(String name) {
-        String ret = "";
-        int i = unicode_glyphs.length;
-        for (int j = 0; j < i; j += 2) {
-            if (unicode_glyphs[j + 1].equals(name)) {
-                ret = unicode_glyphs[j];
-                j = i;
+    public static final String glyphToString(String name) {
+        for (int i = 0; i < UNICODE_GLYPHS.length; i += 2) {
+            if (UNICODE_GLYPHS[i + 1].equals(name)) {
+                return UNICODE_GLYPHS[i];
             }
         }
-        return ret;
+        return "";
     }
 
     /**
      * Return the string representation of a glyphname,
      * eg stringToGlyph("backslash") returns "\\"
+     *
+     * @param name name of the glyph
+     * @return the string representation
      */
     public static String stringToGlyph(String name) {
-        String ret = "";
-        int i = unicode_glyphs.length;
-        for (int j = 0; j < i; j += 2) {
-            if (unicode_glyphs[j].equals(name)) {
-                ret = unicode_glyphs[j + 1];
-                j = i;
+        for (int i = 0; i < UNICODE_GLYPHS.length; i += 2) {
+            if (UNICODE_GLYPHS[i].equals(name)) {
+                return UNICODE_GLYPHS[i + 1];
             }
         }
-        return ret;
+        return "";
     }
 
 }
diff --git a/src/org/apache/fop/fonts/PFMFile.java b/src/org/apache/fop/fonts/PFMFile.java
deleted file mode 100644 (file)
index 9dce844..0000000
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
- * $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.fonts;
-
-import java.io.*;
-import java.util.HashMap;
-
-/**
- * This class represents a PFM file (or parts of it) as a Java object.
- *
- * @author  jeremias.maerki@outline.ch
- */
-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;
-
-    // Extension stuff
-    // ---
-
-    // Extend Text Metrics
-    private int etmCapHeight;
-    private int etmXHeight;
-    private int etmLowerCaseAscent;
-    private int etmLowerCaseDescent;
-
-    // Extent table
-    private int[] extentTable;
-
-    private HashMap kerningTab;
-    public PFMFile() {
-        kerningTab = new HashMap();
-    }
-
-    /**
-     * 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);
-        PFMInputStream in = new PFMInputStream(bufin);
-        int version = in.readShort();
-        long filesize = in.readInt();
-        bufin.reset();
-
-        byte[] buf = new byte[(int)filesize];
-        bufin.read(buf, 0, (int)filesize);
-
-        bufin = new ByteArrayInputStream(buf);
-        in = new PFMInputStream(bufin);
-        loadHeader(in);
-        loadExtension(in);
-    }
-
-    /**
-     * 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();
-        inStream.skip(2);
-        dfWeight = inStream.readShort();
-        dfCharSet = inStream.readByte();
-        inStream.skip(4);
-        dfPitchAndFamily = inStream.readByte();
-        dfAvgWidth = inStream.readShort();
-        dfMaxWidth = inStream.readShort();
-        dfFirstChar = inStream.readByte();
-        dfLastChar = inStream.readByte();
-        inStream.skip(8);
-        long faceOffset = inStream.readInt();
-
-        inStream.reset();
-        inStream.skip(faceOffset);
-        windowsName = inStream.readString();
-
-        inStream.reset();
-        inStream.skip(117);
-    }
-
-    /**
-     * 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();
-        long extentTableOffset = inStream.readInt();
-        inStream.skip(4);
-        long kernPairOffset = inStream.readInt();
-        long kernTrackOffset = inStream.readInt();
-        long driverInfoOffset = inStream.readInt();
-
-        if (kernPairOffset > 0) {
-            inStream.reset();
-            inStream.skip(kernPairOffset);
-            loadKernPairs(inStream);
-        }
-
-        inStream.reset();
-        inStream.skip(driverInfoOffset);
-        postscriptName = inStream.readString();
-
-        if (extMetricsOffset != 0) {
-            inStream.reset();
-            inStream.skip(extMetricsOffset);
-            loadExtMetrics(inStream);
-        }
-        if (extentTableOffset != 0) {
-            inStream.reset();
-            inStream.skip(extentTableOffset);
-            loadExtentTable(inStream);
-        }
-
-    }
-
-    /**
-     * 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];
-
-            HashMap adjTab = (HashMap)kerningTab.get(new Integer(g1));
-            if (adjTab == null)
-                adjTab = new HashMap();
-            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 {
-        int size = inStream.readShort();
-        inStream.skip(12);
-        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 + 1];
-        dfMinWidth = dfMaxWidth;
-        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.
-     */
-    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 HashMap 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).
-     */
-    public short getCharSet() {
-        return dfCharSet;
-    }
-
-    /**
-     * 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";
-        }
-    }
-
-    /**
-     * 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.
-     */
-    public short getLastChar() {
-        return dfLastChar;
-    }
-
-    /**
-     * 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.
-     */
-    public int getXHeight() {
-        return etmXHeight;
-    }
-
-    /**
-     * 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.
-     */
-    public int getLowerCaseDescent() {
-        return etmLowerCaseDescent;
-    }
-
-    /**
-     * 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.
-     */
-    public int[] getFontBBox() {
-        int[] bbox = new int[4];
-
-        // Just guessing....
-        if (!getIsProportional() && (dfAvgWidth == dfMaxWidth)) {
-            bbox[0] = -20;
-        } else {
-            bbox[0] = -100;
-        }
-        bbox[1] = -(getLowerCaseDescent() + 5);
-        bbox[2] = dfMaxWidth + 10;
-        bbox[3] = getLowerCaseAscent() + 5;
-        return bbox;
-    }
-
-    /**
-     * 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;
-        }
-        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.
-     */
-    public int getStemV() {
-        // Just guessing....
-        if (dfItalic != 0) {
-            return (int)Math.round(dfMinWidth * 0.25);
-        } else {
-            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.
-     */
-    public int getItalicAngle() {
-        if (dfItalic != 0) {
-            return -16;    // Just guessing....
-        } else {
-            return 0;
-        }
-    }
-
-    /**
-     * 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];
-    }
-
-}
diff --git a/src/org/apache/fop/fonts/PFMInputStream.java b/src/org/apache/fop/fonts/PFMInputStream.java
deleted file mode 100644 (file)
index e956070..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * $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.fonts;
-
-import java.io.*;
-
-/**
- * This is a helper class for reading PFM files. It defines functions for
- * extracting specific values out of the stream.
- *
- * @author  jeremias.maerki@outline.ch
- */
-public class PFMInputStream extends java.io.FilterInputStream {
-
-    DataInputStream inStream;
-
-    /**
-     * Constructs a PFMInputStream based on an InputStream representing the PFM file.
-     *
-     * @param     inStream The stream from which to read the PFM file.
-     */
-    public PFMInputStream(InputStream in) {
-        super(in);
-        inStream = new DataInputStream(in);
-    }
-
-    /**
-     * Parses a one byte value out of the stream.
-     *
-     * @return The value extracted.
-     */
-    public short readByte() throws IOException {
-        short s = inStream.readByte();
-        // Now, we've got to trick Java into forgetting the sign
-        int s1 = (((s & 0xF0) >>> 4) << 4) + (s & 0x0F);
-        return (short)s1;
-    }
-
-    /**
-     * Parses a two byte value out of the stream.
-     *
-     * @return The value extracted.
-     */
-    public int readShort() throws IOException {
-        int i = inStream.readShort();
-
-        // Change byte order
-        int high = (i & 0xFF00) >>> 8;
-        int low = (i & 0x00FF) << 8;
-        return low + high;
-    }
-
-    /**
-     * Parses a four byte value out of the stream.
-     *
-     * @return The value extracted.
-     */
-    public long readInt() throws IOException {
-        int i = inStream.readInt();
-
-        // Change byte order
-        int i1 = (i & 0xFF000000) >>> 24;
-        int i2 = (i & 0x00FF0000) >>> 8;
-        int i3 = (i & 0x0000FF00) << 8;
-        int i4 = (i & 0x000000FF) << 24;
-        return i1 + i2 + i3 + i4;
-    }
-
-    /**
-     * Parses a zero-terminated string out of the stream.
-     *
-     * @return The value extracted.
-     */
-    public String readString() throws IOException {
-        InputStreamReader reader = new InputStreamReader(in, "ISO-8859-1");
-        StringBuffer buf = new StringBuffer();
-        int ch = reader.read();
-        while (ch != 0) {
-            buf.append((char)ch);
-            ch = reader.read();
-        }
-        return buf.toString();
-    }
-
-}
index d950718a67b46e8575671f89c1cc5ee606a2936e..cef0b414bed4f8816a081d296bfae2c1c52006d7 100644 (file)
@@ -351,9 +351,9 @@ public class TTFFile extends AbstractLogEnabled {
         // Can't just index the winAnsiEncoding when inserting widths
         // same char (eg bullet) is repeated more than one place
         ansiIndex = new java.util.HashMap();
-        for (int i = 32; i < Glyphs.winAnsiEncoding.length; i++) {
+        for (int i = 32; i < Glyphs.WINANSI_ENCODING.length; i++) {
             Integer ansi = new Integer(i);
-            Integer uni = new Integer((int)Glyphs.winAnsiEncoding[i]);
+            Integer uni = new Integer((int)Glyphs.WINANSI_ENCODING[i]);
 
             List v = (List)ansiIndex.get(uni);
             if (v == null) {
@@ -761,8 +761,8 @@ public class TTFFile extends AbstractLogEnabled {
         switch (postFormat) {
         case 0x00010000:
             getLogger().debug("Postscript format 1");
-            for (i = 0; i < Glyphs.mac_glyph_names.length; i++) {
-                mtxTab[i].setName(Glyphs.mac_glyph_names[i]);
+            for (i = 0; i < Glyphs.MAC_GLYPH_NAMES.length; i++) {
+                mtxTab[i].setName(Glyphs.MAC_GLYPH_NAMES[i]);
             }
             break;
         case 0x00020000:
@@ -791,7 +791,7 @@ public class TTFFile extends AbstractLogEnabled {
 
             for (i = 0; i < l; i++) {
                 if (mtxTab[i].getIndex() < NMACGLYPHS) {
-                    mtxTab[i].setName(Glyphs.mac_glyph_names[mtxTab[i].getIndex()]);
+                    mtxTab[i].setName(Glyphs.MAC_GLYPH_NAMES[mtxTab[i].getIndex()]);
                 } else {
                     k = mtxTab[i].getIndex() - NMACGLYPHS;
 
@@ -1150,8 +1150,8 @@ public class TTFFile extends AbstractLogEnabled {
      */
     private Integer[] unicodeToWinAnsi(int unicode) {
         List ret = new java.util.ArrayList();
-        for (int i = 32; i < Glyphs.winAnsiEncoding.length; i++) {
-            if (unicode == Glyphs.winAnsiEncoding[i]) {
+        for (int i = 32; i < Glyphs.WINANSI_ENCODING.length; i++) {
+            if (unicode == Glyphs.WINANSI_ENCODING[i]) {
                 ret.add(new Integer(i));
             }
         }
index 14fd89d7d675404fccf1905279aab19c6ffcca57..cb6cfb09cbd144d9c7f260543113163cab56c8e2 100644 (file)
@@ -1,33 +1,40 @@
 /*
  * $Id$
- * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
+ * Copyright (C) 2001-2002 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;
 
-import java.io.*;
-import org.w3c.dom.*;
-import org.apache.xerces.dom.*;
-import org.apache.xml.serialize.*;
-import org.apache.xalan.xslt.*;
-import org.apache.fop.fonts.*;
-import java.util.HashMap;
-import java.util.ArrayList;
+import java.io.File;
+import java.io.InputStream;
+import java.io.IOException;
+import java.util.Map;
+import java.util.List;
 import java.util.Iterator;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+//Avalon
+import org.apache.avalon.framework.CascadingRuntimeException;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.logger.Logger;
+import org.apache.avalon.framework.logger.ConsoleLogger;
+
+//FOP
+import org.apache.fop.fonts.type1.PFMFile;
 
 /**
  * A tool which reads PFM files from Adobe Type 1 fonts and creates
  * XML font metrics file for use in FOP.
- *
- * @author  jeremias.maerki@outline.ch
  */
-public class PFMReader {
-    private boolean invokedStandalone = false;
-
-    public PFMReader() { }
-
+public class PFMReader extends AbstractLogEnabled {
+    
     /**
      * Parse commandline arguments. put options in the HashMap and return
      * arguments in the String array
@@ -35,8 +42,8 @@ public class PFMReader {
      * 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(HashMap options, String[] args) {
-        ArrayList arguments = new ArrayList();
+    private static String[] parseArguments(Map options, String[] args) {
+        List arguments = new java.util.ArrayList();
         for (int i = 0; i < args.length; i++) {
             if (args[i].startsWith("-")) {
                 if ((i + 1) < args.length && !args[i + 1].startsWith("-")) {
@@ -50,17 +57,19 @@ public class PFMReader {
             }
         }
 
-        return (String[])arguments.toArray(new String[0]);
+        return (String[])arguments.toArray(new String[arguments.size()]);
     }
 
-    private static final 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");
+    private void displayUsage() {
+        getLogger().info(
+            " java org.apache.fop.fonts.apps.PFMReader [options] metricfile.pfm xmlfile.xml");
+        getLogger().info(" where options can be:");
+        getLogger().info(" -fn <fontname>");
+        getLogger().info("     default is to use the fontname in the .pfm file, but");
+        getLogger().info("     you can override that name to make sure that the");
+        getLogger().info("     embedded font is used (if you're embedding fonts)");
+        getLogger().info("     instead of installed fonts when viewing documents ");
+        getLogger().info("     with Acrobat Reader.");
     }
 
 
@@ -89,14 +98,20 @@ public class PFMReader {
         String className = null;
         String fontName = null;
 
-        HashMap options = new HashMap();
+        Map options = new java.util.HashMap();
         String[] arguments = parseArguments(options, args);
 
         PFMReader app = new PFMReader();
-        app.invokedStandalone = true;
+        Logger log;
+        if (options.get("-d") != null) {
+            log = new ConsoleLogger(ConsoleLogger.LEVEL_DEBUG);
+        } else {
+            log = new ConsoleLogger(ConsoleLogger.LEVEL_INFO);
+        }
+        app.enableLogging(log);
 
-        System.out.println("PFM Reader v1.1");
-        System.out.println();
+        log.info("PFM Reader v1.1a");
+        log.info("");
 
         if (options.get("-ef") != null) {
             embFile = (String)options.get("-ef");
@@ -116,16 +131,21 @@ public class PFMReader {
 
         if (arguments.length != 2 || options.get("-h") != null
             || options.get("-help") != null || options.get("--help") != null) {
-            displayUsage();
+            app.displayUsage();
         } else {
-            PFMFile pfm = app.loadPFM(arguments[0]);
-            if (pfm != null) {
-                app.preview(pfm);
-
-                org.w3c.dom.Document doc = app.constructFontXML(pfm,
-                        fontName, className, embResource, embFile);
-
-                app.writeFontXML(doc, arguments[1]);
+            try {
+                PFMFile pfm = app.loadPFM(arguments[0]);
+                if (pfm != null) {
+                    app.preview(pfm);
+    
+                    Document doc = app.constructFontXML(pfm,
+                            fontName, className, embResource, embFile);
+    
+                    app.writeFontXML(doc, arguments[1]);
+                }
+            } catch (Exception e) {
+                log.error("Error while building XML font metrics file", e);
+                System.exit(-1);
             }
         }
     }
@@ -136,18 +156,19 @@ public class PFMReader {
      *
      * @param   filename The filename of the PFM file.
      * @return  The PFM as an object.
+     * @throws IOException In case of an I/O problem
      */
-    public PFMFile loadPFM(String filename) {
+    public PFMFile loadPFM(String filename) throws IOException {
+        getLogger().info("Reading " + filename + "...");
+        getLogger().info("");
+        InputStream in = new java.io.FileInputStream(filename);
         try {
-            System.out.println("Reading " + filename + "...");
-            System.out.println();
-            FileInputStream in = new FileInputStream(filename);
             PFMFile pfm = new PFMFile();
+            setupLogger(pfm);
             pfm.load(in);
             return pfm;
-        } catch (Exception e) {
-            e.printStackTrace();
-            return null;
+        } finally {
+            in.close();
         }
     }
 
@@ -157,34 +178,19 @@ public class PFMReader {
      * @param   pfm The PFM file to preview.
      */
     public void preview(PFMFile pfm) {
-        PrintStream out = System.out;
-
-        out.print("Font: ");
-        out.println(pfm.getWindowsName());
-        out.print("Name: ");
-        out.println(pfm.getPostscriptName());
-        out.print("CharSet: ");
-        out.println(pfm.getCharSetName());
-        out.print("CapHeight: ");
-        out.println(pfm.getCapHeight());
-        out.print("XHeight: ");
-        out.println(pfm.getXHeight());
-        out.print("LowerCaseAscent: ");
-        out.println(pfm.getLowerCaseAscent());
-        out.print("LowerCaseDescent: ");
-        out.println(pfm.getLowerCaseDescent());
-        out.print("Having widths for ");
-        out.print(pfm.getLastChar() - pfm.getFirstChar());
-        out.print(" characters (");
-        out.print(pfm.getFirstChar());
-        out.print("-");
-        out.print(pfm.getLastChar());
-        out.println(").");
-        out.print("for example: Char ");
-        out.print(pfm.getFirstChar());
-        out.print(" has a width of ");
-        out.println(pfm.getCharWidth(pfm.getFirstChar()));
-        out.println();
+        getLogger().info("Font: " + pfm.getWindowsName());
+        getLogger().info("Name: " + pfm.getPostscriptName());
+        getLogger().info("CharSet: " + pfm.getCharSetName());
+        getLogger().info("CapHeight: " + pfm.getCapHeight());
+        getLogger().info("XHeight: " + pfm.getXHeight());
+        getLogger().info("LowerCaseAscent: " + pfm.getLowerCaseAscent());
+        getLogger().info("LowerCaseDescent: " + pfm.getLowerCaseDescent());
+        getLogger().info("Having widths for " + (pfm.getLastChar() - pfm.getFirstChar()) 
+                    + " characters (" + pfm.getFirstChar()
+                    + "-" + pfm.getLastChar() + ").");
+        getLogger().info("for example: Char " + pfm.getFirstChar()
+                    + " has a width of " + pfm.getCharWidth(pfm.getFirstChar()));
+        getLogger().info("");
     }
 
     /**
@@ -194,34 +200,43 @@ public class PFMReader {
      * @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();
+        getLogger().info("Writing xml font file " + target + "...");
+        getLogger().info("");
 
         try {
-            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.serialize(doc.getDocumentElement());
-            out.close();
+            TransformerFactory factory = TransformerFactory.newInstance();
+            Transformer transformer = factory.newTransformer();
+            transformer.transform(
+                    new javax.xml.transform.dom.DOMSource(doc),
+                    new javax.xml.transform.stream.StreamResult(new File(target)));
         } catch (Exception e) {
-            e.printStackTrace();
+            throw new CascadingRuntimeException("Error while serializing XML font metric file", e);
         }
     }
 
     /**
      * Generates the font metrics file from the PFM file.
      *
-     * @param   pfm The PFM file to generate the font metrics from.
+     * @param pfm The PFM file to generate the font metrics from.
+     * @param fontName name of the font
+     * @param className class name for the font
+     * @param resource path to the font as embedded resource
+     * @param file path to the font as file
      * @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();
+        getLogger().info("Creating xml font file...");
+        getLogger().info("");
 
-        Document doc = new DocumentImpl();
+        Document doc;
+        try {
+            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+            doc = factory.newDocumentBuilder().newDocument();
+        } catch (javax.xml.parsers.ParserConfigurationException e) {
+            getLogger().error("Can't create DOM implementation", e);
+            return null;
+        }
         Element root = doc.createElement("font-metrics");
         doc.appendChild(root);
         root.setAttribute("type", "TYPE1");
@@ -275,10 +290,8 @@ public class PFMReader {
         Element bbox = doc.createElement("bbox");
         root.appendChild(bbox);
         int[] bb = pfm.getFontBBox();
-        String[] names = {
-            "left", "bottom", "right", "top"
-        };
-        for (int i = 0; i < 4; i++) {
+        final String[] names = {"left", "bottom", "right", "top"};
+        for (int i = 0; i < names.length; i++) {
             el = doc.createElement(names[i]);
             bbox.appendChild(el);
             value = new Integer(bb[i]);
@@ -323,16 +336,17 @@ public class PFMReader {
 
 
         // Get kerning
-        for (Iterator enum = pfm.getKerning().keySet().iterator();
-                enum.hasNext(); ) {
+        Iterator enum = pfm.getKerning().keySet().iterator();
+        while (enum.hasNext()) {
             Integer kpx1 = (Integer)enum.next();
             el = doc.createElement("kerning");
             el.setAttribute("kpx1", kpx1.toString());
             root.appendChild(el);
             Element el2 = null;
 
-            HashMap h2 = (HashMap)pfm.getKerning().get(kpx1);
-            for (Iterator enum2 = h2.keySet().iterator(); enum2.hasNext(); ) {
+            Map h2 = (Map)pfm.getKerning().get(kpx1);
+            Iterator enum2 = h2.keySet().iterator();
+            while (enum2.hasNext()) {
                 Integer kpx2 = (Integer)enum2.next();
                 el2 = doc.createElement("pair");
                 el2.setAttribute("kpx2", kpx2.toString());
@@ -349,10 +363,11 @@ public class PFMReader {
         StringBuffer esc = new StringBuffer();
 
         for (int i = 0; i < str.length(); i++) {
-            if (str.charAt(i) == '\\')
+            if (str.charAt(i) == '\\') {
                 esc.append("\\\\");
-            else
+            } else {
                 esc.append(str.charAt(i));
+            }
         }
 
         return esc.toString();
index 2aac271d98aca5db2a2208e7d9372f5fda7daf55..239221492fd43bbc7974feaaa76e038894cf2320 100644 (file)
@@ -1,40 +1,39 @@
 /*
  * $Id$
- * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
+ * Copyright (C) 2001-2002 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;
 
-import java.io.FileWriter;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.apache.xerces.dom.DocumentImpl;
-import org.apache.xml.serialize.OutputFormat;
-import org.apache.xml.serialize.XMLSerializer;
-import org.apache.fop.fonts.*;
+import java.io.File;
+import java.io.IOException;
 import java.util.Map;
 import java.util.List;
 import java.util.Iterator;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
 
+//Avalon
+import org.apache.avalon.framework.CascadingRuntimeException;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
 import org.apache.avalon.framework.logger.ConsoleLogger;
 import org.apache.avalon.framework.logger.Logger;
 
+//FOP
+import org.apache.fop.fonts.FontFileReader;
+import org.apache.fop.fonts.TTFCmapEntry;
+import org.apache.fop.fonts.TTFFile;
+
 /**
  * A tool which reads TTF files and generates
  * XML font metrics file for use in FOP.
- *
  */
-public class TTFReader {
-
-    private boolean invokedStandalone = false;
-    private Logger log;
-
-    public TTFReader() {}
-
-    public void setLogger(Logger l) {
-        log = l;
-    }
+public class TTFReader extends AbstractLogEnabled {
 
     /**
      * Parse commandline arguments. put options in the HashMap and return
@@ -47,7 +46,7 @@ public class TTFReader {
         List arguments = new java.util.ArrayList();
         for (int i = 0; i < args.length; i++) {
             if (args[i].startsWith("-")) {
-                if ((i + 1) < args.length &&!args[i + 1].startsWith("-")) {
+                if ((i + 1) < args.length && !args[i + 1].startsWith("-")) {
                     options.put(args[i], args[i + 1]);
                     i++;
                 } else {
@@ -62,26 +61,28 @@ public class TTFReader {
     }
 
 
-    private static final 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");
+    private void displayUsage() {
+        getLogger().info(
+                " java org.apache.fop.fonts.apps.TTFReader [options] fontfile.ttf xmlfile.xml");
+        getLogger().info(" where options can be:");
+        getLogger().info("-enc ansi");
+        getLogger().info("     With this option you create a WinAnsi encoded font.");
+        getLogger().info("     The default is to create a CID keyed font.");
+        getLogger().info("     If you're not going to use characters outside the");
+        getLogger().info("     pdfencoding range (almost the same as iso-8889-1)");
+        getLogger().info("     you can add this option.");
+        getLogger().info("-ttcname <fontname>");
+        getLogger().info("     If you're reading data from a TrueType Collection");
+        getLogger().info("     (.ttc file) you must specify which font from the");
+        getLogger().info("     collection you will read metrics from. If you read");
+        getLogger().info("     from a .ttc file without this option, the fontnames");
+        getLogger().info("      will be listed for you.");
+        getLogger().info(" -fn <fontname>");
+        getLogger().info("     default is to use the fontname in the .ttf file, but");
+        getLogger().info("     you can override that name to make sure that the");
+        getLogger().info("     embedded font is used (if you're embedding fonts)");
+        getLogger().info("     instead of installed fonts when viewing documents ");
+        getLogger().info("     with Acrobat Reader.");
     }
 
 
@@ -118,66 +119,77 @@ public class TTFReader {
         int level = ConsoleLogger.LEVEL_INFO;
         if (options.get("-d") != null) {
             String lev = (String)options.get("-d");
-            if(lev.equals("DEBUG")) {
+            if (lev.equals("DEBUG")) {
                 level = ConsoleLogger.LEVEL_DEBUG;
-            } else if(lev.equals("INFO")) {
+            } else if (lev.equals("INFO")) {
                 level = ConsoleLogger.LEVEL_INFO;
             }
         }
         Logger log = new ConsoleLogger(level);
 
         TTFReader app = new TTFReader();
-        app.setLogger(log);
-        app.invokedStandalone = true;
+        app.enableLogging(log);
 
-        log.info("TTF Reader v1.1.2");
+        log.info("TTF Reader v1.1.3");
 
         if (options.get("-enc") != null) {
             String enc = (String)options.get("-enc");
-            if ("ansi".equals(enc))
+            if ("ansi".equals(enc)) {
                 isCid = false;
+            }
         }
 
-        if (options.get("-ttcname") != null)
+        if (options.get("-ttcname") != null) {
             ttcName = (String)options.get("-ttcname");
+        }
 
-        if (options.get("-ef") != null)
+        if (options.get("-ef") != null) {
             embFile = (String)options.get("-ef");
+        }
 
-        if (options.get("-er") != null)
+        if (options.get("-er") != null) {
             embResource = (String)options.get("-er");
+        }
 
-        if (options.get("-fn") != null)
+        if (options.get("-fn") != null) {
             fontName = (String)options.get("-fn");
+        }
 
-        if (options.get("-cn") != null)
+        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)
-                    log.info("Creating CID encoded metrics");
-                else
-                    log.info("Creating WinAnsi encoded metrics");
-
-                if (doc != null) {
-                    app.writeFontXML(doc, arguments[1]);
+            || options.get("-help") != null || options.get("--help") != null) {
+            app.displayUsage();
+        } else {
+            try {
+                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) {
+                        log.info("Creating CID encoded metrics");
+                    } else {
+                        log.info("Creating WinAnsi encoded metrics");
+                    }
+    
+                    if (doc != null) {
+                        app.writeFontXML(doc, arguments[1]);
+                    }
+    
+                    if (ttf.isEmbeddable()) {
+                        log.info("This font contains no embedding license restrictions");
+                    } else {
+                        log.info("** Note: This font contains license retrictions for\n"
+                               + "         embedding. This font shouldn't be embedded.");
+                    }
                 }
-
-                if (ttf.isEmbeddable())
-                    log.info("This font contains no embedding license restrictions");
-                else
-                    log.info("** Note: This font contains license retrictions for\n"
-                                       + "         embedding. This font shouldn't be embedded.");
-
+            } catch (Exception e) {
+                log.error("Error while building XML font metrics file", e);
+                System.exit(-1);
             }
         }
     }
@@ -185,22 +197,19 @@ public class TTFReader {
     /**
      * Read a TTF file and returns it as an object.
      *
-     * @param   filename The filename of the PFM file.
-     * @return  The TTF as an object.
+     * @param  fileName The filename of the TTF file.
+     * @param  fontName The name of the font
+     * @return The TTF as an object, null if the font is incompatible.
+     * @throws IOException In case of an I/O problem
      */
-    public TTFFile loadTTF(String fileName, String fontName) {
+    public TTFFile loadTTF(String fileName, String fontName) throws IOException {
         TTFFile ttfFile = new TTFFile();
-        ttfFile.enableLogging(log);
-        try {
-            log.info("Reading " + fileName + "...");
+        setupLogger(ttfFile);
+        getLogger().info("Reading " + fileName + "...");
 
-            FontFileReader reader = new FontFileReader(fileName);
-            boolean supported = ttfFile.readFont(reader, fontName);
-            if(!supported) {
-                return null;
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
+        FontFileReader reader = new FontFileReader(fileName);
+        boolean supported = ttfFile.readFont(reader, fontName);
+        if (!supported) {
             return null;
         }
         return ttfFile;
@@ -214,39 +223,52 @@ public class TTFReader {
      * @param   target The target filename for the XML file.
      */
     public void writeFontXML(org.w3c.dom.Document doc, String target) {
-        log.info("Writing xml font file " + target + "...");
+        getLogger().info("Writing xml font file " + target + "...");
 
         try {
-            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.serialize(doc.getDocumentElement());
-            out.close();
+            TransformerFactory factory = TransformerFactory.newInstance();
+            Transformer transformer = factory.newTransformer();
+            transformer.transform(
+                    new javax.xml.transform.dom.DOMSource(doc),
+                    new javax.xml.transform.stream.StreamResult(new File(target)));
         } catch (Exception e) {
-            e.printStackTrace();
+            throw new CascadingRuntimeException(
+                    "Error while serializing XML font metrics file", e);
         }
     }
 
     /**
      * 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.
+     * @param ttf The PFM file to generate the font metrics from.
+     * @param fontName Name of the font
+     * @param className Class name for the font
+     * @param resource path to the font as embedded resource
+     * @param file path to the font as file
+     * @param isCid True if the font is CID encoded
+     * @param ttcName Name of the TrueType Collection
+     * @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) {
-        log.info("Creating xml font file...");
+        getLogger().info("Creating xml font file...");
 
-        Document doc = new DocumentImpl();
+        Document doc;
+        try {
+            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+            doc = factory.newDocumentBuilder().newDocument();
+        } catch (javax.xml.parsers.ParserConfigurationException e) {
+            getLogger().error("Can't create DOM implementation", e);
+            return null;
+        }
         Element root = doc.createElement("font-metrics");
         doc.appendChild(root);
-        if (isCid)
+        if (isCid) {
             root.setAttribute("type", "TYPE0");
-        else
+        } else {
             root.setAttribute("type", "TRUETYPE");
+        }
 
         Element el = doc.createElement("font-name");
         root.appendChild(el);
@@ -257,17 +279,20 @@ public class TTFReader {
 
         String s = stripWhiteSpace(ttf.getPostscriptName());
 
-        if (fontName != null)
+        if (fontName != null) {
             el.appendChild(doc.createTextNode(stripWhiteSpace(fontName)));
-        else
+        } else {
             el.appendChild(doc.createTextNode(s));
+        }
 
         el = doc.createElement("embed");
         root.appendChild(el);
-        if (file != null && ttf.isEmbeddable())
+        if (file != null && ttf.isEmbeddable()) {
             el.setAttribute("file", file);
-        if (resource != null && ttf.isEmbeddable())
+        }
+        if (resource != null && ttf.isEmbeddable()) {
             el.setAttribute("class", resource);
+        }
 
         el = doc.createElement("cap-height");
         root.appendChild(el);
@@ -288,10 +313,8 @@ public class TTFReader {
         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++) {
+        final String[] names = {"left", "bottom", "right", "top"};
+        for (int i = 0; i < names.length; i++) {
             el = doc.createElement(names[i]);
             bbox.appendChild(el);
             el.appendChild(doc.createTextNode(String.valueOf(bb[i])));
@@ -322,91 +345,117 @@ public class TTFReader {
         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"));
-
-            el = doc.createElement("default-width");
-            mel.appendChild(el);
-            el.appendChild(doc.createTextNode("0"));
-
-            el = doc.createElement("bfranges");
-            mel.appendChild(el);
-            for (Iterator e = ttf.getCMaps().listIterator();
-                    e.hasNext(); ) {
-                TTFCmapEntry ce = (TTFCmapEntry)e.next();
-                Element el2 = doc.createElement("bf");
-                el.appendChild(el2);
-                el2.setAttribute("us", String.valueOf(ce.getUnicodeStart()));
-                el2.setAttribute("ue", String.valueOf(ce.getUnicodeEnd()));
-                el2.setAttribute("gi", String.valueOf(ce.getGlyphStartIndex()));
-            }
-
-            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", String.valueOf(wx[i]));
-                el.appendChild(wxel);
-            }
+            generateDOM4MultiByteExtras(root, ttf, isCid);
         } else {
             // Fill in extras for singlebyte fonts
             el.appendChild(doc.createTextNode("TRUETYPE"));
 
-            Element sel = doc.createElement("singlebyte-extras");
-            root.appendChild(sel);
+            generateDOM4SingleByteExtras(root, ttf, isCid);
+        }
 
-            el = doc.createElement("encoding");
-            sel.appendChild(el);
-            el.appendChild(doc.createTextNode(ttf.getCharSetName()));
+        generateDOM4Kerning(root, ttf, isCid);
 
-            el = doc.createElement("first-char");
-            sel.appendChild(el);
-            el.appendChild(doc.createTextNode(String.valueOf(ttf.getFirstChar())));
+        return doc;
+    }
 
-            el = doc.createElement("last-char");
-            sel.appendChild(el);
-            el.appendChild(doc.createTextNode(String.valueOf(ttf.getLastChar())));
+    private void generateDOM4MultiByteExtras(Element parent, TTFFile ttf, boolean isCid) {
+        Element el;
+        Document doc = parent.getOwnerDocument();
+        
+        Element mel = doc.createElement("multibyte-extras");
+        parent.appendChild(mel);
+
+        el = doc.createElement("cid-type");
+        mel.appendChild(el);
+        el.appendChild(doc.createTextNode("CIDFontType2"));
+
+        el = doc.createElement("default-width");
+        mel.appendChild(el);
+        el.appendChild(doc.createTextNode("0"));
+
+        el = doc.createElement("bfranges");
+        mel.appendChild(el);
+        Iterator e = ttf.getCMaps().listIterator();
+        while (e.hasNext()) {
+            TTFCmapEntry ce = (TTFCmapEntry)e.next();
+            Element el2 = doc.createElement("bf");
+            el.appendChild(el2);
+            el2.setAttribute("us", String.valueOf(ce.getUnicodeStart()));
+            el2.setAttribute("ue", String.valueOf(ce.getUnicodeEnd()));
+            el2.setAttribute("gi", String.valueOf(ce.getGlyphStartIndex()));
+        }
 
-            Element widths = doc.createElement("widths");
-            sel.appendChild(widths);
+        el = doc.createElement("cid-widths");
+        el.setAttribute("start-index", "0");
+        mel.appendChild(el);
 
-            for (short i = ttf.getFirstChar(); i <= ttf.getLastChar(); i++) {
-                el = doc.createElement("char");
-                widths.appendChild(el);
-                el.setAttribute("idx", String.valueOf(i));
-                el.setAttribute("wdt", String.valueOf(ttf.getCharWidth(i)));
-            }
+        int[] wx = ttf.getWidths();
+        for (int i = 0; i < wx.length; i++) {
+            Element wxel = doc.createElement("wx");
+            wxel.setAttribute("w", String.valueOf(wx[i]));
+            el.appendChild(wxel);
         }
+    }
+
+    private void generateDOM4SingleByteExtras(Element parent, TTFFile ttf, boolean isCid) {
+        Element el;
+        Document doc = parent.getOwnerDocument();
+
+        Element sel = doc.createElement("singlebyte-extras");
+        parent.appendChild(sel);
+
+        el = doc.createElement("encoding");
+        sel.appendChild(el);
+        el.appendChild(doc.createTextNode(ttf.getCharSetName()));
+
+        el = doc.createElement("first-char");
+        sel.appendChild(el);
+        el.appendChild(doc.createTextNode(String.valueOf(ttf.getFirstChar())));
+
+        el = doc.createElement("last-char");
+        sel.appendChild(el);
+        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++) {
+            el = doc.createElement("char");
+            widths.appendChild(el);
+            el.setAttribute("idx", String.valueOf(i));
+            el.setAttribute("wdt", String.valueOf(ttf.getCharWidth(i)));
+        }
+    }
+    
+    private void generateDOM4Kerning(Element parent, TTFFile ttf, boolean isCid) {
+        Element el;
+        Document doc = parent.getOwnerDocument();
+        
         // Get kerning
         Iterator enum;
-        if (isCid)
+        if (isCid) {
             enum = ttf.getKerning().keySet().iterator();
-        else
+        } else {
             enum = ttf.getAnsiKerning().keySet().iterator();
+        }
 
         while (enum.hasNext()) {
             Integer kpx1 = (Integer)enum.next();
 
             el = doc.createElement("kerning");
             el.setAttribute("kpx1", kpx1.toString());
-            root.appendChild(el);
+            parent.appendChild(el);
             Element el2 = null;
 
             Map h2;
-            if (isCid)
+            if (isCid) {
                 h2 = (Map)ttf.getKerning().get(kpx1);
-            else
+            } else {
                 h2 = (Map)ttf.getAnsiKerning().get(kpx1);
+            }
 
-            for (Iterator enum2 = h2.keySet().iterator(); enum2.hasNext(); ) {
+            Iterator enum2 = h2.keySet().iterator();
+            while (enum2.hasNext()) {
                 Integer kpx2 = (Integer)enum2.next();
                 if (isCid || kpx2.intValue() < 256) {
                     el2 = doc.createElement("pair");
@@ -417,8 +466,6 @@ public class TTFReader {
                 }
             }
         }
-
-        return doc;
     }
 
 
@@ -426,10 +473,14 @@ public class TTFReader {
         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')
+        for (int i = 0; i < ch.length; i++) {
+            if (ch[i] != ' ' 
+                    && ch[i] != '\r' 
+                    && ch[i] != '\n'
+                    && ch[i] != '\t') {
                 stb.append(ch[i]);
+            }
+        }
 
         return stb.toString();
     }
@@ -438,10 +489,11 @@ public class TTFReader {
         StringBuffer esc = new StringBuffer();
 
         for (int i = 0; i < str.length(); i++) {
-            if (str.charAt(i) == '\\')
+            if (str.charAt(i) == '\\') {
                 esc.append("\\\\");
-            else
+            } else {
                 esc.append(str.charAt(i));
+            }
         }
 
         return esc.toString();