1 /*
2  * Copyright (c) 1995, 2017, 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.EventListener;
45 import java.util.Hashtable;
46 import java.util.Locale;
47 import java.util.Map;
48
49 import sun.awt.ComponentFactory;
50 import sun.font.StandardGlyphVector;
51
52 import sun.font.AttributeMap;
53 import sun.font.AttributeValues;
54 import sun.font.CompositeFont;
55 import sun.font.CreatedFontTracker;
56 import sun.font.Font2D;
57 import sun.font.Font2DHandle;
58 import sun.font.FontAccess;
59 import sun.font.FontDesignMetrics;
60 import sun.font.FontManager;
61 import sun.font.FontManagerFactory;
62 import sun.font.FontUtilities;
63 import sun.font.GlyphLayout;
64 import sun.font.FontLineMetrics;
65 import sun.font.CoreMetrics;
66
67 import static sun.font.EAttribute.*;
68
69 /**
70  * The {@code Font} class represents fonts, which are used to
71  * render text in a visible way.
72  * A font provides the information needed to map sequences of
73  * <em>characters</em> to sequences of <em>glyphs</em>
74  * and to render sequences of glyphs on {@code Graphics} and
75  * {@code Component} objects.
76  *
77  * <h3>Characters and Glyphs</h3>
78  *
79  * A <em>character</em> is a symbol that represents an item such as a letter,
80  * a digit, or punctuation in an abstract way. For example, {@code 'g'},
81  * LATIN SMALL LETTER G, is a character.
82  * <p>
83  * A <em>glyph</em> is a shape used to render a character or a sequence of
84  * characters. In simple writing systems, such as Latin, typically one glyph
85  * represents one character. In general, however, characters and glyphs do not
86  * have one-to-one correspondence. For example, the character '&aacute;'
87  * LATIN SMALL LETTER A WITH ACUTE, can be represented by
88  * two glyphs: one for 'a' and one for '&acute;'. On the other hand, the
89  * two-character string "fi" can be represented by a single glyph, an
90  * "fi" ligature. In complex writing systems, such as Arabic or the South
91  * and South-East Asian writing systems, the relationship between characters
92  * and glyphs can be more complicated and involve context-dependent selection
93  * of glyphs as well as glyph reordering.
94  *
95  * A font encapsulates the collection of glyphs needed to render a selected set
96  * of characters as well as the tables needed to map sequences of characters to
97  * corresponding sequences of glyphs.
98  *
99  * <h3>Physical and Logical Fonts</h3>
100  *
101  * The Java Platform distinguishes between two kinds of fonts:
102  * <em>physical</em> fonts and <em>logical</em> fonts.
103  * <p>
104  * <em>Physical</em> fonts are the actual font libraries containing glyph data
105  * and tables to map from character sequences to glyph sequences, using a font
106  * technology such as TrueType or PostScript Type 1.
107  * All implementations of the Java Platform must support TrueType fonts;
108  * support for other font technologies is implementation dependent.
109  * Physical fonts may use names such as Helvetica, Palatino, HonMincho, or
110  * any number of other font names.
111  * Typically, each physical font supports only a limited set of writing
112  * systems, for example, only Latin characters or only Japanese and Basic
113  * Latin.
114  * The set of available physical fonts varies between configurations.
115  * Applications that require specific fonts can bundle them and instantiate
116  * them using the {@link #createFont createFont} method.
117  * <p>
118  * <em>Logical</em> fonts are the five font families defined by the Java
119  * platform which must be supported by any Java runtime environment:
120  * Serif, SansSerif, Monospaced, Dialog, and DialogInput.
121  * These logical fonts are not actual font libraries. Instead, the logical
122  * font names are mapped to physical fonts by the Java runtime environment.
123  * The mapping is implementation and usually locale dependent, so the look
124  * and the metrics provided by them vary.
125  * Typically, each logical font name maps to several physical fonts in order to
126  * cover a large range of characters.
127  * <p>
128  * Peered AWT components, such as {@link Label Label} and
129  * {@link TextField TextField}, can only use logical fonts.
130  * <p>
131  * For a discussion of the relative advantages and disadvantages of using
132  * physical or logical fonts, see the
133  * <a href="https://docs.oracle.com/javase/tutorial/2d/text/fonts.html#advantages-and-disadvantages">
134  *    Physical and Logical Fonts</a>
135  * in <a href="https://docs.oracle.com/javase/tutorial/index.html">The Java Tutorials</a>
136  * document.
137  *
138  * <h3>Font Faces and Names</h3>
139  *
140  * A {@code Font}
141  * can have many faces, such as heavy, medium, oblique, gothic and
142  * regular. All of these faces have similar typographic design.
143  * <p>
144  * There are three different names that you can get from a
145  * {@code Font} object.  The <em>logical font name</em> is simply the
146  * name that was used to construct the font.
147  * The <em>font face name</em>, or just <em>font name</em> for
148  * short, is the name of a particular font face, like Helvetica Bold. The
149  * <em>family name</em> is the name of the font family that determines the
150  * typographic design across several faces, like Helvetica.
151  * <p>
152  * The {@code Font} class represents an instance of a font face from
153  * a collection of  font faces that are present in the system resources
154  * of the host system.  As examples, Arial Bold and Courier Bold Italic
155  * are font faces.  There can be several {@code Font} objects
156  * associated with a font face, each differing in size, style, transform
157  * and font features.
158  * <p>
159  * Glyphs may not always be rendered with the requested properties (e.g, font
160  * and style) due to platform limitations such as the absence of suitable
161  * platform fonts to implement a logical font.
162  * <p>
163  * The {@link GraphicsEnvironment#getAllFonts() getAllFonts} method
164  * of the {@code GraphicsEnvironment} class returns an
165  * array of all font faces available in the system. These font faces are
166  * returned as {@code Font} objects with a size of 1, identity
167  * transform and default font features. These
168  * base fonts can then be used to derive new {@code Font} objects
169  * with varying sizes, styles, transforms and font features via the
170  * {@code deriveFont} methods in this class.
171  *
172  * <h3>Font and TextAttribute</h3>
173  *
174  * <p>{@code Font} supports most
175  * {@code TextAttribute}s.  This makes some operations, such as
176  * rendering underlined text, convenient since it is not
177  * necessary to explicitly construct a {@code TextLayout} object.
178  * Attributes can be set on a Font by constructing or deriving it
179  * using a {@code Map} of {@code TextAttribute} values.
180  *
181  * <p>The values of some {@code TextAttributes} are not
182  * serializable, and therefore attempting to serialize an instance of
183  * {@code Font} that has such values will not serialize them.
184  * This means a Font deserialized from such a stream will not compare
185  * equal to the original Font that contained the non-serializable
186  * attributes.  This should very rarely pose a problem
187  * since these attributes are typically used only in special
188  * circumstances and are unlikely to be serialized.
189  *
190  * <ul>
191  * <li>{@code FOREGROUND} and {@code BACKGROUND} use
192  * {@code Paint} values. The subclass {@code Color} is
193  * serializable, while {@code GradientPaint} and
194  * {@code TexturePaint} are not.</li>
195  * <li>{@code CHAR_REPLACEMENT} uses
196  * {@code GraphicAttribute} values.  The subclasses
197  * {@code ShapeGraphicAttribute} and
198  * {@code ImageGraphicAttribute} are not serializable.</li>
199  * <li>{@code INPUT_METHOD_HIGHLIGHT} uses
200  * {@code InputMethodHighlight} values, which are
201  * not serializable.  See {@link java.awt.im.InputMethodHighlight}.</li>
202  * </ul>
203  *
204  * <p>Clients who create custom subclasses of {@code Paint} and
205  * {@code GraphicAttribute} can make them serializable and
206  * avoid this problem.  Clients who use input method highlights can
207  * convert these to the platform-specific attributes for that
208  * highlight on the current platform and set them on the Font as
209  * a workaround.
210  *
211  * <p>The {@code Map}-based constructor and
212  * {@code deriveFont} APIs ignore the FONT attribute, and it is
213  * not retained by the Font; the static {@link #getFont} method should
214  * be used if the FONT attribute might be present.  See {@link
215  * java.awt.font.TextAttribute#FONT} for more information.</p>
216  *
217  * <p>Several attributes will cause additional rendering overhead
218  * and potentially invoke layout.  If a {@code Font} has such
219  * attributes, the <code>{@link #hasLayoutAttributes()}</code> method
220  * will return true.</p>
221  *
222  * <p>Note: Font rotations can cause text baselines to be rotated.  In
223  * order to account for this (rare) possibility, font APIs are
224  * specified to return metrics and take parameters 'in
225  * baseline-relative coordinates'.  This maps the 'x' coordinate to
226  * the advance along the baseline, (positive x is forward along the
227  * baseline), and the 'y' coordinate to a distance along the
228  * perpendicular to the baseline at 'x' (positive y is 90 degrees
229  * clockwise from the baseline vector).  APIs for which this is
230  * especially important are called out as having 'baseline-relative
231  * coordinates.'
232  */

233 public class Font implements java.io.Serializable
234 {
235     private static class FontAccessImpl extends FontAccess {
236         public Font2D getFont2D(Font font) {
237             return font.getFont2D();
238         }
239
240         public void setFont2D(Font font, Font2DHandle handle) {
241             font.font2DHandle = handle;
242         }
243
244         public void setCreatedFont(Font font) {
245             font.createdFont = true;
246         }
247
248         public boolean isCreatedFont(Font font) {
249             return font.createdFont;
250         }
251
252         @Override
253         public FontPeer getFontPeer(final Font font) {
254             return font.getFontPeer();
255         }
256     }
257
258     static {
259         /* ensure that the necessary native libraries are loaded */
260         Toolkit.loadLibraries();
261         initIDs();
262         FontAccess.setFontAccess(new FontAccessImpl());
263     }
264
265     /**
266      * This is now only used during serialization.  Typically
267      * it is null.
268      *
269      * @serial
270      * @see #getAttributes()
271      */

272     private Hashtable<Object, Object> fRequestedAttributes;
273
274     /*
275      * Constants to be used for logical font family names.
276      */

277
278     /**
279      * A String constant for the canonical family name of the
280      * logical font "Dialog". 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 = "Dialog";
285
286     /**
287      * A String constant for the canonical family name of the
288      * logical font "DialogInput". 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 DIALOG_INPUT = "DialogInput";
293
294     /**
295      * A String constant for the canonical family name of the
296      * logical font "SansSerif". 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 SANS_SERIF = "SansSerif";
301
302     /**
303      * A String constant for the canonical family name of the
304      * logical font "Serif". 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 SERIF = "Serif";
309
310     /**
311      * A String constant for the canonical family name of the
312      * logical font "Monospaced". It is useful in Font construction
313      * to provide compile-time verification of the name.
314      * @since 1.6
315      */

316     public static final String MONOSPACED = "Monospaced";
317
318     /*
319      * Constants to be used for styles. Can be combined to mix
320      * styles.
321      */

322
323     /**
324      * The plain style constant.
325      */

326     public static final int PLAIN       = 0;
327
328     /**
329      * The bold style constant.  This can be combined with the other style
330      * constants (except PLAIN) for mixed styles.
331      */

332     public static final int BOLD        = 1;
333
334     /**
335      * The italicized style constant.  This can be combined with the other
336      * style constants (except PLAIN) for mixed styles.
337      */

338     public static final int ITALIC      = 2;
339
340     /**
341      * The baseline used in most Roman scripts when laying out text.
342      */

343     public static final int ROMAN_BASELINE = 0;
344
345     /**
346      * The baseline used in ideographic scripts like Chinese, Japanese,
347      * and Korean when laying out text.
348      */

349     public static final int CENTER_BASELINE = 1;
350
351     /**
352      * The baseline used in Devanagari and similar scripts when laying
353      * out text.
354      */

355     public static final int HANGING_BASELINE = 2;
356
357     /**
358      * Identify a font resource of type TRUETYPE.
359      * Used to specify a TrueType font resource to the
360      * {@link #createFont} method.
361      * The TrueType format was extended to become the OpenType
362      * format, which adds support for fonts with Postscript outlines,
363      * this tag therefore references these fonts, as well as those
364      * with TrueType outlines.
365      * @since 1.3
366      */

367
368     public static final int TRUETYPE_FONT = 0;
369
370     /**
371      * Identify a font resource of type TYPE1.
372      * Used to specify a Type1 font resource to the
373      * {@link #createFont} method.
374      * @since 1.5
375      */

376     public static final int TYPE1_FONT = 1;
377
378     /**
379      * The logical name of this {@code Font}, as passed to the
380      * constructor.
381      * @since 1.0
382      *
383      * @serial
384      * @see #getName
385      */

386     protected String name;
387
388     /**
389      * The style of this {@code Font}, as passed to the constructor.
390      * This style can be PLAIN, BOLD, ITALIC, or BOLD+ITALIC.
391      * @since 1.0
392      *
393      * @serial
394      * @see #getStyle()
395      */

396     protected int style;
397
398     /**
399      * The point size of this {@code Font}, rounded to integer.
400      * @since 1.0
401      *
402      * @serial
403      * @see #getSize()
404      */

405     protected int size;
406
407     /**
408      * The point size of this {@code Font} in {@code float}.
409      *
410      * @serial
411      * @see #getSize()
412      * @see #getSize2D()
413      */

414     protected float pointSize;
415
416     /**
417      * The platform specific font information.
418      */

419     private transient FontPeer peer;
420     private transient long pData;       // native JDK1.1 font pointer
421     private transient Font2DHandle font2DHandle;
422
423     private transient AttributeValues values;
424     private transient boolean hasLayoutAttributes;
425
426     /*
427      * If the origin of a Font is a created font then this attribute
428      * must be set on all derived fonts too.
429      */

430     private transient boolean createdFont = false;
431
432     /*
433      * This is true if the font transform is not identity.  It
434      * is used to avoid unnecessary instantiation of an AffineTransform.
435      */

436     private transient boolean nonIdentityTx;
437
438     /*
439      * A cached value used when a transform is required for internal
440      * use.  This must not be exposed to callers since AffineTransform
441      * is mutable.
442      */

443     private static final AffineTransform identityTx = new AffineTransform();
444
445     /*
446      * JDK 1.1 serialVersionUID
447      */

448     private static final long serialVersionUID = -4206021311591459213L;
449
450     /**
451      * Gets the peer of this {@code Font}.
452      *
453      * @return the peer of the {@code Font}.
454      */

455     private FontPeer getFontPeer() {
456         if(peer == null) {
457             Toolkit tk = Toolkit.getDefaultToolkit();
458             if (tk instanceof ComponentFactory) {
459                 peer = ((ComponentFactory) tk).getFontPeer(name, style);
460             }
461         }
462         return peer;
463     }
464
465     /**
466      * Return the AttributeValues object associated with this
467      * font.  Most of the time, the internal object is null.
468      * If required, it will be created from the 'standard'
469      * state on the font.  Only non-default values will be
470      * set in the AttributeValues object.
471      *
472      * <p>Since the AttributeValues object is mutable, and it
473      * is cached in the font, care must be taken to ensure that
474      * it is not mutated.
475      */

476     private AttributeValues getAttributeValues() {
477         if (values == null) {
478             AttributeValues valuesTmp = new AttributeValues();
479             valuesTmp.setFamily(name);
480             valuesTmp.setSize(pointSize); // expects the float value.
481
482             if ((style & BOLD) != 0) {
483                 valuesTmp.setWeight(2); // WEIGHT_BOLD
484             }
485
486             if ((style & ITALIC) != 0) {
487                 valuesTmp.setPosture(.2f); // POSTURE_OBLIQUE
488             }
489             valuesTmp.defineAll(PRIMARY_MASK); // for streaming compatibility
490             values = valuesTmp;
491         }
492
493         return values;
494     }
495
496     private Font2D getFont2D() {
497         FontManager fm = FontManagerFactory.getInstance();
498         if (fm.usingPerAppContextComposites() &&
499             font2DHandle != null &&
500             font2DHandle.font2D instanceof CompositeFont &&
501             ((CompositeFont)(font2DHandle.font2D)).isStdComposite()) {
502             return fm.findFont2D(name, style,
503                                           FontManager.LOGICAL_FALLBACK);
504         } else if (font2DHandle == null) {
505             font2DHandle =
506                 fm.findFont2D(name, style,
507                               FontManager.LOGICAL_FALLBACK).handle;
508         }
509         /* Do not cache the de-referenced font2D. It must be explicitly
510          * de-referenced to pick up a valid font in the event that the
511          * original one is marked invalid
512          */

513         return font2DHandle.font2D;
514     }
515
516     /**
517      * Creates a new {@code Font} from the specified name, style and
518      * point size.
519      * <p>
520      * The font name can be a font face name or a font family name.
521      * It is used together with the style to find an appropriate font face.
522      * When a font family name is specified, the style argument is used to
523      * select the most appropriate face from the family. When a font face
524      * name is specified, the face's style and the style argument are
525      * merged to locate the best matching font from the same family.
526      * For example if face name "Arial Bold" is specified with style
527      * {@code Font.ITALIC}, the font system looks for a face in the
528      * "Arial" family that is bold and italic, and may associate the font
529      * instance with the physical font face "Arial Bold Italic".
530      * The style argument is merged with the specified face's style, not
531      * added or subtracted.
532      * This means, specifying a bold face and a bold style does not
533      * double-embolden the font, and specifying a bold face and a plain
534      * style does not lighten the font.
535      * <p>
536      * If no face for the requested style can be found, the font system
537      * may apply algorithmic styling to achieve the desired style.
538      * For example, if {@code ITALIC} is requested, but no italic
539      * face is available, glyphs from the plain face may be algorithmically
540      * obliqued (slanted).
541      * <p>
542      * Font name lookup is case insensitive, using the case folding
543      * rules of the US locale.
544      * <p>
545      * If the {@code name} parameter represents something other than a
546      * logical font, i.e. is interpreted as a physical font face or family, and
547      * this cannot be mapped by the implementation to a physical font or a
548      * compatible alternative, then the font system will map the Font
549      * instance to "Dialog", such that for example, the family as reported
550      * by {@link #getFamily() getFamily} will be "Dialog".
551      *
552      * @param name the font name.  This can be a font face name or a font
553      * family name, and may represent either a logical font or a physical
554      * font found in this {@code GraphicsEnvironment}.
555      * The family names for logical fonts are: Dialog, DialogInput,
556      * Monospaced, Serif, or SansSerif. Pre-defined String constants exist
557      * for all of these names, for example, {@code DIALOG}. If {@code name} is
558      * {@code null}, the <em>logical font name</em> of the new
559      * {@code Font} as returned by {@code getName()} is set to
560      * the name "Default".
561      * @param style the style constant for the {@code Font}
562      * The style argument is an integer bitmask that may
563      * be {@code PLAIN}, or a bitwise union of {@code BOLD} and/or
564      * {@code ITALIC} (for example, {@code ITALIC} or {@code BOLD|ITALIC}).
565      * If the style argument does not conform to one of the expected
566      * integer bitmasks then the style is set to {@code PLAIN}.
567      * @param size the point size of the {@code Font}
568      * @see GraphicsEnvironment#getAllFonts
569      * @see GraphicsEnvironment#getAvailableFontFamilyNames
570      * @since 1.0
571      */

572     public Font(String name, int style, int size) {
573         this.name = (name != null) ? name : "Default";
574         this.style = (style & ~0x03) == 0 ? style : 0;
575         this.size = size;
576         this.pointSize = size;
577     }
578
579     private Font(String name, int style, float sizePts) {
580         this.name = (name != null) ? name : "Default";
581         this.style = (style & ~0x03) == 0 ? style : 0;
582         this.size = (int)(sizePts + 0.5);
583         this.pointSize = sizePts;
584     }
585
586     /* This constructor is used by deriveFont when attributes is null */
587     private Font(String name, int style, float sizePts,
588                  boolean created, Font2DHandle handle) {
589         this(name, style, sizePts);
590         this.createdFont = created;
591         /* Fonts created from a stream will use the same font2D instance
592          * as the parent.
593          * One exception is that if the derived font is requested to be
594          * in a different style, then also check if its a CompositeFont
595          * and if so build a new CompositeFont from components of that style.
596          * CompositeFonts can only be marked as "created" if they are used
597          * to add fall backs to a physical font. And non-composites are
598          * always from "Font.createFont()" and shouldn't get this treatment.
599          */

600         if (created) {
601             if (handle.font2D instanceof CompositeFont &&
602                 handle.font2D.getStyle() != style) {
603                 FontManager fm = FontManagerFactory.getInstance();
604                 this.font2DHandle = fm.getNewComposite(null, style, handle);
605             } else {
606                 this.font2DHandle = handle;
607             }
608         }
609     }
610
611     /* used to implement Font.createFont */
612     private Font(File fontFile, int fontFormat,
613                  boolean isCopy, CreatedFontTracker tracker)
614         throws FontFormatException {
615         this.createdFont = true;
616         /* Font2D instances created by this method track their font file
617          * so that when the Font2D is GC'd it can also remove the file.
618          */

619         FontManager fm = FontManagerFactory.getInstance();
620         Font2D[] fonts =
621             fm.createFont2D(fontFile, fontFormat, false, isCopy, tracker);
622         this.font2DHandle = fonts[0].handle;
623         this.name = this.font2DHandle.font2D.getFontName(Locale.getDefault());
624         this.style = Font.PLAIN;
625         this.size = 1;
626         this.pointSize = 1f;
627     }
628
629     /* This constructor is used when one font is derived from another.
630      * Fonts created from a stream will use the same font2D instance as the
631      * parent. They can be distinguished because the "created" argument
632      * will be "true". Since there is no way to recreate these fonts they
633      * need to have the handle to the underlying font2D passed in.
634      * "created" is also true when a special composite is referenced by the
635      * handle for essentially the same reasons.
636      * But when deriving a font in these cases two particular attributes
637      * need special attention: family/face and style.
638      * The "composites" in these cases need to be recreated with optimal
639      * fonts for the new values of family and style.
640      * For fonts created with createFont() these are treated differently.
641      * JDK can often synthesise a different style (bold from plain
642      * for example). For fonts created with "createFont" this is a reasonable
643      * solution but its also possible (although rare) to derive a font with a
644      * different family attribute. In this case JDK needs
645      * to break the tie with the original Font2D and find a new Font.
646      * The oldName and oldStyle are supplied so they can be compared with
647      * what the Font2D and the values. To speed things along :
648      * oldName == null will be interpreted as the name is unchanged.
649      * oldStyle = -1 will be interpreted as the style is unchanged.
650      * In these cases there is no need to interrogate "values".
651      */

652     private Font(AttributeValues values, String oldName, int oldStyle,
653                  boolean created, Font2DHandle handle) {
654
655         this.createdFont = created;
656         if (created) {
657             this.font2DHandle = handle;
658
659             String newName = null;
660             if (oldName != null) {
661                 newName = values.getFamily();
662                 if (oldName.equals(newName)) newName = null;
663             }
664             int newStyle = 0;
665             if (oldStyle == -1) {
666                 newStyle = -1;
667             } else {
668                 if (values.getWeight() >= 2f)   newStyle  = BOLD;
669                 if (values.getPosture() >= .2f) newStyle |= ITALIC;
670                 if (oldStyle == newStyle)       newStyle  = -1;
671             }
672             if (handle.font2D instanceof CompositeFont) {
673                 if (newStyle != -1 || newName != null) {
674                     FontManager fm = FontManagerFactory.getInstance();
675                     this.font2DHandle =
676                         fm.getNewComposite(newName, newStyle, handle);
677                 }
678             } else if (newName != null) {
679                 this.createdFont = false;
680                 this.font2DHandle = null;
681             }
682         }
683         initFromValues(values);
684     }
685
686     /**
687      * Creates a new {@code Font} with the specified attributes.
688      * Only keys defined in {@link java.awt.font.TextAttribute TextAttribute}
689      * are recognized.  In addition the FONT attribute is
690      *  not recognized by this constructor
691      * (see {@link #getAvailableAttributes}). Only attributes that have
692      * values of valid types will affect the new {@code Font}.
693      * <p>
694      * If {@code attributes} is {@code null}, a new
695      * {@code Font} is initialized with default values.
696      * @see java.awt.font.TextAttribute
697      * @param attributes the attributes to assign to the new
698      *          {@code Font}, or {@code null}
699      */

700     public Font(Map<? extends Attribute, ?> attributes) {
701         initFromValues(AttributeValues.fromMap(attributes, RECOGNIZED_MASK));
702     }
703
704     /**
705      * Creates a new {@code Font} from the specified {@code font}.
706      * This constructor is intended for use by subclasses.
707      * @param font from which to create this {@code Font}.
708      * @throws NullPointerException if {@code font} is null
709      * @since 1.6
710      */

711     protected Font(Font font) {
712         if (font.values != null) {
713             initFromValues(font.getAttributeValues().clone());
714         } else {
715             this.name = font.name;
716             this.style = font.style;
717             this.size = font.size;
718             this.pointSize = font.pointSize;
719         }
720         this.font2DHandle = font.font2DHandle;
721         this.createdFont = font.createdFont;
722     }
723
724     /**
725      * Font recognizes all attributes except FONT.
726      */

727     private static final int RECOGNIZED_MASK = AttributeValues.MASK_ALL
728         & ~AttributeValues.getMask(EFONT);
729
730     /**
731      * These attributes are considered primary by the FONT attribute.
732      */

733     private static final int PRIMARY_MASK =
734         AttributeValues.getMask(EFAMILY, EWEIGHT, EWIDTH, EPOSTURE, ESIZE,
735                                 ETRANSFORM, ESUPERSCRIPT, ETRACKING);
736
737     /**
738      * These attributes are considered secondary by the FONT attribute.
739      */

740     private static final int SECONDARY_MASK =
741         RECOGNIZED_MASK & ~PRIMARY_MASK;
742
743     /**
744      * These attributes are handled by layout.
745      */

746     private static final int LAYOUT_MASK =
747         AttributeValues.getMask(ECHAR_REPLACEMENT, EFOREGROUND, EBACKGROUND,
748                                 EUNDERLINE, ESTRIKETHROUGH, ERUN_DIRECTION,
749                                 EBIDI_EMBEDDING, EJUSTIFICATION,
750                                 EINPUT_METHOD_HIGHLIGHT, EINPUT_METHOD_UNDERLINE,
751                                 ESWAP_COLORS, ENUMERIC_SHAPING, EKERNING,
752                                 ELIGATURES, ETRACKING, ESUPERSCRIPT);
753
754     private static final int EXTRA_MASK =
755             AttributeValues.getMask(ETRANSFORM, ESUPERSCRIPT, EWIDTH);
756
757     /**
758      * Initialize the standard Font fields from the values object.
759      */

760     private void initFromValues(AttributeValues values) {
761         this.values = values;
762         values.defineAll(PRIMARY_MASK); // for 1.5 streaming compatibility
763
764         this.name = values.getFamily();
765         this.pointSize = values.getSize();
766         this.size = (int)(values.getSize() + 0.5);
767         if (values.getWeight() >= 2f) this.style |= BOLD; // not == 2f
768         if (values.getPosture() >= .2f) this.style |= ITALIC; // not  == .2f
769
770         this.nonIdentityTx = values.anyNonDefault(EXTRA_MASK);
771         this.hasLayoutAttributes =  values.anyNonDefault(LAYOUT_MASK);
772     }
773
774     /**
775      * Returns true if any part of the specified text is from a
776      * complex script for which the implementation will need to invoke
777      * layout processing in order to render correctly when using
778      * {@link Graphics#drawString(String,int,int) drawString(String,int,int)}
779      * and other text rendering methods. Measurement of the text
780      * may similarly need the same extra processing.
781      * The {@code start} and {@code end} indices are provided so that
782      * the application can request only a subset of the text be considered.
783      * The last char index examined is at {@code "end-1"},
784      * i.e a request to examine the entire array would be
785      * <pre>
786      * {@code Font.textRequiresLayout(chars, 0, chars.length);}
787      * </pre>
788      * An application may find this information helpful in
789      * performance sensitive code.
790      * <p>
791      * Note that even if this method returns {@code false}, layout processing
792      * may still be invoked when used with any {@code Font}
793      * for which {@link #hasLayoutAttributes()} returns {@code true},
794      * so that method will need to be consulted for the specific font,
795      * in order to obtain an answer which accounts for such font attributes.
796      *
797      * @param chars the text.
798      * @param start the index of the first char to examine.
799      * @param end the ending index, exclusive.
800      * @return {@code trueif the specified text will need special layout.
801      * @throws NullPointerException if {@code chars} is null.
802      * @throws ArrayIndexOutOfBoundsException if {@code start} is negative or
803      * {@code end} is greater than the length of the {@code chars} array.
804      * @since 9
805      */

806     public static boolean textRequiresLayout(char[] chars,
807                                              int start, int end) {
808         if (chars == null) {
809            throw new NullPointerException("null char array");
810         }
811         if (start < 0 || end > chars.length) {
812             throw new ArrayIndexOutOfBoundsException("start < 0 or end > len");
813         }
814         return FontUtilities.isComplexScript(chars, start, end);
815     }
816
817     /**
818      * Returns a {@code Font} appropriate to the attributes.
819      * If {@code attributes} contains a {@code FONT} attribute
820      * with a valid {@code Font} as its value, it will be
821      * merged with any remaining attributes.  See
822      * {@link java.awt.font.TextAttribute#FONT} for more
823      * information.
824      *
825      * @param attributes the attributes to assign to the new
826      *          {@code Font}
827      * @return a new {@code Font} created with the specified
828      *          attributes
829      * @throws NullPointerException if {@code attributes} is null.
830      * @since 1.2
831      * @see java.awt.font.TextAttribute
832      */

833     public static Font getFont(Map<? extends Attribute, ?> attributes) {
834         // optimize for two cases:
835         // 1) FONT attribute, and nothing else
836         // 2) attributes, but no FONT
837
838         // avoid turning the attributemap into a regular map for no reason
839         if (attributes instanceof AttributeMap &&
840             ((AttributeMap)attributes).getValues() != null) {
841             AttributeValues values = ((AttributeMap)attributes).getValues();
842             if (values.isNonDefault(EFONT)) {
843                 Font font = values.getFont();
844                 if (!values.anyDefined(SECONDARY_MASK)) {
845                     return font;
846                 }
847                 // merge
848                 values = font.getAttributeValues().clone();
849                 values.merge(attributes, SECONDARY_MASK);
850                 return new Font(values, font.name, font.style,
851                                 font.createdFont, font.font2DHandle);
852             }
853             return new Font(attributes);
854         }
855
856         Font font = (Font)attributes.get(TextAttribute.FONT);
857         if (font != null) {
858             if (attributes.size() > 1) { // oh well, check for anything else
859                 AttributeValues values = font.getAttributeValues().clone();
860                 values.merge(attributes, SECONDARY_MASK);
861                 return new Font(values, font.name, font.style,
862                                 font.createdFont, font.font2DHandle);
863             }
864
865             return font;
866         }
867
868         return new Font(attributes);
869     }
870
871     /**
872      * Used with the byte count tracker for fonts created from streams.
873      * If a thread can create temp files anyway, no point in counting
874      * font bytes.
875      */

876     private static boolean hasTempPermission() {
877
878         if (System.getSecurityManager() == null) {
879             return true;
880         }
881         File f = null;
882         boolean hasPerm = false;
883         try {
884             f = Files.createTempFile("+~JT"".tmp").toFile();
885             f.delete();
886             f = null;
887             hasPerm = true;
888         } catch (Throwable t) {
889             /* inc. any kind of SecurityException */
890         }
891         return hasPerm;
892     }
893
894
895     /**
896      * Returns a new array of {@code Font} decoded from the specified stream.
897      * The returned {@code Font[]} will have at least one element.
898      * <p>
899      * The explicit purpose of this variation on the
900      * {@code createFont(int, InputStream)} method is to support font
901      * sources which represent a TrueType/OpenType font collection and
902      * be able to return all individual fonts in that collection.
903      * Consequently this method will throw {@code FontFormatException}
904      * if the data source does not contain at least one TrueType/OpenType
905      * font. The same exception will also be thrown if any of the fonts in
906      * the collection does not contain the required font tables.
907      * <p>
908      * The condition "at least one", allows for the stream to represent
909      * a single OpenType/TrueType font. That is, it does not have to be
910      * a collection.
911      * Each {@code Font} element of the returned array is
912      * created with a point size of 1 and style {@link #PLAIN PLAIN}.
913      * This base font can then be used with the {@code deriveFont}
914      * methods in this class to derive new {@code Font} objects with
915      * varying sizes, styles, transforms and font features.
916      * <p>This method does not close the {@link InputStream}.
917      * <p>
918      * To make each {@code Font} available to Font constructors it
919      * must be registered in the {@code GraphicsEnvironment} by calling
920      * {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}.
921      * @param fontStream an {@code InputStream} object representing the
922      * input data for the font or font collection.
923      * @return a new {@code Font[]}.
924      * @throws FontFormatException if the {@code fontStream} data does
925      *     not contain the required font tables for any of the elements of
926      *     the collection, or if it contains no fonts at all.
927      * @throws IOException if the {@code fontStream} cannot be completely read.
928      * @see GraphicsEnvironment#registerFont(Font)
929      * @since 9
930      */

931     public static Font[] createFonts(InputStream fontStream)
932         throws FontFormatException, IOException {
933
934         final int fontFormat = Font.TRUETYPE_FONT;
935         if (hasTempPermission()) {
936             return createFont0(fontFormat, fontStream, truenull);
937         }
938
939         // Otherwise, be extra conscious of pending temp file creation and
940         // resourcefully handle the temp file resources, among other things.
941         CreatedFontTracker tracker = CreatedFontTracker.getTracker();
942         boolean acquired = false;
943         try {
944             acquired = tracker.acquirePermit();
945             if (!acquired) {
946                 throw new IOException("Timed out waiting for resources.");
947             }
948             return createFont0(fontFormat, fontStream, true, tracker);
949         } catch (InterruptedException e) {
950             throw new IOException("Problem reading font data.");
951         } finally {
952             if (acquired) {
953                 tracker.releasePermit();
954             }
955         }
956     }
957
958     /* used to implement Font.createFont */
959     private Font(Font2D font2D) {
960
961         this.createdFont = true;
962         this.font2DHandle = font2D.handle;
963         this.name = font2D.getFontName(Locale.getDefault());
964         this.style = Font.PLAIN;
965         this.size = 1;
966         this.pointSize = 1f;
967     }
968
969     /**
970      * Returns a new array of {@code Font} decoded from the specified file.
971      * The returned {@code Font[]} will have at least one element.
972      * <p>
973      * The explicit purpose of this variation on the
974      * {@code createFont(int, File)} method is to support font
975      * sources which represent a TrueType/OpenType font collection and
976      * be able to return all individual fonts in that collection.
977      * Consequently this method will throw {@code FontFormatException}
978      * if the data source does not contain at least one TrueType/OpenType
979      * font. The same exception will also be thrown if any of the fonts in
980      * the collection does not contain the required font tables.
981      * <p>
982      * The condition "at least one", allows for the stream to represent
983      * a single OpenType/TrueType font. That is, it does not have to be
984      * a collection.
985      * Each {@code Font} element of the returned array is
986      * created with a point size of 1 and style {@link #PLAIN PLAIN}.
987      * This base font can then be used with the {@code deriveFont}
988      * methods in this class to derive new {@code Font} objects with
989      * varying sizes, styles, transforms and font features.
990      * <p>
991      * To make each {@code Font} available to Font constructors it
992      * must be registered in the {@code GraphicsEnvironment} by calling
993      * {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}.
994      * @param fontFile a {@code File} object containing the
995      * input data for the font or font collection.
996      * @return a new {@code Font[]}.
997      * @throws FontFormatException if the {@code File} does
998      *     not contain the required font tables for any of the elements of
999      *     the collection, or if it contains no fonts at all.
1000      * @throws IOException if the {@code fontFile} cannot be read.
1001      * @see GraphicsEnvironment#registerFont(Font)
1002      * @since 9
1003      */

1004     public static Font[] createFonts(File fontFile)
1005             throws FontFormatException, IOException
1006     {
1007         int fontFormat = Font.TRUETYPE_FONT;
1008         fontFile = checkFontFile(fontFormat, fontFile);
1009         FontManager fm = FontManagerFactory.getInstance();
1010         Font2D[] font2DArr =
1011             fm.createFont2D(fontFile, fontFormat, truefalsenull);
1012         int num = font2DArr.length;
1013         Font[] fonts = new Font[num];
1014         for (int i = 0; i < num; i++) {
1015            fonts[i] = new Font(font2DArr[i]);
1016         }
1017         return fonts;
1018     }
1019
1020     /**
1021      * Returns a new {@code Font} using the specified font type
1022      * and input data.  The new {@code Font} is
1023      * created with a point size of 1 and style {@link #PLAIN PLAIN}.
1024      * This base font can then be used with the {@code deriveFont}
1025      * methods in this class to derive new {@code Font} objects with
1026      * varying sizes, styles, transforms and font features.  This
1027      * method does not close the {@link InputStream}.
1028      * <p>
1029      * To make the {@code Font} available to Font constructors the
1030      * returned {@code Font} must be registered in the
1031      * {@code GraphicsEnvironment} by calling
1032      * {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}.
1033      * @param fontFormat the type of the {@code Font}, which is
1034      * {@link #TRUETYPE_FONT TRUETYPE_FONT} if a TrueType resource is specified.
1035      * or {@link #TYPE1_FONT TYPE1_FONT} if a Type 1 resource is specified.
1036      * @param fontStream an {@code InputStream} object representing the
1037      * input data for the font.
1038      * @return a new {@code Font} created with the specified font type.
1039      * @throws IllegalArgumentException if {@code fontFormat} is not
1040      *     {@code TRUETYPE_FONT} or {@code TYPE1_FONT}.
1041      * @throws FontFormatException if the {@code fontStream} data does
1042      *     not contain the required font tables for the specified format.
1043      * @throws IOException if the {@code fontStream}
1044      *     cannot be completely read.
1045      * @see GraphicsEnvironment#registerFont(Font)
1046      * @since 1.3
1047      */

1048     public static Font createFont(int fontFormat, InputStream fontStream)
1049         throws java.awt.FontFormatException, java.io.IOException {
1050
1051         if (hasTempPermission()) {
1052             return createFont0(fontFormat, fontStream, falsenull)[0];
1053         }
1054
1055         // Otherwise, be extra conscious of pending temp file creation and
1056         // resourcefully handle the temp file resources, among other things.
1057         CreatedFontTracker tracker = CreatedFontTracker.getTracker();
1058         boolean acquired = false;
1059         try {
1060             acquired = tracker.acquirePermit();
1061             if (!acquired) {
1062                 throw new IOException("Timed out waiting for resources.");
1063             }
1064             return createFont0(fontFormat, fontStream, false, tracker)[0];
1065         } catch (InterruptedException e) {
1066             throw new IOException("Problem reading font data.");
1067         } finally {
1068             if (acquired) {
1069                 tracker.releasePermit();
1070             }
1071         }
1072     }
1073
1074     private static Font[] createFont0(int fontFormat, InputStream fontStream,
1075                                       boolean allFonts,
1076                                       CreatedFontTracker tracker)
1077         throws java.awt.FontFormatException, java.io.IOException {
1078
1079         if (fontFormat != Font.TRUETYPE_FONT &&
1080             fontFormat != Font.TYPE1_FONT) {
1081             throw new IllegalArgumentException ("font format not recognized");
1082         }
1083         boolean copiedFontData = false;
1084         try {
1085             final File tFile = AccessController.doPrivileged(
1086                 new PrivilegedExceptionAction<File>() {
1087                     public File run() throws IOException {
1088                         return Files.createTempFile("+~JF"".tmp").toFile();
1089                     }
1090                 }
1091             );
1092             if (tracker != null) {
1093                 tracker.add(tFile);
1094             }
1095
1096             int totalSize = 0;
1097             try {
1098                 final OutputStream outStream =
1099                     AccessController.doPrivileged(
1100                         new PrivilegedExceptionAction<OutputStream>() {
1101                             public OutputStream run() throws IOException {
1102                                 return new FileOutputStream(tFile);
1103                             }
1104                         }
1105                     );
1106                 if (tracker != null) {
1107                     tracker.set(tFile, outStream);
1108                 }
1109                 try {
1110                     byte[] buf = new byte[8192];
1111                     for (;;) {
1112                         int bytesRead = fontStream.read(buf);
1113                         if (bytesRead < 0) {
1114                             break;
1115                         }
1116                         if (tracker != null) {
1117                             if (totalSize+bytesRead > CreatedFontTracker.MAX_FILE_SIZE) {
1118                                 throw new IOException("File too big.");
1119                             }
1120                             if (totalSize+tracker.getNumBytes() >
1121                                 CreatedFontTracker.MAX_TOTAL_BYTES)
1122                               {
1123                                 throw new IOException("Total files too big.");
1124                             }
1125                             totalSize += bytesRead;
1126                             tracker.addBytes(bytesRead);
1127                         }
1128                         outStream.write(buf, 0, bytesRead);
1129                     }
1130                     /* don't close the input stream */
1131                 } finally {
1132                     outStream.close();
1133                 }
1134                 /* After all references to a Font2D are dropped, the file
1135                  * will be removed. To support long-lived AppContexts,
1136                  * we need to then decrement the byte count by the size
1137                  * of the file.
1138                  * If the data isn't a valid font, the implementation will
1139                  * delete the tmp file and decrement the byte count
1140                  * in the tracker object before returning from the
1141                  * constructor, so we can set 'copiedFontData' to true here
1142                  * without waiting for the results of that constructor.
1143                  */

1144                 copiedFontData = true;
1145                 FontManager fm = FontManagerFactory.getInstance();
1146                  Font2D[] font2DArr =
1147                     fm.createFont2D(tFile, fontFormat, allFonts, true, tracker);
1148                 int num = font2DArr.length;
1149                 Font[] fonts = new Font[num];
1150                 for (int i = 0; i < num; i++) {
1151                    fonts[i] = new Font(font2DArr[i]);
1152                 }
1153                 return fonts;
1154             } finally {
1155                 if (tracker != null) {
1156                     tracker.remove(tFile);
1157                 }
1158                 if (!copiedFontData) {
1159                     if (tracker != null) {
1160                         tracker.subBytes(totalSize);
1161                     }
1162                     AccessController.doPrivileged(
1163                         new PrivilegedExceptionAction<Void>() {
1164                             public Void run() {
1165                                 tFile.delete();
1166                                 return null;
1167                             }
1168                         }
1169                     );
1170                 }
1171             }
1172         } catch (Throwable t) {
1173             if (t instanceof FontFormatException) {
1174                 throw (FontFormatException)t;
1175             }
1176             if (t instanceof IOException) {
1177                 throw (IOException)t;
1178             }
1179             Throwable cause = t.getCause();
1180             if (cause instanceof FontFormatException) {
1181                 throw (FontFormatException)cause;
1182             }
1183             throw new IOException("Problem reading font data.");
1184         }
1185     }
1186
1187     /**
1188      * Returns a new {@code Font} using the specified font type
1189      * and the specified font file.  The new {@code Font} is
1190      * created with a point size of 1 and style {@link #PLAIN PLAIN}.
1191      * This base font can then be used with the {@code deriveFont}
1192      * methods in this class to derive new {@code Font} objects with
1193      * varying sizes, styles, transforms and font features.
1194      * @param fontFormat the type of the {@code Font}, which is
1195      * {@link #TRUETYPE_FONT TRUETYPE_FONT} if a TrueType resource is
1196      * specified or {@link #TYPE1_FONT TYPE1_FONT} if a Type 1 resource is
1197      * specified.
1198      * So long as the returned font, or its derived fonts are referenced
1199      * the implementation may continue to access {@code fontFile}
1200      * to retrieve font data. Thus the results are undefined if the file
1201      * is changed, or becomes inaccessible.
1202      * <p>
1203      * To make the {@code Font} available to Font constructors the
1204      * returned {@code Font} must be registered in the
1205      * {@code GraphicsEnvironment} by calling
1206      * {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}.
1207      * @param fontFile a {@code File} object representing the
1208      * input data for the font.
1209      * @return a new {@code Font} created with the specified font type.
1210      * @throws IllegalArgumentException if {@code fontFormat} is not
1211      *     {@code TRUETYPE_FONT} or {@code TYPE1_FONT}.
1212      * @throws NullPointerException if {@code fontFile} is null.
1213      * @throws IOException if the {@code fontFile} cannot be read.
1214      * @throws FontFormatException if {@code fontFile} does
1215      *     not contain the required font tables for the specified format.
1216      * @throws SecurityException if the executing code does not have
1217      * permission to read from the file.
1218      * @see GraphicsEnvironment#registerFont(Font)
1219      * @since 1.5
1220      */

1221     public static Font createFont(int fontFormat, File fontFile)
1222         throws java.awt.FontFormatException, java.io.IOException {
1223
1224         fontFile = checkFontFile(fontFormat, fontFile);
1225         return new Font(fontFile, fontFormat, falsenull);
1226     }
1227
1228     private static File checkFontFile(int fontFormat, File fontFile)
1229         throws FontFormatException, IOException {
1230
1231         fontFile = new File(fontFile.getPath());
1232
1233         if (fontFormat != Font.TRUETYPE_FONT &&
1234             fontFormat != Font.TYPE1_FONT) {
1235             throw new IllegalArgumentException ("font format not recognized");
1236         }
1237         SecurityManager sm = System.getSecurityManager();
1238         if (sm != null) {
1239             FilePermission filePermission =
1240                 new FilePermission(fontFile.getPath(), "read");
1241             sm.checkPermission(filePermission);
1242         }
1243         if (!fontFile.canRead()) {
1244             throw new IOException("Can't read " + fontFile);
1245         }
1246         return fontFile;
1247     }
1248
1249     /**
1250      * Returns a copy of the transform associated with this
1251      * {@code Font}.  This transform is not necessarily the one
1252      * used to construct the font.  If the font has algorithmic
1253      * superscripting or width adjustment, this will be incorporated
1254      * into the returned {@code AffineTransform}.
1255      * <p>
1256      * Typically, fonts will not be transformed.  Clients generally
1257      * should call {@link #isTransformed} first, and only call this
1258      * method if {@code isTransformed} returns true.
1259      *
1260      * @return an {@link AffineTransform} object representing the
1261      *          transform attribute of this {@code Font} object.
1262      */

1263     public AffineTransform getTransform() {
1264         /* The most common case is the identity transform.  Most callers
1265          * should call isTransformed() first, to decide if they need to
1266          * get the transform, but some may not.  Here we check to see
1267          * if we have a nonidentity transform, and only do the work to
1268          * fetch and/or compute it if so, otherwise we return a new
1269          * identity transform.
1270          *
1271          * Note that the transform is _not_ necessarily the same as
1272          * the transform passed in as an Attribute in a Map, as the
1273          * transform returned will also reflect the effects of WIDTH and
1274          * SUPERSCRIPT attributes.  Clients who want the actual transform
1275          * need to call getRequestedAttributes.
1276          */

1277         if (nonIdentityTx) {
1278             AttributeValues values = getAttributeValues();
1279
1280             AffineTransform at = values.isNonDefault(ETRANSFORM)
1281                 ? new AffineTransform(values.getTransform())
1282                 : new AffineTransform();
1283
1284             if (values.getSuperscript() != 0) {
1285                 // can't get ascent and descent here, recursive call to this fn,
1286                 // so use pointsize
1287                 // let users combine super- and sub-scripting
1288
1289                 int superscript = values.getSuperscript();
1290
1291                 double trans = 0;
1292                 int n = 0;
1293                 boolean up = superscript > 0;
1294                 int sign = up ? -1 : 1;
1295                 int ss = up ? superscript : -superscript;
1296
1297                 while ((ss & 7) > n) {
1298                     int newn = ss & 7;
1299                     trans += sign * (ssinfo[newn] - ssinfo[n]);
1300                     ss >>= 3;
1301                     sign = -sign;
1302                     n = newn;
1303                 }
1304                 trans *= pointSize;
1305                 double scale = Math.pow(2./3., n);
1306
1307                 at.preConcatenate(AffineTransform.getTranslateInstance(0, trans));
1308                 at.scale(scale, scale);
1309
1310                 // note on placement and italics
1311                 // We preconcatenate the transform because we don't want to translate along
1312                 // the italic angle, but purely perpendicular to the baseline.  While this
1313                 // looks ok for superscripts, it can lead subscripts to stack on each other
1314                 // and bring the following text too close.  The way we deal with potential
1315                 // collisions that can occur in the case of italics is by adjusting the
1316                 // horizontal spacing of the adjacent glyphvectors.  Examine the italic
1317                 // angle of both vectors, if one is non-zero, compute the minimum ascent
1318                 // and descent, and then the x position at each for each vector along its
1319                 // italic angle starting from its (offset) baseline.  Compute the difference
1320                 // between the x positions and use the maximum difference to adjust the
1321                 // position of the right gv.
1322             }
1323
1324             if (values.isNonDefault(EWIDTH)) {
1325                 at.scale(values.getWidth(), 1f);
1326             }
1327
1328             return at;
1329         }
1330
1331         return new AffineTransform();
1332     }
1333
1334     // x = r^0 + r^1 + r^2... r^n
1335     // rx = r^1 + r^2 + r^3... r^(n+1)
1336     // x - rx = r^0 - r^(n+1)
1337     // x (1 - r) = r^0 - r^(n+1)
1338     // x = (r^0 - r^(n+1)) / (1 - r)
1339     // x = (1 - r^(n+1)) / (1 - r)
1340
1341     // scale ratio is 2/3
1342     // trans = 1/2 of ascent * x
1343     // assume ascent is 3/4 of point size
1344
1345     private static final float[] ssinfo = {
1346         0.0f,
1347         0.375f,
1348         0.625f,
1349         0.7916667f,
1350         0.9027778f,
1351         0.9768519f,
1352         1.0262346f,
1353         1.0591564f,
1354     };
1355
1356     /**
1357      * Returns the family name of this {@code Font}.
1358      *
1359      * <p>The family name of a font is font specific. Two fonts such as
1360      * Helvetica Italic and Helvetica Bold have the same family name,
1361      * <i>Helvetica</i>, whereas their font face names are
1362      * <i>Helvetica Bold</i> and <i>Helvetica Italic</i>. The list of
1363      * available family names may be obtained by using the
1364      * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
1365      *
1366      * <p>Use {@code getName} to get the logical name of the font.
1367      * Use {@code getFontName} to get the font face name of the font.
1368      * @return a {@code String} that is the family name of this
1369      *          {@code Font}.
1370      *
1371      * @see #getName
1372      * @see #getFontName
1373      * @since 1.1
1374      */

1375     public String getFamily() {
1376         return getFamily_NoClientCode();
1377     }
1378     // NOTE: This method is called by privileged threads.
1379     //       We implement this functionality in a package-private
1380     //       method to insure that it cannot be overridden by client
1381     //       subclasses.
1382     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
1383     final String getFamily_NoClientCode() {
1384         return getFamily(Locale.getDefault());
1385     }
1386
1387     /**
1388      * Returns the family name of this {@code Font}, localized for
1389      * the specified locale.
1390      *
1391      * <p>The family name of a font is font specific. Two fonts such as
1392      * Helvetica Italic and Helvetica Bold have the same family name,
1393      * <i>Helvetica</i>, whereas their font face names are
1394      * <i>Helvetica Bold</i> and <i>Helvetica Italic</i>. The list of
1395      * available family names may be obtained by using the
1396      * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
1397      *
1398      * <p>Use {@code getFontName} to get the font face name of the font.
1399      * @param l locale for which to get the family name
1400      * @return a {@code String} representing the family name of the
1401      *          font, localized for the specified locale.
1402      * @see #getFontName
1403      * @see java.util.Locale
1404      * @since 1.2
1405      */

1406     public String getFamily(Locale l) {
1407         if (l == null) {
1408             throw new NullPointerException("null locale doesn't mean default");
1409         }
1410         return getFont2D().getFamilyName(l);
1411     }
1412
1413     /**
1414      * Returns the postscript name of this {@code Font}.
1415      * Use {@code getFamily} to get the family name of the font.
1416      * Use {@code getFontName} to get the font face name of the font.
1417      * @return a {@code String} representing the postscript name of
1418      *          this {@code Font}.
1419      * @since 1.2
1420      */

1421     public String getPSName() {
1422         return getFont2D().getPostscriptName();
1423     }
1424
1425     /**
1426      * Returns the logical name of this {@code Font}.
1427      * Use {@code getFamily} to get the family name of the font.
1428      * Use {@code getFontName} to get the font face name of the font.
1429      * @return a {@code String} representing the logical name of
1430      *          this {@code Font}.
1431      * @see #getFamily
1432      * @see #getFontName
1433      * @since 1.0
1434      */

1435     public String getName() {
1436         return name;
1437     }
1438
1439     /**
1440      * Returns the font face name of this {@code Font}.  For example,
1441      * Helvetica Bold could be returned as a font face name.
1442      * Use {@code getFamily} to get the family name of the font.
1443      * Use {@code getName} to get the logical name of the font.
1444      * @return a {@code String} representing the font face name of
1445      *          this {@code Font}.
1446      * @see #getFamily
1447      * @see #getName
1448      * @since 1.2
1449      */

1450     public String getFontName() {
1451       return getFontName(Locale.getDefault());
1452     }
1453
1454     /**
1455      * Returns the font face name of the {@code Font}, localized
1456      * for the specified locale. For example, Helvetica Fett could be
1457      * returned as the font face name.
1458      * Use {@code getFamily} to get the family name of the font.
1459      * @param l a locale for which to get the font face name
1460      * @return a {@code String} representing the font face name,
1461      *          localized for the specified locale.
1462      * @see #getFamily
1463      * @see java.util.Locale
1464      */

1465     public String getFontName(Locale l) {
1466         if (l == null) {
1467             throw new NullPointerException("null locale doesn't mean default");
1468         }
1469         return getFont2D().getFontName(l);
1470     }
1471
1472     /**
1473      * Returns the style of this {@code Font}.  The style can be
1474      * PLAIN, BOLD, ITALIC, or BOLD+ITALIC.
1475      * @return the style of this {@code Font}
1476      * @see #isPlain
1477      * @see #isBold
1478      * @see #isItalic
1479      * @since 1.0
1480      */

1481     public int getStyle() {
1482         return style;
1483     }
1484
1485     /**
1486      * Returns the point size of this {@code Font}, rounded to
1487      * an integer.
1488      * Most users are familiar with the idea of using <i>point size</i> to
1489      * specify the size of glyphs in a font. This point size defines a
1490      * measurement between the baseline of one line to the baseline of the
1491      * following line in a single spaced text document. The point size is
1492      * based on <i>typographic points</i>, approximately 1/72 of an inch.
1493      * <p>
1494      * The Java(tm)2D API adopts the convention that one point is
1495      * equivalent to one unit in user coordinates.  When using a
1496      * normalized transform for converting user space coordinates to
1497      * device space coordinates 72 user
1498      * space units equal 1 inch in device space.  In this case one point
1499      * is 1/72 of an inch.
1500      * @return the point size of this {@code Font} in 1/72 of an
1501      *          inch units.
1502      * @see #getSize2D
1503      * @see GraphicsConfiguration#getDefaultTransform
1504      * @see GraphicsConfiguration#getNormalizingTransform
1505      * @since 1.0
1506      */

1507     public int getSize() {
1508         return size;
1509     }
1510
1511     /**
1512      * Returns the point size of this {@code Font} in
1513      * {@code float} value.
1514      * @return the point size of this {@code Font} as a
1515      * {@code float} value.
1516      * @see #getSize
1517      * @since 1.2
1518      */

1519     public float getSize2D() {
1520         return pointSize;
1521     }
1522
1523     /**
1524      * Indicates whether or not this {@code Font} object's style is
1525      * PLAIN.
1526      * @return    {@code trueif this {@code Font} has a
1527      *            PLAIN style;
1528      *            {@code false} otherwise.
1529      * @see       java.awt.Font#getStyle
1530      * @since     1.0
1531      */

1532     public boolean isPlain() {
1533         return style == 0;
1534     }
1535
1536     /**
1537      * Indicates whether or not this {@code Font} object's style is
1538      * BOLD.
1539      * @return    {@code trueif this {@code Font} object's
1540      *            style is BOLD;
1541      *            {@code false} otherwise.
1542      * @see       java.awt.Font#getStyle
1543      * @since     1.0
1544      */

1545     public boolean isBold() {
1546         return (style & BOLD) != 0;
1547     }
1548
1549     /**
1550      * Indicates whether or not this {@code Font} object's style is
1551      * ITALIC.
1552      * @return    {@code trueif this {@code Font} object's
1553      *            style is ITALIC;
1554      *            {@code false} otherwise.
1555      * @see       java.awt.Font#getStyle
1556      * @since     1.0
1557      */

1558     public boolean isItalic() {
1559         return (style & ITALIC) != 0;
1560     }
1561
1562     /**
1563      * Indicates whether or not this {@code Font} object has a
1564      * transform that affects its size in addition to the Size
1565      * attribute.
1566      * @return  {@code trueif this {@code Font} object
1567      *          has a non-identity AffineTransform attribute.
1568      *          {@code false} otherwise.
1569      * @see     java.awt.Font#getTransform
1570      * @since   1.4
1571      */

1572     public boolean isTransformed() {
1573         return nonIdentityTx;
1574     }
1575
1576     /**
1577      * Return true if this Font contains attributes that require extra
1578      * layout processing.
1579      * @return true if the font has layout attributes
1580      * @since 1.6
1581      */

1582     public boolean hasLayoutAttributes() {
1583         return hasLayoutAttributes;
1584     }
1585
1586     /**
1587      * Returns a {@code Font} object from the system properties list.
1588      * {@code nm} is treated as the name of a system property to be
1589      * obtained.  The {@code String} value of this property is then
1590      * interpreted as a {@code Font} object according to the
1591      * specification of {@code Font.decode(String)}
1592      * If the specified property is not found, or the executing code does
1593      * not have permission to read the property, null is returned instead.
1594      *
1595      * @param nm the property name
1596      * @return a {@code Font} object that the property name
1597      *          describes, or null if no such property exists.
1598      * @throws NullPointerException if nm is null.
1599      * @since 1.2
1600      * @see #decode(String)
1601      */

1602     public static Font getFont(String nm) {
1603         return getFont(nm, null);
1604     }
1605
1606     /**
1607      * Returns the {@code Font} that the {@code str}
1608      * argument describes.
1609      * To ensure that this method returns the desired Font,
1610      * format the {@code str} parameter in
1611      * one of these ways
1612      *
1613      * <ul>
1614      * <li><em>fontname-style-pointsize</em>
1615      * <li><em>fontname-pointsize</em>
1616      * <li><em>fontname-style</em>
1617      * <li><em>fontname</em>
1618      * <li><em>fontname style pointsize</em>
1619      * <li><em>fontname pointsize</em>
1620      * <li><em>fontname style</em>
1621      * <li><em>fontname</em>
1622      * </ul>
1623      * in which <i>style</i> is one of the four
1624      * case-insensitive strings:
1625      * {@code "PLAIN"}, {@code "BOLD"}, {@code "BOLDITALIC"}, or
1626      * {@code "ITALIC"}, and pointsize is a positive decimal integer
1627      * representation of the point size.
1628      * For example, if you want a font that is Arial, bold, with
1629      * a point size of 18, you would call this method with:
1630      * "Arial-BOLD-18".
1631      * This is equivalent to calling the Font constructor :
1632      * {@code new Font("Arial", Font.BOLD, 18);}
1633      * and the values are interpreted as specified by that constructor.
1634      * <p>
1635      * A valid trailing decimal field is always interpreted as the pointsize.
1636      * Therefore a fontname containing a trailing decimal value should not
1637      * be used in the fontname only form.
1638      * <p>
1639      * If a style name field is not one of the valid style strings, it is
1640      * interpreted as part of the font name, and the default style is used.
1641      * <p>
1642      * Only one of ' ' or '-' may be used to separate fields in the input.
1643      * The identified separator is the one closest to the end of the string
1644      * which separates a valid pointsize, or a valid style name from
1645      * the rest of the string.
1646      * Null (empty) pointsize and style fields are treated
1647      * as valid fields with the default value for that field.
1648      *<p>
1649      * Some font names may include the separator characters ' ' or '-'.
1650      * If {@code str} is not formed with 3 components, e.g. such that
1651      * {@code style} or {@code pointsize} fields are not present in
1652      * {@code str}, and {@code fontname} also contains a
1653      * character determined to be the separator character
1654      * then these characters where they appear as intended to be part of
1655      * {@code fontname} may instead be interpreted as separators
1656      * so the font name may not be properly recognised.
1657      *
1658      * <p>
1659      * The default size is 12 and the default style is PLAIN.
1660      * If {@code str} does not specify a valid size, the returned
1661      * {@code Font} has a size of 12.  If {@code str} does not
1662      * specify a valid style, the returned Font has a style of PLAIN.
1663      * If you do not specify a valid font name in
1664      * the {@code str} argument, this method will return
1665      * a font with the family name "Dialog".
1666      * To determine what font family names are available on
1667      * your system, use the
1668      * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
1669      * If {@code str} is {@code null}, a new {@code Font}
1670      * is returned with the family name "Dialog", a size of 12 and a
1671      * PLAIN style.
1672      * @param str the name of the font, or {@code null}
1673      * @return the {@code Font} object that {@code str}
1674      *          describes, or a new default {@code Font} if
1675      *          {@code str} is {@code null}.
1676      * @see #getFamily
1677      * @since 1.1
1678      */

1679     public static Font decode(String str) {
1680         String fontName = str;
1681         String styleName = "";
1682         int fontSize = 12;
1683         int fontStyle = Font.PLAIN;
1684
1685         if (str == null) {
1686             return new Font(DIALOG, fontStyle, fontSize);
1687         }
1688
1689         int lastHyphen = str.lastIndexOf('-');
1690         int lastSpace = str.lastIndexOf(' ');
1691         char sepChar = (lastHyphen > lastSpace) ? '-' : ' ';
1692         int sizeIndex = str.lastIndexOf(sepChar);
1693         int styleIndex = str.lastIndexOf(sepChar, sizeIndex-1);
1694         int strlen = str.length();
1695
1696         if (sizeIndex > 0 && sizeIndex+1 < strlen) {
1697             try {
1698                 fontSize =
1699                     Integer.valueOf(str.substring(sizeIndex+1)).intValue();
1700                 if (fontSize <= 0) {
1701                     fontSize = 12;
1702                 }
1703             } catch (NumberFormatException e) {
1704                 /* It wasn't a valid size, if we didn't also find the
1705                  * start of the style string perhaps this is the style */

1706                 styleIndex = sizeIndex;
1707                 sizeIndex = strlen;
1708                 if (str.charAt(sizeIndex-1) == sepChar) {
1709                     sizeIndex--;
1710                 }
1711             }
1712         }
1713
1714         if (styleIndex >= 0 && styleIndex+1 < strlen) {
1715             styleName = str.substring(styleIndex+1, sizeIndex);
1716             styleName = styleName.toLowerCase(Locale.ENGLISH);
1717             if (styleName.equals("bolditalic")) {
1718                 fontStyle = Font.BOLD | Font.ITALIC;
1719             } else if (styleName.equals("italic")) {
1720                 fontStyle = Font.ITALIC;
1721             } else if (styleName.equals("bold")) {
1722                 fontStyle = Font.BOLD;
1723             } else if (styleName.equals("plain")) {
1724                 fontStyle = Font.PLAIN;
1725             } else {
1726                 /* this string isn't any of the expected styles, so
1727                  * assume its part of the font name
1728                  */

1729                 styleIndex = sizeIndex;
1730                 if (str.charAt(styleIndex-1) == sepChar) {
1731                     styleIndex--;
1732                 }
1733             }
1734             fontName = str.substring(0, styleIndex);
1735
1736         } else {
1737             int fontEnd = strlen;
1738             if (styleIndex > 0) {
1739                 fontEnd = styleIndex;
1740             } else if (sizeIndex > 0) {
1741                 fontEnd = sizeIndex;
1742             }
1743             if (fontEnd > 0 && str.charAt(fontEnd-1) == sepChar) {
1744                 fontEnd--;
1745             }
1746             fontName = str.substring(0, fontEnd);
1747         }
1748
1749         return new Font(fontName, fontStyle, fontSize);
1750     }
1751
1752     /**
1753      * Gets the specified {@code Font} from the system properties
1754      * list.  As in the {@code getProperty} method of
1755      * {@code System}, the first
1756      * argument is treated as the name of a system property to be
1757      * obtained.  The {@code String} value of this property is then
1758      * interpreted as a {@code Font} object.
1759      * <p>
1760      * The property value should be one of the forms accepted by
1761      * {@code Font.decode(String)}
1762      * If the specified property is not found, or the executing code does not
1763      * have permission to read the property, the {@code font}
1764      * argument is returned instead.
1765      * @param nm the case-insensitive property name
1766      * @param font a default {@code Font} to return if property
1767      *          {@code nm} is not defined
1768      * @return    the {@code Font} value of the property.
1769      * @throws NullPointerException if nm is null.
1770      * @see #decode(String)
1771      */

1772     public static Font getFont(String nm, Font font) {
1773         String str = null;
1774         try {
1775             str =System.getProperty(nm);
1776         } catch(SecurityException e) {
1777         }
1778         if (str == null) {
1779             return font;
1780         }
1781         return decode ( str );
1782     }
1783
1784     transient int hash;
1785     /**
1786      * Returns a hashcode for this {@code Font}.
1787      * @return     a hashcode value for this {@code Font}.
1788      * @since      1.0
1789      */

1790     public int hashCode() {
1791         if (hash == 0) {
1792             hash = name.hashCode() ^ style ^ size;
1793             /* It is possible many fonts differ only in transform.
1794              * So include the transform in the hash calculation.
1795              * nonIdentityTx is set whenever there is a transform in
1796              * 'values'. The tests for null are required because it can
1797              * also be set for other reasons.
1798              */

1799             if (nonIdentityTx &&
1800                 values != null && values.getTransform() != null) {
1801                 hash ^= values.getTransform().hashCode();
1802             }
1803         }
1804         return hash;
1805     }
1806
1807     /**
1808      * Compares this {@code Font} object to the specified
1809      * {@code Object}.
1810      * @param obj the {@code Object} to compare
1811      * @return {@code trueif the objects are the same
1812      *          or if the argument is a {@code Font} object
1813      *          describing the same font as this object;
1814      *          {@code false} otherwise.
1815      * @since 1.0
1816      */

1817     public boolean equals(Object obj) {
1818         if (obj == this) {
1819             return true;
1820         }
1821
1822         if (obj instanceof Font) {
1823             Font font = (Font)obj;
1824             if (size == font.size &&
1825                 style == font.style &&
1826                 nonIdentityTx == font.nonIdentityTx &&
1827                 hasLayoutAttributes == font.hasLayoutAttributes &&
1828                 pointSize == font.pointSize &&
1829                 name.equals(font.name)) {
1830
1831                 /* 'values' is usually initialized lazily, except when
1832                  * the font is constructed from a Map, or derived using
1833                  * a Map or other values. So if only one font has
1834                  * the field initialized we need to initialize it in
1835                  * the other instance and compare.
1836                  */

1837                 if (values == null) {
1838                     if (font.values == null) {
1839                         return true;
1840                     } else {
1841                         return getAttributeValues().equals(font.values);
1842                     }
1843                 } else {
1844                     return values.equals(font.getAttributeValues());
1845                 }
1846             }
1847         }
1848         return false;
1849     }
1850
1851     /**
1852      * Converts this {@code Font} object to a {@code String}
1853      * representation.
1854      * @return     a {@code String} representation of this
1855      *          {@code Font} object.
1856      * @since      1.0
1857      */

1858     // NOTE: This method may be called by privileged threads.
1859     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
1860     public String toString() {
1861         String  strStyle;
1862
1863         if (isBold()) {
1864             strStyle = isItalic() ? "bolditalic" : "bold";
1865         } else {
1866             strStyle = isItalic() ? "italic" : "plain";
1867         }
1868
1869         return getClass().getName() + "[family=" + getFamily() + ",name=" + name + ",style=" +
1870             strStyle + ",size=" + size + "]";
1871     } // toString()
1872
1873
1874     /** Serialization support.  A {@code readObject}
1875      *  method is necessary because the constructor creates
1876      *  the font's peer, and we can't serialize the peer.
1877      *  Similarly the computed font "family" may be different
1878      *  at {@code readObject} time than at
1879      *  {@code writeObject} time.  An integer version is
1880      *  written so that future versions of this class will be
1881      *  able to recognize serialized output from this one.
1882      */

1883     /**
1884      * The {@code Font} Serializable Data Form.
1885      *
1886      * @serial
1887      */

1888     private int fontSerializedDataVersion = 1;
1889
1890     /**
1891      * Writes default serializable fields to a stream.
1892      *
1893      * @param s the {@code ObjectOutputStream} to write
1894      * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
1895      * @see #readObject(java.io.ObjectInputStream)
1896      */

1897     private void writeObject(java.io.ObjectOutputStream s)
1898       throws java.lang.ClassNotFoundException,
1899              java.io.IOException
1900     {
1901         if (values != null) {
1902           synchronized(values) {
1903             // transient
1904             fRequestedAttributes = values.toSerializableHashtable();
1905             s.defaultWriteObject();
1906             fRequestedAttributes = null;
1907           }
1908         } else {
1909           s.defaultWriteObject();
1910         }
1911     }
1912
1913     /**
1914      * Reads the {@code ObjectInputStream}.
1915      * Unrecognized keys or values will be ignored.
1916      *
1917      * @param s the {@code ObjectInputStream} to read
1918      * @serial
1919      * @see #writeObject(java.io.ObjectOutputStream)
1920      */

1921     private void readObject(java.io.ObjectInputStream s)
1922       throws java.lang.ClassNotFoundException,
1923              java.io.IOException
1924     {
1925         s.defaultReadObject();
1926         if (pointSize == 0) {
1927             pointSize = (float)size;
1928         }
1929
1930         // Handle fRequestedAttributes.
1931         // in 1.5, we always streamed out the font values plus
1932         // TRANSFORM, SUPERSCRIPT, and WIDTH, regardless of whether the
1933         // values were default or not.  In 1.6 we only stream out
1934         // defined values.  So, 1.6 streams in from a 1.5 stream,
1935         // it check each of these values and 'undefines' it if the
1936         // value is the default.
1937
1938         if (fRequestedAttributes != null) {
1939             try {
1940             values = getAttributeValues(); // init
1941             AttributeValues extras =
1942                 AttributeValues.fromSerializableHashtable(fRequestedAttributes);
1943             if (!AttributeValues.is16Hashtable(fRequestedAttributes)) {
1944                 extras.unsetDefault(); // if legacy stream, undefine these
1945             }
1946             values = getAttributeValues().merge(extras);
1947             this.nonIdentityTx = values.anyNonDefault(EXTRA_MASK);
1948             this.hasLayoutAttributes =  values.anyNonDefault(LAYOUT_MASK);
1949             } catch (Throwable t) {
1950                 throw new IOException(t);
1951             } finally {
1952             fRequestedAttributes = null// don't need it any more
1953         }
1954     }
1955     }
1956
1957     /**
1958      * Returns the number of glyphs in this {@code Font}. Glyph codes
1959      * for this {@code Font} range from 0 to
1960      * {@code getNumGlyphs()} - 1.
1961      * @return the number of glyphs in this {@code Font}.
1962      * @since 1.2
1963      */

1964     public int getNumGlyphs() {
1965         return  getFont2D().getNumGlyphs();
1966     }
1967
1968     /**
1969      * Returns the glyphCode which is used when this {@code Font}
1970      * does not have a glyph for a specified unicode code point.
1971      * @return the glyphCode of this {@code Font}.
1972      * @since 1.2
1973      */

1974     public int getMissingGlyphCode() {
1975         return getFont2D().getMissingGlyphCode();
1976     }
1977
1978     /**
1979      * Returns the baseline appropriate for displaying this character.
1980      * <p>
1981      * Large fonts can support different writing systems, and each system can
1982      * use a different baseline.
1983      * The character argument determines the writing system to use. Clients
1984      * should not assume all characters use the same baseline.
1985      *
1986      * @param c a character used to identify the writing system
1987      * @return the baseline appropriate for the specified character.
1988      * @see LineMetrics#getBaselineOffsets
1989      * @see #ROMAN_BASELINE
1990      * @see #CENTER_BASELINE
1991      * @see #HANGING_BASELINE
1992      * @since 1.2
1993      */

1994     public byte getBaselineFor(char c) {
1995         return getFont2D().getBaselineFor(c);
1996     }
1997
1998     /**
1999      * Returns a map of font attributes available in this
2000      * {@code Font}.  Attributes include things like ligatures and
2001      * glyph substitution.
2002      * @return the attributes map of this {@code Font}.
2003      */

2004     public Map<TextAttribute,?> getAttributes(){
2005         return new AttributeMap(getAttributeValues());
2006     }
2007
2008     /**
2009      * Returns the keys of all the attributes supported by this
2010      * {@code Font}.  These attributes can be used to derive other
2011      * fonts.
2012      * @return an array containing the keys of all the attributes
2013      *          supported by this {@code Font}.
2014      * @since 1.2
2015      */

2016     public Attribute[] getAvailableAttributes() {
2017         // FONT is not supported by Font
2018
2019         Attribute attributes[] = {
2020             TextAttribute.FAMILY,
2021             TextAttribute.WEIGHT,
2022             TextAttribute.WIDTH,
2023             TextAttribute.POSTURE,
2024             TextAttribute.SIZE,
2025             TextAttribute.TRANSFORM,
2026             TextAttribute.SUPERSCRIPT,
2027             TextAttribute.CHAR_REPLACEMENT,
2028             TextAttribute.FOREGROUND,
2029             TextAttribute.BACKGROUND,
2030             TextAttribute.UNDERLINE,
2031             TextAttribute.STRIKETHROUGH,
2032             TextAttribute.RUN_DIRECTION,
2033             TextAttribute.BIDI_EMBEDDING,
2034             TextAttribute.JUSTIFICATION,
2035             TextAttribute.INPUT_METHOD_HIGHLIGHT,
2036             TextAttribute.INPUT_METHOD_UNDERLINE,
2037             TextAttribute.SWAP_COLORS,
2038             TextAttribute.NUMERIC_SHAPING,
2039             TextAttribute.KERNING,
2040             TextAttribute.LIGATURES,
2041             TextAttribute.TRACKING,
2042         };
2043
2044         return attributes;
2045     }
2046
2047     /**
2048      * Creates a new {@code Font} object by replicating this
2049      * {@code Font} object and applying a new style and size.
2050      * @param style the style for the new {@code Font}
2051      * @param size the size for the new {@code Font}
2052      * @return a new {@code Font} object.
2053      * @since 1.2
2054      */

2055     public Font deriveFont(int style, float size){
2056         if (values == null) {
2057             return new Font(name, style, size, createdFont, font2DHandle);
2058         }
2059         AttributeValues newValues = getAttributeValues().clone();
2060         int oldStyle = (this.style != style) ? this.style : -1;
2061         applyStyle(style, newValues);
2062         newValues.setSize(size);
2063         return new Font(newValues, null, oldStyle, createdFont, font2DHandle);
2064     }
2065
2066     /**
2067      * Creates a new {@code Font} object by replicating this
2068      * {@code Font} object and applying a new style and transform.
2069      * @param style the style for the new {@code Font}
2070      * @param trans the {@code AffineTransform} associated with the
2071      * new {@code Font}
2072      * @return a new {@code Font} object.
2073      * @throws IllegalArgumentException if {@code trans} is
2074      *         {@code null}
2075      * @since 1.2
2076      */

2077     public Font deriveFont(int style, AffineTransform trans){
2078         AttributeValues newValues = getAttributeValues().clone();
2079         int oldStyle = (this.style != style) ? this.style : -1;
2080         applyStyle(style, newValues);
2081         applyTransform(trans, newValues);
2082         return new Font(newValues, null, oldStyle, createdFont, font2DHandle);
2083     }
2084
2085     /**
2086      * Creates a new {@code Font} object by replicating the current
2087      * {@code Font} object and applying a new size to it.
2088      * @param size the size for the new {@code Font}.
2089      * @return a new {@code Font} object.
2090      * @since 1.2
2091      */

2092     public Font deriveFont(float size){
2093         if (values == null) {
2094             return new Font(name, style, size, createdFont, font2DHandle);
2095         }
2096         AttributeValues newValues = getAttributeValues().clone();
2097         newValues.setSize(size);
2098         return new Font(newValues, null, -1, createdFont, font2DHandle);
2099     }
2100
2101     /**
2102      * Creates a new {@code Font} object by replicating the current
2103      * {@code Font} object and applying a new transform to it.
2104      * @param trans the {@code AffineTransform} associated with the
2105      * new {@code Font}
2106      * @return a new {@code Font} object.
2107      * @throws IllegalArgumentException if {@code trans} is
2108      *         {@code null}
2109      * @since 1.2
2110      */

2111     public Font deriveFont(AffineTransform trans){
2112         AttributeValues newValues = getAttributeValues().clone();
2113         applyTransform(trans, newValues);
2114         return new Font(newValues, null, -1, createdFont, font2DHandle);
2115     }
2116
2117     /**
2118      * Creates a new {@code Font} object by replicating the current
2119      * {@code Font} object and applying a new style to it.
2120      * @param style the style for the new {@code Font}
2121      * @return a new {@code Font} object.
2122      * @since 1.2
2123      */

2124     public Font deriveFont(int style){
2125         if (values == null) {
2126            return new Font(name, style, size, createdFont, font2DHandle);
2127         }
2128         AttributeValues newValues = getAttributeValues().clone();
2129         int oldStyle = (this.style != style) ? this.style : -1;
2130         applyStyle(style, newValues);
2131         return new Font(newValues, null, oldStyle, createdFont, font2DHandle);
2132     }
2133
2134     /**
2135      * Creates a new {@code Font} object by replicating the current
2136      * {@code Font} object and applying a new set of font attributes
2137      * to it.
2138      *
2139      * @param attributes a map of attributes enabled for the new
2140      * {@code Font}
2141      * @return a new {@code Font} object.
2142      * @since 1.2
2143      */

2144     public Font deriveFont(Map<? extends Attribute, ?> attributes) {
2145         if (attributes == null) {
2146             return this;
2147         }
2148         AttributeValues newValues = getAttributeValues().clone();
2149         newValues.merge(attributes, RECOGNIZED_MASK);
2150
2151         return new Font(newValues, name, style, createdFont, font2DHandle);
2152     }
2153
2154     /**
2155      * Checks if this {@code Font} has a glyph for the specified
2156      * character.
2157      *
2158      * <p> <b>Note:</b> This method cannot handle <a
2159      * href="../../java/lang/Character.html#supplementary"> supplementary
2160      * characters</a>. To support all Unicode characters, including
2161      * supplementary characters, use the {@link #canDisplay(int)}
2162      * method or {@code canDisplayUpTo} methods.
2163      *
2164      * @param c the character for which a glyph is needed
2165      * @return {@code trueif this {@code Font} has a glyph for this
2166      *          character; {@code false} otherwise.
2167      * @since 1.2
2168      */

2169     public boolean canDisplay(char c){
2170         return getFont2D().canDisplay(c);
2171     }
2172
2173     /**
2174      * Checks if this {@code Font} has a glyph for the specified
2175      * character.
2176      *
2177      * @param codePoint the character (Unicode code point) for which a glyph
2178      *        is needed.
2179      * @return {@code trueif this {@code Font} has a glyph for the
2180      *          character; {@code false} otherwise.
2181      * @throws IllegalArgumentException if the code point is not a valid Unicode
2182      *          code point.
2183      * @see Character#isValidCodePoint(int)
2184      * @since 1.5
2185      */

2186     public boolean canDisplay(int codePoint) {
2187         if (!Character.isValidCodePoint(codePoint)) {
2188             throw new IllegalArgumentException("invalid code point: " +
2189                                                Integer.toHexString(codePoint));
2190         }
2191         return getFont2D().canDisplay(codePoint);
2192     }
2193
2194     /**
2195      * Indicates whether or not this {@code Font} can display a
2196      * specified {@code String}.  For strings with Unicode encoding,
2197      * it is important to know if a particular font can display the
2198      * string. This method returns an offset into the {@code String}
2199      * {@code str} which is the first character this
2200      * {@code Font} cannot display without using the missing glyph
2201      * code. If the {@code Font} can display all characters, -1 is
2202      * returned.
2203      * @param str a {@code String} object
2204      * @return an offset into {@code str} that points
2205      *          to the first character in {@code str} that this
2206      *          {@code Font} cannot display; or {@code -1} if
2207      *          this {@code Font} can display all characters in
2208      *          {@code str}.
2209      * @since 1.2
2210      */

2211     public int canDisplayUpTo(String str) {
2212         Font2D font2d = getFont2D();
2213         int len = str.length();
2214         for (int i = 0; i < len; i++) {
2215             char c = str.charAt(i);
2216             if (font2d.canDisplay(c)) {
2217                 continue;
2218             }
2219             if (!Character.isHighSurrogate(c)) {
2220                 return i;
2221             }
2222             if (!font2d.canDisplay(str.codePointAt(i))) {
2223                 return i;
2224             }
2225             i++;
2226         }
2227         return -1;
2228     }
2229
2230     /**
2231      * Indicates whether or not this {@code Font} can display
2232      * the characters in the specified {@code text}
2233      * starting at {@code start} and ending at
2234      * {@code limit}.  This method is a convenience overload.
2235      * @param text the specified array of {@code char} values
2236      * @param start the specified starting offset (in
2237      *              {@code char}s) into the specified array of
2238      *              {@code char} values
2239      * @param limit the specified ending offset (in
2240      *              {@code char}s) into the specified array of
2241      *              {@code char} values
2242      * @return an offset into {@code text} that points
2243      *          to the first character in {@code text} that this
2244      *          {@code Font} cannot display; or {@code -1} if
2245      *          this {@code Font} can display all characters in
2246      *          {@code text}.
2247      * @since 1.2
2248      */

2249     public int canDisplayUpTo(char[] text, int start, int limit) {
2250         Font2D font2d = getFont2D();
2251         for (int i = start; i < limit; i++) {
2252             char c = text[i];
2253             if (font2d.canDisplay(c)) {
2254                 continue;
2255             }
2256             if (!Character.isHighSurrogate(c)) {
2257                 return i;
2258             }
2259             if (!font2d.canDisplay(Character.codePointAt(text, i, limit))) {
2260                 return i;
2261             }
2262             i++;
2263         }
2264         return -1;
2265     }
2266
2267     /**
2268      * Indicates whether or not this {@code Font} can display the
2269      * text specified by the {@code iter} starting at
2270      * {@code start} and ending at {@code limit}.
2271      *
2272      * @param iter  a {@link CharacterIterator} object
2273      * @param start the specified starting offset into the specified
2274      *              {@code CharacterIterator}.
2275      * @param limit the specified ending offset into the specified
2276      *              {@code CharacterIterator}.
2277      * @return an offset into {@code iter} that points
2278      *          to the first character in {@code iter} that this
2279      *          {@code Font} cannot display; or {@code -1} if
2280      *          this {@code Font} can display all characters in
2281      *          {@code iter}.
2282      * @since 1.2
2283      */

2284     public int canDisplayUpTo(CharacterIterator iter, int start, int limit) {
2285         Font2D font2d = getFont2D();
2286         char c = iter.setIndex(start);
2287         for (int i = start; i < limit; i++, c = iter.next()) {
2288             if (font2d.canDisplay(c)) {
2289                 continue;
2290             }
2291             if (!Character.isHighSurrogate(c)) {
2292                 return i;
2293             }
2294             char c2 = iter.next();
2295             // c2 could be CharacterIterator.DONE which is not a low surrogate.
2296             if (!Character.isLowSurrogate(c2)) {
2297                 return i;
2298             }
2299             if (!font2d.canDisplay(Character.toCodePoint(c, c2))) {
2300                 return i;
2301             }
2302             i++;
2303         }
2304         return -1;
2305     }
2306
2307     /**
2308      * Returns the italic angle of this {@code Font}.  The italic angle
2309      * is the inverse slope of the caret which best matches the posture of this
2310      * {@code Font}.
2311      * @see TextAttribute#POSTURE
2312      * @return the angle of the ITALIC style of this {@code Font}.
2313      */

2314     public float getItalicAngle() {
2315         return getItalicAngle(null);
2316     }
2317
2318     /* The FRC hints don't affect the value of the italic angle but
2319      * we need to pass them in to look up a strike.
2320      * If we can pass in ones already being used it can prevent an extra
2321      * strike from being allocated. Note that since italic angle is
2322      * a property of the font, the font transform is needed not the
2323      * device transform. Finally, this is private but the only caller of this
2324      * in the JDK - and the only likely caller - is in this same class.
2325      */

2326     private float getItalicAngle(FontRenderContext frc) {
2327         Object aa, fm;
2328         if (frc == null) {
2329             aa = RenderingHints.VALUE_TEXT_ANTIALIAS_OFF;
2330             fm = RenderingHints.VALUE_FRACTIONALMETRICS_OFF;
2331         } else {
2332             aa = frc.getAntiAliasingHint();
2333             fm = frc.getFractionalMetricsHint();
2334         }
2335         return getFont2D().getItalicAngle(this, identityTx, aa, fm);
2336     }
2337
2338     /**
2339      * Checks whether or not this {@code Font} has uniform
2340      * line metrics.  A logical {@code Font} might be a
2341      * composite font, which means that it is composed of different
2342      * physical fonts to cover different code ranges.  Each of these
2343      * fonts might have different {@code LineMetrics}.  If the
2344      * logical {@code Font} is a single
2345      * font then the metrics would be uniform.
2346      * @return {@code trueif this {@code Font} has
2347      * uniform line metrics; {@code false} otherwise.
2348      */

2349     public boolean hasUniformLineMetrics() {
2350         return false;   // REMIND always safe, but prevents caller optimize
2351     }
2352
2353     private transient SoftReference<FontLineMetrics> flmref;
2354     private FontLineMetrics defaultLineMetrics(FontRenderContext frc) {
2355         FontLineMetrics flm = null;
2356         if (flmref == null
2357             || (flm = flmref.get()) == null
2358             || !flm.frc.equals(frc)) {
2359
2360             /* The device transform in the frc is not used in obtaining line
2361              * metrics, although it probably should be: REMIND find why not?
2362              * The font transform is used but its applied in getFontMetrics, so
2363              * just pass identity here
2364              */

2365             float [] metrics = new float[8];
2366             getFont2D().getFontMetrics(this, identityTx,
2367                                        frc.getAntiAliasingHint(),
2368                                        frc.getFractionalMetricsHint(),
2369                                        metrics);
2370             float ascent  = metrics[0];
2371             float descent = metrics[1];
2372             float leading = metrics[2];
2373             float ssOffset = 0;
2374             if (values != null && values.getSuperscript() != 0) {
2375                 ssOffset = (float)getTransform().getTranslateY();
2376                 ascent -= ssOffset;
2377                 descent += ssOffset;
2378             }
2379             float height = ascent + descent + leading;
2380
2381             int baselineIndex = 0; // need real index, assumes roman for everything
2382             // need real baselines eventually
2383             float[] baselineOffsets = { 0, (descent/2f - ascent) / 2f, -ascent };
2384
2385             float strikethroughOffset = metrics[4];
2386             float strikethroughThickness = metrics[5];
2387
2388             float underlineOffset = metrics[6];
2389             float underlineThickness = metrics[7];
2390
2391             float italicAngle = getItalicAngle(frc);
2392
2393             if (isTransformed()) {
2394                 AffineTransform ctx = values.getCharTransform(); // extract rotation
2395                 if (ctx != null) {
2396                     Point2D.Float pt = new Point2D.Float();
2397                     pt.setLocation(0, strikethroughOffset);
2398                     ctx.deltaTransform(pt, pt);
2399                     strikethroughOffset = pt.y;
2400                     pt.setLocation(0, strikethroughThickness);
2401                     ctx.deltaTransform(pt, pt);
2402                     strikethroughThickness = pt.y;
2403                     pt.setLocation(0, underlineOffset);
2404                     ctx.deltaTransform(pt, pt);
2405                     underlineOffset = pt.y;
2406                     pt.setLocation(0, underlineThickness);
2407                     ctx.deltaTransform(pt, pt);
2408                     underlineThickness = pt.y;
2409                 }
2410             }
2411             strikethroughOffset += ssOffset;
2412             underlineOffset += ssOffset;
2413
2414             CoreMetrics cm = new CoreMetrics(ascent, descent, leading, height,
2415                                              baselineIndex, baselineOffsets,
2416                                              strikethroughOffset, strikethroughThickness,
2417                                              underlineOffset, underlineThickness,
2418                                              ssOffset, italicAngle);
2419
2420             flm = new FontLineMetrics(0, cm, frc);
2421             flmref = new SoftReference<FontLineMetrics>(flm);
2422         }
2423
2424         return (FontLineMetrics)flm.clone();
2425     }
2426
2427     /**
2428      * Returns a {@link LineMetrics} object created with the specified
2429      * {@code String} and {@link FontRenderContext}.
2430      * @param str the specified {@code String}
2431      * @param frc the specified {@code FontRenderContext}
2432      * @return a {@code LineMetrics} object created with the
2433      * specified {@code String} and {@link FontRenderContext}.
2434      */

2435     public LineMetrics getLineMetrics( String str, FontRenderContext frc) {
2436         FontLineMetrics flm = defaultLineMetrics(frc);
2437         flm.numchars = str.length();
2438         return flm;
2439     }
2440
2441     /**
2442      * Returns a {@code LineMetrics} object created with the
2443      * specified arguments.
2444      * @param str the specified {@code String}
2445      * @param beginIndex the initial offset of {@code str}
2446      * @param limit the end offset of {@code str}
2447      * @param frc the specified {@code FontRenderContext}
2448      * @return a {@code LineMetrics} object created with the
2449      * specified arguments.
2450      */

2451     public LineMetrics getLineMetrics( String str,
2452                                     int beginIndex, int limit,
2453                                     FontRenderContext frc) {
2454         FontLineMetrics flm = defaultLineMetrics(frc);
2455         int numChars = limit - beginIndex;
2456         flm.numchars = (numChars < 0)? 0: numChars;
2457         return flm;
2458     }
2459
2460     /**
2461      * Returns a {@code LineMetrics} object created with the
2462      * specified arguments.
2463      * @param chars an array of characters
2464      * @param beginIndex the initial offset of {@code chars}
2465      * @param limit the end offset of {@code chars}
2466      * @param frc the specified {@code FontRenderContext}
2467      * @return a {@code LineMetrics} object created with the
2468      * specified arguments.
2469      */

2470     public LineMetrics getLineMetrics(char [] chars,
2471                                     int beginIndex, int limit,
2472                                     FontRenderContext frc) {
2473         FontLineMetrics flm = defaultLineMetrics(frc);
2474         int numChars = limit - beginIndex;
2475         flm.numchars = (numChars < 0)? 0: numChars;
2476         return flm;
2477     }
2478
2479     /**
2480      * Returns a {@code LineMetrics} object created with the
2481      * specified arguments.
2482      * @param ci the specified {@code CharacterIterator}
2483      * @param beginIndex the initial offset in {@code ci}
2484      * @param limit the end offset of {@code ci}
2485      * @param frc the specified {@code FontRenderContext}
2486      * @return a {@code LineMetrics} object created with the
2487      * specified arguments.
2488      */

2489     public LineMetrics getLineMetrics(CharacterIterator ci,
2490                                     int beginIndex, int limit,
2491                                     FontRenderContext frc) {
2492         FontLineMetrics flm = defaultLineMetrics(frc);
2493         int numChars = limit - beginIndex;
2494         flm.numchars = (numChars < 0)? 0: numChars;
2495         return flm;
2496     }
2497
2498     /**
2499      * Returns the logical bounds of the specified {@code String} in
2500      * the specified {@code FontRenderContext}.  The logical bounds
2501      * contains the origin, ascent, advance, and height, which includes
2502      * the leading.  The logical bounds does not always enclose all the
2503      * text.  For example, in some languages and in some fonts, accent
2504      * marks can be positioned above the ascent or below the descent.
2505      * To obtain a visual bounding box, which encloses all the text,
2506      * use the {@link TextLayout#getBounds() getBounds} method of
2507      * {@code TextLayout}.
2508      * <p>Note: The returned bounds is in baseline-relative coordinates
2509      * (see {@link java.awt.Font class notes}).
2510      * @param str the specified {@code String}
2511      * @param frc the specified {@code FontRenderContext}
2512      * @return a {@link Rectangle2D} that is the bounding box of the
2513      * specified {@code String} in the specified
2514      * {@code FontRenderContext}.
2515      * @see FontRenderContext
2516      * @see Font#createGlyphVector
2517      * @since 1.2
2518      */

2519     public Rectangle2D getStringBounds( String str, FontRenderContext frc) {
2520         char[] array = str.toCharArray();
2521         return getStringBounds(array, 0, array.length, frc);
2522     }
2523
2524    /**
2525      * Returns the logical bounds of the specified {@code String} in
2526      * the specified {@code FontRenderContext}.  The logical bounds
2527      * contains the origin, ascent, advance, and height, which includes
2528      * the leading.  The logical bounds does not always enclose all the
2529      * text.  For example, in some languages and in some fonts, accent
2530      * marks can be positioned above the ascent or below the descent.
2531      * To obtain a visual bounding box, which encloses all the text,
2532      * use the {@link TextLayout#getBounds() getBounds} method of
2533      * {@code TextLayout}.
2534      * <p>Note: The returned bounds is in baseline-relative coordinates
2535      * (see {@link java.awt.Font class notes}).
2536      * @param str the specified {@code String}
2537      * @param beginIndex the initial offset of {@code str}
2538      * @param limit the end offset of {@code str}
2539      * @param frc the specified {@code FontRenderContext}
2540      * @return a {@code Rectangle2D} that is the bounding box of the
2541      * specified {@code String} in the specified
2542      * {@code FontRenderContext}.
2543      * @throws IndexOutOfBoundsException if {@code beginIndex} is
2544      *         less than zero, or {@code limit} is greater than the
2545      *         length of {@code str}, or {@code beginIndex}
2546      *         is greater than {@code limit}.
2547      * @see FontRenderContext
2548      * @see Font#createGlyphVector
2549      * @since 1.2
2550      */

2551     public Rectangle2D getStringBounds( String str,
2552                                     int beginIndex, int limit,
2553                                         FontRenderContext frc) {
2554         String substr = str.substring(beginIndex, limit);
2555         return getStringBounds(substr, frc);
2556     }
2557
2558    /**
2559      * Returns the logical bounds of the specified array of characters
2560      * in the specified {@code FontRenderContext}.  The logical
2561      * bounds contains the origin, ascent, advance, and height, which
2562      * includes the leading.  The logical bounds does not always enclose
2563      * all the text.  For example, in some languages and in some fonts,
2564      * accent marks can be positioned above the ascent or below the
2565      * descent.  To obtain a visual bounding box, which encloses all the
2566      * text, use the {@link TextLayout#getBounds() getBounds} method of
2567      * {@code TextLayout}.
2568      * <p>Note: The returned bounds is in baseline-relative coordinates
2569      * (see {@link java.awt.Font class notes}).
2570      * @param chars an array of characters
2571      * @param beginIndex the initial offset in the array of
2572      * characters
2573      * @param limit the end offset in the array of characters
2574      * @param frc the specified {@code FontRenderContext}
2575      * @return a {@code Rectangle2D} that is the bounding box of the
2576      * specified array of characters in the specified
2577      * {@code FontRenderContext}.
2578      * @throws IndexOutOfBoundsException if {@code beginIndex} is
2579      *         less than zero, or {@code limit} is greater than the
2580      *         length of {@code chars}, or {@code beginIndex}
2581      *         is greater than {@code limit}.
2582      * @see FontRenderContext
2583      * @see Font#createGlyphVector
2584      * @since 1.2
2585      */

2586     public Rectangle2D getStringBounds(char [] chars,
2587                                     int beginIndex, int limit,
2588                                        FontRenderContext frc) {
2589         if (beginIndex < 0) {
2590             throw new IndexOutOfBoundsException("beginIndex: " + beginIndex);
2591         }
2592         if (limit > chars.length) {
2593             throw new IndexOutOfBoundsException("limit: " + limit);
2594         }
2595         if (beginIndex > limit) {
2596             throw new IndexOutOfBoundsException("range length: " +
2597                                                 (limit - beginIndex));
2598         }
2599
2600         // this code should be in textlayout
2601         // quick check for simple text, assume GV ok to use if simple
2602
2603         boolean simple = values == null ||
2604             (values.getKerning() == 0 && values.getLigatures() == 0 &&
2605               values.getBaselineTransform() == null);
2606         if (simple) {
2607             simple = ! FontUtilities.isComplexText(chars, beginIndex, limit);
2608         }
2609
2610         if (simple) {
2611             FontDesignMetrics metrics = FontDesignMetrics.getMetrics(this, frc);
2612             return metrics.getSimpleBounds(chars, beginIndex, limit-beginIndex);
2613         } else {
2614             // need char array constructor on textlayout
2615             String str = new String(chars, beginIndex, limit - beginIndex);
2616             TextLayout tl = new TextLayout(str, this, frc);
2617             return new Rectangle2D.Float(0, -tl.getAscent(), tl.getAdvance(),
2618                                          tl.getAscent() + tl.getDescent() +
2619                                          tl.getLeading());
2620         }
2621     }
2622
2623    /**
2624      * Returns the logical bounds of the characters indexed in the
2625      * specified {@link CharacterIterator} in the
2626      * specified {@code FontRenderContext}.  The logical bounds
2627      * contains the origin, ascent, advance, and height, which includes
2628      * the leading.  The logical bounds does not always enclose all the
2629      * text.  For example, in some languages and in some fonts, accent
2630      * marks can be positioned above the ascent or below the descent.
2631      * To obtain a visual bounding box, which encloses all the text,
2632      * use the {@link TextLayout#getBounds() getBounds} method of
2633      * {@code TextLayout}.
2634      * <p>Note: The returned bounds is in baseline-relative coordinates
2635      * (see {@link java.awt.Font class notes}).
2636      * @param ci the specified {@code CharacterIterator}
2637      * @param beginIndex the initial offset in {@code ci}
2638      * @param limit the end offset in {@code ci}
2639      * @param frc the specified {@code FontRenderContext}
2640      * @return a {@code Rectangle2D} that is the bounding box of the
2641      * characters indexed in the specified {@code CharacterIterator}
2642      * in the specified {@code FontRenderContext}.
2643      * @see FontRenderContext
2644      * @see Font#createGlyphVector
2645      * @since 1.2
2646      * @throws IndexOutOfBoundsException if {@code beginIndex} is
2647      *         less than the start index of {@code ci}, or
2648      *         {@code limit} is greater than the end index of
2649      *         {@code ci}, or {@code beginIndex} is greater
2650      *         than {@code limit}
2651      */

2652     public Rectangle2D getStringBounds(CharacterIterator ci,
2653                                     int beginIndex, int limit,
2654                                        FontRenderContext frc) {
2655         int start = ci.getBeginIndex();
2656         int end = ci.getEndIndex();
2657
2658         if (beginIndex < start) {
2659             throw new IndexOutOfBoundsException("beginIndex: " + beginIndex);
2660         }
2661         if (limit > end) {
2662             throw new IndexOutOfBoundsException("limit: " + limit);
2663         }
2664         if (beginIndex > limit) {
2665             throw new IndexOutOfBoundsException("range length: " +
2666                                                 (limit - beginIndex));
2667         }
2668
2669         char[]  arr = new char[limit - beginIndex];
2670
2671         ci.setIndex(beginIndex);
2672         for(int idx = 0; idx < arr.length; idx++) {
2673             arr[idx] = ci.current();
2674             ci.next();
2675         }
2676
2677         return getStringBounds(arr,0,arr.length,frc);
2678     }
2679
2680     /**
2681      * Returns the bounds for the character with the maximum
2682      * bounds as defined in the specified {@code FontRenderContext}.
2683      * <p>Note: The returned bounds is in baseline-relative coordinates
2684      * (see {@link java.awt.Font class notes}).
2685      * @param frc the specified {@code FontRenderContext}
2686      * @return a {@code Rectangle2D} that is the bounding box
2687      * for the character with the maximum bounds.
2688      */

2689     public Rectangle2D getMaxCharBounds(FontRenderContext frc) {
2690         float [] metrics = new float[4];
2691
2692         getFont2D().getFontMetrics(this, frc, metrics);
2693
2694         return new Rectangle2D.Float(0, -metrics[0],
2695                                 metrics[3],
2696                                 metrics[0] + metrics[1] + metrics[2]);
2697     }
2698
2699     /**
2700      * Creates a {@link java.awt.font.GlyphVector GlyphVector} by
2701      * mapping characters to glyphs one-to-one based on the
2702      * Unicode cmap in this {@code Font}.  This method does no other
2703      * processing besides the mapping of glyphs to characters.  This
2704      * means that this method is not useful for some scripts, such
2705      * as Arabic, Hebrew, Thai, and Indic, that require reordering,
2706      * shaping, or ligature substitution.
2707      * @param frc the specified {@code FontRenderContext}
2708      * @param str the specified {@code String}
2709      * @return a new {@code GlyphVector} created with the
2710      * specified {@code String} and the specified
2711      * {@code FontRenderContext}.
2712      */

2713     public GlyphVector createGlyphVector(FontRenderContext frc, String str)
2714     {
2715         return (GlyphVector)new StandardGlyphVector(this, str, frc);
2716     }
2717
2718     /**
2719      * Creates a {@link java.awt.font.GlyphVector GlyphVector} by
2720      * mapping characters to glyphs one-to-one based on the
2721      * Unicode cmap in this {@code Font}.  This method does no other
2722      * processing besides the mapping of glyphs to characters.  This
2723      * means that this method is not useful for some scripts, such
2724      * as Arabic, Hebrew, Thai, and Indic, that require reordering,
2725      * shaping, or ligature substitution.
2726      * @param frc the specified {@code FontRenderContext}
2727      * @param chars the specified array of characters
2728      * @return a new {@code GlyphVector} created with the
2729      * specified array of characters and the specified
2730      * {@code FontRenderContext}.
2731      */

2732     public GlyphVector createGlyphVector(FontRenderContext frc, char[] chars)
2733     {
2734         return (GlyphVector)new StandardGlyphVector(this, chars, frc);
2735     }
2736
2737     /**
2738      * Creates a {@link java.awt.font.GlyphVector GlyphVector} by
2739      * mapping the specified characters to glyphs one-to-one based on the
2740      * Unicode cmap in this {@code Font}.  This method does no other
2741      * processing besides the mapping of glyphs to characters.  This
2742      * means that this method is not useful for some scripts, such
2743      * as Arabic, Hebrew, Thai, and Indic, that require reordering,
2744      * shaping, or ligature substitution.
2745      * @param frc the specified {@code FontRenderContext}
2746      * @param ci the specified {@code CharacterIterator}
2747      * @return a new {@code GlyphVector} created with the
2748      * specified {@code CharacterIterator} and the specified
2749      * {@code FontRenderContext}.
2750      */

2751     public GlyphVector createGlyphVector(   FontRenderContext frc,
2752                                             CharacterIterator ci)
2753     {
2754         return (GlyphVector)new StandardGlyphVector(this, ci, frc);
2755     }
2756
2757     /**
2758      * Creates a {@link java.awt.font.GlyphVector GlyphVector} by
2759      * mapping characters to glyphs one-to-one based on the
2760      * Unicode cmap in this {@code Font}.  This method does no other
2761      * processing besides the mapping of glyphs to characters.  This
2762      * means that this method is not useful for some scripts, such
2763      * as Arabic, Hebrew, Thai, and Indic, that require reordering,
2764      * shaping, or ligature substitution.
2765      * @param frc the specified {@code FontRenderContext}
2766      * @param glyphCodes the specified integer array
2767      * @return a new {@code GlyphVector} created with the
2768      * specified integer array and the specified
2769      * {@code FontRenderContext}.
2770      */

2771     public GlyphVector createGlyphVector(   FontRenderContext frc,
2772                                             int [] glyphCodes)
2773     {
2774         return (GlyphVector)new StandardGlyphVector(this, glyphCodes, frc);
2775     }
2776
2777     /**
2778      * Returns a new {@code GlyphVector} object, performing full
2779      * layout of the text if possible.  Full layout is required for
2780      * complex text, such as Arabic or Hindi.  Support for different
2781      * scripts depends on the font and implementation.
2782      * <p>
2783      * Layout requires bidi analysis, as performed by
2784      * {@code Bidi}, and should only be performed on text that
2785      * has a uniform direction.  The direction is indicated in the
2786      * flags parameter,by using LAYOUT_RIGHT_TO_LEFT to indicate a
2787      * right-to-left (Arabic and Hebrew) run direction, or
2788      * LAYOUT_LEFT_TO_RIGHT to indicate a left-to-right (English)
2789      * run direction.
2790      * <p>
2791      * In addition, some operations, such as Arabic shaping, require
2792      * context, so that the characters at the start and limit can have
2793      * the proper shapes.  Sometimes the data in the buffer outside
2794      * the provided range does not have valid data.  The values
2795      * LAYOUT_NO_START_CONTEXT and LAYOUT_NO_LIMIT_CONTEXT can be
2796      * added to the flags parameter to indicate that the text before
2797      * start, or after limit, respectively, should not be examined
2798      * for context.
2799      * <p>
2800      * All other values for the flags parameter are reserved.
2801      *
2802      * @param frc the specified {@code FontRenderContext}
2803      * @param text the text to layout
2804      * @param start the start of the text to use for the {@code GlyphVector}
2805      * @param limit the limit of the text to use for the {@code GlyphVector}
2806      * @param flags control flags as described above
2807      * @return a new {@code GlyphVector} representing the text between
2808      * start and limit, with glyphs chosen and positioned so as to best represent
2809      * the text
2810      * @throws ArrayIndexOutOfBoundsException if start or limit is
2811      * out of bounds
2812      * @see java.text.Bidi
2813      * @see #LAYOUT_LEFT_TO_RIGHT
2814      * @see #LAYOUT_RIGHT_TO_LEFT
2815      * @see #LAYOUT_NO_START_CONTEXT
2816      * @see #LAYOUT_NO_LIMIT_CONTEXT
2817      * @since 1.4
2818      */

2819     public GlyphVector layoutGlyphVector(FontRenderContext frc,
2820                                          char[] text,
2821                                          int start,
2822                                          int limit,
2823                                          int flags) {
2824
2825         GlyphLayout gl = GlyphLayout.get(null); // !!! no custom layout engines
2826         StandardGlyphVector gv = gl.layout(this, frc, text,
2827                                            start, limit-start, flags, null);
2828         GlyphLayout.done(gl);
2829         return gv;
2830     }
2831
2832     /**
2833      * A flag to layoutGlyphVector indicating that text is left-to-right as
2834      * determined by Bidi analysis.
2835      */

2836     public static final int LAYOUT_LEFT_TO_RIGHT = 0;
2837
2838     /**
2839      * A flag to layoutGlyphVector indicating that text is right-to-left as
2840      * determined by Bidi analysis.
2841      */

2842     public static final int LAYOUT_RIGHT_TO_LEFT = 1;
2843
2844     /**
2845      * A flag to layoutGlyphVector indicating that text in the char array
2846      * before the indicated start should not be examined.
2847      */

2848     public static final int LAYOUT_NO_START_CONTEXT = 2;
2849
2850     /**
2851      * A flag to layoutGlyphVector indicating that text in the char array
2852      * after the indicated limit should not be examined.
2853      */

2854     public static final int LAYOUT_NO_LIMIT_CONTEXT = 4;
2855
2856
2857     private static void applyTransform(AffineTransform trans, AttributeValues values) {
2858         if (trans == null) {
2859             throw new IllegalArgumentException("transform must not be null");
2860         }
2861         values.setTransform(trans);
2862     }
2863
2864     private static void applyStyle(int style, AttributeValues values) {
2865         // WEIGHT_BOLD, WEIGHT_REGULAR
2866         values.setWeight((style & BOLD) != 0 ? 2f : 1f);
2867         // POSTURE_OBLIQUE, POSTURE_REGULAR
2868         values.setPosture((style & ITALIC) != 0 ? .2f : 0f);
2869     }
2870
2871     /*
2872      * Initialize JNI field and method IDs
2873      */

2874     private static native void initIDs();
2875 }
2876