1 /*
2  * $Id: FontFactory.java,v 1.65 2005/05/03 13:03:47 blowagie Exp $
3  * $Name:  $
4  *
5  * Copyright 2002 by Bruno Lowagie.
6  *
7  *
8  * The Original Code is 'iText, a free JAVA-PDF library'.
9  *
10  * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
11  * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
12  * All Rights Reserved.
13  * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
14  * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
15  *
16  * Contributor(s): all the names of the contributors are added in the source code
17  * where applicable.
18  *
19  *
20  * This library is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU Library General Public
22  * License as published by the Free Software Foundation; either
23  * version 2 of the License, or (at your option) any later version.
24  *
25  * This library is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
28  * Library General Public License for more details.
29  *
30  * You should have received a copy of the GNU Library General Public
31  * License along with this library; if not, write to the
32  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
33  * Boston, MA  02110-1301, USA.
34  *
35  *
36  * This library is free software; you can redistribute it and/or
37  * modify it under the terms of the GNU Library General Public
38  * License as published by the Free Software Foundation; either
39  * version 2 of the License, or (at your option) any later version.
40  *
41  * This library is distributed in the hope that it will be useful,
42  * but WITHOUT ANY WARRANTY; without even the implied warranty of
43  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
44  * Library General Public License for more details.
45  *
46  * You should have received a copy of the GNU Library General Public
47  * License along with this library; if not, write to the
48  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
49  * Boston, MA  02110-1301, USA.
50  *
51  *
52  * If you didn't download this code from the following link, you should check if
53  * you aren't using an obsolete version:
54  * http://www.lowagie.com/iText/
55  */
56 
57 package com.gitlab.pdftk_java.com.lowagie.text;
58 
59 import java.awt.Color;
60 import java.io.IOException;
61 import java.util.Hashtable;
62 import java.util.ArrayList;
63 import java.util.Iterator;
64 import java.util.Properties;
65 import java.util.Set;
66 import java.util.Enumeration;
67 import java.io.File;
68 import com.gitlab.pdftk_java.com.lowagie.text.pdf.BaseFont;
69 import com.gitlab.pdftk_java.com.lowagie.text.markup.MarkupTags;
70 import com.gitlab.pdftk_java.com.lowagie.text.markup.MarkupParser;
71 
72 /**
73  * If you are using True Type fonts, you can declare the paths of the different ttf- and ttc-files
74  * to this static class first and then create fonts in your code using one of the static getFont-method
75  * without having to enter a path as parameter.
76  *
77  * @author  Bruno Lowagie
78  */
79 
80 public class FontFactory extends java.lang.Object {
81 
82 /** This is a possible value of a base 14 type 1 font */
83     public static final String COURIER = BaseFont.COURIER;
84 
85 /** This is a possible value of a base 14 type 1 font */
86     public static final String COURIER_BOLD = BaseFont.COURIER_BOLD;
87 
88 /** This is a possible value of a base 14 type 1 font */
89     public static final String COURIER_OBLIQUE = BaseFont.COURIER_OBLIQUE;
90 
91 /** This is a possible value of a base 14 type 1 font */
92     public static final String COURIER_BOLDOBLIQUE = BaseFont.COURIER_BOLDOBLIQUE;
93 
94 /** This is a possible value of a base 14 type 1 font */
95     public static final String HELVETICA = BaseFont.HELVETICA;
96 
97 /** This is a possible value of a base 14 type 1 font */
98     public static final String HELVETICA_BOLD = BaseFont.HELVETICA_BOLD;
99 
100 /** This is a possible value of a base 14 type 1 font */
101     public static final String HELVETICA_OBLIQUE = BaseFont.HELVETICA_OBLIQUE;
102 
103 /** This is a possible value of a base 14 type 1 font */
104     public static final String HELVETICA_BOLDOBLIQUE = BaseFont.HELVETICA_BOLDOBLIQUE;
105 
106 /** This is a possible value of a base 14 type 1 font */
107     public static final String SYMBOL = BaseFont.SYMBOL;
108 
109 /** This is a possible value of a base 14 type 1 font */
110     public static final String TIMES = "Times";
111 
112 /** This is a possible value of a base 14 type 1 font */
113     public static final String TIMES_ROMAN = BaseFont.TIMES_ROMAN;
114 
115 /** This is a possible value of a base 14 type 1 font */
116     public static final String TIMES_BOLD = BaseFont.TIMES_BOLD;
117 
118 /** This is a possible value of a base 14 type 1 font */
119     public static final String TIMES_ITALIC = BaseFont.TIMES_ITALIC;
120 
121 /** This is a possible value of a base 14 type 1 font */
122     public static final String TIMES_BOLDITALIC = BaseFont.TIMES_BOLDITALIC;
123 
124 /** This is a possible value of a base 14 type 1 font */
125     public static final String ZAPFDINGBATS = BaseFont.ZAPFDINGBATS;
126 
127 /** This is a map of postscriptfontnames of True Type fonts and the path of their ttf- or ttc-file. */
128     private static Properties trueTypeFonts = new Properties();
129 
130     private static String[] TTFamilyOrder = {
131         "3", "1", "1033",
132         "3", "0", "1033",
133         "1", "0", "0",
134         "0", "3", "0"
135     };
136 
137     static {
COURIER.toLowerCase()138         trueTypeFonts.setProperty(COURIER.toLowerCase(), COURIER);
COURIER_BOLD.toLowerCase()139         trueTypeFonts.setProperty(COURIER_BOLD.toLowerCase(), COURIER_BOLD);
COURIER_OBLIQUE.toLowerCase()140         trueTypeFonts.setProperty(COURIER_OBLIQUE.toLowerCase(), COURIER_OBLIQUE);
COURIER_BOLDOBLIQUE.toLowerCase()141         trueTypeFonts.setProperty(COURIER_BOLDOBLIQUE.toLowerCase(), COURIER_BOLDOBLIQUE);
HELVETICA.toLowerCase()142         trueTypeFonts.setProperty(HELVETICA.toLowerCase(), HELVETICA);
HELVETICA_BOLD.toLowerCase()143         trueTypeFonts.setProperty(HELVETICA_BOLD.toLowerCase(), HELVETICA_BOLD);
HELVETICA_OBLIQUE.toLowerCase()144         trueTypeFonts.setProperty(HELVETICA_OBLIQUE.toLowerCase(), HELVETICA_OBLIQUE);
HELVETICA_BOLDOBLIQUE.toLowerCase()145         trueTypeFonts.setProperty(HELVETICA_BOLDOBLIQUE.toLowerCase(), HELVETICA_BOLDOBLIQUE);
SYMBOL.toLowerCase()146         trueTypeFonts.setProperty(SYMBOL.toLowerCase(), SYMBOL);
TIMES_ROMAN.toLowerCase()147         trueTypeFonts.setProperty(TIMES_ROMAN.toLowerCase(), TIMES_ROMAN);
TIMES_BOLD.toLowerCase()148         trueTypeFonts.setProperty(TIMES_BOLD.toLowerCase(), TIMES_BOLD);
TIMES_ITALIC.toLowerCase()149         trueTypeFonts.setProperty(TIMES_ITALIC.toLowerCase(), TIMES_ITALIC);
TIMES_BOLDITALIC.toLowerCase()150         trueTypeFonts.setProperty(TIMES_BOLDITALIC.toLowerCase(), TIMES_BOLDITALIC);
ZAPFDINGBATS.toLowerCase()151         trueTypeFonts.setProperty(ZAPFDINGBATS.toLowerCase(), ZAPFDINGBATS);
152     }
153 
154 /** This is a map of fontfamilies. */
155     private static Hashtable fontFamilies = new Hashtable();
156 
157     static {
158         ArrayList tmp;
159         tmp = new ArrayList();
160         tmp.add(COURIER);
161         tmp.add(COURIER_BOLD);
162         tmp.add(COURIER_OBLIQUE);
163         tmp.add(COURIER_BOLDOBLIQUE);
COURIER.toLowerCase()164         fontFamilies.put(COURIER.toLowerCase(), tmp);
165         tmp = new ArrayList();
166         tmp.add(HELVETICA);
167         tmp.add(HELVETICA_BOLD);
168         tmp.add(HELVETICA_OBLIQUE);
169         tmp.add(HELVETICA_BOLDOBLIQUE);
HELVETICA.toLowerCase()170         fontFamilies.put(HELVETICA.toLowerCase(), tmp);
171         tmp = new ArrayList();
172         tmp.add(SYMBOL);
SYMBOL.toLowerCase()173         fontFamilies.put(SYMBOL.toLowerCase(), tmp);
174         tmp = new ArrayList();
175         tmp.add(TIMES_ROMAN);
176         tmp.add(TIMES_BOLD);
177         tmp.add(TIMES_ITALIC);
178         tmp.add(TIMES_BOLDITALIC);
TIMES.toLowerCase()179         fontFamilies.put(TIMES.toLowerCase(), tmp);
TIMES_ROMAN.toLowerCase()180         fontFamilies.put(TIMES_ROMAN.toLowerCase(), tmp);
181         tmp = new ArrayList();
182         tmp.add(ZAPFDINGBATS);
ZAPFDINGBATS.toLowerCase()183         fontFamilies.put(ZAPFDINGBATS.toLowerCase(), tmp);
184     }
185 
186 
187 /** This is the default encoding to use. */
188     public static String defaultEncoding = BaseFont.WINANSI;
189 
190 /** This is the default value of the <VAR>embedded</VAR> variable. */
191     public static boolean defaultEmbedding = BaseFont.NOT_EMBEDDED;
192 
193 /** Creates new FontFactory */
FontFactory()194     private FontFactory() {
195     }
196 
197 /**
198  * Constructs a <CODE>Font</CODE>-object.
199  *
200  * @param	fontname    the name of the font
201  * @param	encoding    the encoding of the font
202  * @param       embedded    true if the font is to be embedded in the PDF
203  * @param	size	    the size of this font
204  * @param	style	    the style of this font
205  * @param	color	    the <CODE>Color</CODE> of this font.
206  * @return the Font constructed based on the parameters
207  */
208 
getFont(String fontname, String encoding, boolean embedded, float size, int style, Color color)209     public static Font getFont(String fontname, String encoding, boolean embedded, float size, int style, Color color) {
210         if (fontname == null) return new Font(Font.UNDEFINED, size, style, color);
211         String lowercasefontname = fontname.toLowerCase();
212         ArrayList tmp = (ArrayList) fontFamilies.get(lowercasefontname);
213         if (tmp != null) {
214             // some bugs were fixed here by Daniel Marczisovszky
215             int s = style == Font.UNDEFINED ? Font.NORMAL : style;
216             int fs = Font.NORMAL;
217             boolean found = false;
218             for (Iterator i = tmp.iterator(); i.hasNext(); ) {
219                 String f = (String) i.next();
220                 String lcf = f.toLowerCase();
221                 fs = Font.NORMAL;
222                 if (lcf.toLowerCase().indexOf("bold") != -1) fs |= Font.BOLD;
223                 if (lcf.toLowerCase().indexOf("italic") != -1 || lcf.toLowerCase().indexOf("oblique") != -1) fs |= Font.ITALIC;
224                 if ((s & Font.BOLDITALIC) == fs) {
225                     fontname = f;
226                     found = true;
227                     break;
228                 }
229             }
230             if (style != Font.UNDEFINED && found) {
231                 style &= ~fs;
232             }
233         }
234         BaseFont basefont = null;
235         try {
236             try {
237                 // the font is a type 1 font or CJK font
238                 basefont = BaseFont.createFont(fontname, encoding, embedded);
239             }
240             catch(DocumentException de) {
241                 // the font is a true type font or an unknown font
242                 fontname = trueTypeFonts.getProperty(fontname.toLowerCase());
243                 // the font is not registered as truetype font
244                 if (fontname == null) return new Font(Font.UNDEFINED, size, style, color);
245                 // the font is registered as truetype font
246                 basefont = BaseFont.createFont(fontname, encoding, embedded);
247             }
248         }
249         catch(DocumentException de) {
250             // this shouldn't happen
251             throw new ExceptionConverter(de);
252         }
253         catch(IOException ioe) {
254             // the font is registered as a true type font, but the path was wrong
255             return new Font(Font.UNDEFINED, size, style, color);
256         }
257         catch(NullPointerException npe) {
258             // null was entered as fontname and/or encoding
259             return new Font(Font.UNDEFINED, size, style, color);
260         }
261         return new Font(basefont, size, style, color);
262     }
263 
264 /**
265  * Constructs a <CODE>Font</CODE>-object.
266  *
267  * @param   attributes  the attributes of a <CODE>Font</CODE> object.
268  * @return the Font constructed based on the attributes
269  */
270 
getFont(Properties attributes)271     public static Font getFont(Properties attributes) {
272         String fontname = null;
273         String encoding = defaultEncoding;
274         boolean embedded = defaultEmbedding;
275         float size = Font.UNDEFINED;
276         int style = Font.NORMAL;
277         Color color = null;
278         String value = (String) attributes.remove(MarkupTags.HTML_ATTR_STYLE);
279         if (value != null && value.length() > 0) {
280             Properties styleAttributes = MarkupParser.parseAttributes(value);
281             if (styleAttributes.size() == 0) {
282                 attributes.put(MarkupTags.HTML_ATTR_STYLE, value);
283             }
284             else {
285                 fontname = (String)styleAttributes.remove(MarkupTags.CSS_KEY_FONTFAMILY);
286                 if (fontname != null) {
287                     String tmp;
288                     while (fontname.indexOf(",") != -1) {
289                         tmp = fontname.substring(0, fontname.indexOf(","));
290                         if (isRegistered(tmp)) {
291                             fontname = tmp;
292                         }
293                         else {
294                             fontname = fontname.substring(fontname.indexOf(",") + 1);
295                         }
296                     }
297                 }
298                 if ((value = (String)styleAttributes.remove(MarkupTags.CSS_KEY_FONTSIZE)) != null) {
299                     size = MarkupParser.parseLength(value);
300                 }
301                 if ((value = (String)styleAttributes.remove(MarkupTags.CSS_KEY_FONTWEIGHT)) != null) {
302                     style |= Font.getStyleValue(value);
303                 }
304                 if ((value = (String)styleAttributes.remove(MarkupTags.CSS_KEY_FONTSTYLE)) != null) {
305                     style |= Font.getStyleValue(value);
306                 }
307                 if ((value = (String)styleAttributes.remove(MarkupTags.CSS_KEY_COLOR)) != null) {
308                     color = MarkupParser.decodeColor(value);
309                 }
310                 attributes.putAll(styleAttributes);
311                 for (Enumeration e = styleAttributes.keys(); e.hasMoreElements();) {
312                     Object o = e.nextElement();
313                     attributes.put(o, styleAttributes.get(o));
314                 }
315             }
316         }
317         if ((value = (String)attributes.remove(ElementTags.ENCODING)) != null) {
318             encoding = value;
319         }
320         if ("true".equals(attributes.remove(ElementTags.EMBEDDED))) {
321             embedded = true;
322         }
323         if ((value = (String)attributes.remove(ElementTags.FONT)) != null) {
324             fontname = value;
325         }
326         if ((value = (String)attributes.remove(ElementTags.SIZE)) != null) {
327             size = Float.valueOf(value + "f").floatValue();
328         }
329         if ((value = (String)attributes.remove(MarkupTags.HTML_ATTR_STYLE)) != null) {
330             style |= Font.getStyleValue(value);
331         }
332         if ((value = (String)attributes.remove(ElementTags.STYLE)) != null) {
333             style |= Font.getStyleValue(value);
334         }
335         String r = (String)attributes.remove(ElementTags.RED);
336         String g = (String)attributes.remove(ElementTags.GREEN);
337         String b = (String)attributes.remove(ElementTags.BLUE);
338         if (r != null || g != null || b != null) {
339             int red = 0;
340             int green = 0;
341             int blue = 0;
342             if (r != null) red = Integer.parseInt(r);
343             if (g != null) green = Integer.parseInt(g);
344             if (b != null) blue = Integer.parseInt(b);
345             color = new Color(red, green, blue);
346         }
347         else if ((value = (String)attributes.remove(ElementTags.COLOR)) != null) {
348             color = MarkupParser.decodeColor(value);
349         }
350         if (fontname == null) {
351             return getFont(null, encoding, embedded, size, style, color);
352         }
353         return getFont(fontname, encoding, embedded, size, style, color);
354     }
355 
356 /**
357  * Constructs a <CODE>Font</CODE>-object.
358  *
359  * @param	fontname    the name of the font
360  * @param	encoding    the encoding of the font
361  * @param       embedded    true if the font is to be embedded in the PDF
362  * @param	size	    the size of this font
363  * @param	style	    the style of this font
364  * @return the Font constructed based on the parameters
365  */
366 
getFont(String fontname, String encoding, boolean embedded, float size, int style)367     public static Font getFont(String fontname, String encoding, boolean embedded, float size, int style) {
368         return getFont(fontname, encoding, embedded, size, style, null);
369     }
370 
371 /**
372  * Constructs a <CODE>Font</CODE>-object.
373  *
374  * @param	fontname    the name of the font
375  * @param	encoding    the encoding of the font
376  * @param       embedded    true if the font is to be embedded in the PDF
377  * @param	size	    the size of this font
378  * @return the Font constructed based on the parameters
379  */
380 
getFont(String fontname, String encoding, boolean embedded, float size)381     public static Font getFont(String fontname, String encoding, boolean embedded, float size) {
382         return getFont(fontname, encoding, embedded, size, Font.UNDEFINED, null);
383     }
384 
385 /**
386  * Constructs a <CODE>Font</CODE>-object.
387  *
388  * @param	fontname    the name of the font
389  * @param	encoding    the encoding of the font
390  * @param       embedded    true if the font is to be embedded in the PDF
391  * @return the Font constructed based on the parameters
392  */
393 
getFont(String fontname, String encoding, boolean embedded)394     public static Font getFont(String fontname, String encoding, boolean embedded) {
395         return getFont(fontname, encoding, embedded, Font.UNDEFINED, Font.UNDEFINED, null);
396     }
397 
398 /**
399  * Constructs a <CODE>Font</CODE>-object.
400  *
401  * @param	fontname    the name of the font
402  * @param	encoding    the encoding of the font
403  * @param	size	    the size of this font
404  * @param	style	    the style of this font
405  * @param	color	    the <CODE>Color</CODE> of this font.
406  * @return the Font constructed based on the parameters
407  */
408 
getFont(String fontname, String encoding, float size, int style, Color color)409     public static Font getFont(String fontname, String encoding, float size, int style, Color color) {
410         return getFont(fontname, encoding, defaultEmbedding, size, style, color);
411     }
412 
413 /**
414  * Constructs a <CODE>Font</CODE>-object.
415  *
416  * @param	fontname    the name of the font
417  * @param	encoding    the encoding of the font
418  * @param	size	    the size of this font
419  * @param	style	    the style of this font
420  * @return the Font constructed based on the parameters
421  */
422 
getFont(String fontname, String encoding, float size, int style)423     public static Font getFont(String fontname, String encoding, float size, int style) {
424         return getFont(fontname, encoding, defaultEmbedding, size, style, null);
425     }
426 
427 /**
428  * Constructs a <CODE>Font</CODE>-object.
429  *
430  * @param	fontname    the name of the font
431  * @param	encoding    the encoding of the font
432  * @param	size	    the size of this font
433  * @return the Font constructed based on the parameters
434  */
435 
getFont(String fontname, String encoding, float size)436     public static Font getFont(String fontname, String encoding, float size) {
437         return getFont(fontname, encoding, defaultEmbedding, size, Font.UNDEFINED, null);
438     }
439 
440 /**
441  * Constructs a <CODE>Font</CODE>-object.
442  *
443  * @param	fontname    the name of the font
444  * @param	encoding    the encoding of the font
445  * @return the Font constructed based on the parameters
446  */
447 
getFont(String fontname, String encoding)448     public static Font getFont(String fontname, String encoding) {
449         return getFont(fontname, encoding, defaultEmbedding, Font.UNDEFINED, Font.UNDEFINED, null);
450     }
451 
452 /**
453  * Constructs a <CODE>Font</CODE>-object.
454  *
455  * @param	fontname    the name of the font
456  * @param	size	    the size of this font
457  * @param	style	    the style of this font
458  * @param	color	    the <CODE>Color</CODE> of this font.
459  * @return the Font constructed based on the parameters
460  */
461 
getFont(String fontname, float size, int style, Color color)462     public static Font getFont(String fontname, float size, int style, Color color) {
463         return getFont(fontname, defaultEncoding, defaultEmbedding, size, style, color);
464     }
465 
466 /**
467  * Constructs a <CODE>Font</CODE>-object.
468  *
469  * @param	fontname    the name of the font
470  * @param	size	    the size of this font
471  * @param	style	    the style of this font
472  * @return the Font constructed based on the parameters
473  */
474 
getFont(String fontname, float size, int style)475     public static Font getFont(String fontname, float size, int style) {
476         return getFont(fontname, defaultEncoding, defaultEmbedding, size, style, null);
477     }
478 
479 /**
480  * Constructs a <CODE>Font</CODE>-object.
481  *
482  * @param	fontname    the name of the font
483  * @param	size	    the size of this font
484  * @return the Font constructed based on the parameters
485  */
486 
getFont(String fontname, float size)487     public static Font getFont(String fontname, float size) {
488         return getFont(fontname, defaultEncoding, defaultEmbedding, size, Font.UNDEFINED, null);
489     }
490 
491 /**
492  * Constructs a <CODE>Font</CODE>-object.
493  *
494  * @param	fontname    the name of the font
495  * @return the Font constructed based on the parameters
496  */
497 
getFont(String fontname)498     public static Font getFont(String fontname) {
499         return getFont(fontname, defaultEncoding, defaultEmbedding, Font.UNDEFINED, Font.UNDEFINED, null);
500     }
501 
502 /**
503  * Register a ttf- or a ttc-file.
504  *
505  * @param   path    the path to a ttf- or ttc-file
506  */
507 
register(String path)508     public static void register(String path) {
509         register(path, null);
510     }
511 
512 /**
513  * Register a font file and use an alias for the font contained in it.
514  *
515  * @param   path    the path to a font file
516  * @param   alias   the alias you want to use for the font
517  */
518 
register(String path, String alias)519     public static void register(String path, String alias) {
520         try {
521             if (path.toLowerCase().endsWith(".ttf") || path.toLowerCase().endsWith(".otf") || path.toLowerCase().indexOf(".ttc,") > 0) {
522                 Object allNames[] = BaseFont.getAllFontNames(path, BaseFont.WINANSI, null);
523                 trueTypeFonts.setProperty(((String)allNames[0]).toLowerCase(), path);
524                 if (alias != null) {
525                     trueTypeFonts.setProperty(alias, path);
526                 }
527                 // register all the font names with all the locales
528                 String[][] names = (String[][])allNames[2]; //full name
529                 for (int i = 0; i < names.length; i++) {
530                     trueTypeFonts.setProperty(names[i][3].toLowerCase(), path);
531                 }
532                 String fullName = null;
533                 String familyName = null;
534                 names = (String[][])allNames[1]; //family name
535                 for (int k = 0; k < TTFamilyOrder.length; k += 3) {
536                     for (int i = 0; i < names.length; i++) {
537                         if (TTFamilyOrder[k].equals(names[i][0]) && TTFamilyOrder[k + 1].equals(names[i][1]) && TTFamilyOrder[k + 2].equals(names[i][2])) {
538                             familyName = names[i][3].toLowerCase();
539                             k = TTFamilyOrder.length;
540                             break;
541                         }
542                     }
543                 }
544                 if (familyName != null) {
545                     String lastName = "";
546                     names = (String[][])allNames[2]; //full name
547                     for (int i = 0; i < names.length; i++) {
548                         for (int k = 0; k < TTFamilyOrder.length; k += 3) {
549                             if (TTFamilyOrder[k].equals(names[i][0]) && TTFamilyOrder[k + 1].equals(names[i][1]) && TTFamilyOrder[k + 2].equals(names[i][2])) {
550                                 fullName = names[i][3];
551                                 if (fullName.equals(lastName))
552                                     continue;
553                                 lastName = fullName;
554                                 ArrayList tmp = (ArrayList) fontFamilies.get(familyName);
555                                 if (tmp == null) {
556                                     tmp = new ArrayList();
557                                     tmp.add(fullName);
558                                     fontFamilies.put(familyName, tmp);
559                                 }
560                                 else {
561                                     int fullNameLength = fullName.length();
562                                     boolean inserted = false;
563                                     for (int j = 0; j < tmp.size(); ++j) {
564                                         if (((String)tmp.get(j)).length() >= fullNameLength) {
565                                             tmp.add(j, fullName);
566                                             inserted = true;
567                                             break;
568                                         }
569                                     }
570                                     if (!inserted)
571                                         tmp.add(fullName);
572                                 }
573                                 break;
574                             }
575                         }
576                     }
577                 }
578             }
579             else if (path.toLowerCase().endsWith(".ttc")) {
580                 if (alias != null)
581                     System.err.println("class FontFactory: You can't define an alias for a true type collection.");
582                 String[] names = BaseFont.enumerateTTCNames(path);
583                 for (int i = 0; i < names.length; i++) {
584                     register(path + "," + i);
585                 }
586             }
587             else if (path.toLowerCase().endsWith(".afm")) {
588                 BaseFont bf = BaseFont.createFont(path, BaseFont.CP1252, false);
589                 trueTypeFonts.setProperty(bf.getPostscriptFontName().toLowerCase(), path);
590                 trueTypeFonts.setProperty((bf.getFullFontName()[0][3]).toLowerCase(), path);
591             }
592         }
593         catch(DocumentException de) {
594             // this shouldn't happen
595             throw new ExceptionConverter(de);
596         }
597         catch(IOException ioe) {
598             throw new ExceptionConverter(ioe);
599         }
600     }
601 
602     /** Register all the fonts in a directory.
603      * @param dir the directory
604      * @return the number of fonts registered
605      */
registerDirectory(String dir)606     public static int registerDirectory(String dir) {
607         int count = 0;
608         try {
609             File file = new File(dir);
610             if (!file.exists() || !file.isDirectory())
611                 return 0;
612             String files[] = file.list();
613             if (files == null)
614                 return 0;
615             for (int k = 0; k < files.length; ++k) {
616                 try {
617                     file = new File(dir, files[k]);
618                     if (file.isDirectory()) {
619                         registerDirectory(file.getPath());
620                     }
621                     else {
622                         String name = file.getPath().toLowerCase();
623                         if (name.endsWith(".ttf") || name.endsWith(".otf") || name.endsWith(".afm") || name.endsWith(".ttc")) {
624                             register(file.getPath(), null);
625                             ++count;
626                         }
627                     }
628                 }
629                 catch (Exception e) {
630                     //empty on purpose
631                 }
632             }
633         }
634         catch (Exception e) {
635             //empty on purpose
636         }
637         return count;
638     }
639 
640     /** Register fonts in some probable directories. It usually works in Windows,
641      * Linux and Solaris.
642      * @return the number of fonts registered
643      */
registerDirectories()644     public static int registerDirectories() {
645         int count = 0;
646         count += registerDirectory("c:/windows/fonts");
647         count += registerDirectory("c:/winnt/fonts");
648         count += registerDirectory("d:/windows/fonts");
649         count += registerDirectory("d:/winnt/fonts");
650         count += registerDirectory("/usr/X/lib/X11/fonts/TrueType");
651         count += registerDirectory("/usr/openwin/lib/X11/fonts/TrueType");
652         count += registerDirectory("/usr/share/fonts");
653         count += registerDirectory("/usr/X11R6/lib/X11/fonts/ttf");
654         return count;
655     }
656 
657 /**
658  * Gets a set of registered fontnames.
659  * @return a set of registered fonts
660  */
661 
getRegisteredFonts()662     public static Set getRegisteredFonts() {
663         return Chunk.getKeySet(trueTypeFonts);
664     }
665 
666 /**
667  * Gets a set of registered fontnames.
668  * @return a set of registered font families
669  */
670 
getRegisteredFamilies()671     public static Set getRegisteredFamilies() {
672         return Chunk.getKeySet(fontFamilies);
673     }
674 
675 /**
676  * Gets a set of registered fontnames.
677  * @param fontname of a font that may or may not be registered
678  * @return true if a given font is registered
679  */
680 
contains(String fontname)681     public static boolean contains(String fontname) {
682         return trueTypeFonts.containsKey(fontname.toLowerCase());
683     }
684 
685 /**
686  * Checks if a certain font is registered.
687  *
688  * @param   fontname    the name of the font that has to be checked.
689  * @return  true if the font is found
690  */
691 
isRegistered(String fontname)692     public static boolean isRegistered(String fontname) {
693         return trueTypeFonts.containsKey(fontname.toLowerCase());
694     }
695 }
696