1. /*
  2. * @(#)FontMetrics.java 1.38 01/11/29
  3. *
  4. * Copyright 2002 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.Graphics2D;
  9. import java.awt.font.FontRenderContext;
  10. import java.awt.font.LineMetrics;
  11. import java.awt.geom.Rectangle2D;
  12. import java.text.CharacterIterator;
  13. /**
  14. * The <code>FontMetrics</code> class defines a font metrics object, which
  15. * encapsulates information about the rendering of a particular font on a
  16. * particular screen. Note that the implementations of these methods are
  17. * inefficient, so they are usually overridden with more efficient
  18. * toolkit-specific implementations.
  19. * <p>
  20. * <b>Note to subclassers</b>: Since many of these methods form closed,
  21. * mutually recursive loops, you must take care that you implement
  22. * at least one of the methods in each such loop to prevent
  23. * infinite recursion when your subclass is used.
  24. * In particular, the following is the minimal suggested set of methods
  25. * to override in order to ensure correctness and prevent infinite
  26. * recursion (though other subsets are equally feasible):
  27. * <ul>
  28. * <li>{@link #getAscent()}
  29. * <li>{@link #getLeading()}
  30. * <li>{@link #getMaxAdvance()}
  31. * <li>{@link #charWidth(char)}
  32. * <li>{@link #charsWidth(char[], int, int)}
  33. * </ul>
  34. * <p>
  35. * <img src="doc-files/FontMetrics-1.gif" border=15 align
  36. * ALIGN=right HSPACE=10 VSPACE=7>
  37. * When an application asks AWT to place a character at the position
  38. * (<i>x</i>, <i>y</i>), the character is placed so that its
  39. * reference point (shown as the dot in the accompanying image) is
  40. * put at that position. The reference point specifies a horizontal
  41. * line called the <i>baseline</i> of the character. In normal
  42. * printing, the baselines of characters should align.
  43. * <p>
  44. * In addition, every character in a font has an <i>ascent</i>, a
  45. * <i>descent</i>, and an <i>advance width</i>. The ascent is the
  46. * amount by which the character ascends above the baseline. The
  47. * descent is the amount by which the character descends below the
  48. * baseline. The advance width indicates the position at which AWT
  49. * should place the next character.
  50. * <p>
  51. * If the current character is placed with its reference point
  52. * at the position (<i>x</i>, <i>y</i>), and
  53. * the character's advance width is <i>w</i>, then the new
  54. * character is placed with its reference point at the position
  55. * (<i>x </i><code>+</code><i> w</i>, <i>y</i>).
  56. * The advance width is often, but not necessarily, the same as the width
  57. * of a character's bounding box. In particular, oblique and
  58. * italic fonts often have characters whose top-right corner extends
  59. * slightly beyond the advance width.
  60. * <p>
  61. * An array of characters or a string can also have an ascent, a
  62. * descent, and an advance width. The ascent of the array is the
  63. * maximum ascent of any character in the array. The descent is the
  64. * maximum descent of any character in the array. The advance width
  65. * is the sum of the advance widths of each of the characters in the
  66. * array.
  67. * @version 1.21 03/18/98
  68. * @author Jim Graham
  69. * @see java.awt.Font
  70. * @since JDK1.0
  71. */
  72. public abstract class FontMetrics implements java.io.Serializable {
  73. static {
  74. /* ensure that the necessary native libraries are loaded */
  75. Toolkit.loadLibraries();
  76. initIDs();
  77. }
  78. /**
  79. * The actual {@link Font} from which the font metrics are
  80. * created.
  81. * This cannot be null.
  82. *
  83. * @serial
  84. * @see #getFont()
  85. */
  86. protected Font font;
  87. /*
  88. * JDK 1.1 serialVersionUID
  89. */
  90. private static final long serialVersionUID = 1681126225205050147L;
  91. /**
  92. * Creates a new <code>FontMetrics</code> object for finding out
  93. * height and width information about the specified <code>Font</code>
  94. * and specific character glyphs in that <code>Font</code>.
  95. * @param font the <code>Font</code>
  96. * @see java.awt.Font
  97. */
  98. protected FontMetrics(Font font) {
  99. this.font = font;
  100. }
  101. /**
  102. * Gets the <code>Font</code> described by this
  103. * <code>FontMetrics</code> object.
  104. * @return the <code>Font</code> described by this
  105. * <code>FontMetrics</code> object.
  106. */
  107. public Font getFont() {
  108. return font;
  109. }
  110. /**
  111. * Determines the <em>standard leading</em> of the
  112. * <code>Font</code> described by this <code>FontMetrics</code>
  113. * object. The standard leading, or
  114. * interline spacing, is the logical amount of space to be reserved
  115. * between the descent of one line of text and the ascent of the next
  116. * line. The height metric is calculated to include this extra space.
  117. * @return the standard leading of the <code>Font</code>.
  118. * @see #getHeight()
  119. * @see #getAscent()
  120. * @see #getDescent()
  121. */
  122. public int getLeading() {
  123. return 0;
  124. }
  125. /**
  126. * Determines the <em>font ascent</em> of the <code>Font</code>
  127. * described by this <code>FontMetrics</code> object. The font ascent
  128. * is the distance from the font's baseline to the top of most
  129. * alphanumeric characters. Some characters in the <code>Font</code>
  130. * might extend above the font ascent line.
  131. * @return the font ascent of the <code>Font</code>.
  132. * @see #getMaxAscent()
  133. */
  134. public int getAscent() {
  135. return font.getSize();
  136. }
  137. /**
  138. * Determines the <em>font descent</em> of the <code>Font</code>
  139. * described by this
  140. * <code>FontMetrics</code> object. The font descent is the distance
  141. * from the font's baseline to the bottom of most alphanumeric
  142. * characters with descenders. Some characters in the
  143. * <code>Font</code> might extend
  144. * below the font descent line.
  145. * @return the font descent of the <code>Font</code>.
  146. * @see #getMaxDescent()
  147. */
  148. public int getDescent() {
  149. return 0;
  150. }
  151. /**
  152. * Gets the standard height of a line of text in this font. This
  153. * is the distance between the baseline of adjacent lines of text.
  154. * It is the sum of the leading + ascent + descent. There is no
  155. * guarantee that lines of text spaced at this distance are
  156. * disjoint; such lines may overlap if some characters overshoot
  157. * either the standard ascent or the standard descent metric.
  158. * @return the standard height of the font.
  159. * @see #getLeading()
  160. * @see #getAscent()
  161. * @see #getDescent()
  162. */
  163. public int getHeight() {
  164. return getLeading() + getAscent() + getDescent();
  165. }
  166. /**
  167. * Determines the maximum ascent of the <code>Font</code>
  168. * described by this <code>FontMetrics</code> object. No character
  169. * extends further above the font's baseline than this height.
  170. * @return the maximum ascent of any character in the
  171. * <code>Font</code>.
  172. * @see #getAscent()
  173. */
  174. public int getMaxAscent() {
  175. return getAscent();
  176. }
  177. /**
  178. * Determines the maximum descent of the <code>Font</code>
  179. * described by this <code>FontMetrics</code> object. No character
  180. * extends further below the font's baseline than this height.
  181. * @return the maximum descent of any character in the
  182. * <code>Font</code>.
  183. * @see #getDescent()
  184. */
  185. public int getMaxDescent() {
  186. return getDescent();
  187. }
  188. /**
  189. * For backward compatibility only.
  190. * @see #getMaxDescent()
  191. * @deprecated As of JDK version 1.1.1,
  192. * replaced by <code>getMaxDescent()</code>.
  193. */
  194. public int getMaxDecent() {
  195. return getMaxDescent();
  196. }
  197. /**
  198. * Gets the maximum advance width of any character in this
  199. * <code>Font</code>. The advance width is the amount by which the
  200. * current point is moved from one character to the next in a line of
  201. * text.
  202. * @return the maximum advance width of any character
  203. * in the <code>Font</code>, or <code>-1</code> if the
  204. * maximum advance width is not known.
  205. */
  206. public int getMaxAdvance() {
  207. return -1;
  208. }
  209. /**
  210. * Returns the advance width of the specified character in this
  211. * <code>Font</code>.
  212. * The advance width is the amount by which the current point is
  213. * moved from one character to the next in a line of text.
  214. * @param ch the character to be measured
  215. * @return the advance width of the specified <code>char</code>
  216. * in the <code>Font</code> described by this
  217. * <code>FontMetrics</code> object.
  218. * @see #charsWidth(char[], int, int)
  219. * @see #stringWidth(String)
  220. */
  221. public int charWidth(int ch) {
  222. return charWidth((char)ch);
  223. }
  224. /**
  225. * Returns the advance width of the specified character in this
  226. * <code>Font</code>.
  227. * The advance width is the amount by which the current point is
  228. * moved from one character to the next in a line of text.
  229. * @param ch the character to be measured
  230. * @return the advance width of the specified <code>char</code>
  231. * in the <code>Font</code> described by this
  232. * <code>FontMetrics</code> object.
  233. * @see #charsWidth(char[], int, int)
  234. * @see #stringWidth(String)
  235. */
  236. public int charWidth(char ch) {
  237. if (ch < 256) {
  238. return getWidths()[ch];
  239. }
  240. char data[] = {ch};
  241. return charsWidth(data, 0, 1);
  242. }
  243. /**
  244. * Returns the total advance width for showing the specified
  245. * <code>String</code> in this <code>Font</code>. The advance width is
  246. * the amount by which the current point is moved from one character
  247. * to the next in a line of text.
  248. * @param str the <code>String</code> to be measured
  249. * @return the advance width of the specified <code>String</code>
  250. * in the <code>Font</code> described by this
  251. * <code>FontMetrics</code>.
  252. * @see #bytesWidth(byte[], int, int)
  253. * @see #charsWidth(char[], int, int)
  254. */
  255. public int stringWidth(String str) {
  256. int len = str.length();
  257. char data[] = new char[len];
  258. str.getChars(0, len, data, 0);
  259. return charsWidth(data, 0, len);
  260. }
  261. /**
  262. * Returns the total advance width for showing the specified array
  263. * of characters in this <code>Font</code>. The advance width is the
  264. * amount by which the current point is moved from one character to
  265. * the next in a line of text.
  266. * @param data the array of characters to be measured
  267. * @param off the start offset of the characters in the array
  268. * @param len the number of characters to be measured from the array
  269. * @return the advance width of the subarray of the specified
  270. * <code>char</code> array in the font described by
  271. * this <code>FontMetrics</code> object.
  272. * @see #charWidth(int)
  273. * @see #charWidth(char)
  274. * @see #bytesWidth(byte[], int, int)
  275. * @see #stringWidth(String)
  276. */
  277. public int charsWidth(char data[], int off, int len) {
  278. return stringWidth(new String(data, off, len));
  279. }
  280. /**
  281. * Returns the total advance width for showing the specified array
  282. * of bytes in this <code>Font</code>.
  283. * The advance width is the amount by which the current point is
  284. * moved from one character to the next in a line of text.
  285. * @param data the array of bytes to be measured
  286. * @param off the start offset of the bytes in the array
  287. * @param len the number of bytes to be measured from the array
  288. * @return the advance width of the subarray of the specified
  289. * <code>byte</code> array in the <code>Font</code>
  290. * described by
  291. * this <code>FontMetrics</code> object.
  292. * @see #charsWidth(char[], int, int)
  293. * @see #stringWidth(String)
  294. */
  295. public int bytesWidth(byte data[], int off, int len) {
  296. return stringWidth(new String(data, 0, off, len));
  297. }
  298. /**
  299. * Gets the advance widths of the first 256 characters in the
  300. * <code>Font</code>. The advance width is the amount by which the
  301. * current point is moved from one character to the next in a line of
  302. * text.
  303. * @return an array storing the advance widths of the
  304. * characters in the <code>Font</code>
  305. * described by this <code>FontMetrics</code> object.
  306. */
  307. public int[] getWidths() {
  308. int widths[] = new int[256];
  309. for (char ch = 0 ; ch < 256 ; ch++) {
  310. widths[ch] = charWidth(ch);
  311. }
  312. return widths;
  313. }
  314. /**
  315. * Checks to see if the <code>Font</code> has uniform line metrics. A
  316. * composite font may consist of several different fonts to cover
  317. * various character sets. In such cases, the
  318. * <code>FontLineMetrics</code> objects are not uniform.
  319. * Different fonts may have a different ascent, descent, metrics and
  320. * so on. This information is sometimes necessary for line
  321. * measuring and line breaking.
  322. * @return <code>true</code> if the font has uniform line metrics;
  323. * <code>false</code> otherwise.
  324. * @see java.awt.Font#hasUniformLineMetrics()
  325. */
  326. public boolean hasUniformLineMetrics() {
  327. return font.hasUniformLineMetrics();
  328. }
  329. /**
  330. * Returns the {@link LineMetrics} object for the specified
  331. * <code>String</code> in the specified {@link Graphics} context.
  332. * @param str the specified <code>String</code>
  333. * @param context the specified <code>Graphics</code> context
  334. * @return a <code>LineMetrics</code> object created with the
  335. * specified <code>String</code> and <code>Graphics</code> context.
  336. * @see java.awt.Font#getLineMetrics(String, FontRenderContext)
  337. */
  338. public LineMetrics getLineMetrics( String str, Graphics context) {
  339. return font.getLineMetrics(str, myFRC(context));
  340. }
  341. /**
  342. * Returns the {@link LineMetrics} object for the specified
  343. * <code>String</code> in the specified {@link Graphics} context.
  344. * @param str the specified <code>String</code>
  345. * @param beginIndex the initial offset of <code>str</code>
  346. * @param limit the length of <code>str</code>
  347. * @param context the specified <code>Graphics</code> context
  348. * @return a <code>LineMetrics</code> object created with the
  349. * specified <code>String</code> and <code>Graphics</code> context.
  350. * @see java.awt.Font#getLineMetrics(String, int, int, FontRenderContext)
  351. */
  352. public LineMetrics getLineMetrics( String str,
  353. int beginIndex, int limit,
  354. Graphics context) {
  355. return font.getLineMetrics(str, beginIndex, limit, myFRC(context));
  356. }
  357. /**
  358. * Returns the {@link LineMetrics} object for the specified
  359. * character array in the specified {@link Graphics} context.
  360. * @param chars the specified character array
  361. * @param beginIndex the initial offset of <code>chars</code>
  362. * @param limit the length of <code>chars</code>
  363. * @param context the specified <code>Graphics</code> context
  364. * @return a <code>LineMetrics</code> object created with the
  365. * specified character array and <code>Graphics</code> context.
  366. * @see java.awt.Font#getLineMetrics(char[], int, int, FontRenderContext)
  367. */
  368. public LineMetrics getLineMetrics(char [] chars,
  369. int beginIndex, int limit,
  370. Graphics context) {
  371. return font.getLineMetrics(
  372. chars, beginIndex, limit, myFRC(context));
  373. }
  374. /**
  375. * Returns the {@link LineMetrics} object for the specified
  376. * {@link CharacterIterator} in the specified {@link Graphics}
  377. * context.
  378. * @param ci the specified <code>CharacterIterator</code>
  379. * @param beginIndex the initial offset in <code>ci</code>
  380. * @param limit the end index of <code>ci</code>
  381. * @param context the specified <code>Graphics</code> context
  382. * @return a <code>LineMetrics</code> object created with the
  383. * specified arguments.
  384. * @see java.awt.Font#getLineMetrics(CharacterIterator, int, int, FontRenderContext)
  385. */
  386. public LineMetrics getLineMetrics(CharacterIterator ci,
  387. int beginIndex, int limit,
  388. Graphics context) {
  389. return font.getLineMetrics(ci, beginIndex, limit, myFRC(context));
  390. }
  391. /**
  392. * Returns the bounds of the specified <code>String</code> in the
  393. * specified <code>Graphics</code> context. The bounds is used
  394. * to layout the <code>String</code>.
  395. * @param str the specified <code>String</code>
  396. * @param context the specified <code>Graphics</code> context
  397. * @return a {@link Rectangle2D} that is the bounding box of the
  398. * specified <code>String</code> in the specified
  399. * <code>Graphics</code> context.
  400. * @see java.awt.Font#getStringBounds(String, FontRenderContext)
  401. */
  402. public Rectangle2D getStringBounds( String str, Graphics context) {
  403. return font.getStringBounds(str, myFRC(context));
  404. }
  405. /**
  406. * Returns the bounds of the specified <code>String</code> in the
  407. * specified <code>Graphics</code> context. The bounds is used
  408. * to layout the <code>String</code>.
  409. * @param str the specified <code>String</code>
  410. * @param beginIndex the offset of the beginning of <code>str</code>
  411. * @param limit the length of <code>str</code>
  412. * @param context the specified <code>Graphics</code> context
  413. * @return a <code>Rectangle2D</code> that is the bounding box of the
  414. * specified <code>String</code> in the specified
  415. * <code>Graphics</code> context.
  416. * @see java.awt.Font#getStringBounds(String, int, int, FontRenderContext)
  417. */
  418. public Rectangle2D getStringBounds( String str,
  419. int beginIndex, int limit,
  420. Graphics context) {
  421. return font.getStringBounds(str, beginIndex, limit,
  422. myFRC(context));
  423. }
  424. /**
  425. * Returns the bounds of the specified array of characters
  426. * in the specified <code>Graphics</code> context.
  427. * The bounds is used to layout the <code>String</code>
  428. * created with the specified array of characters,
  429. * <code>beginIndex</code> and <code>limit</code>.
  430. * @param chars an array of characters
  431. * @param beginIndex the initial offset of the array of
  432. * characters
  433. * @param limit the length of the array of characters
  434. * @param context the specified <code>Graphics</code> context
  435. * @return a <code>Rectangle2D</code> that is the bounding box of the
  436. * specified character array in the specified
  437. * <code>Graphics</code> context.
  438. * @see java.awt.Font#getStringBounds(char[], int, int, FontRenderContext)
  439. */
  440. public Rectangle2D getStringBounds( char [] chars,
  441. int beginIndex, int limit,
  442. Graphics context) {
  443. return font.getStringBounds(chars, beginIndex, limit,
  444. myFRC(context));
  445. }
  446. /**
  447. * Returns the bounds of the characters indexed in the specified
  448. * <code>CharacterIterator</code> in the
  449. * specified <code>Graphics</code> context.
  450. * @param ci the specified <code>CharacterIterator</code>
  451. * @param beginIndex the initial offset in <code>ci</code>
  452. * @param limit the end index of <code>ci</code>
  453. * @param context the specified <code>Graphics</code> context
  454. * @return a <code>Rectangle2D</code> that is the bounding box of the
  455. * characters indexed in the specified <code>CharacterIterator</code>
  456. * in the specified <code>Graphics</code> context.
  457. * @see java.awt.Font#getStringBounds(CharacterIterator, int, int, FontRenderContext)
  458. */
  459. public Rectangle2D getStringBounds(CharacterIterator ci,
  460. int beginIndex, int limit,
  461. Graphics context) {
  462. return font.getStringBounds(ci, beginIndex, limit,
  463. myFRC(context));
  464. }
  465. /**
  466. * Returns the bounds for the character with the maximum bounds
  467. * in the specified <code>Graphics</code> context.
  468. * @param context the specified <code>Graphics</code> context
  469. * @return a <code>Rectangle2D</code> that is the
  470. * bounding box for the character with the maximum bounds.
  471. * @see java.awt.Font#getMaxCharBounds(FontRenderContext)
  472. */
  473. public Rectangle2D getMaxCharBounds(Graphics context) {
  474. return font.getMaxCharBounds(myFRC(context));
  475. }
  476. private FontRenderContext myFRC(Graphics context) {
  477. if (context instanceof Graphics2D) {
  478. return ((Graphics2D)context).getFontRenderContext();
  479. }
  480. return new FontRenderContext(null, false, false);
  481. }
  482. /**
  483. * Returns a representation of this <code>FontMetrics</code>
  484. * object's values as a <code>String</code>.
  485. * @return a <code>String</code> representation of this
  486. * <code>FontMetrics</code> object.
  487. * @since JDK1.0.
  488. */
  489. public String toString() {
  490. return getClass().getName() +
  491. "[font=" + getFont() +
  492. "ascent=" + getAscent() +
  493. ", descent=" + getDescent() +
  494. ", height=" + getHeight() + "]";
  495. }
  496. /**
  497. * Initialize JNI field and method IDs
  498. */
  499. private static native void initIDs();
  500. }