1 /*
2 * Copyright 2007 - 2007 JEuclid, http://jeuclid.sf.net
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /* $Id: DefaultFontFactory.java 600 2008-01-22 15:12:48Z maxberger $ */
18
19 package net.sourceforge.jeuclid.font;
20
21 import java.awt.Font;
22 import java.awt.FontFormatException;
23 import java.awt.GraphicsEnvironment;
24 import java.io.File;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.util.Collection;
28 import java.util.HashMap;
29 import java.util.List;
30 import java.util.Map;
31
32 /**
33 * Concrete FontFactory implementation that does simple caching of Fonts
34 * loaded via {@link Font#createFont(int, File)} APIs.
35 *
36 * @author Ernest Mishkin
37 * @version $Revision: 600 $
38 */
39 public class DefaultFontFactory extends FontFactory {
40
41 private final Map<String, Font> fontCache;
42
43 private static final String AWT_SANSSERIF = "sansserif";
44
45 DefaultFontFactory() {
46 this.fontCache = new HashMap<String, Font>();
47 this.autoloadFontsFromAWT();
48 }
49
50 private void autoloadFontsFromAWT() {
51 final String[] fam = GraphicsEnvironment
52 .getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
53 for (final String element : fam) {
54 final Font f = new Font(element, 0, 12);
55 this.cacheFont(f);
56 }
57 }
58
59 /**
60 * Create a font object with specified properties. Font name may refer to
61 * either 'built-in' or loaded externally and 'cached' font.
62 *
63 * @param name
64 * font name or font family name
65 * @param style
66 * font style
67 * @param size
68 * font size
69 * @return Font instance
70 * @see java.awt.Font#Font(String, int, int)
71 */
72 @Override
73 public Font getFont(final String name, final int style, final int size) {
74 Font font = this.fontCache.get(name);
75 if (font == null) {
76 font = new Font(name, style, size);
77 } else {
78 font = font.deriveFont(style, size);
79 }
80 return font;
81 }
82
83 /** {@inheritDoc} */
84 @Override
85 public Font getFont(final List<String> preferredFonts,
86 final int codepoint, final int style, final int size) {
87 Font font = this.searchFontList(preferredFonts, codepoint, style,
88 size);
89 if (font == null) {
90 font = this.searchFontList(this.fontCache.keySet(), codepoint,
91 style, size);
92 }
93 if (font == null) {
94 font = this
95 .getFont(DefaultFontFactory.AWT_SANSSERIF, style, size);
96 }
97 return font;
98 }
99
100 private Font searchFontList(final Collection<String> fontList,
101 final int codepoint, final int style, final int size) {
102 for (final String fontName : fontList) {
103 final Font font = this.getFont(fontName, style, size);
104 final String desiredFont = fontName.trim();
105 if ((font.getFamily().equalsIgnoreCase(desiredFont))
106 || (font.getFontName().equalsIgnoreCase(desiredFont))) {
107 if (font.canDisplay(codepoint)) {
108 return font;
109 }
110 }
111 }
112 return null;
113 }
114
115 /**
116 * Load an external font from a file and 'register' (aka 'cache') it for
117 * future use.
118 *
119 * @param format
120 * font format (TTF or TYPE_1 currently supported by the
121 * platform)
122 * @param fontFile
123 * file which contains the font
124 * @return The newly created Font instance
125 * @throws FontFormatException
126 * if font contained in the file doesn't match the specified
127 * format
128 * @throws IOException
129 * in case of problem while reading the file
130 * @see java.awt.Font#createFont(int, File)
131 */
132 @Override
133 public Font registerFont(final int format, final File fontFile)
134 throws IOException, FontFormatException {
135
136 return this.cacheFont(Font.createFont(format, fontFile));
137 }
138
139 /**
140 * Load an external font from a stream and 'register' (aka 'cache') it for
141 * future use.
142 *
143 * @param format
144 * font format (TTF or TYPE_1 currently supported by the
145 * platform)
146 * @param fontStream
147 * file which contains the font
148 * @return The newly created Font instance
149 * @throws FontFormatException
150 * if font contained in the stream doesn't match the specified
151 * format
152 * @throws IOException
153 * in case of problem while reading the stream
154 * @see java.awt.Font#createFont(int, InputStream)
155 */
156 @Override
157 public Font registerFont(final int format, final InputStream fontStream)
158 throws IOException, FontFormatException {
159
160 return this.cacheFont(Font.createFont(format, fontStream));
161 }
162
163 /**
164 * Actually stores a font in the cache. Uses font name and font family as
165 * keys.
166 *
167 * @param font
168 * Font instance to cache
169 * @return the font instance that was cached
170 */
171 protected Font cacheFont(final Font font) {
172 this.fontCache.put(font.getFontName(), font);
173 final String family = font.getFamily();
174 // This is a safeguard. On Linux for DejaVu Sans Oblique we get:
175 // Name: DejaVu Sans Oblique
176 // Family: DejaVu Sans
177 // For DejaVu Sans we get:
178 // Name: DejaVu Sans
179 // Family: DejaVu Sans
180 // And of course we don't want the oblique font to override the
181 // regular font...
182 if (!this.fontCache.containsKey(family)) {
183 this.fontCache.put(font.getFamily(), font);
184 }
185 return font;
186 }
187
188 }