1 /*
2  * $Id: FontFactoryImp.java 3548 2008-07-12 11:15:35Z blowagie $
3  *
4  * Copyright 2002 by Bruno Lowagie.
5  *
6  * The contents of this file are subject to the Mozilla Public License Version 1.1
7  * (the "License"); you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at http://www.mozilla.org/MPL/
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the License.
13  *
14  * The Original Code is 'iText, a free JAVA-PDF library'.
15  *
16  * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
17  * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
18  * All Rights Reserved.
19  * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
20  * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
21  *
22  * Contributor(s): all the names of the contributors are added in the source code
23  * where applicable.
24  *
25  * Alternatively, the contents of this file may be used under the terms of the
26  * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
27  * provisions of LGPL are applicable instead of those above.  If you wish to
28  * allow use of your version of this file only under the terms of the LGPL
29  * License and not to allow others to use your version of this file under
30  * the MPL, indicate your decision by deleting the provisions above and
31  * replace them with the notice and other provisions required by the LGPL.
32  * If you do not delete the provisions above, a recipient may use your version
33  * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
34  *
35  * This library is free software; you can redistribute it and/or modify it
36  * under the terms of the MPL as stated above or under the terms of the GNU
37  * Library General Public License as published by the Free Software Foundation;
38  * either version 2 of the License, or any later version.
39  *
40  * This library is distributed in the hope that it will be useful, but WITHOUT
41  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
42  * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
43  * details.
44  *
45  * If you didn't download this code from the following link, you should check if
46  * you aren't using an obsolete version:
47  * http://www.lowagie.com/iText/
48  */

49
50 package com.lowagie.text;
51
52 import java.awt.Color;
53 import java.io.File;
54 import java.io.IOException;
55 import java.util.ArrayList;
56 import java.util.Enumeration;
57 import java.util.Hashtable;
58 import java.util.Iterator;
59 import java.util.Properties;
60 import java.util.Set;
61
62 import com.lowagie.text.html.Markup;
63 import com.lowagie.text.pdf.BaseFont;
64
65 /**
66  * If you are using True Type fonts, you can declare the paths of the different ttf- and ttc-files
67  * to this class first and then create fonts in your code using one of the getFont method
68  * without having to enter a path as parameter.
69  *
70  * @author  Bruno Lowagie
71  */

72
73 public class FontFactoryImp {
74         
75 /** This is a map of postscriptfontnames of True Type fonts and the path of their ttf- or ttc-file. */
76     private Properties trueTypeFonts = new Properties();
77     
78     private static String[] TTFamilyOrder = {
79         "3""1""1033",
80         "3""0""1033",
81         "1""0""0",
82         "0""3""0"
83     };
84
85 /** This is a map of fontfamilies. */
86     private Hashtable fontFamilies = new Hashtable();
87     
88 /** This is the default encoding to use. */
89     public String defaultEncoding = BaseFont.WINANSI;
90     
91 /** This is the default value of the <VAR>embedded</VAR> variable. */
92     public boolean defaultEmbedding = BaseFont.NOT_EMBEDDED;
93     
94 /** Creates new FontFactory */
95     public FontFactoryImp() {
96         trueTypeFonts.setProperty(FontFactory.COURIER.toLowerCase(), FontFactory.COURIER);
97         trueTypeFonts.setProperty(FontFactory.COURIER_BOLD.toLowerCase(), FontFactory.COURIER_BOLD);
98         trueTypeFonts.setProperty(FontFactory.COURIER_OBLIQUE.toLowerCase(), FontFactory.COURIER_OBLIQUE);
99         trueTypeFonts.setProperty(FontFactory.COURIER_BOLDOBLIQUE.toLowerCase(), FontFactory.COURIER_BOLDOBLIQUE);
100         trueTypeFonts.setProperty(FontFactory.HELVETICA.toLowerCase(), FontFactory.HELVETICA);
101         trueTypeFonts.setProperty(FontFactory.HELVETICA_BOLD.toLowerCase(), FontFactory.HELVETICA_BOLD);
102         trueTypeFonts.setProperty(FontFactory.HELVETICA_OBLIQUE.toLowerCase(), FontFactory.HELVETICA_OBLIQUE);
103         trueTypeFonts.setProperty(FontFactory.HELVETICA_BOLDOBLIQUE.toLowerCase(), FontFactory.HELVETICA_BOLDOBLIQUE);
104         trueTypeFonts.setProperty(FontFactory.SYMBOL.toLowerCase(), FontFactory.SYMBOL);
105         trueTypeFonts.setProperty(FontFactory.TIMES_ROMAN.toLowerCase(), FontFactory.TIMES_ROMAN);
106         trueTypeFonts.setProperty(FontFactory.TIMES_BOLD.toLowerCase(), FontFactory.TIMES_BOLD);
107         trueTypeFonts.setProperty(FontFactory.TIMES_ITALIC.toLowerCase(), FontFactory.TIMES_ITALIC);
108         trueTypeFonts.setProperty(FontFactory.TIMES_BOLDITALIC.toLowerCase(), FontFactory.TIMES_BOLDITALIC);
109         trueTypeFonts.setProperty(FontFactory.ZAPFDINGBATS.toLowerCase(), FontFactory.ZAPFDINGBATS);
110
111         ArrayList tmp;
112         tmp = new ArrayList();
113         tmp.add(FontFactory.COURIER);
114         tmp.add(FontFactory.COURIER_BOLD);
115         tmp.add(FontFactory.COURIER_OBLIQUE);
116         tmp.add(FontFactory.COURIER_BOLDOBLIQUE);
117         fontFamilies.put(FontFactory.COURIER.toLowerCase(), tmp);
118         tmp = new ArrayList();
119         tmp.add(FontFactory.HELVETICA);
120         tmp.add(FontFactory.HELVETICA_BOLD);
121         tmp.add(FontFactory.HELVETICA_OBLIQUE);
122         tmp.add(FontFactory.HELVETICA_BOLDOBLIQUE);
123         fontFamilies.put(FontFactory.HELVETICA.toLowerCase(), tmp);
124         tmp = new ArrayList();
125         tmp.add(FontFactory.SYMBOL);
126         fontFamilies.put(FontFactory.SYMBOL.toLowerCase(), tmp);
127         tmp = new ArrayList();
128         tmp.add(FontFactory.TIMES_ROMAN);
129         tmp.add(FontFactory.TIMES_BOLD);
130         tmp.add(FontFactory.TIMES_ITALIC);
131         tmp.add(FontFactory.TIMES_BOLDITALIC);
132         fontFamilies.put(FontFactory.TIMES.toLowerCase(), tmp);
133         fontFamilies.put(FontFactory.TIMES_ROMAN.toLowerCase(), tmp);
134         tmp = new ArrayList();
135         tmp.add(FontFactory.ZAPFDINGBATS);
136         fontFamilies.put(FontFactory.ZAPFDINGBATS.toLowerCase(), tmp);
137     }
138     
139     /**
140      * Constructs a <CODE>Font</CODE>-object.
141      *
142      * @param    fontname    the name of the font
143      * @param    encoding    the encoding of the font
144      * @param       embedded    true if the font is to be embedded in the PDF
145      * @param    size        the size of this font
146      * @param    style        the style of this font
147      * @param    color        the <CODE>Color</CODE> of this font.
148      * @return the Font constructed based on the parameters
149      */

150     public Font getFont(String fontname, String encoding, boolean embedded, float size, int style, Color color) {
151         return getFont(fontname, encoding, embedded, size, style, color, true);
152     }
153     
154     
155     
156     /**
157      * Constructs a <CODE>Font</CODE>-object.
158      *
159      * @param    fontname    the name of the font
160      * @param    encoding    the encoding of the font
161      * @param       embedded    true if the font is to be embedded in the PDF
162      * @param    size        the size of this font
163      * @param    style        the style of this font
164      * @param    color        the <CODE>Color</CODE> of this font.
165      * @param    cached         true if the font comes from the cache or is added to
166      *                 the cache if newfalse if the font is always created new
167      * @return the Font constructed based on the parameters
168      */

169     public Font getFont(String fontname, String encoding, boolean embedded, float size, int style, Color color, boolean cached) {
170         if (fontname == nullreturn new Font(Font.UNDEFINED, size, style, color);
171         String lowercasefontname = fontname.toLowerCase();
172         ArrayList tmp = (ArrayList) fontFamilies.get(lowercasefontname);
173         if (tmp != null) {
174             // some bugs were fixed here by Daniel Marczisovszky
175             int s = style == Font.UNDEFINED ? Font.NORMAL : style;
176             int fs = Font.NORMAL;
177             boolean found = false;
178             for (Iterator i = tmp.iterator(); i.hasNext(); ) {
179                 String f = (String) i.next();
180                 String lcf = f.toLowerCase();
181                 fs = Font.NORMAL;
182                 if (lcf.toLowerCase().indexOf("bold") != -1) fs |= Font.BOLD;
183                 if (lcf.toLowerCase().indexOf("italic") != -1 || lcf.toLowerCase().indexOf("oblique") != -1) fs |= Font.ITALIC;
184                 if ((s & Font.BOLDITALIC) == fs) {
185                     fontname = f;
186                     found = true;
187                     break;
188                 }
189             }
190             if (style != Font.UNDEFINED && found) {
191                 style &= ~fs;
192             }
193         }
194         BaseFont basefont = null;
195         try {
196             try {
197                 // the font is a type 1 font or CJK font
198                 basefont = BaseFont.createFont(fontname, encoding, embedded, cached, nullnulltrue);
199             }
200             catch(DocumentException de) {
201             }
202             if (basefont == null) {
203                 // the font is a true type font or an unknown font
204                 fontname = trueTypeFonts.getProperty(fontname.toLowerCase());
205                 // the font is not registered as truetype font
206                 if (fontname == nullreturn new Font(Font.UNDEFINED, size, style, color);
207                 // the font is registered as truetype font
208                 basefont = BaseFont.createFont(fontname, encoding, embedded, cached, nullnull);
209             }
210         }
211         catch(DocumentException de) {
212             // this shouldn't happen
213             throw new ExceptionConverter(de);
214         }
215         catch(IOException ioe) {
216             // the font is registered as a true type font, but the path was wrong
217             return new Font(Font.UNDEFINED, size, style, color);
218         }
219         catch(NullPointerException npe) {
220             // null was entered as fontname and/or encoding
221             return new Font(Font.UNDEFINED, size, style, color);
222         }
223         return new Font(basefont, size, style, color);
224     }
225     
226     
227 /**
228  * Constructs a <CODE>Font</CODE>-object.
229  *
230  * @param   attributes  the attributes of a <CODE>Font</CODE> object.
231  * @return the Font constructed based on the attributes
232  */

233     
234     public Font getFont(Properties attributes) {
235         String fontname = null;
236         String encoding = defaultEncoding;
237         boolean embedded = defaultEmbedding;
238         float size = Font.UNDEFINED;
239         int style = Font.NORMAL;
240         Color color = null;
241         String value = attributes.getProperty(Markup.HTML_ATTR_STYLE);
242         if (value != null && value.length() > 0) {
243             Properties styleAttributes = Markup.parseAttributes(value);
244             if (styleAttributes.isEmpty()) {
245                 attributes.put(Markup.HTML_ATTR_STYLE, value);
246             }
247             else {
248                 fontname = styleAttributes.getProperty(Markup.CSS_KEY_FONTFAMILY);
249                 if (fontname != null) {
250                     String tmp;
251                     while (fontname.indexOf(',') != -1) {
252                         tmp = fontname.substring(0, fontname.indexOf(','));
253                         if (isRegistered(tmp)) {
254                             fontname = tmp;
255                         }
256                         else {
257                             fontname = fontname.substring(fontname.indexOf(',') + 1);
258                         }
259                     }
260                 }
261                 if ((value = styleAttributes.getProperty(Markup.CSS_KEY_FONTSIZE)) != null) {
262                     size = Markup.parseLength(value);
263                 }
264                 if ((value = styleAttributes.getProperty(Markup.CSS_KEY_FONTWEIGHT)) != null) {
265                     style |= Font.getStyleValue(value);
266                 }
267                 if ((value = styleAttributes.getProperty(Markup.CSS_KEY_FONTSTYLE)) != null) {
268                     style |= Font.getStyleValue(value);
269                 }
270                 if ((value = styleAttributes.getProperty(Markup.CSS_KEY_COLOR)) != null) {
271                     color = Markup.decodeColor(value);
272                 }
273                 attributes.putAll(styleAttributes);
274                 for (Enumeration e = styleAttributes.keys(); e.hasMoreElements();) {
275                     Object o = e.nextElement();
276                     attributes.put(o, styleAttributes.get(o));
277                 }
278             }
279         }
280         if ((value = attributes.getProperty(ElementTags.ENCODING)) != null) {
281             encoding = value;
282         }
283         if ("true".equals(attributes.getProperty(ElementTags.EMBEDDED))) {
284             embedded = true;
285         }
286         if ((value = attributes.getProperty(ElementTags.FONT)) != null) {
287             fontname = value;
288         }
289         if ((value = attributes.getProperty(ElementTags.SIZE)) != null) {
290             size = Markup.parseLength(value);
291         }
292         if ((value = attributes.getProperty(Markup.HTML_ATTR_STYLE)) != null) {
293             style |= Font.getStyleValue(value);
294         }
295         if ((value = attributes.getProperty(ElementTags.STYLE)) != null) {
296             style |= Font.getStyleValue(value);
297         }
298         String r = attributes.getProperty(ElementTags.RED);
299         String g = attributes.getProperty(ElementTags.GREEN);
300         String b = attributes.getProperty(ElementTags.BLUE);
301         if (r != null || g != null || b != null) {
302             int red = 0;
303             int green = 0;
304             int blue = 0;
305             if (r != null) red = Integer.parseInt(r);
306             if (g != null) green = Integer.parseInt(g);
307             if (b != null) blue = Integer.parseInt(b);
308             color = new Color(red, green, blue);
309         }
310         else if ((value = attributes.getProperty(ElementTags.COLOR)) != null) {
311             color = Markup.decodeColor(value);
312         }
313         if (fontname == null) {
314             return getFont(null, encoding, embedded, size, style, color);
315         }
316         return getFont(fontname, encoding, embedded, size, style, color);
317     }
318     
319 /**
320  * Constructs a <CODE>Font</CODE>-object.
321  *
322  * @param    fontname    the name of the font
323  * @param    encoding    the encoding of the font
324  * @param       embedded    true if the font is to be embedded in the PDF
325  * @param    size        the size of this font
326  * @param    style        the style of this font
327  * @return the Font constructed based on the parameters
328  */

329     
330     public Font getFont(String fontname, String encoding, boolean embedded, float size, int style) {
331         return getFont(fontname, encoding, embedded, size, style, null);
332     }
333     
334 /**
335  * Constructs a <CODE>Font</CODE>-object.
336  *
337  * @param    fontname    the name of the font
338  * @param    encoding    the encoding of the font
339  * @param       embedded    true if the font is to be embedded in the PDF
340  * @param    size        the size of this font
341  * @return the Font constructed based on the parameters
342  */

343     
344     public Font getFont(String fontname, String encoding, boolean embedded, float size) {
345         return getFont(fontname, encoding, embedded, size, Font.UNDEFINED, null);
346     }
347     
348 /**
349  * Constructs a <CODE>Font</CODE>-object.
350  *
351  * @param    fontname    the name of the font
352  * @param    encoding    the encoding of the font
353  * @param       embedded    true if the font is to be embedded in the PDF
354  * @return the Font constructed based on the parameters
355  */

356     
357     public Font getFont(String fontname, String encoding, boolean embedded) {
358         return getFont(fontname, encoding, embedded, Font.UNDEFINED, Font.UNDEFINED, null);
359     }
360     
361 /**
362  * Constructs a <CODE>Font</CODE>-object.
363  *
364  * @param    fontname    the name of the font
365  * @param    encoding    the encoding of the font
366  * @param    size        the size of this font
367  * @param    style        the style of this font
368  * @param    color        the <CODE>Color</CODE> of this font.
369  * @return the Font constructed based on the parameters
370  */

371     
372     public Font getFont(String fontname, String encoding, float size, int style, Color color) {
373         return getFont(fontname, encoding, defaultEmbedding, size, style, color);
374     }
375     
376 /**
377  * Constructs a <CODE>Font</CODE>-object.
378  *
379  * @param    fontname    the name of the font
380  * @param    encoding    the encoding of the font
381  * @param    size        the size of this font
382  * @param    style        the style of this font
383  * @return the Font constructed based on the parameters
384  */

385     
386     public Font getFont(String fontname, String encoding, float size, int style) {
387         return getFont(fontname, encoding, defaultEmbedding, size, style, null);
388     }
389     
390 /**
391  * Constructs a <CODE>Font</CODE>-object.
392  *
393  * @param    fontname    the name of the font
394  * @param    encoding    the encoding of the font
395  * @param    size        the size of this font
396  * @return the Font constructed based on the parameters
397  */

398     
399     public Font getFont(String fontname, String encoding, float size) {
400         return getFont(fontname, encoding, defaultEmbedding, size, Font.UNDEFINED, null);
401     }
402     
403
404 /**
405  * Constructs a <CODE>Font</CODE>-object.
406  *
407  * @param    fontname    the name of the font
408  * @param    size        the size of this font
409  * @param    color        the <CODE>Color</CODE> of this font.
410  * @return the Font constructed based on the parameters
411  * @since 2.1.0
412  */

413     
414     public Font getFont(String fontname, float size, Color color) {
415         return getFont(fontname, defaultEncoding, defaultEmbedding, size, Font.UNDEFINED, color);
416     }
417     
418 /**
419  * Constructs a <CODE>Font</CODE>-object.
420  *
421  * @param    fontname    the name of the font
422  * @param    encoding    the encoding of the font
423  * @return the Font constructed based on the parameters
424  */

425     
426     public Font getFont(String fontname, String encoding) {
427         return getFont(fontname, encoding, defaultEmbedding, Font.UNDEFINED, Font.UNDEFINED, null);
428     }
429     
430 /**
431  * Constructs a <CODE>Font</CODE>-object.
432  *
433  * @param    fontname    the name of the font
434  * @param    size        the size of this font
435  * @param    style        the style of this font
436  * @param    color        the <CODE>Color</CODE> of this font.
437  * @return the Font constructed based on the parameters
438  */

439     
440     public Font getFont(String fontname, float size, int style, Color color) {
441         return getFont(fontname, defaultEncoding, defaultEmbedding, size, style, color);
442     }
443     
444 /**
445  * Constructs a <CODE>Font</CODE>-object.
446  *
447  * @param    fontname    the name of the font
448  * @param    size        the size of this font
449  * @param    style        the style of this font
450  * @return the Font constructed based on the parameters
451  */

452     
453     public Font getFont(String fontname, float size, int style) {
454         return getFont(fontname, defaultEncoding, defaultEmbedding, size, style, null);
455     }
456     
457 /**
458  * Constructs a <CODE>Font</CODE>-object.
459  *
460  * @param    fontname    the name of the font
461  * @param    size        the size of this font
462  * @return the Font constructed based on the parameters
463  */

464     
465     public Font getFont(String fontname, float size) {
466         return getFont(fontname, defaultEncoding, defaultEmbedding, size, Font.UNDEFINED, null);
467     }
468     
469 /**
470  * Constructs a <CODE>Font</CODE>-object.
471  *
472  * @param    fontname    the name of the font
473  * @return the Font constructed based on the parameters
474  */

475     
476     public Font getFont(String fontname) {
477         return getFont(fontname, defaultEncoding, defaultEmbedding, Font.UNDEFINED, Font.UNDEFINED, null);
478     }
479     
480     /**
481      * Register a font by giving explicitly the font family and name.
482      * @param familyName the font family
483      * @param fullName the font name
484      * @param path the font path
485      */

486     public void registerFamily(String familyName, String fullName, String path) {
487         if (path != null)
488             trueTypeFonts.setProperty(fullName, path);
489         ArrayList tmp = (ArrayList) fontFamilies.get(familyName);
490         if (tmp == null) {
491             tmp = new ArrayList();
492             tmp.add(fullName);
493             fontFamilies.put(familyName, tmp);
494         }
495         else {
496             int fullNameLength = fullName.length();
497             boolean inserted = false;
498             for (int j = 0; j < tmp.size(); ++j) {
499                 if (((String)tmp.get(j)).length() >= fullNameLength) {
500                     tmp.add(j, fullName);
501                     inserted = true;
502                     break;
503                 }
504             }
505             if (!inserted)
506                 tmp.add(fullName);
507         }
508     }
509     
510 /**
511  * Register a ttf- or a ttc-file.
512  *
513  * @param   path    the path to a ttf- or ttc-file
514  */

515     
516     public void register(String path) {
517         register(path, null);
518     }
519     
520 /**
521  * Register a font file and use an alias for the font contained in it.
522  *
523  * @param   path    the path to a font file
524  * @param   alias   the alias you want to use for the font
525  */

526     
527     public void register(String path, String alias) {
528         try {
529             if (path.toLowerCase().endsWith(".ttf") || path.toLowerCase().endsWith(".otf") || path.toLowerCase().indexOf(".ttc,") > 0) {
530                 Object allNames[] = BaseFont.getAllFontNames(path, BaseFont.WINANSI, null);
531                 trueTypeFonts.setProperty(((String)allNames[0]).toLowerCase(), path);
532                 if (alias != null) {
533                     trueTypeFonts.setProperty(alias.toLowerCase(), path);
534                 }
535                 // register all the font names with all the locales
536                 String[][] names = (String[][])allNames[2]; //full name
537                 for (int i = 0; i < names.length; i++) {
538                     trueTypeFonts.setProperty(names[i][3].toLowerCase(), path);
539                 }
540                 String fullName = null;
541                 String familyName = null;
542                 names = (String[][])allNames[1]; //family name
543                 for (int k = 0; k < TTFamilyOrder.length; k += 3) {
544                     for (int i = 0; i < names.length; i++) {
545                         if (TTFamilyOrder[k].equals(names[i][0]) && TTFamilyOrder[k + 1].equals(names[i][1]) && TTFamilyOrder[k + 2].equals(names[i][2])) {
546                             familyName = names[i][3].toLowerCase();
547                             k = TTFamilyOrder.length;
548                             break;
549                         }
550                     }
551                 }
552                 if (familyName != null) {
553                     String lastName = "";
554                     names = (String[][])allNames[2]; //full name
555                     for (int i = 0; i < names.length; i++) {
556                         for (int k = 0; k < TTFamilyOrder.length; k += 3) {
557                             if (TTFamilyOrder[k].equals(names[i][0]) && TTFamilyOrder[k + 1].equals(names[i][1]) && TTFamilyOrder[k + 2].equals(names[i][2])) {
558                                 fullName = names[i][3];
559                                 if (fullName.equals(lastName))
560                                     continue;
561                                 lastName = fullName;
562                                 registerFamily(familyName, fullName, null);
563                                 break;
564                             }
565                         }
566                     }
567                 }
568             }
569             else if (path.toLowerCase().endsWith(".ttc")) {
570                 if (alias != null)
571                     System.err.println("class FontFactory: You can't define an alias for a true type collection.");
572                 String[] names = BaseFont.enumerateTTCNames(path);
573                 for (int i = 0; i < names.length; i++) {
574                     register(path + "," + i);
575                 }
576             }
577             else if (path.toLowerCase().endsWith(".afm") || path.toLowerCase().endsWith(".pfm")) {
578                 BaseFont bf = BaseFont.createFont(path, BaseFont.CP1252, false);
579                 String fullName = bf.getFullFontName()[0][3].toLowerCase();
580                 String familyName = bf.getFamilyFontName()[0][3].toLowerCase();
581                 String psName = bf.getPostscriptFontName().toLowerCase();
582                 registerFamily(familyName, fullName, null);
583                 trueTypeFonts.setProperty(psName, path);
584                 trueTypeFonts.setProperty(fullName, path);
585             }
586         }
587         catch(DocumentException de) {
588             // this shouldn't happen
589             throw new ExceptionConverter(de);
590         }
591         catch(IOException ioe) {
592             throw new ExceptionConverter(ioe);
593         }
594     }
595
596     /** Register all the fonts in a directory.
597      * @param dir the directory
598      * @return the number of fonts registered
599      */
    
600     public int registerDirectory(String dir) {
601         return registerDirectory(dir, false);
602     }
603
604     /**
605      * Register all the fonts in a directory and possibly its subdirectories.
606      * @param dir the directory
607      * @param scanSubdirectories recursively scan subdirectories if <code>true</true>
608      * @return the number of fonts registered
609      * @since 2.1.2
610      */

611     public int registerDirectory(String dir, boolean scanSubdirectories) {
612         int count = 0;
613         try {
614             File file = new File(dir);
615             if (!file.exists() || !file.isDirectory())
616                 return 0;
617             String files[] = file.list();
618             if (files == null)
619                 return 0;
620             for (int k = 0; k < files.length; ++k) {
621                 try {
622                     file = new File(dir, files[k]);
623                     if (file.isDirectory()) {
624                         if (scanSubdirectories) {
625                             count += registerDirectory(file.getAbsolutePath(), true);
626                         }
627                     } else {
628                         String name = file.getPath();
629                         String suffix = name.length() < 4 ? null : name.substring(name.length() - 4).toLowerCase();
630                         if (".afm".equals(suffix) || ".pfm".equals(suffix)) {
631                             /* Only register Type 1 fonts with matching .pfb files */
632                             File pfb = new File(name.substring(0, name.length() - 4) + ".pfb");
633                             if (pfb.exists()) {
634                                 register(name, null);
635                                 ++count;
636                             }
637                         } else if (".ttf".equals(suffix) || ".otf".equals(suffix) || ".ttc".equals(suffix)) {
638                             register(name, null);
639                             ++count;
640                         }
641                     }
642                 }
643                 catch (Exception e) {
644                     //empty on purpose
645                 }
646             }
647         }
648         catch (Exception e) {
649             //empty on purpose
650         }
651         return count;
652     }
653
654     /** Register fonts in some probable directories. It usually works in Windows,
655      * Linux and Solaris.
656      * @return the number of fonts registered
657      */
    
658     public int registerDirectories() {
659         int count = 0;
660         count += registerDirectory("c:/windows/fonts");
661         count += registerDirectory("c:/winnt/fonts");
662         count += registerDirectory("d:/windows/fonts");
663         count += registerDirectory("d:/winnt/fonts");
664         count += registerDirectory("/usr/share/X11/fonts"true);
665         count += registerDirectory("/usr/X/lib/X11/fonts"true);
666         count += registerDirectory("/usr/openwin/lib/X11/fonts"true);
667         count += registerDirectory("/usr/share/fonts"true);
668         count += registerDirectory("/usr/X11R6/lib/X11/fonts"true);
669         count += registerDirectory("/Library/Fonts");
670         count += registerDirectory("/System/Library/Fonts");
671         return count;
672     }
673
674 /**
675  * Gets a set of registered fontnames.
676  * @return a set of registered fonts
677  */

678     
679     public Set getRegisteredFonts() {
680         return Utilities.getKeySet(trueTypeFonts);
681     }
682     
683 /**
684  * Gets a set of registered fontnames.
685  * @return a set of registered font families
686  */

687     
688     public Set getRegisteredFamilies() {
689         return Utilities.getKeySet(fontFamilies);
690     }
691     
692 /**
693  * Checks if a certain font is registered.
694  *
695  * @param   fontname    the name of the font that has to be checked.
696  * @return  true if the font is found
697  */

698     public boolean isRegistered(String fontname) {
699         return trueTypeFonts.containsKey(fontname.toLowerCase());
700     }
701 }
702