Coverage Report - net.sourceforge.jeuclid.font.DefaultFontFactory
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultFontFactory
74%
55/74
75%
21/28
2,636
 
 1  
 /*
 2  
  * Copyright 2007 - 2008 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,v 2bab6eb875e8 2010/08/11 16:45:50 max $ */
 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  
  * Concrete FontFactory implementation that does simple caching of Fonts
 44  
  * loaded via {@link Font#createFont(int, File)} APIs.
 45  
  * 
 46  
  * @version $Revision: 2bab6eb875e8 $
 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  
      * Logger for this class
 57  
      */
 58  209
     private static final Log LOGGER = LogFactory
 59  
             .getLog(DefaultFontFactory.class);
 60  
 
 61  209
     private final Map<String, Font[]> fontCache = new HashMap<String, Font[]>();
 62  
 
 63  209
     DefaultFontFactory() {
 64  209
         this.autoloadFontsFromAWT();
 65  209
         this.autoloadFontsFromClasspath();
 66  209
     }
 67  
 
 68  
     private void autoloadFontsFromAWT() {
 69  209
         final String[] fam = GraphicsEnvironment
 70  
                 .getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
 71  25075
         for (final String element : fam) {
 72  124330
             for (int i = 0; i < DefaultFontFactory.NUM_STYLES; i++) {
 73  99464
                 final Font f = new Font(element, i,
 74  
                         DefaultFontFactory.CACHE_FONT_SIZE);
 75  99464
                 this.cacheFont(f);
 76  
             }
 77  
         }
 78  209
     }
 79  
 
 80  
     @SuppressWarnings("unchecked")
 81  
     private void autoloadFontsFromClasspath() {
 82  209
         final List<URL> fonts = ClasspathResource.getInstance()
 83  
                 .listResourcesOfMimeType("application/x-font");
 84  209
         for (final URL u : fonts) {
 85  
             try {
 86  
                 try {
 87  0
                     this.cacheFont(Font.createFont(Font.TRUETYPE_FONT, u
 88  
                             .openStream()));
 89  0
                 } catch (final FontFormatException e) {
 90  
                     try {
 91  0
                         this.cacheFont(Font.createFont(Font.TYPE1_FONT, u
 92  
                                 .openStream()));
 93  0
                     } catch (final FontFormatException e1) {
 94  0
                         DefaultFontFactory.LOGGER.warn(e.getMessage());
 95  0
                     }
 96  0
                 }
 97  0
             } catch (final IOException e) {
 98  0
                 DefaultFontFactory.LOGGER.warn(e.getMessage());
 99  0
             }
 100  
         }
 101  
 
 102  209
     }
 103  
 
 104  
     /**
 105  
      * Create a font object with specified properties. Font name may refer to
 106  
      * either 'built-in' or loaded externally and 'cached' font.
 107  
      * 
 108  
      * @param name
 109  
      *            font name or font family name
 110  
      * @param style
 111  
      *            font style
 112  
      * @param size
 113  
      *            font size
 114  
      * @return Font instance
 115  
      * @see java.awt.Font#Font(String, int, int)
 116  
      */
 117  
     @Override
 118  
     public Font getFont(final String name, final int style, final float size) {
 119  
         Font font;
 120  245412
         synchronized (this.fontCache) {
 121  245412
             final Font[] fonts = this.fontCache.get(name
 122  
                     .toLowerCase(Locale.ENGLISH));
 123  245412
             if (fonts == null) {
 124  1880
                 font = this.cacheFont(
 125  
                         new Font(name, Font.PLAIN,
 126  
                                 DefaultFontFactory.CACHE_FONT_SIZE))
 127  
                         .deriveFont(style, size);
 128  
             } else {
 129  243532
                 font = fonts[style];
 130  243532
                 if (font == null) {
 131  1463
                     font = fonts[0].deriveFont(style, size);
 132  1463
                     fonts[style] = font;
 133  
                 } else {
 134  242069
                     font = font.deriveFont(size);
 135  
                 }
 136  
             }
 137  245412
         }
 138  245412
         return font;
 139  
     }
 140  
 
 141  
     /** {@inheritDoc} */
 142  
     @Override
 143  
     public Font getFont(final List<String> preferredFonts,
 144  
             final int codepoint, final int style, final float size) {
 145  81108
         Font font = this.searchFontList(preferredFonts, codepoint, style,
 146  
                 size);
 147  81108
         if (font == null) {
 148  0
             font = this.searchFontList(this.fontCache.keySet(), codepoint,
 149  
                     style, size);
 150  
         }
 151  81108
         return font;
 152  
     }
 153  
 
 154  
     private Font searchFontList(final Collection<String> fontList,
 155  
             final int codepoint, final int style, final float size) {
 156  81108
         for (final String fontName : fontList) {
 157  244578
             final Font font = this.getFont(fontName, style, size);
 158  244578
             final String desiredFont = fontName.trim();
 159  244578
             if (((font.getFamily().equalsIgnoreCase(desiredFont)) || (font
 160  
                     .getFontName().equalsIgnoreCase(desiredFont)))
 161  
                     && (font.canDisplay(codepoint))) {
 162  81108
                 return font;
 163  
             }
 164  163470
         }
 165  0
         return null;
 166  
     }
 167  
 
 168  
     /**
 169  
      * Load an external font from a file and 'register' (aka 'cache') it for
 170  
      * future use.
 171  
      * 
 172  
      * @param format
 173  
      *            font format (TTF or TYPE_1 currently supported by the
 174  
      *            platform)
 175  
      * @param fontFile
 176  
      *            file which contains the font
 177  
      * @return The newly created Font instance
 178  
      * @throws FontFormatException
 179  
      *             if font contained in the file doesn't match the specified
 180  
      *             format
 181  
      * @throws IOException
 182  
      *             in case of problem while reading the file
 183  
      * @see java.awt.Font#createFont(int, File)
 184  
      */
 185  
     @Override
 186  
     public Font registerFont(final int format, final File fontFile)
 187  
             throws IOException, FontFormatException {
 188  
 
 189  0
         return this.cacheFont(Font.createFont(format, fontFile));
 190  
     }
 191  
 
 192  
     /**
 193  
      * Load an external font from a stream and 'register' (aka 'cache') it for
 194  
      * future use.
 195  
      * 
 196  
      * @param format
 197  
      *            font format (TTF or TYPE_1 currently supported by the
 198  
      *            platform)
 199  
      * @param fontStream
 200  
      *            file which contains the font
 201  
      * @return The newly created Font instance
 202  
      * @throws FontFormatException
 203  
      *             if font contained in the stream doesn't match the specified
 204  
      *             format
 205  
      * @throws IOException
 206  
      *             in case of problem while reading the stream
 207  
      * @see java.awt.Font#createFont(int, InputStream)
 208  
      */
 209  
     @Override
 210  
     public Font registerFont(final int format, final InputStream fontStream)
 211  
             throws IOException, FontFormatException {
 212  
 
 213  209
         return this.cacheFont(Font.createFont(format, fontStream));
 214  
     }
 215  
 
 216  
     /**
 217  
      * Actually stores a font in the cache. Uses font name and font family as
 218  
      * keys.
 219  
      * 
 220  
      * @param font
 221  
      *            Font instance to cache
 222  
      * @return the font instance that was cached
 223  
      */
 224  
     private Font cacheFont(final Font font) {
 225  101552
         final String family = font.getFamily().trim().toLowerCase(
 226  
                 Locale.ENGLISH);
 227  101552
         final String fontname = font.getName().trim().toLowerCase(
 228  
                 Locale.ENGLISH);
 229  101552
         int style = font.getStyle();
 230  101552
         if (fontname.contains("italic")) {
 231  0
             style |= Font.ITALIC;
 232  
         }
 233  101552
         if (fontname.contains("oblique")) {
 234  0
             style |= Font.ITALIC;
 235  
         }
 236  101552
         if (fontname.contains("bold")) {
 237  836
             style |= Font.BOLD;
 238  
         }
 239  101552
         this.cacheFontWithStyle(font, family, style);
 240  101552
         this.cacheFontWithStyle(font, fontname, style);
 241  101552
         return font;
 242  
     }
 243  
 
 244  
     private void cacheFontWithStyle(final Font font, final String cacheName,
 245  
             final int style) {
 246  203104
         synchronized (this.fontCache) {
 247  203104
             Font[] fonts = this.fontCache.get(cacheName);
 248  203104
             if (fonts == null) {
 249  26954
                 fonts = new Font[DefaultFontFactory.NUM_STYLES];
 250  26954
                 this.fontCache.put(cacheName, fonts);
 251  26954
                 fonts[0] = font;
 252  
             }
 253  203104
             fonts[style] = font;
 254  203104
         }
 255  203104
     }
 256  
 
 257  
     /** {@inheritDoc} */
 258  
     @Override
 259  
     public Set<String> listFontNames() {
 260  
         final Set<String> retVal;
 261  0
         synchronized (this.fontCache) {
 262  0
             retVal = new HashSet<String>(this.fontCache.keySet());
 263  0
         }
 264  0
         return retVal;
 265  
     }
 266  
 }