~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/ikvm/openjdk/java/awt/Font.java

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

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