1. /*
  2. * @(#)Font.java 1.200 04/07/20
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.awt;
  8. import java.awt.font.FontRenderContext;
  9. import java.awt.font.GlyphVector;
  10. import java.awt.font.LineMetrics;
  11. import java.awt.font.TextAttribute;
  12. import java.awt.font.TextLayout;
  13. import java.awt.font.TransformAttribute;
  14. import java.awt.geom.AffineTransform;
  15. import java.awt.geom.Rectangle2D;
  16. import java.awt.peer.FontPeer;
  17. import java.io.*;
  18. import java.lang.ref.SoftReference;
  19. import java.text.AttributedCharacterIterator.Attribute;
  20. import java.text.CharacterIterator;
  21. import java.text.StringCharacterIterator;
  22. import java.util.HashMap;
  23. import java.util.Hashtable;
  24. import java.util.Locale;
  25. import java.util.Map;
  26. import sun.font.StandardGlyphVector;
  27. import sun.java2d.FontSupport;
  28. import sun.font.Font2D;
  29. import sun.font.Font2DHandle;
  30. import sun.font.FontManager;
  31. import sun.font.GlyphLayout;
  32. import sun.font.FontLineMetrics;
  33. import sun.font.CoreMetrics;
  34. /**
  35. * The <code>Font</code> class represents fonts, which are used to
  36. * render text in a visible way.
  37. * A font provides the information needed to map sequences of
  38. * <em>characters</em> to sequences of <em>glyphs</em>
  39. * and to render sequences of glyphs on <code>Graphics</code> and
  40. * <code>Component</code> objects.
  41. *
  42. * <h4>Characters and Glyphs</h4>
  43. *
  44. * A <em>character</em> is a symbol that represents an item such as a letter,
  45. * a digit, or punctuation in an abstract way. For example, <code>'g'</code>,
  46. * <font size=-1>LATIN SMALL LETTER G</font>, is a character.
  47. * <p>
  48. * A <em>glyph</em> is a shape used to render a character or a sequence of
  49. * characters. In simple writing systems, such as Latin, typically one glyph
  50. * represents one character. In general, however, characters and glyphs do not
  51. * have one-to-one correspondence. For example, the character 'á'
  52. * <font size=-1>LATIN SMALL LETTER A WITH ACUTE</font>, can be represented by
  53. * two glyphs: one for 'a' and one for '´'. On the other hand, the
  54. * two-character string "fi" can be represented by a single glyph, an
  55. * "fi" ligature. In complex writing systems, such as Arabic or the South
  56. * and South-East Asian writing systems, the relationship between characters
  57. * and glyphs can be more complicated and involve context-dependent selection
  58. * of glyphs as well as glyph reordering.
  59. *
  60. * A font encapsulates the collection of glyphs needed to render a selected set
  61. * of characters as well as the tables needed to map sequences of characters to
  62. * corresponding sequences of glyphs.
  63. *
  64. * <h4>Physical and Logical Fonts</h4>
  65. *
  66. * The Java 2 platform distinguishes between two kinds of fonts:
  67. * <em>physical</em> fonts and <em>logical</em> fonts.
  68. * <p>
  69. * <em>Physical</em> fonts are the actual font libraries containing glyph data
  70. * and tables to map from character sequences to glyph sequences, using a font
  71. * technology such as TrueType or PostScript Type 1.
  72. * All implementations of the Java 2 platform must support TrueType fonts;
  73. * support for other font technologies is implementation dependent.
  74. * Physical fonts may use names such as Helvetica, Palatino, HonMincho, or
  75. * any number of other font names.
  76. * Typically, each physical font supports only a limited set of writing
  77. * systems, for example, only Latin characters or only Japanese and Basic
  78. * Latin.
  79. * The set of available physical fonts varies between configurations.
  80. * Applications that require specific fonts can bundle them and instantiate
  81. * them using the {@link #createFont createFont} method.
  82. * <p>
  83. * <em>Logical</em> fonts are the five font families defined by the Java
  84. * platform which must be supported by any Java runtime environment:
  85. * Serif, SansSerif, Monospaced, Dialog, and DialogInput.
  86. * These logical fonts are not actual font libraries. Instead, the logical
  87. * font names are mapped to physical fonts by the Java runtime environment.
  88. * The mapping is implementation and usually locale dependent, so the look
  89. * and the metrics provided by them vary.
  90. * Typically, each logical font name maps to several physical fonts in order to
  91. * cover a large range of characters.
  92. * <p>
  93. * Peered AWT components, such as {@link Label Label} and
  94. * {@link TextField TextField}, can only use logical fonts.
  95. * <p>
  96. * For a discussion of the relative advantages and disadvantages of using
  97. * physical or logical fonts, see the
  98. * <a href="http://java.sun.com/j2se/corejava/intl/reference/faqs/index.html#desktop-rendering">Internationalization FAQ</a>
  99. * document.
  100. *
  101. * <h4>Font Faces and Names</h4>
  102. *
  103. * A <code>Font</code>
  104. * can have many faces, such as heavy, medium, oblique, gothic and
  105. * regular. All of these faces have similar typographic design.
  106. * <p>
  107. * There are three different names that you can get from a
  108. * <code>Font</code> object. The <em>logical font name</em> is simply the
  109. * name that was used to construct the font.
  110. * The <em>font face name</em>, or just <em>font name</em> for
  111. * short, is the name of a particular font face, like Helvetica Bold. The
  112. * <em>family name</em> is the name of the font family that determines the
  113. * typographic design across several faces, like Helvetica.
  114. * <p>
  115. * The <code>Font</code> class represents an instance of a font face from
  116. * a collection of font faces that are present in the system resources
  117. * of the host system. As examples, Arial Bold and Courier Bold Italic
  118. * are font faces. There can be several <code>Font</code> objects
  119. * associated with a font face, each differing in size, style, transform
  120. * and font features.
  121. * The {@link GraphicsEnvironment#getAllFonts() getAllFonts} method
  122. * of the <code>GraphicsEnvironment</code> class returns an
  123. * array of all font faces available in the system. These font faces are
  124. * returned as <code>Font</code> objects with a size of 1, identity
  125. * transform and default font features. These
  126. * base fonts can then be used to derive new <code>Font</code> objects
  127. * with varying sizes, styles, transforms and font features via the
  128. * <code>deriveFont</code> methods in this class.
  129. *
  130. * @version 1.200, 07/20/04
  131. */
  132. public class Font implements java.io.Serializable
  133. {
  134. static {
  135. /* ensure that the necessary native libraries are loaded */
  136. Toolkit.loadLibraries();
  137. initIDs();
  138. }
  139. /**
  140. * A map of font attributes available in this font.
  141. * Attributes include things like ligatures and glyph substitution.
  142. *
  143. * @serial
  144. * @see #getAttributes()
  145. */
  146. private Hashtable fRequestedAttributes;
  147. private static final Map EMPTY_MAP = new Hashtable(5, (float)0.9);
  148. private static final TransformAttribute IDENT_TX_ATTRIBUTE =
  149. new TransformAttribute(new AffineTransform());
  150. /*
  151. * Constants to be used for styles. Can be combined to mix
  152. * styles.
  153. */
  154. /**
  155. * The plain style constant.
  156. */
  157. public static final int PLAIN = 0;
  158. /**
  159. * The bold style constant. This can be combined with the other style
  160. * constants (except PLAIN) for mixed styles.
  161. */
  162. public static final int BOLD = 1;
  163. /**
  164. * The italicized style constant. This can be combined with the other
  165. * style constants (except PLAIN) for mixed styles.
  166. */
  167. public static final int ITALIC = 2;
  168. /**
  169. * The baseline used in most Roman scripts when laying out text.
  170. */
  171. public static final int ROMAN_BASELINE = 0;
  172. /**
  173. * The baseline used in ideographic scripts like Chinese, Japanese,
  174. * and Korean when laying out text.
  175. */
  176. public static final int CENTER_BASELINE = 1;
  177. /**
  178. * The baseline used in Devanigiri and similar scripts when laying
  179. * out text.
  180. */
  181. public static final int HANGING_BASELINE = 2;
  182. /**
  183. * Identify a font resource of type TRUETYPE.
  184. * Used to specify a TrueType font resource to the
  185. * {@link #createFont} method.
  186. * @since 1.3
  187. */
  188. public static final int TRUETYPE_FONT = 0;
  189. /**
  190. * Identify a font resource of type TYPE1.
  191. * Used to specify a Type1 font resource to the
  192. * {@link #createFont} method.
  193. * @since 1.5
  194. */
  195. public static final int TYPE1_FONT = 1;
  196. /**
  197. * The logical name of this <code>Font</code>, as passed to the
  198. * constructor.
  199. * @since JDK1.0
  200. *
  201. * @serial
  202. * @see #getName
  203. */
  204. protected String name;
  205. /**
  206. * The style of this <code>Font</code>, as passed to the constructor.
  207. * This style can be PLAIN, BOLD, ITALIC, or BOLD+ITALIC.
  208. * @since JDK1.0
  209. *
  210. * @serial
  211. * @see #getStyle()
  212. */
  213. protected int style;
  214. /**
  215. * The point size of this <code>Font</code>, rounded to integer.
  216. * @since JDK1.0
  217. *
  218. * @serial
  219. * @see #getSize()
  220. */
  221. protected int size;
  222. /**
  223. * The point size of this <code>Font</code> in <code>float</code>.
  224. *
  225. * @serial
  226. * @see #getSize()
  227. * @see #getSize2D()
  228. */
  229. protected float pointSize;
  230. /**
  231. * The platform specific font information.
  232. */
  233. private transient FontPeer peer;
  234. private transient long pData; // native JDK1.1 font pointer
  235. private transient Font2DHandle font2DHandle;
  236. private transient int superscript;
  237. private transient float width = 1f;
  238. /*
  239. * If the origin of a Font is a created font then this attribute
  240. * must be set on all derived fonts too.
  241. */
  242. private transient boolean createdFont = false;
  243. // cached values - performance
  244. private transient double[] matrix;
  245. private transient boolean nonIdentityTx;
  246. private static final AffineTransform identityTx = new AffineTransform();
  247. /*
  248. * JDK 1.1 serialVersionUID
  249. */
  250. private static final long serialVersionUID = -4206021311591459213L;
  251. /**
  252. * Gets the peer of this <code>Font</code>.
  253. * @return the peer of the <code>Font</code>.
  254. * @since JDK1.1
  255. * @deprecated Font rendering is now platform independent.
  256. */
  257. @Deprecated
  258. public FontPeer getPeer(){
  259. return getPeer_NoClientCode();
  260. }
  261. // NOTE: This method is called by privileged threads.
  262. // We implement this functionality in a package-private method
  263. // to insure that it cannot be overridden by client subclasses.
  264. // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
  265. final FontPeer getPeer_NoClientCode() {
  266. if(peer == null) {
  267. Toolkit tk = Toolkit.getDefaultToolkit();
  268. this.peer = tk.getFontPeer(name, style);
  269. }
  270. return peer;
  271. }
  272. /* create this map only when requested - which may be rarely */
  273. private Hashtable getRequestedAttributes() {
  274. if (fRequestedAttributes == null) {
  275. fRequestedAttributes = new Hashtable(7, (float)0.9);
  276. fRequestedAttributes.put(TextAttribute.TRANSFORM,
  277. IDENT_TX_ATTRIBUTE);
  278. fRequestedAttributes.put(TextAttribute.FAMILY, name);
  279. fRequestedAttributes.put(TextAttribute.SIZE, new Float(size));
  280. fRequestedAttributes.put(TextAttribute.WEIGHT,
  281. (style & BOLD) != 0 ?
  282. TextAttribute.WEIGHT_BOLD :
  283. TextAttribute.WEIGHT_REGULAR);
  284. fRequestedAttributes.put(TextAttribute.POSTURE,
  285. (style & ITALIC) != 0 ?
  286. TextAttribute.POSTURE_OBLIQUE :
  287. TextAttribute.POSTURE_REGULAR);
  288. fRequestedAttributes.put(TextAttribute.SUPERSCRIPT,
  289. new Integer(superscript));
  290. fRequestedAttributes.put(TextAttribute.WIDTH,
  291. new Float(width));
  292. }
  293. return fRequestedAttributes;
  294. }
  295. private void initializeFont(Hashtable attributes) {
  296. if (attributes != null) {
  297. Object obj = attributes.get(TextAttribute.TRANSFORM);
  298. if (obj instanceof TransformAttribute) {
  299. nonIdentityTx = !((TransformAttribute)obj).isIdentity();
  300. } else if (obj instanceof AffineTransform) {
  301. nonIdentityTx = !((AffineTransform)obj).isIdentity();
  302. }
  303. obj = attributes.get(TextAttribute.SUPERSCRIPT);
  304. if (obj instanceof Integer) {
  305. superscript = ((Integer)obj).intValue();
  306. // !!! always synthesize superscript
  307. nonIdentityTx |= superscript != 0;
  308. }
  309. obj = attributes.get(TextAttribute.WIDTH);
  310. if (obj instanceof Integer) {
  311. width = ((Float)obj).floatValue();
  312. // !!! always synthesize width
  313. nonIdentityTx |= width != 1;
  314. }
  315. }
  316. }
  317. private Font2D getFont2D() {
  318. if (FontManager.usingPerAppContextComposites &&
  319. font2DHandle != null &&
  320. font2DHandle.font2D instanceof sun.font.CompositeFont &&
  321. ((sun.font.CompositeFont)(font2DHandle.font2D)).isStdComposite()) {
  322. return FontManager.findFont2D(name, style,
  323. FontManager.LOGICAL_FALLBACK);
  324. } else if (font2DHandle == null) {
  325. font2DHandle =
  326. FontManager.findFont2D(name, style,
  327. FontManager.LOGICAL_FALLBACK).handle;
  328. }
  329. /* Do not cache the de-referenced font2D. It must be explicitly
  330. * de-referenced to pick up a valid font in the event that the
  331. * original one is marked invalid
  332. */
  333. return font2DHandle.font2D;
  334. }
  335. /**
  336. * Creates a new <code>Font</code> from the specified name, style and
  337. * point size.
  338. * <p>
  339. * The font name can be a font face name or a font family name.
  340. * It is used together with the style to find an appropriate font face.
  341. * When a font family name is specified, the style argument is used to
  342. * select the most appropriate face from the family. When a font face
  343. * name is specified, the face's style and the style argument are
  344. * merged to locate the best matching font from the same family.
  345. * For example if face name "Arial Bold" is specified with style
  346. * <code>Font.ITALIC</code>, the font system looks for a face in the
  347. * "Arial" family that is bold and italic, and may associate the font
  348. * instance with the physical font face "Arial Bold Italic".
  349. * The style argument is merged with the specified face's style, not
  350. * added or subtracted.
  351. * This means, specifying a bold face and a bold style does not
  352. * double-embolden the font, and specifying a bold face and a plain
  353. * style does not lighten the font.
  354. * <p>
  355. * If no face for the requested style can be found, the font system
  356. * may apply algorithmic styling to achieve the desired style.
  357. * For example, if <code>ITALIC</code> is requested, but no italic
  358. * face is available, glyphs from the plain face may be algorithmically
  359. * obliqued (slanted).
  360. * <p>
  361. * Font name lookup is case insensitive, using the case folding
  362. * rules of the US locale.
  363. *
  364. * @param name the font name. This can be a font face name or a font
  365. * family name, and may represent either a logical font or a physical
  366. * font found in this <code>GraphicsEnvironment</code>.
  367. * The family names for logical fonts are: Dialog, DialogInput,
  368. * Monospaced, Serif, or SansSerif. If <code>name</code> is
  369. * <code>null</code>, the <em>logical font name</em> of the new
  370. * <code>Font</code> as returned by <code>getName()</code>is set to
  371. * the name "Default".
  372. * @param style the style constant for the <code>Font</code>
  373. * The style argument is an integer bitmask that may
  374. * be PLAIN, or a bitwise union of BOLD and/or ITALIC
  375. * (for example, ITALIC or BOLD|ITALIC).
  376. * If the style argument does not conform to one of the expected
  377. * integer bitmasks then the style is set to PLAIN.
  378. * @param size the point size of the <code>Font</code>
  379. * @see GraphicsEnvironment#getAllFonts
  380. * @see GraphicsEnvironment#getAvailableFontFamilyNames
  381. * @since JDK1.0
  382. */
  383. public Font(String name, int style, int size) {
  384. this.name = (name != null) ? name : "Default";
  385. this.style = (style & ~0x03) == 0 ? style : 0;
  386. this.size = size;
  387. this.pointSize = size;
  388. }
  389. private Font(String name, int style, float sizePts) {
  390. this.name = (name != null) ? name : "Default";
  391. this.style = (style & ~0x03) == 0 ? style : 0;
  392. this.size = (int)(sizePts + 0.5);
  393. this.pointSize = sizePts;
  394. }
  395. /* used to implement Font.createFont */
  396. private Font(File fontFile, int fontFormat, boolean isCopy)
  397. throws FontFormatException {
  398. this.createdFont = true;
  399. /* Font2D instances created by this method track their font file
  400. * so that when the Font2D is GC'd it can also remove the file.
  401. */
  402. this.font2DHandle =
  403. FontManager.createFont2D(fontFile, fontFormat, isCopy).handle;
  404. this.name = this.font2DHandle.font2D.getFontName(Locale.getDefault());
  405. this.style = Font.PLAIN;
  406. this.size = 1;
  407. this.pointSize = 1f;
  408. }
  409. private Font(Map attributes, boolean created, Font2DHandle handle) {
  410. this.createdFont = created;
  411. /* Fonts created from a stream will use the same font2D instance
  412. * as the parent.
  413. */
  414. if (created) {
  415. this.font2DHandle = handle;
  416. }
  417. initFromMap(attributes);
  418. }
  419. /**
  420. * Creates a new <code>Font</code> with the specified attributes.
  421. * This <code>Font</code> only recognizes keys defined in
  422. * {@link TextAttribute} as attributes. If <code>attributes</code>
  423. * is <code>null</code>, a new <code>Font</code> is initialized
  424. * with default attributes.
  425. * @param attributes the attributes to assign to the new
  426. * <code>Font</code>, or <code>null</code>
  427. */
  428. public Font(Map<? extends Attribute, ?> attributes) {
  429. initFromMap(attributes);
  430. }
  431. private void initFromMap(Map attributes) {
  432. this.name = "Dialog";
  433. this.pointSize = 12;
  434. this.size = 12;
  435. if((attributes != null) &&
  436. (!attributes.equals(EMPTY_MAP)))
  437. {
  438. Object obj;
  439. fRequestedAttributes = new Hashtable(attributes);
  440. if ((obj = attributes.get(TextAttribute.FAMILY)) != null) {
  441. this.name = (String)obj;
  442. }
  443. if ((obj = attributes.get(TextAttribute.WEIGHT)) != null) {
  444. if(obj.equals(TextAttribute.WEIGHT_BOLD)) {
  445. this.style |= BOLD;
  446. }
  447. }
  448. if ((obj = attributes.get(TextAttribute.POSTURE)) != null) {
  449. if(obj.equals(TextAttribute.POSTURE_OBLIQUE)) {
  450. this.style |= ITALIC;
  451. }
  452. }
  453. if ((obj = attributes.get(TextAttribute.SIZE)) != null) {
  454. this.pointSize = ((Float)obj).floatValue();
  455. this.size = (int)(this.pointSize + 0.5);
  456. }
  457. if ((obj = attributes.get(TextAttribute.TRANSFORM)) != null) {
  458. if (obj instanceof TransformAttribute) {
  459. nonIdentityTx = !((TransformAttribute)obj).isIdentity();
  460. } else if (obj instanceof AffineTransform) {
  461. nonIdentityTx = !((AffineTransform)obj).isIdentity();
  462. }
  463. }
  464. if ((obj = attributes.get(TextAttribute.SUPERSCRIPT)) != null) {
  465. if (obj instanceof Integer) {
  466. superscript = ((Integer)obj).intValue();
  467. nonIdentityTx |= superscript != 0;
  468. }
  469. }
  470. if ((obj = attributes.get(TextAttribute.WIDTH)) != null) {
  471. if (obj instanceof Float) {
  472. width = ((Float)obj).floatValue();
  473. nonIdentityTx |= width != 1;
  474. }
  475. }
  476. }
  477. }
  478. /**
  479. * Returns a <code>Font</code> appropriate to this attribute set.
  480. *
  481. * @param attributes the attributes to assign to the new
  482. * <code>Font</code>
  483. * @return a new <code>Font</code> created with the specified
  484. * attributes
  485. * @since 1.2
  486. * @see java.awt.font.TextAttribute
  487. */
  488. public static Font getFont(Map<? extends Attribute, ?> attributes) {
  489. Font font = (Font)attributes.get(TextAttribute.FONT);
  490. if (font != null) {
  491. return font;
  492. }
  493. return get(new Key(attributes));
  494. }
  495. private static SoftReference cacheRef = new SoftReference(new HashMap());
  496. private static Font get(Key key) {
  497. Font f = null;
  498. Map cache = (Map)cacheRef.get();
  499. if (cache == null) {
  500. cache = new HashMap();
  501. cacheRef = new SoftReference(cache);
  502. } else {
  503. f = (Font)cache.get(key);
  504. }
  505. if (f == null) {
  506. f = new Font(key.attrs);
  507. cache.put(key, f);
  508. }
  509. return f;
  510. }
  511. // ideally we would construct a font directly from a key, and not
  512. // bother to keep the map around for this. That ought to be a bit
  513. // faster than picking out the params from the Map again, but the
  514. // cache ought to hide this overhead, so I'll skip it for now.
  515. private static class Key {
  516. String family = "Dialog"; // defaults chosen to match Font implementation
  517. float weight = 1.0f;
  518. float posture = 0.0f;
  519. float size = 12.0f;
  520. int superscript = 0;
  521. float width = 1.0f;
  522. double[] txdata = null; // identity
  523. Map attrs;
  524. int hashCode = 0;
  525. Key(Map map) {
  526. attrs = map;
  527. Object o = map.get(TextAttribute.FAMILY);
  528. if (o != null) {
  529. family = (String)o;
  530. }
  531. hashCode = family.hashCode();
  532. o = map.get(TextAttribute.WEIGHT);
  533. if (o != null && o != TextAttribute.WEIGHT_REGULAR) {
  534. // ugh, force to the only values we understand
  535. // weight is either bold, or it's not...
  536. float xweight = ((Float)o).floatValue();
  537. if (xweight == TextAttribute.WEIGHT_BOLD.floatValue()) {
  538. weight = xweight;
  539. hashCode = (hashCode << 3) ^ Float.floatToIntBits(weight);
  540. }
  541. }
  542. o = map.get(TextAttribute.POSTURE);
  543. if (o != null && o != TextAttribute.POSTURE_REGULAR) {
  544. // ugh, same problem as with weight
  545. float xposture = ((Float)o).floatValue();
  546. if (xposture == TextAttribute.POSTURE_OBLIQUE.floatValue()) {
  547. posture = xposture;
  548. hashCode = (hashCode << 3) ^ Float.floatToIntBits(posture);
  549. }
  550. }
  551. o = map.get(TextAttribute.SIZE);
  552. if (o != null) {
  553. size = ((Float)o).floatValue();
  554. if (size != 12.0f) {
  555. hashCode = (hashCode << 3) ^ Float.floatToIntBits(size);
  556. }
  557. }
  558. o = map.get(TextAttribute.TRANSFORM);
  559. if (o != null) {
  560. AffineTransform tx = null;
  561. if (o instanceof TransformAttribute) {
  562. TransformAttribute ta = (TransformAttribute)o;
  563. if (!ta.isIdentity()) {
  564. tx = ta.getTransform();
  565. }
  566. } else if (o instanceof AffineTransform) {
  567. AffineTransform at = (AffineTransform)o;
  568. if (!at.isIdentity()) {
  569. tx = at;
  570. }
  571. }
  572. if (tx != null) {
  573. txdata = new double[6];
  574. tx.getMatrix(txdata);
  575. hashCode = (hashCode << 3) ^ new Double(txdata[0]).hashCode();
  576. }
  577. }
  578. o = map.get(TextAttribute.SUPERSCRIPT);
  579. if (o != null) {
  580. if (o instanceof Integer) {
  581. superscript = ((Integer)o).intValue();
  582. hashCode = hashCode << 3 ^ superscript;
  583. }
  584. }
  585. o = map.get(TextAttribute.WIDTH);
  586. if (o != null) {
  587. if (o instanceof Float) {
  588. width = ((Float)o).floatValue();
  589. hashCode = hashCode << 3 ^ Float.floatToIntBits(width);
  590. }
  591. }
  592. }
  593. public int hashCode() {
  594. return hashCode;
  595. }
  596. public boolean equals(Object rhs) {
  597. Key rhskey = (Key)rhs;
  598. if (this.hashCode == rhskey.hashCode &&
  599. this.size == rhskey.size &&
  600. this.weight == rhskey.weight &&
  601. this.posture == rhskey.posture &&
  602. this.superscript == rhskey.superscript &&
  603. this.width == rhskey.width &&
  604. this.family.equals(rhskey.family) &&
  605. ((this.txdata == null) == (rhskey.txdata == null))) {
  606. if (this.txdata != null) {
  607. for (int i = 0; i < this.txdata.length; ++i) {
  608. if (this.txdata[i] != rhskey.txdata[i]) {
  609. return false;
  610. }
  611. }
  612. }
  613. return true;
  614. }
  615. return false;
  616. }
  617. }
  618. /**
  619. * Returns a new <code>Font</code> using the specified font type
  620. * and input data. The new <code>Font</code> is
  621. * created with a point size of 1 and style {@link #PLAIN PLAIN}.
  622. * This base font can then be used with the <code>deriveFont</code>
  623. * methods in this class to derive new <code>Font</code> objects with
  624. * varying sizes, styles, transforms and font features. This
  625. * method does not close the {@link InputStream}.
  626. * @param fontFormat the type of the <code>Font</code>, which is
  627. * {@link #TRUETYPE_FONT TRUETYPE_FONT} if a TrueType resource is specified.
  628. * or {@link #TYPE1_FONT TYPE1_FONT} if a Type 1 resource is specified.
  629. * @param fontStream an <code>InputStream</code> object representing the
  630. * input data for the font.
  631. * @return a new <code>Font</code> created with the specified font type.
  632. * @throws IllegalArgumentException if <code>fontFormat</code> is not
  633. * <code>TRUETYPE_FONT</code>or<code>TYPE1_FONT</code>.
  634. * @throws FontFormatException if the <code>fontStream</code> data does
  635. * not contain the required font tables for the specified format.
  636. * @throws IOException if the <code>fontStream</code>
  637. * cannot be completely read.
  638. * @since 1.3
  639. */
  640. public static Font createFont(int fontFormat, InputStream fontStream)
  641. throws java.awt.FontFormatException, java.io.IOException {
  642. if (fontFormat != Font.TRUETYPE_FONT &&
  643. fontFormat != Font.TYPE1_FONT) {
  644. throw new IllegalArgumentException ("font format not recognized");
  645. }
  646. final InputStream fStream = fontStream;
  647. Object ret = java.security.AccessController.doPrivileged(
  648. new java.security.PrivilegedAction() {
  649. public Object run() {
  650. File tFile = null;
  651. try {
  652. tFile = File.createTempFile("+~JF", ".tmp", null);
  653. tFile.deleteOnExit();
  654. BufferedInputStream inStream =
  655. new BufferedInputStream(fStream);
  656. FileOutputStream outStream = new FileOutputStream(tFile);
  657. int bytesRead = 0;
  658. int bufSize = 8192;
  659. byte [] buf = new byte[bufSize];
  660. while (bytesRead != -1) {
  661. bytesRead = inStream.read(buf, 0, bufSize);
  662. if (bytesRead != -1) {
  663. outStream.write(buf, 0, bytesRead);
  664. }
  665. }
  666. /* don't close the input stream */
  667. outStream.close();
  668. } catch (IOException e) {
  669. return e;
  670. }
  671. return tFile;
  672. }
  673. });
  674. if (ret instanceof File) {
  675. return new Font((File)ret, fontFormat, true);
  676. } else if (ret instanceof IOException) {
  677. throw (IOException)ret;
  678. } else {
  679. throw new FontFormatException("Couldn't access font stream");
  680. }
  681. }
  682. /**
  683. * Returns a new <code>Font</code> using the specified font type
  684. * and the specified font file. The new <code>Font</code> is
  685. * created with a point size of 1 and style {@link #PLAIN PLAIN}.
  686. * This base font can then be used with the <code>deriveFont</code>
  687. * methods in this class to derive new <code>Font</code> objects with
  688. * varying sizes, styles, transforms and font features.
  689. * @param fontFormat the type of the <code>Font</code>, which is
  690. * {@link #TRUETYPE_FONT TRUETYPE_FONT} if a TrueType resource is
  691. * specified or {@link #TYPE1_FONT TYPE1_FONT} if a Type 1 resource is
  692. * specified.
  693. * So long as the returned font, or its derived fonts are referenced
  694. * the implementation may continue to access <code>fontFile</code>
  695. * to retrieve font data. Thus the results are undefined if the file
  696. * is changed, or becomes inaccessible.
  697. * @param fontFile a <code>File</code> object representing the
  698. * input data for the font.
  699. * @return a new <code>Font</code> created with the specified font type.
  700. * @throws IllegalArgumentException if <code>fontFormat</code> is not
  701. * <code>TRUETYPE_FONT</code>or<code>TYPE1_FONT</code>.
  702. * @throws NullPointerException if <code>fontFile</code> is null.
  703. * @throws IOException if the <code>fontFile</code> cannot be read.
  704. * @throws FontFormatException if <code>fontFile</code> does
  705. * not contain the required font tables for the specified format.
  706. * @throws SecurityException if the executing code does not have
  707. * permission to read from the file.
  708. * @since 1.5
  709. */
  710. public static Font createFont(int fontFormat, File fontFile)
  711. throws java.awt.FontFormatException, java.io.IOException {
  712. if (fontFormat != Font.TRUETYPE_FONT &&
  713. fontFormat != Font.TYPE1_FONT) {
  714. throw new IllegalArgumentException ("font format not recognized");
  715. }
  716. SecurityManager sm = System.getSecurityManager();
  717. if (sm != null) {
  718. FilePermission filePermission =
  719. new FilePermission(fontFile.getPath(), "read");
  720. sm.checkPermission(filePermission);
  721. }
  722. if (!fontFile.canRead()) {
  723. throw new IOException("Can't read " + fontFile);
  724. }
  725. return new Font(fontFile, fontFormat, false);
  726. }
  727. /**
  728. * Returns a copy of the transform associated with this
  729. * <code>Font</code>.
  730. * @return an {@link AffineTransform} object representing the
  731. * transform attribute of this <code>Font</code> object.
  732. */
  733. public AffineTransform getTransform() {
  734. /* The most common case is the identity transform. Most callers
  735. * should call isTransformed() first, to decide if they need to
  736. * get the transform, but some may not. Here we check to see
  737. * if we have a nonidentity transform, and only do the work to
  738. * fetch and/or compute it if so, otherwise we return a new
  739. * identity transform.
  740. *
  741. * Note that the transform is _not_ necessarily the same as
  742. * the transform passed in as an Attribute in a Map, as the
  743. * transform returned will also reflect the effects of WIDTH and
  744. * SUPERSCRIPT attributes. Clients who want the actual transform
  745. * need to call getRequestedAttributes.
  746. */
  747. if (nonIdentityTx) {
  748. AffineTransform at = null;
  749. Object obj = getRequestedAttributes().get(TextAttribute.TRANSFORM);
  750. if (obj != null) {
  751. if( obj instanceof TransformAttribute ){
  752. at = ((TransformAttribute)obj).getTransform();
  753. }
  754. else {
  755. if ( obj instanceof AffineTransform){
  756. at = new AffineTransform((AffineTransform)obj);
  757. }
  758. }
  759. } else {
  760. at = new AffineTransform();
  761. }
  762. if (superscript != 0) {
  763. // can't get ascent and descent here, recursive call to this fn, so use pointsize
  764. // let users combine super- and sub-scripting
  765. double trans = 0;
  766. int n = 0;
  767. boolean up = superscript > 0;
  768. int sign = up ? -1 : 1;
  769. int ss = up ? superscript : -superscript;
  770. while ((ss & 7) > n) {
  771. int newn = ss & 7;
  772. trans += sign * (ssinfo[newn] - ssinfo[n]);
  773. ss >>= 3;
  774. sign = -sign;
  775. n = newn;
  776. }
  777. trans *= pointSize;
  778. double scale = Math.pow(2./3., n);
  779. at.preConcatenate(AffineTransform.getTranslateInstance(0, trans));
  780. at.scale(scale, scale);
  781. // note on placement and italics
  782. // We preconcatenate the transform because we don't want to translate along
  783. // the italic angle, but purely perpendicular to the baseline. While this
  784. // looks ok for superscripts, it can lead subscripts to stack on each other
  785. // and bring the following text too close. The way we deal with potential
  786. // collisions that can occur in the case of italics is by adjusting the
  787. // horizontal spacing of the adjacent glyphvectors. Examine the italic
  788. // angle of both vectors, if one is non-zero, compute the minimum ascent
  789. // and descent, and then the x position at each for each vector along its
  790. // italic angle starting from its (offset) baseline. Compute the difference
  791. // between the x positions and use the maximum difference to adjust the
  792. // position of the right gv.
  793. }
  794. if (width != 1f) {
  795. at.scale(width, 1f);
  796. }
  797. return at;
  798. }
  799. return new AffineTransform();
  800. }
  801. // x = r^0 + r^1 + r^2... r^n
  802. // rx = r^1 + r^2 + r^3... r^(n+1)
  803. // x - rx = r^0 - r^(n+1)
  804. // x (1 - r) = r^0 - r^(n+1)
  805. // x = (r^0 - r^(n+1)) / (1 - r)
  806. // x = (1 - r^(n+1)) / (1 - r)
  807. // scale ratio is 2/3
  808. // trans = 1/2 of ascent * x
  809. // assume ascent is 3/4 of point size
  810. private static final float[] ssinfo = {
  811. 0.0f,
  812. 0.375f,
  813. 0.625f,
  814. 0.7916667f,
  815. 0.9027778f,
  816. 0.9768519f,
  817. 1.0262346f,
  818. 1.0591564f,
  819. };
  820. /**
  821. * Returns the family name of this <code>Font</code>.
  822. *
  823. * <p>The family name of a font is font specific. Two fonts such as
  824. * Helvetica Italic and Helvetica Bold have the same family name,
  825. * <i>Helvetica</i>, whereas their font face names are
  826. * <i>Helvetica Bold</i> and <i>Helvetica Italic</i>. The list of
  827. * available family names may be obtained by using the
  828. * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
  829. *
  830. * <p>Use <code>getName</code> to get the logical name of the font.
  831. * Use <code>getFontName</code> to get the font face name of the font.
  832. * @return a <code>String</code> that is the family name of this
  833. * <code>Font</code>.
  834. *
  835. * @see #getName
  836. * @see #getFontName
  837. * @since JDK1.1
  838. */
  839. public String getFamily() {
  840. return getFamily_NoClientCode();
  841. }
  842. // NOTE: This method is called by privileged threads.
  843. // We implement this functionality in a package-private
  844. // method to insure that it cannot be overridden by client
  845. // subclasses.
  846. // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
  847. final String getFamily_NoClientCode() {
  848. return getFamily(Locale.getDefault());
  849. }
  850. /**
  851. * Returns the family name of this <code>Font</code>, localized for
  852. * the specified locale.
  853. *
  854. * <p>The family name of a font is font specific. Two fonts such as
  855. * Helvetica Italic and Helvetica Bold have the same family name,
  856. * <i>Helvetica</i>, whereas their font face names are
  857. * <i>Helvetica Bold</i> and <i>Helvetica Italic</i>. The list of
  858. * available family names may be obtained by using the
  859. * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
  860. *
  861. * <p>Use <code>getFontName</code> to get the font face name of the font.
  862. * @param l locale for which to get the family name
  863. * @return a <code>String</code> representing the family name of the
  864. * font, localized for the specified locale.
  865. * @see #getFontName
  866. * @see java.util.Locale
  867. * @since 1.2
  868. */
  869. public String getFamily(Locale l) {
  870. if (l == null) {
  871. throw new NullPointerException("null locale doesn't mean default");
  872. }
  873. return getFont2D().getFamilyName(l);
  874. }
  875. /**
  876. * Returns the postscript name of this <code>Font</code>.
  877. * Use <code>getFamily</code> to get the family name of the font.
  878. * Use <code>getFontName</code> to get the font face name of the font.
  879. * @return a <code>String</code> representing the postscript name of
  880. * this <code>Font</code>.
  881. * @since 1.2
  882. */
  883. public String getPSName() {
  884. return getFont2D().getPostscriptName();
  885. }
  886. /**
  887. * Returns the logical name of this <code>Font</code>.
  888. * Use <code>getFamily</code> to get the family name of the font.
  889. * Use <code>getFontName</code> to get the font face name of the font.
  890. * @return a <code>String</code> representing the logical name of
  891. * this <code>Font</code>.
  892. * @see #getFamily
  893. * @see #getFontName
  894. * @since JDK1.0
  895. */
  896. public String getName() {
  897. return name;
  898. }
  899. /**
  900. * Returns the font face name of this <code>Font</code>. For example,
  901. * Helvetica Bold could be returned as a font face name.
  902. * Use <code>getFamily</code> to get the family name of the font.
  903. * Use <code>getName</code> to get the logical name of the font.
  904. * @return a <code>String</code> representing the font face name of
  905. * this <code>Font</code>.
  906. * @see #getFamily
  907. * @see #getName
  908. * @since 1.2
  909. */
  910. public String getFontName() {
  911. return getFontName(Locale.getDefault());
  912. }
  913. /**
  914. * Returns the font face name of the <code>Font</code>, localized
  915. * for the specified locale. For example, Helvetica Fett could be
  916. * returned as the font face name.
  917. * Use <code>getFamily</code> to get the family name of the font.
  918. * @param l a locale for which to get the font face name
  919. * @return a <code>String</code> representing the font face name,
  920. * localized for the specified locale.
  921. * @see #getFamily
  922. * @see java.util.Locale
  923. */
  924. public String getFontName(Locale l) {
  925. if (l == null) {
  926. throw new NullPointerException("null locale doesn't mean default");
  927. }
  928. return getFont2D().getFontName(l);
  929. }
  930. /**
  931. * Returns the style of this <code>Font</code>. The style can be
  932. * PLAIN, BOLD, ITALIC, or BOLD+ITALIC.
  933. * @return the style of this <code>Font</code>
  934. * @see #isPlain
  935. * @see #isBold
  936. * @see #isItalic
  937. * @since JDK1.0
  938. */
  939. public int getStyle() {
  940. return style;
  941. }
  942. /**
  943. * Returns the point size of this <code>Font</code>, rounded to
  944. * an integer.
  945. * Most users are familiar with the idea of using <i>point size</i> to
  946. * specify the size of glyphs in a font. This point size defines a
  947. * measurement between the baseline of one line to the baseline of the
  948. * following line in a single spaced text document. The point size is
  949. * based on <i>typographic points</i>, approximately 1/72 of an inch.
  950. * <p>
  951. * The Java(tm)2D API adopts the convention that one point is
  952. * equivalent to one unit in user coordinates. When using a
  953. * normalized transform for converting user space coordinates to
  954. * device space coordinates 72 user
  955. * space units equal 1 inch in device space. In this case one point
  956. * is 1/72 of an inch.
  957. * @return the point size of this <code>Font</code> in 1/72 of an
  958. * inch units.
  959. * @see #getSize2D
  960. * @see GraphicsConfiguration#getDefaultTransform
  961. * @see GraphicsConfiguration#getNormalizingTransform
  962. * @since JDK1.0
  963. */
  964. public int getSize() {
  965. return size;
  966. }
  967. /**
  968. * Returns the point size of this <code>Font</code> in
  969. * <code>float</code> value.
  970. * @return the point size of this <code>Font</code> as a
  971. * <code>float</code> value.
  972. * @see #getSize
  973. * @since 1.2
  974. */
  975. public float getSize2D() {
  976. return pointSize;
  977. }
  978. /**
  979. * Indicates whether or not this <code>Font</code> object's style is
  980. * PLAIN.
  981. * @return <code>true</code> if this <code>Font</code> has a
  982. * PLAIN sytle;
  983. * <code>false</code> otherwise.
  984. * @see java.awt.Font#getStyle
  985. * @since JDK1.0
  986. */
  987. public boolean isPlain() {
  988. return style == 0;
  989. }
  990. /**
  991. * Indicates whether or not this <code>Font</code> object's style is
  992. * BOLD.
  993. * @return <code>true</code> if this <code>Font</code> object's
  994. * style is BOLD;
  995. * <code>false</code> otherwise.
  996. * @see java.awt.Font#getStyle
  997. * @since JDK1.0
  998. */
  999. public boolean isBold() {
  1000. return (style & BOLD) != 0;
  1001. }
  1002. /**
  1003. * Indicates whether or not this <code>Font</code> object's style is
  1004. * ITALIC.
  1005. * @return <code>true</code> if this <code>Font</code> object's
  1006. * style is ITALIC;
  1007. * <code>false</code> otherwise.
  1008. * @see java.awt.Font#getStyle
  1009. * @since JDK1.0
  1010. */
  1011. public boolean isItalic() {
  1012. return (style & ITALIC) != 0;
  1013. }
  1014. /**
  1015. * Indicates whether or not this <code>Font</code> object has a
  1016. * transform that affects its size in addition to the Size
  1017. * attribute.
  1018. * @return <code>true</code> if this <code>Font</code> object
  1019. * has a non-identity AffineTransform attribute.
  1020. * <code>false</code> otherwise.
  1021. * @see java.awt.Font#getTransform
  1022. * @since 1.4
  1023. */
  1024. public boolean isTransformed() {
  1025. return nonIdentityTx;
  1026. }
  1027. /**
  1028. * Returns a <code>Font</code> object from the system properties list.
  1029. * <code>nm</code> is treated as the name of a system property to be
  1030. * obtained. The <code>String</code> value of this property is then
  1031. * interpreted as a <code>Font</code> object according to the
  1032. * specification of <code>Font.decode(String)</code>
  1033. * If the specified property is not found, null is returned instead.
  1034. *
  1035. * @param nm the property name
  1036. * @return a <code>Font</code> object that the property name
  1037. * describes, or null if no such property exists.
  1038. * @throws NullPointerException if nm is null.
  1039. * @since 1.2
  1040. * @see #decode(String)
  1041. */
  1042. public static Font getFont(String nm) {
  1043. return getFont(nm, null);
  1044. }
  1045. /**
  1046. * Returns the <code>Font</code> that the <code>str</code>
  1047. * argument describes.
  1048. * To ensure that this method returns the desired Font,
  1049. * format the <code>str</code> parameter in
  1050. * one of these ways
  1051. * <p>
  1052. * <ul>
  1053. * <li><em>fontname-style-pointsize</em>
  1054. * <li><em>fontname-pointsize</em>
  1055. * <li><em>fontname-style</em>
  1056. * <li><em>fontname</em>
  1057. * <li><em>fontname style pointsize</em>
  1058. * <li><em>fontname pointsize</em>
  1059. * <li><em>fontname style</em>
  1060. * <li><em>fontname</em>
  1061. * </ul>
  1062. * in which <i>style</i> is one of the four
  1063. * case-insensitive strings:
  1064. * <code>"PLAIN"</code>, <code>"BOLD"</code>, <code>"BOLDITALIC"</code>, or
  1065. * <code>"ITALIC"</code>, and pointsize is a positive decimal integer
  1066. * representation of the point size.
  1067. * For example, if you want a font that is Arial, bold, with
  1068. * a point size of 18, you would call this method with:
  1069. * "Arial-BOLD-18".
  1070. * This is equivalent to calling the Font constructor :
  1071. * <code>new Font("Arial", Font.BOLD, 18);</code>
  1072. * and the values are interpreted as specified by that constructor.
  1073. * <p>
  1074. * A valid trailing decimal field is always interpreted as the pointsize.
  1075. * Therefore a fontname containing a trailing decimal value should not
  1076. * be used in the fontname only form.
  1077. * <p>
  1078. * If a style name field is not one of the valid style strings, it is
  1079. * interpreted as part of the font name, and the default style is used.
  1080. * <p>
  1081. * Only one of ' ' or '-' may be used to separate fields in the input.
  1082. * The identified separator is the one closest to the end of the string
  1083. * which separates a valid pointsize, or a valid style name from
  1084. * the rest of the string.
  1085. * Null (empty) pointsize and style fields are treated
  1086. * as valid fields with the default value for that field.
  1087. *<p>
  1088. * Some font names may include the separator characters ' ' or '-'.
  1089. * If <code>str</code> is not formed with 3 components, e.g. such that
  1090. * <code>style</code> or <code>pointsize</code> fields are not present in
  1091. * <code>str</code>, and <code>fontname</code> also contains a
  1092. * character determined to be the separator character
  1093. * then these characters where they appear as intended to be part of
  1094. * <code>fontname</code> may instead be interpreted as separators
  1095. * so the font name may not be properly recognised.
  1096. *
  1097. * <p>
  1098. * The default size is 12 and the default style is PLAIN.
  1099. * If <code>str</code> does not specify a valid size, the returned
  1100. * <code>Font</code> has a size of 12. If <code>str</code> does not
  1101. * specify a valid style, the returned Font has a style of PLAIN.
  1102. * If you do not specify a valid font name in
  1103. * the <code>str</code> argument, this method will return
  1104. * a font with the family name "Dialog".
  1105. * To determine what font family names are available on
  1106. * your system, use the
  1107. * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
  1108. * If <code>str</code> is <code>null</code>, a new <code>Font</code>
  1109. * is returned with the family name "Dialog", a size of 12 and a
  1110. * PLAIN style.
  1111. * @param str the name of the font, or <code>null</code>
  1112. * @return the <code>Font</code> object that <code>str</code>
  1113. * describes, or a new default <code>Font</code> if
  1114. * <code>str</code> is <code>null</code>.
  1115. * @see #getFamily
  1116. * @since JDK1.1
  1117. */
  1118. public static Font decode(String str) {
  1119. String fontName = str;
  1120. String styleName = "";
  1121. int fontSize = 12;
  1122. int fontStyle = Font.PLAIN;
  1123. if (str == null) {
  1124. return new Font("Dialog", fontStyle, fontSize);
  1125. }
  1126. int lastHyphen = str.lastIndexOf('-');
  1127. int lastSpace = str.lastIndexOf(' ');
  1128. char sepChar = (lastHyphen > lastSpace) ? '-' : ' ';
  1129. int sizeIndex = str.lastIndexOf(sepChar);
  1130. int styleIndex = str.lastIndexOf(sepChar, sizeIndex-1);
  1131. int strlen = str.length();
  1132. if (sizeIndex > 0 && sizeIndex+1 < strlen) {
  1133. try {
  1134. fontSize =
  1135. Integer.valueOf(str.substring(sizeIndex+1)).intValue();
  1136. if (fontSize <= 0) {
  1137. fontSize = 12;
  1138. }
  1139. } catch (NumberFormatException e) {
  1140. /* It wasn't a valid size, if we didn't also find the
  1141. * start of the style string perhaps this is the style */
  1142. styleIndex = sizeIndex;
  1143. sizeIndex = strlen;
  1144. if (str.charAt(sizeIndex-1) == sepChar) {
  1145. sizeIndex--;
  1146. }
  1147. }
  1148. }
  1149. if (styleIndex >= 0 && styleIndex+1 < strlen) {
  1150. styleName = str.substring(styleIndex+1, sizeIndex);
  1151. styleName = styleName.toLowerCase(Locale.ENGLISH);
  1152. if (styleName.equals("bolditalic")) {
  1153. fontStyle = Font.BOLD | Font.ITALIC;
  1154. } else if (styleName.equals("italic")) {
  1155. fontStyle = Font.ITALIC;
  1156. } else if (styleName.equals("bold")) {
  1157. fontStyle = Font.BOLD;
  1158. } else if (styleName.equals("plain")) {
  1159. fontStyle = Font.PLAIN;
  1160. } else {
  1161. /* this string isn't any of the expected styles, so
  1162. * assume its part of the font name
  1163. */
  1164. styleIndex = sizeIndex;
  1165. if (str.charAt(styleIndex-1) == sepChar) {
  1166. styleIndex--;
  1167. }
  1168. }
  1169. fontName = str.substring(0, styleIndex);
  1170. } else {
  1171. int fontEnd = strlen;
  1172. if (styleIndex > 0) {
  1173. fontEnd = styleIndex;
  1174. } else if (sizeIndex > 0) {
  1175. fontEnd = sizeIndex;
  1176. }
  1177. if (fontEnd > 0 && str.charAt(fontEnd-1) == sepChar) {
  1178. fontEnd--;
  1179. }
  1180. fontName = str.substring(0, fontEnd);
  1181. }
  1182. return new Font(fontName, fontStyle, fontSize);
  1183. }
  1184. /**
  1185. * Gets the specified <code>Font</code> from the system properties
  1186. * list. As in the <code>getProperty</code> method of
  1187. * <code>System</code>, the first
  1188. * argument is treated as the name of a system property to be
  1189. * obtained. The <code>String</code> value of this property is then
  1190. * interpreted as a <code>Font</code> object.
  1191. * <p>
  1192. * The property value should be one of the forms accepted by
  1193. * <code>Font.decode(String)</code>
  1194. * If the specified property is not found, the <code>font</code>
  1195. * argument is returned instead.
  1196. * @param nm the case-insensitive property name
  1197. * @param font a default <code>Font</code> to return if property
  1198. * <code>nm</code> is not defined
  1199. * @return the <code>Font</code> value of the property.
  1200. * @throws NullPointerException if nm is null.
  1201. * @see #decode(String)
  1202. */
  1203. public static Font getFont(String nm, Font font) {
  1204. String str = null;
  1205. try {
  1206. str =System.getProperty(nm);
  1207. } catch(SecurityException e) {
  1208. }
  1209. if (str == null) {
  1210. return font;
  1211. }
  1212. return decode ( str );
  1213. }
  1214. /**
  1215. * Returns a hashcode for this <code>Font</code>.
  1216. * @return a hashcode value for this <code>Font</code>.
  1217. * @since JDK1.0
  1218. */
  1219. public int hashCode() {
  1220. return name.hashCode() ^ style ^ size;
  1221. }
  1222. /**
  1223. * Compares this <code>Font</code> object to the specified
  1224. * <code>Object</code>.
  1225. * @param obj the <code>Object</code> to compare
  1226. * @return <code>true</code> if the objects are the same
  1227. * or if the argument is a <code>Font</code> object
  1228. * describing the same font as this object;
  1229. * <code>false</code> otherwise.
  1230. * @since JDK1.0
  1231. */
  1232. public boolean equals(Object obj) {
  1233. if (obj == this) {
  1234. return true;
  1235. }
  1236. if (obj != null) {
  1237. try {
  1238. Font font = (Font)obj;
  1239. if ((size == font.size) &&
  1240. (pointSize == font.pointSize) &&
  1241. (style == font.style) &&
  1242. (superscript == font.superscript) &&
  1243. (width == font.width) &&
  1244. name.equals(font.name)) {
  1245. double[] thismat = this.getMatrix();
  1246. double[] thatmat = font.getMatrix();
  1247. return thismat[0] == thatmat[0]
  1248. && thismat[1] == thatmat[1]
  1249. && thismat[2] == thatmat[2]
  1250. && thismat[3] == thatmat[3]
  1251. && thismat[4] == thatmat[4]
  1252. && thismat[5] == thatmat[5];
  1253. }
  1254. }
  1255. catch (ClassCastException e) {
  1256. }
  1257. }
  1258. return false;
  1259. }
  1260. /**
  1261. * Converts this <code>Font</code> object to a <code>String</code>
  1262. * representation.
  1263. * @return a <code>String</code> representation of this
  1264. * <code>Font</code> object.
  1265. * @since JDK1.0
  1266. */
  1267. // NOTE: This method may be called by privileged threads.
  1268. // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
  1269. public String toString() {
  1270. String strStyle;
  1271. if (isBold()) {
  1272. strStyle = isItalic() ? "bolditalic" : "bold";
  1273. } else {
  1274. strStyle = isItalic() ? "italic" : "plain";
  1275. }
  1276. return getClass().getName() + "[family=" + getFamily() + ",name=" + name + ",style=" +
  1277. strStyle + ",size=" + size + "]";
  1278. } // toString()
  1279. /** Serialization support. A <code>readObject</code>
  1280. * method is neccessary because the constructor creates
  1281. * the font's peer, and we can't serialize the peer.
  1282. * Similarly the computed font "family" may be different
  1283. * at <code>readObject</code> time than at
  1284. * <code>writeObject</code> time. An integer version is
  1285. * written so that future versions of this class will be
  1286. * able to recognize serialized output from this one.
  1287. */
  1288. /**
  1289. * The <code>Font</code> Serializable Data Form.
  1290. *
  1291. * @serial
  1292. */
  1293. private int fontSerializedDataVersion = 1;
  1294. /**
  1295. * Writes default serializable fields to a stream.
  1296. *
  1297. * @param s the <code>ObjectOutputStream</code> to write
  1298. * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
  1299. * @see #readObject(java.io.ObjectInputStream)
  1300. */
  1301. private void writeObject(java.io.ObjectOutputStream s)
  1302. throws java.lang.ClassNotFoundException,
  1303. java.io.IOException
  1304. {
  1305. s.defaultWriteObject();
  1306. }
  1307. /**
  1308. * Reads the <code>ObjectInputStream</code>.
  1309. * Unrecognized keys or values will be ignored.
  1310. *
  1311. * @param s the <code>ObjectInputStream</code> to read
  1312. * @serial
  1313. * @see #writeObject(java.io.ObjectOutputStream)
  1314. */
  1315. private void readObject(java.io.ObjectInputStream s)
  1316. throws java.lang.ClassNotFoundException,
  1317. java.io.IOException
  1318. {
  1319. s.defaultReadObject();
  1320. if (pointSize == 0) {
  1321. pointSize = (float)size;
  1322. }
  1323. width = 1f; // init transient field
  1324. initializeFont(fRequestedAttributes);
  1325. }
  1326. /**
  1327. * Returns the number of gl