diff options
Diffstat (limited to 'src/org/apache/fop/fonts/apps/TTFReader.java')
-rw-r--r-- | src/org/apache/fop/fonts/apps/TTFReader.java | 402 |
1 files changed, 227 insertions, 175 deletions
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 <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(); |