javafx.scene.text.Font Maven / Gradle / Ivy
/*
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javafx.scene.text;
import com.sun.javafx.scene.text.FontHelper;
import java.io.FilePermission;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import com.sun.javafx.tk.Toolkit;
import javafx.beans.NamedArg;
/**
* The {@code Font} class represents fonts, which are used to render text on
* screen.
*
* The size of a {@code Font} is described as being specified in points
* which are a real world measurement of approximately 1/72 inch.
*
* Given that fonts scale with the rendering transform as determined
* by the transform attributes of a {@code Node} using the {@code Font}
* and its ancestors, the size will actually be relative to the local
* coordinate space of the node, which should provide coordinates
* similar to the size of a point if no scaling transforms are present
* in the environment of the node.
* Note that the real world distances specified by the default coordinate
* system only approximate point sizes as a rule of thumb and are typically
* defaulted to screen pixels for most displays.
*
* For more information see {@link javafx.scene.Node} for more information
* on the default coordinate system
* @since JavaFX 2.0
*/
public final class Font {
static {
// This is used by classes in different packages to get access to
// private and package private methods.
FontHelper.setFontAccessor(new FontHelper.FontAccessor() {
@Override
public Object getNativeFont(Font font) {
return font.getNativeFont();
}
@Override
public void setNativeFont(Font font, Object f, String nam, String fam, String styl) {
font.setNativeFont(f, nam, fam, styl);
}
@Override
public Font nativeFont(Object f, String name, String family, String style, double size) {
return Font.nativeFont(f, name, family, style, size);
}
});
}
private static final String DEFAULT_FAMILY = "System";
private static final String DEFAULT_FULLNAME = "System Regular";
/**
* The default font for this platform. This is used whenever a font is not
* specifically set on a Text node or overridden by CSS.
*/
private static float defaultSystemFontSize = -1;
private static float getDefaultSystemFontSize() {
if (defaultSystemFontSize == -1) {
defaultSystemFontSize =
Toolkit.getToolkit().getFontLoader().getSystemFontSize();
}
return defaultSystemFontSize;
}
private static Font DEFAULT;
/**
* Gets the default font which will be from the family "System",
* and typically the style "Regular", and be of a size consistent
* with the user's desktop environment, to the extent that can
* be determined.
* @return The default font.
*/
public static synchronized Font getDefault() {
if (DEFAULT == null) {
DEFAULT = new Font(DEFAULT_FULLNAME, getDefaultSystemFontSize());
}
return DEFAULT;
}
/**
* Gets all the font families installed on the user's system, including any
* application fonts or SDK fonts. This call has performance considerations
* as looking up all of the fonts may be an expensive operation the
* first time.
* @return The list containing all available font families.
*/
public static List getFamilies() {
return Toolkit.getToolkit().getFontLoader().getFamilies();
}
/**
* Gets the names of all fonts that are installed on the users system,
* including any application fonts and SDK fonts.
* This call has performance considerations as
* looking up all of the fonts may be an expensive operation the first time.
* @return The list containing all available fonts.
*/
public static List getFontNames() {
return Toolkit.getToolkit().getFontLoader().getFontNames();
}
/**
* Gets the names of all fonts in the specified font family that are
* installed on the users system, including any application fonts
* and SDK fonts.
* This call has performance considerations as looking up all of the
* fonts may be an expensive operation the first time.
* @param family the font family
* @return The list containing the fonts for the given family.
*/
public static List getFontNames(String family) {
return Toolkit.getToolkit().getFontLoader().getFontNames(family);
}
/**
* Searches for an appropriate font based on the font family name and
* weight and posture style. This method is not guaranteed to return
* a specific font, but does its best to find one that fits the
* specified requirements.
*
* A null or empty value for family allows the implementation to
* select any suitable font.
*
* @param family The family of the font
* @param weight The weight of the font
* @param posture The posture or posture of the font
* @param size {@literal The point size of the font. This can be a fractional value,
* but must not be negative. If the size is < 0 the default size will be
* used.}
* @return The font that best fits the specified requirements.
*/
public static Font font(String family, FontWeight weight,
FontPosture posture, double size) {
String fam =
(family == null || "".equals(family)) ? DEFAULT_FAMILY : family;
double sz = size < 0 ? getDefaultSystemFontSize() : size;
return Toolkit.getToolkit().getFontLoader().font(fam, weight, posture, (float)sz);
}
/**
* Searches for an appropriate font based on the font family name and weight
* style. This method is not guaranteed to return a specific font, but does
* its best to find one that fits the specified requirements.
* A null or empty value for family allows the implementation
* to select any suitable font.
*
* @param family The family of the font
* @param weight The weight of the font
* @param size {@literal The point size of the font. This can be a fractional value,
* but must not be negative. If the size is < 0 the default size will be
* used.}
* @return The font that best fits the specified requirements.
*/
public static Font font(String family, FontWeight weight, double size) {
return font(family, weight, null, size);
}
/**
* Searches for an appropriate font based on the font family name and posture
* style. This method is not guaranteed to return a specific font, but does
* its best to find one that fits the specified requirements. A null or empty
* value for family allows the implementation to select any suitable font.
*
* @param family The family of the font
* @param posture The posture or posture of the font
* @param size {@literal The point size of the font. This can be a fractional value,
* but must not be negative. If the size is < 0 the default size will be
* used.}
* @return The font that best fits the specified requirements.
*/
public static Font font(String family, FontPosture posture, double size) {
return font(family, null, posture, size);
}
/**
* Searches for an appropriate font based on the font family name and size.
* This method is not guaranteed to return a specific font, but does
* its best to find one that fits the specified requirements. A null or empty
* value for family allows the implementation to select any suitable font.
*
* @param family The family of the font
* @param size {@literal The point size of the font. This can be a fractional value,
* but must not be negative. If the size is < 0 the default size will be
* used.}
* @return The font that best fits the specified requirements.
*/
public static Font font(String family, double size) {
return font(family, null, null, size);
}
/**
* Searches for an appropriate font based on the given font family name and
* default font size.
* This method is not guaranteed to return a specific font, but does
* its best to find one that fits the specified requirements. A null or empty
* value for family allows the implementation to select any suitable font.
*
* @param family The family of the font
* @return The font that best fits the specified requirements.
*/
public static Font font(String family) {
return font(family, null, null, -1);
}
/**
* Searches for an appropriate font based on the default font family name and
* given font size.
* This method is not guaranteed to return a specific font, but does
* its best to find one that fits the specified requirements.
*
* @param size {@literal The point size of the font. This can be a fractional value,
* but must not be negative. If the size is < 0 the default size will be
* used.}
* @return The font that best fits the specified requirements.
*/
public static Font font(double size) {
return font(null, null, null, size);
}
/**
* The full font name. This name includes both the family name
* and the style variant within that family. For example, for a plain
* Arial font this would be "Arial Regular" and for a bolded
* Arial font this would be "Arial Bold". The precise name to use when
* loading a font is defined within each font file as the full font name.
* For example, "Proxima Nova ExtraCondensed Bold Italic" would refer to a
* specific Proxima Nova font.
* A null or empty name allows the implementation to select any suitable
* font.
*
* There is a single unified way to load all of application supplied
* (via Font.loadFont()
, JavaFX runtime delivered fonts,
* and system installed fonts. Simply create the font by specifying
* the full name of the font you want to load.
* If the specific font cannot be located, then a fallback or default
* font will be used. The "name" will be updated to reflect the actual name
* of the font being used. A load failure condition can be discovered by
* checking the name of the Font with the name you tried to load.
*
* Note that if you wish to locate a font by font family and style
* then you can use one of the {@link #font} factory methods defined in
* this class.
*
* @return the full font name
* @defaultValue empty string
*/
public final String getName() { return name; }
private String name;
/**
* Returns the family of this font.
* @return The family of this font.
*/
public final String getFamily() { return family; }
private String family;
/**
* The font specified string describing the style within the font family.
* @return The style name of this font.
*/
public final String getStyle() { return style; }
private String style;
/**
* The point size for this font. This may be a fractional value such as
* {@code 11.5}. {@literal If the specified value is < 0 the default size will be
* used.}
*
* @return the point size for this font
* @defaultValue 12
*/
public final double getSize() { return size; }
private double size;
/**
* The cached hash code, used to improve performance in situations where
* we cache fonts, such as in the CSS routines.
*/
private int hash = 0;
/**
* Constructs a font using the default face "System".
* The underlying font used is determined by the implementation
* based on the typical UI font for the current UI environment.
*
* @param size the font size to use
*/
public Font(@NamedArg("size") double size) {
this(null, size);
}
/**
* Constructs a font using the specified full face name and size
* @param name full name of the font.
* @param size the font size to use
*/
public Font(@NamedArg("name") String name, @NamedArg("size") double size) {
this.name = name;
this.size = size;
if (name == null || "".equals(name)) this.name = DEFAULT_FULLNAME;
if (size < 0f) this.size = getDefaultSystemFontSize();
// if a search was done based on family + style information, then the
// native font has already been located and specified. Likewise if the
// Font was created based on an existing native font. If however a Font
// was created directly in FX, then we need to find the native font
// to use. This call will also set the family and style by invoking
// the setNativeFont callback method.
Toolkit.getToolkit().getFontLoader().loadFont(this);
}
/**
* Private constructor for internal implementation
*
* @param f native font
* @param family font family name
* @param name font full name
* @param style style string
* @param size font size
*/
private Font(Object f, String family, String name, String style, double size) {
this.nativeFont = f;
this.family = family;
this.name = name;
this.style = style;
this.size = size;
}
/**
* Loads a font resource from the specified URL. If the load is successful
* such that the location is readable, and it represents a supported
* font format then a Font
object will be returned.
*
* If a security manager is present, the application
* must have both permission to read from the specified URL location
* and the {@link javafx.util.FXPermission} "loadFont".
* If the application does not have permission to read from the specified
* URL location, then null is returned.
* If the application does not have the "loadFont" permission then this method
* will return the default system font with the specified font size.
*
* Any failure such as a malformed URL being unable to locate or read
* from the resource, or if it doesn't represent a font, will result in
* a null
return. It is the application's responsibility
* to check this before use.
*
* On a successful (non-null) return the font will be registered
* with the FX graphics system for creation by available constructors
* and factory methods, and the application should use it in this
* manner rather than calling this method again, which would
* repeat the overhead of downloading and installing the font.
*
* The font size
parameter is a convenience so that in
* typical usage the application can directly use the returned (non-null)
* font rather than needing to create one via a constructor.
* {@literal Invalid sizes are those <=0 and will result in a default size.}
*
* If the URL represents a local disk file, then no copying is performed
* and the font file is required to persist for the lifetime of the
* application. Updating the file in any manner will result
* in unspecified and likely undesired behaviours.
*
* @param urlStr from which to load the font, specified as a String.
* @param size of the returned font.
* @return the Font, or null if the font cannot be created.
*/
public static Font loadFont(String urlStr, double size) {
Font[] fonts = loadFontInternal(urlStr, size, false);
return (fonts == null) ? null : fonts[0];
}
/**
* Loads font resources from the specified URL. If the load is successful
* such that the location is readable, and it represents a supported
* font format then an array of Font
will be returned.
*
* The use case for this method is for loading all fonts
* from a TrueType Collection (TTC).
*
* If a security manager is present, the application
* must have both permission to read from the specified URL location
* and the {@link javafx.util.FXPermission} "loadFont".
* If the application does not have permission to read from the specified
* URL location, then null is returned.
* If the application does not have the "loadFont" permission then this method
* will return an array of one element which is the default
* system font with the specified font size.
*
* Any failure such as a malformed URL being unable to locate or read
* from the resource, or if it doesn't represent a font, will result in
* a null
return. It is the application's responsibility
* to check this before use.
*
* On a successful (non-null) return the fonts will be registered
* with the FX graphics system for creation by available constructors
* and factory methods, and the application should use it in this
* manner rather than calling this method again, which would
* repeat the overhead of downloading and installing the fonts.
*
* The font size
parameter is a convenience so that in
* typical usage the application can directly use the returned (non-null)
* font rather than needing to create one via a constructor.
* {@literal Invalid sizes are those <=0 and will result in a default size.}
*
* If the URL represents a local disk file, then no copying is performed
* and the font file is required to persist for the lifetime of the
* application. Updating the file in any manner will result
* in unspecified and likely undesired behaviours.
*
* @param urlStr from which to load the fonts, specified as a String.
* @param size of the returned fonts.
* @return array of Font, or null if the fonts cannot be created.
* @since 9
*/
public static Font[] loadFonts(String urlStr, double size) {
return loadFontInternal(urlStr, size, true);
}
private static Font[] loadFontInternal(String urlStr, double size,
boolean loadAll) {
URL url = null;
try {
url = new URL(urlStr); // null string arg. is caught here.
} catch (Exception e) {
return null;
}
if (size <= 0) {
size = getDefaultSystemFontSize();
}
// Now lets parse the URL and decide if its a file,
// or a remote URL from which we need to read.
if (url.getProtocol().equals("file")) {
String path = url.getFile();
// The URL path may have a leading "/", when obtained
// via ClassLoader. This can cause problems on Windows.
// Getting the path from a File fixes this.
path = new java.io.File(path).getPath();
try {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
FilePermission filePermission =
new FilePermission(path, "read");
sm.checkPermission(filePermission);
}
} catch (Exception e) {
return null;
}
return
Toolkit.getToolkit().getFontLoader().loadFont(path, size, loadAll);
}
Font[] fonts = null;
URLConnection connection = null;
InputStream in = null;
try {
connection = url.openConnection();
in = connection.getInputStream();
fonts =
Toolkit.getToolkit().getFontLoader().loadFont(in, size, loadAll);
} catch (Exception e) {
return null;
} finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e) {
}
}
return fonts;
}
/**
* Loads a font resource from the specified input stream.
* If the load is successful such that the stream can be
* fully read, and it represents a supported font format then a
* Font
object will be returned.
*
* If a security manager is present, the application
* must have the {@link javafx.util.FXPermission} "loadFont".
* If the application does not have permission then this method
* will return the default system font with the specified font size.
*
* Any failure such as abbreviated input, or an unsupported font format
* will result in a null
return. It is the application's
* responsibility to check this before use.
*
* On a successful (non-null) return the font will be registered
* with the FX graphics system for creation by available constructors
* and factory methods, and the application should use it in this
* manner rather than calling this method again, which would
* repeat the overhead of re-reading and installing the font.
*
* The font size
parameter is a convenience so that in
* typical usage the application can directly use the returned (non-null)
* font rather than needing to create one via a constructor.
* {@literal Invalid sizes are those <=0 and will result in a default size.}
*
* This method does not close the input stream.
* @param in stream from which to load the font.
* @param size of the returned font.
* @return the Font, or null if the font cannot be created.
*/
public static Font loadFont(InputStream in, double size) {
if (size <= 0) {
size = getDefaultSystemFontSize();
}
Font[] fonts =
Toolkit.getToolkit().getFontLoader().loadFont(in, size, false);
return (fonts == null) ? null : fonts[0];
}
/**
* Loads font resources from the specified input stream.
* If the load is successful such that the stream can be
* fully read, and it represents a supported font format then
* an array of Font
will be returned.
*
* The use case for this method is for loading all fonts
* from a TrueType Collection (TTC).
*
* If a security manager is present, the application
* must have the {@link javafx.util.FXPermission} "loadFont".
* If the application does not have permission then this method
* will return the default system font with the specified font size.
*
* Any failure such as abbreviated input, or an unsupported font format
* will result in a null
return. It is the application's
* responsibility to check this before use.
*
* On a successful (non-null) return the fonts will be registered
* with the FX graphics system for creation by available constructors
* and factory methods, and the application should use it in this
* manner rather than calling this method again, which would
* repeat the overhead of re-reading and installing the fonts.
*
* The font size
parameter is a convenience so that in
* typical usage the application can directly use the returned (non-null)
* fonts rather than needing to re-create via a constructor.
* {@literal Invalid sizes are those <=0 and will result in a default size.}
*
* This method does not close the input stream.
* @param in stream from which to load the fonts.
* @param size of the returned fonts.
* @return array of Font, or null if the fonts cannot be created.
* @since 9
*/
public static Font[] loadFonts(InputStream in, double size) {
if (size <= 0) {
size = getDefaultSystemFontSize();
}
Font[] fonts =
Toolkit.getToolkit().getFontLoader().loadFont(in, size, true);
return (fonts == null) ? null : fonts;
}
/**
* Converts this {@code Font} object to a {@code String} representation.
* The String representation is for informational use only and will change.
* Do not use this string representation for any programmatic purpose.
*/
@Override public String toString() {
StringBuilder builder = new StringBuilder("Font[name=");
builder = builder.append(name);
builder = builder.append(", family=").append(family);
builder = builder.append(", style=").append(style);
builder = builder.append(", size=").append(size);
builder = builder.append("]");
return builder.toString();
}
/**
* Indicates whether some other object is "equal to" this one.
* @param obj the reference object with which to compare.
* @return {@code true} if this object is equal to the {@code obj} argument; {@code false} otherwise.
*/
@Override public boolean equals(Object obj) {
if (obj == this) return true;
if (obj instanceof Font) {
Font other = (Font)obj;
return (name == null ? other.name == null : name.equals(other.name))
&& size == other.size;
}
return false;
}
/**
* Returns a hash code for this {@code Font} object.
* @return a hash code for this {@code Font} object.
*/
@Override public int hashCode() {
if (hash == 0) {
long bits = 17L;
bits = 37L * bits + name.hashCode();
bits = 37L * bits + Double.doubleToLongBits(size);
hash = (int) (bits ^ (bits >> 32));
}
return hash;
}
private Object nativeFont;
Object getNativeFont() { return nativeFont; }
void setNativeFont(Object f, String nam, String fam, String styl) {
nativeFont = f;
name = nam;
family = fam;
style = styl;
}
static Font nativeFont(Object f, String name, String family,
String style, double size) {
Font retFont = new Font( f, family, name, style, size);
return retFont;
}
}