History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/awt/Font.java (1 of 18352 files). Show all

Unified · Split

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