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