Save This Page
Home » openjdk-7 » java » awt » [javadoc | source]
    1   /*
    2    * Copyright 1995-2007 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package java.awt;
   27   
   28   import java.awt.font.FontRenderContext;
   29   import java.awt.font.GlyphVector;
   30   import java.awt.font.LineMetrics;
   31   import java.awt.font.TextAttribute;
   32   import java.awt.font.TextLayout;
   33   import java.awt.font.TransformAttribute;
   34   import java.awt.geom.AffineTransform;
   35   import java.awt.geom.Point2D;
   36   import java.awt.geom.Rectangle2D;
   37   import java.awt.peer.FontPeer;
   38   import java.io;
   39   import java.lang.ref.SoftReference;
   40   import java.text.AttributedCharacterIterator.Attribute;
   41   import java.text.CharacterIterator;
   42   import java.text.StringCharacterIterator;
   43   import java.util.HashMap;
   44   import java.util.Hashtable;
   45   import java.util.Locale;
   46   import java.util.Map;
   47   import sun.font.StandardGlyphVector;
   48   import sun.java2d.FontSupport;
   49   
   50   import sun.font.AttributeMap;
   51   import sun.font.AttributeValues;
   52   import sun.font.EAttribute;
   53   import sun.font.CompositeFont;
   54   import sun.font.Font2D;
   55   import sun.font.Font2DHandle;
   56   import sun.font.FontManager;
   57   import sun.font.GlyphLayout;
   58   import sun.font.FontLineMetrics;
   59   import sun.font.CoreMetrics;
   60   
   61   import static sun.font.EAttribute.*;
   62   
   63   /**
   64    * The <code>Font</code> class represents fonts, which are used to
   65    * render text in a visible way.
   66    * A font provides the information needed to map sequences of
   67    * <em>characters</em> to sequences of <em>glyphs</em>
   68    * and to render sequences of glyphs on <code>Graphics</code> and
   69    * <code>Component</code> objects.
   70    *
   71    * <h4>Characters and Glyphs</h4>
   72    *
   73    * A <em>character</em> is a symbol that represents an item such as a letter,
   74    * a digit, or punctuation in an abstract way. For example, <code>'g'</code>,
   75    * <font size=-1>LATIN SMALL LETTER G</font>, is a character.
   76    * <p>
   77    * A <em>glyph</em> is a shape used to render a character or a sequence of
   78    * characters. In simple writing systems, such as Latin, typically one glyph
   79    * represents one character. In general, however, characters and glyphs do not
   80    * have one-to-one correspondence. For example, the character '&aacute;'
   81    * <font size=-1>LATIN SMALL LETTER A WITH ACUTE</font>, can be represented by
   82    * two glyphs: one for 'a' and one for '&acute;'. On the other hand, the
   83    * two-character string "fi" can be represented by a single glyph, an
   84    * "fi" ligature. In complex writing systems, such as Arabic or the South
   85    * and South-East Asian writing systems, the relationship between characters
   86    * and glyphs can be more complicated and involve context-dependent selection
   87    * of glyphs as well as glyph reordering.
   88    *
   89    * A font encapsulates the collection of glyphs needed to render a selected set
   90    * of characters as well as the tables needed to map sequences of characters to
   91    * corresponding sequences of glyphs.
   92    *
   93    * <h4>Physical and Logical Fonts</h4>
   94    *
   95    * The Java Platform distinguishes between two kinds of fonts:
   96    * <em>physical</em> fonts and <em>logical</em> fonts.
   97    * <p>
   98    * <em>Physical</em> fonts are the actual font libraries containing glyph data
   99    * and tables to map from character sequences to glyph sequences, using a font
  100    * technology such as TrueType or PostScript Type 1.
  101    * All implementations of the Java Platform must support TrueType fonts;
  102    * support for other font technologies is implementation dependent.
  103    * Physical fonts may use names such as Helvetica, Palatino, HonMincho, or
  104    * any number of other font names.
  105    * Typically, each physical font supports only a limited set of writing
  106    * systems, for example, only Latin characters or only Japanese and Basic
  107    * Latin.
  108    * The set of available physical fonts varies between configurations.
  109    * Applications that require specific fonts can bundle them and instantiate
  110    * them using the {@link #createFont createFont} method.
  111    * <p>
  112    * <em>Logical</em> fonts are the five font families defined by the Java
  113    * platform which must be supported by any Java runtime environment:
  114    * Serif, SansSerif, Monospaced, Dialog, and DialogInput.
  115    * These logical fonts are not actual font libraries. Instead, the logical
  116    * font names are mapped to physical fonts by the Java runtime environment.
  117    * The mapping is implementation and usually locale dependent, so the look
  118    * and the metrics provided by them vary.
  119    * Typically, each logical font name maps to several physical fonts in order to
  120    * cover a large range of characters.
  121    * <p>
  122    * Peered AWT components, such as {@link Label Label} and
  123    * {@link TextField TextField}, can only use logical fonts.
  124    * <p>
  125    * For a discussion of the relative advantages and disadvantages of using
  126    * physical or logical fonts, see the
  127    * <a href="http://java.sun.com/j2se/corejava/intl/reference/faqs/index.html#desktop-rendering">Internationalization FAQ</a>
  128    * document.
  129    *
  130    * <h4>Font Faces and Names</h4>
  131    *
  132    * A <code>Font</code>
  133    * can have many faces, such as heavy, medium, oblique, gothic and
  134    * regular. All of these faces have similar typographic design.
  135    * <p>
  136    * There are three different names that you can get from a
  137    * <code>Font</code> object.  The <em>logical font name</em> is simply the
  138    * name that was used to construct the font.
  139    * The <em>font face name</em>, or just <em>font name</em> for
  140    * short, is the name of a particular font face, like Helvetica Bold. The
  141    * <em>family name</em> is the name of the font family that determines the
  142    * typographic design across several faces, like Helvetica.
  143    * <p>
  144    * The <code>Font</code> class represents an instance of a font face from
  145    * a collection of  font faces that are present in the system resources
  146    * of the host system.  As examples, Arial Bold and Courier Bold Italic
  147    * are font faces.  There can be several <code>Font</code> objects
  148    * associated with a font face, each differing in size, style, transform
  149    * and font features.
  150    * <p>
  151    * The {@link GraphicsEnvironment#getAllFonts() getAllFonts} method
  152    * of the <code>GraphicsEnvironment</code> class returns an
  153    * array of all font faces available in the system. These font faces are
  154    * returned as <code>Font</code> objects with a size of 1, identity
  155    * transform and default font features. These
  156    * base fonts can then be used to derive new <code>Font</code> objects
  157    * with varying sizes, styles, transforms and font features via the
  158    * <code>deriveFont</code> methods in this class.
  159    *
  160    * <h4>Font and TextAttribute</h4>
  161    *
  162    * <p><code>Font</code> supports most
  163    * <code>TextAttribute</code>s.  This makes some operations, such as
  164    * rendering underlined text, convenient since it is not
  165    * necessary to explicitly construct a <code>TextLayout</code> object.
  166    * Attributes can be set on a Font by constructing or deriving it
  167    * using a <code>Map</code> of <code>TextAttribute</code> values.
  168    *
  169    * <p>The values of some <code>TextAttributes</code> are not
  170    * serializable, and therefore attempting to serialize an instance of
  171    * <code>Font</code> that has such values will not serialize them.
  172    * This means a Font deserialized from such a stream will not compare
  173    * equal to the original Font that contained the non-serializable
  174    * attributes.  This should very rarely pose a problem
  175    * since these attributes are typically used only in special
  176    * circumstances and are unlikely to be serialized.
  177    *
  178    * <ul>
  179    * <li><code>FOREGROUND</code> and <code>BACKGROUND</code> use
  180    * <code>Paint</code> values. The subclass <code>Color</code> is
  181    * serializable, while <code>GradientPaint</code> and
  182    * <code>TexturePaint</code> are not.</li>
  183    * <li><code>CHAR_REPLACEMENT</code> uses
  184    * <code>GraphicAttribute</code> values.  The subclasses
  185    * <code>ShapeGraphicAttribute</code> and
  186    * <code>ImageGraphicAttribute</code> are not serializable.</li>
  187    * <li><code>INPUT_METHOD_HIGHLIGHT</code> uses
  188    * <code>InputMethodHighlight</code> values, which are
  189    * not serializable.  See {@link java.awt.im.InputMethodHighlight}.</li>
  190    * </ul>
  191    *
  192    * Clients who create custom subclasses of <code>Paint</code> and
  193    * <code>GraphicAttribute</code> can make them serializable and
  194    * avoid this problem.  Clients who use input method highlights can
  195    * convert these to the platform-specific attributes for that
  196    * highlight on the current platform and set them on the Font as
  197    * a workaround.</p>
  198    *
  199    * <p>The <code>Map</code>-based constructor and
  200    * <code>deriveFont</code> APIs ignore the FONT attribute, and it is
  201    * not retained by the Font; the static {@link #getFont} method should
  202    * be used if the FONT attribute might be present.  See {@link
  203    * java.awt.font.TextAttribute#FONT} for more information.</p>
  204    *
  205    * <p>Several attributes will cause additional rendering overhead
  206    * and potentially invoke layout.  If a <code>Font</code> has such
  207    * attributes, the <code>{@link #hasLayoutAttributes()}</code> method
  208    * will return true.</p>
  209    *
  210    * <p>Note: Font rotations can cause text baselines to be rotated.  In
  211    * order to account for this (rare) possibility, font APIs are
  212    * specified to return metrics and take parameters 'in
  213    * baseline-relative coordinates'.  This maps the 'x' coordinate to
  214    * the advance along the baseline, (positive x is forward along the
  215    * baseline), and the 'y' coordinate to a distance along the
  216    * perpendicular to the baseline at 'x' (positive y is 90 degrees
  217    * clockwise from the baseline vector).  APIs for which this is
  218    * especially important are called out as having 'baseline-relative
  219    * coordinates.'
  220    */
  221   public class Font implements java.io.Serializable
  222   {
  223       static {
  224           /* ensure that the necessary native libraries are loaded */
  225           Toolkit.loadLibraries();
  226           initIDs();
  227       }
  228   
  229       /**
  230        * This is now only used during serialization.  Typically
  231        * it is null.
  232        *
  233        * @serial
  234        * @see #getAttributes()
  235        */
  236       private Hashtable fRequestedAttributes;
  237   
  238       /*
  239        * Constants to be used for logical font family names.
  240        */
  241   
  242       /**
  243        * A String constant for the canonical family name of the
  244        * logical font "Dialog". It is useful in Font construction
  245        * to provide compile-time verification of the name.
  246        * @since 1.6
  247        */
  248       public static final String DIALOG = "Dialog";
  249   
  250       /**
  251        * A String constant for the canonical family name of the
  252        * logical font "DialogInput". It is useful in Font construction
  253        * to provide compile-time verification of the name.
  254        * @since 1.6
  255        */
  256       public static final String DIALOG_INPUT = "DialogInput";
  257   
  258       /**
  259        * A String constant for the canonical family name of the
  260        * logical font "SansSerif". It is useful in Font construction
  261        * to provide compile-time verification of the name.
  262        * @since 1.6
  263        */
  264       public static final String SANS_SERIF = "SansSerif";
  265   
  266       /**
  267        * A String constant for the canonical family name of the
  268        * logical font "Serif". It is useful in Font construction
  269        * to provide compile-time verification of the name.
  270        * @since 1.6
  271        */
  272       public static final String SERIF = "Serif";
  273   
  274       /**
  275        * A String constant for the canonical family name of the
  276        * logical font "Monospaced". It is useful in Font construction
  277        * to provide compile-time verification of the name.
  278        * @since 1.6
  279        */
  280       public static final String MONOSPACED = "Monospaced";
  281   
  282       /*
  283        * Constants to be used for styles. Can be combined to mix
  284        * styles.
  285        */
  286   
  287       /**
  288        * The plain style constant.
  289        */
  290       public static final int PLAIN       = 0;
  291   
  292       /**
  293        * The bold style constant.  This can be combined with the other style
  294        * constants (except PLAIN) for mixed styles.
  295        */
  296       public static final int BOLD        = 1;
  297   
  298       /**
  299        * The italicized style constant.  This can be combined with the other
  300        * style constants (except PLAIN) for mixed styles.
  301        */
  302       public static final int ITALIC      = 2;
  303   
  304       /**
  305        * The baseline used in most Roman scripts when laying out text.
  306        */
  307       public static final int ROMAN_BASELINE = 0;
  308   
  309       /**
  310        * The baseline used in ideographic scripts like Chinese, Japanese,
  311        * and Korean when laying out text.
  312        */
  313       public static final int CENTER_BASELINE = 1;
  314   
  315       /**
  316        * The baseline used in Devanigiri and similar scripts when laying
  317        * out text.
  318        */
  319       public static final int HANGING_BASELINE = 2;
  320   
  321       /**
  322        * Identify a font resource of type TRUETYPE.
  323        * Used to specify a TrueType font resource to the
  324        * {@link #createFont} method.
  325        * @since 1.3
  326        */
  327   
  328       public static final int TRUETYPE_FONT = 0;
  329   
  330       /**
  331        * Identify a font resource of type TYPE1.
  332        * Used to specify a Type1 font resource to the
  333        * {@link #createFont} method.
  334        * @since 1.5
  335        */
  336       public static final int TYPE1_FONT = 1;
  337   
  338       /**
  339        * The logical name of this <code>Font</code>, as passed to the
  340        * constructor.
  341        * @since JDK1.0
  342        *
  343        * @serial
  344        * @see #getName
  345        */
  346       protected String name;
  347   
  348       /**
  349        * The style of this <code>Font</code>, as passed to the constructor.
  350        * This style can be PLAIN, BOLD, ITALIC, or BOLD+ITALIC.
  351        * @since JDK1.0
  352        *
  353        * @serial
  354        * @see #getStyle()
  355        */
  356       protected int style;
  357   
  358       /**
  359        * The point size of this <code>Font</code>, rounded to integer.
  360        * @since JDK1.0
  361        *
  362        * @serial
  363        * @see #getSize()
  364        */
  365       protected int size;
  366   
  367       /**
  368        * The point size of this <code>Font</code> in <code>float</code>.
  369        *
  370        * @serial
  371        * @see #getSize()
  372        * @see #getSize2D()
  373        */
  374       protected float pointSize;
  375   
  376       /**
  377        * The platform specific font information.
  378        */
  379       private transient FontPeer peer;
  380       private transient long pData;       // native JDK1.1 font pointer
  381       private transient Font2DHandle font2DHandle;
  382   
  383       private transient AttributeValues values;
  384       private transient boolean hasLayoutAttributes;
  385   
  386       /*
  387        * If the origin of a Font is a created font then this attribute
  388        * must be set on all derived fonts too.
  389        */
  390       private transient boolean createdFont = false;
  391   
  392       /*
  393        * This is true if the font transform is not identity.  It
  394        * is used to avoid unnecessary instantiation of an AffineTransform.
  395        */
  396       private transient boolean nonIdentityTx;
  397   
  398       /*
  399        * A cached value used when a transform is required for internal
  400        * use.  This must not be exposed to callers since AffineTransform
  401        * is mutable.
  402        */
  403       private static final AffineTransform identityTx = new AffineTransform();
  404   
  405       /*
  406        * JDK 1.1 serialVersionUID
  407        */
  408       private static final long serialVersionUID = -4206021311591459213L;
  409   
  410       /**
  411        * Gets the peer of this <code>Font</code>.
  412        * @return  the peer of the <code>Font</code>.
  413        * @since JDK1.1
  414        * @deprecated Font rendering is now platform independent.
  415        */
  416       @Deprecated
  417       public FontPeer getPeer(){
  418           return getPeer_NoClientCode();
  419       }
  420       // NOTE: This method is called by privileged threads.
  421       //       We implement this functionality in a package-private method
  422       //       to insure that it cannot be overridden by client subclasses.
  423       //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
  424       final FontPeer getPeer_NoClientCode() {
  425           if(peer == null) {
  426               Toolkit tk = Toolkit.getDefaultToolkit();
  427               this.peer = tk.getFontPeer(name, style);
  428           }
  429           return peer;
  430       }
  431   
  432       /**
  433        * Return the AttributeValues object associated with this
  434        * font.  Most of the time, the internal object is null.
  435        * If required, it will be created from the 'standard'
  436        * state on the font.  Only non-default values will be
  437        * set in the AttributeValues object.
  438        *
  439        * <p>Since the AttributeValues object is mutable, and it
  440        * is cached in the font, care must be taken to ensure that
  441        * it is not mutated.
  442        */
  443       private AttributeValues getAttributeValues() {
  444           if (values == null) {
  445               values = new AttributeValues();
  446               values.setFamily(name);
  447               values.setSize(pointSize); // expects the float value.
  448   
  449               if ((style & BOLD) != 0) {
  450                   values.setWeight(2); // WEIGHT_BOLD
  451               }
  452   
  453               if ((style & ITALIC) != 0) {
  454                   values.setPosture(.2f); // POSTURE_OBLIQUE
  455               }
  456               values.defineAll(PRIMARY_MASK); // for streaming compatibility
  457           }
  458   
  459           return values;
  460       }
  461   
  462       private Font2D getFont2D() {
  463           if (FontManager.usingPerAppContextComposites &&
  464               font2DHandle != null &&
  465               font2DHandle.font2D instanceof CompositeFont &&
  466               ((CompositeFont)(font2DHandle.font2D)).isStdComposite()) {
  467               return FontManager.findFont2D(name, style,
  468                                             FontManager.LOGICAL_FALLBACK);
  469           } else if (font2DHandle == null) {
  470               font2DHandle =
  471                   FontManager.findFont2D(name, style,
  472                                          FontManager.LOGICAL_FALLBACK).handle;
  473           }
  474           /* Do not cache the de-referenced font2D. It must be explicitly
  475            * de-referenced to pick up a valid font in the event that the
  476            * original one is marked invalid
  477            */
  478           return font2DHandle.font2D;
  479       }
  480   
  481       /**
  482        * Creates a new <code>Font</code> from the specified name, style and
  483        * point size.
  484        * <p>
  485        * The font name can be a font face name or a font family name.
  486        * It is used together with the style to find an appropriate font face.
  487        * When a font family name is specified, the style argument is used to
  488        * select the most appropriate face from the family. When a font face
  489        * name is specified, the face's style and the style argument are
  490        * merged to locate the best matching font from the same family.
  491        * For example if face name "Arial Bold" is specified with style
  492        * <code>Font.ITALIC</code>, the font system looks for a face in the
  493        * "Arial" family that is bold and italic, and may associate the font
  494        * instance with the physical font face "Arial Bold Italic".
  495        * The style argument is merged with the specified face's style, not
  496        * added or subtracted.
  497        * This means, specifying a bold face and a bold style does not
  498        * double-embolden the font, and specifying a bold face and a plain
  499        * style does not lighten the font.
  500        * <p>
  501        * If no face for the requested style can be found, the font system
  502        * may apply algorithmic styling to achieve the desired style.
  503        * For example, if <code>ITALIC</code> is requested, but no italic
  504        * face is available, glyphs from the plain face may be algorithmically
  505        * obliqued (slanted).
  506        * <p>
  507        * Font name lookup is case insensitive, using the case folding
  508        * rules of the US locale.
  509        * <p>
  510        * If the <code>name</code> parameter represents something other than a
  511        * logical font, i.e. is interpreted as a physical font face or family, and
  512        * this cannot be mapped by the implementation to a physical font or a
  513        * compatible alternative, then the font system will map the Font
  514        * instance to "Dialog", such that for example, the family as reported
  515        * by {@link #getFamily() getFamily} will be "Dialog".
  516        * <p>
  517        *
  518        * @param name the font name.  This can be a font face name or a font
  519        * family name, and may represent either a logical font or a physical
  520        * font found in this {@code GraphicsEnvironment}.
  521        * The family names for logical fonts are: Dialog, DialogInput,
  522        * Monospaced, Serif, or SansSerif. Pre-defined String constants exist
  523        * for all of these names, for example, {@code DIALOG}. If {@code name} is
  524        * {@code null}, the <em>logical font name</em> of the new
  525        * {@code Font} as returned by {@code getName()} is set to
  526        * the name "Default".
  527        * @param style the style constant for the {@code Font}
  528        * The style argument is an integer bitmask that may
  529        * be {@code PLAIN}, or a bitwise union of {@code BOLD} and/or
  530        * {@code ITALIC} (for example, {@code ITALIC} or {@code BOLD|ITALIC}).
  531        * If the style argument does not conform to one of the expected
  532        * integer bitmasks then the style is set to {@code PLAIN}.
  533        * @param size the point size of the {@code Font}
  534        * @see GraphicsEnvironment#getAllFonts
  535        * @see GraphicsEnvironment#getAvailableFontFamilyNames
  536        * @since JDK1.0
  537        */
  538       public Font(String name, int style, int size) {
  539           this.name = (name != null) ? name : "Default";
  540           this.style = (style & ~0x03) == 0 ? style : 0;
  541           this.size = size;
  542           this.pointSize = size;
  543       }
  544   
  545       private Font(String name, int style, float sizePts) {
  546           this.name = (name != null) ? name : "Default";
  547           this.style = (style & ~0x03) == 0 ? style : 0;
  548           this.size = (int)(sizePts + 0.5);
  549           this.pointSize = sizePts;
  550       }
  551   
  552       /* This constructor is used by deriveFont when attributes is null */
  553       private Font(String name, int style, float sizePts,
  554                    boolean created, Font2DHandle handle) {
  555           this(name, style, sizePts);
  556           this.createdFont = created;
  557           /* Fonts created from a stream will use the same font2D instance
  558            * as the parent.
  559            * One exception is that if the derived font is requested to be
  560            * in a different style, then also check if its a CompositeFont
  561            * and if so build a new CompositeFont from components of that style.
  562            * CompositeFonts can only be marked as "created" if they are used
  563            * to add fall backs to a physical font. And non-composites are
  564            * always from "Font.createFont()" and shouldn't get this treatment.
  565            */
  566           if (created) {
  567               if (handle.font2D instanceof CompositeFont &&
  568                   handle.font2D.getStyle() != style) {
  569                   this.font2DHandle =
  570                       FontManager.getNewComposite(null, style, handle);
  571               } else {
  572                   this.font2DHandle = handle;
  573               }
  574           }
  575       }
  576   
  577       /* used to implement Font.createFont */
  578       private Font(File fontFile, int fontFormat, boolean isCopy)
  579           throws FontFormatException {
  580           this.createdFont = true;
  581           /* Font2D instances created by this method track their font file
  582            * so that when the Font2D is GC'd it can also remove the file.
  583            */
  584           this.font2DHandle =
  585               FontManager.createFont2D(fontFile, fontFormat, isCopy).handle;
  586           this.name = this.font2DHandle.font2D.getFontName(Locale.getDefault());
  587           this.style = Font.PLAIN;
  588           this.size = 1;
  589           this.pointSize = 1f;
  590       }
  591   
  592       /* This constructor is used when one font is derived from another.
  593        * Fonts created from a stream will use the same font2D instance as the
  594        * parent. They can be distinguished because the "created" argument
  595        * will be "true". Since there is no way to recreate these fonts they
  596        * need to have the handle to the underlying font2D passed in.
  597        * "created" is also true when a special composite is referenced by the
  598        * handle for essentially the same reasons.
  599        * But when deriving a font in these cases two particular attributes
  600        * need special attention: family/face and style.
  601        * The "composites" in these cases need to be recreated with optimal
  602        * fonts for the new values of family and style.
  603        * For fonts created with createFont() these are treated differently.
  604        * JDK can often synthesise a different style (bold from plain
  605        * for example). For fonts created with "createFont" this is a reasonable
  606        * solution but its also possible (although rare) to derive a font with a
  607        * different family attribute. In this case JDK needs
  608        * to break the tie with the original Font2D and find a new Font.
  609        * The oldName and oldStyle are supplied so they can be compared with
  610        * what the Font2D and the values. To speed things along :
  611        * oldName == null will be interpreted as the name is unchanged.
  612        * oldStyle = -1 will be interpreted as the style is unchanged.
  613        * In these cases there is no need to interrogate "values".
  614        */
  615       private Font(AttributeValues values, String oldName, int oldStyle,
  616                    boolean created, Font2DHandle handle) {
  617   
  618           this.createdFont = created;
  619           if (created) {
  620               this.font2DHandle = handle;
  621   
  622               String newName = null;
  623               if (oldName != null) {
  624                   newName = values.getFamily();
  625                   if (oldName.equals(newName)) newName = null;
  626               }
  627               int newStyle = 0;
  628               if (oldStyle == -1) {
  629                   newStyle = -1;
  630               } else {
  631                   if (values.getWeight() >= 2f)   newStyle  = BOLD;
  632                   if (values.getPosture() >= .2f) newStyle |= ITALIC;
  633                   if (oldStyle == newStyle)       newStyle  = -1;
  634               }
  635               if (handle.font2D instanceof CompositeFont) {
  636                   if (newStyle != -1 || newName != null) {
  637                       this.font2DHandle =
  638                           FontManager.getNewComposite(newName, newStyle, handle);
  639                   }
  640               } else if (newName != null) {
  641                   this.createdFont = false;
  642                   this.font2DHandle = null;
  643               }
  644           }
  645           initFromValues(values);
  646       }
  647   
  648       /**
  649        * Creates a new <code>Font</code> with the specified attributes.
  650        * Only keys defined in {@link java.awt.font.TextAttribute TextAttribute}
  651        * are recognized.  In addition the FONT attribute is
  652        *  not recognized by this constructor
  653        * (see {@link #getAvailableAttributes}). Only attributes that have
  654        * values of valid types will affect the new <code>Font</code>.
  655        * <p>
  656        * If <code>attributes</code> is <code>null</code>, a new
  657        * <code>Font</code> is initialized with default values.
  658        * @see java.awt.font.TextAttribute
  659        * @param attributes the attributes to assign to the new
  660        *          <code>Font</code>, or <code>null</code>
  661        */
  662       public Font(Map<? extends Attribute, ?> attributes) {
  663           initFromValues(AttributeValues.fromMap(attributes, RECOGNIZED_MASK));
  664       }
  665   
  666       /**
  667        * Creates a new <code>Font</code> from the specified <code>font</code>.
  668        * This constructor is intended for use by subclasses.
  669        * @param font from which to create this <code>Font</code>.
  670        * @throws NullPointerException if <code>font</code> is null
  671        * @since 1.6
  672        */
  673       protected Font(Font font) {
  674           if (font.values != null) {
  675               initFromValues(font.getAttributeValues().clone());
  676           } else {
  677               this.name = font.name;
  678               this.style = font.style;
  679               this.size = font.size;
  680               this.pointSize = font.pointSize;
  681           }
  682           this.font2DHandle = font.font2DHandle;
  683           this.createdFont = font.createdFont;
  684       }
  685   
  686       /**
  687        * Font recognizes all attributes except FONT.
  688        */
  689       private static final int RECOGNIZED_MASK = AttributeValues.MASK_ALL
  690           & ~AttributeValues.getMask(EFONT);
  691   
  692       /**
  693        * These attributes are considered primary by the FONT attribute.
  694        */
  695       private static final int PRIMARY_MASK =
  696           AttributeValues.getMask(EFAMILY, EWEIGHT, EWIDTH, EPOSTURE, ESIZE,
  697                                   ETRANSFORM, ESUPERSCRIPT, ETRACKING);
  698   
  699       /**
  700        * These attributes are considered secondary by the FONT attribute.
  701        */
  702       private static final int SECONDARY_MASK =
  703           RECOGNIZED_MASK & ~PRIMARY_MASK;
  704   
  705       /**
  706        * These attributes are handled by layout.
  707        */
  708       private static final int LAYOUT_MASK =
  709           AttributeValues.getMask(ECHAR_REPLACEMENT, EFOREGROUND, EBACKGROUND,
  710                                   EUNDERLINE, ESTRIKETHROUGH, ERUN_DIRECTION,
  711                                   EBIDI_EMBEDDING, EJUSTIFICATION,
  712                                   EINPUT_METHOD_HIGHLIGHT, EINPUT_METHOD_UNDERLINE,
  713                                   ESWAP_COLORS, ENUMERIC_SHAPING, EKERNING,
  714                                   ELIGATURES, ETRACKING, ESUPERSCRIPT);
  715   
  716       private static final int EXTRA_MASK =
  717               AttributeValues.getMask(ETRANSFORM, ESUPERSCRIPT, EWIDTH);
  718   
  719       /**
  720        * Initialize the standard Font fields from the values object.
  721        */
  722       private void initFromValues(AttributeValues values) {
  723           this.values = values;
  724           values.defineAll(PRIMARY_MASK); // for 1.5 streaming compatibility
  725   
  726           this.name = values.getFamily();
  727           this.pointSize = values.getSize();
  728           this.size = (int)(values.getSize() + 0.5);
  729           if (values.getWeight() >= 2f) this.style |= BOLD; // not == 2f
  730           if (values.getPosture() >= .2f) this.style |= ITALIC; // not  == .2f
  731   
  732           this.nonIdentityTx = values.anyNonDefault(EXTRA_MASK);
  733           this.hasLayoutAttributes =  values.anyNonDefault(LAYOUT_MASK);
  734       }
  735   
  736       /**
  737        * Returns a <code>Font</code> appropriate to the attributes.
  738        * If <code>attributes</code>contains a <code>FONT</code> attribute
  739        * with a valid <code>Font</code> as its value, it will be
  740        * merged with any remaining attributes.  See
  741        * {@link java.awt.font.TextAttribute#FONT} for more
  742        * information.
  743        *
  744        * @param attributes the attributes to assign to the new
  745        *          <code>Font</code>
  746        * @return a new <code>Font</code> created with the specified
  747        *          attributes
  748        * @throws NullPointerException if <code>attributes</code> is null.
  749        * @since 1.2
  750        * @see java.awt.font.TextAttribute
  751        */
  752       public static Font getFont(Map<? extends Attribute, ?> attributes) {
  753           // optimize for two cases:
  754           // 1) FONT attribute, and nothing else
  755           // 2) attributes, but no FONT
  756   
  757           // avoid turning the attributemap into a regular map for no reason
  758           if (attributes instanceof AttributeMap &&
  759               ((AttributeMap)attributes).getValues() != null) {
  760               AttributeValues values = ((AttributeMap)attributes).getValues();
  761               if (values.isNonDefault(EFONT)) {
  762                   Font font = values.getFont();
  763                   if (!values.anyDefined(SECONDARY_MASK)) {
  764                       return font;
  765                   }
  766                   // merge
  767                   values = font.getAttributeValues().clone();
  768                   values.merge(attributes, SECONDARY_MASK);
  769                   return new Font(values, font.name, font.style,
  770                                   font.createdFont, font.font2DHandle);
  771               }
  772               return new Font(attributes);
  773           }
  774   
  775           Font font = (Font)attributes.get(TextAttribute.FONT);
  776           if (font != null) {
  777               if (attributes.size() > 1) { // oh well, check for anything else
  778                   AttributeValues values = font.getAttributeValues().clone();
  779                   values.merge(attributes, SECONDARY_MASK);
  780                   return new Font(values, font.name, font.style,
  781                                   font.createdFont, font.font2DHandle);
  782               }
  783   
  784               return font;
  785           }
  786   
  787           return new Font(attributes);
  788       }
  789   
  790       /**
  791        * Returns a new <code>Font</code> using the specified font type
  792        * and input data.  The new <code>Font</code> is
  793        * created with a point size of 1 and style {@link #PLAIN PLAIN}.
  794        * This base font can then be used with the <code>deriveFont</code>
  795        * methods in this class to derive new <code>Font</code> objects with
  796        * varying sizes, styles, transforms and font features.  This
  797        * method does not close the {@link InputStream}.
  798        * <p>
  799        * To make the <code>Font</code> available to Font constructors the
  800        * returned <code>Font</code> must be registered in the
  801        * <code>GraphicsEnviroment</code> by calling
  802        * {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}.
  803        * @param fontFormat the type of the <code>Font</code>, which is
  804        * {@link #TRUETYPE_FONT TRUETYPE_FONT} if a TrueType resource is specified.
  805        * or {@link #TYPE1_FONT TYPE1_FONT} if a Type 1 resource is specified.
  806        * @param fontStream an <code>InputStream</code> object representing the
  807        * input data for the font.
  808        * @return a new <code>Font</code> created with the specified font type.
  809        * @throws IllegalArgumentException if <code>fontFormat</code> is not
  810        *     <code>TRUETYPE_FONT</code>or<code>TYPE1_FONT</code>.
  811        * @throws FontFormatException if the <code>fontStream</code> data does
  812        *     not contain the required font tables for the specified format.
  813        * @throws IOException if the <code>fontStream</code>
  814        *     cannot be completely read.
  815        * @see GraphicsEnvironment#registerFont(Font)
  816        * @since 1.3
  817        */
  818       public static Font createFont(int fontFormat, InputStream fontStream)
  819           throws java.awt.FontFormatException, java.io.IOException {
  820   
  821           if (fontFormat != Font.TRUETYPE_FONT &&
  822               fontFormat != Font.TYPE1_FONT) {
  823               throw new IllegalArgumentException ("font format not recognized");
  824           }
  825           final InputStream fStream = fontStream;
  826           Object ret = java.security.AccessController.doPrivileged(
  827              new java.security.PrivilegedAction() {
  828                 public Object run() {
  829                     File tFile = null;
  830                     FileOutputStream outStream = null;
  831                     try {
  832                         tFile = File.createTempFile("+~JF", ".tmp", null);
  833                         /* Temp file deleted by font shutdown hook */
  834                         BufferedInputStream inStream =
  835                             new BufferedInputStream(fStream);
  836                         outStream = new FileOutputStream(tFile);
  837                         int bytesRead = 0;
  838                         int bufSize = 8192;
  839                         byte [] buf = new byte[bufSize];
  840                         while (bytesRead != -1) {
  841                             try {
  842                                 bytesRead = inStream.read(buf, 0, bufSize);
  843                             } catch (Throwable t) {
  844                                 throw new IOException();
  845                             }
  846                             if (bytesRead != -1) {
  847                                 outStream.write(buf, 0, bytesRead);
  848                             }
  849                         }
  850                         /* don't close the input stream */
  851                         outStream.close();
  852                     } catch (IOException e) {
  853                         if (outStream != null) {
  854                             try {
  855                                 outStream.close();
  856                             } catch (Exception e1) {
  857                             }
  858                         }
  859                         if (tFile != null) {
  860                             try {
  861                                 tFile.delete();
  862                             }  catch (Exception e2) {
  863                             }
  864                         }
  865                         return e;
  866                     }
  867                     return tFile;
  868                 }
  869             });
  870   
  871           if (ret instanceof File) {
  872               return new Font((File)ret, fontFormat, true);
  873           } else if (ret instanceof IOException) {
  874               throw (IOException)ret;
  875           } else {
  876               throw new FontFormatException("Couldn't access font stream");
  877           }
  878       }
  879   
  880       /**
  881        * Returns a new <code>Font</code> using the specified font type
  882        * and the specified font file.  The new <code>Font</code> is
  883        * created with a point size of 1 and style {@link #PLAIN PLAIN}.
  884        * This base font can then be used with the <code>deriveFont</code>
  885        * methods in this class to derive new <code>Font</code> objects with
  886        * varying sizes, styles, transforms and font features.
  887        * @param fontFormat the type of the <code>Font</code>, which is
  888        * {@link #TRUETYPE_FONT TRUETYPE_FONT} if a TrueType resource is
  889        * specified or {@link #TYPE1_FONT TYPE1_FONT} if a Type 1 resource is
  890        * specified.
  891        * So long as the returned font, or its derived fonts are referenced
  892        * the implementation may continue to access <code>fontFile</code>
  893        * to retrieve font data. Thus the results are undefined if the file
  894        * is changed, or becomes inaccessible.
  895        * <p>
  896        * To make the <code>Font</code> available to Font constructors the
  897        * returned <code>Font</code> must be registered in the
  898        * <code>GraphicsEnviroment</code> by calling
  899        * {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}.
  900        * @param fontFile a <code>File</code> object representing the
  901        * input data for the font.
  902        * @return a new <code>Font</code> created with the specified font type.
  903        * @throws IllegalArgumentException if <code>fontFormat</code> is not
  904        *     <code>TRUETYPE_FONT</code>or<code>TYPE1_FONT</code>.
  905        * @throws NullPointerException if <code>fontFile</code> is null.
  906        * @throws IOException if the <code>fontFile</code> cannot be read.
  907        * @throws FontFormatException if <code>fontFile</code> does
  908        *     not contain the required font tables for the specified format.
  909        * @throws SecurityException if the executing code does not have
  910        * permission to read from the file.
  911        * @see GraphicsEnvironment#registerFont(Font)
  912        * @since 1.5
  913        */
  914       public static Font createFont(int fontFormat, File fontFile)
  915           throws java.awt.FontFormatException, java.io.IOException {
  916           if (fontFormat != Font.TRUETYPE_FONT &&
  917               fontFormat != Font.TYPE1_FONT) {
  918               throw new IllegalArgumentException ("font format not recognized");
  919           }
  920           SecurityManager sm = System.getSecurityManager();
  921           if (sm != null) {
  922               FilePermission filePermission =
  923                   new FilePermission(fontFile.getPath(), "read");
  924               sm.checkPermission(filePermission);
  925           }
  926           if (!fontFile.canRead()) {
  927               throw new IOException("Can't read " + fontFile);
  928           }
  929           return new Font(fontFile, fontFormat, false);
  930       }
  931   
  932       /**
  933        * Returns a copy of the transform associated with this
  934        * <code>Font</code>.  This transform is not necessarily the one
  935        * used to construct the font.  If the font has algorithmic
  936        * superscripting or width adjustment, this will be incorporated
  937        * into the returned <code>AffineTransform</code>.
  938        * <p>
  939        * Typically, fonts will not be transformed.  Clients generally
  940        * should call {@link #isTransformed} first, and only call this
  941        * method if <code>isTransformed</code> returns true.
  942        *
  943        * @return an {@link AffineTransform} object representing the
  944        *          transform attribute of this <code>Font</code> object.
  945        */
  946       public AffineTransform getTransform() {
  947           /* The most common case is the identity transform.  Most callers
  948            * should call isTransformed() first, to decide if they need to
  949            * get the transform, but some may not.  Here we check to see
  950            * if we have a nonidentity transform, and only do the work to
  951            * fetch and/or compute it if so, otherwise we return a new
  952            * identity transform.
  953            *
  954            * Note that the transform is _not_ necessarily the same as
  955            * the transform passed in as an Attribute in a Map, as the
  956            * transform returned will also reflect the effects of WIDTH and
  957            * SUPERSCRIPT attributes.  Clients who want the actual transform
  958            * need to call getRequestedAttributes.
  959            */
  960           if (nonIdentityTx) {
  961               AttributeValues values = getAttributeValues();
  962   
  963               AffineTransform at = values.isNonDefault(ETRANSFORM)
  964                   ? new AffineTransform(values.getTransform())
  965                   : new AffineTransform();
  966   
  967               if (values.getSuperscript() != 0) {
  968                   // can't get ascent and descent here, recursive call to this fn,
  969                   // so use pointsize
  970                   // let users combine super- and sub-scripting
  971   
  972                   int superscript = values.getSuperscript();
  973   
  974                   double trans = 0;
  975                   int n = 0;
  976                   boolean up = superscript > 0;
  977                   int sign = up ? -1 : 1;
  978                   int ss = up ? superscript : -superscript;
  979   
  980                   while ((ss & 7) > n) {
  981                       int newn = ss & 7;
  982                       trans += sign * (ssinfo[newn] - ssinfo[n]);
  983                       ss >>= 3;
  984                       sign = -sign;
  985                       n = newn;
  986                   }
  987                   trans *= pointSize;
  988                   double scale = Math.pow(2./3., n);
  989   
  990                   at.preConcatenate(AffineTransform.getTranslateInstance(0, trans));
  991                   at.scale(scale, scale);
  992   
  993                   // note on placement and italics
  994                   // We preconcatenate the transform because we don't want to translate along
  995                   // the italic angle, but purely perpendicular to the baseline.  While this
  996                   // looks ok for superscripts, it can lead subscripts to stack on each other
  997                   // and bring the following text too close.  The way we deal with potential
  998                   // collisions that can occur in the case of italics is by adjusting the
  999                   // horizontal spacing of the adjacent glyphvectors.  Examine the italic
 1000                   // angle of both vectors, if one is non-zero, compute the minimum ascent
 1001                   // and descent, and then the x position at each for each vector along its
 1002                   // italic angle starting from its (offset) baseline.  Compute the difference
 1003                   // between the x positions and use the maximum difference to adjust the
 1004                   // position of the right gv.
 1005               }
 1006   
 1007               if (values.isNonDefault(EWIDTH)) {
 1008                   at.scale(values.getWidth(), 1f);
 1009               }
 1010   
 1011               return at;
 1012           }
 1013   
 1014           return new AffineTransform();
 1015       }
 1016   
 1017       // x = r^0 + r^1 + r^2... r^n
 1018       // rx = r^1 + r^2 + r^3... r^(n+1)
 1019       // x - rx = r^0 - r^(n+1)
 1020       // x (1 - r) = r^0 - r^(n+1)
 1021       // x = (r^0 - r^(n+1)) / (1 - r)
 1022       // x = (1 - r^(n+1)) / (1 - r)
 1023   
 1024       // scale ratio is 2/3
 1025       // trans = 1/2 of ascent * x
 1026       // assume ascent is 3/4 of point size
 1027   
 1028       private static final float[] ssinfo = {
 1029           0.0f,
 1030           0.375f,
 1031           0.625f,
 1032           0.7916667f,
 1033           0.9027778f,
 1034           0.9768519f,
 1035           1.0262346f,
 1036           1.0591564f,
 1037       };
 1038   
 1039       /**
 1040        * Returns the family name of this <code>Font</code>.
 1041        *
 1042        * <p>The family name of a font is font specific. Two fonts such as
 1043        * Helvetica Italic and Helvetica Bold have the same family name,
 1044        * <i>Helvetica</i>, whereas their font face names are
 1045        * <i>Helvetica Bold</i> and <i>Helvetica Italic</i>. The list of
 1046        * available family names may be obtained by using the
 1047        * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
 1048        *
 1049        * <p>Use <code>getName</code> to get the logical name of the font.
 1050        * Use <code>getFontName</code> to get the font face name of the font.
 1051        * @return a <code>String</code> that is the family name of this
 1052        *          <code>Font</code>.
 1053        *
 1054        * @see #getName
 1055        * @see #getFontName
 1056        * @since JDK1.1
 1057        */
 1058       public String getFamily() {
 1059           return getFamily_NoClientCode();
 1060       }
 1061       // NOTE: This method is called by privileged threads.
 1062       //       We implement this functionality in a package-private
 1063       //       method to insure that it cannot be overridden by client
 1064       //       subclasses.
 1065       //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
 1066       final String getFamily_NoClientCode() {
 1067           return getFamily(Locale.getDefault());
 1068       }
 1069   
 1070       /**
 1071        * Returns the family name of this <code>Font</code>, localized for
 1072        * the specified locale.
 1073        *
 1074        * <p>The family name of a font is font specific. Two fonts such as
 1075        * Helvetica Italic and Helvetica Bold have the same family name,
 1076        * <i>Helvetica</i>, whereas their font face names are
 1077        * <i>Helvetica Bold</i> and <i>Helvetica Italic</i>. The list of
 1078        * available family names may be obtained by using the
 1079        * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
 1080        *
 1081        * <p>Use <code>getFontName</code> to get the font face name of the font.
 1082        * @param l locale for which to get the family name
 1083        * @return a <code>String</code> representing the family name of the
 1084        *          font, localized for the specified locale.
 1085        * @see #getFontName
 1086        * @see java.util.Locale
 1087        * @since 1.2
 1088        */
 1089       public String getFamily(Locale l) {
 1090           if (l == null) {
 1091               throw new NullPointerException("null locale doesn't mean default");
 1092           }
 1093           return getFont2D().getFamilyName(l);
 1094       }
 1095   
 1096       /**
 1097        * Returns the postscript name of this <code>Font</code>.
 1098        * Use <code>getFamily</code> to get the family name of the font.
 1099        * Use <code>getFontName</code> to get the font face name of the font.
 1100        * @return a <code>String</code> representing the postscript name of
 1101        *          this <code>Font</code>.
 1102        * @since 1.2
 1103        */
 1104       public String getPSName() {
 1105           return getFont2D().getPostscriptName();
 1106       }
 1107   
 1108       /**
 1109        * Returns the logical name of this <code>Font</code>.
 1110        * Use <code>getFamily</code> to get the family name of the font.
 1111        * Use <code>getFontName</code> to get the font face name of the font.
 1112        * @return a <code>String</code> representing the logical name of
 1113        *          this <code>Font</code>.
 1114        * @see #getFamily
 1115        * @see #getFontName
 1116        * @since JDK1.0
 1117        */
 1118       public String getName() {
 1119           return name;
 1120       }
 1121   
 1122       /**
 1123        * Returns the font face name of this <code>Font</code>.  For example,
 1124        * Helvetica Bold could be returned as a font face name.
 1125        * Use <code>getFamily</code> to get the family name of the font.
 1126        * Use <code>getName</code> to get the logical name of the font.
 1127        * @return a <code>String</code> representing the font face name of
 1128        *          this <code>Font</code>.
 1129        * @see #getFamily
 1130        * @see #getName
 1131        * @since 1.2
 1132        */
 1133       public String getFontName() {
 1134         return getFontName(Locale.getDefault());
 1135       }
 1136   
 1137       /**
 1138        * Returns the font face name of the <code>Font</code>, localized
 1139        * for the specified locale. For example, Helvetica Fett could be
 1140        * returned as the font face name.
 1141        * Use <code>getFamily</code> to get the family name of the font.
 1142        * @param l a locale for which to get the font face name
 1143        * @return a <code>String</code> representing the font face name,
 1144        *          localized for the specified locale.
 1145        * @see #getFamily
 1146        * @see java.util.Locale
 1147        */
 1148       public String getFontName(Locale l) {
 1149           if (l == null) {
 1150               throw new NullPointerException("null locale doesn't mean default");
 1151           }
 1152           return getFont2D().getFontName(l);
 1153       }
 1154   
 1155       /**
 1156        * Returns the style of this <code>Font</code>.  The style can be
 1157        * PLAIN, BOLD, ITALIC, or BOLD+ITALIC.
 1158        * @return the style of this <code>Font</code>
 1159        * @see #isPlain
 1160        * @see #isBold
 1161        * @see #isItalic
 1162        * @since JDK1.0
 1163        */
 1164       public int getStyle() {
 1165           return style;
 1166       }
 1167   
 1168       /**
 1169        * Returns the point size of this <code>Font</code>, rounded to
 1170        * an integer.
 1171        * Most users are familiar with the idea of using <i>point size</i> to
 1172        * specify the size of glyphs in a font. This point size defines a
 1173        * measurement between the baseline of one line to the baseline of the
 1174        * following line in a single spaced text document. The point size is
 1175        * based on <i>typographic points</i>, approximately 1/72 of an inch.
 1176        * <p>
 1177        * The Java(tm)2D API adopts the convention that one point is
 1178        * equivalent to one unit in user coordinates.  When using a
 1179        * normalized transform for converting user space coordinates to
 1180        * device space coordinates 72 user
 1181        * space units equal 1 inch in device space.  In this case one point
 1182        * is 1/72 of an inch.
 1183        * @return the point size of this <code>Font</code> in 1/72 of an
 1184        *          inch units.
 1185        * @see #getSize2D
 1186        * @see GraphicsConfiguration#getDefaultTransform
 1187        * @see GraphicsConfiguration#getNormalizingTransform
 1188        * @since JDK1.0
 1189        */
 1190       public int getSize() {
 1191           return size;
 1192       }
 1193   
 1194       /**
 1195        * Returns the point size of this <code>Font</code> in
 1196        * <code>float</code> value.
 1197        * @return the point size of this <code>Font</code> as a
 1198        * <code>float</code> value.
 1199        * @see #getSize
 1200        * @since 1.2
 1201        */
 1202       public float getSize2D() {
 1203           return pointSize;
 1204       }
 1205   
 1206       /**
 1207        * Indicates whether or not this <code>Font</code> object's style is
 1208        * PLAIN.
 1209        * @return    <code>true</code> if this <code>Font</code> has a
 1210        *            PLAIN sytle;
 1211        *            <code>false</code> otherwise.
 1212        * @see       java.awt.Font#getStyle
 1213        * @since     JDK1.0
 1214        */
 1215       public boolean isPlain() {
 1216           return style == 0;
 1217       }
 1218   
 1219       /**
 1220        * Indicates whether or not this <code>Font</code> object's style is
 1221        * BOLD.
 1222        * @return    <code>true</code> if this <code>Font</code> object's
 1223        *            style is BOLD;
 1224        *            <code>false</code> otherwise.
 1225        * @see       java.awt.Font#getStyle
 1226        * @since     JDK1.0
 1227        */
 1228       public boolean isBold() {
 1229           return (style & BOLD) != 0;
 1230       }
 1231   
 1232       /**
 1233        * Indicates whether or not this <code>Font</code> object's style is
 1234        * ITALIC.
 1235        * @return    <code>true</code> if this <code>Font</code> object's
 1236        *            style is ITALIC;
 1237        *            <code>false</code> otherwise.
 1238        * @see       java.awt.Font#getStyle
 1239        * @since     JDK1.0
 1240        */
 1241       public boolean isItalic() {
 1242           return (style & ITALIC) != 0;
 1243       }
 1244   
 1245       /**
 1246        * Indicates whether or not this <code>Font</code> object has a
 1247        * transform that affects its size in addition to the Size
 1248        * attribute.
 1249        * @return  <code>true</code> if this <code>Font</code> object
 1250        *          has a non-identity AffineTransform attribute.
 1251        *          <code>false</code> otherwise.
 1252        * @see     java.awt.Font#getTransform
 1253        * @since   1.4
 1254        */
 1255       public boolean isTransformed() {
 1256           return nonIdentityTx;
 1257       }
 1258   
 1259       /**
 1260        * Return true if this Font contains attributes that require extra
 1261        * layout processing.
 1262        * @return true if the font has layout attributes
 1263        * @since 1.6
 1264        */
 1265       public boolean hasLayoutAttributes() {
 1266           return hasLayoutAttributes;
 1267       }
 1268   
 1269       /**
 1270        * Returns a <code>Font</code> object from the system properties list.
 1271        * <code>nm</code> is treated as the name of a system property to be
 1272        * obtained.  The <code>String</code> value of this property is then
 1273        * interpreted as a <code>Font</code> object according to the
 1274        * specification of <code>Font.decode(String)</code>
 1275        * If the specified property is not found, or the executing code does
 1276        * not have permission to read the property, null is returned instead.
 1277        *
 1278        * @param nm the property name
 1279        * @return a <code>Font</code> object that the property name
 1280        *          describes, or null if no such property exists.
 1281        * @throws NullPointerException if nm is null.
 1282        * @since 1.2
 1283        * @see #decode(String)
 1284        */
 1285       public static Font getFont(String nm) {
 1286           return getFont(nm, null);
 1287       }
 1288   
 1289       /**
 1290        * Returns the <code>Font</code> that the <code>str</code>
 1291        * argument describes.
 1292        * To ensure that this method returns the desired Font,
 1293        * format the <code>str</code> parameter in
 1294        * one of these ways
 1295        * <p>
 1296        * <ul>
 1297        * <li><em>fontname-style-pointsize</em>
 1298        * <li><em>fontname-pointsize</em>
 1299        * <li><em>fontname-style</em>
 1300        * <li><em>fontname</em>
 1301        * <li><em>fontname style pointsize</em>
 1302        * <li><em>fontname pointsize</em>
 1303        * <li><em>fontname style</em>
 1304        * <li><em>fontname</em>
 1305        * </ul>
 1306        * in which <i>style</i> is one of the four
 1307        * case-insensitive strings:
 1308        * <code>"PLAIN"</code>, <code>"BOLD"</code>, <code>"BOLDITALIC"</code>, or
 1309        * <code>"ITALIC"</code>, and pointsize is a positive decimal integer
 1310        * representation of the point size.
 1311        * For example, if you want a font that is Arial, bold, with
 1312        * a point size of 18, you would call this method with:
 1313        * "Arial-BOLD-18".
 1314        * This is equivalent to calling the Font constructor :
 1315        * <code>new Font("Arial", Font.BOLD, 18);</code>
 1316        * and the values are interpreted as specified by that constructor.
 1317        * <p>
 1318        * A valid trailing decimal field is always interpreted as the pointsize.
 1319        * Therefore a fontname containing a trailing decimal value should not
 1320        * be used in the fontname only form.
 1321        * <p>
 1322        * If a style name field is not one of the valid style strings, it is
 1323        * interpreted as part of the font name, and the default style is used.
 1324        * <p>
 1325        * Only one of ' ' or '-' may be used to separate fields in the input.
 1326        * The identified separator is the one closest to the end of the string
 1327        * which separates a valid pointsize, or a valid style name from
 1328        * the rest of the string.
 1329        * Null (empty) pointsize and style fields are treated
 1330        * as valid fields with the default value for that field.
 1331        *<p>
 1332        * Some font names may include the separator characters ' ' or '-'.
 1333        * If <code>str</code> is not formed with 3 components, e.g. such that
 1334        * <code>style</code> or <code>pointsize</code> fields are not present in
 1335        * <code>str</code>, and <code>fontname</code> also contains a
 1336        * character determined to be the separator character
 1337        * then these characters where they appear as intended to be part of
 1338        * <code>fontname</code> may instead be interpreted as separators
 1339        * so the font name may not be properly recognised.
 1340        *
 1341        * <p>
 1342        * The default size is 12 and the default style is PLAIN.
 1343        * If <code>str</code> does not specify a valid size, the returned
 1344        * <code>Font</code> has a size of 12.  If <code>str</code> does not
 1345        * specify a valid style, the returned Font has a style of PLAIN.
 1346        * If you do not specify a valid font name in
 1347        * the <code>str</code> argument, this method will return
 1348        * a font with the family name "Dialog".
 1349        * To determine what font family names are available on
 1350        * your system, use the
 1351        * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
 1352        * If <code>str</code> is <code>null</code>, a new <code>Font</code>
 1353        * is returned with the family name "Dialog", a size of 12 and a
 1354        * PLAIN style.
 1355        * @param str the name of the font, or <code>null</code>
 1356        * @return the <code>Font</code> object that <code>str</code>
 1357        *          describes, or a new default <code>Font</code> if
 1358        *          <code>str</code> is <code>null</code>.
 1359        * @see #getFamily
 1360        * @since JDK1.1
 1361        */
 1362       public static Font decode(String str) {
 1363           String fontName = str;
 1364           String styleName = "";
 1365           int fontSize = 12;
 1366           int fontStyle = Font.PLAIN;
 1367   
 1368           if (str == null) {
 1369               return new Font(DIALOG, fontStyle, fontSize);
 1370           }
 1371   
 1372           int lastHyphen = str.lastIndexOf('-');
 1373           int lastSpace = str.lastIndexOf(' ');
 1374           char sepChar = (lastHyphen > lastSpace) ? '-' : ' ';
 1375           int sizeIndex = str.lastIndexOf(sepChar);
 1376           int styleIndex = str.lastIndexOf(sepChar, sizeIndex-1);
 1377           int strlen = str.length();
 1378   
 1379           if (sizeIndex > 0 && sizeIndex+1 < strlen) {
 1380               try {
 1381                   fontSize =
 1382                       Integer.valueOf(str.substring(sizeIndex+1)).intValue();
 1383                   if (fontSize <= 0) {
 1384                       fontSize = 12;
 1385                   }
 1386               } catch (NumberFormatException e) {
 1387                   /* It wasn't a valid size, if we didn't also find the
 1388                    * start of the style string perhaps this is the style */
 1389                   styleIndex = sizeIndex;
 1390                   sizeIndex = strlen;
 1391                   if (str.charAt(sizeIndex-1) == sepChar) {
 1392                       sizeIndex--;
 1393                   }
 1394               }
 1395           }
 1396   
 1397           if (styleIndex >= 0 && styleIndex+1 < strlen) {
 1398               styleName = str.substring(styleIndex+1, sizeIndex);
 1399               styleName = styleName.toLowerCase(Locale.ENGLISH);
 1400               if (styleName.equals("bolditalic")) {
 1401                   fontStyle = Font.BOLD | Font.ITALIC;
 1402               } else if (styleName.equals("italic")) {
 1403                   fontStyle = Font.ITALIC;
 1404               } else if (styleName.equals("bold")) {
 1405                   fontStyle = Font.BOLD;
 1406               } else if (styleName.equals("plain")) {
 1407                   fontStyle = Font.PLAIN;
 1408               } else {
 1409                   /* this string isn't any of the expected styles, so
 1410                    * assume its part of the font name
 1411                    */
 1412                   styleIndex = sizeIndex;
 1413                   if (str.charAt(styleIndex-1) == sepChar) {
 1414                       styleIndex--;
 1415                   }
 1416               }
 1417               fontName = str.substring(0, styleIndex);
 1418   
 1419           } else {
 1420               int fontEnd = strlen;
 1421               if (styleIndex > 0) {
 1422                   fontEnd = styleIndex;
 1423               } else if (sizeIndex > 0) {
 1424                   fontEnd = sizeIndex;
 1425               }
 1426               if (fontEnd > 0 && str.charAt(fontEnd-1) == sepChar) {
 1427                   fontEnd--;
 1428               }
 1429               fontName = str.substring(0, fontEnd);
 1430           }
 1431   
 1432           return new Font(fontName, fontStyle, fontSize);
 1433       }
 1434   
 1435       /**
 1436        * Gets the specified <code>Font</code> from the system properties
 1437        * list.  As in the <code>getProperty</code> method of
 1438        * <code>System</code>, the first
 1439        * argument is treated as the name of a system property to be
 1440        * obtained.  The <code>String</code> value of this property is then
 1441        * interpreted as a <code>Font</code> object.
 1442        * <p>
 1443        * The property value should be one of the forms accepted by
 1444        * <code>Font.decode(String)</code>
 1445        * If the specified property is not found, or the executing code does not
 1446        * have permission to read the property, the <code>font</code>
 1447        * argument is returned instead.
 1448        * @param nm the case-insensitive property name
 1449        * @param font a default <code>Font</code> to return if property
 1450        *          <code>nm</code> is not defined
 1451        * @return    the <code>Font</code> value of the property.
 1452        * @throws NullPointerException if nm is null.
 1453        * @see #decode(String)
 1454        */
 1455       public static Font getFont(String nm, Font font) {
 1456           String str = null;
 1457           try {
 1458               str =System.getProperty(nm);
 1459           } catch(SecurityException e) {
 1460           }
 1461           if (str == null) {
 1462               return font;
 1463           }
 1464           return decode ( str );
 1465       }
 1466   
 1467       transient int hash;
 1468       /**
 1469        * Returns a hashcode for this <code>Font</code>.
 1470        * @return     a hashcode value for this <code>Font</code>.
 1471        * @since      JDK1.0
 1472        */
 1473       public int hashCode() {
 1474           if (hash == 0) {
 1475               hash = name.hashCode() ^ style ^ size;
 1476               /* It is possible many fonts differ only in transform.
 1477                * So include the transform in the hash calculation.
 1478                * nonIdentityTx is set whenever there is a transform in
 1479                * 'values'. The tests for null are required because it can
 1480                * also be set for other reasons.
 1481                */
 1482               if (nonIdentityTx &&
 1483                   values != null && values.getTransform() != null) {
 1484                   hash ^= values.getTransform().hashCode();
 1485               }
 1486           }
 1487           return hash;
 1488       }
 1489   
 1490       /**
 1491        * Compares this <code>Font</code> object to the specified
 1492        * <code>Object</code>.
 1493        * @param obj the <code>Object</code> to compare
 1494        * @return <code>true</code> if the objects are the same
 1495        *          or if the argument is a <code>Font</code> object
 1496        *          describing the same font as this object;
 1497        *          <code>false</code> otherwise.
 1498        * @since JDK1.0
 1499        */
 1500       public boolean equals(Object obj) {
 1501           if (obj == this) {
 1502               return true;
 1503           }
 1504   
 1505           if (obj != null) {
 1506               try {
 1507                   Font font = (Font)obj;
 1508                   if (size == font.size &&
 1509                       style == font.style &&
 1510                       nonIdentityTx == font.nonIdentityTx &&
 1511                       hasLayoutAttributes == font.hasLayoutAttributes &&
 1512                       pointSize == font.pointSize &&
 1513                       name.equals(font.name)) {
 1514   
 1515                       /* 'values' is usually initialized lazily, except when
 1516                        * the font is constructed from a Map, or derived using
 1517                        * a Map or other values. So if only one font has
 1518                        * the field initialized we need to initialize it in
 1519                        * the other instance and compare.
 1520                        */
 1521                       if (values == null) {
 1522                           if (font.values == null) {
 1523                               return true;
 1524                           } else {
 1525                               return getAttributeValues().equals(font.values);
 1526                           }
 1527                       } else {
 1528                           return values.equals(font.getAttributeValues());
 1529                       }
 1530                   }
 1531               }
 1532               catch (ClassCastException e) {
 1533               }
 1534           }
 1535           return false;
 1536       }
 1537   
 1538       /**
 1539        * Converts this <code>Font</code> object to a <code>String</code>
 1540        * representation.
 1541        * @return     a <code>String</code> representation of this
 1542        *          <code>Font</code> object.
 1543        * @since      JDK1.0
 1544        */
 1545       // NOTE: This method may be called by privileged threads.
 1546       //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
 1547       public String toString() {
 1548           String  strStyle;
 1549   
 1550           if (isBold()) {
 1551               strStyle = isItalic() ? "bolditalic" : "bold";
 1552           } else {
 1553               strStyle = isItalic() ? "italic" : "plain";
 1554           }
 1555   
 1556           return getClass().getName() + "[family=" + getFamily() + ",name=" + name + ",style=" +
 1557               strStyle + ",size=" + size + "]";
 1558       } // toString()
 1559   
 1560   
 1561       /** Serialization support.  A <code>readObject</code>
 1562        *  method is neccessary because the constructor creates
 1563        *  the font's peer, and we can't serialize the peer.
 1564        *  Similarly the computed font "family" may be different
 1565        *  at <code>readObject</code> time than at
 1566        *  <code>writeObject</code> time.  An integer version is
 1567        *  written so that future versions of this class will be
 1568        *  able to recognize serialized output from this one.
 1569        */
 1570       /**
 1571        * The <code>Font</code> Serializable Data Form.
 1572        *
 1573        * @serial
 1574        */
 1575       private int fontSerializedDataVersion = 1;
 1576   
 1577       /**
 1578        * Writes default serializable fields to a stream.
 1579        *
 1580        * @param s the <code>ObjectOutputStream</code> to write
 1581        * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
 1582        * @see #readObject(java.io.ObjectInputStream)
 1583        */
 1584       private void writeObject(java.io.ObjectOutputStream s)
 1585         throws java.lang.ClassNotFoundException,
 1586                java.io.IOException
 1587       {
 1588           if (values != null) {
 1589             synchronized(values) {
 1590               // transient
 1591               fRequestedAttributes = values.toSerializableHashtable();
 1592               s.defaultWriteObject();
 1593               fRequestedAttributes = null;
 1594             }
 1595           } else {
 1596             s.defaultWriteObject();
 1597           }
 1598       }
 1599   
 1600       /**
 1601        * Reads the <code>ObjectInputStream</code>.
 1602        * Unrecognized keys or values will be ignored.
 1603        *
 1604        * @param s the <code>ObjectInputStream</code> to read
 1605        * @serial
 1606        * @see #writeObject(java.io.ObjectOutputStream)
 1607        */
 1608       private void readObject(java.io.ObjectInputStream s)
 1609         throws java.lang.ClassNotFoundException,
 1610                java.io.IOException
 1611       {
 1612           s.defaultReadObject();
 1613           if (pointSize == 0) {
 1614               pointSize = (float)size;
 1615           }
 1616   
 1617           // Handle fRequestedAttributes.
 1618           // in 1.5, we always streamed out the font values plus
 1619           // TRANSFORM, SUPERSCRIPT, and WIDTH, regardless of whether the
 1620           // values were default or not.  In 1.6 we only stream out
 1621           // defined values.  So, 1.6 streams in from a 1.5 stream,
 1622           // it check each of these values and 'undefines' it if the
 1623           // value is the default.
 1624   
 1625           if (fRequestedAttributes != null) {
 1626               values = getAttributeValues(); // init
 1627               AttributeValues extras =
 1628                   AttributeValues.fromSerializableHashtable(fRequestedAttributes);
 1629               if (!AttributeValues.is16Hashtable(fRequestedAttributes)) {
 1630                   extras.unsetDefault(); // if legacy stream, undefine these
 1631               }
 1632               values = getAttributeValues().merge(extras);
 1633               this.nonIdentityTx = values.anyNonDefault(EXTRA_MASK);
 1634               this.hasLayoutAttributes =  values.anyNonDefault(LAYOUT_MASK);
 1635   
 1636               fRequestedAttributes = null; // don't need it any more
 1637           }
 1638       }
 1639   
 1640       /**
 1641        * Returns the number of glyphs in this <code>Font</code>. Glyph codes
 1642        * for this <code>Font</code> range from 0 to
 1643        * <code>getNumGlyphs()</code> - 1.
 1644        * @return the number of glyphs in this <code>Font</code>.
 1645        * @since 1.2
 1646        */
 1647       public int getNumGlyphs() {
 1648           return  getFont2D().getNumGlyphs();
 1649       }
 1650   
 1651       /**
 1652        * Returns the glyphCode which is used when this <code>Font</code>
 1653        * does not have a glyph for a specified unicode code point.
 1654        * @return the glyphCode of this <code>Font</code>.
 1655        * @since 1.2
 1656        */
 1657       public int getMissingGlyphCode() {
 1658           return getFont2D().getMissingGlyphCode();
 1659       }
 1660   
 1661       /**
 1662        * Returns the baseline appropriate for displaying this character.
 1663        * <p>
 1664        * Large fonts can support different writing systems, and each system can
 1665        * use a different baseline.
 1666        * The character argument determines the writing system to use. Clients
 1667        * should not assume all characters use the same baseline.
 1668        *
 1669        * @param c a character used to identify the writing system
 1670        * @return the baseline appropriate for the specified character.
 1671        * @see LineMetrics#getBaselineOffsets
 1672        * @see #ROMAN_BASELINE
 1673        * @see #CENTER_BASELINE
 1674        * @see #HANGING_BASELINE
 1675        * @since 1.2
 1676        */
 1677       public byte getBaselineFor(char c) {
 1678           return getFont2D().getBaselineFor(c);
 1679       }
 1680   
 1681       /**
 1682        * Returns a map of font attributes available in this
 1683        * <code>Font</code>.  Attributes include things like ligatures and
 1684        * glyph substitution.
 1685        * @return the attributes map of this <code>Font</code>.
 1686        */
 1687       public Map<TextAttribute,?> getAttributes(){
 1688           return new AttributeMap(getAttributeValues());
 1689       }
 1690   
 1691       /**
 1692        * Returns the keys of all the attributes supported by this
 1693        * <code>Font</code>.  These attributes can be used to derive other
 1694        * fonts.
 1695        * @return an array containing the keys of all the attributes
 1696        *          supported by this <code>Font</code>.
 1697        * @since 1.2
 1698        */
 1699       public Attribute[] getAvailableAttributes() {
 1700           // FONT is not supported by Font
 1701   
 1702           Attribute attributes[] = {
 1703               TextAttribute.FAMILY,
 1704               TextAttribute.WEIGHT,
 1705               TextAttribute.WIDTH,
 1706               TextAttribute.POSTURE,
 1707               TextAttribute.SIZE,
 1708               TextAttribute.TRANSFORM,
 1709               TextAttribute.SUPERSCRIPT,
 1710               TextAttribute.CHAR_REPLACEMENT,
 1711               TextAttribute.FOREGROUND,
 1712               TextAttribute.BACKGROUND,
 1713               TextAttribute.UNDERLINE,
 1714               TextAttribute.STRIKETHROUGH,
 1715               TextAttribute.RUN_DIRECTION,
 1716               TextAttribute.BIDI_EMBEDDING,
 1717               TextAttribute.JUSTIFICATION,
 1718               TextAttribute.INPUT_METHOD_HIGHLIGHT,
 1719               TextAttribute.INPUT_METHOD_UNDERLINE,
 1720               TextAttribute.SWAP_COLORS,
 1721               TextAttribute.NUMERIC_SHAPING,
 1722               TextAttribute.KERNING,
 1723               TextAttribute.LIGATURES,
 1724               TextAttribute.TRACKING,
 1725           };
 1726   
 1727           return attributes;
 1728       }
 1729   
 1730       /**
 1731        * Creates a new <code>Font</code> object by replicating this
 1732        * <code>Font</code> object and applying a new style and size.
 1733        * @param style the style for the new <code>Font</code>
 1734        * @param size the size for the new <code>Font</code>
 1735        * @return a new <code>Font</code> object.
 1736        * @since 1.2
 1737        */
 1738       public Font deriveFont(int style, float size){
 1739           if (values == null) {
 1740               return new Font(name, style, size, createdFont, font2DHandle);
 1741           }
 1742           AttributeValues newValues = getAttributeValues().clone();
 1743           int oldStyle = (this.style != style) ? this.style : -1;
 1744           applyStyle(style, newValues);
 1745           newValues.setSize(size);
 1746           return new Font(newValues, null, oldStyle, createdFont, font2DHandle);
 1747       }
 1748   
 1749       /**
 1750        * Creates a new <code>Font</code> object by replicating this
 1751        * <code>Font</code> object and applying a new style and transform.
 1752        * @param style the style for the new <code>Font</code>
 1753        * @param trans the <code>AffineTransform</code> associated with the
 1754        * new <code>Font</code>
 1755        * @return a new <code>Font</code> object.
 1756        * @throws IllegalArgumentException if <code>trans</code> is
 1757        *         <code>null</code>
 1758        * @since 1.2
 1759        */
 1760       public Font deriveFont(int style, AffineTransform trans){
 1761           AttributeValues newValues = getAttributeValues().clone();
 1762           int oldStyle = (this.style != style) ? this.style : -1;
 1763           applyStyle(style, newValues);
 1764           applyTransform(trans, newValues);
 1765           return new Font(newValues, null, oldStyle, createdFont, font2DHandle);
 1766       }
 1767   
 1768       /**
 1769        * Creates a new <code>Font</code> object by replicating the current
 1770        * <code>Font</code> object and applying a new size to it.
 1771        * @param size the size for the new <code>Font</code>.
 1772        * @return a new <code>Font</code> object.
 1773        * @since 1.2
 1774        */
 1775       public Font deriveFont(float size){
 1776           if (values == null) {
 1777               return new Font(name, style, size, createdFont, font2DHandle);
 1778           }
 1779           AttributeValues newValues = getAttributeValues().clone();
 1780           newValues.setSize(size);
 1781           return new Font(newValues, null, -1, createdFont, font2DHandle);
 1782       }
 1783   
 1784       /**
 1785        * Creates a new <code>Font</code> object by replicating the current
 1786        * <code>Font</code> object and applying a new transform to it.
 1787        * @param trans the <code>AffineTransform</code> associated with the
 1788        * new <code>Font</code>
 1789        * @return a new <code>Font</code> object.
 1790        * @throws IllegalArgumentException if <code>trans</code> is
 1791        *         <code>null</code>
 1792        * @since 1.2
 1793        */
 1794       public Font deriveFont(AffineTransform trans){
 1795           AttributeValues newValues = getAttributeValues().clone();
 1796           applyTransform(trans, newValues);
 1797           return new Font(newValues, null, -1, createdFont, font2DHandle);
 1798       }
 1799   
 1800       /**
 1801        * Creates a new <code>Font</code> object by replicating the current
 1802        * <code>Font</code> object and applying a new style to it.
 1803        * @param style the style for the new <code>Font</code>
 1804        * @return a new <code>Font</code> object.
 1805        * @since 1.2
 1806        */
 1807       public Font deriveFont(int style){
 1808           if (values == null) {
 1809              return new Font(name, style, size, createdFont, font2DHandle);
 1810           }
 1811           AttributeValues newValues = getAttributeValues().clone();
 1812           int oldStyle = (this.style != style) ? this.style : -1;
 1813           applyStyle(style, newValues);
 1814           return new Font(newValues, null, oldStyle, createdFont, font2DHandle);
 1815       }
 1816   
 1817       /**
 1818        * Creates a new <code>Font</code> object by replicating the current
 1819        * <code>Font</code> object and applying a new set of font attributes
 1820        * to it.
 1821        *
 1822        * @param attributes a map of attributes enabled for the new
 1823        * <code>Font</code>
 1824        * @return a new <code>Font</code> object.
 1825        * @since 1.2
 1826        */
 1827       public Font deriveFont(Map<? extends Attribute, ?> attributes) {
 1828           if (attributes == null) {
 1829               return this;
 1830           }
 1831           AttributeValues newValues = getAttributeValues().clone();
 1832           newValues.merge(attributes, RECOGNIZED_MASK);
 1833   
 1834           return new Font(newValues, name, style, createdFont, font2DHandle);
 1835       }
 1836   
 1837       /**
 1838        * Checks if this <code>Font</code> has a glyph for the specified
 1839        * character.
 1840        *
 1841        * <p> <b>Note:</b> This method cannot handle <a
 1842        * href="../../java/lang/Character.html#supplementary"> supplementary
 1843        * characters</a>. To support all Unicode characters, including
 1844        * supplementary characters, use the {@link #canDisplay(int)}
 1845        * method or <code>canDisplayUpTo</code> methods.
 1846        *
 1847        * @param c the character for which a glyph is needed
 1848        * @return <code>true</code> if this <code>Font</code> has a glyph for this
 1849        *          character; <code>false</code> otherwise.
 1850        * @since 1.2
 1851        */
 1852       public boolean canDisplay(char c){
 1853           return getFont2D().canDisplay(c);
 1854       }
 1855   
 1856       /**
 1857        * Checks if this <code>Font</code> has a glyph for the specified
 1858        * character.
 1859        *
 1860        * @param codePoint the character (Unicode code point) for which a glyph
 1861        *        is needed.
 1862        * @return <code>true</code> if this <code>Font</code> has a glyph for the
 1863        *          character; <code>false</code> otherwise.
 1864        * @throws IllegalArgumentException if the code point is not a valid Unicode
 1865        *          code point.
 1866        * @see Character#isValidCodePoint(int)
 1867        * @since 1.5
 1868        */
 1869       public boolean canDisplay(int codePoint) {
 1870           if (!Character.isValidCodePoint(codePoint)) {
 1871               throw new IllegalArgumentException("invalid code point: " +
 1872                                                  Integer.toHexString(codePoint));
 1873           }
 1874           return getFont2D().canDisplay(codePoint);
 1875       }
 1876   
 1877       /**
 1878        * Indicates whether or not this <code>Font</code> can display a
 1879        * specified <code>String</code>.  For strings with Unicode encoding,
 1880        * it is important to know if a particular font can display the
 1881        * string. This method returns an offset into the <code>String</code>
 1882        * <code>str</code> which is the first character this
 1883        * <code>Font</code> cannot display without using the missing glyph
 1884        * code. If the <code>Font</code> can display all characters, -1 is
 1885        * returned.
 1886        * @param str a <code>String</code> object
 1887        * @return an offset into <code>str</code> that points
 1888        *          to the first character in <code>str</code> that this
 1889        *          <code>Font</code> cannot display; or <code>-1</code> if
 1890        *          this <code>Font</code> can display all characters in
 1891        *          <code>str</code>.
 1892        * @since 1.2
 1893        */
 1894       public int canDisplayUpTo(String str) {
 1895           return canDisplayUpTo(new StringCharacterIterator(str), 0,
 1896               str.length());
 1897       }
 1898   
 1899       /**
 1900        * Indicates whether or not this <code>Font</code> can display
 1901        * the characters in the specified <code>text</code>
 1902        * starting at <code>start</code> and ending at
 1903        * <code>limit</code>.  This method is a convenience overload.
 1904        * @param text the specified array of <code>char</code> values
 1905        * @param start the specified starting offset (in
 1906        *              <code>char</code>s) into the specified array of
 1907        *              <code>char</code> values
 1908        * @param limit the specified ending offset (in
 1909        *              <code>char</code>s) into the specified array of
 1910        *              <code>char</code> values
 1911        * @return an offset into <code>text</code> that points
 1912        *          to the first character in <code>text</code> that this
 1913        *          <code>Font</code> cannot display; or <code>-1</code> if
 1914        *          this <code>Font</code> can display all characters in
 1915        *          <code>text</code>.
 1916        * @since 1.2
 1917        */
 1918       public int canDisplayUpTo(char[] text, int start, int limit) {
 1919           while (start < limit && canDisplay(text[start])) {
 1920               ++start;
 1921           }
 1922   
 1923           return start == limit ? -1 : start;
 1924       }
 1925   
 1926       /**
 1927        * Indicates whether or not this <code>Font</code> can display the
 1928        * text specified by the <code>iter</code> starting at
 1929        * <code>start</code> and ending at <code>limit</code>.
 1930        *
 1931        * @param iter  a {@link CharacterIterator} object
 1932        * @param start the specified starting offset into the specified
 1933        *              <code>CharacterIterator</code>.
 1934        * @param limit the specified ending offset into the specified
 1935        *              <code>CharacterIterator</code>.
 1936        * @return an offset into <code>iter</code> that points
 1937        *          to the first character in <code>iter</code> that this
 1938        *          <code>Font</code> cannot display; or <code>-1</code> if
 1939        *          this <code>Font</code> can display all characters in
 1940        *          <code>iter</code>.
 1941        * @since 1.2
 1942        */
 1943       public int canDisplayUpTo(CharacterIterator iter, int start, int limit) {
 1944           for (char c = iter.setIndex(start);
 1945                iter.getIndex() < limit && canDisplay(c);
 1946                c = iter.next()) {
 1947           }
 1948   
 1949           int result = iter.getIndex();
 1950           return result == limit ? -1 : result;
 1951       }
 1952   
 1953       /**
 1954        * Returns the italic angle of this <code>Font</code>.  The italic angle
 1955        * is the inverse slope of the caret which best matches the posture of this
 1956        * <code>Font</code>.
 1957        * @see TextAttribute#POSTURE
 1958        * @return the angle of the ITALIC style of this <code>Font</code>.
 1959        */
 1960       public float getItalicAngle() {
 1961           return getItalicAngle(null);
 1962       }
 1963   
 1964       /* The FRC hints don't affect the value of the italic angle but
 1965        * we need to pass them in to look up a strike.
 1966        * If we can pass in ones already being used it can prevent an extra
 1967        * strike from being allocated. Note that since italic angle is
 1968        * a property of the font, the font transform is needed not the
 1969        * device transform. Finally, this is private but the only caller of this
 1970        * in the JDK - and the only likely caller - is in this same class.
 1971        */
 1972       private float getItalicAngle(FontRenderContext frc) {
 1973           Object aa, fm;
 1974           if (frc == null) {
 1975               aa = RenderingHints.VALUE_TEXT_ANTIALIAS_OFF;
 1976               fm = RenderingHints.VALUE_FRACTIONALMETRICS_OFF;
 1977           } else {
 1978               aa = frc.getAntiAliasingHint();
 1979               fm = frc.getFractionalMetricsHint();
 1980           }
 1981           return getFont2D().getItalicAngle(this, identityTx, aa, fm);
 1982       }
 1983   
 1984       /**
 1985        * Checks whether or not this <code>Font</code> has uniform
 1986        * line metrics.  A logical <code>Font</code> might be a
 1987        * composite font, which means that it is composed of different
 1988        * physical fonts to cover different code ranges.  Each of these
 1989        * fonts might have different <code>LineMetrics</code>.  If the
 1990        * logical <code>Font</code> is a single
 1991        * font then the metrics would be uniform.
 1992        * @return <code>true</code> if this <code>Font</code> has
 1993        * uniform line metrics; <code>false</code> otherwise.
 1994        */
 1995       public boolean hasUniformLineMetrics() {
 1996           return false;   // REMIND always safe, but prevents caller optimize
 1997       }
 1998   
 1999       private transient SoftReference flmref;
 2000       private FontLineMetrics defaultLineMetrics(FontRenderContext frc) {
 2001           FontLineMetrics flm = null;
 2002           if (flmref == null
 2003               || (flm = (FontLineMetrics)flmref.get()) == null
 2004               || !flm.frc.equals(frc)) {
 2005   
 2006               /* The device transform in the frc is not used in obtaining line
 2007                * metrics, although it probably should be: REMIND find why not?
 2008                * The font transform is used but its applied in getFontMetrics, so
 2009                * just pass identity here
 2010                */
 2011               float [] metrics = new float[8];
 2012               getFont2D().getFontMetrics(this, identityTx,
 2013                                          frc.getAntiAliasingHint(),
 2014                                          frc.getFractionalMetricsHint(),
 2015                                          metrics);
 2016               float ascent  = metrics[0];
 2017               float descent = metrics[1];
 2018               float leading = metrics[2];
 2019               float ssOffset = 0;
 2020               if (values != null && values.getSuperscript() != 0) {
 2021                   ssOffset = (float)getTransform().getTranslateY();
 2022                   ascent -= ssOffset;
 2023                   descent += ssOffset;
 2024               }
 2025               float height = ascent + descent + leading;
 2026   
 2027               int baselineIndex = 0; // need real index, assumes roman for everything
 2028               // need real baselines eventually
 2029               float[] baselineOffsets = { 0, (descent/2f - ascent) / 2f, -ascent };
 2030   
 2031               float strikethroughOffset = metrics[4];
 2032               float strikethroughThickness = metrics[5];
 2033   
 2034               float underlineOffset = metrics[6];
 2035               float underlineThickness = metrics[7];
 2036   
 2037               float italicAngle = getItalicAngle(frc);
 2038   
 2039               if (isTransformed()) {
 2040                   AffineTransform ctx = values.getCharTransform(); // extract rotation
 2041                   if (ctx != null) {
 2042                       Point2D.Float pt = new Point2D.Float();
 2043                       pt.setLocation(0, strikethroughOffset);
 2044                       ctx.deltaTransform(pt, pt);
 2045                       strikethroughOffset = pt.y;
 2046                       pt.setLocation(0, strikethroughThickness);
 2047                       ctx.deltaTransform(pt, pt);
 2048                       strikethroughThickness = pt.y;
 2049                       pt.setLocation(0, underlineOffset);
 2050                       ctx.deltaTransform(pt, pt);
 2051                       underlineOffset = pt.y;
 2052                       pt.setLocation(0, underlineThickness);
 2053                       ctx.deltaTransform(pt, pt);
 2054                       underlineThickness = pt.y;
 2055                   }
 2056               }
 2057               strikethroughOffset += ssOffset;
 2058               underlineOffset += ssOffset;
 2059   
 2060               CoreMetrics cm = new CoreMetrics(ascent, descent, leading, height,
 2061                                                baselineIndex, baselineOffsets,
 2062                                                strikethroughOffset, strikethroughThickness,
 2063                                                underlineOffset, underlineThickness,
 2064                                                ssOffset, italicAngle);
 2065   
 2066               flm = new FontLineMetrics(0, cm, frc);
 2067               flmref = new SoftReference(flm);
 2068           }
 2069   
 2070           return (FontLineMetrics)flm.clone();
 2071       }
 2072   
 2073       /**
 2074        * Returns a {@link LineMetrics} object created with the specified
 2075        * <code>String</code> and {@link FontRenderContext}.
 2076        * @param str the specified <code>String</code>
 2077        * @param frc the specified <code>FontRenderContext</code>
 2078        * @return a <code>LineMetrics</code> object created with the
 2079        * specified <code>String</code> and {@link FontRenderContext}.
 2080        */
 2081       public LineMetrics getLineMetrics( String str, FontRenderContext frc) {
 2082           FontLineMetrics flm = defaultLineMetrics(frc);
 2083           flm.numchars = str.length();
 2084           return flm;
 2085       }
 2086   
 2087       /**
 2088        * Returns a <code>LineMetrics</code> object created with the
 2089        * specified arguments.
 2090        * @param str the specified <code>String</code>
 2091        * @param beginIndex the initial offset of <code>str</code>
 2092        * @param limit the end offset of <code>str</code>
 2093        * @param frc the specified <code>FontRenderContext</code>
 2094        * @return a <code>LineMetrics</code> object created with the
 2095        * specified arguments.
 2096        */
 2097       public LineMetrics getLineMetrics( String str,
 2098                                       int beginIndex, int limit,
 2099                                       FontRenderContext frc) {
 2100           FontLineMetrics flm = defaultLineMetrics(frc);
 2101           int numChars = limit - beginIndex;
 2102           flm.numchars = (numChars < 0)? 0: numChars;
 2103           return flm;
 2104       }
 2105   
 2106       /**
 2107        * Returns a <code>LineMetrics</code> object created with the
 2108        * specified arguments.
 2109        * @param chars an array of characters
 2110        * @param beginIndex the initial offset of <code>chars</code>
 2111        * @param limit the end offset of <code>chars</code>
 2112        * @param frc the specified <code>FontRenderContext</code>
 2113        * @return a <code>LineMetrics</code> object created with the
 2114        * specified arguments.
 2115        */
 2116       public LineMetrics getLineMetrics(char [] chars,
 2117                                       int beginIndex, int limit,
 2118                                       FontRenderContext frc) {
 2119           FontLineMetrics flm = defaultLineMetrics(frc);
 2120           int numChars = limit - beginIndex;
 2121           flm.numchars = (numChars < 0)? 0: numChars;
 2122           return flm;
 2123       }
 2124   
 2125       /**
 2126        * Returns a <code>LineMetrics</code> object created with the
 2127        * specified arguments.
 2128        * @param ci the specified <code>CharacterIterator</code>
 2129        * @param beginIndex the initial offset in <code>ci</code>
 2130        * @param limit the end offset of <code>ci</code>
 2131        * @param frc the specified <code>FontRenderContext</code>
 2132        * @return a <code>LineMetrics</code> object created with the
 2133        * specified arguments.
 2134        */
 2135       public LineMetrics getLineMetrics(CharacterIterator ci,
 2136                                       int beginIndex, int limit,
 2137                                       FontRenderContext frc) {
 2138           FontLineMetrics flm = defaultLineMetrics(frc);
 2139           int numChars = limit - beginIndex;
 2140           flm.numchars = (numChars < 0)? 0: numChars;
 2141           return flm;
 2142       }
 2143   
 2144       /**
 2145        * Returns the logical bounds of the specified <code>String</code> in
 2146        * the specified <code>FontRenderContext</code>.  The logical bounds
 2147        * contains the origin, ascent, advance, and height, which includes
 2148        * the leading.  The logical bounds does not always enclose all the
 2149        * text.  For example, in some languages and in some fonts, accent
 2150        * marks can be positioned above the ascent or below the descent.
 2151        * To obtain a visual bounding box, which encloses all the text,
 2152        * use the {@link TextLayout#getBounds() getBounds} method of
 2153        * <code>TextLayout</code>.
 2154        * <p>Note: The returned bounds is in baseline-relative coordinates
 2155        * (see {@link java.awt.Font class notes}).
 2156        * @param str the specified <code>String</code>
 2157        * @param frc the specified <code>FontRenderContext</code>
 2158        * @return a {@link Rectangle2D} that is the bounding box of the
 2159        * specified <code>String</code> in the specified
 2160        * <code>FontRenderContext</code>.
 2161        * @see FontRenderContext
 2162        * @see Font#createGlyphVector
 2163        * @since 1.2
 2164        */
 2165       public Rectangle2D getStringBounds( String str, FontRenderContext frc) {
 2166           char[] array = str.toCharArray();
 2167           return getStringBounds(array, 0, array.length, frc);
 2168       }
 2169   
 2170      /**
 2171        * Returns the logical bounds of the specified <code>String</code> in
 2172        * the specified <code>FontRenderContext</code>.  The logical bounds
 2173        * contains the origin, ascent, advance, and height, which includes
 2174        * the leading.  The logical bounds does not always enclose all the
 2175        * text.  For example, in some languages and in some fonts, accent
 2176        * marks can be positioned above the ascent or below the descent.
 2177        * To obtain a visual bounding box, which encloses all the text,
 2178        * use the {@link TextLayout#getBounds() getBounds} met