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