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