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}