2
* Copyright (c) 2008, intarsys consulting GmbH
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions are met:
7
* - Redistributions of source code must retain the above copyright notice,
8
* this list of conditions and the following disclaimer.
10
* - Redistributions in binary form must reproduce the above copyright notice,
11
* this list of conditions and the following disclaimer in the documentation
12
* and/or other materials provided with the distribution.
14
* - Neither the name of intarsys nor the names of its contributors may be used
15
* to endorse or promote products derived from this software without specific
16
* prior written permission.
18
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
* POSSIBILITY OF SUCH DAMAGE.
30
package de.intarsys.cwt.font;
34
import java.io.IOException;
35
import java.io.InputStream;
37
import java.util.ArrayList;
38
import java.util.Enumeration;
39
import java.util.List;
40
import java.util.logging.Level;
41
import java.util.logging.Logger;
43
import sun.font.FontManager;
44
import de.intarsys.cwt.freetype.Face;
45
import de.intarsys.cwt.freetype.Freetype;
46
import de.intarsys.cwt.freetype.Library;
47
import de.intarsys.tools.installresource.InstallFileList;
48
import de.intarsys.tools.locator.FileLocator;
49
import de.intarsys.tools.stream.StreamTools;
54
public class FontEnvironment {
56
private static final Logger Log = PACKAGE.Log;
58
private static FontEnvironment Unique = new FontEnvironment();
60
static public FontEnvironment get() {
64
static public void set(FontEnvironment environment) {
68
private List<ClassLoader> fontClassLoaders = new ArrayList<ClassLoader>();
70
private List<File> fontDirectories = new ArrayList<File>();
72
private List<File> fontFiles = new ArrayList<File>();
74
private boolean registeredSystem = false;
76
private boolean registeredUser = false;
78
public FontEnvironment() {
79
registerFontClassLoader(getClass().getClassLoader());
82
synchronized public ClassLoader[] getFontClassLoaders() {
83
return fontClassLoaders
84
.toArray(new ClassLoader[fontClassLoaders.size()]);
87
synchronized public File[] getFontDirectories() {
88
return fontDirectories.toArray(new File[fontDirectories.size()]);
91
synchronized public File[] getFontFiles() {
92
return fontFiles.toArray(new File[fontFiles.size()]);
96
* This method determines the system's font directories.
98
* @return an array containing the font directory paths found on the local
101
synchronized public File[] getSystemFontDirectories() {
102
String definition = null;
103
// force FontManager initialization
104
Font.decode("dummy").getFamily(); //$NON-NLS-1$
105
definition = sun.font.SunFontManager.getInstance().getPlatformFontPath(true);
106
if (definition == null) {
109
String[] names = definition.split(System.getProperty("path.separator")); //$NON-NLS-1$
110
File[] files = new File[names.length];
111
for (int i = 0; i < names.length; i++) {
112
files[i] = new File(names[i]);
117
protected void loadFontClassLoader(Library library, ClassLoader loader) {
119
InstallFileList installer = new InstallFileList("fonts",
120
"fonts.list", false);
122
File[] roots = installer.getFiles();
123
for (int i = 0; i < roots.length; i++) {
124
File root = roots[i];
125
File[] fontFiles = root.listFiles();
126
for (int j = 0; j < fontFiles.length; j++) {
127
File file = fontFiles[j];
129
processFontFile(library, file);
130
} catch (IOException e) {
131
Log.log(Level.WARNING, "error loading font '"
132
+ file.getName() + "'", e);
137
} catch (IOException e) {
138
Log.log(Level.WARNING,
139
"error looking up 'font/fonts.list' resources", e);
143
protected void loadFontDirectory(Library library, File directory) {
144
if (!directory.exists()) {
147
if (!directory.isDirectory()) {
150
File[] files = directory.listFiles();
154
for (int i = 0; i < files.length; i++) {
155
File file = files[i];
156
loadFontFile(library, file);
160
protected void loadFontFile(Library library, File file) {
161
if (!file.isFile()) {
164
String filepath = file.getAbsolutePath();
167
* the absolute path/canonical path check is used to find out if the
168
* file path contains a symbolic link. if so we can ignore the file
169
* because it will also show up in another directory as a "real"
172
if (!filepath.equals(file.getCanonicalPath())) {
175
} catch (IOException ex) {
178
loadFontUnchecked(library, filepath);
181
protected void loadFontMapClassLoader(Library library, ClassLoader loader) {
183
Enumeration<URL> urls = loader.getResources("fonts/fonts.maps");
184
while (urls.hasMoreElements()) {
185
URL url = urls.nextElement();
186
InputStream is = null;
188
is = url.openStream();
189
parseMaps(library, loader, is);
190
} catch (IOException e) {
191
Log.log(Level.WARNING,
192
"error loading 'fonts/fonts.maps' from '" + url
195
StreamTools.close(is);
198
} catch (IOException e) {
199
Log.log(Level.WARNING,
200
"error looking up 'font/fonts.maps' resources", e);
204
protected IFont loadFontUnchecked(Library library, String filepath) {
205
FileLocator locator = new FileLocator(filepath);
206
Face face = library.newFace(filepath, 0);
210
font = GenericFont.createNew(locator, face);
211
FontRegistry.get().registerFont(font);
217
// Log.log(Level.WARNING, "can't register font for " + filepath);
222
protected void loadSystemFonts(Library library) {
224
files = getSystemFontDirectories();
225
for (int i = 0; i < files.length; i++) {
226
File directory = files[i];
227
loadFontDirectory(library, directory);
231
protected void loadUserFonts(Library library) {
233
files = getFontDirectories();
234
for (int i = 0; i < files.length; i++) {
235
File directory = files[i];
236
loadFontDirectory(library, directory);
238
files = getFontFiles();
239
for (int i = 0; i < files.length; i++) {
240
File file = files[i];
241
loadFontFile(library, file);
243
ClassLoader[] loaders = getFontClassLoaders();
244
for (int i = 0; i < loaders.length; i++) {
245
ClassLoader loader = loaders[i];
246
loadFontClassLoader(library, loader);
247
loadFontMapClassLoader(library, loader);
251
protected void parseMaps(Library library, ClassLoader loader, InputStream is)
253
StringBuilder sb = new StringBuilder();
257
String map = sb.toString().trim();
258
processFontMap(library, loader, map);
266
String map = sb.toString().trim();
267
processFontMap(library, loader, map);
270
protected void processFontFile(Library library, File file)
272
IFont font = loadFontUnchecked(library, file.getAbsolutePath());
276
FontTools.mapFont(font.getFontName(), font);
279
protected void processFontMap(Library library, ClassLoader loader,
280
String map) throws IOException {
281
if (map.length() == 0 || map.startsWith("#")) {
284
String[] split = map.split("\\=");
285
if (split.length < 2) {
288
FontTools.mapAlias(split[0], split[1]);
291
public synchronized void registerFontClassLoader(ClassLoader loader) {
292
fontClassLoaders.add(loader);
295
public synchronized void registerFontDirectory(File directory) {
296
fontDirectories.add(directory);
299
synchronized public void registerFontFile(File file) {
303
synchronized public boolean registerSystemFonts() {
304
if (registeredSystem) {
307
registeredSystem = true;
308
Library library = Freetype.initFreeType();
310
loadSystemFonts(library);
312
library.doneFreeType();
317
synchronized public boolean registerUserFonts() {
318
if (registeredUser) {
321
registeredUser = true;
322
Library library = Freetype.initFreeType();
324
loadUserFonts(library);
326
library.doneFreeType();