1 /* 2 * Copyright (c) 1995, 2005, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.awt; 27 28 import java.awt.Graphics2D; 29 import java.awt.font.FontRenderContext; 30 import java.awt.font.LineMetrics; 31 import java.awt.geom.Rectangle2D; 32 import java.nio.charset.Charset; 33 import java.nio.charset.StandardCharsets; 34 import java.text.CharacterIterator; 35 36 /** 37 * The <code>FontMetrics</code> class defines a font metrics object, which 38 * encapsulates information about the rendering of a particular font on a 39 * particular screen. 40 * <p> 41 * <b>Note to subclassers</b>: Since many of these methods form closed, 42 * mutually recursive loops, you must take care that you implement 43 * at least one of the methods in each such loop to prevent 44 * infinite recursion when your subclass is used. 45 * In particular, the following is the minimal suggested set of methods 46 * to override in order to ensure correctness and prevent infinite 47 * recursion (though other subsets are equally feasible): 48 * <ul> 49 * <li>{@link #getAscent()} 50 * <li>{@link #getLeading()} 51 * <li>{@link #getMaxAdvance()} 52 * <li>{@link #charWidth(char)} 53 * <li>{@link #charsWidth(char[], int, int)} 54 * </ul> 55 * <p> 56 * <img src="doc-files/FontMetrics-1.gif" alt="The letter 'p' showing its 'reference point'" border=15 align 57 * ALIGN=right HSPACE=10 VSPACE=7> 58 * Note that the implementations of these methods are 59 * inefficient, so they are usually overridden with more efficient 60 * toolkit-specific implementations. 61 * <p> 62 * When an application asks to place a character at the position 63 * (<i>x</i>, <i>y</i>), the character is placed so that its 64 * reference point (shown as the dot in the accompanying image) is 65 * put at that position. The reference point specifies a horizontal 66 * line called the <i>baseline</i> of the character. In normal 67 * printing, the baselines of characters should align. 68 * <p> 69 * In addition, every character in a font has an <i>ascent</i>, a 70 * <i>descent</i>, and an <i>advance width</i>. The ascent is the 71 * amount by which the character ascends above the baseline. The 72 * descent is the amount by which the character descends below the 73 * baseline. The advance width indicates the position at which AWT 74 * should place the next character. 75 * <p> 76 * An array of characters or a string can also have an ascent, a 77 * descent, and an advance width. The ascent of the array is the 78 * maximum ascent of any character in the array. The descent is the 79 * maximum descent of any character in the array. The advance width 80 * is the sum of the advance widths of each of the characters in the 81 * character array. The advance of a <code>String</code> is the 82 * distance along the baseline of the <code>String</code>. This 83 * distance is the width that should be used for centering or 84 * right-aligning the <code>String</code>. 85 * <p>Note that the advance of a <code>String</code> is not necessarily 86 * the sum of the advances of its characters measured in isolation 87 * because the width of a character can vary depending on its context. 88 * For example, in Arabic text, the shape of a character can change 89 * in order to connect to other characters. Also, in some scripts, 90 * certain character sequences can be represented by a single shape, 91 * called a <em>ligature</em>. Measuring characters individually does 92 * not account for these transformations. 93 * <p>Font metrics are baseline-relative, meaning that they are 94 * generally independent of the rotation applied to the font (modulo 95 * possible grid hinting effects). See {@link java.awt.Font Font}. 96 * 97 * @author Jim Graham 98 * @see java.awt.Font 99 * @since JDK1.0 100 */ 101 public abstract class FontMetrics implements java.io.Serializable { 102 103 static { 104 /* ensure that the necessary native libraries are loaded */ 105 Toolkit.loadLibraries(); 106 if (!GraphicsEnvironment.isHeadless()) { 107 initIDs(); 108 } 109 } 110 111 private static final FontRenderContext 112 DEFAULT_FRC = new FontRenderContext(null, false, false); 113 114 /** 115 * The actual {@link Font} from which the font metrics are 116 * created. 117 * This cannot be null. 118 * 119 * @serial 120 * @see #getFont() 121 */ 122 protected Font font; 123 124 /* 125 * JDK 1.1 serialVersionUID 126 */ 127 private static final long serialVersionUID = 1681126225205050147L; 128 129 /** 130 * Creates a new <code>FontMetrics</code> object for finding out 131 * height and width information about the specified <code>Font</code> 132 * and specific character glyphs in that <code>Font</code>. 133 * @param font the <code>Font</code> 134 * @see java.awt.Font 135 */ 136 protected FontMetrics(Font font) { 137 this.font = font; 138 } 139 140 /** 141 * Gets the <code>Font</code> described by this 142 * <code>FontMetrics</code> object. 143 * @return the <code>Font</code> described by this 144 * <code>FontMetrics</code> object. 145 */ 146 public Font getFont() { 147 return font; 148 } 149 150 /** 151 * Gets the <code>FontRenderContext</code> used by this 152 * <code>FontMetrics</code> object to measure text. 153 * <p> 154 * Note that methods in this class which take a <code>Graphics</code> 155 * parameter measure text using the <code>FontRenderContext</code> 156 * of that <code>Graphics</code> object, and not this 157 * <code>FontRenderContext</code> 158 * @return the <code>FontRenderContext</code> used by this 159 * <code>FontMetrics</code> object. 160 * @since 1.6 161 */ 162 public FontRenderContext getFontRenderContext() { 163 return DEFAULT_FRC; 164 } 165 166 /** 167 * Determines the <em>standard leading</em> of the 168 * <code>Font</code> described by this <code>FontMetrics</code> 169 * object. The standard leading, or 170 * interline spacing, is the logical amount of space to be reserved 171 * between the descent of one line of text and the ascent of the next 172 * line. The height metric is calculated to include this extra space. 173 * @return the standard leading of the <code>Font</code>. 174 * @see #getHeight() 175 * @see #getAscent() 176 * @see #getDescent() 177 */ 178 public int getLeading() { 179 return 0; 180 } 181 182 /** 183 * Determines the <em>font ascent</em> of the <code>Font</code> 184 * described by this <code>FontMetrics</code> object. The font ascent 185 * is the distance from the font's baseline to the top of most 186 * alphanumeric characters. Some characters in the <code>Font</code> 187 * might extend above the font ascent line. 188 * @return the font ascent of the <code>Font</code>. 189 * @see #getMaxAscent() 190 */ 191 public int getAscent() { 192 return font.getSize(); 193 } 194 195 /** 196 * Determines the <em>font descent</em> of the <code>Font</code> 197 * described by this 198 * <code>FontMetrics</code> object. The font descent is the distance 199 * from the font's baseline to the bottom of most alphanumeric 200 * characters with descenders. Some characters in the 201 * <code>Font</code> might extend 202 * below the font descent line. 203 * @return the font descent of the <code>Font</code>. 204 * @see #getMaxDescent() 205 */ 206 public int getDescent() { 207 return 0; 208 } 209 210 /** 211 * Gets the standard height of a line of text in this font. This 212 * is the distance between the baseline of adjacent lines of text. 213 * It is the sum of the leading + ascent + descent. Due to rounding 214 * this may not be the same as getAscent() + getDescent() + getLeading(). 215 * There is no guarantee that lines of text spaced at this distance are 216 * disjoint; such lines may overlap if some characters overshoot 217 * either the standard ascent or the standard descent metric. 218 * @return the standard height of the font. 219 * @see #getLeading() 220 * @see #getAscent() 221 * @see #getDescent() 222 */ 223 public int getHeight() { 224 return getLeading() + getAscent() + getDescent(); 225 } 226 227 /** 228 * Determines the maximum ascent of the <code>Font</code> 229 * described by this <code>FontMetrics</code> object. No character 230 * extends further above the font's baseline than this height. 231 * @return the maximum ascent of any character in the 232 * <code>Font</code>. 233 * @see #getAscent() 234 */ 235 public int getMaxAscent() { 236 return getAscent(); 237 } 238 239 /** 240 * Determines the maximum descent of the <code>Font</code> 241 * described by this <code>FontMetrics</code> object. No character 242 * extends further below the font's baseline than this height. 243 * @return the maximum descent of any character in the 244 * <code>Font</code>. 245 * @see #getDescent() 246 */ 247 public int getMaxDescent() { 248 return getDescent(); 249 } 250 251 /** 252 * For backward compatibility only. 253 * @return the maximum descent of any character in the 254 * <code>Font</code>. 255 * @see #getMaxDescent() 256 * @deprecated As of JDK version 1.1.1, 257 * replaced by <code>getMaxDescent()</code>. 258 */ 259 @Deprecated 260 public int getMaxDecent() { 261 return getMaxDescent(); 262 } 263 264 /** 265 * Gets the maximum advance width of any character in this 266 * <code>Font</code>. The advance is the 267 * distance from the leftmost point to the rightmost point on the 268 * string's baseline. The advance of a <code>String</code> is 269 * not necessarily the sum of the advances of its characters. 270 * @return the maximum advance width of any character 271 * in the <code>Font</code>, or <code>-1</code> if the 272 * maximum advance width is not known. 273 */ 274 public int getMaxAdvance() { 275 return -1; 276 } 277 278 /** 279 * Returns the advance width of the specified character in this 280 * <code>Font</code>. The advance is the 281 * distance from the leftmost point to the rightmost point on the 282 * character's baseline. Note that the advance of a 283 * <code>String</code> is not necessarily the sum of the advances 284 * of its characters. 285 * 286 * <p>This method doesn't validate the specified character to be a 287 * valid Unicode code point. The caller must validate the 288 * character value using {@link 289 * java.lang.Character#isValidCodePoint(int) 290 * Character.isValidCodePoint} if necessary. 291 * 292 * @param codePoint the character (Unicode code point) to be measured 293 * @return the advance width of the specified character 294 * in the <code>Font</code> described by this 295 * <code>FontMetrics</code> object. 296 * @see #charsWidth(char[], int, int) 297 * @see #stringWidth(String) 298 */ 299 public int charWidth(int codePoint) { 300 if (!Character.isValidCodePoint(codePoint)) { 301 codePoint = 0xffff; // substitute missing glyph width 302 } 303 304 if (codePoint < 256) { 305 return getWidths()[codePoint]; 306 } else { 307 char[] buffer = new char[2]; 308 int len = Character.toChars(codePoint, buffer, 0); 309 return charsWidth(buffer, 0, len); 310 } 311 } 312 313 /** 314 * Returns the advance width of the specified character in this 315 * <code>Font</code>. The advance is the 316 * distance from the leftmost point to the rightmost point on the 317 * character's baseline. Note that the advance of a 318 * <code>String</code> is not necessarily the sum of the advances 319 * of its characters. 320 * 321 * <p><b>Note:</b> This method cannot handle <a 322 * href="../lang/Character.html#supplementary"> supplementary 323 * characters</a>. To support all Unicode characters, including 324 * supplementary characters, use the {@link #charWidth(int)} method. 325 * 326 * @param ch the character to be measured 327 * @return the advance width of the specified character 328 * in the <code>Font</code> described by this 329 * <code>FontMetrics</code> object. 330 * @see #charsWidth(char[], int, int) 331 * @see #stringWidth(String) 332 */ 333 public int charWidth(char ch) { 334 if (ch < 256) { 335 return getWidths()[ch]; 336 } 337 char data[] = {ch}; 338 return charsWidth(data, 0, 1); 339 } 340 341 /** 342 * Returns the total advance width for showing the specified 343 * <code>String</code> in this <code>Font</code>. The advance 344 * is the distance from the leftmost point to the rightmost point 345 * on the string's baseline. 346 * <p> 347 * Note that the advance of a <code>String</code> is 348 * not necessarily the sum of the advances of its characters. 349 * @param str the <code>String</code> to be measured 350 * @return the advance width of the specified <code>String</code> 351 * in the <code>Font</code> described by this 352 * <code>FontMetrics</code>. 353 * @throws NullPointerException if str is null. 354 * @see #bytesWidth(byte[], int, int) 355 * @see #charsWidth(char[], int, int) 356 * @see #getStringBounds(String, Graphics) 357 */ 358 public int stringWidth(String str) { 359 int len = str.length(); 360 char data[] = new char[len]; 361 str.getChars(0, len, data, 0); 362 return charsWidth(data, 0, len); 363 } 364 365 /** 366 * Returns the total advance width for showing the specified array 367 * of characters in this <code>Font</code>. The advance is the 368 * distance from the leftmost point to the rightmost point on the 369 * string's baseline. The advance of a <code>String</code> 370 * is not necessarily the sum of the advances of its characters. 371 * This is equivalent to measuring a <code>String</code> of the 372 * characters in the specified range. 373 * @param data the array of characters to be measured 374 * @param off the start offset of the characters in the array 375 * @param len the number of characters to be measured from the array 376 * @return the advance width of the subarray of the specified 377 * <code>char</code> array in the font described by 378 * this <code>FontMetrics</code> object. 379 * @throws NullPointerException if <code>data</code> is null. 380 * @throws IndexOutOfBoundsException if the <code>off</code> 381 * and <code>len</code> arguments index characters outside 382 * the bounds of the <code>data</code> array. 383 * @see #charWidth(int) 384 * @see #charWidth(char) 385 * @see #bytesWidth(byte[], int, int) 386 * @see #stringWidth(String) 387 */ 388 public int charsWidth(char data[], int off, int len) { 389 return stringWidth(new String(data, off, len)); 390 } 391 392 /** 393 * Returns the total advance width for showing the specified array 394 * of bytes in this <code>Font</code>. The advance is the 395 * distance from the leftmost point to the rightmost point on the 396 * string's baseline. The advance of a <code>String</code> 397 * is not necessarily the sum of the advances of its characters. 398 * This is equivalent to measuring a <code>String</code> of the 399 * characters in the specified range. 400 * @param data the array of bytes to be measured 401 * @param off the start offset of the bytes in the array 402 * @param len the number of bytes to be measured from the array 403 * @return the advance width of the subarray of the specified 404 * <code>byte</code> array in the <code>Font</code> 405 * described by 406 * this <code>FontMetrics</code> object. 407 * @throws NullPointerException if <code>data</code> is null. 408 * @throws IndexOutOfBoundsException if the <code>off</code> 409 * and <code>len</code> arguments index bytes outside 410 * the bounds of the <code>data</code> array. 411 * @see #charsWidth(char[], int, int) 412 * @see #stringWidth(String) 413 */ 414 public int bytesWidth(byte data[], int off, int len) { 415 return stringWidth(new String(data, off, len, StandardCharsets.ISO_8859_1)); 416 } 417 418 /** 419 * Gets the advance widths of the first 256 characters in the 420 * <code>Font</code>. The advance is the 421 * distance from the leftmost point to the rightmost point on the 422 * character's baseline. Note that the advance of a 423 * <code>String</code> is not necessarily the sum of the advances 424 * of its characters. 425 * @return an array storing the advance widths of the 426 * characters in the <code>Font</code> 427 * described by this <code>FontMetrics</code> object. 428 */ 429 public int[] getWidths() { 430 int widths[] = new int[256]; 431 for (char ch = 0 ; ch < 256 ; ch++) { 432 widths[ch] = charWidth(ch); 433 } 434 return widths; 435 } 436 437 /** 438 * Checks to see if the <code>Font</code> has uniform line metrics. A 439 * composite font may consist of several different fonts to cover 440 * various character sets. In such cases, the 441 * <code>FontLineMetrics</code> objects are not uniform. 442 * Different fonts may have a different ascent, descent, metrics and 443 * so on. This information is sometimes necessary for line 444 * measuring and line breaking. 445 * @return <code>true</code> if the font has uniform line metrics; 446 * <code>false</code> otherwise. 447 * @see java.awt.Font#hasUniformLineMetrics() 448 */ 449 public boolean hasUniformLineMetrics() { 450 return font.hasUniformLineMetrics(); 451 } 452 453 /** 454 * Returns the {@link LineMetrics} object for the specified 455 * <code>String</code> in the specified {@link Graphics} context. 456 * @param str the specified <code>String</code> 457 * @param context the specified <code>Graphics</code> context 458 * @return a <code>LineMetrics</code> object created with the 459 * specified <code>String</code> and <code>Graphics</code> context. 460 * @see java.awt.Font#getLineMetrics(String, FontRenderContext) 461 */ 462 public LineMetrics getLineMetrics( String str, Graphics context) { 463 return font.getLineMetrics(str, myFRC(context)); 464 } 465 466 /** 467 * Returns the {@link LineMetrics} object for the specified 468 * <code>String</code> in the specified {@link Graphics} context. 469 * @param str the specified <code>String</code> 470 * @param beginIndex the initial offset of <code>str</code> 471 * @param limit the end offset of <code>str</code> 472 * @param context the specified <code>Graphics</code> context 473 * @return a <code>LineMetrics</code> object created with the 474 * specified <code>String</code> and <code>Graphics</code> context. 475 * @see java.awt.Font#getLineMetrics(String, int, int, FontRenderContext) 476 */ 477 public LineMetrics getLineMetrics( String str, 478 int beginIndex, int limit, 479 Graphics context) { 480 return font.getLineMetrics(str, beginIndex, limit, myFRC(context)); 481 } 482 483 /** 484 * Returns the {@link LineMetrics} object for the specified 485 * character array in the specified {@link Graphics} context. 486 * @param chars the specified character array 487 * @param beginIndex the initial offset of <code>chars</code> 488 * @param limit the end offset of <code>chars</code> 489 * @param context the specified <code>Graphics</code> context 490 * @return a <code>LineMetrics</code> object created with the 491 * specified character array and <code>Graphics</code> context. 492 * @see java.awt.Font#getLineMetrics(char[], int, int, FontRenderContext) 493 */ 494 public LineMetrics getLineMetrics(char [] chars, 495 int beginIndex, int limit, 496 Graphics context) { 497 return font.getLineMetrics( 498 chars, beginIndex, limit, myFRC(context)); 499 } 500 501 /** 502 * Returns the {@link LineMetrics} object for the specified 503 * {@link CharacterIterator} in the specified {@link Graphics} 504 * context. 505 * @param ci the specified <code>CharacterIterator</code> 506 * @param beginIndex the initial offset in <code>ci</code> 507 * @param limit the end index of <code>ci</code> 508 * @param context the specified <code>Graphics</code> context 509 * @return a <code>LineMetrics</code> object created with the 510 * specified arguments. 511 * @see java.awt.Font#getLineMetrics(CharacterIterator, int, int, FontRenderContext) 512 */ 513 public LineMetrics getLineMetrics(CharacterIterator ci, 514 int beginIndex, int limit, 515 Graphics context) { 516 return font.getLineMetrics(ci, beginIndex, limit, myFRC(context)); 517 } 518 519 /** 520 * Returns the bounds of the specified <code>String</code> in the 521 * specified <code>Graphics</code> context. The bounds is used 522 * to layout the <code>String</code>. 523 * <p>Note: The returned bounds is in baseline-relative coordinates 524 * (see {@link java.awt.FontMetrics class notes}). 525 * @param str the specified <code>String</code> 526 * @param context the specified <code>Graphics</code> context 527 * @return a {@link Rectangle2D} that is the bounding box of the 528 * specified <code>String</code> in the specified 529 * <code>Graphics</code> context. 530 * @see java.awt.Font#getStringBounds(String, FontRenderContext) 531 */ 532 public Rectangle2D getStringBounds( String str, Graphics context) { 533 return font.getStringBounds(str, myFRC(context)); 534 } 535 536 /** 537 * Returns the bounds of the specified <code>String</code> in the 538 * specified <code>Graphics</code> context. The bounds is used 539 * to layout the <code>String</code>. 540 * <p>Note: The returned bounds is in baseline-relative coordinates 541 * (see {@link java.awt.FontMetrics class notes}). 542 * @param str the specified <code>String</code> 543 * @param beginIndex the offset of the beginning of <code>str</code> 544 * @param limit the end offset of <code>str</code> 545 * @param context the specified <code>Graphics</code> context 546 * @return a <code>Rectangle2D</code> that is the bounding box of the 547 * specified <code>String</code> in the specified 548 * <code>Graphics</code> context. 549 * @see java.awt.Font#getStringBounds(String, int, int, FontRenderContext) 550 */ 551 public Rectangle2D getStringBounds( String str, 552 int beginIndex, int limit, 553 Graphics context) { 554 return font.getStringBounds(str, beginIndex, limit, 555 myFRC(context)); 556 } 557 558 /** 559 * Returns the bounds of the specified array of characters 560 * in the specified <code>Graphics</code> context. 561 * The bounds is used to layout the <code>String</code> 562 * created with the specified array of characters, 563 * <code>beginIndex</code> and <code>limit</code>. 564 * <p>Note: The returned bounds is in baseline-relative coordinates 565 * (see {@link java.awt.FontMetrics class notes}). 566 * @param chars an array of characters 567 * @param beginIndex the initial offset of the array of 568 * characters 569 * @param limit the end offset of the array of characters 570 * @param context the specified <code>Graphics</code> context 571 * @return a <code>Rectangle2D</code> that is the bounding box of the 572 * specified character array in the specified 573 * <code>Graphics</code> context. 574 * @see java.awt.Font#getStringBounds(char[], int, int, FontRenderContext) 575 */ 576 public Rectangle2D getStringBounds( char [] chars, 577 int beginIndex, int limit, 578 Graphics context) { 579 return font.getStringBounds(chars, beginIndex, limit, 580 myFRC(context)); 581 } 582 583 /** 584 * Returns the bounds of the characters indexed in the specified 585 * <code>CharacterIterator</code> in the 586 * specified <code>Graphics</code> context. 587 * <p>Note: The returned bounds is in baseline-relative coordinates 588 * (see {@link java.awt.FontMetrics class notes}). 589 * @param ci the specified <code>CharacterIterator</code> 590 * @param beginIndex the initial offset in <code>ci</code> 591 * @param limit the end index of <code>ci</code> 592 * @param context the specified <code>Graphics</code> context 593 * @return a <code>Rectangle2D</code> that is the bounding box of the 594 * characters indexed in the specified <code>CharacterIterator</code> 595 * in the specified <code>Graphics</code> context. 596 * @see java.awt.Font#getStringBounds(CharacterIterator, int, int, FontRenderContext) 597 */ 598 public Rectangle2D getStringBounds(CharacterIterator ci, 599 int beginIndex, int limit, 600 Graphics context) { 601 return font.getStringBounds(ci, beginIndex, limit, 602 myFRC(context)); 603 } 604 605 /** 606 * Returns the bounds for the character with the maximum bounds 607 * in the specified <code>Graphics</code> context. 608 * @param context the specified <code>Graphics</code> context 609 * @return a <code>Rectangle2D</code> that is the 610 * bounding box for the character with the maximum bounds. 611 * @see java.awt.Font#getMaxCharBounds(FontRenderContext) 612 */ 613 public Rectangle2D getMaxCharBounds(Graphics context) { 614 return font.getMaxCharBounds(myFRC(context)); 615 } 616 617 private FontRenderContext myFRC(Graphics context) { 618 if (context instanceof Graphics2D) { 619 return ((Graphics2D)context).getFontRenderContext(); 620 } 621 return DEFAULT_FRC; 622 } 623 624 625 /** 626 * Returns a representation of this <code>FontMetrics</code> 627 * object's values as a <code>String</code>. 628 * @return a <code>String</code> representation of this 629 * <code>FontMetrics</code> object. 630 * @since JDK1.0. 631 */ 632 public String toString() { 633 return getClass().getName() + 634 "[font=" + getFont() + 635 "ascent=" + getAscent() + 636 ", descent=" + getDescent() + 637 ", height=" + getHeight() + "]"; 638 } 639 640 /** 641 * Initialize JNI field and method IDs 642 */ 643 private static native void initIDs(); 644 }