/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.renderer.style; import java.awt.Font; import java.awt.FontFormatException; import java.awt.GraphicsEnvironment; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; /** * Lookup and caches font definitions for faster retrieval * * @author Andrea Aime - TOPP * * @source $URL$ */ public class FontCache { /** The logger for the rendering module. */ private static final Logger LOGGER = org.geotools.util.logging.Logging .getLogger("org.geotools.rendering"); static FontCache defaultInstance; /** Set containing the font families known of this machine */ Set<String> systemFonts = new HashSet<String>(); /** Fonts already loaded */ Map<String, Font> loadedFonts = new ConcurrentHashMap<String, Font>(); /** * Returns the default, system wide font cache * * @deprecated Use {@link #getDefaultInstance()} instead */ public static FontCache getDefaultInsance() { return getDefaultInstance(); } /** * Returns the default, system wide font cache * * @since 2.6 */ public static FontCache getDefaultInstance() { if (defaultInstance == null) { defaultInstance = new FontCache(); } return defaultInstance; } public synchronized Font getFont(String requestedFont) { // see if the font has already been loaded java.awt.Font javaFont = null; if (LOGGER.isLoggable(Level.FINEST)) { LOGGER.finest("trying to load " + requestedFont); } if (loadedFonts.containsKey(requestedFont)) { return loadedFonts.get(requestedFont); } if (LOGGER.isLoggable(Level.FINEST)) { LOGGER.finest("not already loaded"); } // if not, try to load from the java runtime or as an URL if (getSystemFonts().contains(requestedFont)) { javaFont = new java.awt.Font(requestedFont, Font.PLAIN, 12); } else { if (LOGGER.isLoggable(Level.FINEST)) { LOGGER.finest("not a system font"); } javaFont = loadFromUrl(requestedFont); } // log the result and exit if (javaFont == null) { if (LOGGER.isLoggable(Level.WARNING)) { LOGGER.fine("Could not load font " + requestedFont); } } else { loadedFonts.put(requestedFont, javaFont); } return javaFont; } /** * Tries to load the specified font name as a URL * * @param fontUrl * @return */ java.awt.Font loadFromUrl(String fontUrl) { // may be its a file or url InputStream is = null; if (fontUrl.startsWith("http") || fontUrl.startsWith("file:")) { try { URL url = new URL(fontUrl); is = url.openStream(); } catch (MalformedURLException mue) { // this may be ok - but we should mention it if (LOGGER.isLoggable(Level.INFO)) { LOGGER.info("Bad url in SLDStyleFactory " + fontUrl + "\n" + mue); } } catch (IOException ioe) { // we'll ignore this for the moment if (LOGGER.isLoggable(Level.INFO)) { LOGGER.info("IO error in SLDStyleFactory " + fontUrl + "\n" + ioe); } } } else { if (LOGGER.isLoggable(Level.FINEST)) { LOGGER.finest("not a URL"); } File file = new File(fontUrl); try { is = new FileInputStream(file); } catch (FileNotFoundException fne) { // this may be ok - but we should mention it if (LOGGER.isLoggable(Level.INFO)) { LOGGER.info("Bad file name in SLDStyleFactory" + fontUrl + "\n" + fne); } } } // make sure we have anything to load if (is == null) { if (LOGGER.isLoggable(Level.INFO)) { LOGGER.info("null input stream, could not load the font"); } return null; } if (LOGGER.isLoggable(Level.FINEST)) { LOGGER.finest("about to load"); } try { return java.awt.Font.createFont(java.awt.Font.TRUETYPE_FONT, is); } catch (FontFormatException ffe) { if (LOGGER.isLoggable(Level.INFO)) { LOGGER.info("Font format error in SLDStyleFactory " + fontUrl + "\n" + ffe); } return null; } catch (IOException ioe) { // we'll ignore this for the moment if (LOGGER.isLoggable(Level.INFO)) { LOGGER.info("IO error in SLDStyleFactory " + fontUrl + "\n" + ioe); } return null; } } /** * Adds the specified font in the font cache. Useful if you want to load fonts that are not * installed in the Operating System and cannot provide a full path to fonts either. * * @param f */ public void registerFont(Font f) { loadedFonts.put(f.getName(), f); } /** * Resets the font loading cache. If any font was manually registered, it will have to be * registered again */ public synchronized void resetCache() { if (systemFonts != null) { systemFonts.clear(); } if (loadedFonts != null) { loadedFonts.clear(); } } /** * Lazily loads up the system fonts cache * * @return */ private Set<String> getSystemFonts() { // make sure we load the known font families once. if (systemFonts.size() == 0) { synchronized (systemFonts) { if (systemFonts.size() == 0) { GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); Set<String> fontset = new HashSet<String>(); // register both faces and families Font[] fonts = ge.getAllFonts(); for (Font font : fonts) { fontset.add(font.getName()); fontset.add(font.getFamily()); } if (LOGGER.isLoggable(Level.FINEST)) { LOGGER.finest("there are " + fontset.size() + " fonts available"); } systemFonts.addAll(fontset); } } } return systemFonts; } /** * Returns the set of font families and font faces available in the system and those manually * loaded into the cache * * @return */ public Set<String> getAvailableFonts() { Set<String> availableFonts = new HashSet<String>(); availableFonts.addAll(getSystemFonts()); availableFonts.addAll(loadedFonts.keySet()); return availableFonts; } }