1 /*
2  * Copyright (c) 1995, 2018, 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} 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} is the
80  * distance along the baseline of the {@code String}.  This
81  * distance is the width that should be used for centering or
82  * right-aligning the {@code String}.
83  * <p>Note that the advance of a {@code String} 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 */
Toolkit.loadLibraries()103         Toolkit.loadLibraries();
104         if (!GraphicsEnvironment.isHeadless()) {
initIDs()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} object for finding out
129      * height and width information about the specified {@code Font}
130      * and specific character glyphs in that {@code Font}.
131      * @param     font the {@code Font}
132      * @see       java.awt.Font
133      */
FontMetrics(Font font)134     protected FontMetrics(Font font) {
135         this.font = font;
136     }
137 
138     /**
139      * Gets the {@code Font} described by this
140      * {@code FontMetrics} object.
141      * @return    the {@code Font} described by this
142      * {@code FontMetrics} object.
143      */
getFont()144     public Font getFont() {
145         return font;
146     }
147 
148     /**
149      * Gets the {@code FontRenderContext} used by this
150      * {@code FontMetrics} object to measure text.
151      * <p>
152      * Note that methods in this class which take a {@code Graphics}
153      * parameter measure text using the {@code FontRenderContext}
154      * of that {@code Graphics} object, and not this
155      * {@code FontRenderContext}
156      * @return    the {@code FontRenderContext} used by this
157      * {@code FontMetrics} object.
158      * @since 1.6
159      */
getFontRenderContext()160     public FontRenderContext getFontRenderContext() {
161         return DEFAULT_FRC;
162     }
163 
164     /**
165      * Determines the <em>standard leading</em> of the
166      * {@code Font} described by this {@code FontMetrics}
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}.
172      * @see   #getHeight()
173      * @see   #getAscent()
174      * @see   #getDescent()
175      */
getLeading()176     public int getLeading() {
177         return 0;
178     }
179 
180     /**
181      * Determines the <em>font ascent</em> of the {@code Font}
182      * described by this {@code FontMetrics} 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}
185      * might extend above the font ascent line.
186      * @return     the font ascent of the {@code Font}.
187      * @see        #getMaxAscent()
188      */
getAscent()189     public int getAscent() {
190         return font.getSize();
191     }
192 
193     /**
194      * Determines the <em>font descent</em> of the {@code Font}
195      * described by this
196      * {@code FontMetrics} 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} might extend
200      * below the font descent line.
201      * @return     the font descent of the {@code Font}.
202      * @see        #getMaxDescent()
203      */
getDescent()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      */
getHeight()221     public int getHeight() {
222         return getLeading() + getAscent() + getDescent();
223     }
224 
225     /**
226      * Determines the maximum ascent of the {@code Font}
227      * described by this {@code FontMetrics} 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}.
231      * @see       #getAscent()
232      */
getMaxAscent()233     public int getMaxAscent() {
234         return getAscent();
235     }
236 
237     /**
238      * Determines the maximum descent of the {@code Font}
239      * described by this {@code FontMetrics} 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}.
243      * @see       #getDescent()
244      */
getMaxDescent()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}.
253      * @see #getMaxDescent()
254      * @deprecated As of JDK version 1.1.1,
255      * replaced by {@code getMaxDescent()}.
256      */
257     @Deprecated
getMaxDecent()258     public int getMaxDecent() {
259         return getMaxDescent();
260     }
261 
262     /**
263      * Gets the maximum advance width of any character in this
264      * {@code Font}.  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} 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}, or {@code -1} if the
270      *            maximum advance width is not known.
271      */
getMaxAdvance()272     public int getMaxAdvance() {
273         return -1;
274     }
275 
276     /**
277      * Returns the advance width of the specified character in this
278      * {@code Font}.  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} 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} described by this
293      *            {@code FontMetrics} object.
294      * @see   #charsWidth(char[], int, int)
295      * @see   #stringWidth(String)
296      */
charWidth(int codePoint)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}.  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} 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="../../../java.base/java/lang/Character.html#supplementary">
321      * supplementary characters</a>.
322      * To support all Unicode characters, including
323      * supplementary characters, use the {@link #charWidth(int)} method.
324      *
325      * @param ch the character to be measured
326      * @return     the advance width of the specified character
327      *                  in the {@code Font} described by this
328      *                  {@code FontMetrics} object.
329      * @see        #charsWidth(char[], int, int)
330      * @see        #stringWidth(String)
331      */
charWidth(char ch)332     public int charWidth(char ch) {
333         if (ch < 256) {
334             return getWidths()[ch];
335         }
336         char[] data = {ch};
337         return charsWidth(data, 0, 1);
338     }
339 
340     /**
341      * Returns the total advance width for showing the specified
342      * {@code String} in this {@code Font}.  The advance
343      * is the distance from the leftmost point to the rightmost point
344      * on the string's baseline.
345      * <p>
346      * Note that the advance of a {@code String} is
347      * not necessarily the sum of the advances of its characters.
348      * @param str the {@code String} to be measured
349      * @return    the advance width of the specified {@code String}
350      *                  in the {@code Font} described by this
351      *                  {@code FontMetrics}.
352      * @throws NullPointerException if str is null.
353      * @see       #bytesWidth(byte[], int, int)
354      * @see       #charsWidth(char[], int, int)
355      * @see       #getStringBounds(String, Graphics)
356      */
stringWidth(String str)357     public int stringWidth(String str) {
358         int len = str.length();
359         char[] data = new char[len];
360         str.getChars(0, len, data, 0);
361         return charsWidth(data, 0, len);
362     }
363 
364     /**
365      * Returns the total advance width for showing the specified array
366      * of characters in this {@code Font}.  The advance is the
367      * distance from the leftmost point to the rightmost point on the
368      * string's baseline.  The advance of a {@code String}
369      * is not necessarily the sum of the advances of its characters.
370      * This is equivalent to measuring a {@code String} of the
371      * characters in the specified range.
372      * @param data the array of characters to be measured
373      * @param off the start offset of the characters in the array
374      * @param len the number of characters to be measured from the array
375      * @return    the advance width of the subarray of the specified
376      *               {@code char} array in the font described by
377      *               this {@code FontMetrics} object.
378      * @throws    NullPointerException if {@code data} is null.
379      * @throws    IndexOutOfBoundsException if the {@code off}
380      *            and {@code len} arguments index characters outside
381      *            the bounds of the {@code data} array.
382      * @see       #charWidth(int)
383      * @see       #charWidth(char)
384      * @see       #bytesWidth(byte[], int, int)
385      * @see       #stringWidth(String)
386      */
charsWidth(char[] data, int off, int len)387     public int charsWidth(char[] data, int off, int len) {
388         return stringWidth(new String(data, off, len));
389     }
390 
391     /**
392      * Returns the total advance width for showing the specified array
393      * of bytes in this {@code Font}.  The advance is the
394      * distance from the leftmost point to the rightmost point on the
395      * string's baseline.  The advance of a {@code String}
396      * is not necessarily the sum of the advances of its characters.
397      * This is equivalent to measuring a {@code String} of the
398      * characters in the specified range.
399      * @param data the array of bytes to be measured
400      * @param off the start offset of the bytes in the array
401      * @param len the number of bytes to be measured from the array
402      * @return    the advance width of the subarray of the specified
403      *               {@code byte} array in the {@code Font}
404      *                  described by
405      *               this {@code FontMetrics} object.
406      * @throws    NullPointerException if {@code data} is null.
407      * @throws    IndexOutOfBoundsException if the {@code off}
408      *            and {@code len} arguments index bytes outside
409      *            the bounds of the {@code data} array.
410      * @see       #charsWidth(char[], int, int)
411      * @see       #stringWidth(String)
412      */
413     @SuppressWarnings("deprecation")
bytesWidth(byte[] data, int off, int len)414     public int bytesWidth(byte[] data, int off, int len) {
415         return stringWidth(new String(data, 0, off, len));
416     }
417 
418     /**
419      * Gets the advance widths of the first 256 characters in the
420      * {@code Font}.  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} 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}
427      *                 described by this {@code FontMetrics} object.
428      */
getWidths()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} 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} 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} if the font has uniform line metrics;
446      * {@code false} otherwise.
447      * @see java.awt.Font#hasUniformLineMetrics()
448      */
hasUniformLineMetrics()449     public boolean hasUniformLineMetrics() {
450         return font.hasUniformLineMetrics();
451     }
452 
453     /**
454      * Returns the {@link LineMetrics} object for the specified
455      * {@code String} in the specified {@link Graphics} context.
456      * @param str the specified {@code String}
457      * @param context the specified {@code Graphics} context
458      * @return a {@code LineMetrics} object created with the
459      * specified {@code String} and {@code Graphics} context.
460      * @see java.awt.Font#getLineMetrics(String, FontRenderContext)
461      */
getLineMetrics( String str, Graphics context)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} in the specified {@link Graphics} context.
469      * @param str the specified {@code String}
470      * @param beginIndex the initial offset of {@code str}
471      * @param limit the end offset of {@code str}
472      * @param context the specified {@code Graphics} context
473      * @return a {@code LineMetrics} object created with the
474      * specified {@code String} and {@code Graphics} context.
475      * @see java.awt.Font#getLineMetrics(String, int, int, FontRenderContext)
476      */
getLineMetrics( String str, int beginIndex, int limit, Graphics context)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}
488      * @param limit the end offset of {@code chars}
489      * @param context the specified {@code Graphics} context
490      * @return a {@code LineMetrics} object created with the
491      * specified character array and {@code Graphics} context.
492      * @see java.awt.Font#getLineMetrics(char[], int, int, FontRenderContext)
493      */
getLineMetrics(char [] chars, int beginIndex, int limit, Graphics context)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}
506      * @param beginIndex the initial offset in {@code ci}
507      * @param limit the end index of {@code ci}
508      * @param context the specified {@code Graphics} context
509      * @return a {@code LineMetrics} object created with the
510      * specified arguments.
511      * @see java.awt.Font#getLineMetrics(CharacterIterator, int, int, FontRenderContext)
512      */
getLineMetrics(CharacterIterator ci, int beginIndex, int limit, Graphics context)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} in the
521      * specified {@code Graphics} context.  The bounds is used
522      * to layout the {@code String}.
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}
526      * @param context the specified {@code Graphics} context
527      * @return a {@link Rectangle2D} that is the bounding box of the
528      * specified {@code String} in the specified
529      * {@code Graphics} context.
530      * @see java.awt.Font#getStringBounds(String, FontRenderContext)
531      */
getStringBounds( String str, Graphics context)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} in the
538      * specified {@code Graphics} context.  The bounds is used
539      * to layout the {@code String}.
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}
543      * @param beginIndex the offset of the beginning of {@code str}
544      * @param limit the end offset of {@code str}
545      * @param context the specified {@code Graphics} context
546      * @return a {@code Rectangle2D} that is the bounding box of the
547      * specified {@code String} in the specified
548      * {@code Graphics} context.
549      * @see java.awt.Font#getStringBounds(String, int, int, FontRenderContext)
550      */
getStringBounds( String str, int beginIndex, int limit, Graphics context)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} context.
561      * The bounds is used to layout the {@code String}
562      * created with the specified array of characters,
563      * {@code beginIndex} and {@code limit}.
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} context
571      * @return a {@code Rectangle2D} that is the bounding box of the
572      * specified character array in the specified
573      * {@code Graphics} context.
574      * @see java.awt.Font#getStringBounds(char[], int, int, FontRenderContext)
575      */
getStringBounds( char [] chars, int beginIndex, int limit, Graphics context)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} in the
586      * specified {@code Graphics} 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}
590      * @param beginIndex the initial offset in {@code ci}
591      * @param limit the end index of {@code ci}
592      * @param context the specified {@code Graphics} context
593      * @return a {@code Rectangle2D} that is the bounding box of the
594      * characters indexed in the specified {@code CharacterIterator}
595      * in the specified {@code Graphics} context.
596      * @see java.awt.Font#getStringBounds(CharacterIterator, int, int, FontRenderContext)
597      */
getStringBounds(CharacterIterator ci, int beginIndex, int limit, Graphics context)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} context.
608      * @param context the specified {@code Graphics} context
609      * @return a {@code Rectangle2D} that is the
610      * bounding box for the character with the maximum bounds.
611      * @see java.awt.Font#getMaxCharBounds(FontRenderContext)
612      */
getMaxCharBounds(Graphics context)613     public Rectangle2D getMaxCharBounds(Graphics context) {
614         return font.getMaxCharBounds(myFRC(context));
615     }
616 
myFRC(Graphics context)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}
627      * object's values as a {@code String}.
628      * @return    a {@code String} representation of this
629      * {@code FontMetrics} object.
630      */
toString()631     public String toString() {
632         return getClass().getName() +
633             "[font=" + getFont() +
634             "ascent=" + getAscent() +
635             ", descent=" + getDescent() +
636             ", height=" + getHeight() + "]";
637     }
638 
639     /**
640      * Initialize JNI field and method IDs
641      */
initIDs()642     private static native void initIDs();
643 }
644