001/* 002 * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package javafx.scene.text; 027 028import java.io.FilePermission; 029import java.io.InputStream; 030import java.net.URL; 031import java.net.URLConnection; 032import java.util.List; 033 034import com.sun.javafx.beans.annotations.Default; 035import com.sun.javafx.tk.Toolkit; 036 037/** 038 * <p>The {@code Font} class represents fonts, which are used to render text on 039 * screen. 040 * <p> 041 * The size of a {@code Font} is described as being specified in points 042 * which are a real world measurement of approximately 1/72 inch. 043 * <p> 044 * Given that fonts scale with the rendering transform as determined 045 * by the transform attributes of a {@code Node} using the {@code Font} 046 * and its ancestors, the size will actually be relative to the local 047 * coordinate space of the node, which should provide coordinates 048 * similar to the size of a point if no scaling transforms are present 049 * in the environment of the node. 050 * Note that the real world distances specified by the default coordinate 051 * system only approximate point sizes as a rule of thumb and are typically 052 * defaulted to screen pixels for most displays. 053 * <p> 054 * For more information see {@link javafx.scene.Node} for more information 055 * on the default coordinate system 056 */ 057public final class Font { 058 059 private static final String DEFAULT_FAMILY = "System"; 060 private static final String DEFAULT_FULLNAME = "System Regular"; 061 062 /** 063 * The default font for this platform. This is used whenever a font is not 064 * specifically set on a Text node or overridden by CSS. 065 */ 066 private static float defaultSystemFontSize = -1; 067 private static float getDefaultSystemFontSize() { 068 if (defaultSystemFontSize == -1) { 069 defaultSystemFontSize = 070 Toolkit.getToolkit().getFontLoader().getSystemFontSize(); 071 } 072 return defaultSystemFontSize; 073 } 074 075 private static Font DEFAULT; 076 /** 077 * Gets the default font which will be from the family "System", 078 * and typically the style "Regular", and be of a size consistent 079 * with the user's desktop environment, to the extent that can 080 * be determined. 081 * @return the default font. 082 */ 083 public static synchronized Font getDefault() { 084 if (DEFAULT == null) { 085 DEFAULT = new Font(DEFAULT_FULLNAME, getDefaultSystemFontSize()); 086 } 087 return DEFAULT; 088 } 089 090 /** 091 * Gets all the font families installed on the user's system, including any 092 * application fonts or SDK fonts. This call has performance considerations 093 * as looking up all of the fonts may be an expensive operation the 094 * first time. 095 */ 096 public static List<String> getFamilies() { 097 return Toolkit.getToolkit().getFontLoader().getFamilies(); 098 } 099 100 /** 101 * Gets the names of all fonts that are installed on the users system, 102 * including any application fonts and SDK fonts. 103 * This call has performance considerations as 104 * looking up all of the fonts may be an expensive operation the first time. 105 */ 106 public static List<String> getFontNames() { 107 return Toolkit.getToolkit().getFontLoader().getFontNames(); 108 } 109 110 /** 111 * Gets the names of all fonts in the specified font family that are 112 * installed on the users system, including any application fonts 113 * and SDK fonts. 114 * This call has performance considerations as looking up all of the 115 * fonts may be an expensive operation the first time. 116 */ 117 public static List<String> getFontNames(String family) { 118 return Toolkit.getToolkit().getFontLoader().getFontNames(family); 119 } 120 121 /** 122 * Searches for an appropriate font based on the font family name and 123 * weight and posture style. This method is not guaranteed to return 124 * a specific font, but does its best to find one that fits the 125 * specified requirements. 126 * <p> 127 * A null or empty value for family allows the implementation to 128 * select any suitable font. 129 * 130 * @param family The family of the font 131 * @param weight The weight of the font 132 * @param posture The posture or posture of the font 133 * @param size The point size of the font. This can be a fractional value, 134 * but must not be negative. If the size is < 0 the default size will be 135 * used. 136 */ 137 public static Font font(String family, FontWeight weight, 138 FontPosture posture, double size) { 139 140 String fam = 141 (family == null || "".equals(family)) ? DEFAULT_FAMILY : family; 142 double sz = size < 0 ? getDefaultSystemFontSize() : size; 143 return Toolkit.getToolkit().getFontLoader().font(fam, weight, posture, (float)sz); 144 } 145 146 /** 147 * Searches for an appropriate font based on the font family name and weight 148 * style. This method is not guaranteed to return a specific font, but does 149 * its best to find one that fits the specified requirements. 150 * A null or empty value for family allows the implementation 151 * to select any suitable font. 152 * 153 * @param family The family of the font 154 * @param weight The weight of the font 155 * @param size The point size of the font. This can be a fractional value, 156 * but must not be negative. If the size is < 0 the default size will be 157 * used. 158 */ 159 public static Font font(String family, FontWeight weight, double size) { 160 return font(family, weight, null, size); 161 } 162 163 /** 164 * Searches for an appropriate font based on the font family name and posture 165 * style. This method is not guaranteed to return a specific font, but does 166 * its best to find one that fits the specified requirements. A null or empty 167 * value for family allows the implementation to select any suitable font. 168 * 169 * @param family The family of the font 170 * @param posture The posture or posture of the font 171 * @param size The point size of the font. This can be a fractional value, 172 * but must not be negative. If the size is < 0 the default size will be 173 * used. 174 */ 175 public static Font font(String family, FontPosture posture, double size) { 176 return font(family, null, posture, size); 177 } 178 179 /** 180 * Searches for an appropriate font based on the font family name and size. 181 * This method is not guaranteed to return a specific font, but does 182 * its best to find one that fits the specified requirements. A null or empty 183 * value for family allows the implementation to select any suitable font. 184 * 185 * @param family The family of the font 186 * @param size The point size of the font. This can be a fractional value, 187 * but must not be negative. If the size is < 0 the default size will be 188 * used. 189 */ 190 public static Font font(String family, double size) { 191 return font(family, null, null, size); 192 } 193 194 /** 195 * The full font name. This name includes both the family name 196 * and the style variant within that family. For example, for a plain 197 * Arial font this would be "Arial Regular" and for a bolded 198 * Arial font this would be "Arial Bold". The precise name to use when 199 * loading a font is defined within each font file as the full font name. 200 * For example, "Proxima Nova ExtraCondensed Bold Italic" would refer to a 201 * specific Proxima Nova font. 202 * A null or empty name allows the implementation to select any suitable 203 * font. 204 * <p> 205 * There is a single unified way to load all of application supplied 206 * (via <code>Font.loadFont()</code>, JavaFX runtime delivered fonts, 207 * and system installed fonts. Simply create the font by specifying 208 * the full name of the font you want to load. 209 * If the specific font cannot be located, then a fallback or default 210 * font will be used. The "name" will be updated to reflect the actual name 211 * of the font being used. A load failure condition can be discovered by 212 * checking the name of the Font with the name you tried to load. 213 * <p> 214 * Note that if you wish to locate a font by font family and style 215 * then you can use one of the {@link #font} factory methods defined in 216 * this class. 217 * 218 * @defaultValue empty string 219 */ 220 public final String getName() { return name; } 221 private String name; 222 223 /** 224 * Returns the family of this font. 225 * @return The family of this font. 226 */ 227 public final String getFamily() { return family; } 228 private String family; 229 230 /** 231 * The font specified string describing the style within the font family. 232 * @return The style name of this font. 233 */ 234 public final String getStyle() { return style; } 235 private String style; 236 237 /** 238 * The point size for this font. This may be a fractional value such as 239 * {@code 11.5}. If the specified value is < 0 the default size will be 240 * used. 241 * 242 * @defaultValue 12 243 */ 244 public final double getSize() { return size; } 245 private double size; 246 247 /** 248 * The cached hash code, used to improve performance in situations where 249 * we cache fonts, such as in the CSS routines. 250 */ 251 private int hash = 0; 252 253 /** 254 * Constructs a font using the default face "System". 255 * The underlying font used is determined by the implementation 256 * based on the typical UI font for the current UI environment. 257 * 258 * @param size the font size to use 259 */ 260 public Font(double size) { 261 this(null, size); 262 } 263 264 265 /** 266 * Constructs a font using the specified full face name and size 267 * @param name full name of the font. 268 * @param size the font size to use 269 */ 270 public Font(String name, double size) { 271 this.name = name; 272 this.size = size; 273 274 if (name == null || "".equals(name)) this.name = DEFAULT_FULLNAME; 275 if (size < 0f) this.size = getDefaultSystemFontSize(); 276 // if a search was done based on family + style information, then the 277 // native font has already been located and specified. Likewise if the 278 // Font was created based on an existing native font. If however a Font 279 // was created directly in FX, then we need to find the native font 280 // to use. This call will also set the family and style by invoking 281 // the impl_setNativeFont callback method. 282 Toolkit.getToolkit().getFontLoader().loadFont(this); 283 } 284 285 /** 286 * Private constructor for internal implementation 287 * 288 * @param f native font 289 * @param family font family name 290 * @param name font full name 291 * @param style style string 292 * @param size font size 293 */ 294 private Font(Object f, String family, String name, String style, double size) { 295 this.nativeFont = f; 296 this.family = family; 297 this.name = name; 298 this.style = style; 299 this.size = size; 300 } 301 302 /** 303 * Loads a font resource from the specified URL. If the load is successful 304 * such that the location is readable, and it represents a supported 305 * font format then a <code>Font</code> object will be returned. 306 * <p> 307 * Any failure such as a malformed URL being unable to locate or read 308 * from the resource, or if it doesn't represent a font, will result in 309 * a <code>null</code> return. It is the application's responsibility 310 * to check this before use. 311 * <p> 312 * On a successful (non-null) return the font will be registered 313 * with the FX graphics system for creation by available constructors 314 * and factory methods, and the application should use it in this 315 * manner rather than calling this method again, which would 316 * repeat the overhead of downloading and installing the font. 317 * <p> 318 * The font <code>size</code> parameter is a convenience so that in 319 * typical usage the application can directly use the returned (non-null) 320 * font rather than needing to create one via a constructor. Invalid sizes 321 * are those <=0 and will result in a default size. 322 * <p> 323 * If the URL represents a local disk file, then no copying is performed 324 * and the font file is required to persist for the lifetime of the 325 * application. Updating the file in any manner will result 326 * in unspecified and likely undesired behaviours. 327 * 328 * @param urlStr from which to load the font, specified as a String. 329 * @param size of the returned font. 330 * @return the Font, or null if the font cannot be created. 331 */ 332 public static Font loadFont(String urlStr, double size) { 333 URL url = null; 334 try { 335 url = new URL(urlStr); // null string arg. is caught here. 336 } catch (Exception e) { 337 return null; 338 } 339 if (size <= 0) { 340 size = getDefaultSystemFontSize(); 341 } 342 // Now lets parse the URL and decide if its a file, 343 // or a remote URL from which we need to read. 344 if (url.getProtocol().equals("file")) { 345 String path = url.getFile(); 346 // The URL path may have a leading "/", when obtained 347 // via ClassLoader. This can cause problems on Windows. 348 // Getting the path from a File fixes this. 349 path = new java.io.File(path).getPath(); 350 try { 351 SecurityManager sm = System.getSecurityManager(); 352 if (sm != null) { 353 FilePermission filePermission = 354 new FilePermission(path, "read"); 355 sm.checkPermission(filePermission); 356 } 357 } catch (Exception e) { 358 return null; 359 } 360 return Toolkit.getToolkit().getFontLoader().loadFont(path, size); 361 } 362 Font font = null; 363 URLConnection connection = null; 364 InputStream in = null; 365 try { 366 connection = url.openConnection(); 367 in = connection.getInputStream(); 368 font = Toolkit.getToolkit().getFontLoader().loadFont(in, size); 369 } catch (Exception e) { 370 return null; 371 } finally { 372 try { 373 if (in != null) { 374 in.close(); 375 } 376 } catch (Exception e) { 377 } 378 } 379 return font; 380 } 381 382 /** 383 * Loads a font resource from the specified input stream. 384 * If the load is successful such that the stream can be 385 * fully read, and it represents a supported font format then a 386 * <code>Font</code> object will be returned. 387 * <p> 388 * Any failure such as abbreviated input, or an unsupported font format 389 * will result in a <code>null</code> return. It is the application's 390 * responsibility to check this before use. 391 * <p> 392 * On a successful (non-null) return the font will be registered 393 * with the FX graphics system for creation by available constructors 394 * and factory methods, and the application should use it in this 395 * manner rather than calling this method again, which would 396 * repeat the overhead of re-reading and installing the font. 397 * <p> 398 * The font <code>size</code> parameter is a convenience so that in 399 * typical usage the application can directly use the returned (non-null) 400 * font rather than needing to create one via a constructor. Invalid sizes 401 * are those <=0 and will result in a default size. 402 * <p> 403 * This method does not close the input stream. 404 * @param in stream from which to load the font. 405 * @param size of the returned font. 406 * @return the Font, or null if the font cannot be created. 407 */ 408 public static Font loadFont(InputStream in, double size) { 409 if (size <= 0) { 410 size = getDefaultSystemFontSize(); 411 } 412 return Toolkit.getToolkit().getFontLoader().loadFont(in, size); 413 } 414 415 /** 416 * Converts this {@code Font} object to a {@code String} representation. 417 * The String representation is for informational use only and will change. 418 * Do not use this string representation for any programmatic purpose. 419 */ 420 @Override public String toString() { 421 StringBuilder builder = new StringBuilder("Font[name="); 422 builder = builder.append(name); 423 builder = builder.append(", family=").append(family); 424 builder = builder.append(", style=").append(style); 425 builder = builder.append(", size=").append(size); 426 builder = builder.append("]"); 427 return builder.toString(); 428 } 429 430 /** 431 * Indicates whether some other object is "equal to" this one. 432 * @param obj the reference object with which to compare. 433 * @return {@code true} if this object is equal to the {@code obj} argument; {@code false} otherwise. 434 */ 435 @Override public boolean equals(Object obj) { 436 if (obj == this) return true; 437 if (obj instanceof Font) { 438 Font other = (Font)obj; 439 return (name == null ? other.name == null : name.equals(other.name)) 440 && size == other.size; 441 } 442 return false; 443 } 444 445 /** 446 * Returns a hash code for this {@code Font} object. 447 * @return a hash code for this {@code Font} object. 448 */ 449 @Override public int hashCode() { 450 if (hash == 0) { 451 long bits = 17L; 452 bits = 37L * bits + name.hashCode(); 453 bits = 37L * bits + Double.doubleToLongBits(size); 454 hash = (int) (bits ^ (bits >> 32)); 455 } 456 return hash; 457 } 458 459 private Object nativeFont; 460 461 /** 462 * @treatAsPrivate implementation detail 463 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 464 */ 465 @Deprecated 466 public Object impl_getNativeFont() { return nativeFont; } 467 468 /** 469 * @treatAsPrivate implementation detail 470 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 471 */ 472 @Deprecated 473 public void impl_setNativeFont(Object f, String nam, String fam, String styl) { 474 nativeFont = f; 475 name = nam; 476 family = fam; 477 style = styl; 478 } 479 480 /** 481 * @treatAsPrivate implementation detail 482 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 483 */ 484 @Deprecated 485 public static Font impl_NativeFont(Object f, String name, String family, 486 String style, double size) { 487 Font retFont = new Font( f, family, name, style, size); 488 return retFont; 489 } 490}