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