001/*
002 * SVG Salamander
003 * Copyright (c) 2004, Mark McKay
004 * All rights reserved.
005 *
006 * Redistribution and use in source and binary forms, with or 
007 * without modification, are permitted provided that the following
008 * conditions are met:
009 *
010 *   - Redistributions of source code must retain the above 
011 *     copyright notice, this list of conditions and the following
012 *     disclaimer.
013 *   - Redistributions in binary form must reproduce the above
014 *     copyright notice, this list of conditions and the following
015 *     disclaimer in the documentation and/or other materials 
016 *     provided with the distribution.
017 *
018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
019 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
020 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
021 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
022 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
023 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
025 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
026 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
027 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
028 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
029 * OF THE POSSIBILITY OF SUCH DAMAGE. 
030 * 
031 * Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
032 * projects can be found at http://www.kitfox.com
033 *
034 * Created on April 24, 2015
035 */
036package com.kitfox.svg.util;
037
038import com.kitfox.svg.Font;
039import com.kitfox.svg.FontFace;
040import com.kitfox.svg.Glyph;
041import com.kitfox.svg.MissingGlyph;
042import java.awt.Canvas;
043import java.awt.FontMetrics;
044import java.awt.GraphicsEnvironment;
045import java.awt.font.FontRenderContext;
046import java.awt.font.GlyphMetrics;
047import java.awt.font.GlyphVector;
048import java.util.HashMap;
049import java.util.HashSet;
050import java.util.Locale;
051import java.util.regex.Matcher;
052import java.util.regex.Pattern;
053
054/**
055 *
056 * @author kitfox
057 */
058public class FontSystem extends Font
059{
060    java.awt.Font sysFont;
061    FontMetrics fm;
062
063    HashMap<String, Glyph> glyphCache = new HashMap<String, Glyph>();
064    
065    static HashSet<String> sysFontNames = new HashSet<String>();
066    
067    public static boolean checkIfSystemFontExists(String fontName)
068    {
069        if (sysFontNames.isEmpty())
070        {
071            for (String name: GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(Locale.ENGLISH))
072            {
073                sysFontNames.add(name);
074            }
075        }
076        
077        return sysFontNames.contains(fontName);
078    }
079    
080    public static FontSystem createFont(String fontFamily, int fontStyle, int fontWeight, int fontSize)
081    {
082        String[] families = fontFamily.split(",");
083        for (String fontName: families)
084        {
085            String javaFontName = mapJavaFontName(fontName);
086            if (checkIfSystemFontExists(javaFontName))
087            {
088                return new FontSystem(javaFontName, fontStyle, fontWeight, (int) fontSize);
089            }
090        }
091        
092        return null;
093    }
094
095    private static String mapJavaFontName(String fontName)
096    {
097        if ("serif".equals(fontName))
098        {
099            return java.awt.Font.SERIF;
100        }
101        else if ("sans-serif".equals(fontName))
102        {
103            return java.awt.Font.SANS_SERIF;
104        }
105        else if ("monospace".equals(fontName))
106        {
107            return java.awt.Font.MONOSPACED;
108        }
109        return fontName;
110    }
111
112    private FontSystem(String fontFamily, int fontStyle, int fontWeight, int fontSize)
113    {
114        int style;
115        switch (fontStyle)
116        {
117            case com.kitfox.svg.Text.TXST_ITALIC:
118                style = java.awt.Font.ITALIC;
119                break;
120            default:
121                style = java.awt.Font.PLAIN;
122                break;
123        }
124
125        int weight;
126        switch (fontWeight)
127        {
128            case com.kitfox.svg.Text.TXWE_BOLD:
129            case com.kitfox.svg.Text.TXWE_BOLDER:
130                weight = java.awt.Font.BOLD;
131                break;
132            default:
133                weight = java.awt.Font.PLAIN;
134                break;
135        }
136        
137        sysFont = new java.awt.Font(fontFamily, style | weight, (int) fontSize);
138        
139        Canvas c = new Canvas();
140        fm = c.getFontMetrics(sysFont);
141        
142        FontFace face = new FontFace();
143        face.setAscent(fm.getAscent());
144        face.setDescent(fm.getDescent());
145        face.setUnitsPerEm(fm.charWidth('M'));
146        setFontFace(face);
147    }
148
149    @Override
150    public MissingGlyph getGlyph(String unicode)
151    {
152        FontRenderContext frc = new FontRenderContext(null, true, true);
153        GlyphVector vec = sysFont.createGlyphVector(frc, unicode);
154        
155        Glyph glyph = (Glyph)glyphCache.get(unicode);
156        if (glyph == null)
157        {
158            glyph = new Glyph();
159            glyph.setPath(vec.getGlyphOutline(0));
160
161            GlyphMetrics gm = vec.getGlyphMetrics(0);
162            glyph.setHorizAdvX(gm.getAdvanceX());
163            glyph.setVertAdvY(gm.getAdvanceY());
164            glyph.setVertOriginX(0);
165            glyph.setVertOriginY(0);
166            
167            glyphCache.put(unicode, glyph);
168        }
169        
170        return glyph;
171    }
172    
173    
174}