/* * Copyright (c) 1995, 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.
*/
/** * The {@code Font} class represents fonts, which are used to * render text in a visible way. * A font provides the information needed to map sequences of * <em>characters</em> to sequences of <em>glyphs</em> * and to render sequences of glyphs on {@code Graphics} and * {@code Component} objects. * * <h2>Characters and Glyphs</h2> * * A <em>character</em> is a symbol that represents an item such as a letter, * a digit, or punctuation in an abstract way. For example, {@code 'g'}, * LATIN SMALL LETTER G, is a character. * <p> * A <em>glyph</em> is a shape used to render a character or a sequence of * characters. In simple writing systems, such as Latin, typically one glyph * represents one character. In general, however, characters and glyphs do not * have one-to-one correspondence. For example, the character 'á' * LATIN SMALL LETTER A WITH ACUTE, can be represented by * two glyphs: one for 'a' and one for '´'. On the other hand, the * two-character string "fi" can be represented by a single glyph, an * "fi" ligature. In complex writing systems, such as Arabic or the South * and South-East Asian writing systems, the relationship between characters * and glyphs can be more complicated and involve context-dependent selection * of glyphs as well as glyph reordering. * * A font encapsulates the collection of glyphs needed to render a selected set * of characters as well as the tables needed to map sequences of characters to * corresponding sequences of glyphs. * * <h2>Physical and Logical Fonts</h2> * * The Java Platform distinguishes between two kinds of fonts: * <em>physical</em> fonts and <em>logical</em> fonts. * <p> * <em>Physical</em> fonts are the actual font libraries containing glyph data * and tables to map from character sequences to glyph sequences, using a font * technology such as TrueType or PostScript Type 1. * All implementations of the Java Platform must support TrueType fonts; * support for other font technologies is implementation dependent. * Physical fonts may use names such as Helvetica, Palatino, HonMincho, or * any number of other font names. * Typically, each physical font supports only a limited set of writing * systems, for example, only Latin characters or only Japanese and Basic * Latin. * The set of available physical fonts varies between configurations. * Applications that require specific fonts can bundle them and instantiate * them using the {@link #createFont createFont} method. * <p> * <em>Logical</em> fonts are the five font families defined by the Java * platform which must be supported by any Java runtime environment: * Serif, SansSerif, Monospaced, Dialog, and DialogInput. * These logical fonts are not actual font libraries. Instead, the logical * font names are mapped to physical fonts by the Java runtime environment. * The mapping is implementation and usually locale dependent, so the look * and the metrics provided by them vary. * Typically, each logical font name maps to several physical fonts in order to * cover a large range of characters. * <p> * Peered AWT components, such as {@link Label Label} and * {@link TextField TextField}, can only use logical fonts. * <p> * For a discussion of the relative advantages and disadvantages of using * physical or logical fonts, see the * <a href="https://docs.oracle.com/javase/tutorial/2d/text/fonts.html#advantages-and-disadvantages"> * Physical and Logical Fonts</a> * in <a href="https://docs.oracle.com/javase/tutorial/index.html">The Java Tutorials</a> * document. * * <h2>Font Faces and Names</h2> * * A {@code Font} * can have many faces, such as heavy, medium, oblique, gothic and * regular. All of these faces have similar typographic design. * <p> * There are three different names that you can get from a * {@code Font} object. The <em>logical font name</em> is simply the * name that was used to construct the font. * The <em>font face name</em>, or just <em>font name</em> for * short, is the name of a particular font face, like Helvetica Bold. The * <em>family name</em> is the name of the font family that determines the * typographic design across several faces, like Helvetica. * <p> * The {@code Font} class represents an instance of a font face from * a collection of font faces that are present in the system resources * of the host system. As examples, Arial Bold and Courier Bold Italic * are font faces. There can be several {@code Font} objects * associated with a font face, each differing in size, style, transform * and font features. * <p> * Glyphs may not always be rendered with the requested properties (e.g, font * and style) due to platform limitations such as the absence of suitable * platform fonts to implement a logical font. * <p> * The {@link GraphicsEnvironment#getAllFonts() getAllFonts} method * of the {@code GraphicsEnvironment} class returns an * array of all font faces available in the system. These font faces are * returned as {@code Font} objects with a size of 1, identity * transform and default font features. These * base fonts can then be used to derive new {@code Font} objects * with varying sizes, styles, transforms and font features via the * {@code deriveFont} methods in this class. * * <h2>Font and TextAttribute</h2> * * <p>{@code Font} supports most * {@code TextAttribute}s. This makes some operations, such as * rendering underlined text, convenient since it is not * necessary to explicitly construct a {@code TextLayout} object. * Attributes can be set on a Font by constructing or deriving it * using a {@code Map} of {@code TextAttribute} values. * * <p>The values of some {@code TextAttributes} are not * serializable, and therefore attempting to serialize an instance of * {@code Font} that has such values will not serialize them. * This means a Font deserialized from such a stream will not compare * equal to the original Font that contained the non-serializable * attributes. This should very rarely pose a problem * since these attributes are typically used only in special * circumstances and are unlikely to be serialized. * * <ul> * <li>{@code FOREGROUND} and {@code BACKGROUND} use * {@code Paint} values. The subclass {@code Color} is * serializable, while {@code GradientPaint} and * {@code TexturePaint} are not.</li> * <li>{@code CHAR_REPLACEMENT} uses * {@code GraphicAttribute} values. The subclasses * {@code ShapeGraphicAttribute} and * {@code ImageGraphicAttribute} are not serializable.</li> * <li>{@code INPUT_METHOD_HIGHLIGHT} uses * {@code InputMethodHighlight} values, which are * not serializable. See {@link java.awt.im.InputMethodHighlight}.</li> * </ul> * * <p>Clients who create custom subclasses of {@code Paint} and * {@code GraphicAttribute} can make them serializable and * avoid this problem. Clients who use input method highlights can * convert these to the platform-specific attributes for that * highlight on the current platform and set them on the Font as * a workaround. * * <p>The {@code Map}-based constructor and * {@code deriveFont} APIs ignore the FONT attribute, and it is * not retained by the Font; the static {@link #getFont} method should * be used if the FONT attribute might be present. See {@link * java.awt.font.TextAttribute#FONT} for more information.</p> * * <p>Several attributes will cause additional rendering overhead * and potentially invoke layout. If a {@code Font} has such * attributes, the <code>{@link #hasLayoutAttributes()}</code> method * will return true.</p> * * <p>Note: Font rotations can cause text baselines to be rotated. In * order to account for this (rare) possibility, font APIs are * specified to return metrics and take parameters 'in * baseline-relative coordinates'. This maps the 'x' coordinate to * the advance along the baseline, (positive x is forward along the * baseline), and the 'y' coordinate to a distance along the * perpendicular to the baseline at 'x' (positive y is 90 degrees * clockwise from the baseline vector). APIs for which this is * especially important are called out as having 'baseline-relative * coordinates.'
*/ publicclass Font implements java.io.Serializable
{ privatestaticclass FontAccessImpl extends FontAccess { public Font2D getFont2D(Font font) { return font.getFont2D();
}
@Override public FontPeer getFontPeer(final Font font) { return font.getFontPeer();
}
}
static { /* ensure that the necessary native libraries are loaded */
Toolkit.loadLibraries();
initIDs();
FontAccess.setFontAccess(new FontAccessImpl());
}
/** * This is now only used during serialization. Typically * it is null. * * @serial * @see #getAttributes()
*/ private Hashtable<Object, Object> fRequestedAttributes;
/* * Constants to be used for logical font family names.
*/
/** * A String constant for the canonical family name of the * logical font "Dialog". It is useful in Font construction * to provide compile-time verification of the name. * @since 1.6
*/ publicstaticfinal String DIALOG = "Dialog";
/** * A String constant for the canonical family name of the * logical font "DialogInput". It is useful in Font construction * to provide compile-time verification of the name. * @since 1.6
*/ publicstaticfinal String DIALOG_INPUT = "DialogInput";
/** * A String constant for the canonical family name of the * logical font "SansSerif". It is useful in Font construction * to provide compile-time verification of the name. * @since 1.6
*/ publicstaticfinal String SANS_SERIF = "SansSerif";
/** * A String constant for the canonical family name of the * logical font "Serif". It is useful in Font construction * to provide compile-time verification of the name. * @since 1.6
*/ publicstaticfinal String SERIF = "Serif";
/** * A String constant for the canonical family name of the * logical font "Monospaced". It is useful in Font construction * to provide compile-time verification of the name. * @since 1.6
*/ publicstaticfinal String MONOSPACED = "Monospaced";
/* * Constants to be used for styles. Can be combined to mix * styles.
*/
/** * The bold style constant. This can be combined with the other style * constants (except PLAIN) for mixed styles.
*/ publicstaticfinalint BOLD = 1;
/** * The italicized style constant. This can be combined with the other * style constants (except PLAIN) for mixed styles.
*/ publicstaticfinalint ITALIC = 2;
/** * The baseline used in most Roman scripts when laying out text.
*/ publicstaticfinalint ROMAN_BASELINE = 0;
/** * The baseline used in ideographic scripts like Chinese, Japanese, * and Korean when laying out text.
*/ publicstaticfinalint CENTER_BASELINE = 1;
/** * The baseline used in Devanagari and similar scripts when laying * out text.
*/ publicstaticfinalint HANGING_BASELINE = 2;
/** * Identify a font resource of type TRUETYPE. * Used to specify a TrueType font resource to the * {@link #createFont} method. * The TrueType format was extended to become the OpenType * format, which adds support for fonts with Postscript outlines, * this tag therefore references these fonts, as well as those * with TrueType outlines. * @since 1.3
*/
publicstaticfinalint TRUETYPE_FONT = 0;
/** * Identify a font resource of type TYPE1. * Used to specify a Type1 font resource to the * {@link #createFont} method. * @since 1.5
*/ publicstaticfinalint TYPE1_FONT = 1;
/** * The logical name of this {@code Font}, as passed to the * constructor. * @since 1.0 * * @serial * @see #getName
*/ protected String name;
/** * The style of this {@code Font}, as passed to the constructor. * This style can be PLAIN, BOLD, ITALIC, or BOLD+ITALIC. * @since 1.0 * * @serial * @see #getStyle()
*/ protectedint style;
/** * The point size of this {@code Font}, rounded to integer. * @since 1.0 * * @serial * @see #getSize()
*/ protectedint size;
/** * The point size of this {@code Font} in {@code float}. * * @serial * @see #getSize() * @see #getSize2D()
*/ protectedfloat pointSize;
/** * The platform specific font information.
*/ privatetransient FontPeer peer; privatetransientlong pData; // native JDK1.1 font pointer privatetransient Font2DHandle font2DHandle;
/* * If the origin of a Font is a created font then this attribute * must be set on all derived fonts too.
*/ privatetransientboolean createdFont = false;
/* * This is true if the font transform is not identity. It * is used to avoid unnecessary instantiation of an AffineTransform.
*/ privatetransientboolean nonIdentityTx;
/* * A cached value used when a transform is required for internal * use. This must not be exposed to callers since AffineTransform * is mutable.
*/ privatestaticfinal AffineTransform identityTx = new AffineTransform();
/** * Use serialVersionUID from JDK 1.1 for interoperability.
*/
@Serial privatestaticfinallong serialVersionUID = -4206021311591459213L;
/** * Gets the peer of this {@code Font}. * * @return the peer of the {@code Font}.
*/ private FontPeer getFontPeer() { if(peer == null) {
Toolkit tk = Toolkit.getDefaultToolkit(); if (tk instanceof ComponentFactory) {
peer = ((ComponentFactory) tk).getFontPeer(name, style);
}
} return peer;
}
/** * Return the AttributeValues object associated with this * font. Most of the time, the internal object is null. * If required, it will be created from the 'standard' * state on the font. Only non-default values will be * set in the AttributeValues object. * * <p>Since the AttributeValues object is mutable, and it * is cached in the font, care must be taken to ensure that * it is not mutated.
*/ private AttributeValues getAttributeValues() { if (values == null) {
AttributeValues valuesTmp = new AttributeValues();
valuesTmp.setFamily(name);
valuesTmp.setSize(pointSize); // expects the float value.
if ((style & ITALIC) != 0) {
valuesTmp.setPosture(.2f); // POSTURE_OBLIQUE
}
valuesTmp.defineAll(PRIMARY_MASK); // for streaming compatibility
values = valuesTmp;
}
return values;
}
private Font2D getFont2D() {
FontManager fm = FontManagerFactory.getInstance(); if (font2DHandle == null) {
font2DHandle =
fm.findFont2D(name, style,
FontManager.LOGICAL_FALLBACK).handle;
} /* Do not cache the de-referenced font2D. It must be explicitly * de-referenced to pick up a valid font in the event that the * original one is marked invalid
*/ return font2DHandle.font2D;
}
/** * Creates a new {@code Font} from the specified name, style and * point size. * <p> * The font name can be a font face name or a font family name. * It is used together with the style to find an appropriate font face. * When a font family name is specified, the style argument is used to * select the most appropriate face from the family. When a font face * name is specified, the face's style and the style argument are * merged to locate the best matching font from the same family. * For example if face name "Arial Bold" is specified with style * {@code Font.ITALIC}, the font system looks for a face in the * "Arial" family that is bold and italic, and may associate the font * instance with the physical font face "Arial Bold Italic". * The style argument is merged with the specified face's style, not * added or subtracted. * This means, specifying a bold face and a bold style does not * double-embolden the font, and specifying a bold face and a plain * style does not lighten the font. * <p> * If no face for the requested style can be found, the font system * may apply algorithmic styling to achieve the desired style. * For example, if {@code ITALIC} is requested, but no italic * face is available, glyphs from the plain face may be algorithmically * obliqued (slanted). * <p> * Font name lookup is case insensitive, using the case folding * rules of the US locale. * <p> * If the {@code name} parameter represents something other than a * logical font, i.e. is interpreted as a physical font face or family, and * this cannot be mapped by the implementation to a physical font or a * compatible alternative, then the font system will map the Font * instance to "Dialog", such that for example, the family as reported * by {@link #getFamily() getFamily} will be "Dialog". * * @param name the font name. This can be a font face name or a font * family name, and may represent either a logical font or a physical * font found in this {@code GraphicsEnvironment}. * The family names for logical fonts are: Dialog, DialogInput, * Monospaced, Serif, or SansSerif. Pre-defined String constants exist * for all of these names, for example, {@code DIALOG}. If {@code name} is * {@code null}, the <em>logical font name</em> of the new * {@code Font} as returned by {@code getName()} is set to * the name "Default". * @param style the style constant for the {@code Font} * The style argument is an integer bitmask that may * be {@code PLAIN}, or a bitwise union of {@code BOLD} and/or * {@code ITALIC} (for example, {@code ITALIC} or {@code BOLD|ITALIC}). * If the style argument does not conform to one of the expected * integer bitmasks then the style is set to {@code PLAIN}. * @param size the point size of the {@code Font} * @see GraphicsEnvironment#getAllFonts * @see GraphicsEnvironment#getAvailableFontFamilyNames * @since 1.0
*/ public Font(String name, int style, int size) { this.name = (name != null) ? name : "Default"; this.style = (style & ~0x03) == 0 ? style : 0; this.size = size; this.pointSize = size;
}
/* This constructor is used by deriveFont when attributes is null */ private Font(String name, int style, float sizePts, boolean created, Font2DHandle handle) { this(name, style, sizePts); this.createdFont = created; /* Fonts created from a stream will use the same font2D instance * as the parent. * One exception is that if the derived font is requested to be * in a different style, then also check if its a CompositeFont * and if so build a new CompositeFont from components of that style. * CompositeFonts can only be marked as "created" if they are used * to add fall backs to a physical font. And non-composites are * always from "Font.createFont()" and shouldn't get this treatment.
*/ if (created) { if (handle.font2D instanceof CompositeFont &&
handle.font2D.getStyle() != style) {
FontManager fm = FontManagerFactory.getInstance(); this.font2DHandle = fm.getNewComposite(null, style, handle);
} else { this.font2DHandle = handle;
}
}
}
/* used to implement Font.createFont */ private Font(File fontFile, int fontFormat, boolean isCopy, CreatedFontTracker tracker) throws FontFormatException { this.createdFont = true; /* Font2D instances created by this method track their font file * so that when the Font2D is GC'd it can also remove the file.
*/
FontManager fm = FontManagerFactory.getInstance();
Font2D[] fonts =
fm.createFont2D(fontFile, fontFormat, false, isCopy, tracker); this.font2DHandle = fonts[0].handle; this.name = this.font2DHandle.font2D.getFontName(Locale.getDefault()); this.style = Font.PLAIN; this.size = 1; this.pointSize = 1f;
}
/* This constructor is used when one font is derived from another. * Fonts created from a stream will use the same font2D instance as the * parent. They can be distinguished because the "created" argument * will be "true". Since there is no way to recreate these fonts they * need to have the handle to the underlying font2D passed in. * "created" is also true when a special composite is referenced by the * handle for essentially the same reasons. * But when deriving a font in these cases two particular attributes * need special attention: family/face and style. * The "composites" in these cases need to be recreated with optimal * fonts for the new values of family and style. * For fonts created with createFont() these are treated differently. * JDK can often synthesise a different style (bold from plain * for example). For fonts created with "createFont" this is a reasonable * solution but its also possible (although rare) to derive a font with a * different family attribute. In this case JDK needs * to break the tie with the original Font2D and find a new Font. * The oldName and oldStyle are supplied so they can be compared with * what the Font2D and the values. To speed things along : * oldName == null will be interpreted as the name is unchanged. * oldStyle = -1 will be interpreted as the style is unchanged. * In these cases there is no need to interrogate "values".
*/ private Font(AttributeValues values, String oldName, int oldStyle, boolean created, Font2DHandle handle) {
this.createdFont = created; if (created) { this.font2DHandle = handle;
String newName = null; if (oldName != null) {
newName = values.getFamily(); if (oldName.equals(newName)) newName = null;
} int newStyle = 0; if (oldStyle == -1) {
newStyle = -1;
} else { if (values.getWeight() >= 2f) newStyle = BOLD; if (values.getPosture() >= .2f) newStyle |= ITALIC; if (oldStyle == newStyle) newStyle = -1;
} if (handle.font2D instanceof CompositeFont) { if (newStyle != -1 || newName != null) {
FontManager fm = FontManagerFactory.getInstance(); this.font2DHandle =
fm.getNewComposite(newName, newStyle, handle);
}
} elseif (newName != null) { this.createdFont = false; this.font2DHandle = null;
}
}
initFromValues(values);
}
/** * Creates a new {@code Font} with the specified attributes. * Only keys defined in {@link java.awt.font.TextAttribute TextAttribute} * are recognized. In addition the FONT attribute is * not recognized by this constructor * (see {@link #getAvailableAttributes}). Only attributes that have * values of valid types will affect the new {@code Font}. * <p> * If {@code attributes} is {@code null}, a new * {@code Font} is initialized with default values. * @see java.awt.font.TextAttribute * @param attributes the attributes to assign to the new * {@code Font}, or {@code null}
*/ public Font(Map<? extends Attribute, ?> attributes) {
initFromValues(AttributeValues.fromMap(attributes, RECOGNIZED_MASK));
}
/** * Creates a new {@code Font} from the specified {@code font}. * This constructor is intended for use by subclasses. * @param font from which to create this {@code Font}. * @throws NullPointerException if {@code font} is null * @since 1.6
*/ protected Font(Font font) { if (font.values != null) {
initFromValues(font.getAttributeValues().clone());
} else { this.name = font.name; this.style = font.style; this.size = font.size; this.pointSize = font.pointSize;
} this.font2DHandle = font.font2DHandle; this.createdFont = font.createdFont;
}
/** * Font recognizes all attributes except FONT.
*/ privatestaticfinalint RECOGNIZED_MASK = AttributeValues.MASK_ALL
& ~AttributeValues.getMask(EFONT);
/** * These attributes are considered primary by the FONT attribute.
*/ privatestaticfinalint PRIMARY_MASK =
AttributeValues.getMask(EFAMILY, EWEIGHT, EWIDTH, EPOSTURE, ESIZE,
ETRANSFORM, ESUPERSCRIPT, ETRACKING);
/** * These attributes are considered secondary by the FONT attribute.
*/ privatestaticfinalint SECONDARY_MASK =
RECOGNIZED_MASK & ~PRIMARY_MASK;
/** * These attributes are handled by layout.
*/ privatestaticfinalint LAYOUT_MASK =
AttributeValues.getMask(ECHAR_REPLACEMENT, EFOREGROUND, EBACKGROUND,
EUNDERLINE, ESTRIKETHROUGH, ERUN_DIRECTION,
EBIDI_EMBEDDING, EJUSTIFICATION,
EINPUT_METHOD_HIGHLIGHT, EINPUT_METHOD_UNDERLINE,
ESWAP_COLORS, ENUMERIC_SHAPING, EKERNING,
ELIGATURES, ETRACKING, ESUPERSCRIPT);
/** * Initialize the standard Font fields from the values object.
*/ privatevoid initFromValues(AttributeValues values) { this.values = values;
values.defineAll(PRIMARY_MASK); // for 1.5 streaming compatibility
this.name = values.getFamily(); this.pointSize = values.getSize(); this.size = (int)(values.getSize() + 0.5); if (values.getWeight() >= 2f) this.style |= BOLD; // not == 2f if (values.getPosture() >= .2f) this.style |= ITALIC; // not == .2f
/** * Returns true if any part of the specified text is from a * complex script for which the implementation will need to invoke * layout processing in order to render correctly when using * {@link Graphics#drawString(String,int,int) drawString(String,int,int)} * and other text rendering methods. Measurement of the text * may similarly need the same extra processing. * The {@code start} and {@code end} indices are provided so that * the application can request only a subset of the text be considered. * The last char index examined is at {@code "end-1"}, * i.e a request to examine the entire array would be * <pre> * {@code Font.textRequiresLayout(chars, 0, chars.length);} * </pre> * An application may find this information helpful in * performance sensitive code. * <p> * Note that even if this method returns {@code false}, layout processing * may still be invoked when used with any {@code Font} * for which {@link #hasLayoutAttributes()} returns {@code true}, * so that method will need to be consulted for the specific font, * in order to obtain an answer which accounts for such font attributes. * * @param chars the text. * @param start the index of the first char to examine. * @param end the ending index, exclusive. * @return {@code true} if the specified text will need special layout. * @throws NullPointerException if {@code chars} is null. * @throws ArrayIndexOutOfBoundsException if {@code start} is negative or * {@code end} is greater than the length of the {@code chars} array. * @since 9
*/ publicstaticboolean textRequiresLayout(char[] chars, int start, int end) { if (chars == null) { thrownew NullPointerException("null char array");
} if (start < 0 || end > chars.length) { thrownew ArrayIndexOutOfBoundsException("start < 0 or end > len");
} return FontUtilities.isComplexScript(chars, start, end);
}
/** * Returns a {@code Font} appropriate to the attributes. * If {@code attributes} contains a {@code FONT} attribute * with a valid {@code Font} as its value, it will be * merged with any remaining attributes. See * {@link java.awt.font.TextAttribute#FONT} for more * information. * * @param attributes the attributes to assign to the new * {@code Font} * @return a new {@code Font} created with the specified * attributes * @throws NullPointerException if {@code attributes} is null. * @since 1.2 * @see java.awt.font.TextAttribute
*/ publicstatic Font getFont(Map<? extends Attribute, ?> attributes) { // optimize for two cases: // 1) FONT attribute, and nothing else // 2) attributes, but no FONT
// avoid turning the attributemap into a regular map for no reason if (attributes instanceof AttributeMap &&
((AttributeMap)attributes).getValues() != null) {
AttributeValues values = ((AttributeMap)attributes).getValues(); if (values.isNonDefault(EFONT)) {
Font font = values.getFont(); if (!values.anyDefined(SECONDARY_MASK)) { return font;
} // merge
values = font.getAttributeValues().clone();
values.merge(attributes, SECONDARY_MASK); returnnew Font(values, font.name, font.style,
font.createdFont, font.font2DHandle);
} returnnew Font(attributes);
}
Font font = (Font)attributes.get(TextAttribute.FONT); if (font != null) { if (attributes.size() > 1) { // oh well, check for anything else
AttributeValues values = font.getAttributeValues().clone();
values.merge(attributes, SECONDARY_MASK); returnnew Font(values, font.name, font.style,
font.createdFont, font.font2DHandle);
}
return font;
}
returnnew Font(attributes);
}
/** * Used with the byte count tracker for fonts created from streams. * If a thread can create temp files anyway, no point in counting * font bytes.
*/
@SuppressWarnings("removal") privatestaticboolean hasTempPermission() {
if (System.getSecurityManager() == null) { returntrue;
}
File f = null; boolean hasPerm = false; try {
f = Files.createTempFile("+~JT", ".tmp").toFile();
f.delete();
f = null;
hasPerm = true;
} catch (Throwable t) { /* inc. any kind of SecurityException */
} return hasPerm;
}
/** * Returns a new array of {@code Font} decoded from the specified stream. * The returned {@code Font[]} will have at least one element. * <p> * The explicit purpose of this variation on the * {@code createFont(int, InputStream)} method is to support font * sources which represent a TrueType/OpenType font collection and * be able to return all individual fonts in that collection. * Consequently this method will throw {@code FontFormatException} * if the data source does not contain at least one TrueType/OpenType * font. The same exception will also be thrown if any of the fonts in * the collection does not contain the required font tables. * <p> * The condition "at least one", allows for the stream to represent * a single OpenType/TrueType font. That is, it does not have to be * a collection. * Each {@code Font} element of the returned array is * created with a point size of 1 and style {@link #PLAIN PLAIN}. * This base font can then be used with the {@code deriveFont} * methods in this class to derive new {@code Font} objects with * varying sizes, styles, transforms and font features. * <p>This method does not close the {@link InputStream}. * <p> * To make each {@code Font} available to Font constructors it * must be registered in the {@code GraphicsEnvironment} by calling * {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}. * @param fontStream an {@code InputStream} object representing the * input data for the font or font collection. * @return a new {@code Font[]}. * @throws FontFormatException if the {@code fontStream} data does * not contain the required font tables for any of the elements of * the collection, or if it contains no fonts at all. * @throws IOException if the {@code fontStream} cannot be completely read. * @see GraphicsEnvironment#registerFont(Font) * @since 9
*/ publicstatic Font[] createFonts(InputStream fontStream) throws FontFormatException, IOException {
/** * Returns a new array of {@code Font} decoded from the specified file. * The returned {@code Font[]} will have at least one element. * <p> * The explicit purpose of this variation on the * {@code createFont(int, File)} method is to support font * sources which represent a TrueType/OpenType font collection and * be able to return all individual fonts in that collection. * Consequently this method will throw {@code FontFormatException} * if the data source does not contain at least one TrueType/OpenType * font. The same exception will also be thrown if any of the fonts in * the collection does not contain the required font tables. * <p> * The condition "at least one", allows for the stream to represent * a single OpenType/TrueType font. That is, it does not have to be * a collection. * Each {@code Font} element of the returned array is * created with a point size of 1 and style {@link #PLAIN PLAIN}. * This base font can then be used with the {@code deriveFont} * methods in this class to derive new {@code Font} objects with * varying sizes, styles, transforms and font features. * <p> * To make each {@code Font} available to Font constructors it * must be registered in the {@code GraphicsEnvironment} by calling * {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}. * @param fontFile a {@code File} object containing the * input data for the font or font collection. * @return a new {@code Font[]}. * @throws FontFormatException if the {@code File} does * not contain the required font tables for any of the elements of * the collection, or if it contains no fonts at all. * @throws IOException if the {@code fontFile} cannot be read. * @see GraphicsEnvironment#registerFont(Font) * @since 9
*/ publicstatic Font[] createFonts(File fontFile) throws FontFormatException, IOException
{ int fontFormat = Font.TRUETYPE_FONT;
fontFile = checkFontFile(fontFormat, fontFile);
FontManager fm = FontManagerFactory.getInstance();
Font2D[] font2DArr =
fm.createFont2D(fontFile, fontFormat, true, false, null); int num = font2DArr.length;
Font[] fonts = new Font[num]; for (int i = 0; i < num; i++) {
fonts[i] = new Font(font2DArr[i]);
} return fonts;
}
/** * Returns a new {@code Font} using the specified font type * and input data. The new {@code Font} is * created with a point size of 1 and style {@link #PLAIN PLAIN}. * This base font can then be used with the {@code deriveFont} * methods in this class to derive new {@code Font} objects with * varying sizes, styles, transforms and font features. This * method does not close the {@link InputStream}. * <p> * To make the {@code Font} available to Font constructors the * returned {@code Font} must be registered in the * {@code GraphicsEnvironment} by calling * {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}. * @param fontFormat the type of the {@code Font}, which is * {@link #TRUETYPE_FONT TRUETYPE_FONT} if a TrueType resource is specified. * or {@link #TYPE1_FONT TYPE1_FONT} if a Type 1 resource is specified. * @param fontStream an {@code InputStream} object representing the * input data for the font. * @return a new {@code Font} created with the specified font type. * @throws IllegalArgumentException if {@code fontFormat} is not * {@code TRUETYPE_FONT} or {@code TYPE1_FONT}. * @throws FontFormatException if the {@code fontStream} data does * not contain the required font tables for the specified format. * @throws IOException if the {@code fontStream} * cannot be completely read. * @see GraphicsEnvironment#registerFont(Font) * @since 1.3
*/ publicstatic Font createFont(int fontFormat, InputStream fontStream) throws java.awt.FontFormatException, java.io.IOException {
if (hasTempPermission()) { return createFont0(fontFormat, fontStream, false, null)[0];
}
// Otherwise, be extra conscious of pending temp file creation and // resourcefully handle the temp file resources, among other things.
CreatedFontTracker tracker = CreatedFontTracker.getTracker(); boolean acquired = false; try {
acquired = tracker.acquirePermit(); if (!acquired) { thrownew IOException("Timed out waiting for resources.");
} return createFont0(fontFormat, fontStream, false, tracker)[0];
} catch (InterruptedException e) { thrownew IOException("Problem reading font data.");
} finally { if (acquired) {
tracker.releasePermit();
}
}
}
if (fontFormat != Font.TRUETYPE_FONT &&
fontFormat != Font.TYPE1_FONT) { thrownew IllegalArgumentException ("font format not recognized");
} boolean copiedFontData = false; try { final File tFile = AccessController.doPrivileged( new PrivilegedExceptionAction<File>() { public File run() throws IOException { return Files.createTempFile("+~JF", ".tmp").toFile();
}
}
); if (tracker != null) {
tracker.add(tFile);
}
int totalSize = 0; try { final OutputStream outStream =
AccessController.doPrivileged( new PrivilegedExceptionAction<OutputStream>() { public OutputStream run() throws IOException { returnnew FileOutputStream(tFile);
}
}
); if (tracker != null) {
tracker.set(tFile, outStream);
} try (outStream) { /* don't close the input stream */ byte[] buf = newbyte[8192]; for (;;) { int bytesRead = fontStream.read(buf); if (bytesRead < 0) { break;
} if (tracker != null) { if (totalSize+bytesRead > CreatedFontTracker.MAX_FILE_SIZE) { thrownew IOException("File too big.");
} if (totalSize+tracker.getNumBytes() >
CreatedFontTracker.MAX_TOTAL_BYTES)
{ thrownew IOException("Total files too big.");
}
totalSize += bytesRead;
tracker.addBytes(bytesRead);
}
outStream.write(buf, 0, bytesRead);
}
} /* After all references to a Font2D are dropped, the file * will be removed. To support long-lived AppContexts, * we need to then decrement the byte count by the size * of the file. * If the data isn't a valid font, the implementation will * delete the tmp file and decrement the byte count * in the tracker object before returning from the * constructor, so we can set 'copiedFontData' to true here * without waiting for the results of that constructor.
*/
copiedFontData = true;
FontManager fm = FontManagerFactory.getInstance();
Font2D[] font2DArr =
fm.createFont2D(tFile, fontFormat, allFonts, true, tracker); int num = font2DArr.length;
Font[] fonts = new Font[num]; for (int i = 0; i < num; i++) {
fonts[i] = new Font(font2DArr[i]);
} return fonts;
} finally { if (tracker != null) {
tracker.remove(tFile);
} if (!copiedFontData) { if (tracker != null) {
tracker.subBytes(totalSize);
}
AccessController.doPrivileged( new PrivilegedExceptionAction<Void>() { publicVoid run() {
tFile.delete(); returnnull;
}
}
);
}
}
} catch (Throwable t) { if (t instanceof FontFormatException) { throw (FontFormatException)t;
} if (t instanceof IOException) { throw (IOException)t;
}
Throwable cause = t.getCause(); if (cause instanceof FontFormatException) { throw (FontFormatException)cause;
} thrownew IOException("Problem reading font data.");
}
}
/** * Returns a new {@code Font} using the specified font type * and the specified font file. The new {@code Font} is * created with a point size of 1 and style {@link #PLAIN PLAIN}. * This base font can then be used with the {@code deriveFont} * methods in this class to derive new {@code Font} objects with * varying sizes, styles, transforms and font features. * @param fontFormat the type of the {@code Font}, which is * {@link #TRUETYPE_FONT TRUETYPE_FONT} if a TrueType resource is * specified or {@link #TYPE1_FONT TYPE1_FONT} if a Type 1 resource is * specified. * So long as the returned font, or its derived fonts are referenced * the implementation may continue to access {@code fontFile} * to retrieve font data. Thus the results are undefined if the file * is changed, or becomes inaccessible. * <p> * To make the {@code Font} available to Font constructors the * returned {@code Font} must be registered in the * {@code GraphicsEnvironment} by calling * {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}. * @param fontFile a {@code File} object representing the * input data for the font. * @return a new {@code Font} created with the specified font type. * @throws IllegalArgumentException if {@code fontFormat} is not * {@code TRUETYPE_FONT} or {@code TYPE1_FONT}. * @throws NullPointerException if {@code fontFile} is null. * @throws IOException if the {@code fontFile} cannot be read. * @throws FontFormatException if {@code fontFile} does * not contain the required font tables for the specified format. * @throws SecurityException if the executing code does not have * permission to read from the file. * @see GraphicsEnvironment#registerFont(Font) * @since 1.5
*/ publicstatic Font createFont(int fontFormat, File fontFile) throws java.awt.FontFormatException, java.io.IOException {
if (fontFormat != Font.TRUETYPE_FONT &&
fontFormat != Font.TYPE1_FONT) { thrownew IllegalArgumentException ("font format not recognized");
}
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager(); if (sm != null) {
FilePermission filePermission = new FilePermission(fontFile.getPath(), "read");
sm.checkPermission(filePermission);
} if (!fontFile.canRead()) { thrownew IOException("Can't read " + fontFile);
} return fontFile;
}
/** * Returns a copy of the transform associated with this * {@code Font}. This transform is not necessarily the one * used to construct the font. If the font has algorithmic * superscripting or width adjustment, this will be incorporated * into the returned {@code AffineTransform}. * <p> * Typically, fonts will not be transformed. Clients generally * should call {@link #isTransformed} first, and only call this * method if {@code isTransformed} returns true. * * @return an {@link AffineTransform} object representing the * transform attribute of this {@code Font} object.
*/ public AffineTransform getTransform() { /* The most common case is the identity transform. Most callers * should call isTransformed() first, to decide if they need to * get the transform, but some may not. Here we check to see * if we have a nonidentity transform, and only do the work to * fetch and/or compute it if so, otherwise we return a new * identity transform. * * Note that the transform is _not_ necessarily the same as * the transform passed in as an Attribute in a Map, as the * transform returned will also reflect the effects of WIDTH and * SUPERSCRIPT attributes. Clients who want the actual transform * need to call getRequestedAttributes.
*/ if (nonIdentityTx) {
AttributeValues values = getAttributeValues();
AffineTransform at = values.isNonDefault(ETRANSFORM)
? new AffineTransform(values.getTransform())
: new AffineTransform();
if (values.getSuperscript() != 0) { // can't get ascent and descent here, recursive call to this fn, // so use pointsize // let users combine super- and sub-scripting
int superscript = values.getSuperscript();
double trans = 0; int n = 0; boolean up = superscript > 0; int sign = up ? -1 : 1; int ss = up ? superscript : -superscript;
while ((ss & 7) > n) { int newn = ss & 7;
trans += sign * (ssinfo[newn] - ssinfo[n]);
ss >>= 3;
sign = -sign;
n = newn;
}
trans *= pointSize; double scale = Math.pow(2./3., n);
// note on placement and italics // We preconcatenate the transform because we don't want to translate along // the italic angle, but purely perpendicular to the baseline. While this // looks ok for superscripts, it can lead subscripts to stack on each other // and bring the following text too close. The way we deal with potential // collisions that can occur in the case of italics is by adjusting the // horizontal spacing of the adjacent glyphvectors. Examine the italic // angle of both vectors, if one is non-zero, compute the minimum ascent // and descent, and then the x position at each for each vector along its // italic angle starting from its (offset) baseline. Compute the difference // between the x positions and use the maximum difference to adjust the // position of the right gv.
}
if (values.isNonDefault(EWIDTH)) {
at.scale(values.getWidth(), 1f);
}
/** * Returns the family name of this {@code Font}. * * <p>The family name of a font is font specific. Two fonts such as * Helvetica Italic and Helvetica Bold have the same family name, * <i>Helvetica</i>, whereas their font face names are * <i>Helvetica Bold</i> and <i>Helvetica Italic</i>. The list of * available family names may be obtained by using the * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method. * * <p>Use {@code getName} to get the logical name of the font. * Use {@code getFontName} to get the font face name of the font. * @return a {@code String} that is the family name of this * {@code Font}. * * @see #getName * @see #getFontName * @since 1.1
*/ public String getFamily() { return getFamily_NoClientCode();
} // NOTE: This method is called by privileged threads. // We implement this functionality in a package-private // method to insure that it cannot be overridden by client // subclasses. // DO NOT INVOKE CLIENT CODE ON THIS THREAD! final String getFamily_NoClientCode() { return getFamily(Locale.getDefault());
}
/** * Returns the family name of this {@code Font}, localized for * the specified locale. * * <p>The family name of a font is font specific. Two fonts such as * Helvetica Italic and Helvetica Bold have the same family name, * <i>Helvetica</i>, whereas their font face names are * <i>Helvetica Bold</i> and <i>Helvetica Italic</i>. The list of * available family names may be obtained by using the * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method. * * <p>Use {@code getFontName} to get the font face name of the font. * @param l locale for which to get the family name * @return a {@code String} representing the family name of the * font, localized for the specified locale. * @see #getFontName * @see java.util.Locale * @since 1.2
*/ public String getFamily(Locale l) { if (l == null) { thrownew NullPointerException("null locale doesn't mean default");
} return getFont2D().getFamilyName(l);
}
/** * Returns the postscript name of this {@code Font}. * Use {@code getFamily} to get the family name of the font. * Use {@code getFontName} to get the font face name of the font. * @return a {@code String} representing the postscript name of * this {@code Font}. * @since 1.2
*/ public String getPSName() { return getFont2D().getPostscriptName();
}
/** * Returns the logical name of this {@code Font}. * Use {@code getFamily} to get the family name of the font. * Use {@code getFontName} to get the font face name of the font. * @return a {@code String} representing the logical name of * this {@code Font}. * @see #getFamily * @see #getFontName * @since 1.0
*/ public String getName() { return name;
}
/** * Returns the font face name of this {@code Font}. For example, * Helvetica Bold could be returned as a font face name. * Use {@code getFamily} to get the family name of the font. * Use {@code getName} to get the logical name of the font. * @return a {@code String} representing the font face name of * this {@code Font}. * @see #getFamily * @see #getName * @since 1.2
*/ public String getFontName() { return getFontName(Locale.getDefault());
}
/** * Returns the font face name of the {@code Font}, localized * for the specified locale. For example, Helvetica Fett could be * returned as the font face name. * Use {@code getFamily} to get the family name of the font. * @param l a locale for which to get the font face name * @return a {@code String} representing the font face name, * localized for the specified locale. * @see #getFamily * @see java.util.Locale
*/ public String getFontName(Locale l) { if (l == null) { thrownew NullPointerException("null locale doesn't mean default");
} return getFont2D().getFontName(l);
}
/** * Returns the style of this {@code Font}. The style can be * PLAIN, BOLD, ITALIC, or BOLD+ITALIC. * @return the style of this {@code Font} * @see #isPlain * @see #isBold * @see #isItalic * @since 1.0
*/ publicint getStyle() { return style;
}
/** * Returns the point size of this {@code Font}, rounded to * an integer. * Most users are familiar with the idea of using <i>point size</i> to * specify the size of glyphs in a font. This point size defines a * measurement between the baseline of one line to the baseline of the * following line in a single spaced text document. The point size is * based on <i>typographic points</i>, approximately 1/72 of an inch. * <p> * The Java(tm)2D API adopts the convention that one point is * equivalent to one unit in user coordinates. When using a * normalized transform for converting user space coordinates to * device space coordinates 72 user * space units equal 1 inch in device space. In this case one point * is 1/72 of an inch. * @return the point size of this {@code Font} in 1/72 of an * inch units. * @see #getSize2D * @see GraphicsConfiguration#getDefaultTransform * @see GraphicsConfiguration#getNormalizingTransform * @since 1.0
*/ publicint getSize() { return size;
}
/** * Returns the point size of this {@code Font} in * {@code float} value. * @return the point size of this {@code Font} as a * {@code float} value. * @see #getSize * @since 1.2
*/ publicfloat getSize2D() { return pointSize;
}
/** * Indicates whether or not this {@code Font} object's style is * PLAIN. * @return {@code true} if this {@code Font} has a * PLAIN style; * {@code false} otherwise. * @see java.awt.Font#getStyle * @since 1.0
*/ publicboolean isPlain() { return style == 0;
}
/** * Indicates whether or not this {@code Font} object's style is * BOLD. * @return {@code true} if this {@code Font} object's * style is BOLD; * {@code false} otherwise. * @see java.awt.Font#getStyle * @since 1.0
*/ publicboolean isBold() { return (style & BOLD) != 0;
}
/** * Indicates whether or not this {@code Font} object's style is * ITALIC. * @return {@code true} if this {@code Font} object's * style is ITALIC; * {@code false} otherwise. * @see java.awt.Font#getStyle * @since 1.0
*/ publicboolean isItalic() { return (style & ITALIC) != 0;
}
/** * Indicates whether or not this {@code Font} object has a * transform that affects its size in addition to the Size * attribute. * @return {@code true} if this {@code Font} object * has a non-identity AffineTransform attribute. * {@code false} otherwise. * @see java.awt.Font#getTransform * @since 1.4
*/ publicboolean isTransformed() { return nonIdentityTx;
}
/** * Return true if this Font contains attributes that require extra * layout processing. * @return true if the font has layout attributes * @since 1.6
*/ publicboolean hasLayoutAttributes() { return hasLayoutAttributes;
}
/** * Returns a {@code Font} object from the system properties list. * {@code nm} is treated as the name of a system property to be * obtained. The {@code String} value of this property is then * interpreted as a {@code Font} object according to the * specification of {@code Font.decode(String)} * If the specified property is not found, or the executing code does
--> --------------------
--> maximum size reached
--> --------------------
¤ Dauer der Verarbeitung: 0.36 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.