1 /* 2 * Copyright (c) 2008, 2016, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 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 javafx.scene.text; 27 28 import com.sun.javafx.text.FontHelper; 29 import java.io.FilePermission; 30 import java.io.InputStream; 31 import java.net.URL; 32 import java.net.URLConnection; 33 import java.util.List; 34 35 import com.sun.javafx.tk.Toolkit; 36 import javafx.beans.NamedArg; 37 38 /** 39 * <p>The {@code Font} class represents fonts, which are used to render text on 40 * screen. 41 * <p> 42 * The size of a {@code Font} is described as being specified in points 43 * which are a real world measurement of approximately 1/72 inch. 44 * <p> 45 * Given that fonts scale with the rendering transform as determined 46 * by the transform attributes of a {@code Node} using the {@code Font} 47 * and its ancestors, the size will actually be relative to the local 48 * coordinate space of the node, which should provide coordinates 49 * similar to the size of a point if no scaling transforms are present 50 * in the environment of the node. 51 * Note that the real world distances specified by the default coordinate 52 * system only approximate point sizes as a rule of thumb and are typically 53 * defaulted to screen pixels for most displays. 54 * <p> 55 * For more information see {@link javafx.scene.Node} for more information 56 * on the default coordinate system 57 * @since JavaFX 2.0 58 */ 59 public final class Font { 60 61 static { 62 // This is used by classes in different packages to get access to 63 // private and package private methods. 64 FontHelper.setFontAccessor(new FontHelper.FontAccessor() { 65 66 @Override 67 public Object getNativeFont(Font font) { 68 return font.getNativeFont(); 69 } 70 71 @Override 72 public void setNativeFont(Font font, Object f, String nam, String fam, String styl) { 73 font.setNativeFont(f, nam, fam, styl); 74 } 75 76 @Override 77 public Font nativeFont(Object f, String name, String family, String style, double size) { 78 return Font.nativeFont(f, name, family, style, size); 79 } 80 81 }); 82 } 83 84 private static final String DEFAULT_FAMILY = "System"; 85 private static final String DEFAULT_FULLNAME = "System Regular"; 86 87 /** 88 * The default font for this platform. This is used whenever a font is not 89 * specifically set on a Text node or overridden by CSS. 90 */ 91 private static float defaultSystemFontSize = -1; 92 private static float getDefaultSystemFontSize() { 93 if (defaultSystemFontSize == -1) { 94 defaultSystemFontSize = 95 Toolkit.getToolkit().getFontLoader().getSystemFontSize(); 96 } 97 return defaultSystemFontSize; 98 } 99 100 private static Font DEFAULT; 101 /** 102 * Gets the default font which will be from the family "System", 103 * and typically the style "Regular", and be of a size consistent 104 * with the user's desktop environment, to the extent that can 105 * be determined. 106 * @return The default font. 107 */ 108 public static synchronized Font getDefault() { 109 if (DEFAULT == null) { 110 DEFAULT = new Font(DEFAULT_FULLNAME, getDefaultSystemFontSize()); 111 } 112 return DEFAULT; 113 } 114 115 /** 116 * Gets all the font families installed on the user's system, including any 117 * application fonts or SDK fonts. This call has performance considerations 118 * as looking up all of the fonts may be an expensive operation the 119 * first time. 120 * @return The list containing all available font families. 121 */ 122 public static List<String> getFamilies() { 123 return Toolkit.getToolkit().getFontLoader().getFamilies(); 124 } 125 126 /** 127 * Gets the names of all fonts that are installed on the users system, 128 * including any application fonts and SDK fonts. 129 * This call has performance considerations as 130 * looking up all of the fonts may be an expensive operation the first time. 131 * @return The list containing all available fonts. 132 */ 133 public static List<String> getFontNames() { 134 return Toolkit.getToolkit().getFontLoader().getFontNames(); 135 } 136 137 /** 138 * Gets the names of all fonts in the specified font family that are 139 * installed on the users system, including any application fonts 140 * and SDK fonts. 141 * This call has performance considerations as looking up all of the 142 * fonts may be an expensive operation the first time. 143 * @return The list containing the fonts for the given family. 144 */ 145 public static List<String> getFontNames(String family) { 146 return Toolkit.getToolkit().getFontLoader().getFontNames(family); 147 } 148 149 /** 150 * Searches for an appropriate font based on the font family name and 151 * weight and posture style. This method is not guaranteed to return 152 * a specific font, but does its best to find one that fits the 153 * specified requirements. 154 * <p> 155 * A null or empty value for family allows the implementation to 156 * select any suitable font. 157 * 158 * @param family The family of the font 159 * @param weight The weight of the font 160 * @param posture The posture or posture of the font 161 * @param size The point size of the font. This can be a fractional value, 162 * but must not be negative. If the size is < 0 the default size will be 163 * used. 164 * @return The font that best fits the specified requirements. 165 */ 166 public static Font font(String family, FontWeight weight, 167 FontPosture posture, double size) { 168 169 String fam = 170 (family == null || "".equals(family)) ? DEFAULT_FAMILY : family; 171 double sz = size < 0 ? getDefaultSystemFontSize() : size; 172 return Toolkit.getToolkit().getFontLoader().font(fam, weight, posture, (float)sz); 173 } 174 175 /** 176 * Searches for an appropriate font based on the font family name and weight 177 * style. This method is not guaranteed to return a specific font, but does 178 * its best to find one that fits the specified requirements. 179 * A null or empty value for family allows the implementation 180 * to select any suitable font. 181 * 182 * @param family The family of the font 183 * @param weight The weight of the font 184 * @param size The point size of the font. This can be a fractional value, 185 * but must not be negative. If the size is < 0 the default size will be 186 * used. 187 * @return The font that best fits the specified requirements. 188 */ 189 public static Font font(String family, FontWeight weight, double size) { 190 return font(family, weight, null, size); 191 } 192 193 /** 194 * Searches for an appropriate font based on the font family name and posture 195 * style. This method is not guaranteed to return a specific font, but does 196 * its best to find one that fits the specified requirements. A null or empty 197 * value for family allows the implementation to select any suitable font. 198 * 199 * @param family The family of the font 200 * @param posture The posture or posture of the font 201 * @param size The point size of the font. This can be a fractional value, 202 * but must not be negative. If the size is < 0 the default size will be 203 * used. 204 * @return The font that best fits the specified requirements. 205 */ 206 public static Font font(String family, FontPosture posture, double size) { 207 return font(family, null, posture, size); 208 } 209 210 /** 211 * Searches for an appropriate font based on the font family name and size. 212 * This method is not guaranteed to return a specific font, but does 213 * its best to find one that fits the specified requirements. A null or empty 214 * value for family allows the implementation to select any suitable font. 215 * 216 * @param family The family of the font 217 * @param size The point size of the font. This can be a fractional value, 218 * but must not be negative. If the size is < 0 the default size will be 219 * used. 220 * @return The font that best fits the specified requirements. 221 */ 222 public static Font font(String family, double size) { 223 return font(family, null, null, size); 224 } 225 226 /** 227 * Searches for an appropriate font based on the given font family name and 228 * default font size. 229 * This method is not guaranteed to return a specific font, but does 230 * its best to find one that fits the specified requirements. A null or empty 231 * value for family allows the implementation to select any suitable font. 232 * 233 * @param family The family of the font 234 * @return The font that best fits the specified requirements. 235 */ 236 public static Font font(String family) { 237 return font(family, null, null, -1); 238 } 239 240 /** 241 * Searches for an appropriate font based on the default font family name and 242 * given font size. 243 * This method is not guaranteed to return a specific font, but does 244 * its best to find one that fits the specified requirements. 245 * 246 * @param size The point size of the font. This can be a fractional value, 247 * but must not be negative. If the size is < 0 the default size will be 248 * used. 249 * @return The font that best fits the specified requirements. 250 */ 251 public static Font font(double size) { 252 return font(null, null, null, size); 253 } 254 255 /** 256 * The full font name. This name includes both the family name 257 * and the style variant within that family. For example, for a plain 258 * Arial font this would be "Arial Regular" and for a bolded 259 * Arial font this would be "Arial Bold". The precise name to use when 260 * loading a font is defined within each font file as the full font name. 261 * For example, "Proxima Nova ExtraCondensed Bold Italic" would refer to a 262 * specific Proxima Nova font. 263 * A null or empty name allows the implementation to select any suitable 264 * font. 265 * <p> 266 * There is a single unified way to load all of application supplied 267 * (via <code>Font.loadFont()</code>, JavaFX runtime delivered fonts, 268 * and system installed fonts. Simply create the font by specifying 269 * the full name of the font you want to load. 270 * If the specific font cannot be located, then a fallback or default 271 * font will be used. The "name" will be updated to reflect the actual name 272 * of the font being used. A load failure condition can be discovered by 273 * checking the name of the Font with the name you tried to load. 274 * <p> 275 * Note that if you wish to locate a font by font family and style 276 * then you can use one of the {@link #font} factory methods defined in 277 * this class. 278 * 279 * @defaultValue empty string 280 */ 281 public final String getName() { return name; } 282 private String name; 283 284 /** 285 * Returns the family of this font. 286 * @return The family of this font. 287 */ 288 public final String getFamily() { return family; } 289 private String family; 290 291 /** 292 * The font specified string describing the style within the font family. 293 * @return The style name of this font. 294 */ 295 public final String getStyle() { return style; } 296 private String style; 297 298 /** 299 * The point size for this font. This may be a fractional value such as 300 * {@code 11.5}. If the specified value is < 0 the default size will be 301 * used. 302 * 303 * @defaultValue 12 304 */ 305 public final double getSize() { return size; } 306 private double size; 307 308 /** 309 * The cached hash code, used to improve performance in situations where 310 * we cache fonts, such as in the CSS routines. 311 */ 312 private int hash = 0; 313 314 /** 315 * Constructs a font using the default face "System". 316 * The underlying font used is determined by the implementation 317 * based on the typical UI font for the current UI environment. 318 * 319 * @param size the font size to use 320 */ 321 public Font(@NamedArg("size") double size) { 322 this(null, size); 323 } 324 325 326 /** 327 * Constructs a font using the specified full face name and size 328 * @param name full name of the font. 329 * @param size the font size to use 330 */ 331 public Font(@NamedArg("name") String name, @NamedArg("size") double size) { 332 this.name = name; 333 this.size = size; 334 335 if (name == null || "".equals(name)) this.name = DEFAULT_FULLNAME; 336 if (size < 0f) this.size = getDefaultSystemFontSize(); 337 // if a search was done based on family + style information, then the 338 // native font has already been located and specified. Likewise if the 339 // Font was created based on an existing native font. If however a Font 340 // was created directly in FX, then we need to find the native font 341 // to use. This call will also set the family and style by invoking 342 // the setNativeFont callback method. 343 Toolkit.getToolkit().getFontLoader().loadFont(this); 344 } 345 346 /** 347 * Private constructor for internal implementation 348 * 349 * @param f native font 350 * @param family font family name 351 * @param name font full name 352 * @param style style string 353 * @param size font size 354 */ 355 private Font(Object f, String family, String name, String style, double size) { 356 this.nativeFont = f; 357 this.family = family; 358 this.name = name; 359 this.style = style; 360 this.size = size; 361 } 362 363 /** 364 * Loads a font resource from the specified URL. If the load is successful 365 * such that the location is readable, and it represents a supported 366 * font format then a <code>Font</code> object will be returned. 367 * <p> 368 * If the application does not have the proper permission then this method 369 * will return the default system font with the specified font size. 370 * <p> 371 * Any failure such as a malformed URL being unable to locate or read 372 * from the resource, or if it doesn't represent a font, will result in 373 * a <code>null</code> return. It is the application's responsibility 374 * to check this before use. 375 * <p> 376 * On a successful (non-null) return the font will be registered 377 * with the FX graphics system for creation by available constructors 378 * and factory methods, and the application should use it in this 379 * manner rather than calling this method again, which would 380 * repeat the overhead of downloading and installing the font. 381 * <p> 382 * The font <code>size</code> parameter is a convenience so that in 383 * typical usage the application can directly use the returned (non-null) 384 * font rather than needing to create one via a constructor. Invalid sizes 385 * are those <=0 and will result in a default size. 386 * <p> 387 * If the URL represents a local disk file, then no copying is performed 388 * and the font file is required to persist for the lifetime of the 389 * application. Updating the file in any manner will result 390 * in unspecified and likely undesired behaviours. 391 * 392 * @param urlStr from which to load the font, specified as a String. 393 * @param size of the returned font. 394 * @return the Font, or null if the font cannot be created. 395 */ 396 public static Font loadFont(String urlStr, double size) { 397 URL url = null; 398 try { 399 url = new URL(urlStr); // null string arg. is caught here. 400 } catch (Exception e) { 401 return null; 402 } 403 if (size <= 0) { 404 size = getDefaultSystemFontSize(); 405 } 406 // Now lets parse the URL and decide if its a file, 407 // or a remote URL from which we need to read. 408 if (url.getProtocol().equals("file")) { 409 String path = url.getFile(); 410 // The URL path may have a leading "/", when obtained 411 // via ClassLoader. This can cause problems on Windows. 412 // Getting the path from a File fixes this. 413 path = new java.io.File(path).getPath(); 414 try { 415 SecurityManager sm = System.getSecurityManager(); 416 if (sm != null) { 417 FilePermission filePermission = 418 new FilePermission(path, "read"); 419 sm.checkPermission(filePermission); 420 } 421 } catch (Exception e) { 422 return null; 423 } 424 return Toolkit.getToolkit().getFontLoader().loadFont(path, size); 425 } 426 Font font = null; 427 URLConnection connection = null; 428 InputStream in = null; 429 try { 430 connection = url.openConnection(); 431 in = connection.getInputStream(); 432 font = Toolkit.getToolkit().getFontLoader().loadFont(in, size); 433 } catch (Exception e) { 434 return null; 435 } finally { 436 try { 437 if (in != null) { 438 in.close(); 439 } 440 } catch (Exception e) { 441 } 442 } 443 return font; 444 } 445 446 /** 447 * Loads a font resource from the specified input stream. 448 * If the load is successful such that the stream can be 449 * fully read, and it represents a supported font format then a 450 * <code>Font</code> object will be returned. 451 * <p> 452 * If the application does not have the proper permission then this method 453 * will return the default system font with the specified font size. 454 * <p> 455 * Any failure such as abbreviated input, or an unsupported font format 456 * will result in a <code>null</code> return. It is the application's 457 * responsibility to check this before use. 458 * <p> 459 * On a successful (non-null) return the font will be registered 460 * with the FX graphics system for creation by available constructors 461 * and factory methods, and the application should use it in this 462 * manner rather than calling this method again, which would 463 * repeat the overhead of re-reading and installing the font. 464 * <p> 465 * The font <code>size</code> parameter is a convenience so that in 466 * typical usage the application can directly use the returned (non-null) 467 * font rather than needing to create one via a constructor. Invalid sizes 468 * are those <=0 and will result in a default size. 469 * <p> 470 * This method does not close the input stream. 471 * @param in stream from which to load the font. 472 * @param size of the returned font. 473 * @return the Font, or null if the font cannot be created. 474 */ 475 public static Font loadFont(InputStream in, double size) { 476 if (size <= 0) { 477 size = getDefaultSystemFontSize(); 478 } 479 return Toolkit.getToolkit().getFontLoader().loadFont(in, size); 480 } 481 482 /** 483 * Converts this {@code Font} object to a {@code String} representation. 484 * The String representation is for informational use only and will change. 485 * Do not use this string representation for any programmatic purpose. 486 */ 487 @Override public String toString() { 488 StringBuilder builder = new StringBuilder("Font[name="); 489 builder = builder.append(name); 490 builder = builder.append(", family=").append(family); 491 builder = builder.append(", style=").append(style); 492 builder = builder.append(", size=").append(size); 493 builder = builder.append("]"); 494 return builder.toString(); 495 } 496 497 /** 498 * Indicates whether some other object is "equal to" this one. 499 * @param obj the reference object with which to compare. 500 * @return {@code true} if this object is equal to the {@code obj} argument; {@code false} otherwise. 501 */ 502 @Override public boolean equals(Object obj) { 503 if (obj == this) return true; 504 if (obj instanceof Font) { 505 Font other = (Font)obj; 506 return (name == null ? other.name == null : name.equals(other.name)) 507 && size == other.size; 508 } 509 return false; 510 } 511 512 /** 513 * Returns a hash code for this {@code Font} object. 514 * @return a hash code for this {@code Font} object. 515 */ 516 @Override public int hashCode() { 517 if (hash == 0) { 518 long bits = 17L; 519 bits = 37L * bits + name.hashCode(); 520 bits = 37L * bits + Double.doubleToLongBits(size); 521 hash = (int) (bits ^ (bits >> 32)); 522 } 523 return hash; 524 } 525 526 private Object nativeFont; 527 528 private Object getNativeFont() { return nativeFont; } 529 530 private void setNativeFont(Object f, String nam, String fam, String styl) { 531 nativeFont = f; 532 name = nam; 533 family = fam; 534 style = styl; 535 } 536 537 private static Font nativeFont(Object f, String name, String family, 538 String style, double size) { 539 Font retFont = new Font( f, family, name, style, size); 540 return retFont; 541 } 542 }