Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/ikvm-fork.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'openjdk/java/awt/Font.java')
-rw-r--r--openjdk/java/awt/Font.java2640
1 files changed, 0 insertions, 2640 deletions
diff --git a/openjdk/java/awt/Font.java b/openjdk/java/awt/Font.java
deleted file mode 100644
index d99c6757..00000000
--- a/openjdk/java/awt/Font.java
+++ /dev/null
@@ -1,2640 +0,0 @@
-/*
- * Copyright (c) 1995, 2013, 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 java.awt;
-
-import java.awt.font.FontRenderContext;
-import java.awt.font.GlyphVector;
-import java.awt.font.LineMetrics;
-import java.awt.font.TextAttribute;
-import java.awt.font.TextLayout;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.peer.FontPeer;
-import java.io.*;
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.SoftReference;
-import java.lang.ref.WeakReference;
-import java.nio.file.Files;
-import java.nio.file.StandardCopyOption;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.text.AttributedCharacterIterator.Attribute;
-import java.text.CharacterIterator;
-import java.text.StringCharacterIterator;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-import sun.font.StandardGlyphVector;
-
-import cli.System.IntPtr;
-import cli.System.Drawing.FontFamily;
-import cli.System.Drawing.GraphicsUnit;
-import cli.System.Drawing.Text.PrivateFontCollection;
-import cli.System.Runtime.InteropServices.DllImportAttribute;
-
-import sun.font.AttributeMap;
-import sun.font.AttributeValues;
-import sun.font.CompositeFont;
-import sun.font.CreatedFontTracker;
-import sun.font.Font2D;
-import sun.font.Font2DHandle;
-import sun.font.FontAccess;
-import sun.font.FontManager;
-import sun.font.FontManagerFactory;
-import sun.font.FontUtilities;
-import sun.font.GlyphLayout;
-import sun.font.FontLineMetrics;
-import sun.font.CoreMetrics;
-import sun.font.SunFontManager;
-
-import static sun.font.EAttribute.*;
-
-/**
- * The <code>Font</code> 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</code> and
- * <code>Component</code> objects.
- *
- * <h3>Characters and Glyphs</h3>
- *
- * 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'</code>,
- * 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 '&aacute;'
- * LATIN SMALL LETTER A WITH ACUTE, can be represented by
- * two glyphs: one for 'a' and one for '&acute;'. 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.
- *
- * <h3>Physical and Logical Fonts</h3>
- *
- * 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="http://www.oracle.com/technetwork/java/javase/tech/faq-jsp-138165.html">Internationalization FAQ</a>
- * document.
- *
- * <h3>Font Faces and Names</h3>
- *
- * A <code>Font</code>
- * 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</code> 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</code> 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</code> objects
- * associated with a font face, each differing in size, style, transform
- * and font features.
- * <p>
- * The {@link GraphicsEnvironment#getAllFonts() getAllFonts} method
- * of the <code>GraphicsEnvironment</code> class returns an
- * array of all font faces available in the system. These font faces are
- * returned as <code>Font</code> objects with a size of 1, identity
- * transform and default font features. These
- * base fonts can then be used to derive new <code>Font</code> objects
- * with varying sizes, styles, transforms and font features via the
- * <code>deriveFont</code> methods in this class.
- *
- * <h3>Font and TextAttribute</h3>
- *
- * <p><code>Font</code> supports most
- * <code>TextAttribute</code>s. This makes some operations, such as
- * rendering underlined text, convenient since it is not
- * necessary to explicitly construct a <code>TextLayout</code> object.
- * Attributes can be set on a Font by constructing or deriving it
- * using a <code>Map</code> of <code>TextAttribute</code> values.
- *
- * <p>The values of some <code>TextAttributes</code> are not
- * serializable, and therefore attempting to serialize an instance of
- * <code>Font</code> 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</code> and <code>BACKGROUND</code> use
- * <code>Paint</code> values. The subclass <code>Color</code> is
- * serializable, while <code>GradientPaint</code> and
- * <code>TexturePaint</code> are not.</li>
- * <li><code>CHAR_REPLACEMENT</code> uses
- * <code>GraphicAttribute</code> values. The subclasses
- * <code>ShapeGraphicAttribute</code> and
- * <code>ImageGraphicAttribute</code> are not serializable.</li>
- * <li><code>INPUT_METHOD_HIGHLIGHT</code> uses
- * <code>InputMethodHighlight</code> values, which are
- * not serializable. See {@link java.awt.im.InputMethodHighlight}.</li>
- * </ul>
- *
- * <p>Clients who create custom subclasses of <code>Paint</code> and
- * <code>GraphicAttribute</code> 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</code>-based constructor and
- * <code>deriveFont</code> 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</code> 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.'
- */
-public class Font implements java.io.Serializable
-{
- private static class FontAccessImpl extends FontAccess {
- public Font2D getFont2D(Font font) {
- return font.getFont2D();
- }
-
- public void setFont2D(Font font, Font2DHandle handle) {
- font.font2DHandle = handle;
- }
-
- public void setCreatedFont(Font font) {
- font.createdFont = true;
- }
-
- public boolean isCreatedFont(Font font) {
- return font.createdFont;
- }
- }
-
- static {
- 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
- */
- public static final 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
- */
- public static final 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
- */
- public static final 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
- */
- public static final 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
- */
- public static final String MONOSPACED = "Monospaced";
-
- /*
- * Constants to be used for styles. Can be combined to mix
- * styles.
- */
-
- /**
- * The plain style constant.
- */
- public static final int PLAIN = 0;
-
- /**
- * The bold style constant. This can be combined with the other style
- * constants (except PLAIN) for mixed styles.
- */
- public static final int BOLD = 1;
-
- /**
- * The italicized style constant. This can be combined with the other
- * style constants (except PLAIN) for mixed styles.
- */
- public static final int ITALIC = 2;
-
- /**
- * The baseline used in most Roman scripts when laying out text.
- */
- public static final int ROMAN_BASELINE = 0;
-
- /**
- * The baseline used in ideographic scripts like Chinese, Japanese,
- * and Korean when laying out text.
- */
- public static final int CENTER_BASELINE = 1;
-
- /**
- * The baseline used in Devanigiri and similar scripts when laying
- * out text.
- */
- public static final int 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
- */
-
- public static final int 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
- */
- public static final int TYPE1_FONT = 1;
-
- /**
- * The logical name of this <code>Font</code>, as passed to the
- * constructor.
- * @since JDK1.0
- *
- * @serial
- * @see #getName
- */
- protected String name;
-
- /**
- * The style of this <code>Font</code>, as passed to the constructor.
- * This style can be PLAIN, BOLD, ITALIC, or BOLD+ITALIC.
- * @since JDK1.0
- *
- * @serial
- * @see #getStyle()
- */
- protected int style;
-
- /**
- * The point size of this <code>Font</code>, rounded to integer.
- * @since JDK1.0
- *
- * @serial
- * @see #getSize()
- */
- protected int size;
-
- /**
- * The point size of this <code>Font</code> in <code>float</code>.
- *
- * @serial
- * @see #getSize()
- * @see #getSize2D()
- */
- protected float pointSize;
-
- /**
- * The platform specific font information.
- */
- private transient FontPeer peer;
- private transient cli.System.Drawing.Font netFont;
- private transient Font2DHandle font2DHandle;
-
- private transient AttributeValues values;
- private transient boolean hasLayoutAttributes;
-
- /*
- * If the origin of a Font is a created font then this attribute
- * must be set on all derived fonts too.
- */
- private transient boolean createdFont = false;
-
- /*
- * This is true if the font transform is not identity. It
- * is used to avoid unnecessary instantiation of an AffineTransform.
- */
- private transient boolean nonIdentityTx;
-
- /*
- * A cached value used when a transform is required for internal
- * use. This must not be exposed to callers since AffineTransform
- * is mutable.
- */
- private static final AffineTransform identityTx = new AffineTransform();
-
- /*
- * JDK 1.1 serialVersionUID
- */
- private static final long serialVersionUID = -4206021311591459213L;
-
- /**
- * Gets the peer of this <code>Font</code>.
- * @return the peer of the <code>Font</code>.
- * @since JDK1.1
- * @deprecated Font rendering is now platform independent.
- */
- @Deprecated
- public FontPeer getPeer(){
- return getPeer_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!
- @SuppressWarnings("deprecation")
- final FontPeer getPeer_NoClientCode() {
- if(peer == null) {
- Toolkit tk = Toolkit.getDefaultToolkit();
- this.peer = 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 & BOLD) != 0) {
- valuesTmp.setWeight(2); // WEIGHT_BOLD
- }
-
- 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 (fm.usingPerAppContextComposites() &&
- font2DHandle != null &&
- font2DHandle.font2D instanceof CompositeFont &&
- ((CompositeFont)(font2DHandle.font2D)).isStdComposite()) {
- return fm.findFont2D(name, style,
- FontManager.LOGICAL_FALLBACK);
- } else 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;
- }
-
- @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation
- public cli.System.Drawing.Font getNetFont(){
- if(netFont == null){
- netFont = getFont2D().createNetFont(this);
- }
- return netFont;
- }
- /**
- * Creates a new <code>Font</code> 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</code>, 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</code> 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</code> 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".
- * <p>
- *
- * @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 JDK1.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;
- }
-
- private Font(String name, int style, float sizePts) {
- this.name = (name != null) ? name : "Default";
- this.style = (style & ~0x03) == 0 ? style : 0;
- this.size = (int)(sizePts + 0.5);
- this.pointSize = sizePts;
- }
-
- /* 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;
- }
- }
- }
-
- /* 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);
- }
- } else if (newName != null) {
- this.createdFont = false;
- this.font2DHandle = null;
- }
- }
- initFromValues(values);
- }
-
- /**
- * Creates a new <code>Font</code> 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</code>.
- * <p>
- * If <code>attributes</code> is <code>null</code>, a new
- * <code>Font</code> is initialized with default values.
- * @see java.awt.font.TextAttribute
- * @param attributes the attributes to assign to the new
- * <code>Font</code>, or <code>null</code>
- */
- public Font(Map<? extends Attribute, ?> attributes) {
- initFromValues(AttributeValues.fromMap(attributes, RECOGNIZED_MASK));
- }
-
- /**
- * Creates a new <code>Font</code> from the specified <code>font</code>.
- * This constructor is intended for use by subclasses.
- * @param font from which to create this <code>Font</code>.
- * @throws NullPointerException if <code>font</code> 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.
- */
- private static final int RECOGNIZED_MASK = AttributeValues.MASK_ALL
- & ~AttributeValues.getMask(EFONT);
-
- /**
- * These attributes are considered primary by the FONT attribute.
- */
- private static final int PRIMARY_MASK =
- AttributeValues.getMask(EFAMILY, EWEIGHT, EWIDTH, EPOSTURE, ESIZE,
- ETRANSFORM, ESUPERSCRIPT, ETRACKING);
-
- /**
- * These attributes are considered secondary by the FONT attribute.
- */
- private static final int SECONDARY_MASK =
- RECOGNIZED_MASK & ~PRIMARY_MASK;
-
- /**
- * These attributes are handled by layout.
- */
- private static final int 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);
-
- private static final int EXTRA_MASK =
- AttributeValues.getMask(ETRANSFORM, ESUPERSCRIPT, EWIDTH);
-
- /**
- * Initialize the standard Font fields from the values object.
- */
- private void 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
-
- this.nonIdentityTx = values.anyNonDefault(EXTRA_MASK);
- this.hasLayoutAttributes = values.anyNonDefault(LAYOUT_MASK);
- }
-
- /**
- * Returns a <code>Font</code> appropriate to the attributes.
- * If <code>attributes</code>contains a <code>FONT</code> attribute
- * with a valid <code>Font</code> 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</code>
- * @return a new <code>Font</code> created with the specified
- * attributes
- * @throws NullPointerException if <code>attributes</code> is null.
- * @since 1.2
- * @see java.awt.font.TextAttribute
- */
- public static 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);
- return new Font(values, font.name, font.style,
- font.createdFont, font.font2DHandle);
- }
- return new 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);
- return new Font(values, font.name, font.style,
- font.createdFont, font.font2DHandle);
- }
-
- return font;
- }
-
- return new Font(attributes);
- }
-
- private static class FontFamilyReference extends WeakReference<FontFamily> {
-
- private static final ReferenceQueue<FontFamily> fontFamilyQueue = new ReferenceQueue<>();
- private static final Set<FontFamilyReference> refs = Collections.synchronizedSet( new HashSet<FontFamilyReference>() );
- static {
- sun.misc.SharedSecrets.getJavaLangAccess().registerShutdownHook( 5, // Shutdown hook invocation order
- true, // register even if shutdown in progress
- new Runnable() {
- public void run() {
- for( FontFamilyReference ref : refs ) {
- ref.delete( false );
- }
- }
- } );
- }
- private File fontFile;
-
- private FontFamilyReference( FontFamily family, File fontFile ) {
- super( family, fontFamilyQueue );
- this.fontFile = fontFile;
- refs.add( this );
-
- do {
- FontFamilyReference ref = (FontFamilyReference)fontFamilyQueue.poll();
- if( ref == null ) {
- break;
- }
- ref.delete( true );
- } while(true);
- }
-
- private void delete( boolean isQueue ) {
- FontFamily family = get();
- if( family != null ) {
- family.Dispose();
- }
-
- if( fontFile.delete() && isQueue) {
- refs.remove( this );
- }
- }
- }
-
- /**
- * Returns a new <code>Font</code> using the specified font type
- * and input data. The new <code>Font</code> is
- * created with a point size of 1 and style {@link #PLAIN PLAIN}.
- * This base font can then be used with the <code>deriveFont</code>
- * methods in this class to derive new <code>Font</code> objects with
- * varying sizes, styles, transforms and font features. This
- * method does not close the {@link InputStream}.
- * <p>
- * To make the <code>Font</code> available to Font constructors the
- * returned <code>Font</code> must be registered in the
- * <code>GraphicsEnviroment</code> by calling
- * {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}.
- * @param fontFormat the type of the <code>Font</code>, 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</code> object representing the
- * input data for the font.
- * @return a new <code>Font</code> created with the specified font type.
- * @throws IllegalArgumentException if <code>fontFormat</code> is not
- * <code>TRUETYPE_FONT</code>or<code>TYPE1_FONT</code>.
- * @throws FontFormatException if the <code>fontStream</code> data does
- * not contain the required font tables for the specified format.
- * @throws IOException if the <code>fontStream</code>
- * cannot be completely read.
- * @see GraphicsEnvironment#registerFont(Font)
- * @since 1.3
- */
- public static Font createFont(int fontFormat, InputStream fontStream)
- throws java.awt.FontFormatException, java.io.IOException {
-
- if (fontFormat != Font.TRUETYPE_FONT &&
- fontFormat != Font.TYPE1_FONT) {
- throw new IllegalArgumentException ("font format not recognized");
- }
-
- File fontFile;
- try {
- fontFile = AccessController.doPrivileged(
- new PrivilegedExceptionAction<File>() {
- public File run() throws IOException {
- return Files.createTempFile("+~JF", ".tmp").toFile();
- }
- }
- );
- } catch( PrivilegedActionException ex ) {
- throw (IOException)ex.getException();
- }
- Files.copy( fontStream, fontFile.toPath(), StandardCopyOption.REPLACE_EXISTING );
-
- // create a private Font Collection and add the font data
- PrivateFontCollection pfc = new PrivateFontCollection();
- try {
- String fileName = fontFile.getPath();
- pfc.AddFontFile( fileName );
- RemoveFontResourceEx( fileName ); // hack for bug http://stackoverflow.com/questions/26671026/how-to-delete-the-file-of-a-privatefontcollection-addfontfile
- if (false) throw new cli.System.IO.FileNotFoundException();
- } catch( cli.System.IO.FileNotFoundException x ) {
- FontFormatException ffe = new FontFormatException(x.getMessage());
- ffe.initCause(x);
- fontFile.delete();
- throw ffe;
- }
-
- FontFamily family = pfc.get_Families()[0];
- new FontFamilyReference( family, fontFile );
-
- // create the font object
- Font2D font2D = SunFontManager.createFont2D( family, 0 );
- Font2DHandle font2DHandle = font2D.handle;
- Font font = new Font( font2D.getFontName( Locale.getDefault() ), PLAIN, 1, true, font2DHandle );
- return font;
- }
-
- @DllImportAttribute.Annotation(value="gdi32")
- private static native int RemoveFontResourceEx(String filename, int fl, IntPtr pdv);
-
- @cli.System.Security.SecuritySafeCriticalAttribute.Annotation
- private static void RemoveFontResourceEx(String filename) {
- if( ikvm.internal.Util.WINDOWS ) {
- RemoveFontResourceEx( filename, 16, IntPtr.Zero );
- }
- }
-
- /**
- * Returns a new <code>Font</code> using the specified font type
- * and the specified font file. The new <code>Font</code> is
- * created with a point size of 1 and style {@link #PLAIN PLAIN}.
- * This base font can then be used with the <code>deriveFont</code>
- * methods in this class to derive new <code>Font</code> objects with
- * varying sizes, styles, transforms and font features.
- * @param fontFormat the type of the <code>Font</code>, 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</code>
- * to retrieve font data. Thus the results are undefined if the file
- * is changed, or becomes inaccessible.
- * <p>
- * To make the <code>Font</code> available to Font constructors the
- * returned <code>Font</code> must be registered in the
- * <code>GraphicsEnviroment</code> by calling
- * {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}.
- * @param fontFile a <code>File</code> object representing the
- * input data for the font.
- * @return a new <code>Font</code> created with the specified font type.
- * @throws IllegalArgumentException if <code>fontFormat</code> is not
- * <code>TRUETYPE_FONT</code>or<code>TYPE1_FONT</code>.
- * @throws NullPointerException if <code>fontFile</code> is null.
- * @throws IOException if the <code>fontFile</code> cannot be read.
- * @throws FontFormatException if <code>fontFile</code> 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
- */
- public static Font createFont(int fontFormat, File fontFile)
- throws java.awt.FontFormatException, java.io.IOException {
-
- fontFile = new File(fontFile.getPath());
-
- if (fontFormat != Font.TRUETYPE_FONT &&
- fontFormat != Font.TYPE1_FONT) {
- throw new IllegalArgumentException ("font format not recognized");
- }
- SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- FilePermission filePermission =
- new FilePermission(fontFile.getPath(), "read");
- sm.checkPermission(filePermission);
- }
- if (!fontFile.canRead()) {
- throw new IOException("Can't read " + fontFile);
- }
- // create a private Font Collection and add the font data
- PrivateFontCollection pfc = new PrivateFontCollection();
- try {
- String fileName = fontFile.getPath();
- pfc.AddFontFile( fileName );
- RemoveFontResourceEx( fileName );// hack for bug http://stackoverflow.com/questions/26671026/how-to-delete-the-file-of-a-privatefontcollection-addfontfile
- if (false) throw new cli.System.IO.FileNotFoundException();
- } catch( cli.System.IO.FileNotFoundException fnfe ) {
- FileNotFoundException ex = new FileNotFoundException(fnfe.getMessage());
- ex.initCause( fnfe );
- throw ex;
- }
- // create the font object
- Font2D font2D = SunFontManager.createFont2D( pfc.get_Families()[0], 0 );
- Font2DHandle font2DHandle = font2D.handle;
- Font font = new Font( font2D.getFontName( Locale.getDefault() ), PLAIN, 1, true, font2DHandle );
- return font;
- }
-
- /**
- * Returns a copy of the transform associated with this
- * <code>Font</code>. 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</code>.
- * <p>
- * Typically, fonts will not be transformed. Clients generally
- * should call {@link #isTransformed} first, and only call this
- * method if <code>isTransformed</code> returns true.
- *
- * @return an {@link AffineTransform} object representing the
- * transform attribute of this <code>Font</code> 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);
-
- at.preConcatenate(AffineTransform.getTranslateInstance(0, trans));
- at.scale(scale, scale);
-
- // 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);
- }
-
- return at;
- }
-
- return new AffineTransform();
- }
-
- // x = r^0 + r^1 + r^2... r^n
- // rx = r^1 + r^2 + r^3... r^(n+1)
- // x - rx = r^0 - r^(n+1)
- // x (1 - r) = r^0 - r^(n+1)
- // x = (r^0 - r^(n+1)) / (1 - r)
- // x = (1 - r^(n+1)) / (1 - r)
-
- // scale ratio is 2/3
- // trans = 1/2 of ascent * x
- // assume ascent is 3/4 of point size
-
- private static final float[] ssinfo = {
- 0.0f,
- 0.375f,
- 0.625f,
- 0.7916667f,
- 0.9027778f,
- 0.9768519f,
- 1.0262346f,
- 1.0591564f,
- };
-
- /**
- * Returns the family name of this <code>Font</code>.
- *
- * <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</code> to get the logical name of the font.
- * Use <code>getFontName</code> to get the font face name of the font.
- * @return a <code>String</code> that is the family name of this
- * <code>Font</code>.
- *
- * @see #getName
- * @see #getFontName
- * @since JDK1.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</code>, 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</code> to get the font face name of the font.
- * @param l locale for which to get the family name
- * @return a <code>String</code> 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) {
- throw new NullPointerException("null locale doesn't mean default");
- }
- return getFont2D().getFamilyName(l);
- }
-
- /**
- * Returns the postscript name of this <code>Font</code>.
- * Use <code>getFamily</code> to get the family name of the font.
- * Use <code>getFontName</code> to get the font face name of the font.
- * @return a <code>String</code> representing the postscript name of
- * this <code>Font</code>.
- * @since 1.2
- */
- public String getPSName() {
- return getFont2D().getPostscriptName();
- }
-
- /**
- * Returns the logical name of this <code>Font</code>.
- * Use <code>getFamily</code> to get the family name of the font.
- * Use <code>getFontName</code> to get the font face name of the font.
- * @return a <code>String</code> representing the logical name of
- * this <code>Font</code>.
- * @see #getFamily
- * @see #getFontName
- * @since JDK1.0
- */
- public String getName() {
- return name;
- }
-
- /**
- * Returns the font face name of this <code>Font</code>. For example,
- * Helvetica Bold could be returned as a font face name.
- * Use <code>getFamily</code> to get the family name of the font.
- * Use <code>getName</code> to get the logical name of the font.
- * @return a <code>String</code> representing the font face name of
- * this <code>Font</code>.
- * @see #getFamily
- * @see #getName
- * @since 1.2
- */
- public String getFontName() {
- return getFontName(Locale.getDefault());
- }
-
- /**
- * Returns the font face name of the <code>Font</code>, localized
- * for the specified locale. For example, Helvetica Fett could be
- * returned as the font face name.
- * Use <code>getFamily</code> to get the family name of the font.
- * @param l a locale for which to get the font face name
- * @return a <code>String</code> representing the font face name,
- * localized for the specified locale.
- * @see #getFamily
- * @see java.util.Locale
- */
- public String getFontName(Locale l) {
- if (l == null) {
- throw new NullPointerException("null locale doesn't mean default");
- }
- return getFont2D().getFontName(l);
- }
-
- /**
- * Returns the style of this <code>Font</code>. The style can be
- * PLAIN, BOLD, ITALIC, or BOLD+ITALIC.
- * @return the style of this <code>Font</code>
- * @see #isPlain
- * @see #isBold
- * @see #isItalic
- * @since JDK1.0
- */
- public int getStyle() {
- return style;
- }
-
- /**
- * Returns the point size of this <code>Font</code>, 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</code> in 1/72 of an
- * inch units.
- * @see #getSize2D
- * @see GraphicsConfiguration#getDefaultTransform
- * @see GraphicsConfiguration#getNormalizingTransform
- * @since JDK1.0
- */
- public int getSize() {
- return size;
- }
-
- /**
- * Returns the point size of this <code>Font</code> in
- * <code>float</code> value.
- * @return the point size of this <code>Font</code> as a
- * <code>float</code> value.
- * @see #getSize
- * @since 1.2
- */
- public float getSize2D() {
- return pointSize;
- }
-
- /**
- * Indicates whether or not this <code>Font</code> object's style is
- * PLAIN.
- * @return <code>true</code> if this <code>Font</code> has a
- * PLAIN style;
- * <code>false</code> otherwise.
- * @see java.awt.Font#getStyle
- * @since JDK1.0
- */
- public boolean isPlain() {
- return style == 0;
- }
-
- /**
- * Indicates whether or not this <code>Font</code> object's style is
- * BOLD.
- * @return <code>true</code> if this <code>Font</code> object's
- * style is BOLD;
- * <code>false</code> otherwise.
- * @see java.awt.Font#getStyle
- * @since JDK1.0
- */
- public boolean isBold() {
- return (style & BOLD) != 0;
- }
-
- /**
- * Indicates whether or not this <code>Font</code> object's style is
- * ITALIC.
- * @return <code>true</code> if this <code>Font</code> object's
- * style is ITALIC;
- * <code>false</code> otherwise.
- * @see java.awt.Font#getStyle
- * @since JDK1.0
- */
- public boolean isItalic() {
- return (style & ITALIC) != 0;
- }
-
- /**
- * Indicates whether or not this <code>Font</code> object has a
- * transform that affects its size in addition to the Size
- * attribute.
- * @return <code>true</code> if this <code>Font</code> object
- * has a non-identity AffineTransform attribute.
- * <code>false</code> otherwise.
- * @see java.awt.Font#getTransform
- * @since 1.4
- */
- public boolean 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
- */
- public boolean hasLayoutAttributes() {
- return hasLayoutAttributes;
- }
-
- /**
- * Returns a <code>Font</code> object from the system properties list.
- * <code>nm</code> is treated as the name of a system property to be
- * obtained. The <code>String</code> value of this property is then
- * interpreted as a <code>Font</code> object according to the
- * specification of <code>Font.decode(String)</code>
- * If the specified property is not found, or the executing code does
- * not have permission to read the property, null is returned instead.
- *
- * @param nm the property name
- * @return a <code>Font</code> object that the property name
- * describes, or null if no such property exists.
- * @throws NullPointerException if nm is null.
- * @since 1.2
- * @see #decode(String)
- */
- public static Font getFont(String nm) {
- return getFont(nm, null);
- }
-
- /**
- * Returns the <code>Font</code> that the <code>str</code>
- * argument describes.
- * To ensure that this method returns the desired Font,
- * format the <code>str</code> parameter in
- * one of these ways
- *
- * <ul>
- * <li><em>fontname-style-pointsize</em>
- * <li><em>fontname-pointsize</em>
- * <li><em>fontname-style</em>
- * <li><em>fontname</em>
- * <li><em>fontname style pointsize</em>
- * <li><em>fontname pointsize</em>
- * <li><em>fontname style</em>
- * <li><em>fontname</em>
- * </ul>
- * in which <i>style</i> is one of the four
- * case-insensitive strings:
- * <code>"PLAIN"</code>, <code>"BOLD"</code>, <code>"BOLDITALIC"</code>, or
- * <code>"ITALIC"</code>, and pointsize is a positive decimal integer
- * representation of the point size.
- * For example, if you want a font that is Arial, bold, with
- * a point size of 18, you would call this method with:
- * "Arial-BOLD-18".
- * This is equivalent to calling the Font constructor :
- * <code>new Font("Arial", Font.BOLD, 18);</code>
- * and the values are interpreted as specified by that constructor.
- * <p>
- * A valid trailing decimal field is always interpreted as the pointsize.
- * Therefore a fontname containing a trailing decimal value should not
- * be used in the fontname only form.
- * <p>
- * If a style name field is not one of the valid style strings, it is
- * interpreted as part of the font name, and the default style is used.
- * <p>
- * Only one of ' ' or '-' may be used to separate fields in the input.
- * The identified separator is the one closest to the end of the string
- * which separates a valid pointsize, or a valid style name from
- * the rest of the string.
- * Null (empty) pointsize and style fields are treated
- * as valid fields with the default value for that field.
- *<p>
- * Some font names may include the separator characters ' ' or '-'.
- * If <code>str</code> is not formed with 3 components, e.g. such that
- * <code>style</code> or <code>pointsize</code> fields are not present in
- * <code>str</code>, and <code>fontname</code> also contains a
- * character determined to be the separator character
- * then these characters where they appear as intended to be part of
- * <code>fontname</code> may instead be interpreted as separators
- * so the font name may not be properly recognised.
- *
- * <p>
- * The default size is 12 and the default style is PLAIN.
- * If <code>str</code> does not specify a valid size, the returned
- * <code>Font</code> has a size of 12. If <code>str</code> does not
- * specify a valid style, the returned Font has a style of PLAIN.
- * If you do not specify a valid font name in
- * the <code>str</code> argument, this method will return
- * a font with the family name "Dialog".
- * To determine what font family names are available on
- * your system, use the
- * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
- * If <code>str</code> is <code>null</code>, a new <code>Font</code>
- * is returned with the family name "Dialog", a size of 12 and a
- * PLAIN style.
- * @param str the name of the font, or <code>null</code>
- * @return the <code>Font</code> object that <code>str</code>
- * describes, or a new default <code>Font</code> if
- * <code>str</code> is <code>null</code>.
- * @see #getFamily
- * @since JDK1.1
- */
- public static Font decode(String str) {
- String fontName = str;
- String styleName = "";
- int fontSize = 12;
- int fontStyle = Font.PLAIN;
-
- if (str == null) {
- return new Font(DIALOG, fontStyle, fontSize);
- }
-
- int lastHyphen = str.lastIndexOf('-');
- int lastSpace = str.lastIndexOf(' ');
- char sepChar = (lastHyphen > lastSpace) ? '-' : ' ';
- int sizeIndex = str.lastIndexOf(sepChar);
- int styleIndex = str.lastIndexOf(sepChar, sizeIndex-1);
- int strlen = str.length();
-
- if (sizeIndex > 0 && sizeIndex+1 < strlen) {
- try {
- fontSize =
- Integer.valueOf(str.substring(sizeIndex+1)).intValue();
- if (fontSize <= 0) {
- fontSize = 12;
- }
- } catch (NumberFormatException e) {
- /* It wasn't a valid size, if we didn't also find the
- * start of the style string perhaps this is the style */
- styleIndex = sizeIndex;
- sizeIndex = strlen;
- if (str.charAt(sizeIndex-1) == sepChar) {
- sizeIndex--;
- }
- }
- }
-
- if (styleIndex >= 0 && styleIndex+1 < strlen) {
- styleName = str.substring(styleIndex+1, sizeIndex);
- styleName = styleName.toLowerCase(Locale.ENGLISH);
- if (styleName.equals("bolditalic")) {
- fontStyle = Font.BOLD | Font.ITALIC;
- } else if (styleName.equals("italic")) {
- fontStyle = Font.ITALIC;
- } else if (styleName.equals("bold")) {
- fontStyle = Font.BOLD;
- } else if (styleName.equals("plain")) {
- fontStyle = Font.PLAIN;
- } else {
- /* this string isn't any of the expected styles, so
- * assume its part of the font name
- */
- styleIndex = sizeIndex;
- if (str.charAt(styleIndex-1) == sepChar) {
- styleIndex--;
- }
- }
- fontName = str.substring(0, styleIndex);
-
- } else {
- int fontEnd = strlen;
- if (styleIndex > 0) {
- fontEnd = styleIndex;
- } else if (sizeIndex > 0) {
- fontEnd = sizeIndex;
- }
- if (fontEnd > 0 && str.charAt(fontEnd-1) == sepChar) {
- fontEnd--;
- }
- fontName = str.substring(0, fontEnd);
- }
-
- return new Font(fontName, fontStyle, fontSize);
- }
-
- /**
- * Gets the specified <code>Font</code> from the system properties
- * list. As in the <code>getProperty</code> method of
- * <code>System</code>, the first
- * argument is treated as the name of a system property to be
- * obtained. The <code>String</code> value of this property is then
- * interpreted as a <code>Font</code> object.
- * <p>
- * The property value should be one of the forms accepted by
- * <code>Font.decode(String)</code>
- * If the specified property is not found, or the executing code does not
- * have permission to read the property, the <code>font</code>
- * argument is returned instead.
- * @param nm the case-insensitive property name
- * @param font a default <code>Font</code> to return if property
- * <code>nm</code> is not defined
- * @return the <code>Font</code> value of the property.
- * @throws NullPointerException if nm is null.
- * @see #decode(String)
- */
- public static Font getFont(String nm, Font font) {
- String str = null;
- try {
- str =System.getProperty(nm);
- } catch(SecurityException e) {
- }
- if (str == null) {
- return font;
- }
- return decode ( str );
- }
-
- transient int hash;
- /**
- * Returns a hashcode for this <code>Font</code>.
- * @return a hashcode value for this <code>Font</code>.
- * @since JDK1.0
- */
- public int hashCode() {
- if (hash == 0) {
- hash = name.hashCode() ^ style ^ size;
- /* It is possible many fonts differ only in transform.
- * So include the transform in the hash calculation.
- * nonIdentityTx is set whenever there is a transform in
- * 'values'. The tests for null are required because it can
- * also be set for other reasons.
- */
- if (nonIdentityTx &&
- values != null && values.getTransform() != null) {
- hash ^= values.getTransform().hashCode();
- }
- }
- return hash;
- }
-
- /**
- * Compares this <code>Font</code> object to the specified
- * <code>Object</code>.
- * @param obj the <code>Object</code> to compare
- * @return <code>true</code> if the objects are the same
- * or if the argument is a <code>Font</code> object
- * describing the same font as this object;
- * <code>false</code> otherwise.
- * @since JDK1.0
- */
- public boolean equals(Object obj) {
- if (obj == this) {
- return true;
- }
-
- if (obj != null) {
- try {
- Font font = (Font)obj;
- if (size == font.size &&
- style == font.style &&
- nonIdentityTx == font.nonIdentityTx &&
- hasLayoutAttributes == font.hasLayoutAttributes &&
- pointSize == font.pointSize &&
- name.equals(font.name)) {
-
- /* 'values' is usually initialized lazily, except when
- * the font is constructed from a Map, or derived using
- * a Map or other values. So if only one font has
- * the field initialized we need to initialize it in
- * the other instance and compare.
- */
- if (values == null) {
- if (font.values == null) {
- return true;
- } else {
- return getAttributeValues().equals(font.values);
- }
- } else {
- return values.equals(font.getAttributeValues());
- }
- }
- }
- catch (ClassCastException e) {
- }
- }
- return false;
- }
-
- /**
- * Converts this <code>Font</code> object to a <code>String</code>
- * representation.
- * @return a <code>String</code> representation of this
- * <code>Font</code> object.
- * @since JDK1.0
- */
- // NOTE: This method may be called by privileged threads.
- // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
- public String toString() {
- String strStyle;
-
- if (isBold()) {
- strStyle = isItalic() ? "bolditalic" : "bold";
- } else {
- strStyle = isItalic() ? "italic" : "plain";
- }
-
- return getClass().getName() + "[family=" + getFamily() + ",name=" + name + ",style=" +
- strStyle + ",size=" + size + "]";
- } // toString()
-
-
- /** Serialization support. A <code>readObject</code>
- * method is neccessary because the constructor creates
- * the font's peer, and we can't serialize the peer.
- * Similarly the computed font "family" may be different
- * at <code>readObject</code> time than at
- * <code>writeObject</code> time. An integer version is
- * written so that future versions of this class will be
- * able to recognize serialized output from this one.
- */
- /**
- * The <code>Font</code> Serializable Data Form.
- *
- * @serial
- */
- private int fontSerializedDataVersion = 1;
-
- /**
- * Writes default serializable fields to a stream.
- *
- * @param s the <code>ObjectOutputStream</code> to write
- * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
- * @see #readObject(java.io.ObjectInputStream)
- */
- private void writeObject(java.io.ObjectOutputStream s)
- throws java.lang.ClassNotFoundException,
- java.io.IOException
- {
- if (values != null) {
- synchronized(values) {
- // transient
- fRequestedAttributes = values.toSerializableHashtable();
- s.defaultWriteObject();
- fRequestedAttributes = null;
- }
- } else {
- s.defaultWriteObject();
- }
- }
-
- /**
- * Reads the <code>ObjectInputStream</code>.
- * Unrecognized keys or values will be ignored.
- *
- * @param s the <code>ObjectInputStream</code> to read
- * @serial
- * @see #writeObject(java.io.ObjectOutputStream)
- */
- private void readObject(java.io.ObjectInputStream s)
- throws java.lang.ClassNotFoundException,
- java.io.IOException
- {
- s.defaultReadObject();
- if (pointSize == 0) {
- pointSize = (float)size;
- }
-
- // Handle fRequestedAttributes.
- // in 1.5, we always streamed out the font values plus
- // TRANSFORM, SUPERSCRIPT, and WIDTH, regardless of whether the
- // values were default or not. In 1.6 we only stream out
- // defined values. So, 1.6 streams in from a 1.5 stream,
- // it check each of these values and 'undefines' it if the
- // value is the default.
-
- if (fRequestedAttributes != null) {
- values = getAttributeValues(); // init
- AttributeValues extras =
- AttributeValues.fromSerializableHashtable(fRequestedAttributes);
- if (!AttributeValues.is16Hashtable(fRequestedAttributes)) {
- extras.unsetDefault(); // if legacy stream, undefine these
- }
- values = getAttributeValues().merge(extras);
- this.nonIdentityTx = values.anyNonDefault(EXTRA_MASK);
- this.hasLayoutAttributes = values.anyNonDefault(LAYOUT_MASK);
-
- fRequestedAttributes = null; // don't need it any more
- }
- }
-
- /**
- * Returns the number of glyphs in this <code>Font</code>. Glyph codes
- * for this <code>Font</code> range from 0 to
- * <code>getNumGlyphs()</code> - 1.
- * @return the number of glyphs in this <code>Font</code>.
- * @since 1.2
- */
- public int getNumGlyphs() {
- return getFont2D().getNumGlyphs();
- }
-
- /**
- * Returns the glyphCode which is used when this <code>Font</code>
- * does not have a glyph for a specified unicode code point.
- * @return the glyphCode of this <code>Font</code>.
- * @since 1.2
- */
- public int getMissingGlyphCode() {
- return getFont2D().getMissingGlyphCode();
- }
-
- /**
- * Returns the baseline appropriate for displaying this character.
- * <p>
- * Large fonts can support different writing systems, and each system can
- * use a different baseline.
- * The character argument determines the writing system to use. Clients
- * should not assume all characters use the same baseline.
- *
- * @param c a character used to identify the writing system
- * @return the baseline appropriate for the specified character.
- * @see LineMetrics#getBaselineOffsets
- * @see #ROMAN_BASELINE
- * @see #CENTER_BASELINE
- * @see #HANGING_BASELINE
- * @since 1.2
- */
- public byte getBaselineFor(char c) {
- return getFont2D().getBaselineFor(c);
- }
-
- /**
- * Returns a map of font attributes available in this
- * <code>Font</code>. Attributes include things like ligatures and
- * glyph substitution.
- * @return the attributes map of this <code>Font</code>.
- */
- public Map<TextAttribute,?> getAttributes(){
- return new AttributeMap(getAttributeValues());
- }
-
- /**
- * Returns the keys of all the attributes supported by this
- * <code>Font</code>. These attributes can be used to derive other
- * fonts.
- * @return an array containing the keys of all the attributes
- * supported by this <code>Font</code>.
- * @since 1.2
- */
- public Attribute[] getAvailableAttributes() {
- // FONT is not supported by Font
-
- Attribute attributes[] = {
- TextAttribute.FAMILY,
- TextAttribute.WEIGHT,
- TextAttribute.WIDTH,
- TextAttribute.POSTURE,
- TextAttribute.SIZE,
- TextAttribute.TRANSFORM,
- TextAttribute.SUPERSCRIPT,
- TextAttribute.CHAR_REPLACEMENT,
- TextAttribute.FOREGROUND,
- TextAttribute.BACKGROUND,
- TextAttribute.UNDERLINE,
- TextAttribute.STRIKETHROUGH,
- TextAttribute.RUN_DIRECTION,
- TextAttribute.BIDI_EMBEDDING,
- TextAttribute.JUSTIFICATION,
- TextAttribute.INPUT_METHOD_HIGHLIGHT,
- TextAttribute.INPUT_METHOD_UNDERLINE,
- TextAttribute.SWAP_COLORS,
- TextAttribute.NUMERIC_SHAPING,
- TextAttribute.KERNING,
- TextAttribute.LIGATURES,
- TextAttribute.TRACKING,
- };
-
- return attributes;
- }
-
- /**
- * Creates a new <code>Font</code> object by replicating this
- * <code>Font</code> object and applying a new style and size.
- * @param style the style for the new <code>Font</code>
- * @param size the size for the new <code>Font</code>
- * @return a new <code>Font</code> object.
- * @since 1.2
- */
- public Font deriveFont(int style, float size){
- if (values == null) {
- return new Font(name, style, size, createdFont, font2DHandle);
- }
- AttributeValues newValues = getAttributeValues().clone();
- int oldStyle = (this.style != style) ? this.style : -1;
- applyStyle(style, newValues);
- newValues.setSize(size);
- return new Font(newValues, null, oldStyle, createdFont, font2DHandle);
- }
-
- /**
- * Creates a new <code>Font</code> object by replicating this
- * <code>Font</code> object and applying a new style and transform.
- * @param style the style for the new <code>Font</code>
- * @param trans the <code>AffineTransform</code> associated with the
- * new <code>Font</code>
- * @return a new <code>Font</code> object.
- * @throws IllegalArgumentException if <code>trans</code> is
- * <code>null</code>
- * @since 1.2
- */
- public Font deriveFont(int style, AffineTransform trans){
- AttributeValues newValues = getAttributeValues().clone();
- int oldStyle = (this.style != style) ? this.style : -1;
- applyStyle(style, newValues);
- applyTransform(trans, newValues);
- return new Font(newValues, null, oldStyle, createdFont, font2DHandle);
- }
-
- /**
- * Creates a new <code>Font</code> object by replicating the current
- * <code>Font</code> object and applying a new size to it.
- * @param size the size for the new <code>Font</code>.
- * @return a new <code>Font</code> object.
- * @since 1.2
- */
- public Font deriveFont(float size){
- if (values == null) {
- return new Font(name, style, size, createdFont, font2DHandle);
- }
- AttributeValues newValues = getAttributeValues().clone();
- newValues.setSize(size);
- return new Font(newValues, null, -1, createdFont, font2DHandle);
- }
-
- /**
- * Creates a new <code>Font</code> object by replicating the current
- * <code>Font</code> object and applying a new transform to it.
- * @param trans the <code>AffineTransform</code> associated with the
- * new <code>Font</code>
- * @return a new <code>Font</code> object.
- * @throws IllegalArgumentException if <code>trans</code> is
- * <code>null</code>
- * @since 1.2
- */
- public Font deriveFont(AffineTransform trans){
- AttributeValues newValues = getAttributeValues().clone();
- applyTransform(trans, newValues);
- return new Font(newValues, null, -1, createdFont, font2DHandle);
- }
-
- /**
- * Creates a new <code>Font</code> object by replicating the current
- * <code>Font</code> object and applying a new style to it.
- * @param style the style for the new <code>Font</code>
- * @return a new <code>Font</code> object.
- * @since 1.2
- */
- public Font deriveFont(int style){
- if (values == null) {
- return new Font(name, style, size, createdFont, font2DHandle);
- }
- AttributeValues newValues = getAttributeValues().clone();
- int oldStyle = (this.style != style) ? this.style : -1;
- applyStyle(style, newValues);
- return new Font(newValues, null, oldStyle, createdFont, font2DHandle);
- }
-
- /**
- * Creates a new <code>Font</code> object by replicating the current
- * <code>Font</code> object and applying a new set of font attributes
- * to it.
- *
- * @param attributes a map of attributes enabled for the new
- * <code>Font</code>
- * @return a new <code>Font</code> object.
- * @since 1.2
- */
- public Font deriveFont(Map<? extends Attribute, ?> attributes) {
- if (attributes == null) {
- return this;
- }
- AttributeValues newValues = getAttributeValues().clone();
- newValues.merge(attributes, RECOGNIZED_MASK);
-
- return new Font(newValues, name, style, createdFont, font2DHandle);
- }
-
- /**
- * Checks if this <code>Font</code> has a glyph for the specified
- * character.
- *
- * <p> <b>Note:</b> This method cannot handle <a
- * href="../../java/lang/Character.html#supplementary"> supplementary
- * characters</a>. To support all Unicode characters, including
- * supplementary characters, use the {@link #canDisplay(int)}
- * method or <code>canDisplayUpTo</code> methods.
- *
- * @param c the character for which a glyph is needed
- * @return <code>true</code> if this <code>Font</code> has a glyph for this
- * character; <code>false</code> otherwise.
- * @since 1.2
- */
- public boolean canDisplay(char c){
- return getFont2D().canDisplay(c);
- }
-
- /**
- * Checks if this <code>Font</code> has a glyph for the specified
- * character.
- *
- * @param codePoint the character (Unicode code point) for which a glyph
- * is needed.
- * @return <code>true</code> if this <code>Font</code> has a glyph for the
- * character; <code>false</code> otherwise.
- * @throws IllegalArgumentException if the code point is not a valid Unicode
- * code point.
- * @see Character#isValidCodePoint(int)
- * @since 1.5
- */
- public boolean canDisplay(int codePoint) {
- if (!Character.isValidCodePoint(codePoint)) {
- throw new IllegalArgumentException("invalid code point: " +
- Integer.toHexString(codePoint));
- }
- return getFont2D().canDisplay(codePoint);
- }
-
- /**
- * Indicates whether or not this <code>Font</code> can display a
- * specified <code>String</code>. For strings with Unicode encoding,
- * it is important to know if a particular font can display the
- * string. This method returns an offset into the <code>String</code>
- * <code>str</code> which is the first character this
- * <code>Font</code> cannot display without using the missing glyph
- * code. If the <code>Font</code> can display all characters, -1 is
- * returned.
- * @param str a <code>String</code> object
- * @return an offset into <code>str</code> that points
- * to the first character in <code>str</code> that this
- * <code>Font</code> cannot display; or <code>-1</code> if
- * this <code>Font</code> can display all characters in
- * <code>str</code>.
- * @since 1.2
- */
- public int canDisplayUpTo(String str) {
- Font2D font2d = getFont2D();
- int len = str.length();
- for (int i = 0; i < len; i++) {
- char c = str.charAt(i);
- if (font2d.canDisplay(c)) {
- continue;
- }
- if (!Character.isHighSurrogate(c)) {
- return i;
- }
- if (!font2d.canDisplay(str.codePointAt(i))) {
- return i;
- }
- i++;
- }
- return -1;
- }
-
- /**
- * Indicates whether or not this <code>Font</code> can display
- * the characters in the specified <code>text</code>
- * starting at <code>start</code> and ending at
- * <code>limit</code>. This method is a convenience overload.
- * @param text the specified array of <code>char</code> values
- * @param start the specified starting offset (in
- * <code>char</code>s) into the specified array of
- * <code>char</code> values
- * @param limit the specified ending offset (in
- * <code>char</code>s) into the specified array of
- * <code>char</code> values
- * @return an offset into <code>text</code> that points
- * to the first character in <code>text</code> that this
- * <code>Font</code> cannot display; or <code>-1</code> if
- * this <code>Font</code> can display all characters in
- * <code>text</code>.
- * @since 1.2
- */
- public int canDisplayUpTo(char[] text, int start, int limit) {
- Font2D font2d = getFont2D();
- for (int i = start; i < limit; i++) {
- char c = text[i];
- if (font2d.canDisplay(c)) {
- continue;
- }
- if (!Character.isHighSurrogate(c)) {
- return i;
- }
- if (!font2d.canDisplay(Character.codePointAt(text, i, limit))) {
- return i;
- }
- i++;
- }
- return -1;
- }
-
- /**
- * Indicates whether or not this <code>Font</code> can display the
- * text specified by the <code>iter</code> starting at
- * <code>start</code> and ending at <code>limit</code>.
- *
- * @param iter a {@link CharacterIterator} object
- * @param start the specified starting offset into the specified
- * <code>CharacterIterator</code>.
- * @param limit the specified ending offset into the specified
- * <code>CharacterIterator</code>.
- * @return an offset into <code>iter</code> that points
- * to the first character in <code>iter</code> that this
- * <code>Font</code> cannot display; or <code>-1</code> if
- * this <code>Font</code> can display all characters in
- * <code>iter</code>.
- * @since 1.2
- */
- public int canDisplayUpTo(CharacterIterator iter, int start, int limit) {
- Font2D font2d = getFont2D();
- char c = iter.setIndex(start);
- for (int i = start; i < limit; i++, c = iter.next()) {
- if (font2d.canDisplay(c)) {
- continue;
- }
- if (!Character.isHighSurrogate(c)) {
- return i;
- }
- char c2 = iter.next();
- // c2 could be CharacterIterator.DONE which is not a low surrogate.
- if (!Character.isLowSurrogate(c2)) {
- return i;
- }
- if (!font2d.canDisplay(Character.toCodePoint(c, c2))) {
- return i;
- }
- i++;
- }
- return -1;
- }
-
- /**
- * Returns the italic angle of this <code>Font</code>. The italic angle
- * is the inverse slope of the caret which best matches the posture of this
- * <code>Font</code>.
- * @see TextAttribute#POSTURE
- * @return the angle of the ITALIC style of this <code>Font</code>.
- */
- public float getItalicAngle() {
- return getItalicAngle(null);
- }
-
- /* The FRC hints don't affect the value of the italic angle but
- * we need to pass them in to look up a strike.
- * If we can pass in ones already being used it can prevent an extra
- * strike from being allocated. Note that since italic angle is
- * a property of the font, the font transform is needed not the
- * device transform. Finally, this is private but the only caller of this
- * in the JDK - and the only likely caller - is in this same class.
- */
- private float getItalicAngle(FontRenderContext frc) {
- Object aa, fm;
- if (frc == null) {
- aa = RenderingHints.VALUE_TEXT_ANTIALIAS_OFF;
- fm = RenderingHints.VALUE_FRACTIONALMETRICS_OFF;
- } else {
- aa = frc.getAntiAliasingHint();
- fm = frc.getFractionalMetricsHint();
- }
- return getFont2D().getItalicAngle(this, identityTx, aa, fm);
- }
-
- /**
- * Checks whether or not this <code>Font</code> has uniform
- * line metrics. A logical <code>Font</code> might be a
- * composite font, which means that it is composed of different
- * physical fonts to cover different code ranges. Each of these
- * fonts might have different <code>LineMetrics</code>. If the
- * logical <code>Font</code> is a single
- * font then the metrics would be uniform.
- * @return <code>true</code> if this <code>Font</code> has
- * uniform line metrics; <code>false</code> otherwise.
- */
- public boolean hasUniformLineMetrics() {
- return false; // REMIND always safe, but prevents caller optimize
- }
-
- private transient SoftReference<FontLineMetrics> flmref;
- private FontLineMetrics defaultLineMetrics(FontRenderContext frc) {
- FontLineMetrics flm = null;
- if (flmref == null
- || (flm = flmref.get()) == null
- || !flm.frc.equals(frc)) {
-
- /* The device transform in the frc is not used in obtaining line
- * metrics, although it probably should be: REMIND find why not?
- * The font transform is used but its applied in getFontMetrics, so
- * just pass identity here
- */
- float [] metrics = new float[8];
- getFont2D().getFontMetrics(this, identityTx,
- frc.getAntiAliasingHint(),
- frc.getFractionalMetricsHint(),
- metrics);
- float ascent = metrics[0];
- float descent = metrics[1];
- float leading = metrics[2];
- float ssOffset = 0;
- if (values != null && values.getSuperscript() != 0) {
- ssOffset = (float)getTransform().getTranslateY();
- ascent -= ssOffset;
- descent += ssOffset;
- }
- float height = ascent + descent + leading;
-
- int baselineIndex = 0; // need real index, assumes roman for everything
- // need real baselines eventually
- float[] baselineOffsets = { 0, (descent/2f - ascent) / 2f, -ascent };
-
- float strikethroughOffset = metrics[4];
- float strikethroughThickness = metrics[5];
-
- float underlineOffset = metrics[6];
- float underlineThickness = metrics[7];
-
- float italicAngle = getItalicAngle(frc);
-
- if (isTransformed()) {
- AffineTransform ctx = values.getCharTransform(); // extract rotation
- if (ctx != null) {
- Point2D.Float pt = new Point2D.Float();
- pt.setLocation(0, strikethroughOffset);
- ctx.deltaTransform(pt, pt);
- strikethroughOffset = pt.y;
- pt.setLocation(0, strikethroughThickness);
- ctx.deltaTransform(pt, pt);
- strikethroughThickness = pt.y;
- pt.setLocation(0, underlineOffset);
- ctx.deltaTransform(pt, pt);
- underlineOffset = pt.y;
- pt.setLocation(0, underlineThickness);
- ctx.deltaTransform(pt, pt);
- underlineThickness = pt.y;
- }
- }
- strikethroughOffset += ssOffset;
- underlineOffset += ssOffset;
-
- CoreMetrics cm = new CoreMetrics(ascent, descent, leading, height,
- baselineIndex, baselineOffsets,
- strikethroughOffset, strikethroughThickness,
- underlineOffset, underlineThickness,
- ssOffset, italicAngle);
-
- flm = new FontLineMetrics(0, cm, frc);
- flmref = new SoftReference<FontLineMetrics>(flm);
- }
-
- return (FontLineMetrics)flm.clone();
- }
-
- /**
- * Returns a {@link LineMetrics} object created with the specified
- * <code>String</code> and {@link FontRenderContext}.
- * @param str the specified <code>String</code>
- * @param frc the specified <code>FontRenderContext</code>
- * @return a <code>LineMetrics</code> object created with the
- * specified <code>String</code> and {@link FontRenderContext}.
- */
- public LineMetrics getLineMetrics( String str, FontRenderContext frc) {
- FontLineMetrics flm = defaultLineMetrics(frc);
- flm.numchars = str.length();
- return flm;
- }
-
- /**
- * Returns a <code>LineMetrics</code> object created with the
- * specified arguments.
- * @param str the specified <code>String</code>
- * @param beginIndex the initial offset of <code>str</code>
- * @param limit the end offset of <code>str</code>
- * @param frc the specified <code>FontRenderContext</code>
- * @return a <code>LineMetrics</code> object created with the
- * specified arguments.
- */
- public LineMetrics getLineMetrics( String str,
- int beginIndex, int limit,
- FontRenderContext frc) {
- FontLineMetrics flm = defaultLineMetrics(frc);
- int numChars = limit - beginIndex;
- flm.numchars = (numChars < 0)? 0: numChars;
- return flm;
- }
-
- /**
- * Returns a <code>LineMetrics</code> object created with the
- * specified arguments.
- * @param chars an array of characters
- * @param beginIndex the initial offset of <code>chars</code>
- * @param limit the end offset of <code>chars</code>
- * @param frc the specified <code>FontRenderContext</code>
- * @return a <code>LineMetrics</code> object created with the
- * specified arguments.
- */
- public LineMetrics getLineMetrics(char [] chars,
- int beginIndex, int limit,
- FontRenderContext frc) {
- FontLineMetrics flm = defaultLineMetrics(frc);
- int numChars = limit - beginIndex;
- flm.numchars = (numChars < 0)? 0: numChars;
- return flm;
- }
-
- /**
- * Returns a <code>LineMetrics</code> object created with the
- * specified arguments.
- * @param ci the specified <code>CharacterIterator</code>
- * @param beginIndex the initial offset in <code>ci</code>
- * @param limit the end offset of <code>ci</code>
- * @param frc the specified <code>FontRenderContext</code>
- * @return a <code>LineMetrics</code> object created with the
- * specified arguments.
- */
- public LineMetrics getLineMetrics(CharacterIterator ci,
- int beginIndex, int limit,
- FontRenderContext frc) {
- FontLineMetrics flm = defaultLineMetrics(frc);
- int numChars = limit - beginIndex;
- flm.numchars = (numChars < 0)? 0: numChars;
- return flm;
- }
-
- /**
- * Returns the logical bounds of the specified <code>String</code> in
- * the specified <code>FontRenderContext</code>. The logical bounds
- * contains the origin, ascent, advance, and height, which includes
- * the leading. The logical bounds does not always enclose all the
- * text. For example, in some languages and in some fonts, accent
- * marks can be positioned above the ascent or below the descent.
- * To obtain a visual bounding box, which encloses all the text,
- * use the {@link TextLayout#getBounds() getBounds} method of
- * <code>TextLayout</code>.
- * <p>Note: The returned bounds is in baseline-relative coordinates
- * (see {@link java.awt.Font class notes}).
- * @param str the specified <code>String</code>
- * @param frc the specified <code>FontRenderContext</code>
- * @return a {@link Rectangle2D} that is the bounding box of the
- * specified <code>String</code> in the specified
- * <code>FontRenderContext</code>.
- * @see FontRenderContext
- * @see Font#createGlyphVector
- * @since 1.2
- */
- public Rectangle2D getStringBounds( String str, FontRenderContext frc) {
- char[] array = str.toCharArray();
- return getStringBounds(array, 0, array.length, frc);
- }
-
- /**
- * Returns the logical bounds of the specified <code>String</code> in
- * the specified <code>FontRenderContext</code>. The logical bounds
- * contains the origin, ascent, advance, and height, which includes
- * the leading. The logical bounds does not always enclose all the
- * text. For example, in some languages and in some fonts, accent
- * marks can be positioned above the ascent or below the descent.
- * To obtain a visual bounding box, which encloses all the text,
- * use the {@link TextLayout#getBounds() getBounds} method of
- * <code>TextLayout</code>.
- * <p>Note: The returned bounds is in baseline-relative coordinates
- * (see {@link java.awt.Font class notes}).
- * @param str the specified <code>String</code>
- * @param beginIndex the initial offset of <code>str</code>
- * @param limit the end offset of <code>str</code>
- * @param frc the specified <code>FontRenderContext</code>
- * @return a <code>Rectangle2D</code> that is the bounding box of the
- * specified <code>String</code> in the specified
- * <code>FontRenderContext</code>.
- * @throws IndexOutOfBoundsException if <code>beginIndex</code> is
- * less than zero, or <code>limit</code> is greater than the
- * length of <code>str</code>, or <code>beginIndex</code>
- * is greater than <code>limit</code>.
- * @see FontRenderContext
- * @see Font#createGlyphVector
- * @since 1.2
- */
- public Rectangle2D getStringBounds( String str,
- int beginIndex, int limit,
- FontRenderContext frc) {
- String substr = str.substring(beginIndex, limit);
- return getStringBounds(substr, frc);
- }
-
- /**
- * Returns the logical bounds of the specified array of characters
- * in the specified <code>FontRenderContext</code>. The logical
- * bounds contains the origin, ascent, advance, and height, which
- * includes the leading. The logical bounds does not always enclose
- * all the text. For example, in some languages and in some fonts,
- * accent marks can be positioned above the ascent or below the
- * descent. To obtain a visual bounding box, which encloses all the
- * text, use the {@link TextLayout#getBounds() getBounds} method of
- * <code>TextLayout</code>.
- * <p>Note: The returned bounds is in baseline-relative coordinates
- * (see {@link java.awt.Font class notes}).
- * @param chars an array of characters
- * @param beginIndex the initial offset in the array of
- * characters
- * @param limit the end offset in the array of characters
- * @param frc the specified <code>FontRenderContext</code>
- * @return a <code>Rectangle2D</code> that is the bounding box of the
- * specified array of characters in the specified
- * <code>FontRenderContext</code>.
- * @throws IndexOutOfBoundsException if <code>beginIndex</code> is
- * less than zero, or <code>limit</code> is greater than the
- * length of <code>chars</code>, or <code>beginIndex</code>
- * is greater than <code>limit</code>.
- * @see FontRenderContext
- * @see Font#createGlyphVector
- * @since 1.2
- */
- public Rectangle2D getStringBounds(char [] chars,
- int beginIndex, int limit,
- FontRenderContext frc) {
- if (beginIndex < 0) {
- throw new IndexOutOfBoundsException("beginIndex: " + beginIndex);
- }
- if (limit > chars.length) {
- throw new IndexOutOfBoundsException("limit: " + limit);
- }
- if (beginIndex > limit) {
- throw new IndexOutOfBoundsException("range length: " +
- (limit - beginIndex));
- }
-
- // this code should be in textlayout
- // quick check for simple text, assume GV ok to use if simple
-
- boolean simple = values == null ||
- (values.getKerning() == 0 && values.getLigatures() == 0 &&
- values.getBaselineTransform() == null);
- if (simple) {
- simple = ! FontUtilities.isComplexText(chars, beginIndex, limit);
- }
-
- if (simple) {
- GlyphVector gv = new StandardGlyphVector(this, chars, beginIndex,
- limit - beginIndex, frc);
- return gv.getLogicalBounds();
- } else {
- // need char array constructor on textlayout
- String str = new String(chars, beginIndex, limit - beginIndex);
- TextLayout tl = new TextLayout(str, this, frc);
- return new Rectangle2D.Float(0, -tl.getAscent(), tl.getAdvance(),
- tl.getAscent() + tl.getDescent() +
- tl.getLeading());
- }
- }
-
- /**
- * Returns the logical bounds of the characters indexed in the
- * specified {@link CharacterIterator} in the
- * specified <code>FontRenderContext</code>. The logical bounds
- * contains the origin, ascent, advance, and height, which includes
- * the leading. The logical bounds does not always enclose all the
- * text. For example, in some languages and in some fonts, accent
- * marks can be positioned above the ascent or below the descent.
- * To obtain a visual bounding box, which encloses all the text,
- * use the {@link TextLayout#getBounds() getBounds} method of
- * <code>TextLayout</code>.
- * <p>Note: The returned bounds is in baseline-relative coordinates
- * (see {@link java.awt.Font class notes}).
- * @param ci the specified <code>CharacterIterator</code>
- * @param beginIndex the initial offset in <code>ci</code>
- * @param limit the end offset in <code>ci</code>
- * @param frc the specified <code>FontRenderContext</code>
- * @return a <code>Rectangle2D</code> that is the bounding box of the
- * characters indexed in the specified <code>CharacterIterator</code>
- * in the specified <code>FontRenderContext</code>.
- * @see FontRenderContext
- * @see Font#createGlyphVector
- * @since 1.2
- * @throws IndexOutOfBoundsException if <code>beginIndex</code> is
- * less than the start index of <code>ci</code>, or
- * <code>limit</code> is greater than the end index of
- * <code>ci</code>, or <code>beginIndex</code> is greater
- * than <code>limit</code>
- */
- public Rectangle2D getStringBounds(CharacterIterator ci,
- int beginIndex, int limit,
- FontRenderContext frc) {
- int start = ci.getBeginIndex();
- int end = ci.getEndIndex();
-
- if (beginIndex < start) {
- throw new IndexOutOfBoundsException("beginIndex: " + beginIndex);
- }
- if (limit > end) {
- throw new IndexOutOfBoundsException("limit: " + limit);
- }
- if (beginIndex > limit) {
- throw new IndexOutOfBoundsException("range length: " +
- (limit - beginIndex));
- }
-
- char[] arr = new char[limit - beginIndex];
-
- ci.setIndex(beginIndex);
- for(int idx = 0; idx < arr.length; idx++) {
- arr[idx] = ci.current();
- ci.next();
- }
-
- return getStringBounds(arr,0,arr.length,frc);
- }
-
- /**
- * Returns the bounds for the character with the maximum
- * bounds as defined in the specified <code>FontRenderContext</code>.
- * <p>Note: The returned bounds is in baseline-relative coordinates
- * (see {@link java.awt.Font class notes}).
- * @param frc the specified <code>FontRenderContext</code>
- * @return a <code>Rectangle2D</code> that is the bounding box
- * for the character with the maximum bounds.
- */
- public Rectangle2D getMaxCharBounds(FontRenderContext frc) {
- float [] metrics = new float[4];
-
- getFont2D().getFontMetrics(this, frc, metrics);
-
- return new Rectangle2D.Float(0, -metrics[0],
- metrics[3],
- metrics[0] + metrics[1] + metrics[2]);
- }
-
- /**
- * Creates a {@link java.awt.font.GlyphVector GlyphVector} by
- * mapping characters to glyphs one-to-one based on the
- * Unicode cmap in this <code>Font</code>. This method does no other
- * processing besides the mapping of glyphs to characters. This
- * means that this method is not useful for some scripts, such
- * as Arabic, Hebrew, Thai, and Indic, that require reordering,
- * shaping, or ligature substitution.
- * @param frc the specified <code>FontRenderContext</code>
- * @param str the specified <code>String</code>
- * @return a new <code>GlyphVector</code> created with the
- * specified <code>String</code> and the specified
- * <code>FontRenderContext</code>.
- */
- public GlyphVector createGlyphVector(FontRenderContext frc, String str)
- {
- return (GlyphVector)new StandardGlyphVector(this, str, frc);
- }
-
- /**
- * Creates a {@link java.awt.font.GlyphVector GlyphVector} by
- * mapping characters to glyphs one-to-one based on the
- * Unicode cmap in this <code>Font</code>. This method does no other
- * processing besides the mapping of glyphs to characters. This
- * means that this method is not useful for some scripts, such
- * as Arabic, Hebrew, Thai, and Indic, that require reordering,
- * shaping, or ligature substitution.
- * @param frc the specified <code>FontRenderContext</code>
- * @param chars the specified array of characters
- * @return a new <code>GlyphVector</code> created with the
- * specified array of characters and the specified
- * <code>FontRenderContext</code>.
- */
- public GlyphVector createGlyphVector(FontRenderContext frc, char[] chars)
- {
- return (GlyphVector)new StandardGlyphVector(this, chars, frc);
- }
-
- /**
- * Creates a {@link java.awt.font.GlyphVector GlyphVector} by
- * mapping the specified characters to glyphs one-to-one based on the
- * Unicode cmap in this <code>Font</code>. This method does no other
- * processing besides the mapping of glyphs to characters. This
- * means that this method is not useful for some scripts, such
- * as Arabic, Hebrew, Thai, and Indic, that require reordering,
- * shaping, or ligature substitution.
- * @param frc the specified <code>FontRenderContext</code>
- * @param ci the specified <code>CharacterIterator</code>
- * @return a new <code>GlyphVector</code> created with the
- * specified <code>CharacterIterator</code> and the specified
- * <code>FontRenderContext</code>.
- */
- public GlyphVector createGlyphVector( FontRenderContext frc,
- CharacterIterator ci)
- {
- return (GlyphVector)new StandardGlyphVector(this, ci, frc);
- }
-
- /**
- * Creates a {@link java.awt.font.GlyphVector GlyphVector} by
- * mapping characters to glyphs one-to-one based on the
- * Unicode cmap in this <code>Font</code>. This method does no other
- * processing besides the mapping of glyphs to characters. This
- * means that this method is not useful for some scripts, such
- * as Arabic, Hebrew, Thai, and Indic, that require reordering,
- * shaping, or ligature substitution.
- * @param frc the specified <code>FontRenderContext</code>
- * @param glyphCodes the specified integer array
- * @return a new <code>GlyphVector</code> created with the
- * specified integer array and the specified
- * <code>FontRenderContext</code>.
- */
- public GlyphVector createGlyphVector( FontRenderContext frc,
- int [] glyphCodes)
- {
- return (GlyphVector)new StandardGlyphVector(this, glyphCodes, frc);
- }
-
- /**
- * Returns a new <code>GlyphVector</code> object, performing full
- * layout of the text if possible. Full layout is required for
- * complex text, such as Arabic or Hindi. Support for different
- * scripts depends on the font and implementation.
- * <p>
- * Layout requires bidi analysis, as performed by
- * <code>Bidi</code>, and should only be performed on text that
- * has a uniform direction. The direction is indicated in the
- * flags parameter,by using LAYOUT_RIGHT_TO_LEFT to indicate a
- * right-to-left (Arabic and Hebrew) run direction, or
- * LAYOUT_LEFT_TO_RIGHT to indicate a left-to-right (English)
- * run direction.
- * <p>
- * In addition, some operations, such as Arabic shaping, require
- * context, so that the characters at the start and limit can have
- * the proper shapes. Sometimes the data in the buffer outside
- * the provided range does not have valid data. The values
- * LAYOUT_NO_START_CONTEXT and LAYOUT_NO_LIMIT_CONTEXT can be
- * added to the flags parameter to indicate that the text before
- * start, or after limit, respectively, should not be examined
- * for context.
- * <p>
- * All other values for the flags parameter are reserved.
- *
- * @param frc the specified <code>FontRenderContext</code>
- * @param text the text to layout
- * @param start the start of the text to use for the <code>GlyphVector</code>
- * @param limit the limit of the text to use for the <code>GlyphVector</code>
- * @param flags control flags as described above
- * @return a new <code>GlyphVector</code> representing the text between
- * start and limit, with glyphs chosen and positioned so as to best represent
- * the text
- * @throws ArrayIndexOutOfBoundsException if start or limit is
- * out of bounds
- * @see java.text.Bidi
- * @see #LAYOUT_LEFT_TO_RIGHT
- * @see #LAYOUT_RIGHT_TO_LEFT
- * @see #LAYOUT_NO_START_CONTEXT
- * @see #LAYOUT_NO_LIMIT_CONTEXT
- * @since 1.4
- */
- public GlyphVector layoutGlyphVector(FontRenderContext frc,
- char[] text,
- int start,
- int limit,
- int flags) {
-
- return new StandardGlyphVector(this,text,start, limit-start, frc);
- }
-
- /**
- * A flag to layoutGlyphVector indicating that text is left-to-right as
- * determined by Bidi analysis.
- */
- public static final int LAYOUT_LEFT_TO_RIGHT = 0;
-
- /**
- * A flag to layoutGlyphVector indicating that text is right-to-left as
- * determined by Bidi analysis.
- */
- public static final int LAYOUT_RIGHT_TO_LEFT = 1;
-
- /**
- * A flag to layoutGlyphVector indicating that text in the char array
- * before the indicated start should not be examined.
- */
- public static final int LAYOUT_NO_START_CONTEXT = 2;
-
- /**
- * A flag to layoutGlyphVector indicating that text in the char array
- * after the indicated limit should not be examined.
- */
- public static final int LAYOUT_NO_LIMIT_CONTEXT = 4;
-
-
- private static void applyTransform(AffineTransform trans, AttributeValues values) {
- if (trans == null) {
- throw new IllegalArgumentException("transform must not be null");
- }
- values.setTransform(trans);
- }
-
- private static void applyStyle(int style, AttributeValues values) {
- // WEIGHT_BOLD, WEIGHT_REGULAR
- values.setWeight((style & BOLD) != 0 ? 2f : 1f);
- // POSTURE_OBLIQUE, POSTURE_REGULAR
- values.setPosture((style & ITALIC) != 0 ? .2f : 0f);
- }
-
-}