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.scene.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 a security manager is present, the application
 369      * must have both permission to read from the specified URL location
 370      * and the {@link javafx.util.FXPermission} "loadFont".
 371      * If the application does not have permission to read from the specified
 372      * URL location, then null is returned.
 373      * If the application does not have the "loadFont" permission then this method
 374      * will return the default system font with the specified font size.
 375      * <p>
 376      * Any failure such as a malformed URL being unable to locate or read
 377      * from the resource, or if it doesn't represent a font, will result in
 378      * a <code>null</code> return. It is the application's responsibility
 379      * to check this before use.
 380      * <p>
 381      * On a successful (non-null) return the font will be registered
 382      * with the FX graphics system for creation by available constructors
 383      * and factory methods, and the application should use it in this
 384      * manner rather than calling this method again, which would
 385      * repeat the overhead of downloading and installing the font.
 386      * <p>
 387      * The font <code>size</code> parameter is a convenience so that in
 388      * typical usage the application can directly use the returned (non-null)
 389      * font rather than needing to create one via a constructor. Invalid sizes
 390      * are those <=0 and will result in a default size.
 391      * <p>
 392      * If the URL represents a local disk file, then no copying is performed
 393      * and the font file is required to persist for the lifetime of the
 394      * application. Updating the file in any manner will result
 395      * in unspecified and likely undesired behaviours.
 396      *
 397      * @param urlStr from which to load the font, specified as a String.
 398      * @param size of the returned font.
 399      * @return the Font, or null if the font cannot be created.
 400      */
 401     public static Font loadFont(String urlStr, double size) {
 402         Font[] fonts = loadFontInternal(urlStr, size, false);
 403         return (fonts == null) ? null : fonts[0];
 404     }
 405 
 406     /**
 407      * Loads font resources from the specified URL. If the load is successful
 408      * such that the location is readable, and it represents a supported
 409      * font format then an array of<code>Font</code> object will be returned.
 410      * <p>
 411      * The use case for this method is for loading all fonts
 412      * from a TrueType Collection (TTC).
 413      * <p>
 414      * If a security manager is present, the application
 415      * must have both permission to read from the specified URL location
 416      * and the {@link javafx.util.FXPermission} "loadFont".
 417      * If the application does not have permission to read from the specified
 418      * URL location, then null is returned.
 419      * If the application does not have the "loadFont" permission then this method
 420      * will return an array of one element which is the default
 421      *  system font with the specified font size.
 422      * <p>
 423      * Any failure such as a malformed URL being unable to locate or read
 424      * from the resource, or if it doesn't represent a font, will result in
 425      * a <code>null</code> return. It is the application's responsibility
 426      * to check this before use.
 427      * <p>
 428      * On a successful (non-null) return the fonts will be registered
 429      * with the FX graphics system for creation by available constructors
 430      * and factory methods, and the application should use it in this
 431      * manner rather than calling this method again, which would
 432      * repeat the overhead of downloading and installing the fonts.
 433      * <p>
 434      * The font <code>size</code> parameter is a convenience so that in
 435      * typical usage the application can directly use the returned (non-null)
 436      * font rather than needing to create one via a constructor. Invalid sizes
 437      * are those <=0 and will result in a default size.
 438      * <p>
 439      * If the URL represents a local disk file, then no copying is performed
 440      * and the font file is required to persist for the lifetime of the
 441      * application. Updating the file in any manner will result
 442      * in unspecified and likely undesired behaviours.
 443      *
 444      * @param urlStr from which to load the fonts, specified as a String.
 445      * @param size of the returned fonts.
 446      * @return array of Font, or null if the fonts cannot be created.
 447      * @since 9
 448      */
 449     public static Font[] loadFonts(String urlStr, double size) {
 450         return loadFontInternal(urlStr, size, true);
 451     }
 452 
 453     private static Font[] loadFontInternal(String urlStr, double size,
 454                                            boolean loadAll) {
 455         URL url = null;
 456         try {
 457             url = new URL(urlStr); // null string arg. is caught here.
 458         } catch (Exception e) {
 459             return null;
 460         }
 461         if (size <= 0) {
 462             size = getDefaultSystemFontSize();
 463         }
 464         // Now lets parse the URL and decide if its a file,
 465         // or a remote URL from which we need to read.
 466         if (url.getProtocol().equals("file")) {
 467             String path = url.getFile();
 468             // The URL path may have a leading "/", when obtained
 469             // via ClassLoader. This can cause problems on Windows.
 470             // Getting the path from a File fixes this.
 471             path = new java.io.File(path).getPath();
 472             try {
 473                 SecurityManager sm = System.getSecurityManager();
 474                 if (sm != null) {
 475                     FilePermission filePermission =
 476                         new FilePermission(path, "read");
 477                     sm.checkPermission(filePermission);
 478                 }
 479             } catch (Exception e) {
 480                 return null;
 481             }
 482             return
 483             Toolkit.getToolkit().getFontLoader().loadFont(path, size, loadAll);
 484         }
 485         Font[] fonts = null;
 486         URLConnection connection = null;
 487         InputStream in = null;
 488         try {
 489             connection = url.openConnection();
 490             in = connection.getInputStream();
 491             fonts =
 492                Toolkit.getToolkit().getFontLoader().loadFont(in, size, loadAll);
 493         } catch (Exception e) {
 494             return null;
 495         } finally {
 496             try {
 497                 if (in != null) {
 498                     in.close();
 499                 }
 500             } catch (Exception e) {
 501             }
 502         }
 503         return fonts;
 504     }
 505 
 506     /**
 507      * Loads a font resource from the specified input stream.
 508      * If the load is successful such that the stream can be
 509      * fully read, and it represents a supported font format then a
 510      * <code>Font</code> object will be returned.
 511      * <p>
 512      * The use case for this method is for loading all fonts
 513      * from a TrueType Collection (TTC).
 514      * <p>
 515      * If a security manager is present, the application
 516      * must have the {@link javafx.util.FXPermission} "loadFont".
 517      * If the application does not have permission then this method
 518      * will return the default system font with the specified font size.
 519      * <p>
 520      * Any failure such as abbreviated input, or an unsupported font format
 521      * will result in a <code>null</code> return. It is the application's
 522      * responsibility to check this before use.
 523      * <p>
 524      * On a successful (non-null) return the fonts will be registered
 525      * with the FX graphics system for creation by available constructors
 526      * and factory methods, and the application should use it in this
 527      * manner rather than calling this method again, which would
 528      * repeat the overhead of re-reading and installing the font.
 529      * <p>
 530      * The font <code>size</code> parameter is a convenience so that in
 531      * typical usage the application can directly use the returned (non-null)
 532      * fonts rather than needing to create one via a constructor. Invalid sizes
 533      * are those <=0 and will result in a default size.
 534      * <p>
 535      * This method does not close the input stream.
 536      * @param in stream from which to load the font.
 537      * @param size of the returned font.
 538      * @return array of Font, or null if the fonts cannot be created.
 539      * @since 9
 540      */
 541     public static Font loadFont(InputStream in, double size) {
 542         if (size <= 0) {
 543             size = getDefaultSystemFontSize();
 544         }
 545         Font[] fonts =
 546            Toolkit.getToolkit().getFontLoader().loadFont(in, size, false);
 547         return (fonts == null) ? null : fonts[0];
 548     }
 549 
 550     /**
 551      * Loads font resources from the specified input stream.
 552      * If the load is successful such that the stream can be
 553      * fully read, and it represents a supported font format then a
 554      * an array of <code>Font</code> object will be returned.
 555      * <p>
 556      * If a security manager is present, the application
 557      * must have the {@link javafx.util.FXPermission} "loadFont".
 558      * If the application does not have permission then this method
 559      * will return the default system font with the specified font size.
 560      * <p>
 561      * Any failure such as abbreviated input, or an unsupported font format
 562      * will result in a <code>null</code> return. It is the application's
 563      * responsibility to check this before use.
 564      * <p>
 565      * On a successful (non-null) return the font will be registered
 566      * with the FX graphics system for creation by available constructors
 567      * and factory methods, and the application should use it in this
 568      * manner rather than calling this method again, which would
 569      * repeat the overhead of re-reading and installing the font.
 570      * <p>
 571      * The font <code>size</code> parameter is a convenience so that in
 572      * typical usage the application can directly use the returned (non-null)
 573      * font rather than needing to create one via a constructor. Invalid sizes
 574      * are those <=0 and will result in a default size.
 575      * <p>
 576      * This method does not close the input stream.
 577      * @param in stream from which to load the font.
 578      * @param size of the returned font.
 579      * @return the Font, or null if the font cannot be created.
 580      */
 581     public static Font[] loadFonts(InputStream in, double size) {
 582         if (size <= 0) {
 583             size = getDefaultSystemFontSize();
 584         }
 585         Font[] fonts =
 586             Toolkit.getToolkit().getFontLoader().loadFont(in, size, true);
 587         return (fonts == null) ? null : fonts;
 588     }
 589 
 590     /**
 591      * Converts this {@code Font} object to a {@code String} representation.
 592      * The String representation is for informational use only and will change.
 593      * Do not use this string representation for any programmatic purpose.
 594      */
 595     @Override public String toString() {
 596         StringBuilder builder = new StringBuilder("Font[name=");
 597         builder = builder.append(name);
 598         builder = builder.append(", family=").append(family);
 599         builder = builder.append(", style=").append(style);
 600         builder = builder.append(", size=").append(size);
 601         builder = builder.append("]");
 602         return builder.toString();
 603     }
 604 
 605     /**
 606      * Indicates whether some other object is "equal to" this one.
 607      * @param obj the reference object with which to compare.
 608      * @return {@code true} if this object is equal to the {@code obj} argument; {@code false} otherwise.
 609      */
 610     @Override public boolean equals(Object obj) {
 611         if (obj == this) return true;
 612         if (obj instanceof Font) {
 613             Font other = (Font)obj;
 614             return (name == null ? other.name == null : name.equals(other.name))
 615                 && size == other.size;
 616         }
 617         return false;
 618     }
 619 
 620     /**
 621      * Returns a hash code for this {@code Font} object.
 622      * @return a hash code for this {@code Font} object.
 623      */
 624     @Override public int hashCode() {
 625         if (hash == 0) {
 626             long bits = 17L;
 627             bits = 37L * bits + name.hashCode();
 628             bits = 37L * bits + Double.doubleToLongBits(size);
 629             hash = (int) (bits ^ (bits >> 32));
 630         }
 631         return hash;
 632     }
 633 
 634     private Object nativeFont;
 635 
 636     Object getNativeFont() { return nativeFont; }
 637 
 638     void setNativeFont(Object f, String nam, String fam, String styl) {
 639         nativeFont = f;
 640         name = nam;
 641         family = fam;
 642         style = styl;
 643     }
 644 
 645     static Font nativeFont(Object f, String name, String family,
 646                                        String style, double size) {
 647         Font retFont = new Font( f, family, name, style, size);
 648         return retFont;
 649     }
 650 }