Home » openjdk-7 » java » awt » [javadoc | source]

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

Home » openjdk-7 » java » awt » [javadoc | source]