Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

PFMReader.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. /*
  2. * $Id$
  3. * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
  4. * For details on use and redistribution please refer to the
  5. * LICENSE file included with these sources.
  6. */
  7. package org.apache.fop.fonts.apps;
  8. import java.io.*;
  9. import org.w3c.dom.*;
  10. import org.apache.xerces.dom.*;
  11. import org.apache.xml.serialize.*;
  12. import org.apache.xalan.xslt.*;
  13. import org.apache.fop.fonts.*;
  14. import java.util.HashMap;
  15. import java.util.ArrayList;
  16. import java.util.Iterator;
  17. /**
  18. * A tool which reads PFM files from Adobe Type 1 fonts and creates
  19. * XML font metrics file for use in FOP.
  20. *
  21. * @author jeremias.maerki@outline.ch
  22. */
  23. public class PFMReader {
  24. private boolean invokedStandalone = false;
  25. public PFMReader() { }
  26. /**
  27. * Parse commandline arguments. put options in the HashMap and return
  28. * arguments in the String array
  29. * the arguments: -fn Perpetua,Bold -cn PerpetuaBold per.ttf Perpetua.xml
  30. * returns a String[] with the per.ttf and Perpetua.xml. The hash
  31. * will have the (key, value) pairs: (-fn, Perpetua) and (-cn, PerpetuaBold)
  32. */
  33. private static String[] parseArguments(HashMap options, String[] args) {
  34. ArrayList arguments = new ArrayList();
  35. for (int i = 0; i < args.length; i++) {
  36. if (args[i].startsWith("-")) {
  37. if ((i + 1) < args.length && !args[i + 1].startsWith("-")) {
  38. options.put(args[i], args[i + 1]);
  39. i++;
  40. } else {
  41. options.put(args[i], "");
  42. }
  43. } else {
  44. arguments.add(args[i]);
  45. }
  46. }
  47. return (String[])arguments.toArray(new String[0]);
  48. }
  49. private static final void displayUsage() {
  50. System.out.println(" java org.apache.fop.fonts.apps.PFMReader [options] metricfile.pfm xmlfile.xml\n");
  51. System.out.println(" where options can be:\n");
  52. System.out.println(" -fn <fontname>\n");
  53. System.out.println(" default is to use the fontname in the .ttf file, but\n"
  54. + " you can override that name to make sure that the\n");
  55. System.out.println(" embedded font is used (if you're embedding fonts)\n");
  56. System.out.println(" instead of installed fonts when viewing documents with Acrobat Reader.\n");
  57. }
  58. /**
  59. * The main method for the PFM reader tool.
  60. *
  61. * @param args Command-line arguments: [options] metricfile.pfm xmlfile.xml
  62. * where options can be:
  63. * -fn <fontname>
  64. * default is to use the fontname in the .pfm file, but you can override
  65. * that name to make sure that the embedded font is used instead of installed
  66. * fonts when viewing documents with Acrobat Reader.
  67. * -cn <classname>
  68. * default is to use the fontname
  69. * -ef <path to the Type1 .pfb fontfile>
  70. * will add the possibility to embed the font. When running fop, fop will look
  71. * for this file to embed it
  72. * -er <path to Type1 fontfile relative to org/apache/fop/render/pdf/fonts>
  73. * you can also include the fontfile in the fop.jar file when building fop.
  74. * You can use both -ef and -er. The file specified in -ef will be searched first,
  75. * then the -er file.
  76. */
  77. public static void main(String[] args) {
  78. String embFile = null;
  79. String embResource = null;
  80. String className = null;
  81. String fontName = null;
  82. HashMap options = new HashMap();
  83. String[] arguments = parseArguments(options, args);
  84. PFMReader app = new PFMReader();
  85. app.invokedStandalone = true;
  86. System.out.println("PFM Reader v1.1");
  87. System.out.println();
  88. if (options.get("-ef") != null) {
  89. embFile = (String)options.get("-ef");
  90. }
  91. if (options.get("-er") != null) {
  92. embResource = (String)options.get("-er");
  93. }
  94. if (options.get("-fn") != null) {
  95. fontName = (String)options.get("-fn");
  96. }
  97. if (options.get("-cn") != null) {
  98. className = (String)options.get("-cn");
  99. }
  100. if (arguments.length != 2 || options.get("-h") != null
  101. || options.get("-help") != null || options.get("--help") != null) {
  102. displayUsage();
  103. } else {
  104. PFMFile pfm = app.loadPFM(arguments[0]);
  105. if (pfm != null) {
  106. app.preview(pfm);
  107. org.w3c.dom.Document doc = app.constructFontXML(pfm,
  108. fontName, className, embResource, embFile);
  109. app.writeFontXML(doc, arguments[1]);
  110. }
  111. }
  112. }
  113. /**
  114. * Read a PFM file and returns it as an object.
  115. *
  116. * @param filename The filename of the PFM file.
  117. * @return The PFM as an object.
  118. */
  119. public PFMFile loadPFM(String filename) {
  120. try {
  121. System.out.println("Reading " + filename + "...");
  122. System.out.println();
  123. FileInputStream in = new FileInputStream(filename);
  124. PFMFile pfm = new PFMFile();
  125. pfm.load(in);
  126. return pfm;
  127. } catch (Exception e) {
  128. e.printStackTrace();
  129. return null;
  130. }
  131. }
  132. /**
  133. * Displays a preview of the PFM file on the console.
  134. *
  135. * @param pfm The PFM file to preview.
  136. */
  137. public void preview(PFMFile pfm) {
  138. PrintStream out = System.out;
  139. out.print("Font: ");
  140. out.println(pfm.getWindowsName());
  141. out.print("Name: ");
  142. out.println(pfm.getPostscriptName());
  143. out.print("CharSet: ");
  144. out.println(pfm.getCharSetName());
  145. out.print("CapHeight: ");
  146. out.println(pfm.getCapHeight());
  147. out.print("XHeight: ");
  148. out.println(pfm.getXHeight());
  149. out.print("LowerCaseAscent: ");
  150. out.println(pfm.getLowerCaseAscent());
  151. out.print("LowerCaseDescent: ");
  152. out.println(pfm.getLowerCaseDescent());
  153. out.print("Having widths for ");
  154. out.print(pfm.getLastChar() - pfm.getFirstChar());
  155. out.print(" characters (");
  156. out.print(pfm.getFirstChar());
  157. out.print("-");
  158. out.print(pfm.getLastChar());
  159. out.println(").");
  160. out.print("for example: Char ");
  161. out.print(pfm.getFirstChar());
  162. out.print(" has a width of ");
  163. out.println(pfm.getCharWidth(pfm.getFirstChar()));
  164. out.println();
  165. }
  166. /**
  167. * Writes the generated DOM Document to a file.
  168. *
  169. * @param doc The DOM Document to save.
  170. * @param target The target filename for the XML file.
  171. */
  172. public void writeFontXML(org.w3c.dom.Document doc, String target) {
  173. System.out.println("Writing xml font file " + target + "...");
  174. System.out.println();
  175. try {
  176. OutputFormat format = new OutputFormat(doc); // Serialize DOM
  177. FileWriter out = new FileWriter(target); // Writer will be a String
  178. XMLSerializer serial = new XMLSerializer(out, format);
  179. serial.asDOMSerializer(); // As a DOM Serializer
  180. serial.serialize(doc.getDocumentElement());
  181. out.close();
  182. } catch (Exception e) {
  183. e.printStackTrace();
  184. }
  185. }
  186. /**
  187. * Generates the font metrics file from the PFM file.
  188. *
  189. * @param pfm The PFM file to generate the font metrics from.
  190. * @return The DOM document representing the font metrics file.
  191. */
  192. public org.w3c.dom.Document constructFontXML(PFMFile pfm,
  193. String fontName, String className, String resource, String file) {
  194. System.out.println("Creating xml font file...");
  195. System.out.println();
  196. Document doc = new DocumentImpl();
  197. Element root = doc.createElement("font-metrics");
  198. doc.appendChild(root);
  199. root.setAttribute("type", "TYPE1");
  200. Element el = doc.createElement("font-name");
  201. root.appendChild(el);
  202. el.appendChild(doc.createTextNode(pfm.getPostscriptName()));
  203. String s = pfm.getPostscriptName();
  204. int pos = s.indexOf("-");
  205. if (pos >= 0) {
  206. char sb[] = new char[s.length() - 1];
  207. s.getChars(0, pos, sb, 0);
  208. s.getChars(pos + 1, s.length(), sb, pos);
  209. s = new String(sb);
  210. }
  211. el = doc.createElement("embed");
  212. root.appendChild(el);
  213. if (file != null) {
  214. el.setAttribute("file", file);
  215. }
  216. if (resource != null) {
  217. el.setAttribute("class", resource);
  218. }
  219. el = doc.createElement("encoding");
  220. root.appendChild(el);
  221. el.appendChild(doc.createTextNode(pfm.getCharSetName() + "Encoding"));
  222. el = doc.createElement("cap-height");
  223. root.appendChild(el);
  224. Integer value = new Integer(pfm.getCapHeight());
  225. el.appendChild(doc.createTextNode(value.toString()));
  226. el = doc.createElement("x-height");
  227. root.appendChild(el);
  228. value = new Integer(pfm.getXHeight());
  229. el.appendChild(doc.createTextNode(value.toString()));
  230. el = doc.createElement("ascender");
  231. root.appendChild(el);
  232. value = new Integer(pfm.getLowerCaseAscent());
  233. el.appendChild(doc.createTextNode(value.toString()));
  234. el = doc.createElement("descender");
  235. root.appendChild(el);
  236. value = new Integer(-pfm.getLowerCaseDescent());
  237. el.appendChild(doc.createTextNode(value.toString()));
  238. Element bbox = doc.createElement("bbox");
  239. root.appendChild(bbox);
  240. int[] bb = pfm.getFontBBox();
  241. String[] names = {
  242. "left", "bottom", "right", "top"
  243. };
  244. for (int i = 0; i < 4; i++) {
  245. el = doc.createElement(names[i]);
  246. bbox.appendChild(el);
  247. value = new Integer(bb[i]);
  248. el.appendChild(doc.createTextNode(value.toString()));
  249. }
  250. el = doc.createElement("flags");
  251. root.appendChild(el);
  252. value = new Integer(pfm.getFlags());
  253. el.appendChild(doc.createTextNode(value.toString()));
  254. el = doc.createElement("stemv");
  255. root.appendChild(el);
  256. value = new Integer(pfm.getStemV());
  257. el.appendChild(doc.createTextNode(value.toString()));
  258. el = doc.createElement("italicangle");
  259. root.appendChild(el);
  260. value = new Integer(pfm.getItalicAngle());
  261. el.appendChild(doc.createTextNode(value.toString()));
  262. el = doc.createElement("first-char");
  263. root.appendChild(el);
  264. value = new Integer(pfm.getFirstChar());
  265. el.appendChild(doc.createTextNode(value.toString()));
  266. el = doc.createElement("last-char");
  267. root.appendChild(el);
  268. value = new Integer(pfm.getLastChar());
  269. el.appendChild(doc.createTextNode(value.toString()));
  270. Element widths = doc.createElement("widths");
  271. root.appendChild(widths);
  272. for (short i = pfm.getFirstChar(); i <= pfm.getLastChar(); i++) {
  273. el = doc.createElement("char");
  274. widths.appendChild(el);
  275. el.setAttribute("idx", Integer.toString(i));
  276. el.setAttribute("wdt",
  277. new Integer(pfm.getCharWidth(i)).toString());
  278. }
  279. // Get kerning
  280. for (Iterator enum = pfm.getKerning().keySet().iterator();
  281. enum.hasNext(); ) {
  282. Integer kpx1 = (Integer)enum.next();
  283. el = doc.createElement("kerning");
  284. el.setAttribute("kpx1", kpx1.toString());
  285. root.appendChild(el);
  286. Element el2 = null;
  287. HashMap h2 = (HashMap)pfm.getKerning().get(kpx1);
  288. for (Iterator enum2 = h2.keySet().iterator(); enum2.hasNext(); ) {
  289. Integer kpx2 = (Integer)enum2.next();
  290. el2 = doc.createElement("pair");
  291. el2.setAttribute("kpx2", kpx2.toString());
  292. Integer val = (Integer)h2.get(kpx2);
  293. el2.setAttribute("kern", val.toString());
  294. el.appendChild(el2);
  295. }
  296. }
  297. return doc;
  298. }
  299. private String escapeString(String str) {
  300. StringBuffer esc = new StringBuffer();
  301. for (int i = 0; i < str.length(); i++) {
  302. if (str.charAt(i) == '\\')
  303. esc.append("\\\\");
  304. else
  305. esc.append(str.charAt(i));
  306. }
  307. return esc.toString();
  308. }
  309. }