KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > awt > Font


1 /*
2  * @(#)Font.java 1.201 05/11/02
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.awt;
9
10 import java.awt.font.FontRenderContext JavaDoc;
11 import java.awt.font.GlyphVector JavaDoc;
12 import java.awt.font.LineMetrics JavaDoc;
13 import java.awt.font.TextAttribute JavaDoc;
14 import java.awt.font.TextLayout JavaDoc;
15 import java.awt.font.TransformAttribute JavaDoc;
16 import java.awt.geom.AffineTransform JavaDoc;
17 import java.awt.geom.Rectangle2D JavaDoc;
18 import java.awt.peer.FontPeer;
19 import java.io.*;
20 import java.lang.ref.SoftReference JavaDoc;
21 import java.text.AttributedCharacterIterator.Attribute;
22 import java.text.CharacterIterator JavaDoc;
23 import java.text.StringCharacterIterator JavaDoc;
24 import java.util.HashMap JavaDoc;
25 import java.util.Hashtable JavaDoc;
26 import java.util.Locale JavaDoc;
27 import java.util.Map JavaDoc;
28 import sun.font.StandardGlyphVector;
29 import sun.java2d.FontSupport;
30
31 import sun.font.Font2D;
32 import sun.font.Font2DHandle;
33 import sun.font.FontManager;
34 import sun.font.GlyphLayout;
35 import sun.font.FontLineMetrics;
36 import sun.font.CoreMetrics;
37
38 /**
39  * The <code>Font</code> class represents fonts, which are used to
40  * render text in a visible way.
41  * A font provides the information needed to map sequences of
42  * <em>characters</em> to sequences of <em>glyphs</em>
43  * and to render sequences of glyphs on <code>Graphics</code> and
44  * <code>Component</code> objects.
45  *
46  * <h4>Characters and Glyphs</h4>
47  *
48  * A <em>character</em> is a symbol that represents an item such as a letter,
49  * a digit, or punctuation in an abstract way. For example, <code>'g'</code>,
50  * <font size=-1>LATIN SMALL LETTER G</font>, is a character.
51  * <p>
52  * A <em>glyph</em> is a shape used to render a character or a sequence of
53  * characters. In simple writing systems, such as Latin, typically one glyph
54  * represents one character. In general, however, characters and glyphs do not
55  * have one-to-one correspondence. For example, the character '&aacute;'
56  * <font size=-1>LATIN SMALL LETTER A WITH ACUTE</font>, can be represented by
57  * two glyphs: one for 'a' and one for '&acute;'. On the other hand, the
58  * two-character string "fi" can be represented by a single glyph, an
59  * "fi" ligature. In complex writing systems, such as Arabic or the South
60  * and South-East Asian writing systems, the relationship between characters
61  * and glyphs can be more complicated and involve context-dependent selection
62  * of glyphs as well as glyph reordering.
63  *
64  * A font encapsulates the collection of glyphs needed to render a selected set
65  * of characters as well as the tables needed to map sequences of characters to
66  * corresponding sequences of glyphs.
67  *
68  * <h4>Physical and Logical Fonts</h4>
69  *
70  * The Java 2 platform distinguishes between two kinds of fonts:
71  * <em>physical</em> fonts and <em>logical</em> fonts.
72  * <p>
73  * <em>Physical</em> fonts are the actual font libraries containing glyph data
74  * and tables to map from character sequences to glyph sequences, using a font
75  * technology such as TrueType or PostScript Type 1.
76  * All implementations of the Java 2 platform must support TrueType fonts;
77  * support for other font technologies is implementation dependent.
78  * Physical fonts may use names such as Helvetica, Palatino, HonMincho, or
79  * any number of other font names.
80  * Typically, each physical font supports only a limited set of writing
81  * systems, for example, only Latin characters or only Japanese and Basic
82  * Latin.
83  * The set of available physical fonts varies between configurations.
84  * Applications that require specific fonts can bundle them and instantiate
85  * them using the {@link #createFont createFont} method.
86  * <p>
87  * <em>Logical</em> fonts are the five font families defined by the Java
88  * platform which must be supported by any Java runtime environment:
89  * Serif, SansSerif, Monospaced, Dialog, and DialogInput.
90  * These logical fonts are not actual font libraries. Instead, the logical
91  * font names are mapped to physical fonts by the Java runtime environment.
92  * The mapping is implementation and usually locale dependent, so the look
93  * and the metrics provided by them vary.
94  * Typically, each logical font name maps to several physical fonts in order to
95  * cover a large range of characters.
96  * <p>
97  * Peered AWT components, such as {@link Label Label} and
98  * {@link TextField TextField}, can only use logical fonts.
99  * <p>
100  * For a discussion of the relative advantages and disadvantages of using
101  * physical or logical fonts, see the
102  * <a HREF="http://java.sun.com/j2se/corejava/intl/reference/faqs/index.html#desktop-rendering">Internationalization FAQ</a>
103  * document.
104  *
105  * <h4>Font Faces and Names</h4>
106  *
107  * A <code>Font</code>
108  * can have many faces, such as heavy, medium, oblique, gothic and
109  * regular. All of these faces have similar typographic design.
110  * <p>
111  * There are three different names that you can get from a
112  * <code>Font</code> object. The <em>logical font name</em> is simply the
113  * name that was used to construct the font.
114  * The <em>font face name</em>, or just <em>font name</em> for
115  * short, is the name of a particular font face, like Helvetica Bold. The
116  * <em>family name</em> is the name of the font family that determines the
117  * typographic design across several faces, like Helvetica.
118  * <p>
119  * The <code>Font</code> class represents an instance of a font face from
120  * a collection of font faces that are present in the system resources
121  * of the host system. As examples, Arial Bold and Courier Bold Italic
122  * are font faces. There can be several <code>Font</code> objects
123  * associated with a font face, each differing in size, style, transform
124  * and font features.
125  * The {@link GraphicsEnvironment#getAllFonts() getAllFonts} method
126  * of the <code>GraphicsEnvironment</code> class returns an
127  * array of all font faces available in the system. These font faces are
128  * returned as <code>Font</code> objects with a size of 1, identity
129  * transform and default font features. These
130  * base fonts can then be used to derive new <code>Font</code> objects
131  * with varying sizes, styles, transforms and font features via the
132  * <code>deriveFont</code> methods in this class.
133  *
134  * @version 1.201, 11/02/05
135  */

136 public class Font implements java.io.Serializable JavaDoc
137 {
138    
139     static {
140         /* ensure that the necessary native libraries are loaded */
141     Toolkit.loadLibraries();
142         initIDs();
143     }
144
145     /**
146      * A map of font attributes available in this font.
147      * Attributes include things like ligatures and glyph substitution.
148      *
149      * @serial
150      * @see #getAttributes()
151      */

152     private Hashtable JavaDoc fRequestedAttributes;
153     
154     private static final Map JavaDoc EMPTY_MAP = new Hashtable JavaDoc(5, (float)0.9);
155     private static final TransformAttribute JavaDoc IDENT_TX_ATTRIBUTE =
156     new TransformAttribute JavaDoc(new AffineTransform JavaDoc());
157
158     /*
159      * Constants to be used for styles. Can be combined to mix
160      * styles.
161      */

162
163     /**
164      * The plain style constant.
165      */

166     public static final int PLAIN = 0;
167
168     /**
169      * The bold style constant. This can be combined with the other style
170      * constants (except PLAIN) for mixed styles.
171      */

172     public static final int BOLD = 1;
173
174     /**
175      * The italicized style constant. This can be combined with the other
176      * style constants (except PLAIN) for mixed styles.
177      */

178     public static final int ITALIC = 2;
179
180     /**
181      * The baseline used in most Roman scripts when laying out text.
182      */

183     public static final int ROMAN_BASELINE = 0;
184
185     /**
186      * The baseline used in ideographic scripts like Chinese, Japanese,
187      * and Korean when laying out text.
188      */

189     public static final int CENTER_BASELINE = 1;
190
191     /**
192      * The baseline used in Devanigiri and similar scripts when laying
193      * out text.
194      */

195     public static final int HANGING_BASELINE = 2;
196
197     /**
198      * Identify a font resource of type TRUETYPE.
199      * Used to specify a TrueType font resource to the
200      * {@link #createFont} method.
201      * @since 1.3
202      */

203
204     public static final int TRUETYPE_FONT = 0;
205
206     /**
207      * Identify a font resource of type TYPE1.
208      * Used to specify a Type1 font resource to the
209      * {@link #createFont} method.
210      * @since 1.5
211      */

212     public static final int TYPE1_FONT = 1;
213
214     /**
215      * The logical name of this <code>Font</code>, as passed to the
216      * constructor.
217      * @since JDK1.0
218      *
219      * @serial
220      * @see #getName
221      */

222     protected String JavaDoc name;
223
224     /**
225      * The style of this <code>Font</code>, as passed to the constructor.
226      * This style can be PLAIN, BOLD, ITALIC, or BOLD+ITALIC.
227      * @since JDK1.0
228      *
229      * @serial
230      * @see #getStyle()
231      */

232     protected int style;
233
234     /**
235      * The point size of this <code>Font</code>, rounded to integer.
236      * @since JDK1.0
237      *
238      * @serial
239      * @see #getSize()
240      */

241     protected int size;
242
243     /**
244      * The point size of this <code>Font</code> in <code>float</code>.
245      *
246      * @serial
247      * @see #getSize()
248      * @see #getSize2D()
249      */

250     protected float pointSize;
251
252     /**
253      * The platform specific font information.
254      */

255     private transient FontPeer peer;
256     private transient long pData; // native JDK1.1 font pointer
257
private transient Font2DHandle font2DHandle;
258     private transient int superscript;
259     private transient float width = 1f;
260
261     /*
262      * If the origin of a Font is a created font then this attribute
263      * must be set on all derived fonts too.
264      */

265     private transient boolean createdFont = false;
266
267     // cached values - performance
268
private transient double[] matrix;
269     private transient boolean nonIdentityTx;
270
271     private static final AffineTransform JavaDoc identityTx = new AffineTransform JavaDoc();
272     /*
273      * JDK 1.1 serialVersionUID
274      */

275     private static final long serialVersionUID = -4206021311591459213L;
276
277     /**
278      * Gets the peer of this <code>Font</code>.
279      * @return the peer of the <code>Font</code>.
280      * @since JDK1.1
281      * @deprecated Font rendering is now platform independent.
282      */

283     @Deprecated JavaDoc
284     public FontPeer getPeer(){
285     return getPeer_NoClientCode();
286     }
287     // NOTE: This method is called by privileged threads.
288
// We implement this functionality in a package-private method
289
// to insure that it cannot be overridden by client subclasses.
290
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
291
final FontPeer getPeer_NoClientCode() {
292         if(peer == null) {
293             Toolkit JavaDoc tk = Toolkit.getDefaultToolkit();
294             this.peer = tk.getFontPeer(name, style);
295         }
296         return peer;
297     }
298
299     /* create this map only when requested - which may be rarely */
300     private Hashtable JavaDoc getRequestedAttributes() {
301     if (fRequestedAttributes == null) {
302         fRequestedAttributes = new Hashtable JavaDoc(7, (float)0.9);
303             fRequestedAttributes.put(TextAttribute.TRANSFORM,
304                      IDENT_TX_ATTRIBUTE);
305             fRequestedAttributes.put(TextAttribute.FAMILY, name);
306             fRequestedAttributes.put(TextAttribute.SIZE, new Float JavaDoc(size));
307         fRequestedAttributes.put(TextAttribute.WEIGHT,
308                      (style & BOLD) != 0 ?
309                      TextAttribute.WEIGHT_BOLD :
310                      TextAttribute.WEIGHT_REGULAR);
311         fRequestedAttributes.put(TextAttribute.POSTURE,
312                      (style & ITALIC) != 0 ?
313                      TextAttribute.POSTURE_OBLIQUE :
314                      TextAttribute.POSTURE_REGULAR);
315             fRequestedAttributes.put(TextAttribute.SUPERSCRIPT,
316                                      new Integer JavaDoc(superscript));
317             fRequestedAttributes.put(TextAttribute.WIDTH,
318                                      new Float JavaDoc(width));
319     }
320     return fRequestedAttributes;
321     }
322
323     private void initializeFont(Hashtable JavaDoc attributes) {
324         if (attributes != null) {
325         Object JavaDoc obj = attributes.get(TextAttribute.TRANSFORM);
326         if (obj instanceof TransformAttribute JavaDoc) {
327         nonIdentityTx = !((TransformAttribute JavaDoc)obj).isIdentity();
328         } else if (obj instanceof AffineTransform JavaDoc) {
329         nonIdentityTx = !((AffineTransform JavaDoc)obj).isIdentity();
330         }
331
332             obj = attributes.get(TextAttribute.SUPERSCRIPT);
333             if (obj instanceof Integer JavaDoc) {
334                 superscript = ((Integer JavaDoc)obj).intValue();
335
336                 // !!! always synthesize superscript
337
nonIdentityTx |= superscript != 0;
338             }
339
340             obj = attributes.get(TextAttribute.WIDTH);
341             if (obj instanceof Integer JavaDoc) {
342                 width = ((Float JavaDoc)obj).floatValue();
343
344                 // !!! always synthesize width
345
nonIdentityTx |= width != 1;
346             }
347         }
348     }
349
350     private Font2D getFont2D() {
351     if (FontManager.usingPerAppContextComposites &&
352         font2DHandle != null &&
353         font2DHandle.font2D instanceof sun.font.CompositeFont &&
354         ((sun.font.CompositeFont)(font2DHandle.font2D)).isStdComposite()) {
355         return FontManager.findFont2D(name, style,
356                       FontManager.LOGICAL_FALLBACK);
357     } else if (font2DHandle == null) {
358         font2DHandle =
359         FontManager.findFont2D(name, style,
360                        FontManager.LOGICAL_FALLBACK).handle;
361     }
362     /* Do not cache the de-referenced font2D. It must be explicitly
363      * de-referenced to pick up a valid font in the event that the
364      * original one is marked invalid
365      */

366     return font2DHandle.font2D;
367     }
368
369     /*
370      * If this font was created by "createFont" return its handle,
371      * else return null. created fonts always have a non-null handle.
372      * The test for CompositeFont is because the boolean "createdFont"
373      * is overloaded to indicate any font that needs to copy its handle
374      * and that doesn't apply to true created fonts.
375      */

376     private Font2DHandle getFont2DHandleForCreatedFont() {
377         if (font2DHandle != null && createdFont &&
378             !(font2DHandle.font2D instanceof sun.font.CompositeFont)) {
379             return font2DHandle;
380         } else {
381             return null;
382         }
383     }
384
385     /**
386      * Creates a new <code>Font</code> from the specified name, style and
387      * point size.
388      * <p>
389      * The font name can be a font face name or a font family name.
390      * It is used together with the style to find an appropriate font face.
391      * When a font family name is specified, the style argument is used to
392      * select the most appropriate face from the family. When a font face
393      * name is specified, the face's style and the style argument are
394      * merged to locate the best matching font from the same family.
395      * For example if face name "Arial Bold" is specified with style
396      * <code>Font.ITALIC</code>, the font system looks for a face in the
397      * "Arial" family that is bold and italic, and may associate the font
398      * instance with the physical font face "Arial Bold Italic".
399      * The style argument is merged with the specified face's style, not
400      * added or subtracted.
401      * This means, specifying a bold face and a bold style does not
402      * double-embolden the font, and specifying a bold face and a plain
403      * style does not lighten the font.
404      * <p>
405      * If no face for the requested style can be found, the font system
406      * may apply algorithmic styling to achieve the desired style.
407      * For example, if <code>ITALIC</code> is requested, but no italic
408      * face is available, glyphs from the plain face may be algorithmically
409      * obliqued (slanted).
410      * <p>
411      * Font name lookup is case insensitive, using the case folding
412      * rules of the US locale.
413      *
414      * @param name the font name. This can be a font face name or a font
415      * family name, and may represent either a logical font or a physical
416      * font found in this <code>GraphicsEnvironment</code>.
417      * The family names for logical fonts are: Dialog, DialogInput,
418      * Monospaced, Serif, or SansSerif. If <code>name</code> is
419      * <code>null</code>, the <em>logical font name</em> of the new
420      * <code>Font</code> as returned by <code>getName()</code>is set to
421      * the name "Default".
422      * @param style the style constant for the <code>Font</code>
423      * The style argument is an integer bitmask that may
424      * be PLAIN, or a bitwise union of BOLD and/or ITALIC
425      * (for example, ITALIC or BOLD|ITALIC).
426      * If the style argument does not conform to one of the expected
427      * integer bitmasks then the style is set to PLAIN.
428      * @param size the point size of the <code>Font</code>
429      * @see GraphicsEnvironment#getAllFonts
430      * @see GraphicsEnvironment#getAvailableFontFamilyNames
431      * @since JDK1.0
432      */

433     public Font(String JavaDoc name, int style, int size) {
434     this.name = (name != null) ? name : "Default";
435     this.style = (style & ~0x03) == 0 ? style : 0;
436     this.size = size;
437         this.pointSize = size;
438     }
439
440     private Font(String JavaDoc name, int style, float sizePts) {
441     this.name = (name != null) ? name : "Default";
442     this.style = (style & ~0x03) == 0 ? style : 0;
443     this.size = (int)(sizePts + 0.5);
444         this.pointSize = sizePts;
445     }
446
447     /* used to implement Font.createFont */
448     private Font(File fontFile, int fontFormat, boolean isCopy)
449         throws FontFormatException JavaDoc {
450     this.createdFont = true;
451     /* Font2D instances created by this method track their font file
452      * so that when the Font2D is GC'd it can also remove the file.
453      */

454     this.font2DHandle =
455         FontManager.createFont2D(fontFile, fontFormat, isCopy).handle;
456     this.name = this.font2DHandle.font2D.getFontName(Locale.getDefault());
457     this.style = Font.PLAIN;
458     this.size = 1;
459     this.pointSize = 1f;
460     }
461
462     private Font(Map JavaDoc attributes, boolean created, Font2DHandle handle) {
463     this.createdFont = created;
464     /* Fonts created from a stream will use the same font2D instance
465      * as the parent.
466      */

467     if (created) {
468         this.font2DHandle = handle;
469     }
470     initFromMap(attributes);
471     }
472
473     /**
474      * Creates a new <code>Font</code> with the specified attributes.
475      * This <code>Font</code> only recognizes keys defined in
476      * {@link TextAttribute} as attributes. If <code>attributes</code>
477      * is <code>null</code>, a new <code>Font</code> is initialized
478      * with default attributes.
479      * @param attributes the attributes to assign to the new
480      * <code>Font</code>, or <code>null</code>
481      */

482     public Font(Map JavaDoc<? extends Attribute JavaDoc, ?> attributes) {
483     initFromMap(attributes);
484     }
485
486
487     private void initFromMap(Map JavaDoc attributes) {
488     this.name = "Dialog";
489         this.pointSize = 12;
490         this.size = 12;
491
492         if((attributes != null) &&
493            (!attributes.equals(EMPTY_MAP)))
494         {
495             Object JavaDoc obj;
496             fRequestedAttributes = new Hashtable JavaDoc(attributes);
497             if ((obj = attributes.get(TextAttribute.FAMILY)) != null) {
498                 this.name = (String JavaDoc)obj;
499             }
500
501             if ((obj = attributes.get(TextAttribute.WEIGHT)) != null) {
502                 if(obj.equals(TextAttribute.WEIGHT_BOLD)) {
503                     this.style |= BOLD;
504                 }
505             }
506
507             if ((obj = attributes.get(TextAttribute.POSTURE)) != null) {
508                 if(obj.equals(TextAttribute.POSTURE_OBLIQUE)) {
509                     this.style |= ITALIC;
510                 }
511             }
512
513             if ((obj = attributes.get(TextAttribute.SIZE)) != null) {
514                 this.pointSize = ((Float JavaDoc)obj).floatValue();
515                 this.size = (int)(this.pointSize + 0.5);
516             }
517
518             if ((obj = attributes.get(TextAttribute.TRANSFORM)) != null) {
519         if (obj instanceof TransformAttribute JavaDoc) {
520             nonIdentityTx = !((TransformAttribute JavaDoc)obj).isIdentity();
521         } else if (obj instanceof AffineTransform JavaDoc) {
522             nonIdentityTx = !((AffineTransform JavaDoc)obj).isIdentity();
523         }
524         }
525
526             if ((obj = attributes.get(TextAttribute.SUPERSCRIPT)) != null) {
527                 if (obj instanceof Integer JavaDoc) {
528                     superscript = ((Integer JavaDoc)obj).intValue();
529                     nonIdentityTx |= superscript != 0;
530                 }
531             }
532
533             if ((obj = attributes.get(TextAttribute.WIDTH)) != null) {
534                 if (obj instanceof Float JavaDoc) {
535                     width = ((Float JavaDoc)obj).floatValue();
536                     nonIdentityTx |= width != 1;
537                 }
538             }
539         }
540     }
541
542      /**
543      * Returns a <code>Font</code> appropriate to this attribute set.
544      *
545      * @param attributes the attributes to assign to the new
546      * <code>Font</code>
547      * @return a new <code>Font</code> created with the specified
548      * attributes
549      * @since 1.2
550      * @see java.awt.font.TextAttribute
551      */

552     public static Font JavaDoc getFont(Map JavaDoc<? extends Attribute JavaDoc, ?> attributes) {
553         Font JavaDoc font = (Font JavaDoc)attributes.get(TextAttribute.FONT);
554         if (font != null) {
555             return font;
556         }
557
558     return get(new Key(attributes));
559     }
560
561     private static SoftReference JavaDoc cacheRef = new SoftReference JavaDoc(new HashMap JavaDoc());
562     private static Font JavaDoc get(Key key) {
563     Font JavaDoc f = null;
564     Map JavaDoc cache = (Map JavaDoc)cacheRef.get();
565     if (cache == null) {
566         cache = new HashMap JavaDoc();
567         cacheRef = new SoftReference JavaDoc(cache);
568     } else {
569         f = (Font JavaDoc)cache.get(key);
570     }
571
572     if (f == null) {
573         f = new Font JavaDoc(key.attrs);
574         cache.put(key, f);
575     }
576
577     return f;
578     }
579
580     // ideally we would construct a font directly from a key, and not
581
// bother to keep the map around for this. That ought to be a bit
582
// faster than picking out the params from the Map again, but the
583
// cache ought to hide this overhead, so I'll skip it for now.
584

585     private static class Key {
586     String JavaDoc family = "Dialog"; // defaults chosen to match Font implementation
587
float weight = 1.0f;
588     float posture = 0.0f;
589     float size = 12.0f;
590         int superscript = 0;
591         float width = 1.0f;
592     double[] txdata = null; // identity
593

594     Map JavaDoc attrs;
595     int hashCode = 0;
596
597     Key(Map JavaDoc map) {
598         attrs = map;
599
600         Object JavaDoc o = map.get(TextAttribute.FAMILY);
601         if (o != null) {
602         family = (String JavaDoc)o;
603         }
604         hashCode = family.hashCode();
605
606         o = map.get(TextAttribute.WEIGHT);
607         if (o != null && o != TextAttribute.WEIGHT_REGULAR) {
608         // ugh, force to the only values we understand
609
// weight is either bold, or it's not...
610
float xweight = ((Float JavaDoc)o).floatValue();
611         if (xweight == TextAttribute.WEIGHT_BOLD.floatValue()) {
612             weight = xweight;
613             hashCode = (hashCode << 3) ^ Float.floatToIntBits(weight);
614         }
615         }
616
617         o = map.get(TextAttribute.POSTURE);
618         if (o != null && o != TextAttribute.POSTURE_REGULAR) {
619         // ugh, same problem as with weight
620
float xposture = ((Float JavaDoc)o).floatValue();
621         if (xposture == TextAttribute.POSTURE_OBLIQUE.floatValue()) {
622             posture = xposture;
623             hashCode = (hashCode << 3) ^ Float.floatToIntBits(posture);
624         }
625         }
626
627         o = map.get(TextAttribute.SIZE);
628         if (o != null) {
629         size = ((Float JavaDoc)o).floatValue();
630         if (size != 12.0f) {
631             hashCode = (hashCode << 3) ^ Float.floatToIntBits(size);
632         }
633         }
634
635         o = map.get(TextAttribute.TRANSFORM);
636         if (o != null) {
637         AffineTransform JavaDoc tx = null;
638         if (o instanceof TransformAttribute JavaDoc) {
639             TransformAttribute JavaDoc ta = (TransformAttribute JavaDoc)o;
640             if (!ta.isIdentity()) {
641             tx = ta.getTransform();
642             }
643         } else if (o instanceof AffineTransform JavaDoc) {
644             AffineTransform JavaDoc at = (AffineTransform JavaDoc)o;
645             if (!at.isIdentity()) {
646             tx = at;
647             }
648         }
649         if (tx != null) {
650             txdata = new double[6];
651             tx.getMatrix(txdata);
652             hashCode = (hashCode << 3) ^ new Double JavaDoc(txdata[0]).hashCode();
653         }
654         }
655
656             o = map.get(TextAttribute.SUPERSCRIPT);
657             if (o != null) {
658                 if (o instanceof Integer JavaDoc) {
659                     superscript = ((Integer JavaDoc)o).intValue();
660                     hashCode = hashCode << 3 ^ superscript;
661                 }
662             }
663
664             o = map.get(TextAttribute.WIDTH);
665             if (o != null) {
666                 if (o instanceof Float JavaDoc) {
667                     width = ((Float JavaDoc)o).floatValue();
668                     hashCode = hashCode << 3 ^ Float.floatToIntBits(width);
669                 }
670             }
671     }
672
673     public int hashCode() {
674         return hashCode;
675     }
676
677     public boolean equals(Object JavaDoc rhs) {
678         Key rhskey = (Key)rhs;
679         if (this.hashCode == rhskey.hashCode &&
680         this.size == rhskey.size &&
681         this.weight == rhskey.weight &&
682         this.posture == rhskey.posture &&
683                 this.superscript == rhskey.superscript &&
684                 this.width == rhskey.width &&
685         this.family.equals(rhskey.family) &&
686         ((this.txdata == null) == (rhskey.txdata == null))) {
687         
688         if (this.txdata != null) {
689             for (int i = 0; i < this.txdata.length; ++i) {
690             if (this.txdata[i] != rhskey.txdata[i]) {
691                 return false;
692             }
693             }
694         }
695         return true;
696         }
697         return false;
698     }
699     }
700     
701
702   /**
703    * Returns a new <code>Font</code> using the specified font type
704    * and input data. The new <code>Font</code> is
705    * created with a point size of 1 and style {@link #PLAIN PLAIN}.
706    * This base font can then be used with the <code>deriveFont</code>
707    * methods in this class to derive new <code>Font</code> objects with
708    * varying sizes, styles, transforms and font features. This
709    * method does not close the {@link InputStream}.
710    * @param fontFormat the type of the <code>Font</code>, which is
711    * {@link #TRUETYPE_FONT TRUETYPE_FONT} if a TrueType resource is specified.
712    * or {@link #TYPE1_FONT TYPE1_FONT} if a Type 1 resource is specified.
713    * @param fontStream an <code>InputStream</code> object representing the
714    * input data for the font.
715    * @return a new <code>Font</code> created with the specified font type.
716    * @throws IllegalArgumentException if <code>fontFormat</code> is not
717    * <code>TRUETYPE_FONT</code>or<code>TYPE1_FONT</code>.
718    * @throws FontFormatException if the <code>fontStream</code> data does
719    * not contain the required font tables for the specified format.
720    * @throws IOException if the <code>fontStream</code>
721    * cannot be completely read.
722    * @since 1.3
723    */

724     public static Font JavaDoc createFont(int fontFormat, InputStream fontStream)
725     throws java.awt.FontFormatException JavaDoc, java.io.IOException JavaDoc {
726
727     if (fontFormat != Font.TRUETYPE_FONT &&
728         fontFormat != Font.TYPE1_FONT) {
729         throw new IllegalArgumentException JavaDoc ("font format not recognized");
730     }
731     final InputStream fStream = fontStream;
732     Object JavaDoc ret = java.security.AccessController.doPrivileged(
733        new java.security.PrivilegedAction JavaDoc() {
734           public Object JavaDoc run() {
735           File tFile = null;
736           try {
737               tFile = File.createTempFile("+~JF", ".tmp", null);
738               tFile.deleteOnExit();
739               BufferedInputStream inStream =
740               new BufferedInputStream(fStream);
741               FileOutputStream outStream = new FileOutputStream(tFile);
742               int bytesRead = 0;
743               int bufSize = 8192;
744               byte [] buf = new byte[bufSize];
745               while (bytesRead != -1) {
746               bytesRead = inStream.read(buf, 0, bufSize);
747               if (bytesRead != -1) {
748                   outStream.write(buf, 0, bytesRead);
749               }
750               }
751               /* don't close the input stream */
752               outStream.close();
753           } catch (IOException e) {
754               return e;
755           }
756           return tFile;
757           }
758       });
759
760     if (ret instanceof File) {
761         return new Font JavaDoc((File)ret, fontFormat, true);
762     } else if (ret instanceof IOException) {
763         throw (IOException)ret;
764     } else {
765         throw new FontFormatException JavaDoc("Couldn't access font stream");
766     }
767     }
768
769     /**
770      * Returns a new <code>Font</code> using the specified font type
771      * and the specified font file. The new <code>Font</code> is
772      * created with a point size of 1 and style {@link #PLAIN PLAIN}.
773      * This base font can then be used with the <code>deriveFont</code>
774      * methods in this class to derive new <code>Font</code> objects with
775      * varying sizes, styles, transforms and font features.
776      * @param fontFormat the type of the <code>Font</code>, which is
777      * {@link #TRUETYPE_FONT TRUETYPE_FONT} if a TrueType resource is
778      * specified or {@link #TYPE1_FONT TYPE1_FONT} if a Type 1 resource is
779      * specified.
780      * So long as the returned font, or its derived fonts are referenced
781      * the implementation may continue to access <code>fontFile</code>
782      * to retrieve font data. Thus the results are undefined if the file
783      * is changed, or becomes inaccessible.
784      * @param fontFile a <code>File</code> object representing the
785      * input data for the font.
786      * @return a new <code>Font</code> created with the specified font type.
787      * @throws IllegalArgumentException if <code>fontFormat</code> is not
788      * <code>TRUETYPE_FONT</code>or<code>TYPE1_FONT</code>.
789      * @throws NullPointerException if <code>fontFile</code> is null.
790      * @throws IOException if the <code>fontFile</code> cannot be read.
791      * @throws FontFormatException if <code>fontFile</code> does
792      * not contain the required font tables for the specified format.
793      * @throws SecurityException if the executing code does not have
794      * permission to read from the file.
795      * @since 1.5
796      */

797     public static Font JavaDoc createFont(int fontFormat, File fontFile)
798     throws java.awt.FontFormatException JavaDoc, java.io.IOException JavaDoc {
799     if (fontFormat != Font.TRUETYPE_FONT &&
800         fontFormat != Font.TYPE1_FONT) {
801         throw new IllegalArgumentException JavaDoc ("font format not recognized");
802     }
803     SecurityManager JavaDoc sm = System.getSecurityManager();
804     if (sm != null) {
805         FilePermission filePermission =
806             new FilePermission(fontFile.getPath(), "read");
807         sm.checkPermission(filePermission);
808     }
809     if (!fontFile.canRead()) {
810         throw new IOException("Can't read " + fontFile);
811     }
812     return new Font JavaDoc(fontFile, fontFormat, false);
813     }
814
815     /**
816      * Returns a copy of the transform associated with this
817      * <code>Font</code>.
818      * @return an {@link AffineTransform} object representing the
819      * transform attribute of this <code>Font</code> object.
820      */

821     public AffineTransform JavaDoc getTransform() {
822     /* The most common case is the identity transform. Most callers
823      * should call isTransformed() first, to decide if they need to
824      * get the transform, but some may not. Here we check to see
825      * if we have a nonidentity transform, and only do the work to
826      * fetch and/or compute it if so, otherwise we return a new
827      * identity transform.
828      *
829      * Note that the transform is _not_ necessarily the same as
830      * the transform passed in as an Attribute in a Map, as the
831      * transform returned will also reflect the effects of WIDTH and
832      * SUPERSCRIPT attributes. Clients who want the actual transform
833      * need to call getRequestedAttributes.
834      */

835     if (nonIdentityTx) {
836             AffineTransform JavaDoc at = null;
837         Object JavaDoc obj = getRequestedAttributes().get(TextAttribute.TRANSFORM);
838         if (obj != null) {
839         if( obj instanceof TransformAttribute JavaDoc ){
840             at = ((TransformAttribute JavaDoc)obj).getTransform();
841         }
842         else {
843             if ( obj instanceof AffineTransform JavaDoc){
844             at = new AffineTransform JavaDoc((AffineTransform JavaDoc)obj);
845             }
846         }
847         } else {
848                 at = new AffineTransform JavaDoc();
849             }
850             
851