1 /* 2 * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Sun designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Sun in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 22 * CA 95054 USA or visit www.sun.com if you need additional information or 23 * have any questions. 24 */ 25 26 package sun.font; 27 28 import java.awt.Font; 29 import java.util.HashMap; 30 import java.util.concurrent.ConcurrentHashMap; 31 import java.util.Locale; 32 33 public class FontFamily { 34 35 private static ConcurrentHashMap<String, FontFamily> 36 familyNameMap = new ConcurrentHashMap<String, FontFamily>(); 37 private static HashMap<String, FontFamily> allLocaleNames; 38 39 protected String familyName; 40 protected Font2D plain; 41 protected Font2D bold; 42 protected Font2D italic; 43 protected Font2D bolditalic; 44 protected boolean logicalFont = false; 45 protected int familyRank; 46 47 public static FontFamily getFamily(String name) { 48 return familyNameMap.get(name.toLowerCase(Locale.ENGLISH)); 49 } 50 51 public static String[] getAllFamilyNames() { 52 return null; 53 } 54 55 /* Only for use by FontManager.deRegisterBadFont(..). 56 * If this was the only font in the family, the family is removed 57 * from the map 58 */ 59 static void remove(Font2D font2D) { 60 61 String name = font2D.getFamilyName(Locale.ENGLISH); 62 FontFamily family = getFamily(name); 63 if (family == null) { 64 return; 65 } 66 if (family.plain == font2D) { 67 family.plain = null; 68 } 69 if (family.bold == font2D) { 70 family.bold = null; 71 } 72 if (family.italic == font2D) { 73 family.italic = null; 74 } 75 if (family.bolditalic == font2D) { 76 family.bolditalic = null; 77 } 78 if (family.plain == null && family.bold == null && 79 family.plain == null && family.bold == null) { 80 familyNameMap.remove(name); 81 } 82 } 83 84 public FontFamily(String name, boolean isLogFont, int rank) { 85 logicalFont = isLogFont; 86 familyName = name; 87 familyRank = rank; 88 familyNameMap.put(name.toLowerCase(Locale.ENGLISH), this); 89 } 90 91 /* Create a family for created fonts which aren't listed in the 92 * main map. 93 */ 94 FontFamily(String name) { 95 logicalFont = false; 96 familyName = name; 97 familyRank = Font2D.DEFAULT_RANK; 98 } 99 100 public String getFamilyName() { 101 return familyName; 102 } 103 104 public int getRank() { 105 return familyRank; 106 } 107 108 public void setFont(Font2D font, int style) { 109 if (font.getRank() > familyRank) { 110 if (FontUtilities.isLogging()) { 111 FontUtilities.getLogger() 112 .warning("Rejecting adding " + font + 113 " of lower rank " + font.getRank() + 114 " to family " + this + 115 " of rank " + familyRank); 116 } 117 return; 118 } 119 120 switch (style) { 121 122 case Font.PLAIN: 123 plain = font; 124 break; 125 126 case Font.BOLD: 127 bold = font; 128 break; 129 130 case Font.ITALIC: 131 italic = font; 132 break; 133 134 case Font.BOLD|Font.ITALIC: 135 bolditalic = font; 136 break; 137 138 default: 139 break; 140 } 141 } 142 143 public Font2D getFontWithExactStyleMatch(int style) { 144 145 switch (style) { 146 147 case Font.PLAIN: 148 return plain; 149 150 case Font.BOLD: 151 return bold; 152 153 case Font.ITALIC: 154 return italic; 155 156 case Font.BOLD|Font.ITALIC: 157 return bolditalic; 158 159 default: 160 return null; 161 } 162 } 163 164 /* REMIND: if the callers of this method are operating in an 165 * environment in which not all fonts are registered, the returned 166 * font may be a algorithmically styled one, where in fact if loadfonts 167 * were executed, a styled font may be located. Our present "solution" 168 * to this is to register all fonts in a directory and assume that this 169 * registered all the styles of a font, since they would all be in the 170 * same location. 171 */ 172 public Font2D getFont(int style) { 173 174 switch (style) { 175 176 case Font.PLAIN: 177 return plain; 178 179 case Font.BOLD: 180 if (bold != null) { 181 return bold; 182 } else if (plain != null && plain.canDoStyle(style)) { 183 return plain; 184 } else { 185 return null; 186 } 187 188 case Font.ITALIC: 189 if (italic != null) { 190 return italic; 191 } else if (plain != null && plain.canDoStyle(style)) { 192 return plain; 193 } else { 194 return null; 195 } 196 197 case Font.BOLD|Font.ITALIC: 198 if (bolditalic != null) { 199 return bolditalic; 200 } else if (italic != null && italic.canDoStyle(style)) { 201 return italic; 202 } else if (bold != null && bold.canDoStyle(style)) { 203 return italic; 204 } else if (plain != null && plain.canDoStyle(style)) { 205 return plain; 206 } else { 207 return null; 208 } 209 default: 210 return null; 211 } 212 } 213 214 /* Only to be called if getFont(style) returns null 215 * This method will only return null if the family is completely empty! 216 * Note that it assumes the font of the style you need isn't in the 217 * family. The logic here is that if we must substitute something 218 * it might as well be from the same family. 219 */ 220 Font2D getClosestStyle(int style) { 221 222 switch (style) { 223 /* if you ask for a plain font try to return a non-italic one, 224 * then a italic one, finally a bold italic one */ 225 case Font.PLAIN: 226 if (bold != null) { 227 return bold; 228 } else if (italic != null) { 229 return italic; 230 } else { 231 return bolditalic; 232 } 233 234 /* if you ask for a bold font try to return a non-italic one, 235 * then a bold italic one, finally an italic one */ 236 case Font.BOLD: 237 if (plain != null) { 238 return plain; 239 } else if (bolditalic != null) { 240 return bolditalic; 241 } else { 242 return italic; 243 } 244 245 /* if you ask for a italic font try to return a bold italic one, 246 * then a plain one, finally an bold one */ 247 case Font.ITALIC: 248 if (bolditalic != null) { 249 return bolditalic; 250 } else if (plain != null) { 251 return plain; 252 } else { 253 return bold; 254 } 255 256 case Font.BOLD|Font.ITALIC: 257 if (italic != null) { 258 return italic; 259 } else if (bold != null) { 260 return bold; 261 } else { 262 return plain; 263 } 264 } 265 return null; 266 } 267 268 /* Font may have localized names. Store these in a separate map, so 269 * that only clients who use these names need be affected. 270 */ 271 static synchronized void addLocaleNames(FontFamily family, String[] names){ 272 if (allLocaleNames == null) { 273 allLocaleNames = new HashMap<String, FontFamily>(); 274 } 275 for (int i=0; i<names.length; i++) { 276 allLocaleNames.put(names[i].toLowerCase(), family); 277 } 278 } 279 280 public static synchronized FontFamily getLocaleFamily(String name) { 281 if (allLocaleNames == null) { 282 return null; 283 } 284 return allLocaleNames.get(name.toLowerCase()); 285 } 286 287 public String toString() { 288 return 289 "Font family: " + familyName + 290 " plain="+plain+ 291 " bold=" + bold + 292 " italic=" + italic + 293 " bolditalic=" + bolditalic; 294 295 } 296 297 }