KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > fonts > apps > PFMReader


1 /*
2  * $Id: PFMReader.java,v 1.7.2.5 2003/02/25 13:13:21 jeremias Exp $
3  * ============================================================================
4  * The Apache Software License, Version 1.1
5  * ============================================================================
6  *
7  * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without modifica-
10  * tion, are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * 3. The end-user documentation included with the redistribution, if any, must
20  * include the following acknowledgment: "This product includes software
21  * developed by the Apache Software Foundation (http://www.apache.org/)."
22  * Alternately, this acknowledgment may appear in the software itself, if
23  * and wherever such third-party acknowledgments normally appear.
24  *
25  * 4. The names "FOP" and "Apache Software Foundation" must not be used to
26  * endorse or promote products derived from this software without prior
27  * written permission. For written permission, please contact
28  * apache@apache.org.
29  *
30  * 5. Products derived from this software may not be called "Apache", nor may
31  * "Apache" appear in their name, without prior written permission of the
32  * Apache Software Foundation.
33  *
34  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
35  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
36  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
37  * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
38  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
39  * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
40  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
41  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
43  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44  * ============================================================================
45  *
46  * This software consists of voluntary contributions made by many individuals
47  * on behalf of the Apache Software Foundation and was originally created by
48  * James Tauber <jtauber@jtauber.com>. For more information on the Apache
49  * Software Foundation, please see <http://www.apache.org/>.
50  */

51 package org.apache.fop.fonts.apps;
52
53 import java.io.File;
54 import java.io.InputStream;
55 import java.util.Map;
56 import java.util.List;
57 import java.util.Iterator;
58
59 import org.w3c.dom.*;
60
61 import org.apache.fop.fonts.type1.PFMFile;
62 import org.apache.avalon.framework.logger.AbstractLogEnabled;
63 import org.apache.avalon.framework.logger.ConsoleLogger;
64 import org.apache.avalon.framework.logger.Logger;
65
66 /**
67  * A tool which reads PFM files from Adobe Type 1 fonts and creates
68  * XML font metrics file for use in FOP.
69  */

70 public class PFMReader extends AbstractLogEnabled {
71     
72     //private boolean invokedStandalone = false;
73

74
75     /**
76      * Parse commandline arguments. put options in the HashMap and return
77      * arguments in the String array
78      * the arguments: -fn Perpetua,Bold -cn PerpetuaBold per.ttf Perpetua.xml
79      * returns a String[] with the per.ttf and Perpetua.xml. The hash
80      * will have the (key, value) pairs: (-fn, Perpetua) and (-cn, PerpetuaBold)
81      */

82     private static String[] parseArguments(Map options, String[] args) {
83         List arguments = new java.util.ArrayList();
84         for (int i = 0; i < args.length; i++) {
85             if (args[i].startsWith("-")) {
86                 if ((i + 1) < args.length &&!args[i + 1].startsWith("-")) {
87                     options.put(args[i], args[i + 1]);
88                     i++;
89                 } else {
90                     options.put(args[i], "");
91                 }
92             } else {
93                 arguments.add(args[i]);
94             }
95         }
96
97         String[] argStrings = new String[arguments.size()];
98         arguments.toArray(argStrings);
99         return argStrings;
100     }
101
102     private void displayUsage() {
103         getLogger().info(" java org.apache.fop.fonts.apps.PFMReader [options] metricfile.pfm xmlfile.xml");
104         getLogger().info(" where options can be:");
105         getLogger().info(" -fn <fontname>");
106         getLogger().info(" default is to use the fontname in the .pfm file, but");
107         getLogger().info(" you can override that name to make sure that the");
108         getLogger().info(" embedded font is used (if you're embedding fonts)");
109         getLogger().info(" instead of installed fonts when viewing documents with Acrobat Reader.");
110     }
111
112
113     /**
114      * The main method for the PFM reader tool.
115      *
116      * @param args Command-line arguments: [options] metricfile.pfm xmlfile.xml
117      * where options can be:
118      * -fn <fontname>
119      * default is to use the fontname in the .pfm file, but you can override
120      * that name to make sure that the embedded font is used instead of installed
121      * fonts when viewing documents with Acrobat Reader.
122      * -cn <classname>
123      * default is to use the fontname
124      * -ef <path to the Type1 .pfb fontfile>
125      * will add the possibility to embed the font. When running fop, fop will look
126      * for this file to embed it
127      * -er <path to Type1 fontfile relative to org/apache/fop/render/pdf/fonts>
128      * you can also include the fontfile in the fop.jar file when building fop.
129      * You can use both -ef and -er. The file specified in -ef will be searched first,
130      * then the -er file.
131      */

132     public static void main(String[] args) {
133         String embFile = null;
134         String embResource = null;
135         String className = null;
136         String fontName = null;
137
138         Map options = new java.util.HashMap();
139         String[] arguments = parseArguments(options, args);
140
141         PFMReader app = new PFMReader();
142         Logger log;
143         if (options.get("-d") != null) {
144             log = new ConsoleLogger(ConsoleLogger.LEVEL_DEBUG);
145         } else {
146             log = new ConsoleLogger(ConsoleLogger.LEVEL_INFO);
147         }
148         app.enableLogging(log);
149         
150         //app.invokedStandalone = true;
151

152         log.info("PFM Reader v1.1");
153         log.info("");
154
155         if (options.get("-ef") != null) {
156             embFile = (String)options.get("-ef");
157         }
158
159         if (options.get("-er") != null) {
160             embResource = (String)options.get("-er");
161         }
162
163         if (options.get("-fn") != null) {
164             fontName = (String)options.get("-fn");
165         }
166
167         if (options.get("-cn") != null) {
168             className = (String)options.get("-cn");
169         }
170
171         if (arguments.length != 2 || options.get("-h") != null
172             || options.get("-help") != null || options.get("--help") != null) {
173             app.displayUsage();
174         } else {
175             PFMFile pfm = app.loadPFM(arguments[0]);
176             if (pfm != null) {
177                 app.preview(pfm);
178
179                 org.w3c.dom.Document doc = app.constructFontXML(pfm,
180                         fontName, className, embResource, embFile);
181
182                 app.writeFontXML(doc, arguments[1]);
183             }
184         }
185     }
186
187
188     /**
189      * Read a PFM file and returns it as an object.
190      *
191      * @param filename The filename of the PFM file.
192      * @return The PFM as an object.
193      */

194     public PFMFile loadPFM(String filename) {
195         try {
196             getLogger().info("Reading " + filename + "...");
197             getLogger().info("");
198             InputStream in = new java.io.FileInputStream(filename);
199             try {
200                 PFMFile pfm = new PFMFile();
201                 setupLogger(pfm);
202                 pfm.load(in);
203                 return pfm;
204             } finally {
205                 in.close();
206             }
207         } catch (Exception e) {
208             e.printStackTrace();
209             return null;
210         }
211     }
212
213     /**
214      * Displays a preview of the PFM file on the console.
215      *
216      * @param pfm The PFM file to preview.
217      */

218     public void preview(PFMFile pfm) {
219         getLogger().info("Font: " + pfm.getWindowsName());
220         getLogger().info("Name: " + pfm.getPostscriptName());
221         getLogger().info("CharSet: " + pfm.getCharSetName());
222         getLogger().info("CapHeight: " + pfm.getCapHeight());
223         getLogger().info("XHeight: " + pfm.getXHeight());
224         getLogger().info("LowerCaseAscent: " + pfm.getLowerCaseAscent());
225         getLogger().info("LowerCaseDescent: " + pfm.getLowerCaseDescent());
226         getLogger().info("Having widths for " + (pfm.getLastChar() - pfm.getFirstChar())
227                     +" characters (" + pfm.getFirstChar()
228                     + "-" + pfm.getLastChar() + ").");
229         getLogger().info("for example: Char " + pfm.getFirstChar()
230                     + " has a width of " + pfm.getCharWidth(pfm.getFirstChar()));
231         getLogger().info("");
232     }
233
234     /**
235      * Writes the generated DOM Document to a file.
236      *
237      * @param doc The DOM Document to save.
238      * @param target The target filename for the XML file.
239      */

240     public void writeFontXML(org.w3c.dom.Document doc, String target) {
241         getLogger().info("Writing xml font file " + target + "...");
242         getLogger().info("");
243
244         try {
245             javax.xml.transform.TransformerFactory.newInstance()
246                 .newTransformer().transform(
247                     new javax.xml.transform.dom.DOMSource(doc),
248                     new javax.xml.transform.stream.StreamResult(new File(target)));
249         } catch (Exception e) {
250             e.printStackTrace();
251         }
252     }
253
254     /**
255      * Generates the font metrics file from the PFM file.
256      *
257      * @param pfm The PFM file to generate the font metrics from.
258      * @return The DOM document representing the font metrics file.
259      */

260     public org.w3c.dom.Document constructFontXML(PFMFile pfm,
261             String fontName, String className, String resource, String file) {
262         getLogger().info("Creating xml font file...");
263         getLogger().info("");
264
265 // Document doc = new DocumentImpl();
266
Document doc;
267         try {
268             doc = javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
269         }
270         catch (javax.xml.parsers.ParserConfigurationException e) {
271             System.out.println("Can't create DOM implementation "+e.getMessage());
272             return null;
273         }
274         Element root = doc.createElement("font-metrics");
275         doc.appendChild(root);
276         root.setAttribute("type", "TYPE1");
277
278         Element el = doc.createElement("font-name");
279         root.appendChild(el);
280         el.appendChild(doc.createTextNode(pfm.getPostscriptName()));
281
282         String s = pfm.getPostscriptName();
283         int pos = s.indexOf("-");
284         if (pos >= 0) {
285             char sb[] = new char[s.length() - 1];
286             s.getChars(0, pos, sb, 0);
287             s.getChars(pos + 1, s.length(), sb, pos);
288             s = new String(sb);
289         }
290
291         el = doc.createElement("embed");
292         root.appendChild(el);
293         if (file != null) {
294             el.setAttribute("file", file);
295         }
296         if (resource != null) {
297             el.setAttribute("class", resource);
298         }
299
300         el = doc.createElement("encoding");
301         root.appendChild(el);
302         el.appendChild(doc.createTextNode(pfm.getCharSetName() + "Encoding"));
303
304         el = doc.createElement("cap-height");
305         root.appendChild(el);
306         Integer value = new Integer(pfm.getCapHeight());
307         el.appendChild(doc.createTextNode(value.toString()));
308
309         el = doc.createElement("x-height");
310         root.appendChild(el);
311         value = new Integer(pfm.getXHeight());
312         el.appendChild(doc.createTextNode(value.toString()));
313
314         el = doc.createElement("ascender");
315         root.appendChild(el);
316         value = new Integer(pfm.getLowerCaseAscent());
317         el.appendChild(doc.createTextNode(value.toString()));
318
319         el = doc.createElement("descender");
320         root.appendChild(el);
321         value = new Integer(-pfm.getLowerCaseDescent());
322         el.appendChild(doc.createTextNode(value.toString()));
323
324         Element bbox = doc.createElement("bbox");
325         root.appendChild(bbox);
326         int[] bb = pfm.getFontBBox();
327         final String[] names = {"left", "bottom", "right", "top"};
328         for (int i = 0; i < names.length; i++) {
329             el = doc.createElement(names[i]);
330             bbox.appendChild(el);
331             value = new Integer(bb[i]);
332             el.appendChild(doc.createTextNode(value.toString()));
333         }
334
335         el = doc.createElement("flags");
336         root.appendChild(el);
337         value = new Integer(pfm.getFlags());
338         el.appendChild(doc.createTextNode(value.toString()));
339
340         el = doc.createElement("stemv");
341         root.appendChild(el);
342         value = new Integer(pfm.getStemV());
343         el.appendChild(doc.createTextNode(value.toString()));
344
345         el = doc.createElement("italicangle");
346         root.appendChild(el);
347         value = new Integer(pfm.getItalicAngle());
348         el.appendChild(doc.createTextNode(value.toString()));
349
350         el = doc.createElement("first-char");
351         root.appendChild(el);
352         value = new Integer(pfm.getFirstChar());
353         el.appendChild(doc.createTextNode(value.toString()));
354
355         el = doc.createElement("last-char");
356         root.appendChild(el);
357         value = new Integer(pfm.getLastChar());
358         el.appendChild(doc.createTextNode(value.toString()));
359
360         Element widths = doc.createElement("widths");
361         root.appendChild(widths);
362
363         for (short i = pfm.getFirstChar(); i <= pfm.getLastChar(); i++) {
364             el = doc.createElement("char");
365             widths.appendChild(el);
366             el.setAttribute("idx", Integer.toString(i));
367             el.setAttribute("wdt",
368                             new Integer(pfm.getCharWidth(i)).toString());
369         }
370
371
372         // Get kerning
373
for (Iterator enum = pfm.getKerning().keySet().iterator(); enum.hasNext(); ) {
374             Integer kpx1 = (Integer)enum.next();
375             el = doc.createElement("kerning");
376             el.setAttribute("kpx1", kpx1.toString());
377             root.appendChild(el);
378             Element el2 = null;
379
380             Map h2 = (Map)pfm.getKerning().get(kpx1);
381             for (Iterator enum2 = h2.keySet().iterator(); enum2.hasNext(); ) {
382                 Integer kpx2 = (Integer)enum2.next();
383                 el2 = doc.createElement("pair");
384                 el2.setAttribute("kpx2", kpx2.toString());
385                 Integer val = (Integer)h2.get(kpx2);
386                 el2.setAttribute("kern", val.toString());
387                 el.appendChild(el2);
388             }
389         }
390         return doc;
391     }
392
393
394     private String escapeString(String str) {
395         StringBuffer esc = new StringBuffer();
396
397         for (int i = 0; i < str.length(); i++) {
398             if (str.charAt(i) == '\\') {
399                 esc.append("\\\\");
400             } else {
401                 esc.append(str.charAt(i));
402             }
403         }
404
405         return esc.toString();
406     }
407
408 }
409
410
411
412
413
Popular Tags