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.
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.
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).
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.
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
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;
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;
48
import sun.font.StandardGlyphVector;
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;
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;
71
import static sun.font.EAttribute.*;
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.
81
* <h4>Characters and Glyphs</h4>
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.
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 'á'
91
* <font size=-1>LATIN SMALL LETTER A WITH ACUTE</font>, can be represented by
92
* two glyphs: one for 'a' and one for '´'. 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.
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.
103
* <h4>Physical and Logical Fonts</h4>
105
* The Java Platform distinguishes between two kinds of fonts:
106
* <em>physical</em> fonts and <em>logical</em> fonts.
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
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.
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.
132
* Peered AWT components, such as {@link Label Label} and
133
* {@link TextField TextField}, can only use logical fonts.
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>
140
* <h4>Font Faces and Names</h4>
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.
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.
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
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.
170
* <h4>Font and TextAttribute</h4>
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.
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.
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>
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
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>
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>
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
231
public class Font implements java.io.Serializable
233
private static class FontAccessImpl extends FontAccess {
234
public Font2D getFont2D(Font font) {
235
return font.getFont2D();
238
public void setFont2D(Font font, Font2DHandle handle) {
239
font.font2DHandle = handle;
242
public void setCreatedFont(Font font) {
243
font.createdFont = true;
246
public boolean isCreatedFont(Font font) {
247
return font.createdFont;
252
FontAccess.setFontAccess(new FontAccessImpl());
256
* This is now only used during serialization. Typically
260
* @see #getAttributes()
262
private Hashtable fRequestedAttributes;
265
* Constants to be used for logical font family names.
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.
274
public static final String DIALOG = "Dialog";
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.
282
public static final String DIALOG_INPUT = "DialogInput";
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.
290
public static final String SANS_SERIF = "SansSerif";
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.
298
public static final String SERIF = "Serif";
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.
306
public static final String MONOSPACED = "Monospaced";
309
* Constants to be used for styles. Can be combined to mix
314
* The plain style constant.
316
public static final int PLAIN = 0;
319
* The bold style constant. This can be combined with the other style
320
* constants (except PLAIN) for mixed styles.
322
public static final int BOLD = 1;
325
* The italicized style constant. This can be combined with the other
326
* style constants (except PLAIN) for mixed styles.
328
public static final int ITALIC = 2;
331
* The baseline used in most Roman scripts when laying out text.
333
public static final int ROMAN_BASELINE = 0;
336
* The baseline used in ideographic scripts like Chinese, Japanese,
337
* and Korean when laying out text.
339
public static final int CENTER_BASELINE = 1;
342
* The baseline used in Devanigiri and similar scripts when laying
345
public static final int HANGING_BASELINE = 2;
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.
358
public static final int TRUETYPE_FONT = 0;
361
* Identify a font resource of type TYPE1.
362
* Used to specify a Type1 font resource to the
363
* {@link #createFont} method.
366
public static final int TYPE1_FONT = 1;
369
* The logical name of this <code>Font</code>, as passed to the
376
protected String name;
379
* The style of this <code>Font</code>, as passed to the constructor.
380
* This style can be PLAIN, BOLD, ITALIC, or BOLD+ITALIC.
389
* The point size of this <code>Font</code>, rounded to integer.
398
* The point size of this <code>Font</code> in <code>float</code>.
404
protected float pointSize;
407
* The platform specific font information.
409
private transient FontPeer peer;
410
private transient cli.System.Drawing.Font netFont;
411
private transient Font2DHandle font2DHandle;
413
private transient AttributeValues values;
414
private transient boolean hasLayoutAttributes;
417
* If the origin of a Font is a created font then this attribute
418
* must be set on all derived fonts too.
420
private transient boolean createdFont = false;
423
* This is true if the font transform is not identity. It
424
* is used to avoid unnecessary instantiation of an AffineTransform.
426
private transient boolean nonIdentityTx;
429
* A cached value used when a transform is required for internal
430
* use. This must not be exposed to callers since AffineTransform
433
private static final AffineTransform identityTx = new AffineTransform();
436
* JDK 1.1 serialVersionUID
438
private static final long serialVersionUID = -4206021311591459213L;
441
* Gets the peer of this <code>Font</code>.
442
* @return the peer of the <code>Font</code>.
444
* @deprecated Font rendering is now platform independent.
447
public FontPeer getPeer(){
448
return getPeer_NoClientCode();
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() {
456
Toolkit tk = Toolkit.getDefaultToolkit();
457
this.peer = tk.getFontPeer(name, style);
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.
469
* <p>Since the AttributeValues object is mutable, and it
470
* is cached in the font, care must be taken to ensure that
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.
479
if ((style & BOLD) != 0) {
480
valuesTmp.setWeight(2); // WEIGHT_BOLD
483
if ((style & ITALIC) != 0) {
484
valuesTmp.setPosture(.2f); // POSTURE_OBLIQUE
486
valuesTmp.defineAll(PRIMARY_MASK); // for streaming compatibility
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) {
503
fm.findFont2D(name, style,
504
FontManager.LOGICAL_FALLBACK).handle;
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
510
return font2DHandle.font2D;
513
@cli.IKVM.Attributes.HideFromJavaAttribute.Annotation
514
public cli.System.Drawing.Font getNetFont(){
516
netFont = getFont2D().createNetFont(this);
521
* Creates a new <code>Font</code> from the specified name, style and
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.
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).
546
* Font name lookup is case insensitive, using the case folding
547
* rules of the US locale.
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".
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
577
public Font(String name, int style, int size) {
578
this.name = (name != null) ? name : "Default";
579
this.style = (style & ~0x03) == 0 ? style : 0;
581
this.pointSize = size;
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;
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
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.
606
if (handle.font2D instanceof CompositeFont &&
607
handle.font2D.getStyle() != style) {
608
FontManager fm = FontManagerFactory.getInstance();
609
this.font2DHandle = fm.getNewComposite(null, style, handle);
611
this.font2DHandle = handle;
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".
639
private Font(AttributeValues values, String oldName, int oldStyle,
640
boolean created, Font2DHandle handle) {
642
this.createdFont = created;
644
this.font2DHandle = handle;
646
String newName = null;
647
if (oldName != null) {
648
newName = values.getFamily();
649
if (oldName.equals(newName)) newName = null;
652
if (oldStyle == -1) {
655
if (values.getWeight() >= 2f) newStyle = BOLD;
656
if (values.getPosture() >= .2f) newStyle |= ITALIC;
657
if (oldStyle == newStyle) newStyle = -1;
659
if (handle.font2D instanceof CompositeFont) {
660
if (newStyle != -1 || newName != null) {
661
FontManager fm = FontManagerFactory.getInstance();
663
fm.getNewComposite(newName, newStyle, handle);
665
} else if (newName != null) {
666
this.createdFont = false;
667
this.font2DHandle = null;
670
initFromValues(values);
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>.
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>
687
public Font(Map<? extends Attribute, ?> attributes) {
688
initFromValues(AttributeValues.fromMap(attributes, RECOGNIZED_MASK));
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
698
protected Font(Font font) {
699
if (font.values != null) {
700
initFromValues(font.getAttributeValues().clone());
702
this.name = font.name;
703
this.style = font.style;
704
this.size = font.size;
705
this.pointSize = font.pointSize;
707
this.font2DHandle = font.font2DHandle;
708
this.createdFont = font.createdFont;
712
* Font recognizes all attributes except FONT.
714
private static final int RECOGNIZED_MASK = AttributeValues.MASK_ALL
715
& ~AttributeValues.getMask(EFONT);
718
* These attributes are considered primary by the FONT attribute.
720
private static final int PRIMARY_MASK =
721
AttributeValues.getMask(EFAMILY, EWEIGHT, EWIDTH, EPOSTURE, ESIZE,
722
ETRANSFORM, ESUPERSCRIPT, ETRACKING);
725
* These attributes are considered secondary by the FONT attribute.
727
private static final int SECONDARY_MASK =
728
RECOGNIZED_MASK & ~PRIMARY_MASK;
731
* These attributes are handled by layout.
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);
741
private static final int EXTRA_MASK =
742
AttributeValues.getMask(ETRANSFORM, ESUPERSCRIPT, EWIDTH);
745
* Initialize the standard Font fields from the values object.
747
private void initFromValues(AttributeValues values) {
748
this.values = values;
749
values.defineAll(PRIMARY_MASK); // for 1.5 streaming compatibility
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
757
this.nonIdentityTx = values.anyNonDefault(EXTRA_MASK);
758
this.hasLayoutAttributes = values.anyNonDefault(LAYOUT_MASK);
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
769
* @param attributes the attributes to assign to the new
771
* @return a new <code>Font</code> created with the specified
773
* @throws NullPointerException if <code>attributes</code> is null.
775
* @see java.awt.font.TextAttribute
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
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)) {
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);
797
return new Font(attributes);
800
Font font = (Font)attributes.get(TextAttribute.FONT);
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);
812
return new Font(attributes);
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}.
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)
843
public static Font createFont(int fontFormat, InputStream fontStream)
844
throws java.awt.FontFormatException, java.io.IOException {
846
if (fontFormat != Font.TRUETYPE_FONT &&
847
fontFormat != Font.TYPE1_FONT) {
848
throw new IllegalArgumentException ("font format not recognized");
851
// read the stream in a byte array
852
ByteArrayOutputStream baos = new ByteArrayOutputStream( fontStream.available() );
853
byte[] buffer = new byte[1024];
855
while( (count = fontStream.read( buffer, 0, buffer.length )) != -1 ) {
856
baos.write( buffer, 0, count );
858
byte[] fontData = baos.toByteArray();
860
// create a private Font Collection and add the font data
861
PrivateFontCollection pfc;
863
pfc = createPrivateFontCollection(fontData);
864
} catch( cli.System.IO.FileNotFoundException x ) {
865
FontFormatException ffe = new FontFormatException(x.getMessage());
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 );
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));
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 );
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
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.
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)
925
public static Font createFont(int fontFormat, File fontFile)
926
throws java.awt.FontFormatException, java.io.IOException {
928
fontFile = new File(fontFile.getPath());
930
if (fontFormat != Font.TRUETYPE_FONT &&
931
fontFormat != Font.TYPE1_FONT) {
932
throw new IllegalArgumentException ("font format not recognized");
934
SecurityManager sm = System.getSecurityManager();
936
FilePermission filePermission =
937
new FilePermission(fontFile.getPath(), "read");
938
sm.checkPermission(filePermission);
940
if (!fontFile.canRead()) {
941
throw new IOException("Can't read " + fontFile);
943
// create a private Font Collection and add the font data
944
PrivateFontCollection pfc = new PrivateFontCollection();
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 );
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 );
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>.
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.
971
* @return an {@link AffineTransform} object representing the
972
* transform attribute of this <code>Font</code> object.
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.
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.
989
AttributeValues values = getAttributeValues();
991
AffineTransform at = values.isNonDefault(ETRANSFORM)
992
? new AffineTransform(values.getTransform())
993
: new AffineTransform();
995
if (values.getSuperscript() != 0) {
996
// can't get ascent and descent here, recursive call to this fn,
998
// let users combine super- and sub-scripting
1000
int superscript = values.getSuperscript();
1004
boolean up = superscript > 0;
1005
int sign = up ? -1 : 1;
1006
int ss = up ? superscript : -superscript;
1008
while ((ss & 7) > n) {
1010
trans += sign * (ssinfo[newn] - ssinfo[n]);
1016
double scale = Math.pow(2./3., n);
1018
at.preConcatenate(AffineTransform.getTranslateInstance(0, trans));
1019
at.scale(scale, scale);
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.
1035
if (values.isNonDefault(EWIDTH)) {
1036
at.scale(values.getWidth(), 1f);
1042
return new AffineTransform();
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)
1052
// scale ratio is 2/3
1053
// trans = 1/2 of ascent * x
1054
// assume ascent is 3/4 of point size
1056
private static final float[] ssinfo = {
1068
* Returns the family name of this <code>Font</code>.
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.
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>.
1086
public String getFamily() {
1087
return getFamily_NoClientCode();
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
1093
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
1094
final String getFamily_NoClientCode() {
1095
return getFamily(Locale.getDefault());
1099
* Returns the family name of this <code>Font</code>, localized for
1100
* the specified locale.
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.
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.
1114
* @see java.util.Locale
1117
public String getFamily(Locale l) {
1119
throw new NullPointerException("null locale doesn't mean default");
1121
return getFont2D().getFamilyName(l);
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>.
1132
public String getPSName() {
1133
return getFont2D().getPostscriptName();
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>.
1146
public String getName() {
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>.
1161
public String getFontName() {
1162
return getFontName(Locale.getDefault());
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.
1174
* @see java.util.Locale
1176
public String getFontName(Locale l) {
1178
throw new NullPointerException("null locale doesn't mean default");
1180
return getFont2D().getFontName(l);
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>
1192
public int getStyle() {
1197
* Returns the point size of this <code>Font</code>, rounded to
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.
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
1214
* @see GraphicsConfiguration#getDefaultTransform
1215
* @see GraphicsConfiguration#getNormalizingTransform
1218
public int getSize() {
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.
1230
public float getSize2D() {
1235
* Indicates whether or not this <code>Font</code> object's style is
1237
* @return <code>true</code> if this <code>Font</code> has a
1239
* <code>false</code> otherwise.
1240
* @see java.awt.Font#getStyle
1243
public boolean isPlain() {
1248
* Indicates whether or not this <code>Font</code> object's style is
1250
* @return <code>true</code> if this <code>Font</code> object's
1252
* <code>false</code> otherwise.
1253
* @see java.awt.Font#getStyle
1256
public boolean isBold() {
1257
return (style & BOLD) != 0;
1261
* Indicates whether or not this <code>Font</code> object's style is
1263
* @return <code>true</code> if this <code>Font</code> object's
1265
* <code>false</code> otherwise.
1266
* @see java.awt.Font#getStyle
1269
public boolean isItalic() {
1270
return (style & ITALIC) != 0;
1274
* Indicates whether or not this <code>Font</code> object has a
1275
* transform that affects its size in addition to the Size
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
1283
public boolean isTransformed() {
1284
return nonIdentityTx;
1288
* Return true if this Font contains attributes that require extra
1289
* layout processing.
1290
* @return true if the font has layout attributes
1293
public boolean hasLayoutAttributes() {
1294
return hasLayoutAttributes;
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.
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.
1311
* @see #decode(String)
1313
public static Font getFont(String nm) {
1314
return getFont(nm, null);
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
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>
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:
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.
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.
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.
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.
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.
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
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>.
1390
public static Font decode(String str) {
1391
String fontName = str;
1392
String styleName = "";
1394
int fontStyle = Font.PLAIN;
1397
return new Font(DIALOG, fontStyle, fontSize);
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();
1407
if (sizeIndex > 0 && sizeIndex+1 < strlen) {
1410
Integer.valueOf(str.substring(sizeIndex+1)).intValue();
1411
if (fontSize <= 0) {
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;
1419
if (str.charAt(sizeIndex-1) == sepChar) {
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;
1437
/* this string isn't any of the expected styles, so
1438
* assume its part of the font name
1440
styleIndex = sizeIndex;
1441
if (str.charAt(styleIndex-1) == sepChar) {
1445
fontName = str.substring(0, styleIndex);
1448
int fontEnd = strlen;
1449
if (styleIndex > 0) {
1450
fontEnd = styleIndex;
1451
} else if (sizeIndex > 0) {
1452
fontEnd = sizeIndex;
1454
if (fontEnd > 0 && str.charAt(fontEnd-1) == sepChar) {
1457
fontName = str.substring(0, fontEnd);
1460
return new Font(fontName, fontStyle, fontSize);
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.
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)
1483
public static Font getFont(String nm, Font font) {
1486
str =System.getProperty(nm);
1487
} catch(SecurityException e) {
1492
return decode ( str );
1497
* Returns a hashcode for this <code>Font</code>.
1498
* @return a hashcode value for this <code>Font</code>.
1501
public int hashCode() {
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.
1510
if (nonIdentityTx &&
1511
values != null && values.getTransform() != null) {
1512
hash ^= values.getTransform().hashCode();
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.
1528
public boolean equals(Object obj) {
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)) {
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.
1549
if (values == null) {
1550
if (font.values == null) {
1553
return getAttributeValues().equals(font.values);
1556
return values.equals(font.getAttributeValues());
1560
catch (ClassCastException e) {
1567
* Converts this <code>Font</code> object to a <code>String</code>
1569
* @return a <code>String</code> representation of this
1570
* <code>Font</code> object.
1573
// NOTE: This method may be called by privileged threads.
1574
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
1575
public String toString() {
1579
strStyle = isItalic() ? "bolditalic" : "bold";
1581
strStyle = isItalic() ? "italic" : "plain";
1584
return getClass().getName() + "[family=" + getFamily() + ",name=" + name + ",style=" +
1585
strStyle + ",size=" + size + "]";
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.
1599
* The <code>Font</code> Serializable Data Form.
1603
private int fontSerializedDataVersion = 1;
1606
* Writes default serializable fields to a stream.
1608
* @param s the <code>ObjectOutputStream</code> to write
1609
* @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
1610
* @see #readObject(java.io.ObjectInputStream)
1612
private void writeObject(java.io.ObjectOutputStream s)
1613
throws java.lang.ClassNotFoundException,
1616
if (values != null) {
1617
synchronized(values) {
1619
fRequestedAttributes = values.toSerializableHashtable();
1620
s.defaultWriteObject();
1621
fRequestedAttributes = null;
1624
s.defaultWriteObject();
1629
* Reads the <code>ObjectInputStream</code>.
1630
* Unrecognized keys or values will be ignored.
1632
* @param s the <code>ObjectInputStream</code> to read
1634
* @see #writeObject(java.io.ObjectOutputStream)
1636
private void readObject(java.io.ObjectInputStream s)
1637
throws java.lang.ClassNotFoundException,
1640
s.defaultReadObject();
1641
if (pointSize == 0) {
1642
pointSize = (float)size;
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.
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
1660
values = getAttributeValues().merge(extras);
1661
this.nonIdentityTx = values.anyNonDefault(EXTRA_MASK);
1662
this.hasLayoutAttributes = values.anyNonDefault(LAYOUT_MASK);
1664
fRequestedAttributes = null; // don't need it any more
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>.
1675
public int getNumGlyphs() {
1676
return getFont2D().getNumGlyphs();
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>.
1685
public int getMissingGlyphCode() {
1686
return getFont2D().getMissingGlyphCode();
1690
* Returns the baseline appropriate for displaying this character.
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.
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
1705
public byte getBaselineFor(char c) {
1706
return getFont2D().getBaselineFor(c);
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>.
1715
public Map<TextAttribute,?> getAttributes(){
1716
return new AttributeMap(getAttributeValues());
1720
* Returns the keys of all the attributes supported by this
1721
* <code>Font</code>. These attributes can be used to derive other
1723
* @return an array containing the keys of all the attributes
1724
* supported by this <code>Font</code>.
1727
public Attribute[] getAvailableAttributes() {
1728
// FONT is not supported by Font
1730
Attribute attributes[] = {
1731
TextAttribute.FAMILY,
1732
TextAttribute.WEIGHT,
1733
TextAttribute.WIDTH,
1734
TextAttribute.POSTURE,
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,
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.
1766
public Font deriveFont(int style, float size){
1767
if (values == null) {
1768
return new Font(name, style, size, createdFont, font2DHandle);
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);
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
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);
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.
1803
public Font deriveFont(float size){
1804
if (values == null) {
1805
return new Font(name, style, size, createdFont, font2DHandle);
1807
AttributeValues newValues = getAttributeValues().clone();
1808
newValues.setSize(size);
1809
return new Font(newValues, null, -1, createdFont, font2DHandle);
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
1822
public Font deriveFont(AffineTransform trans){
1823
AttributeValues newValues = getAttributeValues().clone();
1824
applyTransform(trans, newValues);
1825
return new Font(newValues, null, -1, createdFont, font2DHandle);
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.
1835
public Font deriveFont(int style){
1836
if (values == null) {
1837
return new Font(name, style, size, createdFont, font2DHandle);
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);
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
1850
* @param attributes a map of attributes enabled for the new
1852
* @return a new <code>Font</code> object.
1855
public Font deriveFont(Map<? extends Attribute, ?> attributes) {
1856
if (attributes == null) {
1859
AttributeValues newValues = getAttributeValues().clone();
1860
newValues.merge(attributes, RECOGNIZED_MASK);
1862
return new Font(newValues, name, style, createdFont, font2DHandle);
1866
* Checks if this <code>Font</code> has a glyph for the specified
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.
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.
1880
public boolean canDisplay(char c){
1881
return getFont2D().canDisplay(c);
1885
* Checks if this <code>Font</code> has a glyph for the specified
1888
* @param codePoint the character (Unicode code point) for which a glyph
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
1894
* @see Character#isValidCodePoint(int)
1897
public boolean canDisplay(int codePoint) {
1898
if (!Character.isValidCodePoint(codePoint)) {
1899
throw new IllegalArgumentException("invalid code point: " +
1900
Integer.toHexString(codePoint));
1902
return getFont2D().canDisplay(codePoint);
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
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
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)) {
1930
if (!Character.isHighSurrogate(c)) {
1933
if (!font2d.canDisplay(str.codePointAt(i))) {
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>.
1960
public int canDisplayUpTo(char[] text, int start, int limit) {
1961
Font2D font2d = getFont2D();
1962
for (int i = start; i < limit; i++) {
1964
if (font2d.canDisplay(c)) {
1967
if (!Character.isHighSurrogate(c)) {
1970
if (!font2d.canDisplay(Character.codePointAt(text, i, limit))) {
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>.
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>.
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)) {
2002
if (!Character.isHighSurrogate(c)) {
2005
char c2 = iter.next();
2006
// c2 could be CharacterIterator.DONE which is not a low surrogate.
2007
if (!Character.isLowSurrogate(c2)) {
2010
if (!font2d.canDisplay(Character.toCodePoint(c, c2))) {
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>.
2025
public float getItalicAngle() {
2026
return getItalicAngle(null);
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.
2037
private float getItalicAngle(FontRenderContext frc) {
2040
aa = RenderingHints.VALUE_TEXT_ANTIALIAS_OFF;
2041
fm = RenderingHints.VALUE_FRACTIONALMETRICS_OFF;
2043
aa = frc.getAntiAliasingHint();
2044
fm = frc.getFractionalMetricsHint();
2046
return getFont2D().getItalicAngle(this, identityTx, aa, fm);
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.
2060
public boolean hasUniformLineMetrics() {
2061
return false; // REMIND always safe, but prevents caller optimize
2064
private transient SoftReference flmref;
2065
private FontLineMetrics defaultLineMetrics(FontRenderContext frc) {
2066
FontLineMetrics flm = null;
2068
|| (flm = (FontLineMetrics)flmref.get()) == null
2069
|| !flm.frc.equals(frc)) {
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
2076
float [] metrics = new float[8];
2077
getFont2D().getFontMetrics(this, identityTx,
2078
frc.getAntiAliasingHint(),
2079
frc.getFractionalMetricsHint(),
2081
float ascent = metrics[0];
2082
float descent = metrics[1];
2083
float leading = metrics[2];
2085
if (values != null && values.getSuperscript() != 0) {
2086
ssOffset = (float)getTransform().getTranslateY();
2088
descent += ssOffset;
2090
float height = ascent + descent + leading;
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 };
2096
float strikethroughOffset = metrics[4];
2097
float strikethroughThickness = metrics[5];
2099
float underlineOffset = metrics[6];
2100
float underlineThickness = metrics[7];
2102
float italicAngle = getItalicAngle(frc);
2104
if (isTransformed()) {
2105
AffineTransform ctx = values.getCharTransform(); // extract rotation
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;
2122
strikethroughOffset += ssOffset;
2123
underlineOffset += ssOffset;
2125
CoreMetrics cm = new CoreMetrics(ascent, descent, leading, height,
2126
baselineIndex, baselineOffsets,
2127
strikethroughOffset, strikethroughThickness,
2128
underlineOffset, underlineThickness,
2129
ssOffset, italicAngle);
2131
flm = new FontLineMetrics(0, cm, frc);
2132
flmref = new SoftReference(flm);
2135
return (FontLineMetrics)flm.clone();
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}.
2146
public LineMetrics getLineMetrics( String str, FontRenderContext frc) {
2147
FontLineMetrics flm = defaultLineMetrics(frc);
2148
flm.numchars = str.length();
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.
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;
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.
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;
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.
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;
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
2230
public Rectangle2D getStringBounds( String str, FontRenderContext frc) {
2231
char[] array = str.toCharArray();
2232
return getStringBounds(array, 0, array.length, frc);
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
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);
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
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
2297
public Rectangle2D getStringBounds(char [] chars,
2298
int beginIndex, int limit,
2299
FontRenderContext frc) {
2300
if (beginIndex < 0) {
2301
throw new IndexOutOfBoundsException("beginIndex: " + beginIndex);
2303
if (limit > chars.length) {
2304
throw new IndexOutOfBoundsException("limit: " + limit);
2306
if (beginIndex > limit) {
2307
throw new IndexOutOfBoundsException("range length: " +
2308
(limit - beginIndex));
2311
// this code should be in textlayout
2312
// quick check for simple text, assume GV ok to use if simple
2314
boolean simple = values == null ||
2315
(values.getKerning() == 0 && values.getLigatures() == 0 &&
2316
values.getBaselineTransform() == null);
2318
simple = ! FontUtilities.isComplexText(chars, beginIndex, limit);
2322
GlyphVector gv = new StandardGlyphVector(this, chars, beginIndex,
2323
limit - beginIndex, frc);
2324
return gv.getLogicalBounds();
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() +
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
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>
2364
public Rectangle2D getStringBounds(CharacterIterator ci,
2365
int beginIndex, int limit,
2366
FontRenderContext frc) {
2367
int start = ci.getBeginIndex();
2368
int end = ci.getEndIndex();
2370
if (beginIndex < start) {
2371
throw new IndexOutOfBoundsException("beginIndex: " + beginIndex);
2374
throw new IndexOutOfBoundsException("limit: " + limit);
2376
if (beginIndex > limit) {
2377
throw new IndexOutOfBoundsException("range length: " +
2378
(limit - beginIndex));
2381
char[] arr = new char[limit - beginIndex];
2383
ci.setIndex(beginIndex);
2384
for(int idx = 0; idx < arr.length; idx++) {
2385
arr[idx] = ci.current();
2389
return getStringBounds(arr,0,arr.length,frc);
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.
2401
public Rectangle2D getMaxCharBounds(FontRenderContext frc) {
2402
float [] metrics = new float[4];
2404
getFont2D().getFontMetrics(this, frc, metrics);
2406
return new Rectangle2D.Float(0, -metrics[0],
2408
metrics[0] + metrics[1] + metrics[2]);
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>.
2425
public GlyphVector createGlyphVector(FontRenderContext frc, String str)
2427
return (GlyphVector)new StandardGlyphVector(this, str, frc);
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>.
2444
public GlyphVector createGlyphVector(FontRenderContext frc, char[] chars)
2446
return (GlyphVector)new StandardGlyphVector(this, chars, frc);
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>.
2463
public GlyphVector createGlyphVector( FontRenderContext frc,
2464
CharacterIterator ci)
2466
return (GlyphVector)new StandardGlyphVector(this, ci, frc);
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>.
2483
public GlyphVector createGlyphVector( FontRenderContext frc,
2486
return (GlyphVector)new StandardGlyphVector(this, glyphCodes, frc);
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.
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)
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
2512
* All other values for the flags parameter are reserved.
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
2522
* @throws ArrayIndexOutOfBoundsException if start or limit is
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
2531
public GlyphVector layoutGlyphVector(FontRenderContext frc,
2537
return new StandardGlyphVector(this,text,start, limit-start, frc);
2541
* A flag to layoutGlyphVector indicating that text is left-to-right as
2542
* determined by Bidi analysis.
2544
public static final int LAYOUT_LEFT_TO_RIGHT = 0;
2547
* A flag to layoutGlyphVector indicating that text is right-to-left as
2548
* determined by Bidi analysis.
2550
public static final int LAYOUT_RIGHT_TO_LEFT = 1;
2553
* A flag to layoutGlyphVector indicating that text in the char array
2554
* before the indicated start should not be examined.
2556
public static final int LAYOUT_NO_START_CONTEXT = 2;
2559
* A flag to layoutGlyphVector indicating that text in the char array
2560
* after the indicated limit should not be examined.
2562
public static final int LAYOUT_NO_LIMIT_CONTEXT = 4;
2565
private static void applyTransform(AffineTransform trans, AttributeValues values) {
2566
if (trans == null) {
2567
throw new IllegalArgumentException("transform must not be null");
2569
values.setTransform(trans);
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);