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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.font;
27
28 import java.io.File;
29 import java.awt.Font;
30 import java.util.HashMap;
31 import java.util.concurrent.ConcurrentHashMap;
32 import java.util.Locale;
33
34 public class FontFamily {
35
36 private static ConcurrentHashMap<String, FontFamily>
37 familyNameMap = new ConcurrentHashMap<String, FontFamily>();
38 private static HashMap<String, FontFamily> allLocaleNames;
39
40 protected String familyName;
41 protected Font2D plain;
42 protected Font2D bold;
43 protected Font2D italic;
44 protected Font2D bolditalic;
45 protected boolean logicalFont = false;
46 protected int familyRank;
47
48 public static FontFamily getFamily(String name) {
49 return familyNameMap.get(name.toLowerCase(Locale.ENGLISH));
117 } else if (bold instanceof FileFont) {
118 existingFont = (FileFont)bold;
119 } else if (italic instanceof FileFont) {
120 existingFont = (FileFont)italic;
121 } else if (bolditalic instanceof FileFont) {
122 existingFont = (FileFont)bolditalic;
123 }
124 // A family isn't created until there's a font.
125 // So if we didn't find a file font it means this
126 // isn't a file-based family.
127 if (existingFont == null) {
128 return false;
129 }
130 File existDir = (new File(existingFont.platName)).getParentFile();
131
132 FileFont newFont = (FileFont)font;
133 File newDir = (new File(newFont.platName)).getParentFile();
134 return java.util.Objects.equals(newDir, existDir);
135 }
136
137 public void setFont(Font2D font, int style) {
138 /* Allow a lower-rank font only if its a file font
139 * from the exact same source as any previous font.
140 */
141 if ((font.getRank() > familyRank) && !isFromSameSource(font)) {
142 if (FontUtilities.isLogging()) {
143 FontUtilities.getLogger()
144 .warning("Rejecting adding " + font +
145 " of lower rank " + font.getRank() +
146 " to family " + this +
147 " of rank " + familyRank);
148 }
149 return;
150 }
151
152 switch (style) {
153
154 case Font.PLAIN:
155 plain = font;
156 break;
157
158 case Font.BOLD:
159 bold = font;
160 break;
161
162 case Font.ITALIC:
163 italic = font;
164 break;
165
166 case Font.BOLD|Font.ITALIC:
167 bolditalic = font;
168 break;
169
170 default:
171 break;
172 }
173 }
174
175 public Font2D getFontWithExactStyleMatch(int style) {
176
177 switch (style) {
178
179 case Font.PLAIN:
180 return plain;
181
182 case Font.BOLD:
183 return bold;
184
185 case Font.ITALIC:
186 return italic;
187
299
300 /* Font may have localized names. Store these in a separate map, so
301 * that only clients who use these names need be affected.
302 */
303 static synchronized void addLocaleNames(FontFamily family, String[] names){
304 if (allLocaleNames == null) {
305 allLocaleNames = new HashMap<String, FontFamily>();
306 }
307 for (int i=0; i<names.length; i++) {
308 allLocaleNames.put(names[i].toLowerCase(), family);
309 }
310 }
311
312 public static synchronized FontFamily getLocaleFamily(String name) {
313 if (allLocaleNames == null) {
314 return null;
315 }
316 return allLocaleNames.get(name.toLowerCase());
317 }
318
319 public String toString() {
320 return
321 "Font family: " + familyName +
322 " plain="+plain+
323 " bold=" + bold +
324 " italic=" + italic +
325 " bolditalic=" + bolditalic;
326
327 }
328
329 }
|
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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.font;
27
28 import java.io.File;
29 import java.awt.Font;
30 import java.util.Collection;
31 import java.util.HashMap;
32 import java.util.concurrent.ConcurrentHashMap;
33 import java.util.Locale;
34
35 public class FontFamily {
36
37 private static ConcurrentHashMap<String, FontFamily>
38 familyNameMap = new ConcurrentHashMap<String, FontFamily>();
39 private static HashMap<String, FontFamily> allLocaleNames;
40
41 protected String familyName;
42 protected Font2D plain;
43 protected Font2D bold;
44 protected Font2D italic;
45 protected Font2D bolditalic;
46 protected boolean logicalFont = false;
47 protected int familyRank;
48
49 public static FontFamily getFamily(String name) {
50 return familyNameMap.get(name.toLowerCase(Locale.ENGLISH));
118 } else if (bold instanceof FileFont) {
119 existingFont = (FileFont)bold;
120 } else if (italic instanceof FileFont) {
121 existingFont = (FileFont)italic;
122 } else if (bolditalic instanceof FileFont) {
123 existingFont = (FileFont)bolditalic;
124 }
125 // A family isn't created until there's a font.
126 // So if we didn't find a file font it means this
127 // isn't a file-based family.
128 if (existingFont == null) {
129 return false;
130 }
131 File existDir = (new File(existingFont.platName)).getParentFile();
132
133 FileFont newFont = (FileFont)font;
134 File newDir = (new File(newFont.platName)).getParentFile();
135 return java.util.Objects.equals(newDir, existDir);
136 }
137
138 /*
139 * We want a family to be of the same width and prefer medium/normal width.
140 * Once we find a particular width we accept more of the same width
141 * until we find one closer to normal when we 'evict' all existing fonts.
142 * So once we see a 'normal' width font we evict all members that are not
143 * normal width and then accept only new ones that are normal width.
144 *
145 * Once a font passes the width test we subject it to the weight test.
146 * For Plain we target the weight the closest that is <= NORMAL (400)
147 * For Bold we target the weight that is closest to BOLD (700).
148 *
149 * In the future, rather than discarding these fonts, we should
150 * extend the family to include these so lookups on these properties
151 * can locate them, as presently they will only be located by full name
152 * based lookup.
153 */
154
155 private int familyWidth = 0;
156 private boolean preferredWidth(Font2D font) {
157
158 int newWidth = font.getWidth();
159
160 if (familyWidth == 0) {
161 familyWidth = newWidth;
162 return true;
163 }
164
165 if (newWidth == familyWidth) {
166 return true;
167 }
168
169 if (Math.abs(Font2D.FWIDTH_NORMAL - newWidth) <
170 Math.abs(Font2D.FWIDTH_NORMAL - familyWidth))
171 {
172 if (FontUtilities.debugFonts()) {
173 FontUtilities.getLogger().info(
174 "Found more preferred width. New width = " + newWidth +
175 " Old width = " + familyWidth + " in font " + font +
176 " nulling out fonts plain: " + plain + " bold: " + bold +
177 " italic: " + italic + " bolditalic: " + bolditalic);
178 }
179 familyWidth = newWidth;
180 plain = bold = italic = bolditalic = null;
181 return true;
182 } else if (FontUtilities.debugFonts()) {
183 FontUtilities.getLogger().info(
184 "Family rejecting font " + font +
185 " of less preferred width " + newWidth);
186 }
187 return false;
188 }
189
190 private boolean closerWeight(Font2D currFont, Font2D font, int style) {
191 if (familyWidth != font.getWidth()) {
192 return false;
193 }
194
195 if (currFont == null) {
196 return true;
197 }
198
199 if (FontUtilities.debugFonts()) {
200 FontUtilities.getLogger().info(
201 "New weight for style " + style + ". Curr.font=" + currFont +
202 " New font="+font+" Curr.weight="+ + currFont.getWeight()+
203 " New weight="+font.getWeight());
204 }
205
206 int newWeight = font.getWeight();
207 switch (style) {
208 case Font.PLAIN:
209 case Font.ITALIC:
210 return (newWeight <= Font2D.FWEIGHT_NORMAL &&
211 newWeight > currFont.getWeight());
212
213 case Font.BOLD:
214 case Font.BOLD|Font.ITALIC:
215 return (Math.abs(newWeight - Font2D.FWEIGHT_BOLD) <
216 Math.abs(currFont.getWeight() - Font2D.FWEIGHT_BOLD));
217
218 default:
219 return false;
220 }
221 }
222
223 public void setFont(Font2D font, int style) {
224
225 if (FontUtilities.isLogging()) {
226 FontUtilities.getLogger().info(
227 "Request to add " + font + " with style " + style +
228 " to family " + this);
229 }
230 /* Allow a lower-rank font only if its a file font
231 * from the exact same source as any previous font.
232 */
233 if ((font.getRank() > familyRank) && !isFromSameSource(font)) {
234 if (FontUtilities.isLogging()) {
235 FontUtilities.getLogger()
236 .warning("Rejecting adding " + font +
237 " of lower rank " + font.getRank() +
238 " to family " + this +
239 " of rank " + familyRank);
240 }
241 return;
242 }
243
244 switch (style) {
245
246 case Font.PLAIN:
247 if (preferredWidth(font) && closerWeight(plain, font, style)) {
248 plain = font;
249 }
250 break;
251
252 case Font.BOLD:
253 if (preferredWidth(font) && closerWeight(bold, font, style)) {
254 bold = font;
255 }
256 break;
257
258 case Font.ITALIC:
259 if (preferredWidth(font) && closerWeight(italic, font, style)) {
260 italic = font;
261 }
262 break;
263
264 case Font.BOLD|Font.ITALIC:
265 if (preferredWidth(font) && closerWeight(bolditalic, font, style)) {
266 bolditalic = font;
267 }
268 break;
269
270 default:
271 break;
272 }
273 }
274
275 public Font2D getFontWithExactStyleMatch(int style) {
276
277 switch (style) {
278
279 case Font.PLAIN:
280 return plain;
281
282 case Font.BOLD:
283 return bold;
284
285 case Font.ITALIC:
286 return italic;
287
399
400 /* Font may have localized names. Store these in a separate map, so
401 * that only clients who use these names need be affected.
402 */
403 static synchronized void addLocaleNames(FontFamily family, String[] names){
404 if (allLocaleNames == null) {
405 allLocaleNames = new HashMap<String, FontFamily>();
406 }
407 for (int i=0; i<names.length; i++) {
408 allLocaleNames.put(names[i].toLowerCase(), family);
409 }
410 }
411
412 public static synchronized FontFamily getLocaleFamily(String name) {
413 if (allLocaleNames == null) {
414 return null;
415 }
416 return allLocaleNames.get(name.toLowerCase());
417 }
418
419 public static FontFamily[] getAllFontFamilies() {
420 Collection<FontFamily> families = familyNameMap.values();
421 return families.toArray(new FontFamily[0]);
422 }
423
424 public String toString() {
425 return
426 "Font family: " + familyName +
427 " plain="+plain+
428 " bold=" + bold +
429 " italic=" + italic +
430 " bolditalic=" + bolditalic;
431
432 }
433
434 }
|