0001 /*
0002 * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025
0026 package java.awt;
0027
0028 import java.awt.font.FontRenderContext;
0029 import java.awt.font.GlyphVector;
0030 import java.awt.font.LineMetrics;
0031 import java.awt.font.TextAttribute;
0032 import java.awt.font.TextLayout;
0033 import java.awt.font.TransformAttribute;
0034 import java.awt.geom.AffineTransform;
0035 import java.awt.geom.Point2D;
0036 import java.awt.geom.Rectangle2D;
0037 import java.awt.peer.FontPeer;
0038 import java.io.*;
0039 import java.lang.ref.SoftReference;
0040 import java.text.AttributedCharacterIterator.Attribute;
0041 import java.text.CharacterIterator;
0042 import java.text.StringCharacterIterator;
0043 import java.util.HashMap;
0044 import java.util.Hashtable;
0045 import java.util.Locale;
0046 import java.util.Map;
0047 import sun.font.StandardGlyphVector;
0048 import sun.java2d.FontSupport;
0049
0050 import sun.font.AttributeMap;
0051 import sun.font.AttributeValues;
0052 import sun.font.EAttribute;
0053 import sun.font.CompositeFont;
0054 import sun.font.Font2D;
0055 import sun.font.Font2DHandle;
0056 import sun.font.FontManager;
0057 import sun.font.GlyphLayout;
0058 import sun.font.FontLineMetrics;
0059 import sun.font.CoreMetrics;
0060
0061 import static sun.font.EAttribute.*;
0062
0063 /**
0064 * The <code>Font</code> class represents fonts, which are used to
0065 * render text in a visible way.
0066 * A font provides the information needed to map sequences of
0067 * <em>characters</em> to sequences of <em>glyphs</em>
0068 * and to render sequences of glyphs on <code>Graphics</code> and
0069 * <code>Component</code> objects.
0070 *
0071 * <h4>Characters and Glyphs</h4>
0072 *
0073 * A <em>character</em> is a symbol that represents an item such as a letter,
0074 * a digit, or punctuation in an abstract way. For example, <code>'g'</code>,
0075 * <font size=-1>LATIN SMALL LETTER G</font>, is a character.
0076 * <p>
0077 * A <em>glyph</em> is a shape used to render a character or a sequence of
0078 * characters. In simple writing systems, such as Latin, typically one glyph
0079 * represents one character. In general, however, characters and glyphs do not
0080 * have one-to-one correspondence. For example, the character 'á'
0081 * <font size=-1>LATIN SMALL LETTER A WITH ACUTE</font>, can be represented by
0082 * two glyphs: one for 'a' and one for '´'. On the other hand, the
0083 * two-character string "fi" can be represented by a single glyph, an
0084 * "fi" ligature. In complex writing systems, such as Arabic or the South
0085 * and South-East Asian writing systems, the relationship between characters
0086 * and glyphs can be more complicated and involve context-dependent selection
0087 * of glyphs as well as glyph reordering.
0088 *
0089 * A font encapsulates the collection of glyphs needed to render a selected set
0090 * of characters as well as the tables needed to map sequences of characters to
0091 * corresponding sequences of glyphs.
0092 *
0093 * <h4>Physical and Logical Fonts</h4>
0094 *
0095 * The Java Platform distinguishes between two kinds of fonts:
0096 * <em>physical</em> fonts and <em>logical</em> fonts.
0097 * <p>
0098 * <em>Physical</em> fonts are the actual font libraries containing glyph data
0099 * and tables to map from character sequences to glyph sequences, using a font
0100 * technology such as TrueType or PostScript Type 1.
0101 * All implementations of the Java Platform must support TrueType fonts;
0102 * support for other font technologies is implementation dependent.
0103 * Physical fonts may use names such as Helvetica, Palatino, HonMincho, or
0104 * any number of other font names.
0105 * Typically, each physical font supports only a limited set of writing
0106 * systems, for example, only Latin characters or only Japanese and Basic
0107 * Latin.
0108 * The set of available physical fonts varies between configurations.
0109 * Applications that require specific fonts can bundle them and instantiate
0110 * them using the {@link #createFont createFont} method.
0111 * <p>
0112 * <em>Logical</em> fonts are the five font families defined by the Java
0113 * platform which must be supported by any Java runtime environment:
0114 * Serif, SansSerif, Monospaced, Dialog, and DialogInput.
0115 * These logical fonts are not actual font libraries. Instead, the logical
0116 * font names are mapped to physical fonts by the Java runtime environment.
0117 * The mapping is implementation and usually locale dependent, so the look
0118 * and the metrics provided by them vary.
0119 * Typically, each logical font name maps to several physical fonts in order to
0120 * cover a large range of characters.
0121 * <p>
0122 * Peered AWT components, such as {@link Label Label} and
0123 * {@link TextField TextField}, can only use logical fonts.
0124 * <p>
0125 * For a discussion of the relative advantages and disadvantages of using
0126 * physical or logical fonts, see the
0127 * <a href="http://java.sun.com/j2se/corejava/intl/reference/faqs/index.html#desktop-rendering">Internationalization FAQ</a>
0128 * document.
0129 *
0130 * <h4>Font Faces and Names</h4>
0131 *
0132 * A <code>Font</code>
0133 * can have many faces, such as heavy, medium, oblique, gothic and
0134 * regular. All of these faces have similar typographic design.
0135 * <p>
0136 * There are three different names that you can get from a
0137 * <code>Font</code> object. The <em>logical font name</em> is simply the
0138 * name that was used to construct the font.
0139 * The <em>font face name</em>, or just <em>font name</em> for
0140 * short, is the name of a particular font face, like Helvetica Bold. The
0141 * <em>family name</em> is the name of the font family that determines the
0142 * typographic design across several faces, like Helvetica.
0143 * <p>
0144 * The <code>Font</code> class represents an instance of a font face from
0145 * a collection of font faces that are present in the system resources
0146 * of the host system. As examples, Arial Bold and Courier Bold Italic
0147 * are font faces. There can be several <code>Font</code> objects
0148 * associated with a font face, each differing in size, style, transform
0149 * and font features.
0150 * <p>
0151 * The {@link GraphicsEnvironment#getAllFonts() getAllFonts} method
0152 * of the <code>GraphicsEnvironment</code> class returns an
0153 * array of all font faces available in the system. These font faces are
0154 * returned as <code>Font</code> objects with a size of 1, identity
0155 * transform and default font features. These
0156 * base fonts can then be used to derive new <code>Font</code> objects
0157 * with varying sizes, styles, transforms and font features via the
0158 * <code>deriveFont</code> methods in this class.
0159 *
0160 * <h4>Font and TextAttribute</h4>
0161 *
0162 * <p><code>Font</code> supports most
0163 * <code>TextAttribute</code>s. This makes some operations, such as
0164 * rendering underlined text, convenient since it is not
0165 * necessary to explicitly construct a <code>TextLayout</code> object.
0166 * Attributes can be set on a Font by constructing or deriving it
0167 * using a <code>Map</code> of <code>TextAttribute</code> values.
0168 *
0169 * <p>The values of some <code>TextAttributes</code> are not
0170 * serializable, and therefore attempting to serialize an instance of
0171 * <code>Font</code> that has such values will not serialize them.
0172 * This means a Font deserialized from such a stream will not compare
0173 * equal to the original Font that contained the non-serializable
0174 * attributes. This should very rarely pose a problem
0175 * since these attributes are typically used only in special
0176 * circumstances and are unlikely to be serialized.
0177 *
0178 * <ul>
0179 * <li><code>FOREGROUND</code> and <code>BACKGROUND</code> use
0180 * <code>Paint</code> values. The subclass <code>Color</code> is
0181 * serializable, while <code>GradientPaint</code> and
0182 * <code>TexturePaint</code> are not.</li>
0183 * <li><code>CHAR_REPLACEMENT</code> uses
0184 * <code>GraphicAttribute</code> values. The subclasses
0185 * <code>ShapeGraphicAttribute</code> and
0186 * <code>ImageGraphicAttribute</code> are not serializable.</li>
0187 * <li><code>INPUT_METHOD_HIGHLIGHT</code> uses
0188 * <code>InputMethodHighlight</code> values, which are
0189 * not serializable. See {@link java.awt.im.InputMethodHighlight}.</li>
0190 * </ul>
0191 *
0192 * Clients who create custom subclasses of <code>Paint</code> and
0193 * <code>GraphicAttribute</code> can make them serializable and
0194 * avoid this problem. Clients who use input method highlights can
0195 * convert these to the platform-specific attributes for that
0196 * highlight on the current platform and set them on the Font as
0197 * a workaround.</p>
0198 *
0199 * <p>The <code>Map</code>-based constructor and
0200 * <code>deriveFont</code> APIs ignore the FONT attribute, and it is
0201 * not retained by the Font; the static {@link #getFont} method should
0202 * be used if the FONT attribute might be present. See {@link
0203 * java.awt.font.TextAttribute#FONT} for more information.</p>
0204 *
0205 * <p>Several attributes will cause additional rendering overhead
0206 * and potentially invoke layout. If a <code>Font</code> has such
0207 * attributes, the <code>{@link #hasLayoutAttributes()}</code> method
0208 * will return true.</p>
0209 *
0210 * <p>Note: Font rotations can cause text baselines to be rotated. In
0211 * order to account for this (rare) possibility, font APIs are
0212 * specified to return metrics and take parameters 'in
0213 * baseline-relative coordinates'. This maps the 'x' coordinate to
0214 * the advance along the baseline, (positive x is forward along the
0215 * baseline), and the 'y' coordinate to a distance along the
0216 * perpendicular to the baseline at 'x' (positive y is 90 degrees
0217 * clockwise from the baseline vector). APIs for which this is
0218 * especially important are called out as having 'baseline-relative
0219 * coordinates.'
0220 */
0221 public class Font implements java.io.Serializable {
0222 static {
0223 /* ensure that the necessary native libraries are loaded */
0224 Toolkit.loadLibraries();
0225 initIDs();
0226 }
0227
0228 /**
0229 * This is now only used during serialization. Typically
0230 * it is null.
0231 *
0232 * @serial
0233 * @see #getAttributes()
0234 */
0235 private Hashtable fRequestedAttributes;
0236
0237 /*
0238 * Constants to be used for logical font family names.
0239 */
0240
0241 /**
0242 * A String constant for the canonical family name of the
0243 * logical font "Dialog". It is useful in Font construction
0244 * to provide compile-time verification of the name.
0245 * @since 1.6
0246 */
0247 public static final String DIALOG = "Dialog";
0248
0249 /**
0250 * A String constant for the canonical family name of the
0251 * logical font "DialogInput". It is useful in Font construction
0252 * to provide compile-time verification of the name.
0253 * @since 1.6
0254 */
0255 public static final String DIALOG_INPUT = "DialogInput";
0256
0257 /**
0258 * A String constant for the canonical family name of the
0259 * logical font "SansSerif". It is useful in Font construction
0260 * to provide compile-time verification of the name.
0261 * @since 1.6
0262 */
0263 public static final String SANS_SERIF = "SansSerif";
0264
0265 /**
0266 * A String constant for the canonical family name of the
0267 * logical font "Serif". It is useful in Font construction
0268 * to provide compile-time verification of the name.
0269 * @since 1.6
0270 */
0271 public static final String SERIF = "Serif";
0272
0273 /**
0274 * A String constant for the canonical family name of the
0275 * logical font "Monospaced". It is useful in Font construction
0276 * to provide compile-time verification of the name.
0277 * @since 1.6
0278 */
0279 public static final String MONOSPACED = "Monospaced";
0280
0281 /*
0282 * Constants to be used for styles. Can be combined to mix
0283 * styles.
0284 */
0285
0286 /**
0287 * The plain style constant.
0288 */
0289 public static final int PLAIN = 0;
0290
0291 /**
0292 * The bold style constant. This can be combined with the other style
0293 * constants (except PLAIN) for mixed styles.
0294 */
0295 public static final int BOLD = 1;
0296
0297 /**
0298 * The italicized style constant. This can be combined with the other
0299 * style constants (except PLAIN) for mixed styles.
0300 */
0301 public static final int ITALIC = 2;
0302
0303 /**
0304 * The baseline used in most Roman scripts when laying out text.
0305 */
0306 public static final int ROMAN_BASELINE = 0;
0307
0308 /**
0309 * The baseline used in ideographic scripts like Chinese, Japanese,
0310 * and Korean when laying out text.
0311 */
0312 public static final int CENTER_BASELINE = 1;
0313
0314 /**
0315 * The baseline used in Devanigiri and similar scripts when laying
0316 * out text.
0317 */
0318 public static final int HANGING_BASELINE = 2;
0319
0320 /**
0321 * Identify a font resource of type TRUETYPE.
0322 * Used to specify a TrueType font resource to the
0323 * {@link #createFont} method.
0324 * @since 1.3
0325 */
0326
0327 public static final int TRUETYPE_FONT = 0;
0328
0329 /**
0330 * Identify a font resource of type TYPE1.
0331 * Used to specify a Type1 font resource to the
0332 * {@link #createFont} method.
0333 * @since 1.5
0334 */
0335 public static final int TYPE1_FONT = 1;
0336
0337 /**
0338 * The logical name of this <code>Font</code>, as passed to the
0339 * constructor.
0340 * @since JDK1.0
0341 *
0342 * @serial
0343 * @see #getName
0344 */
0345 protected String name;
0346
0347 /**
0348 * The style of this <code>Font</code>, as passed to the constructor.
0349 * This style can be PLAIN, BOLD, ITALIC, or BOLD+ITALIC.
0350 * @since JDK1.0
0351 *
0352 * @serial
0353 * @see #getStyle()
0354 */
0355 protected int style;
0356
0357 /**
0358 * The point size of this <code>Font</code>, rounded to integer.
0359 * @since JDK1.0
0360 *
0361 * @serial
0362 * @see #getSize()
0363 */
0364 protected int size;
0365
0366 /**
0367 * The point size of this <code>Font</code> in <code>float</code>.
0368 *
0369 * @serial
0370 * @see #getSize()
0371 * @see #getSize2D()
0372 */
0373 protected float pointSize;
0374
0375 /**
0376 * The platform specific font information.
0377 */
0378 private transient FontPeer peer;
0379 private transient long pData; // native JDK1.1 font pointer
0380 private transient Font2DHandle font2DHandle;
0381
0382 private transient AttributeValues values;
0383 private transient boolean hasLayoutAttributes;
0384
0385 /*
0386 * If the origin of a Font is a created font then this attribute
0387 * must be set on all derived fonts too.
0388 */
0389 private transient boolean createdFont = false;
0390
0391 /*
0392 * This is true if the font transform is not identity. It
0393 * is used to avoid unnecessary instantiation of an AffineTransform.
0394 */
0395 private transient boolean nonIdentityTx;
0396
0397 /*
0398 * A cached value used when a transform is required for internal
0399 * use. This must not be exposed to callers since AffineTransform
0400 * is mutable.
0401 */
0402 private static final AffineTransform identityTx = new AffineTransform();
0403
0404 /*
0405 * JDK 1.1 serialVersionUID
0406 */
0407 private static final long serialVersionUID = -4206021311591459213L;
0408
0409 /**
0410 * Gets the peer of this <code>Font</code>.
0411 * @return the peer of the <code>Font</code>.
0412 * @since JDK1.1
0413 * @deprecated Font rendering is now platform independent.
0414 */
0415 @Deprecated
0416 public FontPeer getPeer() {
0417 return getPeer_NoClientCode();
0418 }
0419
0420 // NOTE: This method is called by privileged threads.
0421 // We implement this functionality in a package-private method
0422 // to insure that it cannot be overridden by client subclasses.
0423 // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
0424 final FontPeer getPeer_NoClientCode() {
0425 if (peer == null) {
0426 Toolkit tk = Toolkit.getDefaultToolkit();
0427 this .peer = tk.getFontPeer(name, style);
0428 }
0429 return peer;
0430 }
0431
0432 /**
0433 * Return the AttributeValues object associated with this
0434 * font. Most of the time, the internal object is null.
0435 * If required, it will be created from the 'standard'
0436 * state on the font. Only non-default values will be
0437 * set in the AttributeValues object.
0438 *
0439 * <p>Since the AttributeValues object is mutable, and it
0440 * is cached in the font, care must be taken to ensure that
0441 * it is not mutated.
0442 */
0443 private AttributeValues getAttributeValues() {
0444 if (values == null) {
0445 values = new AttributeValues();
0446 values.setFamily(name);
0447 values.setSize(pointSize); // expects the float value.
0448
0449 if ((style & BOLD) != 0) {
0450 values.setWeight(2); // WEIGHT_BOLD
0451 }
0452
0453 if ((style & ITALIC) != 0) {
0454 values.setPosture(.2f); // POSTURE_OBLIQUE
0455 }
0456 values.defineAll(PRIMARY_MASK); // for streaming compatibility
0457 }
0458
0459 return values;
0460 }
0461
0462 private Font2D getFont2D() {
0463 if (FontManager.usingPerAppContextComposites
0464 && font2DHandle != null
0465 && font2DHandle.font2D instanceof CompositeFont
0466 && ((CompositeFont) (font2DHandle.font2D))
0467 .isStdComposite()) {
0468 return FontManager.findFont2D(name, style,
0469 FontManager.LOGICAL_FALLBACK);
0470 } else if (font2DHandle == null) {
0471 font2DHandle = FontManager.findFont2D(name, style,
0472 FontManager.LOGICAL_FALLBACK).handle;
0473 }
0474 /* Do not cache the de-referenced font2D. It must be explicitly
0475 * de-referenced to pick up a valid font in the event that the
0476 * original one is marked invalid
0477 */
0478 return font2DHandle.font2D;
0479 }
0480
0481 /**
0482 * Creates a new <code>Font</code> from the specified name, style and
0483 * point size.
0484 * <p>
0485 * The font name can be a font face name or a font family name.
0486 * It is used together with the style to find an appropriate font face.
0487 * When a font family name is specified, the style argument is used to
0488 * select the most appropriate face from the family. When a font face
0489 * name is specified, the face's style and the style argument are
0490 * merged to locate the best matching font from the same family.
0491 * For example if face name "Arial Bold" is specified with style
0492 * <code>Font.ITALIC</code>, the font system looks for a face in the
0493 * "Arial" family that is bold and italic, and may associate the font
0494 * instance with the physical font face "Arial Bold Italic".
0495 * The style argument is merged with the specified face's style, not
0496 * added or subtracted.
0497 * This means, specifying a bold face and a bold style does not
0498 * double-embolden the font, and specifying a bold face and a plain
0499 * style does not lighten the font.
0500 * <p>
0501 * If no face for the requested style can be found, the font system
0502 * may apply algorithmic styling to achieve the desired style.
0503 * For example, if <code>ITALIC</code> is requested, but no italic
0504 * face is available, glyphs from the plain face may be algorithmically
0505 * obliqued (slanted).
0506 * <p>
0507 * Font name lookup is case insensitive, using the case folding
0508 * rules of the US locale.
0509 * <p>
0510 * If the <code>name</code> parameter represents something other than a
0511 * logical font, i.e. is interpreted as a physical font face or family, and
0512 * this cannot be mapped by the implementation to a physical font or a
0513 * compatible alternative, then the font system will map the Font
0514 * instance to "Dialog", such that for example, the family as reported
0515 * by {@link #getFamily() getFamily} will be "Dialog".
0516 * <p>
0517 *
0518 * @param name the font name. This can be a font face name or a font
0519 * family name, and may represent either a logical font or a physical
0520 * font found in this {@code GraphicsEnvironment}.
0521 * The family names for logical fonts are: Dialog, DialogInput,
0522 * Monospaced, Serif, or SansSerif. Pre-defined String constants exist
0523 * for all of these names, for example, {@code DIALOG}. If {@code name} is
0524 * {@code null}, the <em>logical font name</em> of the new
0525 * {@code Font} as returned by {@code getName()} is set to
0526 * the name "Default".
0527 * @param style the style constant for the {@code Font}
0528 * The style argument is an integer bitmask that may
0529 * be {@code PLAIN}, or a bitwise union of {@code BOLD} and/or
0530 * {@code ITALIC} (for example, {@code ITALIC} or {@code BOLD|ITALIC}).
0531 * If the style argument does not conform to one of the expected
0532 * integer bitmasks then the style is set to {@code PLAIN}.
0533 * @param size the point size of the {@code Font}
0534 * @see GraphicsEnvironment#getAllFonts
0535 * @see GraphicsEnvironment#getAvailableFontFamilyNames
0536 * @since JDK1.0
0537 */
0538 public Font(String name, int style, int size) {
0539 this .name = (name != null) ? name : "Default";
0540 this .style = (style & ~0x03) == 0 ? style : 0;
0541 this .size = size;
0542 this .pointSize = size;
0543 }
0544
0545 private Font(String name, int style, float sizePts) {
0546 this .name = (name != null) ? name : "Default";
0547 this .style = (style & ~0x03) == 0 ? style : 0;
0548 this .size = (int) (sizePts + 0.5);
0549 this .pointSize = sizePts;
0550 }
0551
0552 /* This constructor is used by deriveFont when attributes is null */
0553 private Font(String name, int style, float sizePts,
0554 boolean created, Font2DHandle handle) {
0555 this (name, style, sizePts);
0556 this .createdFont = created;
0557 /* Fonts created from a stream will use the same font2D instance
0558 * as the parent.
0559 * One exception is that if the derived font is requested to be
0560 * in a different style, then also check if its a CompositeFont
0561 * and if so build a new CompositeFont from components of that style.
0562 * CompositeFonts can only be marked as "created" if they are used
0563 * to add fall backs to a physical font. And non-composites are
0564 * always from "Font.createFont()" and shouldn't get this treatment.
0565 */
0566 if (created) {
0567 if (handle.font2D instanceof CompositeFont
0568 && handle.font2D.getStyle() != style) {
0569 this .font2DHandle = FontManager.getNewComposite(null,
0570 style, handle);
0571 } else {
0572 this .font2DHandle = handle;
0573 }
0574 }
0575 }
0576
0577 /* used to implement Font.createFont */
0578 private Font(File fontFile, int fontFormat, boolean isCopy)
0579 throws FontFormatException {
0580 this .createdFont = true;
0581 /* Font2D instances created by this method track their font file
0582 * so that when the Font2D is GC'd it can also remove the file.
0583 */
0584 this .font2DHandle = FontManager.createFont2D(fontFile,
0585 fontFormat, isCopy).handle;
0586 this .name = this .font2DHandle.font2D.getFontName(Locale
0587 .getDefault());
0588 this .style = Font.PLAIN;
0589 this .size = 1;
0590 this .pointSize = 1f;
0591 }
0592
0593 /* This constructor is used when one font is derived from another.
0594 * Fonts created from a stream will use the same font2D instance as the
0595 * parent. They can be distinguished because the "created" argument
0596 * will be "true". Since there is no way to recreate these fonts they
0597 * need to have the handle to the underlying font2D passed in.
0598 * "created" is also true when a special composite is referenced by the
0599 * handle for essentially the same reasons.
0600 * But when deriving a font in these cases two particular attributes
0601 * need special attention: family/face and style.
0602 * The "composites" in these cases need to be recreated with optimal
0603 * fonts for the new values of family and style.
0604 * For fonts created with createFont() these are treated differently.
0605 * JDK can often synthesise a different style (bold from plain
0606 * for example). For fonts created with "createFont" this is a reasonable
0607 * solution but its also possible (although rare) to derive a font with a
0608 * different family attribute. In this case JDK needs
0609 * to break the tie with the original Font2D and find a new Font.
0610 * The oldName and oldStyle are supplied so they can be compared with
0611 * what the Font2D and the values. To speed things along :
0612 * oldName == null will be interpreted as the name is unchanged.
0613 * oldStyle = -1 will be interpreted as the style is unchanged.
0614 * In these cases there is no need to interrogate "values".
0615 */
0616 private Font(AttributeValues values, String oldName, int oldStyle,
0617 boolean created, Font2DHandle handle) {
0618
0619 this .createdFont = created;
0620 if (created) {
0621 this .font2DHandle = handle;
0622
0623 String newName = null;
0624 if (oldName != null) {
0625 newName = values.getFamily();
0626 if (oldName.equals(newName))
0627 newName = null;
0628 }
0629 int newStyle = 0;
0630 if (oldStyle == -1) {
0631 newStyle = -1;
0632 } else {
0633 if (values.getWeight() >= 2f)
0634 newStyle = BOLD;
0635 if (values.getPosture() >= .2f)
0636 newStyle |= ITALIC;
0637 if (oldStyle == newStyle)
0638 newStyle = -1;
0639 }
0640 if (handle.font2D instanceof CompositeFont) {
0641 if (newStyle != -1 || newName != null) {
0642 this .font2DHandle = FontManager.getNewComposite(
0643 newName, newStyle, handle);
0644 }
0645 } else if (newName != null) {
0646 this .createdFont = false;
0647 this .font2DHandle = null;
0648 }
0649 }
0650 initFromValues(values);
0651 }
0652
0653 /**
0654 * Creates a new <code>Font</code> with the specified attributes.
0655 * Only keys defined in {@link java.awt.font.TextAttribute TextAttribute}
0656 * are recognized. In addition the FONT attribute is
0657 * not recognized by this constructor
0658 * (see {@link #getAvailableAttributes}). Only attributes that have
0659 * values of valid types will affect the new <code>Font</code>.
0660 * <p>
0661 * If <code>attributes</code> is <code>null</code>, a new
0662 * <code>Font</code> is initialized with default values.
0663 * @see java.awt.font.TextAttribute
0664 * @param attributes the attributes to assign to the new
0665 * <code>Font</code>, or <code>null</code>
0666 */
0667 public Font(Map<? extends Attribute, ?> attributes) {
0668 initFromValues(AttributeValues.fromMap(attributes,
0669 RECOGNIZED_MASK));
0670 }
0671
0672 /**
0673 * Creates a new <code>Font</code> from the specified <code>font</code>.
0674 * This constructor is intended for use by subclasses.
0675 * @param font from which to create this <code>Font</code>.
0676 * @throws NullPointerException if <code>font</code> is null
0677 * @since 1.6
0678 */
0679 protected Font(Font font) {
0680 if (font.values != null) {
0681 initFromValues(font.getAttributeValues().clone());
0682 } else {
0683 this .name = font.name;
0684 this .style = font.style;
0685 this .size = font.size;
0686 this .pointSize = font.pointSize;
0687 }
0688 this .font2DHandle = font.font2DHandle;
0689 this .createdFont = font.createdFont;
0690 }
0691
0692 /**
0693 * Font recognizes all attributes except FONT.
0694 */
0695 private static final int RECOGNIZED_MASK = AttributeValues.MASK_ALL
0696 & ~AttributeValues.getMask(EFONT);
0697
0698 /**
0699 * These attributes are considered primary by the FONT attribute.
0700 */
0701 private static final int PRIMARY_MASK = AttributeValues.getMask(
0702 EFAMILY, EWEIGHT, EWIDTH, EPOSTURE, ESIZE, ETRANSFORM,
0703 ESUPERSCRIPT, ETRACKING);
0704
0705 /**
0706 * These attributes are considered secondary by the FONT attribute.
0707 */
0708 private static final int SECONDARY_MASK = RECOGNIZED_MASK
0709 & ~PRIMARY_MASK;
0710
0711 /**
0712 * These attributes are handled by layout.
0713 */
0714 private static final int LAYOUT_MASK = AttributeValues.getMask(
0715 ECHAR_REPLACEMENT, EFOREGROUND, EBACKGROUND, EUNDERLINE,
0716 ESTRIKETHROUGH, ERUN_DIRECTION, EBIDI_EMBEDDING,
0717 EJUSTIFICATION, EINPUT_METHOD_HIGHLIGHT,
0718 EINPUT_METHOD_UNDERLINE, ESWAP_COLORS, ENUMERIC_SHAPING,
0719 EKERNING, ELIGATURES, ETRACKING);
0720
0721 private static final int EXTRA_MASK = AttributeValues.getMask(
0722 ETRANSFORM, ESUPERSCRIPT, EWIDTH);
0723
0724 /**
0725 * Initialize the standard Font fields from the values object.
0726 */
0727 private void initFromValues(AttributeValues values) {
0728 this .values = values;
0729 values.defineAll(PRIMARY_MASK); // for 1.5 streaming compatibility
0730
0731 this .name = values.getFamily();
0732 this .pointSize = values.getSize();
0733 this .size = (int) (values.getSize() + 0.5);
0734 if (values.getWeight() >= 2f)
0735 this .style |= BOLD; // not == 2f
0736 if (values.getPosture() >= .2f)
0737 this .style |= ITALIC; // not == .2f
0738
0739 this .nonIdentityTx = values.anyNonDefault(EXTRA_MASK);
0740 this .hasLayoutAttributes = values.anyNonDefault(LAYOUT_MASK);
0741 }
0742
0743 /**
0744 * Returns a <code>Font</code> appropriate to the attributes.
0745 * If <code>attributes</code>contains a <code>FONT</code> attribute
0746 * with a valid <code>Font</code> as its value, it will be
0747 * merged with any remaining attributes. See
0748 * {@link java.awt.font.TextAttribute#FONT} for more
0749 * information.
0750 *
0751 * @param attributes the attributes to assign to the new
0752 * <code>Font</code>
0753 * @return a new <code>Font</code> created with the specified
0754 * attributes
0755 * @throws NullPointerException if <code>attributes</code> is null.
0756 * @since 1.2
0757 * @see java.awt.font.TextAttribute
0758 */
0759 public static Font getFont(Map<? extends Attribute, ?> attributes) {
0760 // optimize for two cases:
0761 // 1) FONT attribute, and nothing else
0762 // 2) attributes, but no FONT
0763
0764 // avoid turning the attributemap into a regular map for no reason
0765 if (attributes instanceof AttributeMap
0766 && ((AttributeMap) attributes).getValues() != null) {
0767 AttributeValues values = ((AttributeMap) attributes)
0768 .getValues();
0769 if (values.isNonDefault(EFONT)) {
0770 Font font = values.getFont();
0771 if (!values.anyDefined(SECONDARY_MASK)) {
0772 return font;
0773 }
0774 // merge
0775 values = font.getAttributeValues().clone();
0776 values.merge(attributes, SECONDARY_MASK);
0777 return new Font(values, font.name, font.style,
0778 font.createdFont, font.font2DHandle);
0779 }
0780 return new Font(attributes);
0781 }
0782
0783 Font font = (Font) attributes.get(TextAttribute.FONT);
0784 if (font != null) {
0785 if (attributes.size() > 1) { // oh well, check for anything else
0786 AttributeValues values = font.getAttributeValues()
0787 .clone();
0788 values.merge(attributes, SECONDARY_MASK);
0789 return new Font(values, font.name, font.style,
0790 font.createdFont, font.font2DHandle);
0791 }
0792
0793 return font;
0794 }
0795
0796 return new Font(attributes);
0797 }
0798
0799 /**
0800 * Returns a new <code>Font</code> using the specified font type
0801 * and input data. The new <code>Font</code> is
0802 * created with a point size of 1 and style {@link #PLAIN PLAIN}.
0803 * This base font can then be used with the <code>deriveFont</code>
0804 * methods in this class to derive new <code>Font</code> objects with
0805 * varying sizes, styles, transforms and font features. This
0806 * method does not close the {@link InputStream}.
0807 * <p>
0808 * To make the <code>Font</code> available to Font constructors the
0809 * returned <code>Font</code> must be registered in the
0810 * <code>GraphicsEnviroment</code> by calling
0811 * {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}.
0812 * @param fontFormat the type of the <code>Font</code>, which is
0813 * {@link #TRUETYPE_FONT TRUETYPE_FONT} if a TrueType resource is specified.
0814 * or {@link #TYPE1_FONT TYPE1_FONT} if a Type 1 resource is specified.
0815 * @param fontStream an <code>InputStream</code> object representing the
0816 * input data for the font.
0817 * @return a new <code>Font</code> created with the specified font type.
0818 * @throws IllegalArgumentException if <code>fontFormat</code> is not
0819 * <code>TRUETYPE_FONT</code>or<code>TYPE1_FONT</code>.
0820 * @throws FontFormatException if the <code>fontStream</code> data does
0821 * not contain the required font tables for the specified format.
0822 * @throws IOException if the <code>fontStream</code>
0823 * cannot be completely read.
0824 * @see GraphicsEnvironment#registerFont(Font)
0825 * @since 1.3
0826 */
0827 public static Font createFont(int fontFormat, InputStream fontStream)
0828 throws java.awt.FontFormatException, java.io.IOException {
0829
0830 if (fontFormat != Font.TRUETYPE_FONT
0831 && fontFormat != Font.TYPE1_FONT) {
0832 throw new IllegalArgumentException(
0833 "font format not recognized");
0834 }
0835 final InputStream fStream = fontStream;
0836 Object ret = java.security.AccessController
0837 .doPrivileged(new java.security.PrivilegedAction() {
0838 public Object run() {
0839 File tFile = null;
0840 FileOutputStream outStream = null;
0841 try {
0842 tFile = File.createTempFile("+~JF", ".tmp",
0843 null);
0844 /* Temp file deleted by font shutdown hook */
0845 BufferedInputStream inStream = new BufferedInputStream(
0846 fStream);
0847 outStream = new FileOutputStream(tFile);
0848 int bytesRead = 0;
0849 int bufSize = 8192;
0850 byte[] buf = new byte[bufSize];
0851 while (bytesRead != -1) {
0852 try {
0853 bytesRead = inStream.read(buf, 0,
0854 bufSize);
0855 } catch (Throwable t) {
0856 throw new IOException();
0857 }
0858 if (bytesRead != -1) {
0859 outStream.write(buf, 0, bytesRead);
0860 }
0861 }
0862 /* don't close the input stream */
0863 outStream.close();
0864 } catch (IOException e) {
0865 if (outStream != null) {
0866 try {
0867 outStream.close();
0868 } catch (Exception e1) {
0869 }
0870 }
0871 if (tFile != null) {
0872 try {
0873 tFile.delete();
0874 } catch (Exception e2) {
0875 }
0876 }
0877 return e;
0878 }
0879 return tFile;
0880 }
0881 });
0882
0883 if (ret instanceof File) {
0884 return new Font((File) ret, fontFormat, true);
0885 } else if (ret instanceof IOException) {
0886 throw (IOException) ret;
0887 } else {
0888 throw new FontFormatException("Couldn't access font stream");
0889 }
0890 }
0891
0892 /**
0893 * Returns a new <code>Font</code> using the specified font type
0894 * and the specified font file. The new <code>Font</code> is
0895 * created with a point size of 1 and style {@link #PLAIN PLAIN}.
0896 * This base font can then be used with the <code>deriveFont</code>
0897 * methods in this class to derive new <code>Font</code> objects with
0898 * varying sizes, styles, transforms and font features.
0899 * @param fontFormat the type of the <code>Font</code>, which is
0900 * {@link #TRUETYPE_FONT TRUETYPE_FONT} if a TrueType resource is
0901 * specified or {@link #TYPE1_FONT TYPE1_FONT} if a Type 1 resource is
0902 * specified.
0903 * So long as the returned font, or its derived fonts are referenced
0904 * the implementation may continue to access <code>fontFile</code>
0905 * to retrieve font data. Thus the results are undefined if the file
0906 * is changed, or becomes inaccessible.
0907 * <p>
0908 * To make the <code>Font</code> available to Font constructors the
0909 * returned <code>Font</code> must be registered in the
0910 * <code>GraphicsEnviroment</code> by calling
0911 * {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}.
0912 * @param fontFile a <code>File</code> object representing the
0913 * input data for the font.
0914 * @return a new <code>Font</code> created with the specified font type.
0915 * @throws IllegalArgumentException if <code>fontFormat</code> is not
0916 * <code>TRUETYPE_FONT</code>or<code>TYPE1_FONT</code>.
0917 * @throws NullPointerException if <code>fontFile</code> is null.
0918 * @throws IOException if the <code>fontFile</code> cannot be read.
0919 * @throws FontFormatException if <code>fontFile</code> does
0920 * not contain the required font tables for the specified format.
0921 * @throws SecurityException if the executing code does not have
0922 * permission to read from the file.
0923 * @see GraphicsEnvironment#registerFont(Font)
0924 * @since 1.5
0925 */
0926 public static Font createFont(int fontFormat, File fontFile)
0927 throws java.awt.FontFormatException, java.io.IOException {
0928 if (fontFormat != Font.TRUETYPE_FONT
0929 && fontFormat != Font.TYPE1_FONT) {
0930 throw new IllegalArgumentException(
0931 "font format not recognized");
0932 }
0933 SecurityManager sm = System.getSecurityManager();
0934 if (sm != null) {
0935 FilePermission filePermission = new FilePermission(fontFile
0936 .getPath(), "read");
0937 sm.checkPermission(filePermission);
0938 }
0939 if (!fontFile.canRead()) {
0940 throw new IOException("Can't read " + fontFile);
0941 }
0942 return new Font(fontFile, fontFormat, false);
0943 }
0944
0945 /**
0946 * Returns a copy of the transform associated with this
0947 * <code>Font</code>. This transform is not necessarily the one
0948 * used to construct the font. If the font has algorithmic
0949 * superscripting or width adjustment, this will be incorporated
0950 * into the returned <code>AffineTransform</code>.
0951 * <p>
0952 * Typically, fonts will not be transformed. Clients generally
0953 * should call {@link #isTransformed} first, and only call this
0954 * method if <code>isTransformed</code> returns true.
0955 *
0956 * @return an {@link AffineTransform} object representing the
0957 * transform attribute of this <code>Font</code> object.
0958 */
0959 public AffineTransform getTransform() {
0960 /* The most common case is the identity transform. Most callers
0961 * should call isTransformed() first, to decide if they need to
0962 * get the transform, but some may not. Here we check to see
0963 * if we have a nonidentity transform, and only do the work to
0964 * fetch and/or compute it if so, otherwise we return a new
0965 * identity transform.
0966 *
0967 * Note that the transform is _not_ necessarily the same as
0968 * the transform passed in as an Attribute in a Map, as the
0969 * transform returned will also reflect the effects of WIDTH and
0970 * SUPERSCRIPT attributes. Clients who want the actual transform
0971 * need to call getRequestedAttributes.
0972 */
0973 if (nonIdentityTx) {
0974 AttributeValues values = getAttributeValues();
0975
0976 AffineTransform at = values.isNonDefault(ETRANSFORM) ? new AffineTransform(
0977 values.getTransform())
0978 : new AffineTransform();
0979
0980 if (values.getSuperscript() != 0) {
0981 // can't get ascent and descent here, recursive call to this fn,
0982 // so use pointsize
0983 // let users combine super- and sub-scripting
0984
0985 int super script = values.getSuperscript();
0986
0987 double trans = 0;
0988 int n = 0;
0989 boolean up = super script > 0;
0990 int sign = up ? -1 : 1;
0991 int ss = up ? super script : -super script;
0992
0993 while ((ss & 7) > n) {
0994 int newn = ss & 7;
0995 trans += sign * (ssinfo[newn] - ssinfo[n]);
0996 ss >>= 3;
0997 sign = -sign;
0998 n = newn;
0999 }
1000 trans *= pointSize;
1001 double scale = Math.pow(2. / 3., n);
1002
1003 at.preConcatenate(AffineTransform.getTranslateInstance(
1004 0, trans));
1005 at.scale(scale, scale);
1006
1007 // note on placement and italics
1008 // We preconcatenate the transform because we don't want to translate along
1009 // the italic angle, but purely perpendicular to the baseline. While this
1010 // looks ok for superscripts, it can lead subscripts to stack on each other
1011 // and bring the following text too close. The way we deal with potential
1012 // collisions that can occur in the case of italics is by adjusting the
1013 // horizontal spacing of the adjacent glyphvectors. Examine the italic
1014 // angle of both vectors, if one is non-zero, compute the minimum ascent
1015 // and descent, and then the x position at each for each vector along its
1016 // italic angle starting from its (offset) baseline. Compute the difference
1017 // between the x positions and use the maximum difference to adjust the
1018 // position of the right gv.
1019 }
1020
1021 if (values.isNonDefault(EWIDTH)) {
1022 at.scale(values.getWidth(), 1f);
1023 }
1024
1025 return at;
1026 }
1027
1028 return new AffineTransform();
1029 }
1030
1031 // x = r^0 + r^1 + r^2... r^n
1032 // rx = r^1 + r^2 + r^3... r^(n+1)
1033 // x - rx = r^0 - r^(n+1)
1034 // x (1 - r) = r^0 - r^(n+1)
1035 // x = (r^0 - r^(n+1)) / (1 - r)
1036 // x = (1 - r^(n+1)) / (1 - r)
1037
1038 // scale ratio is 2/3
1039 // trans = 1/2 of ascent * x
1040 // assume ascent is 3/4 of point size
1041
1042 private static final float[] ssinfo = { 0.0f, 0.375f, 0.625f,
1043 0.7916667f, 0.9027778f, 0.9768519f, 1.0262346f, 1.0591564f, };
1044
1045 /**
1046 * Returns the family name of this <code>Font</code>.
1047 *
1048 * <p>The family name of a font is font specific. Two fonts such as
1049 * Helvetica Italic and Helvetica Bold have the same family name,
1050 * <i>Helvetica</i>, whereas their font face names are
1051 * <i>Helvetica Bold</i> and <i>Helvetica Italic</i>. The list of
1052 * available family names may be obtained by using the
1053 * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
1054 *
1055 * <p>Use <code>getName</code> to get the logical name of the font.
1056 * Use <code>getFontName</code> to get the font face name of the font.
1057 * @return a <code>String</code> that is the family name of this
1058 * <code>Font</code>.
1059 *
1060 * @see #getName
1061 * @see #getFontName
1062 * @since JDK1.1
1063 */
1064 public String getFamily() {
1065 return getFamily_NoClientCode();
1066 }
1067
1068 // NOTE: This method is called by privileged threads.
1069 // We implement this functionality in a package-private
1070 // method to insure that it cannot be overridden by client
1071 // subclasses.
1072 // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
1073 final String getFamily_NoClientCode() {
1074 return getFamily(Locale.getDefault());
1075 }
1076
1077 /**
1078 * Returns the family name of this <code>Font</code>, localized for
1079 * the specified locale.
1080 *
1081 * <p>The family name of a font is font specific. Two fonts such as
1082 * Helvetica Italic and Helvetica Bold have the same family name,
1083 * <i>Helvetica</i>, whereas their font face names are
1084 * <i>Helvetica Bold</i> and <i>Helvetica Italic</i>. The list of
1085 * available family names may be obtained by using the
1086 * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
1087 *
1088 * <p>Use <code>getFontName</code> to get the font face name of the font.
1089 * @param l locale for which to get the family name
1090 * @return a <code>String</code> representing the family name of the
1091 * font, localized for the specified locale.
1092 * @see #getFontName
1093 * @see java.util.Locale
1094 * @since 1.2
1095 */
1096 public String getFamily(Locale l) {
1097 if (l == null) {
1098 throw new NullPointerException(
1099 "null locale doesn't mean default");
1100 }
1101 return getFont2D().getFamilyName(l);
1102 }
1103
1104 /**
1105 * Returns the postscript name of this <code>Font</code>.
1106 * Use <code>getFamily</code> to get the family name of the font.
1107 * Use <code>getFontName</code> to get the font face name of the font.
1108 * @return a <code>String</code> representing the postscript name of
1109 * this <code>Font</code>.
1110 * @since 1.2
1111 */
1112 public String getPSName() {
1113 return getFont2D().getPostscriptName();
1114 }
1115
1116 /**
1117 * Returns the logical name of this <code>Font</code>.
1118 * Use <code>getFamily</code> to get the family name of the font.
1119 * Use <code>getFontName</code> to get the font face name of the font.
1120 * @return a <code>String</code> representing the logical name of
1121 * this <code>Font</code>.
1122 * @see #getFamily
1123 * @see #getFontName
1124 * @since JDK1.0
1125 */
1126 public String getName() {
1127 return name;
1128 }
1129
1130 /**
1131 * Returns the font face name of this <code>Font</code>. For example,
1132 * Helvetica Bold could be returned as a font face name.
1133 * Use <code>getFamily</code> to get the family name of the font.
1134 * Use <code>getName</code> to get the logical name of the font.
1135 * @return a <code>String</code> representing the font face name of
1136 * this <code>Font</code>.
1137 * @see #getFamily
1138 * @see #getName
1139 * @since 1.2
1140 */
1141 public String getFontName() {
1142 return getFontName(Locale.getDefault());
1143 }
1144
1145 /**
1146 * Returns the font face name of the <code>Font</code>, localized
1147 * for the specified locale. For example, Helvetica Fett could be
1148 * returned as the font face name.
1149 * Use <code>getFamily</code> to get the family name of the font.
1150 * @param l a locale for which to get the font face name
1151 * @return a <code>String</code> representing the font face name,
1152 * localized for the specified locale.
1153 * @see #getFamily
1154 * @see java.util.Locale
1155 */
1156 public String getFontName(Locale l) {
1157 if (l == null) {
1158 throw new NullPointerException(
1159 "null locale doesn't mean default");
1160 }
1161 return getFont2D().getFontName(l);
1162 }
1163
1164 /**
1165 * Returns the style of this <code>Font</code>. The style can be
1166 * PLAIN, BOLD, ITALIC, or BOLD+ITALIC.
1167 * @return the style of this <code>Font</code>
1168 * @see #isPlain
1169 * @see #isBold
1170 * @see #isItalic
1171 * @since JDK1.0
1172 */
1173 public int getStyle() {
1174 return style;
1175 }
1176
1177 /**
1178 * Returns the point size of this <code>Font</code>, rounded to
1179 * an integer.
1180 * Most users are familiar with the idea of using <i>point size</i> to
1181 * specify the size of glyphs in a font. This point size defines a
1182 * measurement between the baseline of one line to the baseline of the
1183 * following line in a single spaced text document. The point size is
1184 * based on <i>typographic points</i>, approximately 1/72 of an inch.
1185 * <p>
1186 * The Java(tm)2D API adopts the convention that one point is
1187 * equivalent to one unit in user coordinates. When using a
1188 * normalized transform for converting user space coordinates to
1189 * device space coordinates 72 user
1190 * space units equal 1 inch in device space. In this case one point
1191 * is 1/72 of an inch.
1192 * @return the point size of this <code>Font</code> in 1/72 of an
1193 * inch units.
1194 * @see #getSize2D
1195 * @see GraphicsConfiguration#getDefaultTransform
1196 * @see GraphicsConfiguration#getNormalizingTransform
1197 * @since JDK1.0
1198 */
1199 public int getSize() {
1200 return size;
1201 }
1202
1203 /**
1204 * Returns the point size of this <code>Font</code> in
1205 * <code>float</code> value.
1206 * @return the point size of this <code>Font</code> as a
1207 * <code>float</code> value.
1208 * @see #getSize
1209 * @since 1.2
1210 */
1211 public float getSize2D() {
1212 return pointSize;
1213 }
1214
1215 /**
1216 * Indicates whether or not this <code>Font</code> object's style is
1217 * PLAIN.
1218 * @return <code>true</code> if this <code>Font</code> has a
1219 * PLAIN sytle;
1220 * <code>false</code> otherwise.
1221 * @see java.awt.Font#getStyle
1222 * @since JDK1.0
1223 */
1224 public boolean isPlain() {
1225 return style == 0;
1226 }
1227
1228 /**
1229 * Indicates whether or not this <code>Font</code> object's style is
1230 * BOLD.
1231 * @return <code>true</code> if this <code>Font</code> object's
1232 * style is BOLD;
1233 * <code>false</code> otherwise.
1234 * @see java.awt.Font#getStyle
1235 * @since JDK1.0
1236 */
1237 public boolean isBold() {
1238 return (style & BOLD) != 0;
1239 }
1240
1241 /**
1242 * Indicates whether or not this <code>Font</code> object's style is
1243 * ITALIC.
1244 * @return <code>true</code> if this <code>Font</code> object's
1245 * style is ITALIC;
1246 * <code>false</code> otherwise.
1247 * @see java.awt.Font#getStyle
1248 * @since JDK1.0
1249 */
1250 public boolean isItalic() {
1251 return (style & ITALIC) != 0;
1252 }
1253
1254 /**
1255 * Indicates whether or not this <code>Font</code> object has a
1256 * transform that affects its size in addition to the Size
1257 * attribute.
1258 * @return <code>true</code> if this <code>Font</code> object
1259 * has a non-identity AffineTransform attribute.
1260 * <code>false</code> otherwise.
1261 * @see java.awt.Font#getTransform
1262 * @since 1.4
1263 */
1264 public boolean isTransformed() {
1265 return nonIdentityTx;
1266 }
1267
1268 /**
1269 * Return true if this Font contains attributes that require extra
1270 * layout processing.
1271 * @return true if the font has layout attributes
1272 * @since 1.6
1273 */
1274 public boolean hasLayoutAttributes() {
1275 return hasLayoutAttributes;
1276 }
1277
1278 /**
1279 * Returns a <code>Font</code> object from the system properties list.
1280 * <code>nm</code> is treated as the name of a system property to be
1281 * obtained. The <code>String</code> value of this property is then
1282 * interpreted as a <code>Font</code> object according to the
1283 * specification of <code>Font.decode(String)</code>
1284 * If the specified property is not found, or the executing code does
1285 * not have permission to read the property, null is returned instead.
1286 *
1287 * @param nm the property name
1288 * @return a <code>Font</code> object that the property name
1289 * describes, or null if no such property exists.
1290 * @throws NullPointerException if nm is null.
1291 * @since 1.2
1292 * @see #decode(String)
1293 */
1294 public static Font getFont(String nm) {
1295 return getFont(nm, null);
1296 }
1297
1298 /**
1299 * Returns the <code>Font</code> that the <code>str</code>
1300 * argument describes.
1301 * To ensure that this method returns the desired Font,
1302 * format the <code>str</code> parameter in
1303 * one of these ways
1304 * <p>
1305 * <ul>
1306 * <li><em>fontname-style-pointsize</em>
1307 * <li><em>fontname-pointsize</em>
1308 * <li><em>fontname-style</em>
1309 * <li><em>fontname</em>
1310 * <li><em>fontname style pointsize</em>
1311 * <li><em>fontname pointsize</em>
1312 * <li><em>fontname style</em>
1313 * <li><em>fontname</em>
1314 * </ul>
1315 * in which <i>style</i> is one of the four
1316 * case-insensitive strings:
1317 * <code>"PLAIN"</code>, <code>"BOLD"</code>, <code>"BOLDITALIC"</code>, or
1318 * <code>"ITALIC"</code>, and pointsize is a positive decimal integer
1319 * representation of the point size.
1320 * For example, if you want a font that is Arial, bold, with
1321 * a point size of 18, you would call this method with:
1322 * "Arial-BOLD-18".
1323 * This is equivalent to calling the Font constructor :
1324 * <code>new Font("Arial", Font.BOLD, 18);</code>
1325 * and the values are interpreted as specified by that constructor.
1326 * <p>
1327 * A valid trailing decimal field is always interpreted as the pointsize.
1328 * Therefore a fontname containing a trailing decimal value should not
1329 * be used in the fontname only form.
1330 * <p>
1331 * If a style name field is not one of the valid style strings, it is
1332 * interpreted as part of the font name, and the default style is used.
1333 * <p>
1334 * Only one of ' ' or '-' may be used to separate fields in the input.
1335 * The identified separator is the one closest to the end of the string
1336 * which separates a valid pointsize, or a valid style name from
1337 * the rest of the string.
1338 * Null (empty) pointsize and style fields are treated
1339 * as valid fields with the default value for that field.
1340 *<p>
1341 * Some font names may include the separator characters ' ' or '-'.
1342 * If <code>str</code> is not formed with 3 components, e.g. such that
1343 * <code>style</code> or <code>pointsize</code> fields are not present in
1344 * <code>str</code>, and <code>fontname</code> also contains a
1345 * character determined to be the separator character
1346 * then these characters where they appear as intended to be part of
1347 * <code>fontname</code> may instead be interpreted as separators
1348 * so the font name may not be properly recognised.
1349 *
1350 * <p>
1351 * The default size is 12 and the default style is PLAIN.
1352 * If <code>str</code> does not specify a valid size, the returned
1353 * <code>Font</code> has a size of 12. If <code>str</code> does not
1354 * specify a valid style, the returned Font has a style of PLAIN.
1355 * If you do not specify a valid font name in
1356 * the <code>str</code> argument, this method will return
1357 * a font with the family name "Dialog".
1358 * To determine what font family names are available on
1359 * your system, use the
1360 * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
1361 * If <code>str</code> is <code>null</code>, a new <code>Font</code>
1362 * is returned with the family name "Dialog", a size of 12 and a
1363 * PLAIN style.
1364 * @param str the name of the font, or <code>null</code>
1365 * @return the <code>Font</code> object that <code>str</code>
1366 * describes, or a new default <code>Font</code> if
1367 * <code>str</code> is <code>null</code>.
1368 * @see #getFamily
1369 * @since JDK1.1
1370 */
1371 public static Font decode(String str) {
1372 String fontName = str;
1373 String styleName = "";
1374 int fontSize = 12;
1375 int fontStyle = Font.PLAIN;
1376
1377 if (str == null) {
1378 return new Font(DIALOG, fontStyle, fontSize);
1379 }
1380
1381 int lastHyphen = str.lastIndexOf('-');
1382 int lastSpace = str.lastIndexOf(' ');
1383 char sepChar = (lastHyphen > lastSpace) ? '-' : ' ';
1384 int sizeIndex = str.lastIndexOf(sepChar);
1385 int styleIndex = str.lastIndexOf(sepChar, sizeIndex - 1);
1386 int strlen = str.length();
1387
1388 if (sizeIndex > 0 && sizeIndex + 1 < strlen) {
1389 try {
1390 fontSize = Integer
1391 .valueOf(str.substring(sizeIndex + 1))
1392 .intValue();
1393 if (fontSize <= 0) {
1394 fontSize = 12;
1395 }
1396 } catch (NumberFormatException e) {
1397 /* It wasn't a valid size, if we didn't also find the
1398 * start of the style string perhaps this is the style */
1399 styleIndex = sizeIndex;
1400 sizeIndex = strlen;
1401 if (str.charAt(sizeIndex - 1) == sepChar) {
1402 sizeIndex--;
1403 }
1404 }
1405 }
1406
1407 if (styleIndex >= 0 && styleIndex + 1 < strlen) {
1408 styleName = str.substring(styleIndex + 1, sizeIndex);
1409 styleName = styleName.toLowerCase(Locale.ENGLISH);
1410 if (styleName.equals("bolditalic")) {
1411 fontStyle = Font.BOLD | Font.ITALIC;
1412 } else if (styleName.equals("italic")) {
1413 fontStyle = Font.ITALIC;
1414 } else if (styleName.equals("bold")) {
1415 fontStyle = Font.BOLD;
1416 } else if (styleName.equals("plain")) {
1417 fontStyle = Font.PLAIN;
1418 } else {
1419 /* this string isn't any of the expected styles, so
1420 * assume its part of the font name
1421 */
1422 styleIndex = sizeIndex;
1423 if (str.charAt(styleIndex - 1) == sepChar) {
1424 styleIndex--;
1425 }
1426 }
1427 fontName = str.substring(0, styleIndex);
1428
1429 } else {
1430 int fontEnd = strlen;
1431 if (styleIndex > 0) {
1432 fontEnd = styleIndex;
1433 } else if (sizeIndex > 0) {
1434 fontEnd = sizeIndex;
1435 }
1436 if (fontEnd > 0 && str.charAt(fontEnd - 1) == sepChar) {
1437 fontEnd--;
1438 }
1439 fontName = str.substring(0, fontEnd);
1440 }
1441
1442 return new Font(fontName, fontStyle, fontSize);
1443 }
1444
1445 /**
1446 * Gets the specified <code>Font</code> from the system properties
1447 * list. As in the <code>getProperty</code> method of
1448 * <code>System</code>, the first
1449 * argument is treated as the name of a system property to be
1450 * obtained. The <code>String</code> value of this property is then
1451 * interpreted as a <code>Font</code> object.
1452 * <p>
1453 * The property value should be one of the forms accepted by
1454 * <code>Font.decode(String)</code>
1455 * If the specified property is not found, or the executing code does not
1456 * have permission to read the property, the <code>font</code>
1457 * argument is returned instead.
1458 * @param nm the case-insensitive property name
1459 * @param font a default <code>Font</code> to return if property
1460 * <code>nm</code> is not defined
1461 * @return the <code>Font</code> value of the property.
1462 * @throws NullPointerException if nm is null.
1463 * @see #decode(String)
1464 */
1465 public static Font getFont(String nm, Font font) {
1466 String str = null;
1467 try {
1468 str = System.getProperty(nm);
1469 } catch (SecurityException e) {
1470 }
1471 if (str == null) {
1472 return font;
1473 }
1474 return decode(str);
1475 }
1476
1477 transient int hash;
1478
1479 /**
1480 * Returns a hashcode for this <code>Font</code>.
1481 * @return a hashcode value for this <code>Font</code>.
1482 * @since JDK1.0
1483 */
1484 public int hashCode() {
1485 if (hash == 0) {
1486 hash = name.hashCode() ^ style ^ size;
1487 /* It is possible many fonts differ only in transform.
1488 * So include the transform in the hash calculation.
1489 * nonIdentityTx is set whenever there is a transform in
1490 * 'values'. The tests for null are required because it can
1491 * also be set for other reasons.
1492 */
1493 if (nonIdentityTx && values != null
1494 && values.getTransform() != null) {
1495 hash ^= values.getTransform().hashCode();
1496 }
1497 }
1498 return hash;
1499 }
1500
1501 /**
1502 * Compares this <code>Font</code> object to the specified
1503 * <code>Object</code>.
1504 * @param obj the <code>Object</code> to compare
1505 * @return <code>true</code> if the objects are the same
1506 * or if the argument is a <code>Font</code> object
1507 * describing the same font as this object;
1508 * <code>false</code> otherwise.
1509 * @since JDK1.0
1510 */
1511 public boolean equals(Object obj) {
1512 if (obj == this ) {
1513 return true;
1514 }
1515
1516 if (obj != null) {
1517 try {
1518 Font font = (Font) obj;
1519 if (size == font.size
1520 && style == font.style
1521 && nonIdentityTx == font.nonIdentityTx
1522 && hasLayoutAttributes == font.hasLayoutAttributes
1523 && pointSize == font.pointSize
1524 && name.equals(font.name)) {
1525
1526 /* 'values' is usually initialized lazily, except when
1527 * the font is constructed from a Map, or derived using
1528 * a Map or other values. So if only one font has
1529 * the field initialized we need to initialize it in
1530 * the other instance and compare.
1531 */
1532 if (values == null) {
1533 if (font.values == null) {
1534 return true;
1535 } else {
1536 return getAttributeValues().equals(
1537 font.values);
1538 }
1539 } else {
1540 return values.equals(font.getAttributeValues());
1541 }
1542 }
1543 } catch (ClassCastException e) {
1544 }
1545 }
1546 return false;
1547 }
1548
1549 /**
1550 * Converts this <code>Font</code> object to a <code>String</code>
1551 * representation.
1552 * @return a <code>String</code> representation of this
1553 * <code>Font</code> object.
1554 * @since JDK1.0
1555 */
1556 // NOTE: This method may be called by privileged threads.
1557 // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
1558 public String toString() {
1559 String strStyle;
1560
1561 if (isBold()) {
1562 strStyle = isItalic() ? "bolditalic" : "bold";
1563 } else {
1564 strStyle = isItalic() ? "italic" : "plain";
1565 }
1566
1567 return getClass().getName() + "[family=" + getFamily()
1568 + ",name=" + name + ",style=" + strStyle + ",size="
1569 + size + "]";
1570 } // toString()
1571
1572 /** Serialization support. A <code>readObject</code>
1573 * method is neccessary because the constructor creates
1574 * the font's peer, and we can't serialize the peer.
1575 * Similarly the computed font "family" may be different
1576 * at <code>readObject</code> time than at
1577 * <code>writeObject</code> time. An integer version is
1578 * written so that future versions of this class will be
1579 * able to recognize serialized output from this one.
1580 */
1581 /**
1582 * The <code>Font</code> Serializable Data Form.
1583 *
1584 * @serial
1585 */
1586 private int fontSerializedDataVersion = 1;
1587
1588 /**
1589 * Writes default serializable fields to a stream.
1590 *
1591 * @param s the <code>ObjectOutputStream</code> to write
1592 * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
1593 * @see #readObject(java.io.ObjectInputStream)
1594 */
1595 private void writeObject(java.io.ObjectOutputStream s)
1596 throws java.lang.ClassNotFoundException,
1597 java.io.IOException {
1598 if (values != null) {
1599 synchronized (values) {
1600 // transient
1601 fRequestedAttributes = values.toSerializableHashtable();
1602 s.defaultWriteObject();
1603 fRequestedAttributes = null;
1604 }
1605 } else {
1606 s.defaultWriteObject();
1607 }
1608 }
1609
1610 /**
1611 * Reads the <code>ObjectInputStream</code>.
1612 * Unrecognized keys or values will be ignored.
1613 *
1614 * @param s the <code>ObjectInputStream</code> to read
1615 * @serial
1616 * @see #writeObject(java.io.ObjectOutputStream)
1617 */
1618 private void readObject(java.io.ObjectInputStream s)
1619 throws java.lang.ClassNotFoundException,
1620 java.io.IOException {
1621 s.defaultReadObject();
1622 if (pointSize == 0) {
1623 pointSize = (float) size;
1624 }
1625
1626 // Handle fRequestedAttributes.
1627 // in 1.5, we always streamed out the font values plus
1628 // TRANSFORM, SUPERSCRIPT, and WIDTH, regardless of whether the
1629 // values were default or not. In 1.6 we only stream out
1630 // defined values. So, 1.6 streams in from a 1.5 stream,
1631 // it check each of these values and 'undefines' it if the
1632 // value is the default.
1633
1634 if (fRequestedAttributes != null) {
1635 values = getAttributeValues(); // init
1636 AttributeValues extras = AttributeValues
1637 .fromSerializableHashtable(fRequestedAttributes);
1638 if (!AttributeValues.is16Hashtable(fRequestedAttributes)) {
1639 extras.unsetDefault(); // if legacy stream, undefine these
1640 }
1641 values = getAttributeValues().merge(extras);
1642 this .nonIdentityTx = values.anyNonDefault(EXTRA_MASK);
1643 this .hasLayoutAttributes = values
1644 .anyNonDefault(LAYOUT_MASK);
1645
1646 fRequestedAttributes = null; // don't need it any more
1647 }
1648 }
1649
1650 /**
1651 * Returns the number of glyphs in this <code>Font</code>. Glyph codes
1652 * for this <code>Font</code> range from 0 to
1653 * <code>getNumGlyphs()</code> - 1.
1654 * @return the number of glyphs in this <code>Font</code>.
1655 * @since 1.2
1656 */
1657 public int getNumGlyphs() {
1658 return getFont2D().getNumGlyphs();
1659 }
1660
1661 /**
1662 * Returns the glyphCode which is used when this <code>Font</code>
1663 * does not have a glyph for a specified unicode code point.
1664 * @return the glyphCode of this <code>Font</code>.
1665 * @since 1.2
1666 */
1667 public int getMissingGlyphCode() {
1668 return getFont2D().getMissingGlyphCode();
1669 }
1670
1671 /**
1672 * Returns the baseline appropriate for displaying this character.
1673 * <p>
1674 * Large fonts can support different writing systems, and each system can
1675 * use a different baseline.
1676 * The character argument determines the writing system to use. Clients
1677 * should not assume all characters use the same baseline.
1678 *
1679 * @param c a character used to identify the writing system
1680 * @return the baseline appropriate for the specified character.
1681 * @see LineMetrics#getBaselineOffsets
1682 * @see #ROMAN_BASELINE
1683 * @see #CENTER_BASELINE
1684 * @see #HANGING_BASELINE
1685 * @since 1.2
1686 */
1687 public byte getBaselineFor(char c) {
1688 return getFont2D().getBaselineFor(c);
1689 }
1690
1691 /**
1692 * Returns a map of font attributes available in this
1693 * <code>Font</code>. Attributes include things like ligatures and
1694 * glyph substitution.
1695 * @return the attributes map of this <code>Font</code>.
1696 */
1697 public Map<TextAttribute, ?> getAttributes() {
1698 return new AttributeMap(getAttributeValues());
1699 }
1700
1701 /**
1702 * Returns the keys of all the attributes supported by this
1703 * <code>Font</code>. These attributes can be used to derive other
1704 * fonts.
1705 * @return an array containing the keys of all the attributes
1706 * supported by this <code>Font</code>.
1707 * @since 1.2
1708 */
1709 public Attribute[] getAvailableAttributes() {
1710 // FONT is not supported by Font
1711
1712 Attribute attributes[] = { TextAttribute.FAMILY,
1713 TextAttribute.WEIGHT, TextAttribute.WIDTH,
1714 TextAttribute.POSTURE, TextAttribute.SIZE,
1715 TextAttribute.TRANSFORM, TextAttribute.SUPERSCRIPT,
1716 TextAttribute.CHAR_REPLACEMENT,
1717 TextAttribute.FOREGROUND, TextAttribute.BACKGROUND,
1718 TextAttribute.UNDERLINE, TextAttribute.STRIKETHROUGH,
1719 TextAttribute.RUN_DIRECTION,
1720 TextAttribute.BIDI_EMBEDDING,
1721 TextAttribute.JUSTIFICATION,
1722 TextAttribute.INPUT_METHOD_HIGHLIGHT,
1723 TextAttribute.INPUT_METHOD_UNDERLINE,
1724 TextAttribute.SWAP_COLORS,
1725 TextAttribute.NUMERIC_SHAPING, TextAttribute.KERNING,
1726 TextAttribute.LIGATURES, TextAttribute.TRACKING, };
1727
1728 return attributes;
1729 }
1730
1731 /**
1732 * Creates a new <code>Font</code> object by replicating this
1733 * <code>Font</code> object and applying a new style and size.
1734 * @param style the style for the new <code>Font</code>
1735 * @param size the size for the new <code>Font</code>
1736 * @return a new <code>Font</code> object.
1737 * @since 1.2
1738 */
1739 public Font deriveFont(int style, float size) {
1740 if (values == null) {
1741 return new Font(name, style, size, createdFont,
1742 font2DHandle);
1743 }
1744 AttributeValues newValues = getAttributeValues().clone();
1745 int oldStyle = (this .style != style) ? this .style : -1;
1746 applyStyle(style, newValues);
1747 newValues.setSize(size);
1748 return new Font(newValues, null, oldStyle, createdFont,
1749 font2DHandle);
1750 }
1751
1752 /**
1753 * Creates a new <code>Font</code> object by replicating this
1754 * <code>Font</code> object and applying a new style and transform.
1755 * @param style the style for the new <code>Font</code>
1756 * @param trans the <code>AffineTransform</code> associated with the
1757 * new <code>Font</code>
1758 * @return a new <code>Font</code> object.
1759 * @throws IllegalArgumentException if <code>trans</code> is
1760 * <code>null</code>
1761 * @since 1.2
1762 */
1763 public Font deriveFont(int style, AffineTransform trans) {
1764 AttributeValues newValues = getAttributeValues().clone();
1765 int oldStyle = (this .style != style) ? this .style : -1;
1766 applyStyle(style, newValues);
1767 applyTransform(trans, newValues);
1768 return new Font(newValues, null, oldStyle, createdFont,
1769 font2DHandle);
1770 }
1771
1772 /**
1773 * Creates a new <code>Font</code> object by replicating the current
1774 * <code>Font</code> object and applying a new size to it.
1775 * @param size the size for the new <code>Font</code>.
1776 * @return a new <code>Font</code> object.
1777 * @since 1.2
1778 */
1779 public Font deriveFont(float size) {
1780 if (values == null) {
1781 return new Font(name, style, size, createdFont,
1782 font2DHandle);
1783 }
1784 AttributeValues newValues = getAttributeValues().clone();
1785 newValues.setSize(size);
1786 return new Font(newValues, null, -1, createdFont, font2DHandle);
1787 }
1788
1789 /**
1790 * Creates a new <code>Font</code> object by replicating the current
1791 * <code>Font</code> object and applying a new transform to it.
1792 * @param trans the <code>AffineTransform</code> associated with the
1793 * new <code>Font</code>
1794 * @return a new <code>Font</code> object.
1795 * @throws IllegalArgumentException if <code>trans</code> is
1796 * <code>null</code>
1797 * @since 1.2
1798 */
1799 public Font deriveFont(AffineTransform trans) {
1800 AttributeValues newValues = getAttributeValues().clone();
1801 applyTransform(trans, newValues);
1802 return new Font(newValues, null, -1, createdFont, font2DHandle);
1803 }
1804
1805 /**
1806 * Creates a new <code>Font</code> object by replicating the current
1807 * <code>Font</code> object and applying a new style to it.
1808 * @param style the style for the new <code>Font</code>
1809 * @return a new <code>Font</code> object.
1810 * @since 1.2
1811 */
1812 public Font deriveFont(int style) {
1813 if (values == null) {
1814 return new Font(name, style, size, createdFont,
1815 font2DHandle);
1816 }
1817 AttributeValues newValues = getAttributeValues().clone();
1818 int oldStyle = (this .style != style) ? this .style : -1;
1819 applyStyle(style, newValues);
1820 return new Font(newValues, null, oldStyle, createdFont,
1821 font2DHandle);
1822 }
1823
1824 /**
1825 * Creates a new <code>Font</code> object by replicating the current
1826 * <code>Font</code> object and applying a new set of font attributes
1827 * to it.
1828 *
1829 * @param attributes a map of attributes enabled for the new
1830 * <code>Font</code>
1831 * @return a new <code>Font</code> object.
1832 * @since 1.2
1833 */
1834 public Font deriveFont(Map<? extends Attribute, ?> attributes) {
1835 if (attributes == null) {
1836 return this ;
1837 }
1838 AttributeValues newValues = getAttributeValues().clone();
1839 newValues.merge(attributes, RECOGNIZED_MASK);
1840
1841 return new Font(newValues, name, style, createdFont,
1842 font2DHandle);
1843 }
1844
1845 /**
1846 * Checks if this <code>Font</code> has a glyph for the specified
1847 * character.
1848 *
1849 * <p> <b>Note:</b> This method cannot handle <a
1850 * href="../../java/lang/Character.html#supplementary"> supplementary
1851 * characters</a>. To support all Unicode characters, including
1852 * supplementary characters, use the {@link #canDisplay(int)}
1853 * method or <code>canDisplayUpTo</code> methods.
1854 *
1855 * @param c the character for which a glyph is needed
1856 * @return <code>true</code> if this <code>Font</code> has a glyph for this
1857 * character; <code>false</code> otherwise.
1858 * @since 1.2
1859 */
1860 public boolean canDisplay(char c) {
1861 return getFont2D().canDisplay(c);
1862 }
1863
1864 /**
1865 * Checks if this <code>Font</code> has a glyph for the specified
1866 * character.
1867 *
1868 * @param codePoint the character (Unicode code point) for which a glyph
1869 * is needed.
1870 * @return <code>true</code> if this <code>Font</code> has a glyph for the
1871 * character; <code>false</code> otherwise.
1872 * @throws IllegalArgumentException if the code point is not a valid Unicode
1873 * code point.
1874 * @see Character#isValidCodePoint(int)
1875 * @since 1.5
1876 */
1877 public boolean canDisplay(int codePoint) {
1878 if (!Character.isValidCodePoint(codePoint)) {
1879 throw new IllegalArgumentException("invalid code point: "
1880 + Integer.toHexString(codePoint));
1881 }
1882 return getFont2D().canDisplay(codePoint);
1883 }
1884
1885 /**
1886 * Indicates whether or not this <code>Font</code> can display a
1887 * specified <code>String</code>. For strings with Unicode encoding,
1888 * it is important to know if a particular font can display the
1889 * string. This method returns an offset into the <code>String</code>
1890 * <code>str</code> which is the first character this
1891 * <code>Font</code> cannot display without using the missing glyph
1892 * code. If the <code>Font</code> can display all characters, -1 is
1893 * returned.
1894 * @param str a <code>String</code> object
1895 * @return an offset into <code>str</code> that points
1896 * to the first character in <code>str</code> that this
1897 * <code>Font</code> cannot display; or <code>-1</code> if
1898 * this <code>Font</code> can display all characters in
1899 * <code>str</code>.
1900 * @since 1.2
1901 */
1902 public int canDisplayUpTo(String str) {
1903 return canDisplayUpTo(new StringCharacterIterator(str), 0, str
1904 .length());
1905 }
1906
1907 /**
1908 * Indicates whether or not this <code>Font</code> can display
1909 * the characters in the specified <code>text</code>
1910 * starting at <code>start</code> and ending at
1911 * <code>limit</code>. This method is a convenience overload.
1912 * @param text the specified array of <code>char</code> values
1913 * @param start the specified starting offset (in
1914 * <code>char</code>s) into the specified array of
1915 * <code>char</code> values
1916 * @param limit the specified ending offset (in
1917 * <code>char</code>s) into the specified array of
1918 * <code>char</code> values
1919 * @return an offset into <code>text</code> that points
1920 * to the first character in <code>text</code> that this
1921 * <code>Font</code> cannot display; or <code>-1</code> if
1922 * this <code>Font</code> can display all characters in
1923 * <code>text</code>.
1924 * @since 1.2
1925 */
1926 public int canDisplayUpTo(char[] text, int start, int limit) {
1927 while (start < limit && canDisplay(text[start])) {
1928 ++start;
1929 }
1930
1931 return start == limit ? -1 : start;
1932 }
1933
1934 /**
1935 * Indicates whether or not this <code>Font</code> can display the
1936 * text specified by the <code>iter</code> starting at
1937 * <code>start</code> and ending at <code>limit</code>.
1938 *
1939 * @param iter a {@link CharacterIterator} object
1940 * @param start the specified starting offset into the specified
1941 * <code>CharacterIterator</code>.
1942 * @param limit the specified ending offset into the specified
1943 * <code>CharacterIterator</code>.
1944 * @return an offset into <code>iter</code> that points
1945 * to the first character in <code>iter</code> that this
1946 * <code>Font</code> cannot display; or <code>-1</code> if
1947 * this <code>Font</code> can display all characters in
1948 * <code>iter</code>.
1949 * @since 1.2
1950 */
1951 public int canDisplayUpTo(CharacterIterator iter, int start,
1952 int limit) {
1953 for (char c = iter.setIndex(start); iter.getIndex() < limit
1954 && canDisplay(c); c = iter.next()) {
1955 }
1956
1957 int result = iter.getIndex();
1958 return result == limit ? -1 : result;
1959 }
1960
1961 /**
1962 * Returns the italic angle of this <code>Font</code>. The italic angle
1963 * is the inverse slope of the caret which best matches the posture of this
1964 * <code>Font</code>.
1965 * @see TextAttribute#POSTURE
1966 * @return the angle of the ITALIC style of this <code>Font</code>.
1967 */
1968 public float getItalicAngle() {
1969 return getItalicAngle(null);
1970 }
1971
1972 /* The FRC hints don't affect the value of the italic angle but
1973 * we need to pass them in to look up a strike.
1974 * If we can pass in ones already being used it can prevent an extra
1975 * strike from being allocated. Note that since italic angle is
1976 * a property of the font, the font transform is needed not the
1977 * device transform. Finally, this is private but the only caller of this
1978 * in the JDK - and the only likely caller - is in this same class.
1979 */
1980 private float getItalicAngle(FontRenderContext frc) {
1981 AffineTransform at = (isTransformed()) ? getTransform()
1982 : identityTx;
1983 Object aa, fm;
1984 if (frc == null) {
1985 aa = RenderingHints.VALUE_TEXT_ANTIALIAS_OFF;
1986 fm = RenderingHints.VALUE_FRACTIONALMETRICS_OFF;
1987 } else {
1988 aa = frc.getAntiAliasingHint();
1989 fm = frc.getFractionalMetricsHint();
1990 }
1991 return getFont2D().getItalicAngle(this , at, aa, fm);
1992 }
1993
1994 /**
1995 * Checks whether or not this <code>Font</code> has uniform
1996 * line metrics. A logical <code>Font</code> might be a
1997 * composite font, which means that it is composed of different
1998 * physical fonts to cover different code ranges. Each of these
1999 * fonts might have different <code>LineMetrics</code>. If the
2000 * logical <code>Font</code> is a single
2001 * font then the metrics would be uniform.
2002 * @return <code>true</code> if this <code>Font</code> has
2003 * uniform line metrics; <code>false</code> otherwise.
2004 */
2005 public boolean hasUniformLineMetrics() {
2006 return false; // REMIND always safe, but prevents caller optimize
2007 }
2008
2009 private transient SoftReference flmref;
2010
2011 private FontLineMetrics defaultLineMetrics(FontRenderContext frc) {
2012 FontLineMetrics flm = null;
2013 if (flmref == null
2014 || (flm = (FontLineMetrics) flmref.get()) == null
2015 || !flm.frc.equals(frc)) {
2016
2017 /* The device transform in the frc is not used in obtaining line
2018 * metrics, although it probably should be: REMIND find why not?
2019 * The font transform is used but its applied in getFontMetrics, so
2020 * just pass identity here
2021 */
2022 float[] metrics = new float[8];
2023 getFont2D().getFontMetrics(this , identityTx,
2024 frc.getAntiAliasingHint(),
2025 frc.getFractionalMetricsHint(), metrics);
2026 float ascent = metrics[0];
2027 float descent = metrics[1];
2028 float leading = metrics[2];
2029 float ssOffset = 0;
2030 if (values != null && values.getSuperscript() != 0) {
2031 ssOffset = (float) getTransform().getTranslateY();
2032 ascent -= ssOffset;
2033 descent += ssOffset;
2034 }
2035 float height = ascent + descent + leading;
2036
2037 int baselineIndex = 0; // need real index, assumes roman for everything
2038 // need real baselines eventually
2039 float[] baselineOffsets = { 0,
2040 (descent / 2f - ascent) / 2f, -ascent };
2041
2042 float strikethroughOffset = metrics[4];
2043 float strikethroughThickness = metrics[5];
2044
2045 float underlineOffset = metrics[6];
2046 float underlineThickness = metrics[7];
2047
2048 float italicAngle = getItalicAngle(frc);
2049
2050 if (isTransformed()) {
2051 AffineTransform ctx = values.getCharTransform(); // extract rotation
2052 if (ctx != null) {
2053 Point2D.Float pt = new Point2D.Float();
2054 pt.setLocation(0, strikethroughOffset);
2055 ctx.deltaTransform(pt, pt);
2056 strikethroughOffset = pt.y;
2057 pt.setLocation(0, strikethroughThickness);
2058 ctx.deltaTransform(pt, pt);
2059 strikethroughThickness = pt.y;
2060 pt.setLocation(0, underlineOffset);
2061 ctx.deltaTransform(pt, pt);
2062 underlineOffset = pt.y;
2063 pt.setLocation(0, underlineThickness);
2064 ctx.deltaTransform(pt, pt);
2065 underlineThickness = pt.y;
2066 }
2067 }
2068 strikethroughOffset += ssOffset;
2069 underlineOffset += ssOffset;
2070
2071 CoreMetrics cm = new CoreMetrics(ascent, descent, leading,
2072 height, baselineIndex, baselineOffsets,
2073 strikethroughOffset, strikethroughThickness,
2074 underlineOffset, underlineThickness, ssOffset,
2075 italicAngle);
2076
2077 flm = new FontLineMetrics(0, cm, frc);
2078 flmref = new SoftReference(flm);
2079 }
2080
2081 return (FontLineMetrics) flm.clone();
2082 }
2083
2084 /**
2085 * Returns a {@link LineMetrics} object created with the specified
2086 * <code>String</code> and {@link FontRenderContext}.
2087 * @param str the specified <code>String</code>
2088 * @param frc the specified <code>FontRenderContext</code>
2089 * @return a <code>LineMetrics</code> object created with the
2090 * specified <code>String</code> and {@link FontRenderContext}.
2091 */
2092 public LineMetrics getLineMetrics(String str, FontRenderContext frc) {
2093 FontLineMetrics flm = defaultLineMetrics(frc);
2094 flm.numchars = str.length();
2095 return flm;
2096 }
2097
2098 /**
2099 * Returns a <code>LineMetrics</code> object created with the
2100 * specified arguments.
2101 * @param str the specified <code>String</code>
2102 * @param beginIndex the initial offset of <code>str</code>
2103 * @param limit the end offset of <code>str</code>
2104 * @param frc the specified <code>FontRenderContext</code>
2105 * @return a <code>LineMetrics</code> object created with the
2106 * specified arguments.
2107 */
2108 public LineMetrics getLineMetrics(String str, int beginIndex,
2109 int limit, FontRenderContext frc) {
2110 FontLineMetrics flm = defaultLineMetrics(frc);
2111 int numChars = limit - beginIndex;
2112 flm.numchars = (numChars < 0) ? 0 : numChars;
2113 return flm;
2114 }
2115
2116 /**
2117 * Returns a <code>LineMetrics</code> object created with the
2118 * specified arguments.
2119 * @param chars an array of characters
2120 * @param beginIndex the initial offset of <code>chars</code>
2121 * @param limit the end offset of <code>chars</code>
2122 * @param frc the specified <code>FontRenderContext</code>
2123 * @return a <code>LineMetrics</code> object created with the
2124 * specified arguments.
2125 */
2126 public LineMetrics getLineMetrics(char[] chars, int beginIndex,
2127 int limit, FontRenderContext frc) {
2128 FontLineMetrics flm = defaultLineMetrics(frc);
2129 int numChars = limit - beginIndex;
2130 flm.numchars = (numChars < 0) ? 0 : numChars;
2131 return flm;
2132 }
2133
2134 /**
2135 * Returns a <code>LineMetrics</code> object created with the
2136 * specified arguments.
2137 * @param ci the specified <code>CharacterIterator</code>
2138 * @param beginIndex the initial offset in <code>ci</code>
2139 * @param limit the end offset of <code>ci</code>
2140 * @param frc the specified <code>FontRenderContext</code>
2141 * @return a <code>LineMetrics</code> object created with the
2142 * specified arguments.
2143 */
2144 public LineMetrics getLineMetrics(CharacterIterator ci,
2145 int beginIndex, int limit, FontRenderContext frc) {
2146 FontLineMetrics flm = defaultLineMetrics(frc);
2147 int numChars = limit - beginIndex;
2148 flm.numchars = (numChars < 0) ? 0 : numChars;
2149 return flm;
2150 }
2151
2152 /**
2153 * Returns the logical bounds of the specified <code>String</code> in
2154 * the specified <code>FontRenderContext</code>. The logical bounds
2155 * contains the origin, ascent, advance, and height, which includes
2156 * the leading. The logical bounds does not always enclose all the
2157 * text. For example, in some languages and in some fonts, accent
2158 * marks can be positioned above the ascent or below the descent.
2159 * To obtain a visual bounding box, which encloses all the text,
2160 * use the {@link TextLayout#getBounds() getBounds} method of
2161 * <code>TextLayout</code>.
2162 * <p>Note: The returned bounds is in baseline-relative coordinates
2163 * (see {@link java.awt.Font class notes}).
2164 * @param str the specified <code>String</code>
2165 * @param frc the specified <code>FontRenderContext</code>
2166 * @return a {@link Rectangle2D} that is the bounding box of the
2167 * specified <code>String</code> in the specified
2168 * <code>FontRenderContext</code>.
2169 * @see FontRenderContext
2170 * @see Font#createGlyphVector
2171 * @since 1.2
2172 */
2173 public Rectangle2D getStringBounds(String str, FontRenderContext frc) {
2174 char[] array = str.toCharArray();
2175 return getStringBounds(array, 0, array.length, frc);
2176 }
2177
2178 /**
2179 * Returns the logical bounds of the specified <code>String</code> in
2180 * the specified <code>FontRenderContext</code>. The logical bounds
2181 * contains the origin, ascent, advance, and height, which includes
2182 * the leading. The logical bounds does not always enclose all the
2183 * text. For example, in some languages and in some fonts, accent
2184 * marks can be positioned above the ascent or below the descent.
2185 * To obtain a visual bounding box, which encloses all the text,
2186 * use the {@link TextLayout#getBounds() getBounds} method of
2187 * <code>TextLayout</code>.
2188 * <p>Note: The returned bounds is in baseline-relative coordinates
2189 * (see {@link java.awt.Font class notes}).
2190 * @param str the specified <code>String</code>
2191 * @param beginIndex the initial offset of <code>str</code>
2192 * @param limit the end offset of <code>str</code>
2193 * @param frc the specified <code>FontRenderContext</code>
2194 * @return a <code>Rectangle2D</code> that is the bounding box of the
2195 * specified <code>String</code> in the specified
2196 * <code>FontRenderContext</code>.
2197 * @throws IndexOutOfBoundsException if <code>beginIndex</code> is
2198 * less than zero, or <code>limit</code> is greater than the
2199 * length of <code>str</code>, or <code>beginIndex</code>
2200 * is greater than <code>limit</code>.
2201 * @see FontRenderContext
2202 * @see Font#createGlyphVector
2203 * @since 1.2
2204 */
2205 public Rectangle2D getStringBounds(String str, int beginIndex,
2206 int limit, FontRenderContext frc) {
2207 String substr = str.substring(beginIndex, limit);
2208 return getStringBounds(substr, frc);
2209 }
2210
2211 /**
2212 * Returns the logical bounds of the specified array of characters
2213 * in the specified <code>FontRenderContext</code>. The logical
2214 * bounds contains the origin, ascent, advance, and height, which
2215 * includes the leading. The logical bounds does not always enclose
2216 * all the text. For example, in some languages and in some fonts,
2217 * accent marks can be positioned above the ascent or below the
2218 * descent. To obtain a visual bounding box, which encloses all the
2219 * text, use the {@link TextLayout#getBounds() getBounds} method of
2220 * <code>TextLayout</code>.
2221 * <p>Note: The returned bounds is in baseline-relative coordinates
2222 * (see {@link java.awt.Font class notes}).
2223 * @param chars an array of characters
2224 * @param beginIndex the initial offset in the array of
2225 * characters
2226 * @param limit the end offset in the array of characters
2227 * @param frc the specified <code>FontRenderContext</code>
2228 * @return a <code>Rectangle2D</code> that is the bounding box of the
2229 * specified array of characters in the specified
2230 * <code>FontRenderContext</code>.
2231 * @throws IndexOutOfBoundsException if <code>beginIndex</code> is
2232 * less than zero, or <code>limit</code> is greater than the
2233 * length of <code>chars</code>, or <code>beginIndex</code>
2234 * is greater than <code>limit</code>.
2235 * @see FontRenderContext
2236 * @see Font#createGlyphVector
2237 * @since 1.2
2238 */
2239 public Rectangle2D getStringBounds(char[] chars, int beginIndex,
2240 int limit, FontRenderContext frc) {
2241 if (beginIndex < 0) {
2242 throw new IndexOutOfBoundsException("beginIndex: "
2243 + beginIndex);
2244 }
2245 if (limit > chars.length) {
2246 throw new IndexOutOfBoundsException("limit: " + limit);
2247 }
2248 if (beginIndex > limit) {
2249 throw new IndexOutOfBoundsException("range length: "
2250 + (limit - beginIndex));
2251 }
2252
2253 // this code should be in textlayout
2254 // quick check for simple text, assume GV ok to use if simple
2255
2256 boolean simple = values == null
2257 || (values.getKerning() == 0
2258 && values.getLigatures() == 0 && values
2259 .getBaselineTransform() == null);
2260 if (simple) {
2261 simple = !FontManager.isComplexText(chars, beginIndex,
2262 limit);
2263 }
2264
2265 if (simple) {
2266 GlyphVector gv = new StandardGlyphVector(this , chars,
2267 beginIndex, limit - beginIndex, frc);
2268 return gv.getLogicalBounds();
2269 } else {
2270 // need char array constructor on textlayout
2271 String str = new String(chars, beginIndex, limit
2272 - beginIndex);
2273 TextLayout tl = new TextLayout(str, this , frc);
2274 return new Rectangle2D.Float(0, -tl.getAscent(), tl
2275 .getAdvance(), tl.getAscent() + tl.getDescent()
2276 + tl.getLeading());
2277 }
2278 }
2279
2280 /**
2281 * Returns the logical bounds of the characters indexed in the
2282 * specified {@link CharacterIterator} in the
2283 * specified <code>FontRenderContext</code>. The logical bounds
2284 * contains the origin, ascent, advance, and height, which includes
2285 * the leading. The logical bounds does not always enclose all the
2286 * text. For example, in some languages and in some fonts, accent
2287 * marks can be positioned above the ascent or below the descent.
2288 * To obtain a visual bounding box, which encloses all the text,
2289 * use the {@link TextLayout#getBounds() getBounds} method of
2290 * <code>TextLayout</code>.
2291 * <p>Note: The returned bounds is in baseline-relative coordinates
2292 * (see {@link java.awt.Font class notes}).
2293 * @param ci the specified <code>CharacterIterator</code>
2294 * @param beginIndex the initial offset in <code>ci</code>
2295 * @param limit the end offset in <code>ci</code>
2296 * @param frc the specified <code>FontRenderContext</code>
2297 * @return a <code>Rectangle2D</code> that is the bounding box of the
2298 * characters indexed in the specified <code>CharacterIterator</code>
2299 * in the specified <code>FontRenderContext</code>.
2300 * @see FontRenderContext
2301 * @see Font#createGlyphVector
2302 * @since 1.2
2303 * @throws IndexOutOfBoundsException if <code>beginIndex</code> is
2304 * less than the start index of <code>ci</code>, or
2305 * <code>limit</code> is greater than the end index of
2306 * <code>ci</code>, or <code>beginIndex</code> is greater
2307 * than <code>limit</code>
2308 */
2309 public Rectangle2D getStringBounds(CharacterIterator ci,
2310 int beginIndex, int limit, FontRenderContext frc) {
2311 int start = ci.getBeginIndex();
2312 int end = ci.getEndIndex();
2313
2314 if (beginIndex < start) {
2315 throw new IndexOutOfBoundsException("beginIndex: "
2316 + beginIndex);
2317 }
2318 if (limit > end) {
2319 throw new IndexOutOfBoundsException("limit: " + limit);
2320 }
2321 if (beginIndex > limit) {
2322 throw new IndexOutOfBoundsException("range length: "
2323 + (limit - beginIndex));
2324 }
2325
2326 char[] arr = new char[limit - beginIndex];
2327
2328 ci.setIndex(beginIndex);
2329 for (int idx = 0; idx < arr.length; idx++) {
2330 arr[idx] = ci.current();
2331 ci.next();
2332 }
2333
2334 return getStringBounds(arr, 0, arr.length, frc);
2335 }
2336
2337 /**
2338 * Returns the bounds for the character with the maximum
2339 * bounds as defined in the specified <code>FontRenderContext</code>.
2340 * <p>Note: The returned bounds is in baseline-relative coordinates
2341 * (see {@link java.awt.Font class notes}).
2342 * @param frc the specified <code>FontRenderContext</code>
2343 * @return a <code>Rectangle2D</code> that is the bounding box
2344 * for the character with the maximum bounds.
2345 */
2346 public Rectangle2D getMaxCharBounds(FontRenderContext frc) {
2347 float[] metrics = new float[4];
2348
2349 getFont2D().getFontMetrics(this , frc, metrics);
2350
2351 return new Rectangle2D.Float(0, -metrics[0], metrics[3],
2352 metrics[0] + metrics[1] + metrics[2]);
2353 }
2354
2355 /**
2356 * Creates a {@link java.awt.font.GlyphVector GlyphVector} by
2357 * mapping characters to glyphs one-to-one based on the
2358 * Unicode cmap in this <code>Font</code>. This method does no other
2359 * processing besides the mapping of glyphs to characters. This
2360 * means that this method is not useful for some scripts, such
2361 * as Arabic, Hebrew, Thai, and Indic, that require reordering,
2362 * shaping, or ligature substitution.
2363 * @param frc the specified <code>FontRenderContext</code>
2364 * @param str the specified <code>String</code>
2365 * @return a new <code>GlyphVector</code> created with the
2366 * specified <code>String</code> and the specified
2367 * <code>FontRenderContext</code>.
2368 */
2369 public GlyphVector createGlyphVector(FontRenderContext frc,
2370 String str) {
2371 return (GlyphVector) new StandardGlyphVector(this , str, frc);
2372 }
2373
2374 /**
2375 * Creates a {@link java.awt.font.GlyphVector GlyphVector} by
2376 * mapping characters to glyphs one-to-one based on the
2377 * Unicode cmap in this <code>Font</code>. This method does no other
2378 * processing besides the mapping of glyphs to characters. This
2379 * means that this method is not useful for some scripts, such
2380 * as Arabic, Hebrew, Thai, and Indic, that require reordering,
2381 * shaping, or ligature substitution.
2382 * @param frc the specified <code>FontRenderContext</code>
2383 * @param chars the specified array of characters
2384 * @return a new <code>GlyphVector</code> created with the
2385 * specified array of characters and the specified
2386 * <code>FontRenderContext</code>.
2387 */
2388 public GlyphVector createGlyphVector(FontRenderContext frc,
2389 char[] chars) {
2390 return (GlyphVector) new StandardGlyphVector(this , chars, frc);
2391 }
2392
2393 /**
2394 * Creates a {@link java.awt.font.GlyphVector GlyphVector} by
2395 * mapping the specified characters to glyphs one-to-one based on the
2396 * Unicode cmap in this <code>Font</code>. This method does no other
2397 * processing besides the mapping of glyphs to characters. This
2398 * means that this method is not useful for some scripts, such
2399 * as Arabic, Hebrew, Thai, and Indic, that require reordering,
2400 * shaping, or ligature substitution.
2401 * @param frc the specified <code>FontRenderContext</code>
2402 * @param ci the specified <code>CharacterIterator</code>
2403 * @return a new <code>GlyphVector</code> created with the
2404 * specified <code>CharacterIterator</code> and the specified
2405 * <code>FontRenderContext</code>.
2406 */
2407 public GlyphVector createGlyphVector(FontRenderContext frc,
2408 CharacterIterator ci) {
2409 return (GlyphVector) new StandardGlyphVector(this , ci, frc);
2410 }
2411
2412 /**
2413 * Creates a {@link java.awt.font.GlyphVector GlyphVector} by
2414 * mapping characters to glyphs one-to-one based on the
2415 * Unicode cmap in this <code>Font</code>. This method does no other
2416 * processing besides the mapping of glyphs to characters. This
2417 * means that this method is not useful for some scripts, such
2418 * as Arabic, Hebrew, Thai, and Indic, that require reordering,
2419 * shaping, or ligature substitution.
2420 * @param frc the specified <code>FontRenderContext</code>
2421 * @param glyphCodes the specified integer array
2422 * @return a new <code>GlyphVector</code> created with the
2423 * specified integer array and the specified
2424 * <code>FontRenderContext</code>.
2425 */
2426 public GlyphVector createGlyphVector(FontRenderContext frc,
2427 int[] glyphCodes) {
2428 return (GlyphVector) new StandardGlyphVector(this , glyphCodes,
2429 frc);
2430 }
2431
2432 /**
2433 * Returns a new <code>GlyphVector</code> object, performing full
2434 * layout of the text if possible. Full layout is required for
2435 * complex text, such as Arabic or Hindi. Support for different
2436 * scripts depends on the font and implementation.
2437 * <p>
2438 * Layout requires bidi analysis, as performed by
2439 * <code>Bidi</code>, and should only be performed on text that
2440 * has a uniform direction. The direction is indicated in the
2441 * flags parameter,by using LAYOUT_RIGHT_TO_LEFT to indicate a
2442 * right-to-left (Arabic and Hebrew) run direction, or
2443 * LAYOUT_LEFT_TO_RIGHT to indicate a left-to-right (English)
2444 * run direction.
2445 * <p>
2446 * In addition, some operations, such as Arabic shaping, require
2447 * context, so that the characters at the start and limit can have
2448 * the proper shapes. Sometimes the data in the buffer outside
2449 * the provided range does not have valid data. The values
2450 * LAYOUT_NO_START_CONTEXT and LAYOUT_NO_LIMIT_CONTEXT can be
2451 * added to the flags parameter to indicate that the text before
2452 * start, or after limit, respectively, should not be examined
2453 * for context.
2454 * <p>
2455 * All other values for the flags parameter are reserved.
2456 *
2457 * @param frc the specified <code>FontRenderContext</code>
2458 * @param text the text to layout
2459 * @param start the start of the text to use for the <code>GlyphVector</code>
2460 * @param limit the limit of the text to use for the <code>GlyphVector</code>
2461 * @param flags control flags as described above
2462 * @return a new <code>GlyphVector</code> representing the text between
2463 * start and limit, with glyphs chosen and positioned so as to best represent
2464 * the text
2465 * @throws ArrayIndexOutOfBoundsException if start or limit is
2466 * out of bounds
2467 * @see java.text.Bidi
2468 * @see #LAYOUT_LEFT_TO_RIGHT
2469 * @see #LAYOUT_RIGHT_TO_LEFT
2470 * @see #LAYOUT_NO_START_CONTEXT
2471 * @see #LAYOUT_NO_LIMIT_CONTEXT
2472 * @since 1.4
2473 */
2474 public GlyphVector layoutGlyphVector(FontRenderContext frc,
2475 char[] text, int start, int limit, int flags) {
2476
2477 GlyphLayout gl = GlyphLayout.get(null); // !!! no custom layout engines
2478 StandardGlyphVector gv = gl.layout(this , frc, text, start,
2479 limit - start, flags, null);
2480 GlyphLayout.done(gl);
2481 return gv;
2482 }
2483
2484 /**
2485 * A flag to layoutGlyphVector indicating that text is left-to-right as
2486 * determined by Bidi analysis.
2487 */
2488 public static final int LAYOUT_LEFT_TO_RIGHT = 0;
2489
2490 /**
2491 * A flag to layoutGlyphVector indicating that text is right-to-left as
2492 * determined by Bidi analysis.
2493 */
2494 public static final int LAYOUT_RIGHT_TO_LEFT = 1;
2495
2496 /**
2497 * A flag to layoutGlyphVector indicating that text in the char array
2498 * before the indicated start should not be examined.
2499 */
2500 public static final int LAYOUT_NO_START_CONTEXT = 2;
2501
2502 /**
2503 * A flag to layoutGlyphVector indicating that text in the char array
2504 * after the indicated limit should not be examined.
2505 */
2506 public static final int LAYOUT_NO_LIMIT_CONTEXT = 4;
2507
2508 private static void applyTransform(AffineTransform trans,
2509 AttributeValues values) {
2510 if (trans == null) {
2511 throw new IllegalArgumentException(
2512 "transform must not be null");
2513 }
2514 values.setTransform(trans);
2515 }
2516
2517 private static void applyStyle(int style, AttributeValues values) {
2518 // WEIGHT_BOLD, WEIGHT_REGULAR
2519 values.setWeight((style & BOLD) != 0 ? 2f : 1f);
2520 // POSTURE_OBLIQUE, POSTURE_REGULAR
2521 values.setPosture((style & ITALIC) != 0 ? .2f : 0f);
2522 }
2523
2524 /*
2525 * Initialize JNI field and method IDs
2526 */
2527 private static native void initIDs();
2528 }
|