blob: 3f0d5fd601de8e9c7f7474e4dce7a736d423d59a [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
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
26package sun.font;
27
28import java.awt.Font;
29import java.util.HashMap;
30import java.util.concurrent.ConcurrentHashMap;
31import java.util.Locale;
32
33public 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 (FontManager.logging) {
111 FontManager.logger.warning("Rejecting adding " + font +
112 " of lower rank " + font.getRank() +
113 " to family " + this +
114 " of rank " + familyRank);
115 }
116 return;
117 }
118
119 switch (style) {
120
121 case Font.PLAIN:
122 plain = font;
123 break;
124
125 case Font.BOLD:
126 bold = font;
127 break;
128
129 case Font.ITALIC:
130 italic = font;
131 break;
132
133 case Font.BOLD|Font.ITALIC:
134 bolditalic = font;
135 break;
136
137 default:
138 break;
139 }
140 }
141
142 public Font2D getFontWithExactStyleMatch(int style) {
143
144 switch (style) {
145
146 case Font.PLAIN:
147 return plain;
148
149 case Font.BOLD:
150 return bold;
151
152 case Font.ITALIC:
153 return italic;
154
155 case Font.BOLD|Font.ITALIC:
156 return bolditalic;
157
158 default:
159 return null;
160 }
161 }
162
163 /* REMIND: if the callers of this method are operating in an
164 * environment in which not all fonts are registered, the returned
165 * font may be a algorithmically styled one, where in fact if loadfonts
166 * were executed, a styled font may be located. Our present "solution"
167 * to this is to register all fonts in a directory and assume that this
168 * registered all the styles of a font, since they would all be in the
169 * same location.
170 */
171 public Font2D getFont(int style) {
172
173 switch (style) {
174
175 case Font.PLAIN:
176 return plain;
177
178 case Font.BOLD:
179 if (bold != null) {
180 return bold;
181 } else if (plain != null && plain.canDoStyle(style)) {
182 return plain;
183 } else {
184 return null;
185 }
186
187 case Font.ITALIC:
188 if (italic != null) {
189 return italic;
190 } else if (plain != null && plain.canDoStyle(style)) {
191 return plain;
192 } else {
193 return null;
194 }
195
196 case Font.BOLD|Font.ITALIC:
197 if (bolditalic != null) {
198 return bolditalic;
199 } else if (italic != null && italic.canDoStyle(style)) {
200 return italic;
201 } else if (bold != null && bold.canDoStyle(style)) {
202 return italic;
203 } else if (plain != null && plain.canDoStyle(style)) {
204 return plain;
205 } else {
206 return null;
207 }
208 default:
209 return null;
210 }
211 }
212
213 /* Only to be called if getFont(style) returns null
214 * This method will only return null if the family is completely empty!
215 * Note that it assumes the font of the style you need isn't in the
216 * family. The logic here is that if we must substitute something
217 * it might as well be from the same family.
218 */
219 Font2D getClosestStyle(int style) {
220
221 switch (style) {
222 /* if you ask for a plain font try to return a non-italic one,
223 * then a italic one, finally a bold italic one */
224 case Font.PLAIN:
225 if (bold != null) {
226 return bold;
227 } else if (italic != null) {
228 return italic;
229 } else {
230 return bolditalic;
231 }
232
233 /* if you ask for a bold font try to return a non-italic one,
234 * then a bold italic one, finally an italic one */
235 case Font.BOLD:
236 if (plain != null) {
237 return plain;
238 } else if (bolditalic != null) {
239 return bolditalic;
240 } else {
241 return italic;
242 }
243
244 /* if you ask for a italic font try to return a bold italic one,
245 * then a plain one, finally an bold one */
246 case Font.ITALIC:
247 if (bolditalic != null) {
248 return bolditalic;
249 } else if (plain != null) {
250 return plain;
251 } else {
252 return bold;
253 }
254
255 case Font.BOLD|Font.ITALIC:
256 if (italic != null) {
257 return italic;
258 } else if (bold != null) {
259 return bold;
260 } else {
261 return plain;
262 }
263 }
264 return null;
265 }
266
267 /* Font may have localized names. Store these in a separate map, so
268 * that only clients who use these names need be affected.
269 */
270 static synchronized void addLocaleNames(FontFamily family, String[] names){
271 if (allLocaleNames == null) {
272 allLocaleNames = new HashMap<String, FontFamily>();
273 }
274 for (int i=0; i<names.length; i++) {
275 allLocaleNames.put(names[i].toLowerCase(), family);
276 }
277 }
278
279 public static synchronized FontFamily getLocaleFamily(String name) {
280 if (allLocaleNames == null) {
281 return null;
282 }
283 return allLocaleNames.get(name.toLowerCase());
284 }
285
286 public String toString() {
287 return
288 "Font family: " + familyName +
289 " plain="+plain+
290 " bold=" + bold +
291 " italic=" + italic +
292 " bolditalic=" + bolditalic;
293
294 }
295
296}