You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

FontListMain.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /* $Id$ */
  18. package org.apache.fop.tools.fontlist;
  19. import java.io.File;
  20. import java.io.FileNotFoundException;
  21. import java.io.IOException;
  22. import java.io.OutputStream;
  23. import java.io.PrintStream;
  24. import java.net.URL;
  25. import java.util.Iterator;
  26. import java.util.List;
  27. import java.util.Map;
  28. import java.util.SortedMap;
  29. import javax.xml.transform.Transformer;
  30. import javax.xml.transform.TransformerConfigurationException;
  31. import javax.xml.transform.sax.SAXResult;
  32. import javax.xml.transform.sax.SAXTransformerFactory;
  33. import javax.xml.transform.sax.TransformerHandler;
  34. import javax.xml.transform.stream.StreamResult;
  35. import javax.xml.transform.stream.StreamSource;
  36. import org.xml.sax.ContentHandler;
  37. import org.xml.sax.SAXException;
  38. import org.apache.commons.io.FilenameUtils;
  39. import org.apache.commons.io.IOUtils;
  40. import org.apache.fop.Version;
  41. import org.apache.fop.apps.FOPException;
  42. import org.apache.fop.apps.Fop;
  43. import org.apache.fop.apps.FopFactory;
  44. import org.apache.fop.apps.MimeConstants;
  45. import org.apache.fop.fonts.FontEventListener;
  46. import org.apache.fop.fonts.FontTriplet;
  47. import org.apache.fop.util.GenerationHelperContentHandler;
  48. /**
  49. * Command-line application to list available fonts and to optionally produce sample pages
  50. * with those fonts.
  51. */
  52. public final class FontListMain {
  53. private static final int GENERATE_CONSOLE = 0;
  54. private static final int GENERATE_XML = 1;
  55. private static final int GENERATE_FO = 2;
  56. private static final int GENERATE_RENDERED = 3;
  57. private FopFactory fopFactory = FopFactory.newInstance();
  58. private File configFile;
  59. private File outputFile;
  60. private String configMime = MimeConstants.MIME_PDF;
  61. private String outputMime;
  62. private int mode = GENERATE_CONSOLE;
  63. private String singleFamilyFilter;
  64. private FontListMain() throws SAXException, IOException {
  65. }
  66. private void prepare() throws SAXException, IOException {
  67. if (this.configFile != null) {
  68. fopFactory.setUserConfig(this.configFile);
  69. }
  70. }
  71. private ContentHandler getFOPContentHandler(OutputStream out) throws FOPException {
  72. Fop fop = fopFactory.newFop(this.outputMime, out);
  73. return fop.getDefaultHandler();
  74. }
  75. private void generateXML(SortedMap fontFamilies, File outFile, String singleFamily)
  76. throws TransformerConfigurationException, SAXException, IOException {
  77. SAXTransformerFactory tFactory = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
  78. TransformerHandler handler;
  79. if (this.mode == GENERATE_XML) {
  80. handler = tFactory.newTransformerHandler();
  81. } else {
  82. URL url = getClass().getResource("fonts2fo.xsl");
  83. if (url == null) {
  84. throw new FileNotFoundException("Did not find resource: fonts2fo.xsl");
  85. }
  86. handler = tFactory.newTransformerHandler(new StreamSource(url.toExternalForm()));
  87. }
  88. if (singleFamily != null) {
  89. Transformer transformer = handler.getTransformer();
  90. transformer.setParameter("single-family", singleFamily);
  91. }
  92. OutputStream out = new java.io.FileOutputStream(outFile);
  93. out = new java.io.BufferedOutputStream(out);
  94. if (this.mode == GENERATE_RENDERED) {
  95. handler.setResult(new SAXResult(getFOPContentHandler(out)));
  96. } else {
  97. handler.setResult(new StreamResult(out));
  98. }
  99. try {
  100. GenerationHelperContentHandler helper = new GenerationHelperContentHandler(
  101. handler, null);
  102. FontListSerializer serializer = new FontListSerializer();
  103. serializer.generateSAX(fontFamilies, singleFamily, helper);
  104. } finally {
  105. IOUtils.closeQuietly(out);
  106. }
  107. }
  108. private void generate() throws Exception {
  109. prepare();
  110. FontEventListener listener = new FontEventListener() {
  111. public void fontLoadingErrorAtAutoDetection(Object source,
  112. String fontURL, Exception e) {
  113. System.err.println("Could not load " + fontURL
  114. + " (" + e.getLocalizedMessage() + ")");
  115. }
  116. public void fontSubstituted(Object source,
  117. FontTriplet requested, FontTriplet effective) {
  118. //ignore
  119. }
  120. public void glyphNotAvailable(Object source, char ch, String fontName) {
  121. //ignore
  122. }
  123. public void fontDirectoryNotFound(Object source, String msg) {
  124. //ignore
  125. }
  126. };
  127. FontListGenerator listGenerator = new FontListGenerator();
  128. SortedMap fontFamilies = listGenerator.listFonts(fopFactory, configMime, listener);
  129. if (this.mode == GENERATE_CONSOLE) {
  130. writeToConsole(fontFamilies);
  131. } else {
  132. writeOutput(fontFamilies);
  133. }
  134. }
  135. private void writeToConsole(SortedMap fontFamilies)
  136. throws TransformerConfigurationException, SAXException, IOException {
  137. Iterator iter = fontFamilies.entrySet().iterator();
  138. while (iter.hasNext()) {
  139. Map.Entry entry = (Map.Entry)iter.next();
  140. String firstFamilyName = (String)entry.getKey();
  141. System.out.println(firstFamilyName + ":");
  142. List list = (List)entry.getValue();
  143. Iterator fonts = list.iterator();
  144. while (fonts.hasNext()) {
  145. FontSpec f = (FontSpec)fonts.next();
  146. System.out.println(" " + f.getKey() + " " + f.getFamilyNames());
  147. Iterator triplets = f.getTriplets().iterator();
  148. while (triplets.hasNext()) {
  149. FontTriplet triplet = (FontTriplet)triplets.next();
  150. System.out.println(" " + triplet.toString());
  151. }
  152. }
  153. }
  154. }
  155. private void writeOutput(SortedMap fontFamilies)
  156. throws TransformerConfigurationException, SAXException, IOException {
  157. if (this.outputFile.isDirectory()) {
  158. System.out.println("Creating one file for each family...");
  159. Iterator iter = fontFamilies.entrySet().iterator();
  160. while (iter.hasNext()) {
  161. Map.Entry entry = (Map.Entry)iter.next();
  162. String familyName = (String)entry.getKey();
  163. System.out.println("Creating output file for " + familyName + "...");
  164. String filename;
  165. switch(this.mode) {
  166. case GENERATE_RENDERED:
  167. filename = familyName + ".pdf";
  168. break;
  169. case GENERATE_FO:
  170. filename = familyName + ".fo";
  171. break;
  172. case GENERATE_XML:
  173. filename = familyName + ".xml";
  174. break;
  175. default:
  176. throw new IllegalStateException("Unsupported mode");
  177. }
  178. File outFile = new File(this.outputFile, filename);
  179. generateXML(fontFamilies, outFile, familyName);
  180. }
  181. } else {
  182. System.out.println("Creating output file...");
  183. generateXML(fontFamilies, this.outputFile, this.singleFamilyFilter);
  184. }
  185. System.out.println(this.outputFile + " written.");
  186. }
  187. private static void printVersion() {
  188. System.out.println("Apache FOP " + Version.getVersion()
  189. + " - http://xmlgraphics.apache.org/fop/\n");
  190. }
  191. private static void printHelp() {
  192. printVersion();
  193. String className = FontListMain.class.getName();
  194. PrintStream out = System.out;
  195. out.println("USAGE");
  196. out.println(" java [vmargs] " + className
  197. + " [-c <config-file>] [-f <mime>] [[output-dir|output-file] [font-family]]");
  198. out.println();
  199. out.println("PARAMETERS");
  200. out.println(" config-file: an optional FOP configuration file");
  201. out.println(" mime: The MIME type of the output format for which to");
  202. out.println(" create the font list (defaults to application/pdf)");
  203. out.println(" output-dir: Creates one sample PDF per font-family");
  204. out.println(" output-file: writes the list as file (valid file extensions: xml, fo, pdf)");
  205. out.println(" font-family: filters to a single font family");
  206. out.println();
  207. out.println("EXAMPLE");
  208. out.println(" java [vmargs] " + className
  209. + " -c userconfig.xml all-fonts.pdf");
  210. out.println(" --> this generates a single PDF containing a sample");
  211. out.println(" of all configured fonts.");
  212. out.println(" java [vmargs] " + className
  213. + " -c userconfig.xml");
  214. out.println(" --> this prints all configured fonts to the console.");
  215. out.println();
  216. }
  217. private void parseArguments(String[] args) {
  218. if (args.length > 0) {
  219. int idx = 0;
  220. if ("--help".equals(args[idx]) || "-?".equals(args[idx]) || "-h".equals(args[idx])) {
  221. printHelp();
  222. System.exit(0);
  223. }
  224. if (idx < args.length - 1 && "-c".equals(args[idx])) {
  225. String filename = args[idx + 1];
  226. this.configFile = new File(filename);
  227. idx += 2;
  228. }
  229. if (idx < args.length - 1 && "-f".equals(args[idx])) {
  230. this.configMime = args[idx + 1];
  231. idx += 2;
  232. }
  233. if (idx < args.length) {
  234. String name = args[idx];
  235. this.outputFile = new File(name);
  236. if (this.outputFile.isDirectory()) {
  237. this.mode = GENERATE_RENDERED;
  238. this.outputMime = MimeConstants.MIME_PDF;
  239. } else if (FilenameUtils.getExtension(name).equalsIgnoreCase("pdf")) {
  240. this.mode = GENERATE_RENDERED;
  241. this.outputMime = MimeConstants.MIME_PDF;
  242. } else if (FilenameUtils.getExtension(name).equalsIgnoreCase("fo")) {
  243. this.mode = GENERATE_FO;
  244. } else if (FilenameUtils.getExtension(name).equalsIgnoreCase("xml")) {
  245. this.mode = GENERATE_XML;
  246. } else {
  247. throw new IllegalArgumentException(
  248. "Operating mode for the output file cannot be determined"
  249. + " or is unsupported: " + name);
  250. }
  251. idx++;
  252. }
  253. if (idx < args.length) {
  254. this.singleFamilyFilter = args[idx];
  255. }
  256. } else {
  257. System.out.println("use --help or -? for usage information.");
  258. }
  259. }
  260. /**
  261. * The command-line interface.
  262. * @param args the command-line arguments
  263. */
  264. public static void main(String[] args) {
  265. try {
  266. FontListMain app = new FontListMain();
  267. app.parseArguments(args);
  268. app.generate();
  269. } catch (Throwable t) {
  270. printHelp();
  271. t.printStackTrace();
  272. System.exit(-1);
  273. }
  274. }
  275. }