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