View Javadoc
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       JDK1.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      * @since     JDK1.0.
629      */
630     public String toString() {
631         return getClass().getName() +
632             "[font=" + getFont() +
633             "ascent=" + getAscent() +
634             ", descent=" + getDescent() +
635             ", height=" + getHeight() + "]";
636     }
637 
638     /**
639      * Initialize JNI field and method IDs
640      */
641     private static native void initIDs();
642 }