Source Code Cross Referenced for Font.java in  » 6.0-JDK-Core » AWT » java » awt » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » AWT » java.awt 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001        /*
0002         * Copyright 1995-2007 Sun Microsystems, Inc.  All Rights Reserved.
0003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004         *
0005         * This code is free software; you can redistribute it and/or modify it
0006         * under the terms of the GNU General Public License version 2 only, as
0007         * published by the Free Software Foundation.  Sun designates this
0008         * particular file as subject to the "Classpath" exception as provided
0009         * by Sun in the LICENSE file that accompanied this code.
0010         *
0011         * This code is distributed in the hope that it will be useful, but WITHOUT
0012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014         * version 2 for more details (a copy is included in the LICENSE file that
0015         * accompanied this code).
0016         *
0017         * You should have received a copy of the GNU General Public License version
0018         * 2 along with this work; if not, write to the Free Software Foundation,
0019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020         *
0021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022         * CA 95054 USA or visit www.sun.com if you need additional information or
0023         * have any questions.
0024         */
0025
0026        package java.awt;
0027
0028        import java.awt.font.FontRenderContext;
0029        import java.awt.font.GlyphVector;
0030        import java.awt.font.LineMetrics;
0031        import java.awt.font.TextAttribute;
0032        import java.awt.font.TextLayout;
0033        import java.awt.font.TransformAttribute;
0034        import java.awt.geom.AffineTransform;
0035        import java.awt.geom.Point2D;
0036        import java.awt.geom.Rectangle2D;
0037        import java.awt.peer.FontPeer;
0038        import java.io.*;
0039        import java.lang.ref.SoftReference;
0040        import java.text.AttributedCharacterIterator.Attribute;
0041        import java.text.CharacterIterator;
0042        import java.text.StringCharacterIterator;
0043        import java.util.HashMap;
0044        import java.util.Hashtable;
0045        import java.util.Locale;
0046        import java.util.Map;
0047        import sun.font.StandardGlyphVector;
0048        import sun.java2d.FontSupport;
0049
0050        import sun.font.AttributeMap;
0051        import sun.font.AttributeValues;
0052        import sun.font.EAttribute;
0053        import sun.font.CompositeFont;
0054        import sun.font.Font2D;
0055        import sun.font.Font2DHandle;
0056        import sun.font.FontManager;
0057        import sun.font.GlyphLayout;
0058        import sun.font.FontLineMetrics;
0059        import sun.font.CoreMetrics;
0060
0061        import static sun.font.EAttribute.*;
0062
0063        /**
0064         * The <code>Font</code> class represents fonts, which are used to
0065         * render text in a visible way.
0066         * A font provides the information needed to map sequences of
0067         * <em>characters</em> to sequences of <em>glyphs</em>
0068         * and to render sequences of glyphs on <code>Graphics</code> and
0069         * <code>Component</code> objects.
0070         * 
0071         * <h4>Characters and Glyphs</h4>
0072         * 
0073         * A <em>character</em> is a symbol that represents an item such as a letter,
0074         * a digit, or punctuation in an abstract way. For example, <code>'g'</code>,
0075         * <font size=-1>LATIN SMALL LETTER G</font>, is a character.
0076         * <p>
0077         * A <em>glyph</em> is a shape used to render a character or a sequence of
0078         * characters. In simple writing systems, such as Latin, typically one glyph
0079         * represents one character. In general, however, characters and glyphs do not
0080         * have one-to-one correspondence. For example, the character '&aacute;'
0081         * <font size=-1>LATIN SMALL LETTER A WITH ACUTE</font>, can be represented by
0082         * two glyphs: one for 'a' and one for '&acute;'. On the other hand, the
0083         * two-character string "fi" can be represented by a single glyph, an
0084         * "fi" ligature. In complex writing systems, such as Arabic or the South
0085         * and South-East Asian writing systems, the relationship between characters
0086         * and glyphs can be more complicated and involve context-dependent selection
0087         * of glyphs as well as glyph reordering.
0088         *
0089         * A font encapsulates the collection of glyphs needed to render a selected set
0090         * of characters as well as the tables needed to map sequences of characters to
0091         * corresponding sequences of glyphs.
0092         *
0093         * <h4>Physical and Logical Fonts</h4>
0094         *
0095         * The Java Platform distinguishes between two kinds of fonts:
0096         * <em>physical</em> fonts and <em>logical</em> fonts.
0097         * <p>
0098         * <em>Physical</em> fonts are the actual font libraries containing glyph data
0099         * and tables to map from character sequences to glyph sequences, using a font
0100         * technology such as TrueType or PostScript Type 1.
0101         * All implementations of the Java Platform must support TrueType fonts;
0102         * support for other font technologies is implementation dependent.
0103         * Physical fonts may use names such as Helvetica, Palatino, HonMincho, or
0104         * any number of other font names.
0105         * Typically, each physical font supports only a limited set of writing
0106         * systems, for example, only Latin characters or only Japanese and Basic
0107         * Latin.
0108         * The set of available physical fonts varies between configurations.
0109         * Applications that require specific fonts can bundle them and instantiate
0110         * them using the {@link #createFont createFont} method.
0111         * <p>
0112         * <em>Logical</em> fonts are the five font families defined by the Java
0113         * platform which must be supported by any Java runtime environment:
0114         * Serif, SansSerif, Monospaced, Dialog, and DialogInput.
0115         * These logical fonts are not actual font libraries. Instead, the logical
0116         * font names are mapped to physical fonts by the Java runtime environment.
0117         * The mapping is implementation and usually locale dependent, so the look
0118         * and the metrics provided by them vary.
0119         * Typically, each logical font name maps to several physical fonts in order to
0120         * cover a large range of characters.
0121         * <p>
0122         * Peered AWT components, such as {@link Label Label} and
0123         * {@link TextField TextField}, can only use logical fonts.
0124         * <p>
0125         * For a discussion of the relative advantages and disadvantages of using
0126         * physical or logical fonts, see the
0127         * <a href="http://java.sun.com/j2se/corejava/intl/reference/faqs/index.html#desktop-rendering">Internationalization FAQ</a>
0128         * document.
0129         *
0130         * <h4>Font Faces and Names</h4>
0131         * 
0132         * A <code>Font</code> 
0133         * can have many faces, such as heavy, medium, oblique, gothic and
0134         * regular. All of these faces have similar typographic design.
0135         * <p>
0136         * There are three different names that you can get from a 
0137         * <code>Font</code> object.  The <em>logical font name</em> is simply the
0138         * name that was used to construct the font.
0139         * The <em>font face name</em>, or just <em>font name</em> for
0140         * short, is the name of a particular font face, like Helvetica Bold. The
0141         * <em>family name</em> is the name of the font family that determines the
0142         * typographic design across several faces, like Helvetica.
0143         * <p>
0144         * The <code>Font</code> class represents an instance of a font face from
0145         * a collection of  font faces that are present in the system resources
0146         * of the host system.  As examples, Arial Bold and Courier Bold Italic
0147         * are font faces.  There can be several <code>Font</code> objects
0148         * associated with a font face, each differing in size, style, transform
0149         * and font features.
0150         * <p>
0151         * The {@link GraphicsEnvironment#getAllFonts() getAllFonts} method 
0152         * of the <code>GraphicsEnvironment</code> class returns an
0153         * array of all font faces available in the system. These font faces are
0154         * returned as <code>Font</code> objects with a size of 1, identity
0155         * transform and default font features. These
0156         * base fonts can then be used to derive new <code>Font</code> objects
0157         * with varying sizes, styles, transforms and font features via the
0158         * <code>deriveFont</code> methods in this class.
0159         *
0160         * <h4>Font and TextAttribute</h4>
0161         *
0162         * <p><code>Font</code> supports most 
0163         * <code>TextAttribute</code>s.  This makes some operations, such as
0164         * rendering underlined text, convenient since it is not 
0165         * necessary to explicitly construct a <code>TextLayout</code> object.  
0166         * Attributes can be set on a Font by constructing or deriving it 
0167         * using a <code>Map</code> of <code>TextAttribute</code> values.
0168         *
0169         * <p>The values of some <code>TextAttributes</code> are not
0170         * serializable, and therefore attempting to serialize an instance of
0171         * <code>Font</code> that has such values will not serialize them.
0172         * This means a Font deserialized from such a stream will not compare
0173         * equal to the original Font that contained the non-serializable
0174         * attributes.  This should very rarely pose a problem
0175         * since these attributes are typically used only in special
0176         * circumstances and are unlikely to be serialized.
0177         *
0178         * <ul>
0179         * <li><code>FOREGROUND</code> and <code>BACKGROUND</code> use 
0180         * <code>Paint</code> values. The subclass <code>Color</code> is 
0181         * serializable, while <code>GradientPaint</code> and
0182         * <code>TexturePaint</code> are not.</li>
0183         * <li><code>CHAR_REPLACEMENT</code> uses 
0184         * <code>GraphicAttribute</code> values.  The subclasses 
0185         * <code>ShapeGraphicAttribute</code> and 
0186         * <code>ImageGraphicAttribute</code> are not serializable.</li>
0187         * <li><code>INPUT_METHOD_HIGHLIGHT</code> uses 
0188         * <code>InputMethodHighlight</code> values, which are
0189         * not serializable.  See {@link java.awt.im.InputMethodHighlight}.</li>
0190         * </ul>
0191         *
0192         * Clients who create custom subclasses of <code>Paint</code> and
0193         * <code>GraphicAttribute</code> can make them serializable and 
0194         * avoid this problem.  Clients who use input method highlights can
0195         * convert these to the platform-specific attributes for that 
0196         * highlight on the current platform and set them on the Font as
0197         * a workaround.</p>
0198         *
0199         * <p>The <code>Map</code>-based constructor and
0200         * <code>deriveFont</code> APIs ignore the FONT attribute, and it is
0201         * not retained by the Font; the static {@link #getFont} method should
0202         * be used if the FONT attribute might be present.  See {@link
0203         * java.awt.font.TextAttribute#FONT} for more information.</p>
0204         *
0205         * <p>Several attributes will cause additional rendering overhead
0206         * and potentially invoke layout.  If a <code>Font</code> has such 
0207         * attributes, the <code>{@link #hasLayoutAttributes()}</code> method 
0208         * will return true.</p>
0209         *
0210         * <p>Note: Font rotations can cause text baselines to be rotated.  In
0211         * order to account for this (rare) possibility, font APIs are
0212         * specified to return metrics and take parameters 'in
0213         * baseline-relative coordinates'.  This maps the 'x' coordinate to
0214         * the advance along the baseline, (positive x is forward along the
0215         * baseline), and the 'y' coordinate to a distance along the
0216         * perpendicular to the baseline at 'x' (positive y is 90 degrees
0217         * clockwise from the baseline vector).  APIs for which this is
0218         * especially important are called out as having 'baseline-relative
0219         * coordinates.'
0220         */
0221        public class Font implements  java.io.Serializable {
0222            static {
0223                /* ensure that the necessary native libraries are loaded */
0224                Toolkit.loadLibraries();
0225                initIDs();
0226            }
0227
0228            /**
0229             * This is now only used during serialization.  Typically
0230             * it is null.
0231             *
0232             * @serial
0233             * @see #getAttributes()
0234             */
0235            private Hashtable fRequestedAttributes;
0236
0237            /*
0238             * Constants to be used for logical font family names.
0239             */
0240
0241            /**
0242             * A String constant for the canonical family name of the
0243             * logical font "Dialog". It is useful in Font construction
0244             * to provide compile-time verification of the name.
0245             * @since 1.6
0246             */
0247            public static final String DIALOG = "Dialog";
0248
0249            /**
0250             * A String constant for the canonical family name of the
0251             * logical font "DialogInput". It is useful in Font construction
0252             * to provide compile-time verification of the name.
0253             * @since 1.6
0254             */
0255            public static final String DIALOG_INPUT = "DialogInput";
0256
0257            /**
0258             * A String constant for the canonical family name of the
0259             * logical font "SansSerif". It is useful in Font construction
0260             * to provide compile-time verification of the name.
0261             * @since 1.6
0262             */
0263            public static final String SANS_SERIF = "SansSerif";
0264
0265            /**
0266             * A String constant for the canonical family name of the
0267             * logical font "Serif". It is useful in Font construction
0268             * to provide compile-time verification of the name.
0269             * @since 1.6
0270             */
0271            public static final String SERIF = "Serif";
0272
0273            /**
0274             * A String constant for the canonical family name of the
0275             * logical font "Monospaced". It is useful in Font construction
0276             * to provide compile-time verification of the name.
0277             * @since 1.6
0278             */
0279            public static final String MONOSPACED = "Monospaced";
0280
0281            /*
0282             * Constants to be used for styles. Can be combined to mix
0283             * styles.
0284             */
0285
0286            /**
0287             * The plain style constant.
0288             */
0289            public static final int PLAIN = 0;
0290
0291            /**
0292             * The bold style constant.  This can be combined with the other style
0293             * constants (except PLAIN) for mixed styles.
0294             */
0295            public static final int BOLD = 1;
0296
0297            /**
0298             * The italicized style constant.  This can be combined with the other
0299             * style constants (except PLAIN) for mixed styles.
0300             */
0301            public static final int ITALIC = 2;
0302
0303            /**
0304             * The baseline used in most Roman scripts when laying out text.
0305             */
0306            public static final int ROMAN_BASELINE = 0;
0307
0308            /**
0309             * The baseline used in ideographic scripts like Chinese, Japanese,
0310             * and Korean when laying out text.
0311             */
0312            public static final int CENTER_BASELINE = 1;
0313
0314            /**
0315             * The baseline used in Devanigiri and similar scripts when laying
0316             * out text.
0317             */
0318            public static final int HANGING_BASELINE = 2;
0319
0320            /**
0321             * Identify a font resource of type TRUETYPE.
0322             * Used to specify a TrueType font resource to the
0323             * {@link #createFont} method.
0324             * @since 1.3
0325             */
0326
0327            public static final int TRUETYPE_FONT = 0;
0328
0329            /**
0330             * Identify a font resource of type TYPE1.
0331             * Used to specify a Type1 font resource to the
0332             * {@link #createFont} method.
0333             * @since 1.5
0334             */
0335            public static final int TYPE1_FONT = 1;
0336
0337            /**
0338             * The logical name of this <code>Font</code>, as passed to the
0339             * constructor.
0340             * @since JDK1.0
0341             *
0342             * @serial
0343             * @see #getName
0344             */
0345            protected String name;
0346
0347            /**
0348             * The style of this <code>Font</code>, as passed to the constructor.
0349             * This style can be PLAIN, BOLD, ITALIC, or BOLD+ITALIC.
0350             * @since JDK1.0
0351             *
0352             * @serial
0353             * @see #getStyle()
0354             */
0355            protected int style;
0356
0357            /**
0358             * The point size of this <code>Font</code>, rounded to integer.
0359             * @since JDK1.0
0360             *
0361             * @serial
0362             * @see #getSize()
0363             */
0364            protected int size;
0365
0366            /**
0367             * The point size of this <code>Font</code> in <code>float</code>.
0368             *
0369             * @serial
0370             * @see #getSize()
0371             * @see #getSize2D()
0372             */
0373            protected float pointSize;
0374
0375            /**
0376             * The platform specific font information.
0377             */
0378            private transient FontPeer peer;
0379            private transient long pData; // native JDK1.1 font pointer
0380            private transient Font2DHandle font2DHandle;
0381
0382            private transient AttributeValues values;
0383            private transient boolean hasLayoutAttributes;
0384
0385            /*
0386             * If the origin of a Font is a created font then this attribute
0387             * must be set on all derived fonts too.
0388             */
0389            private transient boolean createdFont = false;
0390
0391            /*
0392             * This is true if the font transform is not identity.  It
0393             * is used to avoid unnecessary instantiation of an AffineTransform.
0394             */
0395            private transient boolean nonIdentityTx;
0396
0397            /*
0398             * A cached value used when a transform is required for internal
0399             * use.  This must not be exposed to callers since AffineTransform
0400             * is mutable.
0401             */
0402            private static final AffineTransform identityTx = new AffineTransform();
0403
0404            /*
0405             * JDK 1.1 serialVersionUID
0406             */
0407            private static final long serialVersionUID = -4206021311591459213L;
0408
0409            /**
0410             * Gets the peer of this <code>Font</code>.
0411             * @return  the peer of the <code>Font</code>.
0412             * @since JDK1.1
0413             * @deprecated Font rendering is now platform independent.
0414             */
0415            @Deprecated
0416            public FontPeer getPeer() {
0417                return getPeer_NoClientCode();
0418            }
0419
0420            // NOTE: This method is called by privileged threads.
0421            //       We implement this functionality in a package-private method 
0422            //       to insure that it cannot be overridden by client subclasses. 
0423            //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
0424            final FontPeer getPeer_NoClientCode() {
0425                if (peer == null) {
0426                    Toolkit tk = Toolkit.getDefaultToolkit();
0427                    this .peer = tk.getFontPeer(name, style);
0428                }
0429                return peer;
0430            }
0431
0432            /**
0433             * Return the AttributeValues object associated with this
0434             * font.  Most of the time, the internal object is null.
0435             * If required, it will be created from the 'standard'
0436             * state on the font.  Only non-default values will be
0437             * set in the AttributeValues object.
0438             *
0439             * <p>Since the AttributeValues object is mutable, and it
0440             * is cached in the font, care must be taken to ensure that
0441             * it is not mutated.
0442             */
0443            private AttributeValues getAttributeValues() {
0444                if (values == null) {
0445                    values = new AttributeValues();
0446                    values.setFamily(name);
0447                    values.setSize(pointSize); // expects the float value.
0448
0449                    if ((style & BOLD) != 0) {
0450                        values.setWeight(2); // WEIGHT_BOLD
0451                    }
0452
0453                    if ((style & ITALIC) != 0) {
0454                        values.setPosture(.2f); // POSTURE_OBLIQUE
0455                    }
0456                    values.defineAll(PRIMARY_MASK); // for streaming compatibility
0457                }
0458
0459                return values;
0460            }
0461
0462            private Font2D getFont2D() {
0463                if (FontManager.usingPerAppContextComposites
0464                        && font2DHandle != null
0465                        && font2DHandle.font2D instanceof  CompositeFont
0466                        && ((CompositeFont) (font2DHandle.font2D))
0467                                .isStdComposite()) {
0468                    return FontManager.findFont2D(name, style,
0469                            FontManager.LOGICAL_FALLBACK);
0470                } else if (font2DHandle == null) {
0471                    font2DHandle = FontManager.findFont2D(name, style,
0472                            FontManager.LOGICAL_FALLBACK).handle;
0473                }
0474                /* Do not cache the de-referenced font2D. It must be explicitly
0475                 * de-referenced to pick up a valid font in the event that the
0476                 * original one is marked invalid
0477                 */
0478                return font2DHandle.font2D;
0479            }
0480
0481            /**
0482             * Creates a new <code>Font</code> from the specified name, style and
0483             * point size.
0484             * <p>
0485             * The font name can be a font face name or a font family name.
0486             * It is used together with the style to find an appropriate font face.
0487             * When a font family name is specified, the style argument is used to
0488             * select the most appropriate face from the family. When a font face
0489             * name is specified, the face's style and the style argument are
0490             * merged to locate the best matching font from the same family.
0491             * For example if face name "Arial Bold" is specified with style
0492             * <code>Font.ITALIC</code>, the font system looks for a face in the
0493             * "Arial" family that is bold and italic, and may associate the font
0494             * instance with the physical font face "Arial Bold Italic".
0495             * The style argument is merged with the specified face's style, not
0496             * added or subtracted.
0497             * This means, specifying a bold face and a bold style does not
0498             * double-embolden the font, and specifying a bold face and a plain
0499             * style does not lighten the font.
0500             * <p>
0501             * If no face for the requested style can be found, the font system
0502             * may apply algorithmic styling to achieve the desired style.
0503             * For example, if <code>ITALIC</code> is requested, but no italic
0504             * face is available, glyphs from the plain face may be algorithmically
0505             * obliqued (slanted).
0506             * <p>
0507             * Font name lookup is case insensitive, using the case folding
0508             * rules of the US locale.
0509             * <p>
0510             * If the <code>name</code> parameter represents something other than a
0511             * logical font, i.e. is interpreted as a physical font face or family, and
0512             * this cannot be mapped by the implementation to a physical font or a
0513             * compatible alternative, then the font system will map the Font
0514             * instance to "Dialog", such that for example, the family as reported
0515             * by {@link #getFamily() getFamily} will be "Dialog".
0516             * <p>
0517             *
0518             * @param name the font name.  This can be a font face name or a font
0519             * family name, and may represent either a logical font or a physical
0520             * font found in this {@code GraphicsEnvironment}.
0521             * The family names for logical fonts are: Dialog, DialogInput,
0522             * Monospaced, Serif, or SansSerif. Pre-defined String constants exist
0523             * for all of these names, for example, {@code DIALOG}. If {@code name} is
0524             * {@code null}, the <em>logical font name</em> of the new
0525             * {@code Font} as returned by {@code getName()} is set to
0526             * the name "Default".
0527             * @param style the style constant for the {@code Font}
0528             * The style argument is an integer bitmask that may
0529             * be {@code PLAIN}, or a bitwise union of {@code BOLD} and/or
0530             * {@code ITALIC} (for example, {@code ITALIC} or {@code BOLD|ITALIC}).
0531             * If the style argument does not conform to one of the expected
0532             * integer bitmasks then the style is set to {@code PLAIN}.
0533             * @param size the point size of the {@code Font}
0534             * @see GraphicsEnvironment#getAllFonts
0535             * @see GraphicsEnvironment#getAvailableFontFamilyNames
0536             * @since JDK1.0
0537             */
0538            public Font(String name, int style, int size) {
0539                this .name = (name != null) ? name : "Default";
0540                this .style = (style & ~0x03) == 0 ? style : 0;
0541                this .size = size;
0542                this .pointSize = size;
0543            }
0544
0545            private Font(String name, int style, float sizePts) {
0546                this .name = (name != null) ? name : "Default";
0547                this .style = (style & ~0x03) == 0 ? style : 0;
0548                this .size = (int) (sizePts + 0.5);
0549                this .pointSize = sizePts;
0550            }
0551
0552            /* This constructor is used by deriveFont when attributes is null */
0553            private Font(String name, int style, float sizePts,
0554                    boolean created, Font2DHandle handle) {
0555                this (name, style, sizePts);
0556                this .createdFont = created;
0557                /* Fonts created from a stream will use the same font2D instance
0558                 * as the parent.
0559                 * One exception is that if the derived font is requested to be
0560                 * in a different style, then also check if its a CompositeFont
0561                 * and if so build a new CompositeFont from components of that style.
0562                 * CompositeFonts can only be marked as "created" if they are used
0563                 * to add fall backs to a physical font. And non-composites are
0564                 * always from "Font.createFont()" and shouldn't get this treatment.
0565                 */
0566                if (created) {
0567                    if (handle.font2D instanceof  CompositeFont
0568                            && handle.font2D.getStyle() != style) {
0569                        this .font2DHandle = FontManager.getNewComposite(null,
0570                                style, handle);
0571                    } else {
0572                        this .font2DHandle = handle;
0573                    }
0574                }
0575            }
0576
0577            /* used to implement Font.createFont */
0578            private Font(File fontFile, int fontFormat, boolean isCopy)
0579                    throws FontFormatException {
0580                this .createdFont = true;
0581                /* Font2D instances created by this method track their font file
0582                 * so that when the Font2D is GC'd it can also remove the file.
0583                 */
0584                this .font2DHandle = FontManager.createFont2D(fontFile,
0585                        fontFormat, isCopy).handle;
0586                this .name = this .font2DHandle.font2D.getFontName(Locale
0587                        .getDefault());
0588                this .style = Font.PLAIN;
0589                this .size = 1;
0590                this .pointSize = 1f;
0591            }
0592
0593            /* This constructor is used when one font is derived from another.
0594             * Fonts created from a stream will use the same font2D instance as the
0595             * parent. They can be distinguished because the "created" argument
0596             * will be "true". Since there is no way to recreate these fonts they
0597             * need to have the handle to the underlying font2D passed in.
0598             * "created" is also true when a special composite is referenced by the
0599             * handle for essentially the same reasons.
0600             * But when deriving a font in these cases two particular attributes
0601             * need special attention: family/face and style.
0602             * The "composites" in these cases need to be recreated with optimal
0603             * fonts for the new values of family and style.
0604             * For fonts created with createFont() these are treated differently.
0605             * JDK can often synthesise a different style (bold from plain
0606             * for example). For fonts created with "createFont" this is a reasonable
0607             * solution but its also possible (although rare) to derive a font with a
0608             * different family attribute. In this case JDK needs
0609             * to break the tie with the original Font2D and find a new Font.
0610             * The oldName and oldStyle are supplied so they can be compared with
0611             * what the Font2D and the values. To speed things along :
0612             * oldName == null will be interpreted as the name is unchanged.
0613             * oldStyle = -1 will be interpreted as the style is unchanged.
0614             * In these cases there is no need to interrogate "values".
0615             */
0616            private Font(AttributeValues values, String oldName, int oldStyle,
0617                    boolean created, Font2DHandle handle) {
0618
0619                this .createdFont = created;
0620                if (created) {
0621                    this .font2DHandle = handle;
0622
0623                    String newName = null;
0624                    if (oldName != null) {
0625                        newName = values.getFamily();
0626                        if (oldName.equals(newName))
0627                            newName = null;
0628                    }
0629                    int newStyle = 0;
0630                    if (oldStyle == -1) {
0631                        newStyle = -1;
0632                    } else {
0633                        if (values.getWeight() >= 2f)
0634                            newStyle = BOLD;
0635                        if (values.getPosture() >= .2f)
0636                            newStyle |= ITALIC;
0637                        if (oldStyle == newStyle)
0638                            newStyle = -1;
0639                    }
0640                    if (handle.font2D instanceof  CompositeFont) {
0641                        if (newStyle != -1 || newName != null) {
0642                            this .font2DHandle = FontManager.getNewComposite(
0643                                    newName, newStyle, handle);
0644                        }
0645                    } else if (newName != null) {
0646                        this .createdFont = false;
0647                        this .font2DHandle = null;
0648                    }
0649                }
0650                initFromValues(values);
0651            }
0652
0653            /**
0654             * Creates a new <code>Font</code> with the specified attributes.
0655             * Only keys defined in {@link java.awt.font.TextAttribute TextAttribute} 
0656             * are recognized.  In addition the FONT attribute is
0657             *  not recognized by this constructor 
0658             * (see {@link #getAvailableAttributes}). Only attributes that have 
0659             * values of valid types will affect the new <code>Font</code>.
0660             * <p>
0661             * If <code>attributes</code> is <code>null</code>, a new 
0662             * <code>Font</code> is initialized with default values.
0663             * @see java.awt.font.TextAttribute
0664             * @param attributes the attributes to assign to the new
0665             *          <code>Font</code>, or <code>null</code>
0666             */
0667            public Font(Map<? extends Attribute, ?> attributes) {
0668                initFromValues(AttributeValues.fromMap(attributes,
0669                        RECOGNIZED_MASK));
0670            }
0671
0672            /**
0673             * Creates a new <code>Font</code> from the specified <code>font</code>.
0674             * This constructor is intended for use by subclasses.
0675             * @param font from which to create this <code>Font</code>.
0676             * @throws NullPointerException if <code>font</code> is null
0677             * @since 1.6
0678             */
0679            protected Font(Font font) {
0680                if (font.values != null) {
0681                    initFromValues(font.getAttributeValues().clone());
0682                } else {
0683                    this .name = font.name;
0684                    this .style = font.style;
0685                    this .size = font.size;
0686                    this .pointSize = font.pointSize;
0687                }
0688                this .font2DHandle = font.font2DHandle;
0689                this .createdFont = font.createdFont;
0690            }
0691
0692            /**
0693             * Font recognizes all attributes except FONT.
0694             */
0695            private static final int RECOGNIZED_MASK = AttributeValues.MASK_ALL
0696                    & ~AttributeValues.getMask(EFONT);
0697
0698            /**
0699             * These attributes are considered primary by the FONT attribute.
0700             */
0701            private static final int PRIMARY_MASK = AttributeValues.getMask(
0702                    EFAMILY, EWEIGHT, EWIDTH, EPOSTURE, ESIZE, ETRANSFORM,
0703                    ESUPERSCRIPT, ETRACKING);
0704
0705            /**
0706             * These attributes are considered secondary by the FONT attribute.
0707             */
0708            private static final int SECONDARY_MASK = RECOGNIZED_MASK
0709                    & ~PRIMARY_MASK;
0710
0711            /**
0712             * These attributes are handled by layout.
0713             */
0714            private static final int LAYOUT_MASK = AttributeValues.getMask(
0715                    ECHAR_REPLACEMENT, EFOREGROUND, EBACKGROUND, EUNDERLINE,
0716                    ESTRIKETHROUGH, ERUN_DIRECTION, EBIDI_EMBEDDING,
0717                    EJUSTIFICATION, EINPUT_METHOD_HIGHLIGHT,
0718                    EINPUT_METHOD_UNDERLINE, ESWAP_COLORS, ENUMERIC_SHAPING,
0719                    EKERNING, ELIGATURES, ETRACKING);
0720
0721            private static final int EXTRA_MASK = AttributeValues.getMask(
0722                    ETRANSFORM, ESUPERSCRIPT, EWIDTH);
0723
0724            /**
0725             * Initialize the standard Font fields from the values object.
0726             */
0727            private void initFromValues(AttributeValues values) {
0728                this .values = values;
0729                values.defineAll(PRIMARY_MASK); // for 1.5 streaming compatibility
0730
0731                this .name = values.getFamily();
0732                this .pointSize = values.getSize();
0733                this .size = (int) (values.getSize() + 0.5);
0734                if (values.getWeight() >= 2f)
0735                    this .style |= BOLD; // not == 2f
0736                if (values.getPosture() >= .2f)
0737                    this .style |= ITALIC; // not  == .2f
0738
0739                this .nonIdentityTx = values.anyNonDefault(EXTRA_MASK);
0740                this .hasLayoutAttributes = values.anyNonDefault(LAYOUT_MASK);
0741            }
0742
0743            /**
0744             * Returns a <code>Font</code> appropriate to the attributes.
0745             * If <code>attributes</code>contains a <code>FONT</code> attribute
0746             * with a valid <code>Font</code> as its value, it will be 
0747             * merged with any remaining attributes.  See 
0748             * {@link java.awt.font.TextAttribute#FONT} for more
0749             * information.
0750             *
0751             * @param attributes the attributes to assign to the new 
0752             *          <code>Font</code>
0753             * @return a new <code>Font</code> created with the specified
0754             *          attributes
0755             * @throws NullPointerException if <code>attributes</code> is null.
0756             * @since 1.2
0757             * @see java.awt.font.TextAttribute
0758             */
0759            public static Font getFont(Map<? extends Attribute, ?> attributes) {
0760                // optimize for two cases:
0761                // 1) FONT attribute, and nothing else
0762                // 2) attributes, but no FONT
0763
0764                // avoid turning the attributemap into a regular map for no reason
0765                if (attributes instanceof  AttributeMap
0766                        && ((AttributeMap) attributes).getValues() != null) {
0767                    AttributeValues values = ((AttributeMap) attributes)
0768                            .getValues();
0769                    if (values.isNonDefault(EFONT)) {
0770                        Font font = values.getFont();
0771                        if (!values.anyDefined(SECONDARY_MASK)) {
0772                            return font;
0773                        }
0774                        // merge
0775                        values = font.getAttributeValues().clone();
0776                        values.merge(attributes, SECONDARY_MASK);
0777                        return new Font(values, font.name, font.style,
0778                                font.createdFont, font.font2DHandle);
0779                    }
0780                    return new Font(attributes);
0781                }
0782
0783                Font font = (Font) attributes.get(TextAttribute.FONT);
0784                if (font != null) {
0785                    if (attributes.size() > 1) { // oh well, check for anything else
0786                        AttributeValues values = font.getAttributeValues()
0787                                .clone();
0788                        values.merge(attributes, SECONDARY_MASK);
0789                        return new Font(values, font.name, font.style,
0790                                font.createdFont, font.font2DHandle);
0791                    }
0792
0793                    return font;
0794                }
0795
0796                return new Font(attributes);
0797            }
0798
0799            /**
0800             * Returns a new <code>Font</code> using the specified font type
0801             * and input data.  The new <code>Font</code> is
0802             * created with a point size of 1 and style {@link #PLAIN PLAIN}.
0803             * This base font can then be used with the <code>deriveFont</code>
0804             * methods in this class to derive new <code>Font</code> objects with
0805             * varying sizes, styles, transforms and font features.  This
0806             * method does not close the {@link InputStream}.
0807             * <p>
0808             * To make the <code>Font</code> available to Font constructors the
0809             * returned <code>Font</code> must be registered in the
0810             * <code>GraphicsEnviroment</code> by calling
0811             * {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}.
0812             * @param fontFormat the type of the <code>Font</code>, which is
0813             * {@link #TRUETYPE_FONT TRUETYPE_FONT} if a TrueType resource is specified.
0814             * or {@link #TYPE1_FONT TYPE1_FONT} if a Type 1 resource is specified.
0815             * @param fontStream an <code>InputStream</code> object representing the
0816             * input data for the font.
0817             * @return a new <code>Font</code> created with the specified font type.
0818             * @throws IllegalArgumentException if <code>fontFormat</code> is not
0819             *     <code>TRUETYPE_FONT</code>or<code>TYPE1_FONT</code>.
0820             * @throws FontFormatException if the <code>fontStream</code> data does
0821             *     not contain the required font tables for the specified format.
0822             * @throws IOException if the <code>fontStream</code>
0823             *     cannot be completely read.
0824             * @see GraphicsEnvironment#registerFont(Font)
0825             * @since 1.3
0826             */
0827            public static Font createFont(int fontFormat, InputStream fontStream)
0828                    throws java.awt.FontFormatException, java.io.IOException {
0829
0830                if (fontFormat != Font.TRUETYPE_FONT
0831                        && fontFormat != Font.TYPE1_FONT) {
0832                    throw new IllegalArgumentException(
0833                            "font format not recognized");
0834                }
0835                final InputStream fStream = fontStream;
0836                Object ret = java.security.AccessController
0837                        .doPrivileged(new java.security.PrivilegedAction() {
0838                            public Object run() {
0839                                File tFile = null;
0840                                FileOutputStream outStream = null;
0841                                try {
0842                                    tFile = File.createTempFile("+~JF", ".tmp",
0843                                            null);
0844                                    /* Temp file deleted by font shutdown hook */
0845                                    BufferedInputStream inStream = new BufferedInputStream(
0846                                            fStream);
0847                                    outStream = new FileOutputStream(tFile);
0848                                    int bytesRead = 0;
0849                                    int bufSize = 8192;
0850                                    byte[] buf = new byte[bufSize];
0851                                    while (bytesRead != -1) {
0852                                        try {
0853                                            bytesRead = inStream.read(buf, 0,
0854                                                    bufSize);
0855                                        } catch (Throwable t) {
0856                                            throw new IOException();
0857                                        }
0858                                        if (bytesRead != -1) {
0859                                            outStream.write(buf, 0, bytesRead);
0860                                        }
0861                                    }
0862                                    /* don't close the input stream */
0863                                    outStream.close();
0864                                } catch (IOException e) {
0865                                    if (outStream != null) {
0866                                        try {
0867                                            outStream.close();
0868                                        } catch (Exception e1) {
0869                                        }
0870                                    }
0871                                    if (tFile != null) {
0872                                        try {
0873                                            tFile.delete();
0874                                        } catch (Exception e2) {
0875                                        }
0876                                    }
0877                                    return e;
0878                                }
0879                                return tFile;
0880                            }
0881                        });
0882
0883                if (ret instanceof  File) {
0884                    return new Font((File) ret, fontFormat, true);
0885                } else if (ret instanceof  IOException) {
0886                    throw (IOException) ret;
0887                } else {
0888                    throw new FontFormatException("Couldn't access font stream");
0889                }
0890            }
0891
0892            /**
0893             * Returns a new <code>Font</code> using the specified font type
0894             * and the specified font file.  The new <code>Font</code> is
0895             * created with a point size of 1 and style {@link #PLAIN PLAIN}.
0896             * This base font can then be used with the <code>deriveFont</code>
0897             * methods in this class to derive new <code>Font</code> objects with
0898             * varying sizes, styles, transforms and font features.
0899             * @param fontFormat the type of the <code>Font</code>, which is
0900             * {@link #TRUETYPE_FONT TRUETYPE_FONT} if a TrueType resource is
0901             * specified or {@link #TYPE1_FONT TYPE1_FONT} if a Type 1 resource is
0902             * specified.
0903             * So long as the returned font, or its derived fonts are referenced
0904             * the implementation may continue to access <code>fontFile</code>
0905             * to retrieve font data. Thus the results are undefined if the file
0906             * is changed, or becomes inaccessible.
0907             * <p>
0908             * To make the <code>Font</code> available to Font constructors the
0909             * returned <code>Font</code> must be registered in the
0910             * <code>GraphicsEnviroment</code> by calling
0911             * {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}.
0912             * @param fontFile a <code>File</code> object representing the
0913             * input data for the font.
0914             * @return a new <code>Font</code> created with the specified font type.
0915             * @throws IllegalArgumentException if <code>fontFormat</code> is not
0916             *     <code>TRUETYPE_FONT</code>or<code>TYPE1_FONT</code>.
0917             * @throws NullPointerException if <code>fontFile</code> is null.
0918             * @throws IOException if the <code>fontFile</code> cannot be read.
0919             * @throws FontFormatException if <code>fontFile</code> does
0920             *     not contain the required font tables for the specified format.
0921             * @throws SecurityException if the executing code does not have
0922             * permission to read from the file.
0923             * @see GraphicsEnvironment#registerFont(Font)
0924             * @since 1.5
0925             */
0926            public static Font createFont(int fontFormat, File fontFile)
0927                    throws java.awt.FontFormatException, java.io.IOException {
0928                if (fontFormat != Font.TRUETYPE_FONT
0929                        && fontFormat != Font.TYPE1_FONT) {
0930                    throw new IllegalArgumentException(
0931                            "font format not recognized");
0932                }
0933                SecurityManager sm = System.getSecurityManager();
0934                if (sm != null) {
0935                    FilePermission filePermission = new FilePermission(fontFile
0936                            .getPath(), "read");
0937                    sm.checkPermission(filePermission);
0938                }
0939                if (!fontFile.canRead()) {
0940                    throw new IOException("Can't read " + fontFile);
0941                }
0942                return new Font(fontFile, fontFormat, false);
0943            }
0944
0945            /**
0946             * Returns a copy of the transform associated with this 
0947             * <code>Font</code>.  This transform is not necessarily the one
0948             * used to construct the font.  If the font has algorithmic
0949             * superscripting or width adjustment, this will be incorporated
0950             * into the returned <code>AffineTransform</code>.
0951             * <p>
0952             * Typically, fonts will not be transformed.  Clients generally
0953             * should call {@link #isTransformed} first, and only call this
0954             * method if <code>isTransformed</code> returns true.
0955             *
0956             * @return an {@link AffineTransform} object representing the
0957             *          transform attribute of this <code>Font</code> object.
0958             */
0959            public AffineTransform getTransform() {
0960                /* The most common case is the identity transform.  Most callers 
0961                 * should call isTransformed() first, to decide if they need to
0962                 * get the transform, but some may not.  Here we check to see
0963                 * if we have a nonidentity transform, and only do the work to
0964                 * fetch and/or compute it if so, otherwise we return a new
0965                 * identity transform.
0966                 *
0967                 * Note that the transform is _not_ necessarily the same as 
0968                 * the transform passed in as an Attribute in a Map, as the
0969                 * transform returned will also reflect the effects of WIDTH and
0970                 * SUPERSCRIPT attributes.  Clients who want the actual transform
0971                 * need to call getRequestedAttributes.
0972                 */
0973                if (nonIdentityTx) {
0974                    AttributeValues values = getAttributeValues();
0975
0976                    AffineTransform at = values.isNonDefault(ETRANSFORM) ? new AffineTransform(
0977                            values.getTransform())
0978                            : new AffineTransform();
0979
0980                    if (values.getSuperscript() != 0) {
0981                        // can't get ascent and descent here, recursive call to this fn, 
0982                        // so use pointsize
0983                        // let users combine super- and sub-scripting
0984
0985                        int super script = values.getSuperscript();
0986
0987                        double trans = 0;
0988                        int n = 0;
0989                        boolean up = super script > 0;
0990                        int sign = up ? -1 : 1;
0991                        int ss = up ? super script : -super script;
0992
0993                        while ((ss & 7) > n) {
0994                            int newn = ss & 7;
0995                            trans += sign * (ssinfo[newn] - ssinfo[n]);
0996                            ss >>= 3;
0997                            sign = -sign;
0998                            n = newn;
0999                        }
1000                        trans *= pointSize;
1001                        double scale = Math.pow(2. / 3., n);
1002
1003                        at.preConcatenate(AffineTransform.getTranslateInstance(
1004                                0, trans));
1005                        at.scale(scale, scale);
1006
1007                        // note on placement and italics
1008                        // We preconcatenate the transform because we don't want to translate along
1009                        // the italic angle, but purely perpendicular to the baseline.  While this
1010                        // looks ok for superscripts, it can lead subscripts to stack on each other
1011                        // and bring the following text too close.  The way we deal with potential
1012                        // collisions that can occur in the case of italics is by adjusting the
1013                        // horizontal spacing of the adjacent glyphvectors.  Examine the italic
1014                        // angle of both vectors, if one is non-zero, compute the minimum ascent
1015                        // and descent, and then the x position at each for each vector along its
1016                        // italic angle starting from its (offset) baseline.  Compute the difference
1017                        // between the x positions and use the maximum difference to adjust the
1018                        // position of the right gv.
1019                    }
1020
1021                    if (values.isNonDefault(EWIDTH)) {
1022                        at.scale(values.getWidth(), 1f);
1023                    }
1024
1025                    return at;
1026                }
1027
1028                return new AffineTransform();
1029            }
1030
1031            // x = r^0 + r^1 + r^2... r^n
1032            // rx = r^1 + r^2 + r^3... r^(n+1)
1033            // x - rx = r^0 - r^(n+1)
1034            // x (1 - r) = r^0 - r^(n+1)
1035            // x = (r^0 - r^(n+1)) / (1 - r)
1036            // x = (1 - r^(n+1)) / (1 - r)
1037
1038            // scale ratio is 2/3
1039            // trans = 1/2 of ascent * x
1040            // assume ascent is 3/4 of point size
1041
1042            private static final float[] ssinfo = { 0.0f, 0.375f, 0.625f,
1043                    0.7916667f, 0.9027778f, 0.9768519f, 1.0262346f, 1.0591564f, };
1044
1045            /**
1046             * Returns the family name of this <code>Font</code>.  
1047             * 
1048             * <p>The family name of a font is font specific. Two fonts such as 
1049             * Helvetica Italic and Helvetica Bold have the same family name, 
1050             * <i>Helvetica</i>, whereas their font face names are 
1051             * <i>Helvetica Bold</i> and <i>Helvetica Italic</i>. The list of 
1052             * available family names may be obtained by using the 
1053             * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
1054             * 
1055             * <p>Use <code>getName</code> to get the logical name of the font.
1056             * Use <code>getFontName</code> to get the font face name of the font.
1057             * @return a <code>String</code> that is the family name of this
1058             *          <code>Font</code>.
1059             * 
1060             * @see #getName
1061             * @see #getFontName
1062             * @since JDK1.1
1063             */
1064            public String getFamily() {
1065                return getFamily_NoClientCode();
1066            }
1067
1068            // NOTE: This method is called by privileged threads.
1069            //       We implement this functionality in a package-private
1070            //       method to insure that it cannot be overridden by client
1071            //       subclasses. 
1072            //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
1073            final String getFamily_NoClientCode() {
1074                return getFamily(Locale.getDefault());
1075            }
1076
1077            /**
1078             * Returns the family name of this <code>Font</code>, localized for
1079             * the specified locale.
1080             * 
1081             * <p>The family name of a font is font specific. Two fonts such as 
1082             * Helvetica Italic and Helvetica Bold have the same family name, 
1083             * <i>Helvetica</i>, whereas their font face names are 
1084             * <i>Helvetica Bold</i> and <i>Helvetica Italic</i>. The list of 
1085             * available family names may be obtained by using the 
1086             * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
1087             * 
1088             * <p>Use <code>getFontName</code> to get the font face name of the font.
1089             * @param l locale for which to get the family name
1090             * @return a <code>String</code> representing the family name of the
1091             *          font, localized for the specified locale.
1092             * @see #getFontName
1093             * @see java.util.Locale
1094             * @since 1.2
1095             */
1096            public String getFamily(Locale l) {
1097                if (l == null) {
1098                    throw new NullPointerException(
1099                            "null locale doesn't mean default");
1100                }
1101                return getFont2D().getFamilyName(l);
1102            }
1103
1104            /**
1105             * Returns the postscript name of this <code>Font</code>.
1106             * Use <code>getFamily</code> to get the family name of the font.
1107             * Use <code>getFontName</code> to get the font face name of the font.
1108             * @return a <code>String</code> representing the postscript name of
1109             *          this <code>Font</code>.
1110             * @since 1.2
1111             */
1112            public String getPSName() {
1113                return getFont2D().getPostscriptName();
1114            }
1115
1116            /**
1117             * Returns the logical name of this <code>Font</code>.
1118             * Use <code>getFamily</code> to get the family name of the font.
1119             * Use <code>getFontName</code> to get the font face name of the font.
1120             * @return a <code>String</code> representing the logical name of
1121             *          this <code>Font</code>.
1122             * @see #getFamily
1123             * @see #getFontName
1124             * @since JDK1.0
1125             */
1126            public String getName() {
1127                return name;
1128            }
1129
1130            /**
1131             * Returns the font face name of this <code>Font</code>.  For example,
1132             * Helvetica Bold could be returned as a font face name.
1133             * Use <code>getFamily</code> to get the family name of the font.
1134             * Use <code>getName</code> to get the logical name of the font.
1135             * @return a <code>String</code> representing the font face name of 
1136             *          this <code>Font</code>.
1137             * @see #getFamily
1138             * @see #getName
1139             * @since 1.2
1140             */
1141            public String getFontName() {
1142                return getFontName(Locale.getDefault());
1143            }
1144
1145            /**
1146             * Returns the font face name of the <code>Font</code>, localized
1147             * for the specified locale. For example, Helvetica Fett could be
1148             * returned as the font face name.
1149             * Use <code>getFamily</code> to get the family name of the font.
1150             * @param l a locale for which to get the font face name
1151             * @return a <code>String</code> representing the font face name,
1152             *          localized for the specified locale.
1153             * @see #getFamily
1154             * @see java.util.Locale
1155             */
1156            public String getFontName(Locale l) {
1157                if (l == null) {
1158                    throw new NullPointerException(
1159                            "null locale doesn't mean default");
1160                }
1161                return getFont2D().getFontName(l);
1162            }
1163
1164            /**
1165             * Returns the style of this <code>Font</code>.  The style can be
1166             * PLAIN, BOLD, ITALIC, or BOLD+ITALIC.
1167             * @return the style of this <code>Font</code>
1168             * @see #isPlain
1169             * @see #isBold
1170             * @see #isItalic
1171             * @since JDK1.0
1172             */
1173            public int getStyle() {
1174                return style;
1175            }
1176
1177            /**
1178             * Returns the point size of this <code>Font</code>, rounded to
1179             * an integer.
1180             * Most users are familiar with the idea of using <i>point size</i> to
1181             * specify the size of glyphs in a font. This point size defines a
1182             * measurement between the baseline of one line to the baseline of the
1183             * following line in a single spaced text document. The point size is
1184             * based on <i>typographic points</i>, approximately 1/72 of an inch.
1185             * <p>
1186             * The Java(tm)2D API adopts the convention that one point is
1187             * equivalent to one unit in user coordinates.  When using a
1188             * normalized transform for converting user space coordinates to
1189             * device space coordinates 72 user
1190             * space units equal 1 inch in device space.  In this case one point
1191             * is 1/72 of an inch.
1192             * @return the point size of this <code>Font</code> in 1/72 of an 
1193             *          inch units.
1194             * @see #getSize2D
1195             * @see GraphicsConfiguration#getDefaultTransform
1196             * @see GraphicsConfiguration#getNormalizingTransform
1197             * @since JDK1.0
1198             */
1199            public int getSize() {
1200                return size;
1201            }
1202
1203            /**
1204             * Returns the point size of this <code>Font</code> in
1205             * <code>float</code> value.
1206             * @return the point size of this <code>Font</code> as a
1207             * <code>float</code> value.
1208             * @see #getSize
1209             * @since 1.2
1210             */
1211            public float getSize2D() {
1212                return pointSize;
1213            }
1214
1215            /**
1216             * Indicates whether or not this <code>Font</code> object's style is
1217             * PLAIN.
1218             * @return    <code>true</code> if this <code>Font</code> has a
1219             *            PLAIN sytle;
1220             *            <code>false</code> otherwise.
1221             * @see       java.awt.Font#getStyle
1222             * @since     JDK1.0
1223             */
1224            public boolean isPlain() {
1225                return style == 0;
1226            }
1227
1228            /**
1229             * Indicates whether or not this <code>Font</code> object's style is
1230             * BOLD.
1231             * @return    <code>true</code> if this <code>Font</code> object's
1232             *            style is BOLD;
1233             *            <code>false</code> otherwise.
1234             * @see       java.awt.Font#getStyle
1235             * @since     JDK1.0
1236             */
1237            public boolean isBold() {
1238                return (style & BOLD) != 0;
1239            }
1240
1241            /**
1242             * Indicates whether or not this <code>Font</code> object's style is
1243             * ITALIC.
1244             * @return    <code>true</code> if this <code>Font</code> object's
1245             *            style is ITALIC;
1246             *            <code>false</code> otherwise.
1247             * @see       java.awt.Font#getStyle
1248             * @since     JDK1.0
1249             */
1250            public boolean isItalic() {
1251                return (style & ITALIC) != 0;
1252            }
1253
1254            /**
1255             * Indicates whether or not this <code>Font</code> object has a
1256             * transform that affects its size in addition to the Size
1257             * attribute.
1258             * @return  <code>true</code> if this <code>Font</code> object
1259             *          has a non-identity AffineTransform attribute.
1260             *          <code>false</code> otherwise.
1261             * @see     java.awt.Font#getTransform
1262             * @since   1.4
1263             */
1264            public boolean isTransformed() {
1265                return nonIdentityTx;
1266            }
1267
1268            /**
1269             * Return true if this Font contains attributes that require extra 
1270             * layout processing.
1271             * @return true if the font has layout attributes
1272             * @since 1.6
1273             */
1274            public boolean hasLayoutAttributes() {
1275                return hasLayoutAttributes;
1276            }
1277
1278            /**
1279             * Returns a <code>Font</code> object from the system properties list.
1280             * <code>nm</code> is treated as the name of a system property to be
1281             * obtained.  The <code>String</code> value of this property is then
1282             * interpreted as a <code>Font</code> object according to the
1283             * specification of <code>Font.decode(String)</code>
1284             * If the specified property is not found, or the executing code does
1285             * not have permission to read the property, null is returned instead.
1286             * 
1287             * @param nm the property name
1288             * @return a <code>Font</code> object that the property name
1289             *          describes, or null if no such property exists.
1290             * @throws NullPointerException if nm is null.
1291             * @since 1.2
1292             * @see #decode(String)
1293             */
1294            public static Font getFont(String nm) {
1295                return getFont(nm, null);
1296            }
1297
1298            /**
1299             * Returns the <code>Font</code> that the <code>str</code> 
1300             * argument describes.
1301             * To ensure that this method returns the desired Font, 
1302             * format the <code>str</code> parameter in
1303             * one of these ways
1304             * <p>
1305             * <ul>
1306             * <li><em>fontname-style-pointsize</em>
1307             * <li><em>fontname-pointsize</em>
1308             * <li><em>fontname-style</em>
1309             * <li><em>fontname</em>
1310             * <li><em>fontname style pointsize</em>
1311             * <li><em>fontname pointsize</em>
1312             * <li><em>fontname style</em>
1313             * <li><em>fontname</em>
1314             * </ul>
1315             * in which <i>style</i> is one of the four 
1316             * case-insensitive strings:
1317             * <code>"PLAIN"</code>, <code>"BOLD"</code>, <code>"BOLDITALIC"</code>, or
1318             * <code>"ITALIC"</code>, and pointsize is a positive decimal integer
1319             * representation of the point size.
1320             * For example, if you want a font that is Arial, bold, with
1321             * a point size of 18, you would call this method with:
1322             * "Arial-BOLD-18".
1323             * This is equivalent to calling the Font constructor :
1324             * <code>new Font("Arial", Font.BOLD, 18);</code>
1325             * and the values are interpreted as specified by that constructor.
1326             * <p>
1327             * A valid trailing decimal field is always interpreted as the pointsize.
1328             * Therefore a fontname containing a trailing decimal value should not
1329             * be used in the fontname only form.
1330             * <p>
1331             * If a style name field is not one of the valid style strings, it is
1332             * interpreted as part of the font name, and the default style is used.
1333             * <p>
1334             * Only one of ' ' or '-' may be used to separate fields in the input.
1335             * The identified separator is the one closest to the end of the string
1336             * which separates a valid pointsize, or a valid style name from
1337             * the rest of the string.
1338             * Null (empty) pointsize and style fields are treated
1339             * as valid fields with the default value for that field. 
1340             *<p>
1341             * Some font names may include the separator characters ' ' or '-'.
1342             * If <code>str</code> is not formed with 3 components, e.g. such that
1343             * <code>style</code> or <code>pointsize</code> fields are not present in
1344             * <code>str</code>, and <code>fontname</code> also contains a
1345             * character determined to be the separator character
1346             * then these characters where they appear as intended to be part of
1347             * <code>fontname</code> may instead be interpreted as separators
1348             * so the font name may not be properly recognised.
1349             * 
1350             * <p>
1351             * The default size is 12 and the default style is PLAIN.
1352             * If <code>str</code> does not specify a valid size, the returned 
1353             * <code>Font</code> has a size of 12.  If <code>str</code> does not
1354             * specify a valid style, the returned Font has a style of PLAIN.
1355             * If you do not specify a valid font name in 
1356             * the <code>str</code> argument, this method will return
1357             * a font with the family name "Dialog".
1358             * To determine what font family names are available on
1359             * your system, use the
1360             * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
1361             * If <code>str</code> is <code>null</code>, a new <code>Font</code>
1362             * is returned with the family name "Dialog", a size of 12 and a 
1363             * PLAIN style.
1364             * @param str the name of the font, or <code>null</code>
1365             * @return the <code>Font</code> object that <code>str</code>
1366             *          describes, or a new default <code>Font</code> if 
1367             *          <code>str</code> is <code>null</code>.
1368             * @see #getFamily
1369             * @since JDK1.1
1370             */
1371            public static Font decode(String str) {
1372                String fontName = str;
1373                String styleName = "";
1374                int fontSize = 12;
1375                int fontStyle = Font.PLAIN;
1376
1377                if (str == null) {
1378                    return new Font(DIALOG, fontStyle, fontSize);
1379                }
1380
1381                int lastHyphen = str.lastIndexOf('-');
1382                int lastSpace = str.lastIndexOf(' ');
1383                char sepChar = (lastHyphen > lastSpace) ? '-' : ' ';
1384                int sizeIndex = str.lastIndexOf(sepChar);
1385                int styleIndex = str.lastIndexOf(sepChar, sizeIndex - 1);
1386                int strlen = str.length();
1387
1388                if (sizeIndex > 0 && sizeIndex + 1 < strlen) {
1389                    try {
1390                        fontSize = Integer
1391                                .valueOf(str.substring(sizeIndex + 1))
1392                                .intValue();
1393                        if (fontSize <= 0) {
1394                            fontSize = 12;
1395                        }
1396                    } catch (NumberFormatException e) {
1397                        /* It wasn't a valid size, if we didn't also find the
1398                         * start of the style string perhaps this is the style */
1399                        styleIndex = sizeIndex;
1400                        sizeIndex = strlen;
1401                        if (str.charAt(sizeIndex - 1) == sepChar) {
1402                            sizeIndex--;
1403                        }
1404                    }
1405                }
1406
1407                if (styleIndex >= 0 && styleIndex + 1 < strlen) {
1408                    styleName = str.substring(styleIndex + 1, sizeIndex);
1409                    styleName = styleName.toLowerCase(Locale.ENGLISH);
1410                    if (styleName.equals("bolditalic")) {
1411                        fontStyle = Font.BOLD | Font.ITALIC;
1412                    } else if (styleName.equals("italic")) {
1413                        fontStyle = Font.ITALIC;
1414                    } else if (styleName.equals("bold")) {
1415                        fontStyle = Font.BOLD;
1416                    } else if (styleName.equals("plain")) {
1417                        fontStyle = Font.PLAIN;
1418                    } else {
1419                        /* this string isn't any of the expected styles, so
1420                         * assume its part of the font name
1421                         */
1422                        styleIndex = sizeIndex;
1423                        if (str.charAt(styleIndex - 1) == sepChar) {
1424                            styleIndex--;
1425                        }
1426                    }
1427                    fontName = str.substring(0, styleIndex);
1428
1429                } else {
1430                    int fontEnd = strlen;
1431                    if (styleIndex > 0) {
1432                        fontEnd = styleIndex;
1433                    } else if (sizeIndex > 0) {
1434                        fontEnd = sizeIndex;
1435                    }
1436                    if (fontEnd > 0 && str.charAt(fontEnd - 1) == sepChar) {
1437                        fontEnd--;
1438                    }
1439                    fontName = str.substring(0, fontEnd);
1440                }
1441
1442                return new Font(fontName, fontStyle, fontSize);
1443            }
1444
1445            /**
1446             * Gets the specified <code>Font</code> from the system properties
1447             * list.  As in the <code>getProperty</code> method of 
1448             * <code>System</code>, the first
1449             * argument is treated as the name of a system property to be
1450             * obtained.  The <code>String</code> value of this property is then
1451             * interpreted as a <code>Font</code> object. 
1452             * <p>
1453             * The property value should be one of the forms accepted by
1454             * <code>Font.decode(String)</code>
1455             * If the specified property is not found, or the executing code does not
1456             * have permission to read the property, the <code>font</code> 
1457             * argument is returned instead. 
1458             * @param nm the case-insensitive property name
1459             * @param font a default <code>Font</code> to return if property
1460             *          <code>nm</code> is not defined
1461             * @return    the <code>Font</code> value of the property.
1462             * @throws NullPointerException if nm is null.
1463             * @see #decode(String)
1464             */
1465            public static Font getFont(String nm, Font font) {
1466                String str = null;
1467                try {
1468                    str = System.getProperty(nm);
1469                } catch (SecurityException e) {
1470                }
1471                if (str == null) {
1472                    return font;
1473                }
1474                return decode(str);
1475            }
1476
1477            transient int hash;
1478
1479            /**
1480             * Returns a hashcode for this <code>Font</code>.
1481             * @return     a hashcode value for this <code>Font</code>.
1482             * @since      JDK1.0
1483             */
1484            public int hashCode() {
1485                if (hash == 0) {
1486                    hash = name.hashCode() ^ style ^ size;
1487                    /* It is possible many fonts differ only in transform.
1488                     * So include the transform in the hash calculation.
1489                     * nonIdentityTx is set whenever there is a transform in
1490                     * 'values'. The tests for null are required because it can
1491                     * also be set for other reasons.
1492                     */
1493                    if (nonIdentityTx && values != null
1494                            && values.getTransform() != null) {
1495                        hash ^= values.getTransform().hashCode();
1496                    }
1497                }
1498                return hash;
1499            }
1500
1501            /**
1502             * Compares this <code>Font</code> object to the specified 
1503             * <code>Object</code>.
1504             * @param obj the <code>Object</code> to compare
1505             * @return <code>true</code> if the objects are the same
1506             *          or if the argument is a <code>Font</code> object
1507             *          describing the same font as this object; 
1508             *          <code>false</code> otherwise.
1509             * @since JDK1.0
1510             */
1511            public boolean equals(Object obj) {
1512                if (obj == this ) {
1513                    return true;
1514                }
1515
1516                if (obj != null) {
1517                    try {
1518                        Font font = (Font) obj;
1519                        if (size == font.size
1520                                && style == font.style
1521                                && nonIdentityTx == font.nonIdentityTx
1522                                && hasLayoutAttributes == font.hasLayoutAttributes
1523                                && pointSize == font.pointSize
1524                                && name.equals(font.name)) {
1525
1526                            /* 'values' is usually initialized lazily, except when
1527                             * the font is constructed from a Map, or derived using
1528                             * a Map or other values. So if only one font has
1529                             * the field initialized we need to initialize it in
1530                             * the other instance and compare.
1531                             */
1532                            if (values == null) {
1533                                if (font.values == null) {
1534                                    return true;
1535                                } else {
1536                                    return getAttributeValues().equals(
1537                                            font.values);
1538                                }
1539                            } else {
1540                                return values.equals(font.getAttributeValues());
1541                            }
1542                        }
1543                    } catch (ClassCastException e) {
1544                    }
1545                }
1546                return false;
1547            }
1548
1549            /**
1550             * Converts this <code>Font</code> object to a <code>String</code>
1551             * representation.
1552             * @return     a <code>String</code> representation of this 
1553             *          <code>Font</code> object.
1554             * @since      JDK1.0
1555             */
1556            // NOTE: This method may be called by privileged threads.
1557            //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
1558            public String toString() {
1559                String strStyle;
1560
1561                if (isBold()) {
1562                    strStyle = isItalic() ? "bolditalic" : "bold";
1563                } else {
1564                    strStyle = isItalic() ? "italic" : "plain";
1565                }
1566
1567                return getClass().getName() + "[family=" + getFamily()
1568                        + ",name=" + name + ",style=" + strStyle + ",size="
1569                        + size + "]";
1570            } // toString()
1571
1572            /** Serialization support.  A <code>readObject</code>
1573             *  method is neccessary because the constructor creates
1574             *  the font's peer, and we can't serialize the peer.
1575             *  Similarly the computed font "family" may be different
1576             *  at <code>readObject</code> time than at
1577             *  <code>writeObject</code> time.  An integer version is
1578             *  written so that future versions of this class will be
1579             *  able to recognize serialized output from this one.
1580             */
1581            /**
1582             * The <code>Font</code> Serializable Data Form.
1583             *
1584             * @serial
1585             */
1586            private int fontSerializedDataVersion = 1;
1587
1588            /**
1589             * Writes default serializable fields to a stream.
1590             *
1591             * @param s the <code>ObjectOutputStream</code> to write
1592             * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
1593             * @see #readObject(java.io.ObjectInputStream)
1594             */
1595            private void writeObject(java.io.ObjectOutputStream s)
1596                    throws java.lang.ClassNotFoundException,
1597                    java.io.IOException {
1598                if (values != null) {
1599                    synchronized (values) {
1600                        // transient
1601                        fRequestedAttributes = values.toSerializableHashtable();
1602                        s.defaultWriteObject();
1603                        fRequestedAttributes = null;
1604                    }
1605                } else {
1606                    s.defaultWriteObject();
1607                }
1608            }
1609
1610            /**
1611             * Reads the <code>ObjectInputStream</code>.
1612             * Unrecognized keys or values will be ignored.
1613             *
1614             * @param s the <code>ObjectInputStream</code> to read
1615             * @serial
1616             * @see #writeObject(java.io.ObjectOutputStream)
1617             */
1618            private void readObject(java.io.ObjectInputStream s)
1619                    throws java.lang.ClassNotFoundException,
1620                    java.io.IOException {
1621                s.defaultReadObject();
1622                if (pointSize == 0) {
1623                    pointSize = (float) size;
1624                }
1625
1626                // Handle fRequestedAttributes.  
1627                // in 1.5, we always streamed out the font values plus 
1628                // TRANSFORM, SUPERSCRIPT, and WIDTH, regardless of whether the
1629                // values were default or not.  In 1.6 we only stream out
1630                // defined values.  So, 1.6 streams in from a 1.5 stream,
1631                // it check each of these values and 'undefines' it if the
1632                // value is the default.
1633
1634                if (fRequestedAttributes != null) {
1635                    values = getAttributeValues(); // init
1636                    AttributeValues extras = AttributeValues
1637                            .fromSerializableHashtable(fRequestedAttributes);
1638                    if (!AttributeValues.is16Hashtable(fRequestedAttributes)) {
1639                        extras.unsetDefault(); // if legacy stream, undefine these
1640                    }
1641                    values = getAttributeValues().merge(extras);
1642                    this .nonIdentityTx = values.anyNonDefault(EXTRA_MASK);
1643                    this .hasLayoutAttributes = values
1644                            .anyNonDefault(LAYOUT_MASK);
1645
1646                    fRequestedAttributes = null; // don't need it any more
1647                }
1648            }
1649
1650            /**
1651             * Returns the number of glyphs in this <code>Font</code>. Glyph codes
1652             * for this <code>Font</code> range from 0 to 
1653             * <code>getNumGlyphs()</code> - 1.
1654             * @return the number of glyphs in this <code>Font</code>.
1655             * @since 1.2
1656             */
1657            public int getNumGlyphs() {
1658                return getFont2D().getNumGlyphs();
1659            }
1660
1661            /**
1662             * Returns the glyphCode which is used when this <code>Font</code> 
1663             * does not have a glyph for a specified unicode code point.
1664             * @return the glyphCode of this <code>Font</code>.
1665             * @since 1.2
1666             */
1667            public int getMissingGlyphCode() {
1668                return getFont2D().getMissingGlyphCode();
1669            }
1670
1671            /**
1672             * Returns the baseline appropriate for displaying this character.
1673             * <p>
1674             * Large fonts can support different writing systems, and each system can
1675             * use a different baseline.
1676             * The character argument determines the writing system to use. Clients
1677             * should not assume all characters use the same baseline.
1678             *
1679             * @param c a character used to identify the writing system
1680             * @return the baseline appropriate for the specified character.
1681             * @see LineMetrics#getBaselineOffsets
1682             * @see #ROMAN_BASELINE
1683             * @see #CENTER_BASELINE
1684             * @see #HANGING_BASELINE
1685             * @since 1.2
1686             */
1687            public byte getBaselineFor(char c) {
1688                return getFont2D().getBaselineFor(c);
1689            }
1690
1691            /**
1692             * Returns a map of font attributes available in this
1693             * <code>Font</code>.  Attributes include things like ligatures and
1694             * glyph substitution.
1695             * @return the attributes map of this <code>Font</code>.
1696             */
1697            public Map<TextAttribute, ?> getAttributes() {
1698                return new AttributeMap(getAttributeValues());
1699            }
1700
1701            /**
1702             * Returns the keys of all the attributes supported by this 
1703             * <code>Font</code>.  These attributes can be used to derive other
1704             * fonts.
1705             * @return an array containing the keys of all the attributes
1706             *          supported by this <code>Font</code>.
1707             * @since 1.2
1708             */
1709            public Attribute[] getAvailableAttributes() {
1710                // FONT is not supported by Font
1711
1712                Attribute attributes[] = { TextAttribute.FAMILY,
1713                        TextAttribute.WEIGHT, TextAttribute.WIDTH,
1714                        TextAttribute.POSTURE, TextAttribute.SIZE,
1715                        TextAttribute.TRANSFORM, TextAttribute.SUPERSCRIPT,
1716                        TextAttribute.CHAR_REPLACEMENT,
1717                        TextAttribute.FOREGROUND, TextAttribute.BACKGROUND,
1718                        TextAttribute.UNDERLINE, TextAttribute.STRIKETHROUGH,
1719                        TextAttribute.RUN_DIRECTION,
1720                        TextAttribute.BIDI_EMBEDDING,
1721                        TextAttribute.JUSTIFICATION,
1722                        TextAttribute.INPUT_METHOD_HIGHLIGHT,
1723                        TextAttribute.INPUT_METHOD_UNDERLINE,
1724                        TextAttribute.SWAP_COLORS,
1725                        TextAttribute.NUMERIC_SHAPING, TextAttribute.KERNING,
1726                        TextAttribute.LIGATURES, TextAttribute.TRACKING, };
1727
1728                return attributes;
1729            }
1730
1731            /**
1732             * Creates a new <code>Font</code> object by replicating this
1733             * <code>Font</code> object and applying a new style and size.
1734             * @param style the style for the new <code>Font</code>
1735             * @param size the size for the new <code>Font</code>
1736             * @return a new <code>Font</code> object.
1737             * @since 1.2
1738             */
1739            public Font deriveFont(int style, float size) {
1740                if (values == null) {
1741                    return new Font(name, style, size, createdFont,
1742                            font2DHandle);
1743                }
1744                AttributeValues newValues = getAttributeValues().clone();
1745                int oldStyle = (this .style != style) ? this .style : -1;
1746                applyStyle(style, newValues);
1747                newValues.setSize(size);
1748                return new Font(newValues, null, oldStyle, createdFont,
1749                        font2DHandle);
1750            }
1751
1752            /**
1753             * Creates a new <code>Font</code> object by replicating this
1754             * <code>Font</code> object and applying a new style and transform.
1755             * @param style the style for the new <code>Font</code>
1756             * @param trans the <code>AffineTransform</code> associated with the
1757             * new <code>Font</code>
1758             * @return a new <code>Font</code> object.
1759             * @throws IllegalArgumentException if <code>trans</code> is
1760             *         <code>null</code>
1761             * @since 1.2
1762             */
1763            public Font deriveFont(int style, AffineTransform trans) {
1764                AttributeValues newValues = getAttributeValues().clone();
1765                int oldStyle = (this .style != style) ? this .style : -1;
1766                applyStyle(style, newValues);
1767                applyTransform(trans, newValues);
1768                return new Font(newValues, null, oldStyle, createdFont,
1769                        font2DHandle);
1770            }
1771
1772            /**
1773             * Creates a new <code>Font</code> object by replicating the current
1774             * <code>Font</code> object and applying a new size to it.
1775             * @param size the size for the new <code>Font</code>.
1776             * @return a new <code>Font</code> object.
1777             * @since 1.2
1778             */
1779            public Font deriveFont(float size) {
1780                if (values == null) {
1781                    return new Font(name, style, size, createdFont,
1782                            font2DHandle);
1783                }
1784                AttributeValues newValues = getAttributeValues().clone();
1785                newValues.setSize(size);
1786                return new Font(newValues, null, -1, createdFont, font2DHandle);
1787            }
1788
1789            /**
1790             * Creates a new <code>Font</code> object by replicating the current
1791             * <code>Font</code> object and applying a new transform to it.
1792             * @param trans the <code>AffineTransform</code> associated with the
1793             * new <code>Font</code>
1794             * @return a new <code>Font</code> object.
1795             * @throws IllegalArgumentException if <code>trans</code> is 
1796             *         <code>null</code>
1797             * @since 1.2
1798             */
1799            public Font deriveFont(AffineTransform trans) {
1800                AttributeValues newValues = getAttributeValues().clone();
1801                applyTransform(trans, newValues);
1802                return new Font(newValues, null, -1, createdFont, font2DHandle);
1803            }
1804
1805            /**
1806             * Creates a new <code>Font</code> object by replicating the current
1807             * <code>Font</code> object and applying a new style to it.
1808             * @param style the style for the new <code>Font</code>
1809             * @return a new <code>Font</code> object.
1810             * @since 1.2
1811             */
1812            public Font deriveFont(int style) {
1813                if (values == null) {
1814                    return new Font(name, style, size, createdFont,
1815                            font2DHandle);
1816                }
1817                AttributeValues newValues = getAttributeValues().clone();
1818                int oldStyle = (this .style != style) ? this .style : -1;
1819                applyStyle(style, newValues);
1820                return new Font(newValues, null, oldStyle, createdFont,
1821                        font2DHandle);
1822            }
1823
1824            /**
1825             * Creates a new <code>Font</code> object by replicating the current
1826             * <code>Font</code> object and applying a new set of font attributes
1827             * to it.
1828             * 
1829             * @param attributes a map of attributes enabled for the new 
1830             * <code>Font</code>
1831             * @return a new <code>Font</code> object.
1832             * @since 1.2
1833             */
1834            public Font deriveFont(Map<? extends Attribute, ?> attributes) {
1835                if (attributes == null) {
1836                    return this ;
1837                }
1838                AttributeValues newValues = getAttributeValues().clone();
1839                newValues.merge(attributes, RECOGNIZED_MASK);
1840
1841                return new Font(newValues, name, style, createdFont,
1842                        font2DHandle);
1843            }
1844
1845            /**
1846             * Checks if this <code>Font</code> has a glyph for the specified
1847             * character.
1848             *
1849             * <p> <b>Note:</b> This method cannot handle <a
1850             * href="../../java/lang/Character.html#supplementary"> supplementary
1851             * characters</a>. To support all Unicode characters, including
1852             * supplementary characters, use the {@link #canDisplay(int)}
1853             * method or <code>canDisplayUpTo</code> methods.
1854             *
1855             * @param c the character for which a glyph is needed
1856             * @return <code>true</code> if this <code>Font</code> has a glyph for this
1857             *          character; <code>false</code> otherwise.
1858             * @since 1.2
1859             */
1860            public boolean canDisplay(char c) {
1861                return getFont2D().canDisplay(c);
1862            }
1863
1864            /**
1865             * Checks if this <code>Font</code> has a glyph for the specified
1866             * character.
1867             *
1868             * @param codePoint the character (Unicode code point) for which a glyph
1869             *        is needed.
1870             * @return <code>true</code> if this <code>Font</code> has a glyph for the
1871             *          character; <code>false</code> otherwise.
1872             * @throws IllegalArgumentException if the code point is not a valid Unicode
1873             *          code point.
1874             * @see Character#isValidCodePoint(int)
1875             * @since 1.5
1876             */
1877            public boolean canDisplay(int codePoint) {
1878                if (!Character.isValidCodePoint(codePoint)) {
1879                    throw new IllegalArgumentException("invalid code point: "
1880                            + Integer.toHexString(codePoint));
1881                }
1882                return getFont2D().canDisplay(codePoint);
1883            }
1884
1885            /**
1886             * Indicates whether or not this <code>Font</code> can display a
1887             * specified <code>String</code>.  For strings with Unicode encoding,
1888             * it is important to know if a particular font can display the
1889             * string. This method returns an offset into the <code>String</code> 
1890             * <code>str</code> which is the first character this 
1891             * <code>Font</code> cannot display without using the missing glyph
1892             * code. If the <code>Font</code> can display all characters, -1 is
1893             * returned.
1894             * @param str a <code>String</code> object
1895             * @return an offset into <code>str</code> that points
1896             *          to the first character in <code>str</code> that this
1897             *          <code>Font</code> cannot display; or <code>-1</code> if
1898             *          this <code>Font</code> can display all characters in
1899             *          <code>str</code>.
1900             * @since 1.2
1901             */
1902            public int canDisplayUpTo(String str) {
1903                return canDisplayUpTo(new StringCharacterIterator(str), 0, str
1904                        .length());
1905            }
1906
1907            /**
1908             * Indicates whether or not this <code>Font</code> can display
1909             * the characters in the specified <code>text</code> 
1910             * starting at <code>start</code> and ending at 
1911             * <code>limit</code>.  This method is a convenience overload.
1912             * @param text the specified array of <code>char</code> values
1913             * @param start the specified starting offset (in
1914             *              <code>char</code>s) into the specified array of
1915             *              <code>char</code> values
1916             * @param limit the specified ending offset (in
1917             *              <code>char</code>s) into the specified array of
1918             *              <code>char</code> values
1919             * @return an offset into <code>text</code> that points
1920             *          to the first character in <code>text</code> that this
1921             *          <code>Font</code> cannot display; or <code>-1</code> if
1922             *          this <code>Font</code> can display all characters in
1923             *          <code>text</code>.
1924             * @since 1.2
1925             */
1926            public int canDisplayUpTo(char[] text, int start, int limit) {
1927                while (start < limit && canDisplay(text[start])) {
1928                    ++start;
1929                }
1930
1931                return start == limit ? -1 : start;
1932            }
1933
1934            /**
1935             * Indicates whether or not this <code>Font</code> can display the
1936             * text specified by the <code>iter</code> starting at
1937             * <code>start</code> and ending at <code>limit</code>.
1938             *
1939             * @param iter  a {@link CharacterIterator} object
1940             * @param start the specified starting offset into the specified
1941             *              <code>CharacterIterator</code>.
1942             * @param limit the specified ending offset into the specified
1943             *              <code>CharacterIterator</code>.
1944             * @return an offset into <code>iter</code> that points
1945             *          to the first character in <code>iter</code> that this
1946             *          <code>Font</code> cannot display; or <code>-1</code> if
1947             *          this <code>Font</code> can display all characters in
1948             *          <code>iter</code>.
1949             * @since 1.2
1950             */
1951            public int canDisplayUpTo(CharacterIterator iter, int start,
1952                    int limit) {
1953                for (char c = iter.setIndex(start); iter.getIndex() < limit
1954                        && canDisplay(c); c = iter.next()) {
1955                }
1956
1957                int result = iter.getIndex();
1958                return result == limit ? -1 : result;
1959            }
1960
1961            /**
1962             * Returns the italic angle of this <code>Font</code>.  The italic angle
1963             * is the inverse slope of the caret which best matches the posture of this
1964             * <code>Font</code>.
1965             * @see TextAttribute#POSTURE
1966             * @return the angle of the ITALIC style of this <code>Font</code>.
1967             */
1968            public float getItalicAngle() {
1969                return getItalicAngle(null);
1970            }
1971
1972            /* The FRC hints don't affect the value of the italic angle but
1973             * we need to pass them in to look up a strike.
1974             * If we can pass in ones already being used it can prevent an extra
1975             * strike from being allocated. Note that since italic angle is
1976             * a property of the font, the font transform is needed not the
1977             * device transform. Finally, this is private but the only caller of this
1978             * in the JDK - and the only likely caller - is in this same class.
1979             */
1980            private float getItalicAngle(FontRenderContext frc) {
1981                AffineTransform at = (isTransformed()) ? getTransform()
1982                        : identityTx;
1983                Object aa, fm;
1984                if (frc == null) {
1985                    aa = RenderingHints.VALUE_TEXT_ANTIALIAS_OFF;
1986                    fm = RenderingHints.VALUE_FRACTIONALMETRICS_OFF;
1987                } else {
1988                    aa = frc.getAntiAliasingHint();
1989                    fm = frc.getFractionalMetricsHint();
1990                }
1991                return getFont2D().getItalicAngle(this , at, aa, fm);
1992            }
1993
1994            /**
1995             * Checks whether or not this <code>Font</code> has uniform 
1996             * line metrics.  A logical <code>Font</code> might be a
1997             * composite font, which means that it is composed of different
1998             * physical fonts to cover different code ranges.  Each of these
1999             * fonts might have different <code>LineMetrics</code>.  If the
2000             * logical <code>Font</code> is a single
2001             * font then the metrics would be uniform. 
2002             * @return <code>true</code> if this <code>Font</code> has
2003             * uniform line metrics; <code>false</code> otherwise.
2004             */
2005            public boolean hasUniformLineMetrics() {
2006                return false; // REMIND always safe, but prevents caller optimize
2007            }
2008
2009            private transient SoftReference flmref;
2010
2011            private FontLineMetrics defaultLineMetrics(FontRenderContext frc) {
2012                FontLineMetrics flm = null;
2013                if (flmref == null
2014                        || (flm = (FontLineMetrics) flmref.get()) == null
2015                        || !flm.frc.equals(frc)) {
2016
2017                    /* The device transform in the frc is not used in obtaining line
2018                     * metrics, although it probably should be: REMIND find why not?
2019                     * The font transform is used but its applied in getFontMetrics, so
2020                     * just pass identity here
2021                     */
2022                    float[] metrics = new float[8];
2023                    getFont2D().getFontMetrics(this , identityTx,
2024                            frc.getAntiAliasingHint(),
2025                            frc.getFractionalMetricsHint(), metrics);
2026                    float ascent = metrics[0];
2027                    float descent = metrics[1];
2028                    float leading = metrics[2];
2029                    float ssOffset = 0;
2030                    if (values != null && values.getSuperscript() != 0) {
2031                        ssOffset = (float) getTransform().getTranslateY();
2032                        ascent -= ssOffset;
2033                        descent += ssOffset;
2034                    }
2035                    float height = ascent + descent + leading;
2036
2037                    int baselineIndex = 0; // need real index, assumes roman for everything
2038                    // need real baselines eventually
2039                    float[] baselineOffsets = { 0,
2040                            (descent / 2f - ascent) / 2f, -ascent };
2041
2042                    float strikethroughOffset = metrics[4];
2043                    float strikethroughThickness = metrics[5];
2044
2045                    float underlineOffset = metrics[6];
2046                    float underlineThickness = metrics[7];
2047
2048                    float italicAngle = getItalicAngle(frc);
2049
2050                    if (isTransformed()) {
2051                        AffineTransform ctx = values.getCharTransform(); // extract rotation
2052                        if (ctx != null) {
2053                            Point2D.Float pt = new Point2D.Float();
2054                            pt.setLocation(0, strikethroughOffset);
2055                            ctx.deltaTransform(pt, pt);
2056                            strikethroughOffset = pt.y;
2057                            pt.setLocation(0, strikethroughThickness);
2058                            ctx.deltaTransform(pt, pt);
2059                            strikethroughThickness = pt.y;
2060                            pt.setLocation(0, underlineOffset);
2061                            ctx.deltaTransform(pt, pt);
2062                            underlineOffset = pt.y;
2063                            pt.setLocation(0, underlineThickness);
2064                            ctx.deltaTransform(pt, pt);
2065                            underlineThickness = pt.y;
2066                        }
2067                    }
2068                    strikethroughOffset += ssOffset;
2069                    underlineOffset += ssOffset;
2070
2071                    CoreMetrics cm = new CoreMetrics(ascent, descent, leading,
2072                            height, baselineIndex, baselineOffsets,
2073                            strikethroughOffset, strikethroughThickness,
2074                            underlineOffset, underlineThickness, ssOffset,
2075                            italicAngle);
2076
2077                    flm = new FontLineMetrics(0, cm, frc);
2078                    flmref = new SoftReference(flm);
2079                }
2080
2081                return (FontLineMetrics) flm.clone();
2082            }
2083
2084            /**
2085             * Returns a {@link LineMetrics} object created with the specified
2086             * <code>String</code> and {@link FontRenderContext}.
2087             * @param str the specified <code>String</code>
2088             * @param frc the specified <code>FontRenderContext</code>
2089             * @return a <code>LineMetrics</code> object created with the
2090             * specified <code>String</code> and {@link FontRenderContext}.
2091             */
2092            public LineMetrics getLineMetrics(String str, FontRenderContext frc) {
2093                FontLineMetrics flm = defaultLineMetrics(frc);
2094                flm.numchars = str.length();
2095                return flm;
2096            }
2097
2098            /**
2099             * Returns a <code>LineMetrics</code> object created with the
2100             * specified arguments.
2101             * @param str the specified <code>String</code>
2102             * @param beginIndex the initial offset of <code>str</code> 
2103             * @param limit the end offset of <code>str</code>
2104             * @param frc the specified <code>FontRenderContext</code>
2105             * @return a <code>LineMetrics</code> object created with the
2106             * specified arguments.
2107             */
2108            public LineMetrics getLineMetrics(String str, int beginIndex,
2109                    int limit, FontRenderContext frc) {
2110                FontLineMetrics flm = defaultLineMetrics(frc);
2111                int numChars = limit - beginIndex;
2112                flm.numchars = (numChars < 0) ? 0 : numChars;
2113                return flm;
2114            }
2115
2116            /**
2117             * Returns a <code>LineMetrics</code> object created with the
2118             * specified arguments.
2119             * @param chars an array of characters
2120             * @param beginIndex the initial offset of <code>chars</code>
2121             * @param limit the end offset of <code>chars</code>
2122             * @param frc the specified <code>FontRenderContext</code>
2123             * @return a <code>LineMetrics</code> object created with the
2124             * specified arguments.
2125             */
2126            public LineMetrics getLineMetrics(char[] chars, int beginIndex,
2127                    int limit, FontRenderContext frc) {
2128                FontLineMetrics flm = defaultLineMetrics(frc);
2129                int numChars = limit - beginIndex;
2130                flm.numchars = (numChars < 0) ? 0 : numChars;
2131                return flm;
2132            }
2133
2134            /**
2135             * Returns a <code>LineMetrics</code> object created with the
2136             * specified arguments.
2137             * @param ci the specified <code>CharacterIterator</code>
2138             * @param beginIndex the initial offset in <code>ci</code>
2139             * @param limit the end offset of <code>ci</code>
2140             * @param frc the specified <code>FontRenderContext</code>
2141             * @return a <code>LineMetrics</code> object created with the
2142             * specified arguments.
2143             */
2144            public LineMetrics getLineMetrics(CharacterIterator ci,
2145                    int beginIndex, int limit, FontRenderContext frc) {
2146                FontLineMetrics flm = defaultLineMetrics(frc);
2147                int numChars = limit - beginIndex;
2148                flm.numchars = (numChars < 0) ? 0 : numChars;
2149                return flm;
2150            }
2151
2152            /**
2153             * Returns the logical bounds of the specified <code>String</code> in
2154             * the specified <code>FontRenderContext</code>.  The logical bounds
2155             * contains the origin, ascent, advance, and height, which includes 
2156             * the leading.  The logical bounds does not always enclose all the
2157             * text.  For example, in some languages and in some fonts, accent
2158             * marks can be positioned above the ascent or below the descent.
2159             * To obtain a visual bounding box, which encloses all the text,
2160             * use the {@link TextLayout#getBounds() getBounds} method of
2161             * <code>TextLayout</code>.
2162             * <p>Note: The returned bounds is in baseline-relative coordinates
2163             * (see {@link java.awt.Font class notes}).
2164             * @param str the specified <code>String</code>
2165             * @param frc the specified <code>FontRenderContext</code>
2166             * @return a {@link Rectangle2D} that is the bounding box of the
2167             * specified <code>String</code> in the specified
2168             * <code>FontRenderContext</code>.
2169             * @see FontRenderContext
2170             * @see Font#createGlyphVector
2171             * @since 1.2
2172             */
2173            public Rectangle2D getStringBounds(String str, FontRenderContext frc) {
2174                char[] array = str.toCharArray();
2175                return getStringBounds(array, 0, array.length, frc);
2176            }
2177
2178            /**
2179             * Returns the logical bounds of the specified <code>String</code> in
2180             * the specified <code>FontRenderContext</code>.  The logical bounds
2181             * contains the origin, ascent, advance, and height, which includes   
2182             * the leading.  The logical bounds does not always enclose all the
2183             * text.  For example, in some languages and in some fonts, accent
2184             * marks can be positioned above the ascent or below the descent.
2185             * To obtain a visual bounding box, which encloses all the text,
2186             * use the {@link TextLayout#getBounds() getBounds} method of 
2187             * <code>TextLayout</code>.
2188             * <p>Note: The returned bounds is in baseline-relative coordinates
2189             * (see {@link java.awt.Font class notes}).
2190             * @param str the specified <code>String</code>
2191             * @param beginIndex the initial offset of <code>str</code>
2192             * @param limit the end offset of <code>str</code>
2193             * @param frc the specified <code>FontRenderContext</code>   
2194             * @return a <code>Rectangle2D</code> that is the bounding box of the
2195             * specified <code>String</code> in the specified
2196             * <code>FontRenderContext</code>.
2197             * @throws IndexOutOfBoundsException if <code>beginIndex</code> is 
2198             *         less than zero, or <code>limit</code> is greater than the
2199             *         length of <code>str</code>, or <code>beginIndex</code>
2200             *         is greater than <code>limit</code>.
2201             * @see FontRenderContext
2202             * @see Font#createGlyphVector
2203             * @since 1.2
2204             */
2205            public Rectangle2D getStringBounds(String str, int beginIndex,
2206                    int limit, FontRenderContext frc) {
2207                String substr = str.substring(beginIndex, limit);
2208                return getStringBounds(substr, frc);
2209            }
2210
2211            /**
2212             * Returns the logical bounds of the specified array of characters
2213             * in the specified <code>FontRenderContext</code>.  The logical
2214             * bounds contains the origin, ascent, advance, and height, which
2215             * includes the leading.  The logical bounds does not always enclose
2216             * all the text.  For example, in some languages and in some fonts,
2217             * accent marks can be positioned above the ascent or below the
2218             * descent.  To obtain a visual bounding box, which encloses all the
2219             * text, use the {@link TextLayout#getBounds() getBounds} method of 
2220             * <code>TextLayout</code>.
2221             * <p>Note: The returned bounds is in baseline-relative coordinates
2222             * (see {@link java.awt.Font class notes}).
2223             * @param chars an array of characters
2224             * @param beginIndex the initial offset in the array of
2225             * characters
2226             * @param limit the end offset in the array of characters
2227             * @param frc the specified <code>FontRenderContext</code>   
2228             * @return a <code>Rectangle2D</code> that is the bounding box of the
2229             * specified array of characters in the specified
2230             * <code>FontRenderContext</code>.
2231             * @throws IndexOutOfBoundsException if <code>beginIndex</code> is 
2232             *         less than zero, or <code>limit</code> is greater than the
2233             *         length of <code>chars</code>, or <code>beginIndex</code>
2234             *         is greater than <code>limit</code>.
2235             * @see FontRenderContext
2236             * @see Font#createGlyphVector
2237             * @since 1.2
2238             */
2239            public Rectangle2D getStringBounds(char[] chars, int beginIndex,
2240                    int limit, FontRenderContext frc) {
2241                if (beginIndex < 0) {
2242                    throw new IndexOutOfBoundsException("beginIndex: "
2243                            + beginIndex);
2244                }
2245                if (limit > chars.length) {
2246                    throw new IndexOutOfBoundsException("limit: " + limit);
2247                }
2248                if (beginIndex > limit) {
2249                    throw new IndexOutOfBoundsException("range length: "
2250                            + (limit - beginIndex));
2251                }
2252
2253                // this code should be in textlayout
2254                // quick check for simple text, assume GV ok to use if simple
2255
2256                boolean simple = values == null
2257                        || (values.getKerning() == 0
2258                                && values.getLigatures() == 0 && values
2259                                .getBaselineTransform() == null);
2260                if (simple) {
2261                    simple = !FontManager.isComplexText(chars, beginIndex,
2262                            limit);
2263                }
2264
2265                if (simple) {
2266                    GlyphVector gv = new StandardGlyphVector(this , chars,
2267                            beginIndex, limit - beginIndex, frc);
2268                    return gv.getLogicalBounds();
2269                } else {
2270                    // need char array constructor on textlayout
2271                    String str = new String(chars, beginIndex, limit
2272                            - beginIndex);
2273                    TextLayout tl = new TextLayout(str, this , frc);
2274                    return new Rectangle2D.Float(0, -tl.getAscent(), tl
2275                            .getAdvance(), tl.getAscent() + tl.getDescent()
2276                            + tl.getLeading());
2277                }
2278            }
2279
2280            /**
2281             * Returns the logical bounds of the characters indexed in the
2282             * specified {@link CharacterIterator} in the
2283             * specified <code>FontRenderContext</code>.  The logical bounds
2284             * contains the origin, ascent, advance, and height, which includes   
2285             * the leading.  The logical bounds does not always enclose all the
2286             * text.  For example, in some languages and in some fonts, accent
2287             * marks can be positioned above the ascent or below the descent. 
2288             * To obtain a visual bounding box, which encloses all the text, 
2289             * use the {@link TextLayout#getBounds() getBounds} method of 
2290             * <code>TextLayout</code>.
2291             * <p>Note: The returned bounds is in baseline-relative coordinates
2292             * (see {@link java.awt.Font class notes}).
2293             * @param ci the specified <code>CharacterIterator</code>
2294             * @param beginIndex the initial offset in <code>ci</code>
2295             * @param limit the end offset in <code>ci</code>
2296             * @param frc the specified <code>FontRenderContext</code>   
2297             * @return a <code>Rectangle2D</code> that is the bounding box of the
2298             * characters indexed in the specified <code>CharacterIterator</code>
2299             * in the specified <code>FontRenderContext</code>.
2300             * @see FontRenderContext
2301             * @see Font#createGlyphVector
2302             * @since 1.2
2303             * @throws IndexOutOfBoundsException if <code>beginIndex</code> is
2304             *         less than the start index of <code>ci</code>, or 
2305             *         <code>limit</code> is greater than the end index of 
2306             *         <code>ci</code>, or <code>beginIndex</code> is greater 
2307             *         than <code>limit</code>
2308             */
2309            public Rectangle2D getStringBounds(CharacterIterator ci,
2310                    int beginIndex, int limit, FontRenderContext frc) {
2311                int start = ci.getBeginIndex();
2312                int end = ci.getEndIndex();
2313
2314                if (beginIndex < start) {
2315                    throw new IndexOutOfBoundsException("beginIndex: "
2316                            + beginIndex);
2317                }
2318                if (limit > end) {
2319                    throw new IndexOutOfBoundsException("limit: " + limit);
2320                }
2321                if (beginIndex > limit) {
2322                    throw new IndexOutOfBoundsException("range length: "
2323                            + (limit - beginIndex));
2324                }
2325
2326                char[] arr = new char[limit - beginIndex];
2327
2328                ci.setIndex(beginIndex);
2329                for (int idx = 0; idx < arr.length; idx++) {
2330                    arr[idx] = ci.current();
2331                    ci.next();
2332                }
2333
2334                return getStringBounds(arr, 0, arr.length, frc);
2335            }
2336
2337            /**
2338             * Returns the bounds for the character with the maximum
2339             * bounds as defined in the specified <code>FontRenderContext</code>.
2340             * <p>Note: The returned bounds is in baseline-relative coordinates
2341             * (see {@link java.awt.Font class notes}).
2342             * @param frc the specified <code>FontRenderContext</code>
2343             * @return a <code>Rectangle2D</code> that is the bounding box
2344             * for the character with the maximum bounds.
2345             */
2346            public Rectangle2D getMaxCharBounds(FontRenderContext frc) {
2347                float[] metrics = new float[4];
2348
2349                getFont2D().getFontMetrics(this , frc, metrics);
2350
2351                return new Rectangle2D.Float(0, -metrics[0], metrics[3],
2352                        metrics[0] + metrics[1] + metrics[2]);
2353            }
2354
2355            /**
2356             * Creates a {@link java.awt.font.GlyphVector GlyphVector} by 
2357             * mapping characters to glyphs one-to-one based on the 
2358             * Unicode cmap in this <code>Font</code>.  This method does no other
2359             * processing besides the mapping of glyphs to characters.  This
2360             * means that this method is not useful for some scripts, such
2361             * as Arabic, Hebrew, Thai, and Indic, that require reordering, 
2362             * shaping, or ligature substitution.
2363             * @param frc the specified <code>FontRenderContext</code>
2364             * @param str the specified <code>String</code>
2365             * @return a new <code>GlyphVector</code> created with the 
2366             * specified <code>String</code> and the specified
2367             * <code>FontRenderContext</code>.
2368             */
2369            public GlyphVector createGlyphVector(FontRenderContext frc,
2370                    String str) {
2371                return (GlyphVector) new StandardGlyphVector(this , str, frc);
2372            }
2373
2374            /**
2375             * Creates a {@link java.awt.font.GlyphVector GlyphVector} by
2376             * mapping characters to glyphs one-to-one based on the
2377             * Unicode cmap in this <code>Font</code>.  This method does no other
2378             * processing besides the mapping of glyphs to characters.  This
2379             * means that this method is not useful for some scripts, such
2380             * as Arabic, Hebrew, Thai, and Indic, that require reordering,   
2381             * shaping, or ligature substitution. 
2382             * @param frc the specified <code>FontRenderContext</code>
2383             * @param chars the specified array of characters
2384             * @return a new <code>GlyphVector</code> created with the
2385             * specified array of characters and the specified
2386             * <code>FontRenderContext</code>.
2387             */
2388            public GlyphVector createGlyphVector(FontRenderContext frc,
2389                    char[] chars) {
2390                return (GlyphVector) new StandardGlyphVector(this , chars, frc);
2391            }
2392
2393            /**
2394             * Creates a {@link java.awt.font.GlyphVector GlyphVector} by
2395             * mapping the specified characters to glyphs one-to-one based on the
2396             * Unicode cmap in this <code>Font</code>.  This method does no other
2397             * processing besides the mapping of glyphs to characters.  This
2398             * means that this method is not useful for some scripts, such
2399             * as Arabic, Hebrew, Thai, and Indic, that require reordering,   
2400             * shaping, or ligature substitution. 
2401             * @param frc the specified <code>FontRenderContext</code>
2402             * @param ci the specified <code>CharacterIterator</code>
2403             * @return a new <code>GlyphVector</code> created with the
2404             * specified <code>CharacterIterator</code> and the specified
2405             * <code>FontRenderContext</code>.
2406             */
2407            public GlyphVector createGlyphVector(FontRenderContext frc,
2408                    CharacterIterator ci) {
2409                return (GlyphVector) new StandardGlyphVector(this , ci, frc);
2410            }
2411
2412            /**
2413             * Creates a {@link java.awt.font.GlyphVector GlyphVector} by
2414             * mapping characters to glyphs one-to-one based on the
2415             * Unicode cmap in this <code>Font</code>.  This method does no other
2416             * processing besides the mapping of glyphs to characters.  This
2417             * means that this method is not useful for some scripts, such
2418             * as Arabic, Hebrew, Thai, and Indic, that require reordering,   
2419             * shaping, or ligature substitution.
2420             * @param frc the specified <code>FontRenderContext</code>
2421             * @param glyphCodes the specified integer array
2422             * @return a new <code>GlyphVector</code> created with the
2423             * specified integer array and the specified
2424             * <code>FontRenderContext</code>.
2425             */
2426            public GlyphVector createGlyphVector(FontRenderContext frc,
2427                    int[] glyphCodes) {
2428                return (GlyphVector) new StandardGlyphVector(this , glyphCodes,
2429                        frc);
2430            }
2431
2432            /**
2433             * Returns a new <code>GlyphVector</code> object, performing full
2434             * layout of the text if possible.  Full layout is required for
2435             * complex text, such as Arabic or Hindi.  Support for different
2436             * scripts depends on the font and implementation.  
2437             * <p>
2438             * Layout requires bidi analysis, as performed by 
2439             * <code>Bidi</code>, and should only be performed on text that
2440             * has a uniform direction.  The direction is indicated in the
2441             * flags parameter,by using LAYOUT_RIGHT_TO_LEFT to indicate a
2442             * right-to-left (Arabic and Hebrew) run direction, or 
2443             * LAYOUT_LEFT_TO_RIGHT to indicate a left-to-right (English) 
2444             * run direction.
2445             * <p>
2446             * In addition, some operations, such as Arabic shaping, require 
2447             * context, so that the characters at the start and limit can have 
2448             * the proper shapes.  Sometimes the data in the buffer outside
2449             * the provided range does not have valid data.  The values
2450             * LAYOUT_NO_START_CONTEXT and LAYOUT_NO_LIMIT_CONTEXT can be
2451             * added to the flags parameter to indicate that the text before
2452             * start, or after limit, respectively, should not be examined
2453             * for context.
2454             * <p>
2455             * All other values for the flags parameter are reserved.
2456             * 
2457             * @param frc the specified <code>FontRenderContext</code>
2458             * @param text the text to layout
2459             * @param start the start of the text to use for the <code>GlyphVector</code>
2460             * @param limit the limit of the text to use for the <code>GlyphVector</code>
2461             * @param flags control flags as described above
2462             * @return a new <code>GlyphVector</code> representing the text between
2463             * start and limit, with glyphs chosen and positioned so as to best represent 
2464             * the text
2465             * @throws ArrayIndexOutOfBoundsException if start or limit is 
2466             * out of bounds
2467             * @see java.text.Bidi
2468             * @see #LAYOUT_LEFT_TO_RIGHT
2469             * @see #LAYOUT_RIGHT_TO_LEFT
2470             * @see #LAYOUT_NO_START_CONTEXT
2471             * @see #LAYOUT_NO_LIMIT_CONTEXT
2472             * @since 1.4
2473             */
2474            public GlyphVector layoutGlyphVector(FontRenderContext frc,
2475                    char[] text, int start, int limit, int flags) {
2476
2477                GlyphLayout gl = GlyphLayout.get(null); // !!! no custom layout engines
2478                StandardGlyphVector gv = gl.layout(this , frc, text, start,
2479                        limit - start, flags, null);
2480                GlyphLayout.done(gl);
2481                return gv;
2482            }
2483
2484            /**
2485             * A flag to layoutGlyphVector indicating that text is left-to-right as
2486             * determined by Bidi analysis.
2487             */
2488            public static final int LAYOUT_LEFT_TO_RIGHT = 0;
2489
2490            /** 
2491             * A flag to layoutGlyphVector indicating that text is right-to-left as
2492             * determined by Bidi analysis.
2493             */
2494            public static final int LAYOUT_RIGHT_TO_LEFT = 1;
2495
2496            /**
2497             * A flag to layoutGlyphVector indicating that text in the char array
2498             * before the indicated start should not be examined.
2499             */
2500            public static final int LAYOUT_NO_START_CONTEXT = 2;
2501
2502            /**
2503             * A flag to layoutGlyphVector indicating that text in the char array
2504             * after the indicated limit should not be examined.
2505             */
2506            public static final int LAYOUT_NO_LIMIT_CONTEXT = 4;
2507
2508            private static void applyTransform(AffineTransform trans,
2509                    AttributeValues values) {
2510                if (trans == null) {
2511                    throw new IllegalArgumentException(
2512                            "transform must not be null");
2513                }
2514                values.setTransform(trans);
2515            }
2516
2517            private static void applyStyle(int style, AttributeValues values) {
2518                // WEIGHT_BOLD, WEIGHT_REGULAR
2519                values.setWeight((style & BOLD) != 0 ? 2f : 1f);
2520                // POSTURE_OBLIQUE, POSTURE_REGULAR
2521                values.setPosture((style & ITALIC) != 0 ? .2f : 0f);
2522            }
2523
2524            /*
2525             * Initialize JNI field and method IDs
2526             */
2527            private static native void initIDs();
2528        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.