Source Code Cross Referenced for Font.java in  » JDK-Core » AWT » java » awt » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. JDK Core
2. JDK Modules
3. JDK Modules com.sun
4. JDK Modules com.sun.java
5. JDK Modules Platform
6. JDK Modules sun
7. Open Source Build
8. Open Source Graphic Library
9. Open Source IDE Eclipse
10. Open Source J2EE
11. Open Source JDBC Driver
12. Open Source Library
13. Open Source Library Database
14. Open Source Net
15. Open Source Script
16. Science
17. Security
18. Sevlet Container
19. SUN GlassFish
20. Swing Library
21. Web Services apache cxf 2.0.1
22. Web Services AXIS2
23. XML
Microsoft Office Word 2007 Tutorial
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
C# / C Sharp
C# / CSharp Tutorial
ASP.Net
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
PHP
Python
SQL Server / T-SQL
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Java Source Code / Java Documentation » JDK Core » AWT » java.awt 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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 '&aacute;'
0081:         * <font size=-1>LATIN SMALL LETTER A WITH ACUTE</font>, can be represented by
0082:         * two glyphs: one for 'a' and one for '&acute;'. 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:        }
w_ww_.ja___va2_s_._c_o_m
Home | Contact Us
Copyright 2003 - 08 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.