1. /*
  2. * @(#)Font.java 1.181 03/01/23
  3. *
  4. * Copyright 2003 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.awt.font.NativeFontWrapper;
  27. import sun.awt.font.StandardGlyphVector;
  28. import sun.java2d.FontSupport;
  29. import sun.java2d.SunGraphicsEnvironment;
  30. /**
  31. * The <code>Font</code> class represents fonts, which are used to
  32. * render text in a visible way.
  33. * A font provides the information needed to map sequences of
  34. * <em>characters</em> to sequences of <em>glyphs</em>
  35. * and to render sequences of glyphs on <code>Graphics</code> and
  36. * <code>Component</code> objects.
  37. *
  38. * <h4>Characters and Glyphs</h4>
  39. *
  40. * A <em>character</em> is a symbol that represents an item such as a letter,
  41. * a digit, or punctuation in an abstract way. For example, <code>'g'</code>,
  42. * <font size=-1>LATIN SMALL LETTER G</font>, is a character.
  43. * <p>
  44. * A <em>glyph</em> is a shape used to render a character or a sequence of
  45. * characters. In simple writing systems, such as Latin, typically one glyph
  46. * represents one character. In general, however, characters and glyphs do not
  47. * have one-to-one correspondence. For example, the character 'á'
  48. * <font size=-1>LATIN SMALL LETTER A WITH ACUTE</font>, can be represented by
  49. * two glyphs: one for 'a' and one for '´'. On the other hand, the
  50. * two-character string "fi" can be represented by a single glyph, an
  51. * "fi" ligature. In complex writing systems, such as Arabic or the South
  52. * and South-East Asian writing systems, the relationship between characters
  53. * and glyphs can be more complicated and involve context-dependent selection
  54. * of glyphs as well as glyph reordering.
  55. *
  56. * A font encapsulates the collection of glyphs needed to render a selected set
  57. * of characters as well as the tables needed to map sequences of characters to
  58. * corresponding sequences of glyphs.
  59. *
  60. * <h4>Physical and Logical Fonts</h4>
  61. *
  62. * The Java 2 platform distinguishes between two kinds of fonts:
  63. * <em>physical</em> fonts and <em>logical</em> fonts.
  64. * <p>
  65. * <em>Physical</em> fonts are the actual font libraries containing glyph data
  66. * and tables to map from character sequences to glyph sequences, using a font
  67. * technology such as TrueType or PostScript Type 1.
  68. * All implementations of the Java 2 platform must support TrueType fonts;
  69. * support for other font technologies is implementation dependent.
  70. * Physical fonts may use names such as Helvetica, Palatino, HonMincho, or
  71. * any number of other font names.
  72. * Typically, each physical font supports only a limited set of writing
  73. * systems, for example, only Latin characters or only Japanese and Basic
  74. * Latin.
  75. * The set of available physical fonts varies between configurations.
  76. * Applications that require specific fonts can bundle them and instantiate
  77. * them using the {@link #createFont createFont} method.
  78. * <p>
  79. * <em>Logical</em> fonts are the five font families defined by the Java
  80. * platform which must be supported by any Java runtime environment:
  81. * Serif, SansSerif, Monospaced, Dialog, and DialogInput.
  82. * These logical fonts are not actual font libraries. Instead, the logical
  83. * font names are mapped to physical fonts by the Java runtime environment.
  84. * The mapping is implementation and usually locale dependent, so the look
  85. * and the metrics provided by them vary.
  86. * Typically, each logical font name maps to several physical fonts in order to
  87. * cover a large range of characters.
  88. * <p>
  89. * Peered AWT components, such as {@link Label Label} and
  90. * {@link TextField TextField}, can only use logical fonts.
  91. * <p>
  92. * For a discussion of the relative advantages and disadvantages of using
  93. * physical or logical fonts, see the
  94. * <a href="../../../guide/intl/faq.html#fonts">Internationalization FAQ</a>
  95. * document.
  96. *
  97. * <h4>Font Faces and Names</h4>
  98. *
  99. * A <code>Font</code>
  100. * can have many faces, such as heavy, medium, oblique, gothic and
  101. * regular. All of these faces have similar typographic design.
  102. * <p>
  103. * There are three different names that you can get from a
  104. * <code>Font</code> object. The <em>logical font name</em> is simply the
  105. * name that was used to construct the font.
  106. * The <em>font face name</em>, or just <em>font name</em> for
  107. * short, is the name of a particular font face, like Helvetica Bold. The
  108. * <em>family name</em> is the name of the font family that determines the
  109. * typographic design across several faces, like Helvetica.
  110. * <p>
  111. * The <code>Font</code> class represents an instance of a font face from
  112. * a collection of font faces that are present in the system resources
  113. * of the host system. As examples, Arial Bold and Courier Bold Italic
  114. * are font faces. There can be several <code>Font</code> objects
  115. * associated with a font face, each differing in size, style, transform
  116. * and font features.
  117. * The {@link GraphicsEnvironment#getAllFonts() getAllFonts} method
  118. * of the <code>GraphicsEnvironment</code> class returns an
  119. * array of all font faces available in the system. These font faces are
  120. * returned as <code>Font</code> objects with a size of 1, identity
  121. * transform and default font features. These
  122. * base fonts can then be used to derive new <code>Font</code> objects
  123. * with varying sizes, styles, transforms and font features via the
  124. * <code>deriveFont</code> methods in this class.
  125. *
  126. * @version 1.181, 01/23/03
  127. */
  128. public class Font implements java.io.Serializable
  129. {
  130. static {
  131. /* ensure that the necessary native libraries are loaded */
  132. Toolkit.loadLibraries();
  133. initIDs();
  134. }
  135. /**
  136. * A map of font attributes available in this font.
  137. * Attributes include things like ligatures and glyph substitution.
  138. *
  139. * @serial
  140. * @see #getAttributes()
  141. */
  142. private Hashtable fRequestedAttributes;
  143. private static final Map EMPTY_MAP = new Hashtable(5, (float)0.9);
  144. private static final TransformAttribute IDENT_TX_ATTRIBUTE =
  145. new TransformAttribute(new AffineTransform());
  146. /*
  147. * Constants to be used for styles. Can be combined to mix
  148. * styles.
  149. */
  150. /**
  151. * The plain style constant.
  152. */
  153. public static final int PLAIN = 0;
  154. /**
  155. * The bold style constant. This can be combined with the other style
  156. * constants (except PLAIN) for mixed styles.
  157. */
  158. public static final int BOLD = 1;
  159. /**
  160. * The italicized style constant. This can be combined with the other
  161. * style constants (except PLAIN) for mixed styles.
  162. */
  163. public static final int ITALIC = 2;
  164. /**
  165. * The baseline used in most Roman scripts when laying out text.
  166. */
  167. public static final int ROMAN_BASELINE = 0;
  168. /**
  169. * The baseline used in ideographic scripts like Chinese, Japanese,
  170. * and Korean when laying out text.
  171. */
  172. public static final int CENTER_BASELINE = 1;
  173. /**
  174. * The baseline used in Devanigiri and similar scripts when laying
  175. * out text.
  176. */
  177. public static final int HANGING_BASELINE = 2;
  178. /**
  179. * Create a Font of type TRUETYPE.
  180. * In future other types may be added to support other font types.
  181. */
  182. public static final int TRUETYPE_FONT = 0;
  183. /**
  184. * The logical name of this <code>Font</code>, as passed to the
  185. * constructor.
  186. * @since JDK1.0
  187. *
  188. * @serial
  189. * @see #getName
  190. */
  191. protected String name;
  192. /**
  193. * The style of this <code>Font</code>, as passed to the constructor.
  194. * This style can be PLAIN, BOLD, ITALIC, or BOLD+ITALIC.
  195. * @since JDK1.0
  196. *
  197. * @serial
  198. * @see #getStyle()
  199. */
  200. protected int style;
  201. /**
  202. * The point size of this <code>Font</code>, rounded to integer.
  203. * @since JDK1.0
  204. *
  205. * @serial
  206. * @see #getSize()
  207. */
  208. protected int size;
  209. /**
  210. * The point size of this <code>Font</code> in <code>float</code>.
  211. *
  212. * @serial
  213. * @see #getSize()
  214. * @see #getSize2D()
  215. */
  216. protected float pointSize;
  217. /**
  218. * The platform specific font information.
  219. */
  220. private transient FontPeer peer;
  221. private transient long pData; // native JDK1.1 font pointer
  222. private transient long pNativeFont; // native Java 2 platform font reference
  223. /*
  224. * If the origin of a Font is a created font then this attribute
  225. * must be set on all derived fonts too.
  226. */
  227. private transient boolean createdFont = false;
  228. // cached values - performance
  229. private transient int numGlyphs = -1;
  230. private transient int missingGlyph = -1;
  231. private transient int canRotate = -1;
  232. private transient double[] matrix;
  233. private transient boolean nonIdentityTx;
  234. /*
  235. * JDK 1.1 serialVersionUID
  236. */
  237. private static final long serialVersionUID = -4206021311591459213L;
  238. /**
  239. * Gets the peer of this <code>Font</code>.
  240. * @return the peer of the <code>Font</code>.
  241. * @since JDK1.1
  242. * @deprecated Font rendering is now platform independent.
  243. */
  244. public FontPeer getPeer(){
  245. return getPeer_NoClientCode();
  246. }
  247. // NOTE: This method is called by privileged threads.
  248. // We implement this functionality in a package-private method
  249. // to insure that it cannot be overridden by client subclasses.
  250. // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
  251. final FontPeer getPeer_NoClientCode() {
  252. if(peer == null) {
  253. Toolkit tk = Toolkit.getDefaultToolkit();
  254. this.peer = tk.getFontPeer(name, style);
  255. }
  256. return peer;
  257. }
  258. private void initializeFont(Hashtable attributes) {
  259. if (this.name == null) {
  260. this.name = "Default";
  261. }
  262. if (attributes == null) {
  263. fRequestedAttributes = new Hashtable(5, (float)0.9);
  264. fRequestedAttributes.put(TextAttribute.TRANSFORM, IDENT_TX_ATTRIBUTE);
  265. fRequestedAttributes.put(TextAttribute.FAMILY, name);
  266. fRequestedAttributes.put(TextAttribute.SIZE, new Float(size));
  267. fRequestedAttributes.put(TextAttribute.WEIGHT, (style & BOLD) != 0 ?
  268. TextAttribute.WEIGHT_BOLD : TextAttribute.WEIGHT_REGULAR);
  269. fRequestedAttributes.put(TextAttribute.POSTURE, (style & ITALIC) != 0 ?
  270. TextAttribute.POSTURE_OBLIQUE : TextAttribute.POSTURE_REGULAR);
  271. // nonIdentityTx = false;
  272. } else {
  273. // fRequestedAttributes = ffApply(style, attributes);
  274. Object obj = fRequestedAttributes.get(TextAttribute.TRANSFORM);
  275. if (obj instanceof TransformAttribute) {
  276. nonIdentityTx = !((TransformAttribute)obj).isIdentity();
  277. } else if (obj instanceof AffineTransform) {
  278. nonIdentityTx = !((AffineTransform)obj).isIdentity();
  279. }
  280. // else nonIdentityTx = false;
  281. }
  282. GraphicsEnvironment env =
  283. GraphicsEnvironment.getLocalGraphicsEnvironment();
  284. String localName = this.name;
  285. if (env instanceof FontSupport && createdFont == false) {
  286. localName = ((FontSupport)env).mapFontName(
  287. this.name, this.style);
  288. }
  289. NativeFontWrapper.initializeFont(this, localName, style); // sets pNativeFont
  290. // System.out.println("Initializing font: '" + localName + "'.");
  291. }
  292. /**
  293. * Creates a new <code>Font</code> from the specified name, style and
  294. * point size.
  295. * @param name the font name. This can be a logical font name or a
  296. * font face name. A logical name must be either: Dialog, DialogInput,
  297. * Monospaced, Serif, or SansSerif. If <code>name</code> is
  298. * <code>null</code>, the <code>name</code> of the new
  299. * <code>Font</code> is set to the name "Default".
  300. * @param style the style constant for the <code>Font</code>
  301. * The style argument is an integer bitmask that may
  302. * be PLAIN, or a bitwise union of BOLD and/or ITALIC
  303. * (for example, ITALIC or BOLD|ITALIC).
  304. * If the style argument does not conform to one of the expected
  305. * integer bitmasks then the style is set to PLAIN.
  306. * @param size the point size of the <code>Font</code>
  307. * @see GraphicsEnvironment#getAllFonts
  308. * @see GraphicsEnvironment#getAvailableFontFamilyNames
  309. * @since JDK1.0
  310. */
  311. public Font(String name, int style, int size) {
  312. this.name = name;
  313. this.style = (style & ~0x03) == 0 ? style : 0;
  314. this.size = size;
  315. this.pointSize = size;
  316. initializeFont(null);
  317. }
  318. private Font(String name, int style, int size, boolean created) {
  319. this.createdFont = created;
  320. this.name = name;
  321. this.style = (style & ~0x03) == 0 ? style : 0;
  322. this.size = size;
  323. this.pointSize = size;
  324. initializeFont(null);
  325. }
  326. private Font(String name, int style, float sizePts, boolean created) {
  327. this.createdFont = created;
  328. this.name = name;
  329. this.style = (style & ~0x03) == 0 ? style : 0;
  330. this.size = (int)(sizePts + 0.5);
  331. this.pointSize = sizePts;
  332. initializeFont(null);
  333. }
  334. /**
  335. * Creates a new <code>Font</code> with the specified attributes.
  336. * This <code>Font</code> only recognizes keys defined in
  337. * {@link TextAttribute} as attributes. If <code>attributes</code>
  338. * is <code>null</code>, a new <code>Font</code> is initialized
  339. * with default attributes.
  340. * @param attributes the attributes to assign to the new
  341. * <code>Font</code>, or <code>null</code>
  342. */
  343. public Font(Map attributes){
  344. initFromMap(attributes);
  345. }
  346. private Font(Map attributes, boolean created) {
  347. this.createdFont = created;
  348. initFromMap(attributes);
  349. }
  350. private void initFromMap(Map attributes) {
  351. this.name = "Dialog";
  352. this.pointSize = 12;
  353. this.size = 12;
  354. if((attributes != null) &&
  355. (!attributes.equals(EMPTY_MAP)))
  356. {
  357. Object obj;
  358. fRequestedAttributes = new Hashtable(attributes);
  359. if ((obj = attributes.get(TextAttribute.FAMILY)) != null) {
  360. this.name = (String)obj;
  361. }
  362. if ((obj = attributes.get(TextAttribute.WEIGHT)) != null){
  363. if(obj.equals(TextAttribute.WEIGHT_BOLD)) {
  364. this.style |= BOLD;
  365. }
  366. }
  367. if ((obj = attributes.get(TextAttribute.POSTURE)) != null){
  368. if(obj.equals(TextAttribute.POSTURE_OBLIQUE)) {
  369. this.style |= ITALIC;
  370. }
  371. }
  372. if ((obj = attributes.get(TextAttribute.SIZE)) != null){
  373. this.pointSize = ((Float)obj).floatValue();
  374. this.size = (int)(this.pointSize + 0.5);
  375. }
  376. }
  377. initializeFont(fRequestedAttributes);
  378. }
  379. /**
  380. * Returns a <code>Font</code> appropriate to this attribute set.
  381. *
  382. * @param attributes the attributes to assign to the new
  383. * <code>Font</code>
  384. * @return a new <code>Font</code> created with the specified
  385. * attributes
  386. * @since 1.2
  387. * @see java.awt.font.TextAttribute
  388. */
  389. public static Font getFont(Map attributes) {
  390. Font font = (Font)attributes.get(TextAttribute.FONT);
  391. if (font != null) {
  392. return font;
  393. }
  394. return get(new Key(attributes));
  395. }
  396. private static SoftReference cacheRef = new SoftReference(new HashMap());
  397. private static Font get(Key key) {
  398. Font f = null;
  399. Map cache = (Map)cacheRef.get();
  400. if (cache == null) {
  401. cache = new HashMap();
  402. cacheRef = new SoftReference(cache);
  403. } else {
  404. f = (Font)cache.get(key);
  405. }
  406. if (f == null) {
  407. f = new Font(key.attrs);
  408. cache.put(key, f);
  409. }
  410. return f;
  411. }
  412. // ideally we would construct a font directly from a key, and not
  413. // bother to keep the map around for this. That ought to be a bit
  414. // faster than picking out the params from the Map again, but the
  415. // cache ought to hide this overhead, so I'll skip it for now.
  416. private static class Key {
  417. String family = "Dialog"; // defaults chosen to match Font implementation
  418. float weight = 1.0f;
  419. float posture = 0.0f;
  420. float size = 12.0f;
  421. double[] txdata = null; // identity
  422. Map attrs;
  423. int hashCode = 0;
  424. Key(Map map) {
  425. attrs = map;
  426. Object o = map.get(TextAttribute.FAMILY);
  427. if (o != null) {
  428. family = (String)o;
  429. }
  430. hashCode = family.hashCode();
  431. o = map.get(TextAttribute.WEIGHT);
  432. if (o != null && o != TextAttribute.WEIGHT_REGULAR) {
  433. // ugh, force to the only values we understand
  434. // weight is either bold, or it's not...
  435. float xweight = ((Float)o).floatValue();
  436. if (xweight == TextAttribute.WEIGHT_BOLD.floatValue()) {
  437. weight = xweight;
  438. hashCode = (hashCode << 3) ^ Float.floatToIntBits(weight);
  439. }
  440. }
  441. o = map.get(TextAttribute.POSTURE);
  442. if (o != null && o != TextAttribute.POSTURE_REGULAR) {
  443. // ugh, same problem as with weight
  444. float xposture = ((Float)o).floatValue();
  445. if (xposture == TextAttribute.POSTURE_OBLIQUE.floatValue()) {
  446. posture = xposture;
  447. hashCode = (hashCode << 3) ^ Float.floatToIntBits(posture);
  448. }
  449. }
  450. o = map.get(TextAttribute.SIZE);
  451. if (o != null) {
  452. size = ((Float)o).floatValue();
  453. if (size != 12.0f) {
  454. hashCode = (hashCode << 3) ^ Float.floatToIntBits(size);
  455. }
  456. }
  457. o = map.get(TextAttribute.TRANSFORM);
  458. if (o != null) {
  459. AffineTransform tx = null;
  460. if (o instanceof TransformAttribute) {
  461. TransformAttribute ta = (TransformAttribute)o;
  462. if (!ta.isIdentity()) {
  463. tx = ta.getTransform();
  464. }
  465. } else if (o instanceof AffineTransform) {
  466. AffineTransform at = (AffineTransform)o;
  467. if (!at.isIdentity()) {
  468. tx = at;
  469. }
  470. }
  471. if (tx != null) {
  472. txdata = new double[6];
  473. tx.getMatrix(txdata);
  474. hashCode = (hashCode << 3) ^ new Double(txdata[0]).hashCode();
  475. }
  476. }
  477. }
  478. public int hashCode() {
  479. return hashCode;
  480. }
  481. public boolean equals(Object rhs) {
  482. Key rhskey = (Key)rhs;
  483. if (this.hashCode == rhskey.hashCode &&
  484. this.size == rhskey.size &&
  485. this.weight == rhskey.weight &&
  486. this.posture == rhskey.posture &&
  487. this.family.equals(rhskey.family) &&
  488. ((this.txdata == null) == (rhskey.txdata == null))) {
  489. if (this.txdata != null) {
  490. for (int i = 0; i < this.txdata.length; ++i) {
  491. if (this.txdata[i] != rhskey.txdata[i]) {
  492. return false;
  493. }
  494. }
  495. }
  496. return true;
  497. }
  498. return false;
  499. }
  500. }
  501. /**
  502. * Returns a new <code>Font</code> with the specified font type
  503. * and input data. The new <code>Font</code> is
  504. * created with a point size of 1 and style {@link #PLAIN PLAIN}.
  505. * This base font can then be used with the <code>deriveFont</code>
  506. * methods in this class to derive new <code>Font</code> objects with
  507. * varying sizes, styles, transforms and font features. This
  508. * method does not close the {@link InputStream}.
  509. * @param fontFormat the type of the <code>Font</code>, which is
  510. * {@link #TRUETYPE_FONT TRUETYPE_FONT} if a TrueType is desired. Other
  511. * types might be provided in the future.
  512. * @param fontStream an <code>InputStream</code> object representing the
  513. * input data for the font.
  514. * @return a new <code>Font</code> created with the specified font type.
  515. * @throws IllegalArgumentException if <code>fontType</code> is not
  516. * <code>TRUETYPE_FONT</code>
  517. * @throws FontFormatException if the <code>fontStream</code> data does
  518. * not contain the required Truetype font tables.
  519. * @throws IOException if the <code>fontStream</code>
  520. * cannot be completely read.
  521. * @since 1.3
  522. */
  523. // REMIND - need to update this for serialization
  524. public static Font createFont ( int fontFormat, InputStream fontStream )
  525. throws java.awt.FontFormatException, java.io.IOException {
  526. if ( fontFormat != Font.TRUETYPE_FONT ) {
  527. throw new IllegalArgumentException ( "font format not recognized" );
  528. }
  529. final File fontFile =
  530. (File)java.security.AccessController.doPrivileged(
  531. new java.security.PrivilegedAction() {
  532. public Object run() {
  533. File tFile = null;
  534. try {
  535. tFile = File.createTempFile ( "+~JF", ".tmp", null );
  536. tFile.deleteOnExit();
  537. } catch (IOException ioe) {
  538. }
  539. return tFile;
  540. }
  541. });
  542. BufferedInputStream bufferedStream = null;
  543. bufferedStream = new BufferedInputStream ( fontStream );
  544. FileOutputStream theOutputStream =
  545. (FileOutputStream)java.security.AccessController.doPrivileged(
  546. new java.security.PrivilegedAction() {
  547. public Object run() {
  548. FileOutputStream fos = null;
  549. try {
  550. fos = new FileOutputStream(fontFile);
  551. } catch (IOException ioe) {
  552. }
  553. return fos;
  554. }
  555. });
  556. int bytesRead = 0;
  557. byte buf[];
  558. int bufSize = 8192; // this seems like a reasonable number
  559. buf = new byte[bufSize];
  560. while ( bytesRead != -1 ) {
  561. bytesRead = bufferedStream.read ( buf, 0, bufSize );
  562. if ( bytesRead != -1 )
  563. theOutputStream.write ( buf, 0, bytesRead );
  564. }
  565. bufferedStream.close();
  566. theOutputStream.close();
  567. String createName = SunGraphicsEnvironment.createFont( fontFile );
  568. if ( createName == null ) {
  569. throw new FontFormatException ( "Unable to create font - bad font data" );
  570. }
  571. // System.out.println (" Creating font with the name " + createName );
  572. Font createFont = new Font ( createName, Font.PLAIN, 1, true);
  573. return createFont;
  574. }
  575. /**
  576. * Returns a copy of the transform associated with this
  577. * <code>Font</code>.
  578. * @return an {@link AffineTransform} object representing the
  579. * transform attribute of this <code>Font</code> object.
  580. */
  581. public AffineTransform getTransform() {
  582. Object obj = fRequestedAttributes.get(TextAttribute.TRANSFORM);
  583. if (obj != null) {
  584. if( obj instanceof TransformAttribute ){
  585. return ((TransformAttribute)obj).getTransform();
  586. }
  587. else {
  588. if ( obj instanceof AffineTransform){
  589. return new AffineTransform((AffineTransform)obj);
  590. }
  591. }
  592. }else{
  593. obj = new AffineTransform();
  594. }
  595. return (AffineTransform)obj;
  596. }
  597. /**
  598. * Returns the family name of this <code>Font</code>.
  599. *
  600. * <p>The family name of a font is font specific. Two fonts such as
  601. * Helvetica Italic and Helvetica Bold have the same family name,
  602. * <i>Helvetica</i>, whereas their font face names are
  603. * <i>Helvetica Bold</i> and <i>Helvetica Italic</i>. The list of
  604. * available family names may be obtained by using the
  605. * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
  606. *
  607. * <p>Use <code>getName</code> to get the logical name of the font.
  608. * Use <code>getFontName</code> to get the font face name of the font.
  609. * @return a <code>String</code> that is the family name of this
  610. * <code>Font</code>.
  611. *
  612. * @see #getName
  613. * @see #getFontName
  614. * @since JDK1.1
  615. */
  616. public String getFamily() {
  617. return getFamily_NoClientCode();
  618. }
  619. // NOTE: This method is called by privileged threads.
  620. // We implement this functionality in a package-private
  621. // method to insure that it cannot be overridden by client
  622. // subclasses.
  623. // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
  624. final String getFamily_NoClientCode() {
  625. return getFamily(Locale.getDefault());
  626. }
  627. /**
  628. * Returns the family name of this <code>Font</code>, localized for
  629. * the specified locale.
  630. *
  631. * <p>The family name of a font is font specific. Two fonts such as
  632. * Helvetica Italic and Helvetica Bold have the same family name,
  633. * <i>Helvetica</i>, whereas their font face names are
  634. * <i>Helvetica Bold</i> and <i>Helvetica Italic</i>. The list of
  635. * available family names may be obtained by using the
  636. * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
  637. *
  638. * <p>Use <code>getFontName</code> to get the font face name of the font.
  639. * @param l locale for which to get the family name
  640. * @return a <code>String</code> representing the family name of the
  641. * font, localized for the specified locale.
  642. * @see #getFontName
  643. * @see java.util.Locale
  644. * @since 1.2
  645. */
  646. public String getFamily(Locale l) {
  647. if (SunGraphicsEnvironment.isLogicalFont(name)) {
  648. return name;
  649. }
  650. short lcid = NativeFontWrapper.getLCIDFromLocale(l);
  651. return NativeFontWrapper.getFamilyName(this, lcid);
  652. }
  653. /**
  654. * Returns the postscript name of this <code>Font</code>.
  655. * Use <code>getFamily</code> to get the family name of the font.
  656. * Use <code>getFontName</code> to get the font face name of the font.
  657. * @return a <code>String</code> representing the postscript name of
  658. * this <code>Font</code>.
  659. * @since 1.2
  660. */
  661. public String getPSName() {
  662. String psName = NativeFontWrapper.getPostscriptName(this);
  663. return (psName == null ? getFontName() : psName);
  664. }
  665. /**
  666. * Returns the logical name of this <code>Font</code>.
  667. * Use <code>getFamily</code> to get the family name of the font.
  668. * Use <code>getFontName</code> to get the font face name of the font.
  669. * @return a <code>String</code> representing the logical name of
  670. * this <code>Font</code>.
  671. * @see #getFamily
  672. * @see #getFontName
  673. * @since JDK1.0
  674. */
  675. public String getName() {
  676. return new String(name);
  677. }
  678. /**
  679. * Returns the font face name of this <code>Font</code>. For example,
  680. * Helvetica Bold could be returned as a font face name.
  681. * Use <code>getFamily</code> to get the family name of the font.
  682. * Use <code>getName</code> to get the logical name of the font.
  683. * @return a <code>String</code> representing the font face name of
  684. * this <code>Font</code>.
  685. * @see #getFamily
  686. * @see #getName
  687. * @since 1.2
  688. */
  689. public String getFontName() {
  690. return getFontName(Locale.getDefault());
  691. }
  692. /**
  693. * Returns the font face name of the <code>Font</code>, localized
  694. * for the specified locale. For example, Helvetica Fett could be
  695. * returned as the font face name.
  696. * Use <code>getFamily</code> to get the family name of the font.
  697. * @param l a locale for which to get the font face name
  698. * @return a <code>String</code> representing the font face name,
  699. * localized for the specified locale.
  700. * @see #getFamily
  701. * @see java.util.Locale
  702. */
  703. public String getFontName(Locale l) {
  704. if (SunGraphicsEnvironment.isLogicalFont(name)) {
  705. return name + "." + SunGraphicsEnvironment.styleStr(style);
  706. }
  707. short lcid = NativeFontWrapper.getLCIDFromLocale(l);
  708. return NativeFontWrapper.getFullName(this, lcid);
  709. }
  710. /**
  711. * Returns the style of this <code>Font</code>. The style can be
  712. * PLAIN, BOLD, ITALIC, or BOLD+ITALIC.
  713. * @return the style of this <code>Font</code>
  714. * @see #isPlain
  715. * @see #isBold
  716. * @see #isItalic
  717. * @since JDK1.0
  718. */
  719. public int getStyle() {
  720. return style;
  721. }
  722. /**
  723. * Returns the point size of this <code>Font</code>, rounded to
  724. * an integer.
  725. * Most users are familiar with the idea of using <i>point size</i> to
  726. * specify the size of glyphs in a font. This point size defines a
  727. * measurement between the baseline of one line to the baseline of the
  728. * following line in a single spaced text document. The point size is
  729. * based on <i>typographic points</i>, approximately 1/72 of an inch.
  730. * <p>
  731. * The Java(tm)2D API adopts the convention that one point is
  732. * equivalent to one unit in user coordinates. When using a
  733. * normalized transform for converting user space coordinates to
  734. * device space coordinates 72 user
  735. * space units equal 1 inch in device space. In this case one point
  736. * is 1/72 of an inch.
  737. * @return the point size of this <code>Font</code> in 1/72 of an
  738. * inch units.
  739. * @see #getSize2D
  740. * @see GraphicsConfiguration#getDefaultTransform
  741. * @see GraphicsConfiguration#getNormalizingTransform
  742. * @since JDK1.0
  743. */
  744. public int getSize() {
  745. return size;
  746. }
  747. /**
  748. * Returns the point size of this <code>Font</code> in
  749. * <code>float</code> value.
  750. * @return the point size of this <code>Font</code> as a
  751. * <code>float</code> value.
  752. * @see #getSize
  753. * @since 1.2
  754. */
  755. public float getSize2D() {
  756. return pointSize;
  757. }
  758. /**
  759. * Indicates whether or not this <code>Font</code> object's style is
  760. * PLAIN.
  761. * @return <code>true</code> if this <code>Font</code> has a
  762. * PLAIN sytle;
  763. * <code>false</code> otherwise.
  764. * @see java.awt.Font#getStyle
  765. * @since JDK1.0
  766. */
  767. public boolean isPlain() {
  768. return style == 0;
  769. }
  770. /**
  771. * Indicates whether or not this <code>Font</code> object's style is
  772. * BOLD.
  773. * @return <code>true</code> if this <code>Font</code> object's
  774. * style is BOLD;
  775. * <code>false</code> otherwise.
  776. * @see java.awt.Font#getStyle
  777. * @since JDK1.0
  778. */
  779. public boolean isBold() {
  780. return (style & BOLD) != 0;
  781. }
  782. /**
  783. * Indicates whether or not this <code>Font</code> object's style is
  784. * ITALIC.
  785. * @return <code>true</code> if this <code>Font</code> object's
  786. * style is ITALIC;
  787. * <code>false</code> otherwise.
  788. * @see java.awt.Font#getStyle
  789. * @since JDK1.0
  790. */
  791. public boolean isItalic() {
  792. return (style & ITALIC) != 0;
  793. }
  794. /**
  795. * Indicates whether or not this <code>Font</code> object has a
  796. * transform that affects its size in addition to the Size
  797. * attribute.
  798. * @return <code>true</code> if this <code>Font</code> object
  799. * has a non-identity AffineTransform attribute.
  800. * <code>false</code> otherwise.
  801. * @see java.awt.Font#getTransform
  802. * @since 1.4
  803. */
  804. public boolean isTransformed() {
  805. return nonIdentityTx;
  806. }
  807. /**
  808. * Returns a <code>Font</code> object from the system properties list.
  809. * @param nm the property name
  810. * @return a <code>Font</code> object that the property name
  811. * describes.
  812. * @since 1.2
  813. */
  814. public static Font getFont(String nm) {
  815. return getFont(nm, null);
  816. }
  817. /**
  818. * Returns the <code>Font</code> that the <code>str</code>
  819. * argument describes.
  820. * To ensure that this method returns the desired Font,
  821. * format the <code>str</code> parameter in
  822. * one of two ways:
  823. * <p>
  824. * "fontfamilyname-style-pointsize" or <br>
  825. * "fontfamilyname style pointsize"<p>
  826. * in which <i>style</i> is one of the three
  827. * case-insensitive strings:
  828. * <code>"BOLD"</code>, <code>"BOLDITALIC"</code>, or
  829. * <code>"ITALIC"</code>, and pointsize is a decimal
  830. * representation of the point size.
  831. * For example, if you want a font that is Arial, bold, and
  832. * a point size of 18, you would call this method with:
  833. * "Arial-BOLD-18".
  834. * <p>
  835. * The default size is 12 and the default style is PLAIN.
  836. * If you don't specify a valid size, the returned
  837. * <code>Font</code> has a size of 12. If you don't specify
  838. * a valid style, the returned Font has a style of PLAIN.
  839. * If you do not provide a valid font family name in
  840. * the <code>str</code> argument, this method still returns
  841. * a valid font with a family name of "dialog".
  842. * To determine what font family names are available on
  843. * your system, use the
  844. * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method.
  845. * If <code>str</code> is <code>null</code>, a new <code>Font</code>
  846. * is returned with the family name "dialog", a size of 12 and a
  847. * PLAIN style.
  848. If <code>str</code> is <code>null</code>,
  849. * a new <code>Font</code> is returned with the name "dialog", a
  850. * size of 12 and a PLAIN style.
  851. * @param str the name of the font, or <code>null</code>
  852. * @return the <code>Font</code> object that <code>str</code>
  853. * describes, or a new default <code>Font</code> if
  854. * <code>str</code> is <code>null</code>.
  855. * @see #getFamily
  856. * @since JDK1.1
  857. */
  858. public static Font decode(String str) {
  859. String fontName = str;
  860. String fontSizeStr;
  861. int index;
  862. int fontSize = 12;
  863. int fontStyle = Font.PLAIN;
  864. if (str == null) {
  865. return new Font("dialog", fontStyle, fontSize);
  866. }
  867. int i = str.indexOf('-');
  868. if (i >= 0) {
  869. fontName = str.substring(0, i);
  870. str = str.substring(i+1);
  871. str = str.toLowerCase(); // name may be in upper/lower causing incorrect style matching
  872. index = str.indexOf ( "bold-italic" );
  873. if ( index != -1 ) {
  874. fontStyle = Font.BOLD | Font.ITALIC;
  875. }
  876. if ( index == -1 ) {
  877. index = str.indexOf ( "bolditalic" );
  878. if (index != -1) {
  879. fontStyle = Font.BOLD | Font.ITALIC;
  880. }
  881. }
  882. if ( index == -1 ) {
  883. index = str.indexOf ( "bold" );
  884. if ( index != -1 ) {
  885. fontStyle = Font.BOLD;
  886. }
  887. }
  888. if ( index == -1 ) {
  889. index = str.indexOf ( "italic" );
  890. if (index != -1) {
  891. fontStyle = Font.ITALIC;
  892. }
  893. }
  894. index = str.lastIndexOf ( "-" );
  895. if ( index != -1 ) {
  896. str = str.substring(index+1);
  897. }
  898. try {
  899. fontSize = Integer.valueOf(str).intValue();
  900. } catch (NumberFormatException e) {
  901. }
  902. } else if ( i == -1 ) {
  903. fontStyle = Font.PLAIN;
  904. fontSize = 12;
  905. str = str.toLowerCase();
  906. index = str.indexOf ( "bolditalic" );
  907. if (index != -1 ) {
  908. fontStyle = Font.BOLD | Font.ITALIC;
  909. }
  910. if ( index == -1 ) {
  911. index = str.indexOf ( "bold italic" );
  912. if ( index != -1 ) {
  913. fontStyle = Font.BOLD | Font.ITALIC;
  914. }
  915. }
  916. if ( index == -1 ) {
  917. index = str.indexOf ("bold");
  918. if ( index != -1 ) {
  919. fontStyle = Font.BOLD;
  920. }
  921. }
  922. if ( index == -1 ) {
  923. index = str.indexOf ("italic");
  924. if ( index != -1 )
  925. fontStyle = Font.ITALIC;
  926. }
  927. if ( index != -1 ) { // found a style
  928. fontName = fontName.substring(0, index );
  929. fontName = fontName.trim();
  930. }
  931. index = str.lastIndexOf (" " );
  932. if ( index != -1 ) {
  933. fontSizeStr = str.substring ( index );
  934. fontSizeStr = fontSizeStr.trim();
  935. try {
  936. fontSize = Integer.valueOf(fontSizeStr).intValue();
  937. } catch (NumberFormatException e) {
  938. }
  939. }
  940. }
  941. return new Font(fontName, fontStyle, fontSize);
  942. }
  943. /**
  944. * Gets the specified <code>Font</code> from the system properties
  945. * list. As in the <code>getProperty</code> method of
  946. * <code>System</code>, the first
  947. * argument is treated as the name of a system property to be
  948. * obtained. The <code>String</code> value of this property is then
  949. * interpreted as a <code>Font</code> object.
  950. * <p>
  951. * The property value should be one of the following forms:
  952. * <ul>
  953. * <li><em>fontname-style-pointsize</em>
  954. * <li><em>fontname-pointsize</em>
  955. * <li><em>fontname-style</em>
  956. * <li><em>fontname</em>
  957. * </ul>
  958. * where <i>style</i> is one of the three case-insensitive strings
  959. * <code>"BOLD"</code>, <code>"BOLDITALIC"</code>, or
  960. * <code>"ITALIC"</code>, and point size is a decimal
  961. * representation of the point size.
  962. * <p>
  963. * The default style is <code>PLAIN</code>. The default point size
  964. * is 12.
  965. * <p>
  966. * If the specified property is not found, the <code>font</code>
  967. * argument is returned instead.
  968. * @param nm the case-insensitive property name
  969. * @param font a default <code>Font</code> to return if property
  970. * <code>nm</code> is not defined
  971. * @return the <code>Font</code> value of the property.
  972. * @see #decode(String)
  973. */
  974. public static Font getFont(String nm, Font font) {
  975. String str = null;
  976. try {
  977. str =System.getProperty(nm);
  978. } catch(SecurityException e) {
  979. }
  980. if (str == null) {
  981. return font;
  982. }
  983. return decode ( str );
  984. }
  985. /**
  986. * Returns a hashcode for this <code>Font</code>.
  987. * @return a hashcode value for this <code>Font</code>.
  988. * @since JDK1.0
  989. */
  990. public int hashCode() {
  991. return name.hashCode() ^ style ^ size;
  992. }
  993. /**
  994. * Compares this <code>Font</code> object to the specified
  995. * <code>Object</code>.
  996. * @param obj the <code>Object</code> to compare
  997. * @return <code>true</code> if the objects are the same
  998. * or if the argument is a <code>Font</code> object
  999. * describing the same font as this object;
  1000. * <code>false</code> otherwise.
  1001. * @since JDK1.0
  1002. */
  1003. public boolean equals(Object obj) {
  1004. if (obj == this) {
  1005. return true;
  1006. }
  1007. if (obj != null) {
  1008. try {
  1009. Font font = (Font)obj;
  1010. double[] thismat = this.getMatrix();
  1011. double[] thatmat = font.getMatrix();
  1012. return (size == font.size)
  1013. && (pointSize == font.pointSize)
  1014. && (style == font.style)
  1015. && name.equals(font.name)
  1016. && thismat[0] == thatmat[0]
  1017. && thismat[1] == thatmat[1]
  1018. && thismat[2] == thatmat[2]
  1019. && thismat[3] == thatmat[3];
  1020. }
  1021. catch (ClassCastException e) {
  1022. }
  1023. }
  1024. return false;
  1025. }
  1026. /**
  1027. * Converts this <code>Font</code> object to a <code>String</code>
  1028. * representation.
  1029. * @return a <code>String</code> representation of this
  1030. * <code>Font</code> object.
  1031. * @since JDK1.0
  1032. */
  1033. // NOTE: This method may be called by privileged threads.
  1034. // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
  1035. public String toString() {
  1036. String strStyle;
  1037. if (isBold()) {
  1038. strStyle = isItalic() ? "bolditalic" : "bold";
  1039. } else {
  1040. strStyle = isItalic() ? "italic" : "plain";
  1041. }
  1042. return getClass().getName() + "[family=" + getFamily() + ",name=" + name + ",style=" +
  1043. strStyle + ",size=" + size + "]";
  1044. } // toString()
  1045. /** Serialization support. A <code>readObject</code>
  1046. * method is neccessary because the constructor creates
  1047. * the font's peer, and we can't serialize the peer.
  1048. * Similarly the computed font "family" may be different
  1049. * at <code>readObject</code> time than at
  1050. * <code>writeObject</code> time. An integer version is
  1051. * written so that future versions of this class will be
  1052. * able to recognize serialized output from this one.
  1053. */
  1054. /**
  1055. * The <code>Font</code> Serializable Data Form.
  1056. *
  1057. * @serial
  1058. */
  1059. private int fontSerializedDataVersion = 1;
  1060. /**
  1061. * Writes default serializable fields to a stream.
  1062. *
  1063. * @param s the <code>ObjectOutputStream</code> to write
  1064. * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
  1065. * @see #readObject(java.io.ObjectInputStream)
  1066. */
  1067. private void writeObject(java.io.ObjectOutputStream s)
  1068. throws java.lang.ClassNotFoundException,
  1069. java.io.IOException
  1070. {
  1071. s.defaultWriteObject();
  1072. }
  1073. /**
  1074. * Reads the <code>ObjectInputStream</code>.
  1075. * Unrecognized keys or values will be ignored.
  1076. *
  1077. * @param s the <code>ObjectInputStream</code> to read
  1078. * @serial
  1079. * @see #writeObject(java.io.ObjectOutputStream)
  1080. */
  1081. private void readObject(java.io.ObjectInputStream s)
  1082. throws java.lang.ClassNotFoundException,
  1083. java.io.IOException
  1084. {
  1085. s.defaultReadObject();
  1086. if (pointSize == 0) {
  1087. pointSize = (float)size;
  1088. }
  1089. initializeFont(fRequestedAttributes);
  1090. }
  1091. /**
  1092. * Returns the number of glyphs in this <code>Font</code>. Glyph codes
  1093. * for this <code>Font</code> range from 0 to
  1094. * <code>getNumGlyphs()</code> - 1.
  1095. * @return the number of glyphs in this <code>Font</code>.
  1096. * @since 1.2
  1097. */
  1098. public int getNumGlyphs() {
  1099. if (numGlyphs == -1) {
  1100. numGlyphs = NativeFontWrapper.getNumGlyphs(this);
  1101. }
  1102. return numGlyphs;
  1103. }
  1104. /**
  1105. * Returns the glyphCode which is used when this <code>Font</code>
  1106. * does not have a glyph for a specified unicode.
  1107. * @return the glyphCode of this <code>Font</code>.
  1108. * @since 1.2
  1109. */
  1110. public int getMissingGlyphCode() {
  1111. if (missingGlyph == -1) {
  1112. missingGlyph = NativeFontWrapper.getMissingGlyphCode(this);
  1113. }
  1114. return missingGlyph;
  1115. }
  1116. /**
  1117. * get the transform matrix for this font.
  1118. */
  1119. private static double cachedMat[];
  1120. private double[] getMatrix() {
  1121. if (matrix == null) {
  1122. double ptSize = this.getSize2D();
  1123. if (nonIdentityTx) {
  1124. AffineTransform tx = getTransform();
  1125. tx.scale(ptSize, ptSize);
  1126. matrix = new double[] { tx.getScaleX(), tx.getShearY(),
  1127. tx.getShearX(), tx.getScaleY() };
  1128. } else {
  1129. synchronized (Font.class) {
  1130. double[] m = cachedMat;
  1131. if (m == null || m[0] != ptSize) {
  1132. cachedMat = m = new double[] {ptSize, 0, 0, ptSize};
  1133. }
  1134. matrix = m;
  1135. }
  1136. }
  1137. }
  1138. return matrix;
  1139. }
  1140. /**
  1141. * Returns the baseline appropriate for displaying this character.
  1142. * <p>
  1143. * Large fonts can support different writing systems, and each system can
  1144. * use a different baseline.
  1145. * The character argument determines the writing system to use. Clients
  1146. * should not assume all characters use the same baseline.
  1147. *
  1148. * @param c a character used to identify the writing system
  1149. * @return the baseline appropriate for the specified character.
  1150. * @see LineMetrics#getBaselineOffsets
  1151. * @see #ROMAN_BASELINE
  1152. * @see #CENTER_BASELINE
  1153. * @see #HANGING_BASELINE
  1154. * @since 1.2
  1155. */
  1156. public byte getBaselineFor(char c) {
  1157. return NativeFontWrapper.getBaselineFor(this, c);
  1158. }
  1159. /**
  1160. * Returns a map of font attributes available in this
  1161. * <code>Font</code>. Attributes include things like ligatures and
  1162. * glyph substitution.
  1163. * @return the attributes map of this <code>Font</code>.
  1164. */
  1165. public Map getAttributes(){
  1166. return (Map)fRequestedAttributes.clone();
  1167. }
  1168. /**
  1169. * Returns the keys of all the attributes supported by this
  1170. * <code>Font</code>. These attributes can be used to derive other
  1171. * fonts.
  1172. * @return an array containing the keys of all the attributes
  1173. * supported by this <code>Font</code>.
  1174. * @since 1.2
  1175. */
  1176. public Attribute[] getAvailableAttributes(){
  1177. Attribute attributes[] = {
  1178. TextAttribute.FAMILY,
  1179. TextAttribute.WEIGHT,
  1180. TextAttribute.POSTURE,
  1181. TextAttribute.SIZE,
  1182. TextAttribute.TRANSFORM
  1183. };
  1184. return attributes;
  1185. }
  1186. /**
  1187. * Creates a new <code>Font</code> object by replicating this
  1188. * <code>Font</code> object and applying a new style and size.
  1189. * @param style the style for the new <code>Font</code>
  1190. * @param size the size for the new <code>Font</code>
  1191. * @return a new <code>Font</code> object.
  1192. * @since 1.2
  1193. */
  1194. public Font deriveFont(int style, float size){
  1195. Hashtable newAttributes = (Hashtable)fRequestedAttributes.clone();
  1196. applyStyle(style, newAttributes);
  1197. applySize(size, newAttributes);
  1198. return new Font(newAttributes, createdFont);
  1199. }
  1200. /**
  1201. * Creates a new <code>Font</code> object by replicating this
  1202. * <code>Font</code> object and applying a new style and transform.
  1203. * @param style the style for the new <code>Font</code>
  1204. * @param trans the <code>AffineTransform</code> associated with the
  1205. * new <code>Font</code>
  1206. * @return a new <code>Font</code> object.
  1207. * @throws IllegalArgumentException if <code>trans</code> is
  1208. * <code>null</code>
  1209. * @since 1.2
  1210. */
  1211. public Font deriveFont(int style, AffineTransform trans){
  1212. Hashtable newAttributes = (Hashtable)fRequestedAttributes.clone();
  1213. applyStyle(style, newAttributes);
  1214. applyTransform(trans, newAttributes);
  1215. return new Font(newAttributes, createdFont);
  1216. }
  1217. /**
  1218. * Creates a new <code>Font</code> object by replicating the current
  1219. * <code>Font</code> object and applying a new size to it.
  1220. * @param size the size for the new <code>Font</code>.
  1221. * @return a new <code>Font</code> object.
  1222. * @since 1.2
  1223. */
  1224. public Font deriveFont(float size){
  1225. Hashtable newAttributes = (Hashtable)fRequestedAttributes.clone();
  1226. applySize(size, newAttributes);
  1227. return new Font(newAttributes, createdFont);
  1228. }
  1229. /**
  1230. * Creates a new <code>Font</code> object by replicating the current
  1231. * <code>Font</code> object and applying a new transform to it.
  1232. * @param trans the <code>AffineTransform</code> associated with the
  1233. * new <code>Font</code>
  1234. * @return a new <code>Font</code> object.
  1235. * @throws IllegalArgumentException if <code>trans</code> is
  1236. * <code>null</code>
  1237. * @since 1.2
  1238. */
  1239. public Font deriveFont(AffineTransform trans){
  1240. Hashtable newAttributes = (Hashtable)fRequestedAttributes.clone();
  1241. applyTransform(trans, newAttributes);
  1242. return new Font(newAttributes, createdFont);
  1243. }
  1244. /**
  1245. * Creates a new <code>Font</code> object by replicating the current
  1246. * <code>Font</code> object and applying a new style to it.
  1247. * @param style the style for the new <code>Font</code>
  1248. * @return a new <code>Font</code> object.
  1249. * @since 1.2
  1250. */
  1251. public Font deriveFont(int style){
  1252. Hashtable newAttributes = (Hashtable)fRequestedAttributes.clone();
  1253. applyStyle(style, newAttributes);
  1254. return new Font(newAttributes, createdFont);
  1255. }
  1256. /**
  1257. * Creates a new <code>Font</code> object by replicating the current
  1258. * <code>Font</code> object and applying a new set of font attributes
  1259. * to it.
  1260. * @param attributes a map of attributes enabled for the new
  1261. * <code>Font</code>
  1262. * @return a new <code>Font</code> object.
  1263. * @since 1.2
  1264. */
  1265. public Font deriveFont(Map attributes) {
  1266. if (attributes == null || attributes.size() == 0) {
  1267. return this;
  1268. }
  1269. Hashtable newAttrs = new Hashtable(getAttributes());
  1270. Attribute validAttribs[] = getAvailableAttributes();
  1271. Object obj;
  1272. for(int i = 0; i < validAttribs.length; i++){
  1273. if ((obj = attributes.get(validAttribs[i])) != null) {
  1274. newAttrs.put(validAttribs[i],obj);
  1275. }
  1276. }
  1277. return new Font(newAttrs, createdFont);
  1278. }
  1279. /**
  1280. * Checks if this <code>Font</code> has a glyph for the specified
  1281. * character.
  1282. * @param c a unicode character code
  1283. * @return <code>true</code> if this <code>Font</code> can display the
  1284. * character; <code>false</code> otherwise.
  1285. * @since 1.2
  1286. */
  1287. public boolean canDisplay(char c){
  1288. return NativeFontWrapper.canDisplay(this, c);
  1289. }
  1290. /**
  1291. * Indicates whether or not this <code>Font</code> can display a
  1292. * specified <code>String</code>. For strings with Unicode encoding,
  1293. * it is important to know if a particular font can display the
  1294. * string. This method returns an offset into the <code>String</code>
  1295. * <code>str</code> which is the first character this
  1296. * <code>Font</code> cannot display without using the missing glyph
  1297. * code. If the <code>Font</code> can display all characters, -1 is
  1298. * returned.
  1299. * @param str a <code>String</code> object
  1300. * @return an offset into <code>str</code> that points
  1301. * to the first character in <code>str</code> that this
  1302. * <code>Font</code> cannot display; or <code>-1</code> if
  1303. * this <code>Font</code> can display all characters in
  1304. * <code>str</code>.
  1305. * @since 1.2
  1306. */
  1307. public int canDisplayUpTo(String str) {
  1308. return canDisplayUpTo(new StringCharacterIterator(str), 0,
  1309. str.length());
  1310. }
  1311. /**
  1312. * Indicates whether or not this <code>Font</code> can display
  1313. * the characters in the specified <code>text</code>
  1314. * starting at <code>start</code> and ending at
  1315. * <code>limit</code>. This method is a convenience overload.
  1316. * @param text the specified array of characters
  1317. * @param start the specified starting offset into the specified array
  1318. * of characters
  1319. * @param limit the specified ending offset into the specified
  1320. * array of characters
  1321. * @return an offset into <code>text</code> that points
  1322. * to the first character in <code>text</code> that this
  1323. * <code>Font</code> cannot display; or <code>-1</code> if
  1324. * this <code>Font</code> can display all characters in
  1325. * <code>text</code>.
  1326. * @since 1.2
  1327. */
  1328. public int canDisplayUpTo(char[] text, int start, int limit) {
  1329. while (start < limit && canDisplay(text[start])) {
  1330. ++start;
  1331. }
  1332. return start == limit ? -1 : start;
  1333. }
  1334. /**
  1335. * Indicates whether or not this <code>Font</code> can display
  1336. * the specified <code>String</code>. For strings with Unicode
  1337. * encoding, it is important to know if a particular font can display
  1338. * the string. This method returns an offset
  1339. * into the <code>String</code> <code>str</code> which is the first
  1340. * character this <code>Font</code> cannot display without using the
  1341. * missing glyph code . If this <code>Font</code> can display all
  1342. * characters, <code>-1</code> is returned.
  1343. * @param iter a {@link CharacterIterator} object
  1344. * @param start the specified starting offset into the specified array
  1345. * of characters
  1346. * @param limit the specified ending offset into the specified
  1347. * array of characters
  1348. * @return an offset into the <code>String</code> object that can be
  1349. * displayed by this <code>Font</code>.
  1350. * @since 1.2
  1351. */
  1352. public int canDisplayUpTo(CharacterIterator iter, int start, int limit) {
  1353. for (char c = iter.setIndex(start);
  1354. iter.getIndex() < limit && canDisplay(c);
  1355. c = iter.next()) {
  1356. }
  1357. int result = iter.getIndex();
  1358. return result == limit ? -1 : result;
  1359. }
  1360. /**
  1361. * Returns the italic angle of this <code>Font</code>. The italic angle
  1362. * is the inverse slope of the caret which best matches the posture of this
  1363. * <code>Font</code>.
  1364. * @see TextAttribute#POSTURE
  1365. * @return the angle of the ITALIC style of this <code>Font</code>.
  1366. */
  1367. public float getItalicAngle(){
  1368. double matrix[] = getMatrix();
  1369. return NativeFontWrapper.getItalicAngle(this, matrix, false, false);
  1370. }
  1371. /**
  1372. * Metrics from a font for layout of characters along a line
  1373. * and layout of set of lines.
  1374. */
  1375. private final class FontLineMetrics extends LineMetrics {
  1376. // package private fields
  1377. int numchars;
  1378. float ascent, descent, leading, height;
  1379. int baselineIndex;
  1380. float [] baselineOffsets;
  1381. float strikethroughOffset, strikethroughThickness;
  1382. float underlineOffset, underlineThickness;
  1383. public final int getNumChars() {
  1384. return numchars;
  1385. }
  1386. public final float getAscent() {
  1387. return ascent;
  1388. }
  1389. public final float getDescent() {
  1390. return descent;
  1391. }
  1392. public final float getLeading() {
  1393. return leading;
  1394. }
  1395. public final float getHeight() {
  1396. return height;
  1397. }
  1398. public final int getBaselineIndex() {
  1399. return baselineIndex;
  1400. }
  1401. public final float[] getBaselineOffsets() {
  1402. return baselineOffsets;
  1403. }
  1404. public final float getStrikethroughOffset() {
  1405. return strikethroughOffset;
  1406. }
  1407. public final float getStrikethroughThickness() {
  1408. return strikethroughThickness;
  1409. }
  1410. public final float getUnderlineOffset() {
  1411. return underlineOffset;
  1412. }
  1413. public final float getUnderlineThickness() {
  1414. return underlineThickness;
  1415. }
  1416. public final boolean equals(Object rhs) {
  1417. if (rhs != null) {
  1418. if (this == rhs) {
  1419. return true;
  1420. }
  1421. try {
  1422. FontLineMetrics rlm = (FontLineMetrics)rhs;
  1423. // does not include numchars, which should never have been here anyway
  1424. return ascent == rlm.ascent
  1425. && descent == rlm.descent
  1426. && leading == rlm.leading
  1427. && baselineIndex == rlm.baselineIndex
  1428. && baselineOffsets[0] == rlm.baselineOffsets[0]
  1429. && baselineOffsets[1] == rlm.baselineOffsets[1]
  1430. && baselineOffsets[2] == rlm.baselineOffsets[2]
  1431. && strikethroughOffset == rlm.strikethroughOffset
  1432. && strikethroughThickness == rlm.strikethroughThickness
  1433. && underlineOffset == rlm.underlineOffset
  1434. && underlineThickness == rlm.underlineThickness;
  1435. }
  1436. catch (ClassCastException e) {
  1437. }
  1438. }
  1439. return false;
  1440. }
  1441. }
  1442. /**
  1443. * Checks whether or not this <code>Font</code> has uniform
  1444. * line metrics. A logical <code>Font</code> might be a
  1445. * composite font, which means that it is composed of different
  1446. * physical fonts to cover different code ranges. Each of these
  1447. * fonts might have different <code>LineMetrics</code>. If the
  1448. * logical <code>Font</code> is a single
  1449. * font then the metrics would be uniform.
  1450. * @return <code>true</code> if this <code>Font</code> has
  1451. * uniform line metrics; <code>false</code> otherwise.
  1452. */
  1453. public boolean hasUniformLineMetrics() {
  1454. return false; // REMIND always safe, but prevents caller optimize
  1455. }
  1456. private FontLineMetrics defaultLineMetrics(FontRenderContext frc) {
  1457. FontLineMetrics flm = new FontLineMetrics();
  1458. double [] matrix = getMatrix();
  1459. float [] metrics = new float[4];
  1460. NativeFontWrapper.getFontMetrics(this, matrix,
  1461. frc.isAntiAliased(),
  1462. frc.usesFractionalMetrics(),
  1463. metrics);
  1464. flm.ascent = metrics[0];
  1465. flm.descent = metrics[1];
  1466. flm.leading = metrics[2];
  1467. flm.height = metrics[0] + metrics[1] + metrics[2];
  1468. flm.baselineIndex = 0;
  1469. flm.baselineOffsets = new float[3];
  1470. flm.baselineOffsets[0] = 0;
  1471. flm.strikethroughOffset = -(flm.ascent / 3.0f);
  1472. flm.strikethroughThickness = pointSize / 12.0f;
  1473. flm.underlineOffset = 0f;
  1474. flm.underlineThickness = pointSize / 12.0f;
  1475. return flm;
  1476. }
  1477. /**
  1478. * Returns a {@link LineMetrics} object created with the specified
  1479. * <code>String</code> and {@link FontRenderContext}.
  1480. * @param str the specified <code>String</code>
  1481. * @param frc the specified <code>FontRenderContext</code>
  1482. * @return a <code>LineMetrics</code> object created with the
  1483. * specified <code>String</code> and {@link FontRenderContext}.
  1484. */
  1485. public LineMetrics getLineMetrics( String str, FontRenderContext frc) {
  1486. FontLineMetrics flm = defaultLineMetrics(frc);
  1487. flm.numchars = str.length();
  1488. return flm;
  1489. }
  1490. /**
  1491. * Returns a <code>LineMetrics</code> object created with the
  1492. * specified arguments.
  1493. * @param str the specified <code>String</code>
  1494. * @param beginIndex the initial offset of <code>str</code>
  1495. * @param limit the end offset of <code>str</code>
  1496. * @param frc the specified <code>FontRenderContext</code>
  1497. * @return a <code>LineMetrics</code> object created with the
  1498. * specified arguments.
  1499. */
  1500. public LineMetrics getLineMetrics( String str,
  1501. int beginIndex, int limit,
  1502. FontRenderContext frc) {
  1503. FontLineMetrics flm = defaultLineMetrics(frc);
  1504. int numChars = limit - beginIndex;
  1505. flm.numchars = (numChars < 0)? 0: numChars;
  1506. return flm;
  1507. }
  1508. /**
  1509. * Returns a <code>LineMetrics</code> object created with the
  1510. * specified arguments.
  1511. * @param chars an array of characters
  1512. * @param beginIndex the initial offset of <code>chars</code>
  1513. * @param limit the end offset of <code>chars</code>
  1514. * @param frc the specified <code>FontRenderContext</code>
  1515. * @return a <code>LineMetrics</code> object created with the
  1516. * specified arguments.
  1517. */
  1518. public LineMetrics getLineMetrics(char [] chars,
  1519. int beginIndex, int limit,
  1520. FontRenderContext frc) {
  1521. FontLineMetrics flm = defaultLineMetrics(frc);
  1522. int numChars = limit - beginIndex;
  1523. flm.numchars = (numChars < 0)? 0: numChars;
  1524. return flm;
  1525. }
  1526. /**
  1527. * Returns a <code>LineMetrics</code> object created with the
  1528. * specified arguments.
  1529. * @param ci the specified <code>CharacterIterator</code>
  1530. * @param beginIndex the initial offset in <code>ci</code>
  1531. * @param limit the end offset of <code>ci</code>
  1532. * @param frc the specified <code>FontRenderContext</code>
  1533. * @return a <code>LineMetrics</code> object created with the
  1534. * specified arguments.
  1535. */
  1536. public LineMetrics getLineMetrics(CharacterIterator ci,
  1537. int beginIndex, int limit,
  1538. FontRenderContext frc) {
  1539. FontLineMetrics flm = defaultLineMetrics(frc);
  1540. int numChars = limit - beginIndex;
  1541. flm.numchars = (numChars < 0)? 0: numChars;
  1542. return flm;
  1543. }
  1544. /**
  1545. * Returns the logical bounds of the specified <code>String</code> in
  1546. * the specified <code>FontRenderContext</code>. The logical bounds
  1547. * contains the origin, ascent, advance, and height, which includes
  1548. * the leading. The logical bounds does not always enclose all the
  1549. * text. For example, in some languages and in some fonts, accent
  1550. * marks can be positioned above the ascent or below the descent.
  1551. * To obtain a visual bounding box, which encloses all the text,
  1552. * use the {@link TextLayout#getBounds() getBounds} method of
  1553. * <code>TextLayout</code>.
  1554. * @param str the specified <code>String</code>
  1555. * @param frc the specified <code>FontRenderContext</code>
  1556. * @return a {@link Rectangle2D} that is the bounding box of the
  1557. * specified <code>String</code> in the specified
  1558. * <code>FontRenderContext</code>.
  1559. * @see FontRenderContext
  1560. * @see Font#createGlyphVector
  1561. * @since 1.2
  1562. */
  1563. public Rectangle2D getStringBounds( String str, FontRenderContext frc) {
  1564. char[] array = str.toCharArray();
  1565. return getStringBounds(array, 0, array.length, frc);
  1566. }
  1567. /**
  1568. * Returns the logical bounds of the specified <code>String</code> in
  1569. * the specified <code>FontRenderContext</code>. The logical bounds
  1570. * contains the origin, ascent, advance, and height, which includes
  1571. * the leading. The logical bounds does not always enclose all the
  1572. * text. For example, in some languages and in some fonts, accent
  1573. * marks can be positioned above the ascent or below the descent.
  1574. * To obtain a visual bounding box, which encloses all the text,
  1575. * use the {@link TextLayout#getBounds() getBounds} method of
  1576. * <code>TextLayout</code>.
  1577. * @param str the specified <code>String</code>
  1578. * @param beginIndex the initial offset of <code>str</code>
  1579. * @param limit the end offset of <code>str</code>
  1580. * @param frc the specified <code>FontRenderContext</code>
  1581. * @return a <code>Rectangle2D</code> that is the bounding box of the
  1582. * specified <code>String</code> in the specified
  1583. * <code>FontRenderContext</code>.
  1584. * @throws IndexOutOfBoundsException if <code>beginIndex</code> is
  1585. * less than zero, or <code>limit</code> is greater than the
  1586. * length of <code>str</code>, or <code>beginIndex</code>
  1587. * is greater than <code>limit</code>.
  1588. * @see FontRenderContext
  1589. * @see Font#createGlyphVector
  1590. * @since 1.2
  1591. */
  1592. public Rectangle2D getStringBounds( String str,
  1593. int beginIndex, int limit,
  1594. FontRenderContext frc) {
  1595. String substr = str.substring(beginIndex, limit);
  1596. return getStringBounds(substr, frc);
  1597. }
  1598. /**
  1599. * Returns the logical bounds of the specified array of characters
  1600. * in the specified <code>FontRenderContext</code>. The logical
  1601. * bounds contains the origin, ascent, advance, and height, which
  1602. * includes the leading. The logical bounds does not always enclose
  1603. * all the text. For example, in some languages and in some fonts,
  1604. * accent marks can be positioned above the ascent or below the
  1605. * descent. To obtain a visual bounding box, which encloses all the
  1606. * text, use the {@link TextLayout#getBounds() getBounds} method of
  1607. * <code>TextLayout</code>.
  1608. * @param chars an array of characters
  1609. * @param beginIndex the initial offset in the array of
  1610. * characters
  1611. * @param limit the end offset in the array of characters
  1612. * @param frc the specified <code>FontRenderContext</code>
  1613. * @return a <code>Rectangle2D</code> that is the bounding box of the
  1614. * specified array of characters in the specified
  1615. * <code>FontRenderContext</code>.
  1616. * @throws IndexOutOfBoundsException if <code>beginIndex</code> is
  1617. * less than zero, or <code>limit</code> is greater than the
  1618. * length of <code>chars</code>, or <code>beginIndex</code>
  1619. * is greater than <code>limit</code>.
  1620. * @see FontRenderContext
  1621. * @see Font#createGlyphVector
  1622. * @since 1.2
  1623. */
  1624. public Rectangle2D getStringBounds(char [] chars,
  1625. int beginIndex, int limit,
  1626. FontRenderContext frc) {
  1627. if (beginIndex < 0) {
  1628. throw new IndexOutOfBoundsException("beginIndex: " + beginIndex);
  1629. }
  1630. if (limit > chars.length) {
  1631. throw new IndexOutOfBoundsException("limit: " + limit);
  1632. }
  1633. if (beginIndex > limit) {
  1634. throw new IndexOutOfBoundsException("range length: " + (limit - beginIndex));
  1635. }
  1636. // this code should be in textlayout
  1637. // quick check for simple text, assume GV ok to use if simple
  1638. boolean simple = true;
  1639. for (int i = beginIndex; i < limit; ++i) {
  1640. char c = chars[i];
  1641. if (c >= '\u0590' && c <= '\u206f') {
  1642. simple = false;
  1643. break;
  1644. }
  1645. }
  1646. if (simple) {
  1647. GlyphVector gv = new StandardGlyphVector(this, chars, beginIndex, limit - beginIndex, frc);
  1648. return gv.getLogicalBounds();
  1649. } else {
  1650. // need char array constructor on textlayout
  1651. String str = new String(chars, beginIndex, limit - beginIndex);
  1652. TextLayout tl = new TextLayout(str, this, frc);
  1653. return new Rectangle2D.Float(0, -tl.getAscent(), tl.getAdvance(), tl.getDescent() + tl.getLeading());
  1654. }
  1655. }
  1656. /**
  1657. * Returns the logical bounds of the characters indexed in the
  1658. * specified {@link CharacterIterator} in the
  1659. * specified <code>FontRenderContext</code>. The logical bounds
  1660. * contains the origin, ascent, advance, and height, which includes
  1661. * the leading. The logical bounds does not always enclose all the
  1662. * text. For example, in some languages and in some fonts, accent
  1663. * marks can be positioned above the ascent or below the descent.
  1664. * To obtain a visual bounding box, which encloses all the text,
  1665. * use the {@link TextLayout#getBounds() getBounds} method of
  1666. * <code>TextLayout</code>.
  1667. * @param ci the specified <code>CharacterIterator</code>
  1668. * @param beginIndex the initial offset in <code>ci</code>
  1669. * @param limit the end offset in <code>ci</code>
  1670. * @param frc the specified <code>FontRenderContext</code>
  1671. * @return a <code>Rectangle2D</code> that is the bounding box of the
  1672. * characters indexed in the specified <code>CharacterIterator</code>
  1673. * in the specified <code>FontRenderContext</code>.
  1674. * @see FontRenderContext
  1675. * @see Font#createGlyphVector
  1676. * @since 1.2
  1677. * @throws IndexOutOfBoundsException if <code>beginIndex</code> is
  1678. * less than the start index of <code>ci</code>, or
  1679. * <code>limit</code> is greater than the end index of
  1680. * <code>ci</code>, or <code>beginIndex</code> is greater
  1681. * than <code>limit</code>
  1682. */
  1683. public Rectangle2D getStringBounds(CharacterIterator ci,
  1684. int beginIndex, int limit,
  1685. FontRenderContext frc) {
  1686. int start = ci.getBeginIndex();
  1687. int end = ci.getEndIndex();
  1688. if (beginIndex < start) {
  1689. throw new IndexOutOfBoundsException("beginIndex: " + beginIndex);
  1690. }
  1691. if (limit > end) {
  1692. throw new IndexOutOfBoundsException("limit: " + limit);
  1693. }
  1694. if (beginIndex > limit) {
  1695. throw new IndexOutOfBoundsException("range length: " + (limit - beginIndex));
  1696. }
  1697. char[] arr = new char[limit - beginIndex];
  1698. ci.setIndex(beginIndex);
  1699. for(int idx = 0; idx < arr.length; idx++) {
  1700. arr[idx] = ci.current();
  1701. ci.next();
  1702. }
  1703. return getStringBounds(arr,0,arr.length,frc);
  1704. }
  1705. /**
  1706. * Returns the bounds for the character with the maximum
  1707. * bounds as defined in the specified <code>FontRenderContext</code>.
  1708. * @param frc the specified <code>FontRenderContext</code>
  1709. * @return a <code>Rectangle2D</code> that is the bounding box
  1710. * for the character with the maximum bounds.
  1711. */
  1712. public Rectangle2D getMaxCharBounds(FontRenderContext frc) {
  1713. double [] matrix = getMatrix();
  1714. float [] metrics = new float[4];
  1715. NativeFontWrapper.getFontMetrics(this, matrix,
  1716. frc.isAntiAliased(),
  1717. frc.usesFractionalMetrics(),
  1718. metrics);
  1719. return new Rectangle2D.Float(0, -metrics[0],
  1720. metrics[3],
  1721. metrics[0] + metrics[1] + metrics[2]);
  1722. }
  1723. /**
  1724. * Creates a {@link java.awt.font.GlyphVector GlyphVector} by
  1725. * mapping characters to glyphs one-to-one based on the
  1726. * Unicode cmap in this <code>Font</code>. This method does no other
  1727. * processing besides the mapping of glyphs to characters. This
  1728. * means that this method is not useful for some scripts, such
  1729. * as Arabic, Hebrew, Thai, and Indic, that require reordering,
  1730. * shaping, or ligature substitution.
  1731. * @param frc the specified <code>FontRenderContext</code>
  1732. * @param str the specified <code>String</code>
  1733. * @return a new <code>GlyphVector</code> created with the
  1734. * specified <code>String</code> and the specified
  1735. * <code>FontRenderContext</code>.
  1736. */
  1737. public GlyphVector createGlyphVector(FontRenderContext frc, String str)
  1738. {
  1739. return (GlyphVector)new StandardGlyphVector(this, str, frc);
  1740. }
  1741. /**
  1742. * Creates a {@link java.awt.font.GlyphVector GlyphVector} by
  1743. * mapping characters to glyphs one-to-one based on the
  1744. * Unicode cmap in this <code>Font</code>. This method does no other
  1745. * processing besides the mapping of glyphs to characters. This
  1746. * means that this method is not useful for some scripts, such
  1747. * as Arabic, Hebrew, Thai, and Indic, that require reordering,
  1748. * shaping, or ligature substitution.
  1749. * @param frc the specified <code>FontRenderContext</code>
  1750. * @param chars the specified array of characters
  1751. * @return a new <code>GlyphVector</code> created with the
  1752. * specified array of characters and the specified
  1753. * <code>FontRenderContext</code>.
  1754. */
  1755. public GlyphVector createGlyphVector(FontRenderContext frc, char[] chars)
  1756. {
  1757. return (GlyphVector)new StandardGlyphVector(this, chars, frc);
  1758. }
  1759. /**
  1760. * Creates a {@link java.awt.font.GlyphVector GlyphVector} by
  1761. * mapping the specified characters to glyphs one-to-one based on the
  1762. * Unicode cmap in this <code>Font</code>. This method does no other
  1763. * processing besides the mapping of glyphs to characters. This
  1764. * means that this method is not useful for some scripts, such
  1765. * as Arabic, Hebrew, Thai, and Indic, that require reordering,
  1766. * shaping, or ligature substitution.
  1767. * @param frc the specified <code>FontRenderContext</code>
  1768. * @param ci the specified <code>CharacterIterator</code>
  1769. * @return a new <code>GlyphVector</code> created with the
  1770. * specified <code>CharacterIterator</code> and the specified
  1771. * <code>FontRenderContext</code>.
  1772. */
  1773. public GlyphVector createGlyphVector( FontRenderContext frc,
  1774. CharacterIterator ci)
  1775. {
  1776. return (GlyphVector)new StandardGlyphVector(this, ci, frc);
  1777. }
  1778. /**
  1779. * Creates a {@link java.awt.font.GlyphVector GlyphVector} by
  1780. * mapping characters to glyphs one-to-one based on the
  1781. * Unicode cmap in this <code>Font</code>. This method does no other
  1782. * processing besides the mapping of glyphs to characters. This
  1783. * means that this method is not useful for some scripts, such
  1784. * as Arabic, Hebrew, Thai, and Indic, that require reordering,
  1785. * shaping, or ligature substitution.
  1786. * @param frc the specified <code>FontRenderContext</code>
  1787. * @param glyphCodes the specified integer array
  1788. * @return a new <code>GlyphVector</code> created with the
  1789. * specified integer array and the specified
  1790. * <code>FontRenderContext</code>.
  1791. */
  1792. public GlyphVector createGlyphVector( FontRenderContext frc,
  1793. int [] glyphCodes)
  1794. {
  1795. return (GlyphVector)new StandardGlyphVector(this, glyphCodes, frc);
  1796. }
  1797. /**
  1798. * Returns a new <code>GlyphVector</code> object, performing full
  1799. * layout of the text if possible. Full layout is required for
  1800. * complex text, such as Arabic or Hindi. Support for different
  1801. * scripts depends on the font and implementation.
  1802. * <p
  1803. * Layout requires bidi analysis, as performed by
  1804. * <code>Bidi</code>, and should only be performed on text that
  1805. * has a uniform direction. The direction is indicated in the
  1806. * flags parameter,by using LAYOUT_RIGHT_TO_LEFT to indicate a
  1807. * right-to-left (Arabic and Hebrew) run direction, or
  1808. * LAYOUT_LEFT_TO_RIGHT to indicate a left-to-right (English)
  1809. * run direction.
  1810. * <p>
  1811. * In addition, some operations, such as Arabic shaping, require
  1812. * context, so that the characters at the start and limit can have
  1813. * the proper shapes. Sometimes the data in the buffer outside
  1814. * the provided range does not have valid data. The values
  1815. * LAYOUT_NO_START_CONTEXT and LAYOUT_NO_LIMIT_CONTEXT can be
  1816. * added to the flags parameter to indicate that the text before
  1817. * start, or after limit, respectively, should not be examined
  1818. * for context.
  1819. * <p>
  1820. * All other values for the flags parameter are reserved.
  1821. *
  1822. * @param frc the specified <code>FontRenderContext</code>
  1823. * @param text the text to layout
  1824. * @param start the start of the text to use for the <code>GlyphVector</code>
  1825. * @param limit the limit of the text to use for the <code>GlyphVector</code>
  1826. * @param flags control flags as described above
  1827. * @return a new <code>GlyphVector</code> representing the text between
  1828. * start and limit, with glyphs chosen and positioned so as to best represent
  1829. * the text
  1830. * @throws ArrayIndexOutOfBoundsException if start or limit is
  1831. * out of bounds
  1832. * @see java.text.Bidi
  1833. * @see #LAYOUT_LEFT_TO_RIGHT
  1834. * @see #LAYOUT_RIGHT_TO_LEFT
  1835. * @see #LAYOUT_NO_START_CONTEXT
  1836. * @see #LAYOUT_NO_LIMIT_CONTEXT
  1837. */
  1838. public GlyphVector layoutGlyphVector(FontRenderContext frc,
  1839. char[] text,
  1840. int start,
  1841. int limit,
  1842. int flags) {
  1843. return new StandardGlyphVector(this, text, start, limit-start, flags, frc);
  1844. }
  1845. /**
  1846. * A flag to layoutGlyphVector indicating that text is left-to-right as
  1847. * determined by Bidi analysis.
  1848. */
  1849. public static final int LAYOUT_LEFT_TO_RIGHT = 0;
  1850. /**
  1851. * A flag to layoutGlyphVector indicating that text is right-to-left as
  1852. * determined by Bidi analysis.
  1853. */
  1854. public static final int LAYOUT_RIGHT_TO_LEFT = 1;
  1855. /**
  1856. * A flag to layoutGlyphVector indicating that text in the char array
  1857. * before the indicated start should not be examined.
  1858. */
  1859. public static final int LAYOUT_NO_START_CONTEXT = 2;
  1860. /**
  1861. * A flag to layoutGlyphVector indicating that text in the char array
  1862. * after the indicated limit should not be examined.
  1863. */
  1864. public static final int LAYOUT_NO_LIMIT_CONTEXT = 4;
  1865. private static void applyTransform(AffineTransform trans, Map attributes) {
  1866. if (trans == null) {
  1867. throw new IllegalArgumentException("transform must not be null");
  1868. }
  1869. if (trans.isIdentity()) {
  1870. attributes.remove(TextAttribute.TRANSFORM);
  1871. } else {
  1872. attributes.put(TextAttribute.TRANSFORM, new TransformAttribute(trans));
  1873. }
  1874. }
  1875. private static void applyStyle(int style, Map attributes) {
  1876. if ((style & BOLD) != 0) {
  1877. attributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
  1878. } else {
  1879. attributes.remove(TextAttribute.WEIGHT);
  1880. }
  1881. if ((style & ITALIC) != 0) {
  1882. attributes.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
  1883. } else {
  1884. attributes.remove(TextAttribute.POSTURE);
  1885. }
  1886. }
  1887. private static void applySize(float size, Map attributes) {
  1888. attributes.put(TextAttribute.SIZE, new Float(size));
  1889. }
  1890. /*
  1891. * Initialize JNI field and method IDs
  1892. */
  1893. private static native void initIDs();
  1894. private native void pDispose();
  1895. /**
  1896. * Disposes the native <code>Font</code> object.
  1897. */
  1898. protected void finalize() throws Throwable {
  1899. if (this.peer != null) {
  1900. pDispose();
  1901. }
  1902. super.finalize();
  1903. }
  1904. }