From 19fb112824a5dc1c6b2dc7e3d54e79ec7bb46198 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 2 Dec 2002 14:27:58 +0000 Subject: [PATCH] Moved PFM classes to type1 subpackage 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 | 72 ++-- src/org/apache/fop/fonts/PFMFile.java | 407 ------------------- src/org/apache/fop/fonts/PFMInputStream.java | 90 ---- src/org/apache/fop/fonts/TTFFile.java | 14 +- src/org/apache/fop/fonts/apps/PFMReader.java | 213 +++++----- src/org/apache/fop/fonts/apps/TTFReader.java | 402 ++++++++++-------- 6 files changed, 392 insertions(+), 806 deletions(-) delete mode 100644 src/org/apache/fop/fonts/PFMFile.java delete mode 100644 src/org/apache/fop/fonts/PFMInputStream.java diff --git a/src/org/apache/fop/fonts/Glyphs.java b/src/org/apache/fop/fonts/Glyphs.java index 9f5da3b75..0b584d56f 100644 --- a/src/org/apache/fop/fonts/Glyphs.java +++ b/src/org/apache/fop/fonts/Glyphs.java @@ -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 index 9dce84478..000000000 --- a/src/org/apache/fop/fonts/PFMFile.java +++ /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 index e956070ed..000000000 --- a/src/org/apache/fop/fonts/PFMInputStream.java +++ /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(); - } - -} diff --git a/src/org/apache/fop/fonts/TTFFile.java b/src/org/apache/fop/fonts/TTFFile.java index d950718a6..cef0b414b 100644 --- a/src/org/apache/fop/fonts/TTFFile.java +++ b/src/org/apache/fop/fonts/TTFFile.java @@ -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)); } } diff --git a/src/org/apache/fop/fonts/apps/PFMReader.java b/src/org/apache/fop/fonts/apps/PFMReader.java index 14fd89d7d..cb6cfb09c 100644 --- a/src/org/apache/fop/fonts/apps/PFMReader.java +++ b/src/org/apache/fop/fonts/apps/PFMReader.java @@ -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 \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 "); + 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(); diff --git a/src/org/apache/fop/fonts/apps/TTFReader.java b/src/org/apache/fop/fonts/apps/TTFReader.java index 2aac271d9..239221492 100644 --- a/src/org/apache/fop/fonts/apps/TTFReader.java +++ b/src/org/apache/fop/fonts/apps/TTFReader.java @@ -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 "); - 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 \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 "); + 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 "); + 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(); -- 2.39.5