1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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.net.URL;
28 import java.util.Collection;
29 import java.util.HashMap;
30 import java.util.HashSet;
31 import java.util.List;
32 import java.util.Locale;
33 import java.util.Map;
34 import java.util.Set;
35
36 import javax.annotation.concurrent.ThreadSafe;
37
38 import org.apache.commons.logging.Log;
39 import org.apache.commons.logging.LogFactory;
40 import org.apache.xmlgraphics.util.ClasspathResource;
41
42
43
44
45
46
47
48 @ThreadSafe
49 public class DefaultFontFactory extends FontFactory {
50
51 private static final int CACHE_FONT_SIZE = 12;
52
53 private static final int NUM_STYLES = 4;
54
55
56
57
58 private static final Log LOGGER = LogFactory
59 .getLog(DefaultFontFactory.class);
60
61 private final Map<String, Font[]> fontCache = new HashMap<String, Font[]>();
62
63 DefaultFontFactory() {
64 this.autoloadFontsFromAWT();
65 this.autoloadFontsFromClasspath();
66 }
67
68 private void autoloadFontsFromAWT() {
69 final String[] fam = GraphicsEnvironment
70 .getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
71 for (final String element : fam) {
72 for (int i = 0; i < DefaultFontFactory.NUM_STYLES; i++) {
73 final Font f = new Font(element, i,
74 DefaultFontFactory.CACHE_FONT_SIZE);
75 this.cacheFont(f);
76 }
77 }
78 }
79
80 @SuppressWarnings("unchecked")
81 private void autoloadFontsFromClasspath() {
82 final List<URL> fonts = ClasspathResource.getInstance()
83 .listResourcesOfMimeType("application/x-font");
84 for (final URL u : fonts) {
85 try {
86 try {
87 this.cacheFont(Font.createFont(Font.TRUETYPE_FONT, u
88 .openStream()));
89 } catch (final FontFormatException e) {
90 try {
91 this.cacheFont(Font.createFont(Font.TYPE1_FONT, u
92 .openStream()));
93 } catch (final FontFormatException e1) {
94 DefaultFontFactory.LOGGER.warn(e.getMessage());
95 }
96 }
97 } catch (final IOException e) {
98 DefaultFontFactory.LOGGER.warn(e.getMessage());
99 }
100 }
101
102 }
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117 @Override
118 public Font getFont(final String name, final int style, final float size) {
119 Font font;
120 synchronized (this.fontCache) {
121 final Font[] fonts = this.fontCache.get(name
122 .toLowerCase(Locale.ENGLISH));
123 if (fonts == null) {
124 font = this.cacheFont(
125 new Font(name, Font.PLAIN,
126 DefaultFontFactory.CACHE_FONT_SIZE))
127 .deriveFont(style, size);
128 } else {
129 font = fonts[style];
130 if (font == null) {
131 font = fonts[0].deriveFont(style, size);
132 fonts[style] = font;
133 } else {
134 font = font.deriveFont(size);
135 }
136 }
137 }
138 return font;
139 }
140
141
142 @Override
143 public Font getFont(final List<String> preferredFonts,
144 final int codepoint, final int style, final float size) {
145 Font font = this.searchFontList(preferredFonts, codepoint, style,
146 size);
147 if (font == null) {
148 font = this.searchFontList(this.fontCache.keySet(), codepoint,
149 style, size);
150 }
151 return font;
152 }
153
154 private Font searchFontList(final Collection<String> fontList,
155 final int codepoint, final int style, final float size) {
156 for (final String fontName : fontList) {
157 final Font font = this.getFont(fontName, style, size);
158 final String desiredFont = fontName.trim();
159 if (((font.getFamily().equalsIgnoreCase(desiredFont)) || (font
160 .getFontName().equalsIgnoreCase(desiredFont)))
161 && (font.canDisplay(codepoint))) {
162 return font;
163 }
164 }
165 return null;
166 }
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185 @Override
186 public Font registerFont(final int format, final File fontFile)
187 throws IOException, FontFormatException {
188
189 return this.cacheFont(Font.createFont(format, fontFile));
190 }
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209 @Override
210 public Font registerFont(final int format, final InputStream fontStream)
211 throws IOException, FontFormatException {
212
213 return this.cacheFont(Font.createFont(format, fontStream));
214 }
215
216
217
218
219
220
221
222
223
224 private Font cacheFont(final Font font) {
225 final String family = font.getFamily().trim().toLowerCase(
226 Locale.ENGLISH);
227 final String fontname = font.getName().trim().toLowerCase(
228 Locale.ENGLISH);
229 int style = font.getStyle();
230 if (fontname.contains("italic")) {
231 style |= Font.ITALIC;
232 }
233 if (fontname.contains("oblique")) {
234 style |= Font.ITALIC;
235 }
236 if (fontname.contains("bold")) {
237 style |= Font.BOLD;
238 }
239 this.cacheFontWithStyle(font, family, style);
240 this.cacheFontWithStyle(font, fontname, style);
241 return font;
242 }
243
244 private void cacheFontWithStyle(final Font font, final String cacheName,
245 final int style) {
246 synchronized (this.fontCache) {
247 Font[] fonts = this.fontCache.get(cacheName);
248 if (fonts == null) {
249 fonts = new Font[DefaultFontFactory.NUM_STYLES];
250 this.fontCache.put(cacheName, fonts);
251 fonts[0] = font;
252 }
253 fonts[style] = font;
254 }
255 }
256
257
258 @Override
259 public Set<String> listFontNames() {
260 final Set<String> retVal;
261 synchronized (this.fontCache) {
262 retVal = new HashSet<String>(this.fontCache.keySet());
263 }
264 return retVal;
265 }
266 }