Source for java.awt.Font

   1: /* Font.java -- Font object
   2:    Copyright (C) 1999, 2002, 2004, 2005  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package java.awt;
  40: 
  41: import gnu.java.awt.ClasspathToolkit;
  42: import gnu.java.awt.peer.ClasspathFontPeer;
  43: 
  44: import java.awt.font.FontRenderContext;
  45: import java.awt.font.GlyphVector;
  46: import java.awt.font.LineMetrics;
  47: import java.awt.font.TextAttribute;
  48: import java.awt.font.TextLayout;
  49: import java.awt.geom.AffineTransform;
  50: import java.awt.geom.Rectangle2D;
  51: import java.awt.peer.FontPeer;
  52: import java.io.File;
  53: import java.io.FileInputStream;
  54: import java.io.IOException;
  55: import java.io.InputStream;
  56: import java.io.ObjectInputStream;
  57: import java.io.Serializable;
  58: import java.text.AttributedCharacterIterator;
  59: import java.text.CharacterIterator;
  60: import java.text.StringCharacterIterator;
  61: import java.util.HashMap;
  62: import java.util.Locale;
  63: import java.util.Map;
  64: import java.util.StringTokenizer;
  65: 
  66: /**
  67:  * This class represents a windowing system font.
  68:  *
  69:  * @author Aaron M. Renn (arenn@urbanophile.com)
  70:  * @author Warren Levy (warrenl@cygnus.com)
  71:  * @author Graydon Hoare (graydon@redhat.com)
  72:  */
  73: public class Font implements Serializable
  74: {
  75: 
  76:   /**
  77:    * Constant indicating a "plain" font.
  78:    */
  79:   public static final int PLAIN = 0;
  80: 
  81:   /**
  82:    * Constant indicating a "bold" font.
  83:    */
  84:   public static final int BOLD = 1;
  85: 
  86:   /**
  87:    * Constant indicating an "italic" font.
  88:    */
  89:   public static final int ITALIC = 2;
  90: 
  91:   /**
  92:    * Constant indicating the baseline mode characteristic of Roman.
  93:    */
  94:   public static final int ROMAN_BASELINE = 0;
  95: 
  96:   /**
  97:    * Constant indicating the baseline mode characteristic of Chinese.
  98:    */
  99:   public static final int CENTER_BASELINE = 1;
 100: 
 101:   /**
 102:    * Constant indicating the baseline mode characteristic of Devanigri.
 103:    */
 104:   public static final int HANGING_BASELINE = 2;  
 105: 
 106: 
 107:   /**
 108:    * Indicates to <code>createFont</code> that the supplied font data
 109:    * is in TrueType format.
 110:    *
 111:    * <p><em>Specification Note:</em> The Sun JavaDoc for J2SE 1.4 does
 112:    * not indicate whether this value also subsumes OpenType. OpenType
 113:    * is essentially the same format as TrueType, but allows to define
 114:    * glyph shapes in the same way as PostScript, using cubic bezier
 115:    * curves.
 116:    *
 117:    * @since 1.3
 118:    */
 119:   public static final int TRUETYPE_FONT = 0;
 120:   
 121:   /**
 122:    * Indicates to <code>createFont</code> that the supplied font data
 123:    * is in Type1 format.
 124:    * 
 125:    * @since 1.5
 126:    */
 127:   public static final int TYPE1_FONT = 1;
 128: 
 129:   /**
 130:    * A flag for <code>layoutGlyphVector</code>, indicating that the
 131:    * orientation of a text run is from left to right.
 132:    *
 133:    * @since 1.4
 134:    */
 135:   public static final int LAYOUT_LEFT_TO_RIGHT = 0;
 136: 
 137: 
 138:   /**
 139:    * A flag for <code>layoutGlyphVector</code>, indicating that the
 140:    * orientation of a text run is from right to left.
 141:    *
 142:    * @since 1.4
 143:    */
 144:   public static final int LAYOUT_RIGHT_TO_LEFT = 1;
 145: 
 146: 
 147:   /**
 148:    * A flag for <code>layoutGlyphVector</code>, indicating that the
 149:    * text does not contain valid characters before the
 150:    * <code>start</code> position.  If this flag is set,
 151:    * <code>layoutGlyphVector</code> does not examine the text before
 152:    * <code>start</code>, even if this would be necessary to select the
 153:    * correct glyphs (e.g., for Arabic text).
 154:    *
 155:    * @since 1.4
 156:    */
 157:   public static final int LAYOUT_NO_START_CONTEXT = 2;
 158: 
 159: 
 160:   /**
 161:    * A flag for <code>layoutGlyphVector</code>, indicating that the
 162:    * text does not contain valid characters after the
 163:    * <code>limit</code> position.  If this flag is set,
 164:    * <code>layoutGlyphVector</code> does not examine the text after
 165:    * <code>limit</code>, even if this would be necessary to select the
 166:    * correct glyphs (e.g., for Arabic text).
 167:    *
 168:    * @since 1.4
 169:    */
 170:   public static final int LAYOUT_NO_LIMIT_CONTEXT = 4;
 171: 
 172:   /**
 173:    * The logical name of this font.
 174:    *
 175:    * @since 1.0
 176:    */
 177:   protected String name;
 178: 
 179:   /**
 180:    * The size of this font in points, rounded.
 181:    *
 182:    * @since 1.0
 183:    */
 184:   protected int size;
 185: 
 186:   /**
 187:    * The size of this font in points.
 188:    *
 189:    * @since 1.0
 190:    */
 191:   protected float pointSize;
 192: 
 193:   /**
 194:    * The style of this font -- PLAIN, BOLD, ITALIC or BOLD+ITALIC.
 195:    *
 196:    * @since 1.0
 197:    */
 198:   protected int style;
 199: 
 200: //Serialization constant
 201:   private static final long serialVersionUID = -4206021311591459213L;
 202: 
 203: 
 204:   // The ClasspathToolkit-provided peer which implements this font
 205:   private transient ClasspathFontPeer peer;
 206: 
 207: 
 208:   /**
 209:    * Creates a <code>Font</code> object from the specified string, which
 210:    * is in one of the following formats:
 211:    * <p>
 212:    * <ul>
 213:    * <li>fontname-style-pointsize
 214:    * <li>fontname-style
 215:    * <li>fontname-pointsize
 216:    * <li>fontname
 217:    * </ul>
 218:    * <p>
 219:    * The style should be one of BOLD, ITALIC, or BOLDITALIC.  The default
 220:    * style if none is specified is PLAIN.  The default size if none
 221:    * is specified is 12.
 222:    * 
 223:    * @param fontspec  a string specifying the required font (<code>null</code> 
 224:    *                  permitted, interpreted as 'Dialog-PLAIN-12').
 225:    * 
 226:    * @return A font.
 227:    */
 228:   public static Font decode(String fontspec)
 229:   {
 230:     if (fontspec == null) 
 231:       fontspec = "Dialog-PLAIN-12";
 232:     String name = null;
 233:     int style = PLAIN;
 234:     int size = 12;
 235: 
 236:     StringTokenizer st = new StringTokenizer(fontspec, "- ");
 237:     while (st.hasMoreTokens())
 238:       {
 239:         String token = st.nextToken();
 240:         if (name == null)
 241:           {
 242:             name = token;
 243:             continue;
 244:           }
 245: 
 246:         if (token.toUpperCase().equals("BOLD"))
 247:           {
 248:             style = BOLD;
 249:             continue;
 250:           }
 251:         if (token.toUpperCase().equals("ITALIC"))
 252:           {
 253:             style = ITALIC;
 254:             continue;
 255:           }
 256:         if (token.toUpperCase().equals("BOLDITALIC"))
 257:           {
 258:             style = BOLD | ITALIC;
 259:             continue;
 260:           }
 261: 
 262:         int tokenval = 0;
 263:         try
 264:           {
 265:             tokenval = Integer.parseInt(token);
 266:           }
 267:         catch (NumberFormatException e)
 268:           {
 269:             // Ignored.
 270:           }
 271: 
 272:       if (tokenval != 0)
 273:         size = tokenval;
 274:     }
 275: 
 276:     HashMap attrs = new HashMap();
 277:     ClasspathFontPeer.copyStyleToAttrs(style, attrs);
 278:     ClasspathFontPeer.copySizeToAttrs(size, attrs);
 279: 
 280:     return getFontFromToolkit(name, attrs);
 281:   }
 282: 
 283:   /* These methods delegate to the toolkit. */
 284: 
 285:   static ClasspathToolkit tk()
 286:   {
 287:     return (ClasspathToolkit) Toolkit.getDefaultToolkit();
 288:   }
 289: 
 290:   /* Every factory method in Font should eventually call this. */
 291:   static Font getFontFromToolkit(String name, Map attribs)
 292:   {
 293:     return tk().getFont(name, attribs);
 294:   }
 295: 
 296:   /* Every Font constructor should eventually call this. */
 297:   static ClasspathFontPeer getPeerFromToolkit(String name, Map attrs)
 298:   {
 299:     return tk().getClasspathFontPeer(name, attrs);
 300:   }
 301: 
 302: 
 303:   /**
 304:    * Returns a <code>Font</code> object from the passed property name.
 305:    *
 306:    * @param propname The name of the system property.
 307:    * @param defval Value to use if the property is not found.
 308:    *
 309:    * @return The requested font, or <code>default</code> if the property 
 310:    * not exist or is malformed.
 311:    */
 312:   public static Font getFont(String propname, Font defval)
 313:   {
 314:     String propval = System.getProperty(propname);
 315:     if (propval != null)
 316:       return decode(propval);
 317:     return defval;
 318:   }
 319: 
 320:   /**
 321:    * Returns a <code>Font</code> object from the passed property name.
 322:    *
 323:    * @param propname The name of the system property.
 324:    *
 325:    * @return The requested font, or <code>null</code> if the property 
 326:    * not exist or is malformed.
 327:    */
 328:   public static Font getFont(String propname)
 329:   {
 330:     return getFont(propname, (Font) null);
 331:   }
 332: 
 333:   /**
 334:    * Initializes a new instance of <code>Font</code> with the specified
 335:    * attributes.
 336:    *
 337:    * @param name The name of the font.
 338:    * @param style The font style.
 339:    * @param size The font point size.
 340:    */
 341:   public Font(String name, int style, int size)
 342:   {
 343:     HashMap attrs = new HashMap();
 344:     ClasspathFontPeer.copyStyleToAttrs(style, attrs);
 345:     ClasspathFontPeer.copySizeToAttrs(size, attrs);
 346:     this.peer = getPeerFromToolkit(name, attrs);
 347:     this.size = size;
 348:     this.pointSize = (float) size;
 349:     if (name != null)
 350:       this.name = name;
 351:     else
 352:       this.name = peer.getName(this);
 353:   }
 354: 
 355:   public Font(Map<? extends AttributedCharacterIterator.Attribute, ?> attrs)
 356:   {
 357:     this(null, attrs);
 358:   }
 359: 
 360:   /* This extra constructor is here to permit ClasspathToolkit and to
 361:    build a font with a "logical name" as well as attrs.
 362:    ClasspathToolkit.getFont(String,Map) uses reflection to call this
 363:    package-private constructor. */
 364:   Font(String name, Map attrs)
 365:   {
 366:     // If attrs is null, setting it to an empty HashMap will give this
 367:     // Font default attributes.
 368:     if (attrs == null)
 369:       attrs = new HashMap();
 370:     peer = getPeerFromToolkit(name, attrs);
 371:     size = (int) peer.getSize(this);
 372:     pointSize = peer.getSize(this);
 373:     if (name != null)
 374:       this.name = name;
 375:     else
 376:       this.name = peer.getName(this);
 377:   }
 378: 
 379:   /**
 380:    * Returns the logical name of the font.  A logical name is the name the
 381:    * font was constructed with. It may be the name of a logical font (one
 382:    * of 6 required names in all java environments) or it may be a face
 383:    * name.
 384:    *
 385:    * @return The logical name of the font.
 386:    *
 387:    * @see #getFamily()
 388:    * @see #getFontName()
 389:    */
 390:   public String getName ()
 391:   {
 392:     return peer.getName(this);
 393:   }
 394: 
 395:   /**
 396:    * Returns the size of the font, in typographics points (1/72 of an inch),
 397:    * rounded to an integer.
 398:    * 
 399:    * @return The font size
 400:    */
 401:   public int getSize()
 402:   {
 403:     return size;
 404:   }
 405: 
 406:   /**
 407:    * Returns the size of the font, in typographics points (1/72 of an inch).
 408:    * 
 409:    * @return The font size
 410:    */
 411:   public float getSize2D()
 412:   {
 413:     return pointSize;
 414:   }
 415: 
 416:   /**
 417:    * Tests whether or not this is a plain font.  This will be true if
 418:    * and only if neither the bold nor the italics style is set.
 419:    *
 420:    * @return <code>true</code> if this is a plain font, <code>false</code>
 421:    * otherwise.
 422:    */
 423:   public boolean isPlain()
 424:   {
 425:     return peer.isPlain(this); 
 426:   }
 427: 
 428:   /**
 429:    * Tests whether or not this font is bold.
 430:    *
 431:    * @return <code>true</code> if this font is bold, <code>false</code>
 432:    * otherwise.
 433:    */
 434:   public boolean isBold()
 435:   {
 436:     return peer.isBold(this);
 437:   }
 438: 
 439:   /**
 440:    * Tests whether or not this font is italic.
 441:    *
 442:    * @return <code>true</code> if this font is italic, <code>false</code>
 443:    * otherwise.
 444:    */
 445:   public boolean isItalic()
 446:   {
 447:     return peer.isItalic(this);
 448:   }
 449: 
 450:   /**
 451:    * Returns the family name of this font. A family name describes a design
 452:    * or "brand name" (such as Helvetica or Palatino). It is less specific
 453:    * than a font face name (such as Helvetica Bold).
 454:    *
 455:    * @return A string containing the font family name.
 456:    *
 457:    * @since 1.2
 458:    *
 459:    * @see #getName()
 460:    * @see #getFontName()
 461:    * @see GraphicsEnvironment#getAvailableFontFamilyNames()
 462:    */
 463:   public String getFamily()
 464:   {
 465:     return peer.getFamily(this);
 466:   }
 467: 
 468:   /**
 469:    * Returns integer code representing the sum of style flags of this font, a
 470:    * combination of either {@link #PLAIN}, {@link #BOLD}, or {@link #ITALIC}.
 471:    *
 472:    * @return code representing the style of this font.
 473:    *
 474:    * @see #isPlain()
 475:    * @see #isBold()
 476:    * @see #isItalic()
 477:    */
 478:   public int getStyle()
 479:   {
 480:     return peer.getStyle(this);
 481:   }
 482: 
 483:   /**
 484:    * Checks if specified character maps to a glyph in this font.
 485:    *
 486:    * @param c The character to check.
 487:    *
 488:    * @return Whether the character has a corresponding glyph in this font.
 489:    *
 490:    * @since 1.2
 491:    */
 492:   public boolean canDisplay(char c)
 493:   {
 494:     return peer.canDisplay(this, c);    
 495:   }
 496: 
 497:   /**
 498:    * Checks how much of a given string can be mapped to glyphs in 
 499:    * this font.
 500:    *
 501:    * @param s The string to check.
 502:    *
 503:    * @return The index of the first character in <code>s</code> which cannot
 504:    * be converted to a glyph by this font, or <code>-1</code> if all
 505:    * characters can be mapped to glyphs.
 506:    *
 507:    * @since 1.2
 508:    */
 509:   public int canDisplayUpTo(String s)
 510:   {
 511:     return peer.canDisplayUpTo(this, new StringCharacterIterator(s), 
 512:                                0, s.length() - 1);
 513:   }
 514: 
 515:   /**
 516:    * Checks how much of a given sequence of text can be mapped to glyphs in
 517:    * this font.
 518:    *
 519:    * @param text Array containing the text to check.
 520:    * @param start Position of first character to check in <code>text</code>.
 521:    * @param limit Position of last character to check in <code>text</code>.
 522:    *
 523:    * @return The index of the first character in the indicated range which
 524:    * cannot be converted to a glyph by this font, or <code>-1</code> if all
 525:    * characters can be mapped to glyphs.
 526:    *
 527:    * @since 1.2
 528:    *
 529:    * @throws IndexOutOfBoundsException if the range [start, limit] is
 530:    * invalid in <code>text</code>.
 531:    */
 532:   public int canDisplayUpTo (char[] text, int start, int limit)
 533:   {
 534:     return peer.canDisplayUpTo(this,
 535:                                new StringCharacterIterator(new String (text)),
 536:                                start, limit);
 537:   }
 538: 
 539:   /**
 540:    * Checks how much of a given sequence of text can be mapped to glyphs in
 541:    * this font.
 542:    *
 543:    * @param i Iterator over the text to check.
 544:    * @param start Position of first character to check in <code>i</code>.
 545:    * @param limit Position of last character to check in <code>i</code>.
 546:    *
 547:    * @return The index of the first character in the indicated range which
 548:    * cannot be converted to a glyph by this font, or <code>-1</code> if all
 549:    * characters can be mapped to glyphs.
 550:    *
 551:    * @since 1.2
 552:    *
 553:    * @throws IndexOutOfBoundsException if the range [start, limit] is
 554:    * invalid in <code>i</code>.
 555:    */
 556:   public int canDisplayUpTo(CharacterIterator i, int start, int limit)
 557:   {
 558:     return peer.canDisplayUpTo(this, i, start, limit);    
 559:   }
 560: 
 561:   /**
 562:    * Creates a new font with point size 1 and {@link #PLAIN} style,
 563:    * reading font data from the provided input stream. The resulting font
 564:    * can have further fonts derived from it using its
 565:    * <code>deriveFont</code> method.
 566:    *
 567:    * @param fontFormat Integer code indicating the format the font data is
 568:    * in.Currently this can only be {@link #TRUETYPE_FONT}.
 569:    * @param is {@link InputStream} from which font data will be read. This
 570:    * stream is not closed after font data is extracted.
 571:    *
 572:    * @return A new {@link Font} of the format indicated.
 573:    *
 574:    * @throws IllegalArgumentException if <code>fontType</code> is not
 575:    * recognized.
 576:    * @throws FontFormatException if data in InputStream is not of format
 577:    * indicated.
 578:    * @throws IOException if insufficient data is present on InputStream.
 579:    *
 580:    * @since 1.3
 581:    */
 582:   public static Font createFont (int fontFormat, InputStream is)
 583:     throws FontFormatException, IOException
 584:   {
 585:     return tk().createFont(fontFormat, is);
 586:   }
 587: 
 588:   /**
 589:    * Creates a new font from a File object.
 590:    *
 591:    * @see #layoutGlyphVector(FontRenderContext, char[], int, int, int)
 592:    *
 593:    * @param fontFormat - Integer code indicating the format the font data is
 594:    * in.Currently this can only be {@link #TRUETYPE_FONT}.
 595:    * @param file - a {@link File} from which font data will be read.
 596:    *
 597:    * @return A new {@link Font} of the format indicated.
 598:    *
 599:    * @throws IllegalArgumentException if <code>fontType</code> is not
 600:    * recognized.
 601:    * @throws NullPointerException if <code>file</code> is <code>null</code>.
 602:    * @throws FontFormatException if data in the file is invalid or cannot be read..
 603:    * @throws SecurityException if the caller has no read permission for the file.
 604:    * @throws IOException if the file cannot be read
 605:    *
 606:    * @since 1.5
 607:    */
 608:   public static Font createFont (int fontFormat, File file)
 609:     throws FontFormatException, IOException
 610:   {
 611:     if( file == null )
 612:       throw new NullPointerException("Null file argument");
 613:     return tk().createFont(fontFormat, new FileInputStream( file ));
 614:   }
 615: 
 616:   /**
 617:    * Maps characters to glyphs in a one-to-one relationship, returning a new
 618:    * {@link GlyphVector} with a mapped glyph for each input character. This
 619:    * sort of mapping is often sufficient for some scripts such as Roman, but
 620:    * is inappropriate for scripts with special shaping or contextual layout
 621:    * requirements such as Arabic, Indic, Hebrew or Thai.
 622:    *
 623:    * @param ctx The rendering context used for precise glyph placement.
 624:    * @param str The string to convert to Glyphs.
 625:    *
 626:    * @return A new {@link GlyphVector} containing glyphs mapped from str,
 627:    * through the font's cmap table.
 628:    *
 629:    * @see #layoutGlyphVector(FontRenderContext, char[], int, int, int)
 630:    */
 631:   public GlyphVector createGlyphVector(FontRenderContext ctx, String str)
 632:   {
 633:     return peer.createGlyphVector(this, ctx, new StringCharacterIterator(str));
 634:   }
 635: 
 636:   /**
 637:    * Maps characters to glyphs in a one-to-one relationship, returning a new
 638:    * {@link GlyphVector} with a mapped glyph for each input character. This
 639:    * sort of mapping is often sufficient for some scripts such as Roman, but
 640:    * is inappropriate for scripts with special shaping or contextual layout
 641:    * requirements such as Arabic, Indic, Hebrew or Thai.
 642:    *
 643:    * @param ctx The rendering context used for precise glyph placement.
 644:    * @param i Iterator over the text to convert to glyphs.
 645:    *
 646:    * @return A new {@link GlyphVector} containing glyphs mapped from str,
 647:    * through the font's cmap table.
 648:    *
 649:    * @see #layoutGlyphVector(FontRenderContext, char[], int, int, int)
 650:    */
 651:   public GlyphVector createGlyphVector(FontRenderContext ctx,
 652:                                        CharacterIterator i)
 653:   {
 654:     return peer.createGlyphVector(this, ctx, i);
 655:   }
 656: 
 657:   /**
 658:    * Maps characters to glyphs in a one-to-one relationship, returning a new
 659:    * {@link GlyphVector} with a mapped glyph for each input character. This
 660:    * sort of mapping is often sufficient for some scripts such as Roman, but
 661:    * is inappropriate for scripts with special shaping or contextual layout
 662:    * requirements such as Arabic, Indic, Hebrew or Thai.
 663:    *
 664:    * @param ctx The rendering context used for precise glyph placement.
 665:    * @param chars Array of characters to convert to glyphs.
 666:    *
 667:    * @return A new {@link GlyphVector} containing glyphs mapped from str,
 668:    * through the font's cmap table.
 669:    *
 670:    * @see #layoutGlyphVector(FontRenderContext, char[], int, int, int)
 671:    */
 672:   public GlyphVector createGlyphVector(FontRenderContext ctx, char[] chars)
 673:   {
 674:     return peer.createGlyphVector(this, ctx,
 675:                                new StringCharacterIterator(new String(chars)));
 676:   }
 677: 
 678:   /**
 679:    * Extracts a sequence of glyphs from a font, returning a new {@link
 680:    * GlyphVector} with a mapped glyph for each input glyph code. 
 681:    *
 682:    * @param ctx The rendering context used for precise glyph placement.
 683:    * @param glyphCodes Array of characters to convert to glyphs.
 684:    *
 685:    * @return A new {@link GlyphVector} containing glyphs mapped from str,
 686:    * through the font's cmap table.
 687:    *
 688:    * @see #layoutGlyphVector(FontRenderContext, char[], int, int, int)
 689:    *
 690:    * @specnote This method is documented to perform character-to-glyph
 691:    * conversions, in the Sun documentation, but its second parameter name is
 692:    * "glyphCodes" and it is not clear to me why it would exist if its
 693:    * purpose was to transport character codes inside integers. I assume it
 694:    * is mis-documented in the Sun documentation.
 695:    */
 696:   public GlyphVector createGlyphVector(FontRenderContext ctx, int[] glyphCodes)
 697:   {
 698:     return peer.createGlyphVector(this, ctx, glyphCodes);
 699:   }
 700: 
 701:   /**
 702:    * Produces a new {@link Font} based on the current font, adjusted to a
 703:    * new size and style.
 704:    *
 705:    * @param style The style of the newly created font.
 706:    * @param size The size of the newly created font.
 707:    *
 708:    * @return A clone of the current font, with the specified size and style.
 709:    *
 710:    * @since 1.2
 711:    */
 712:   public Font deriveFont(int style, float size)
 713:   {
 714:     return peer.deriveFont(this, style, size);
 715:   }
 716: 
 717:   /**
 718:    * Produces a new {@link Font} based on the current font, adjusted to a
 719:    * new size.
 720:    *
 721:    * @param size The size of the newly created font.
 722:    *
 723:    * @return A clone of the current font, with the specified size.
 724:    *
 725:    * @since 1.2
 726:    */
 727:   public Font deriveFont(float size)
 728:   {
 729:     return peer.deriveFont(this, size);
 730:   }
 731: 
 732:   /**
 733:    * Produces a new {@link Font} based on the current font, adjusted to a
 734:    * new style.
 735:    *
 736:    * @param style The style of the newly created font.
 737:    *
 738:    * @return A clone of the current font, with the specified style.
 739:    *
 740:    * @since 1.2
 741:    */
 742:   public Font deriveFont(int style)
 743:   {
 744:     return peer.deriveFont(this, style);
 745:   }
 746: 
 747:   /**
 748:    * Produces a new {@link Font} based on the current font, adjusted to a
 749:    * new style and subjected to a new affine transformation.
 750:    *
 751:    * @param style The style of the newly created font.
 752:    * @param a The transformation to apply.
 753:    *
 754:    * @return A clone of the current font, with the specified style and
 755:    * transform.
 756:    *
 757:    * @throws IllegalArgumentException If transformation is
 758:    * <code>null</code>.
 759:    *
 760:    * @since 1.2
 761:    */
 762:   public Font deriveFont(int style, AffineTransform a)
 763:   {
 764:     if (a == null)
 765:       throw new IllegalArgumentException("Affine transformation is null");
 766: 
 767:     return peer.deriveFont(this, style, a);
 768:   }
 769: 
 770:   /**
 771:    * Produces a new {@link Font} based on the current font, subjected
 772:    * to a new affine transformation.
 773:    *
 774:    * @param a The transformation to apply.
 775:    *
 776:    * @return A clone of the current font, with the specified transform.
 777:    *
 778:    * @throws IllegalArgumentException If transformation is
 779:    * <code>null</code>.
 780:    *
 781:    * @since 1.2
 782:    */
 783:   public Font deriveFont(AffineTransform a)
 784:   {
 785:     if (a == null)
 786:       throw new IllegalArgumentException("Affine transformation is null");
 787: 
 788:     return peer.deriveFont(this, a);
 789:   }
 790: 
 791:   /**
 792:    * Produces a new {@link Font} based on the current font, adjusted to a
 793:    * new set of attributes.
 794:    *
 795:    * @param attributes Attributes of the newly created font.
 796:    *
 797:    * @return A clone of the current font, with the specified attributes.
 798:    *
 799:    * @since 1.2
 800:    */
 801:   public Font deriveFont(Map<? extends AttributedCharacterIterator.Attribute, ?> attributes)
 802:   {
 803:     return peer.deriveFont(this, attributes);
 804:   }
 805: 
 806:   /**
 807:    * Returns a map of chracter attributes which this font currently has set.
 808:    *
 809:    * @return A map of chracter attributes which this font currently has set.
 810:    *
 811:    * @see #getAvailableAttributes()
 812:    * @see java.text.AttributedCharacterIterator.Attribute
 813:    * @see java.awt.font.TextAttribute
 814:    */
 815:   public Map<TextAttribute, ?> getAttributes()
 816:   {
 817:     return peer.getAttributes(this);
 818:   }
 819: 
 820:   /**
 821:    * Returns an array of chracter attribute keys which this font understands. 
 822:    *
 823:    * @return An array of chracter attribute keys which this font understands.
 824:    *
 825:    * @see #getAttributes()
 826:    * @see java.text.AttributedCharacterIterator.Attribute
 827:    * @see java.awt.font.TextAttribute
 828:    */
 829:   public AttributedCharacterIterator.Attribute[] getAvailableAttributes()
 830:   {
 831:     return peer.getAvailableAttributes(this);
 832:   }
 833: 
 834:   /**
 835:    * Returns a baseline code (one of {@link #ROMAN_BASELINE}, {@link
 836:    * #CENTER_BASELINE} or {@link #HANGING_BASELINE}) indicating which baseline
 837:    * this font will measure baseline offsets for, when presenting glyph
 838:    * metrics for a given character.
 839:    *
 840:    * Baseline offsets describe the position of a glyph relative to an
 841:    * invisible line drawn under, through the center of, or over a line of
 842:    * rendered text, respectively. Different scripts use different baseline
 843:    * modes, so clients should not assume all baseline offsets in a glyph
 844:    * vector are from a common baseline.
 845:    *
 846:    * @param c The character code to select a baseline mode for.
 847:    *
 848:    * @return The baseline mode which would be used in a glyph associated
 849:    * with the provided character.
 850:    *
 851:    * @since 1.2
 852:    *
 853:    * @see LineMetrics#getBaselineOffsets()
 854:    */
 855:   public byte getBaselineFor(char c)
 856:   {
 857:     return peer.getBaselineFor(this, c);
 858:   }
 859: 
 860:   /**
 861:    * Returns the family name of this font. A family name describes a
 862:    * typographic style (such as Helvetica or Palatino). It is more specific
 863:    * than a logical font name (such as Sans Serif) but less specific than a
 864:    * font face name (such as Helvetica Bold).
 865:    *
 866:    * @param lc The locale in which to describe the name of the font family.
 867:    *
 868:    * @return A string containing the font family name, localized for the
 869:    * provided locale.
 870:    *
 871:    * @since 1.2
 872:    *
 873:    * @see #getName()
 874:    * @see #getFontName()
 875:    * @see GraphicsEnvironment#getAvailableFontFamilyNames()
 876:    * @see Locale
 877:    */
 878:   public String getFamily(Locale lc)
 879:   {
 880:     return peer.getFamily(this, lc); 
 881:   }
 882: 
 883:   /**
 884:    * Returns a font appropriate for the given attribute set.
 885:    *
 886:    * @param attributes The attributes required for the new font.
 887:    *
 888:    * @return A new Font with the given attributes.
 889:    *
 890:    * @since 1.2
 891:    *
 892:    * @see java.awt.font.TextAttribute  
 893:    */
 894:   public static Font getFont(Map<? extends AttributedCharacterIterator.Attribute, ?> attributes)
 895:   {
 896:     return getFontFromToolkit(null, attributes);
 897:   }
 898: 
 899:   /**
 900:    * Returns the font face name of the font.  A font face name describes a
 901:    * specific variant of a font family (such as Helvetica Bold). It is more
 902:    * specific than both a font family name (such as Helvetica) and a logical
 903:    * font name (such as Sans Serif).
 904:    *
 905:    * @return The font face name of the font.
 906:    *
 907:    * @since 1.2
 908:    *
 909:    * @see #getName()
 910:    * @see #getFamily()
 911:    */
 912:   public String getFontName()
 913:   {
 914:     return peer.getFontName(this);
 915:   }
 916: 
 917:   /**
 918:    * Returns the font face name of the font.  A font face name describes a
 919:    * specific variant of a font family (such as Helvetica Bold). It is more
 920:    * specific than both a font family name (such as Helvetica).
 921:    *
 922:    * @param lc The locale in which to describe the name of the font face.
 923:    *
 924:    * @return A string containing the font face name, localized for the
 925:    * provided locale.
 926:    *
 927:    * @since 1.2
 928:    *
 929:    * @see #getName()
 930:    * @see #getFamily()
 931:    */
 932:   public String getFontName(Locale lc)
 933:   {
 934:     return peer.getFontName(this, lc);
 935:   }
 936: 
 937:   /**
 938:    * Returns the italic angle of this font, a measurement of its slant when
 939:    * style is {@link #ITALIC}. The precise meaning is the inverse slope of a
 940:    * caret line which "best measures" the font's italic posture.
 941:    *
 942:    * @return The italic angle.
 943:    *
 944:    * @see java.awt.font.TextAttribute#POSTURE
 945:    */
 946:   public float getItalicAngle()
 947:   {
 948:     return peer.getItalicAngle(this);
 949:   }
 950: 
 951:   /**
 952:    * Returns a {@link LineMetrics} object constructed with the specified
 953:    * text and {@link FontRenderContext}. 
 954:    *
 955:    * @param text The string to calculate metrics from.
 956:    * @param begin Index of first character in <code>text</code> to measure.
 957:    * @param limit Index of last character in <code>text</code> to measure.
 958:    * @param rc Context for calculating precise glyph placement and hints.
 959:    *
 960:    * @return A new {@link LineMetrics} object.
 961:    *
 962:    * @throws IndexOutOfBoundsException if the range [begin, limit] is
 963:    * invalid in <code>text</code>.
 964:    */
 965:   public LineMetrics getLineMetrics(String text, int begin, 
 966:                                     int limit, FontRenderContext rc)
 967:   {
 968:     return peer.getLineMetrics(this, new StringCharacterIterator(text), 
 969:                                begin, limit, rc);
 970:   }
 971: 
 972:   /**
 973:    * Returns a {@link LineMetrics} object constructed with the specified
 974:    * text and {@link FontRenderContext}. 
 975:    *
 976:    * @param chars The string to calculate metrics from.
 977:    * @param begin Index of first character in <code>text</code> to measure.
 978:    * @param limit Index of last character in <code>text</code> to measure.
 979:    * @param rc Context for calculating precise glyph placement and hints.
 980:    *
 981:    * @return A new {@link LineMetrics} object.
 982:    *
 983:    * @throws IndexOutOfBoundsException if the range [begin, limit] is
 984:    * invalid in <code>chars</code>.
 985:    */
 986:   public LineMetrics getLineMetrics(char[] chars, int begin, 
 987:                                     int limit, FontRenderContext rc)
 988:   {
 989:     return peer.getLineMetrics(this,
 990:                                new StringCharacterIterator(new String(chars)), 
 991:                                begin, limit, rc);
 992:   }
 993: 
 994:   /**
 995:    * Returns a {@link LineMetrics} object constructed with the specified
 996:    * text and {@link FontRenderContext}. 
 997:    *
 998:    * @param ci The string to calculate metrics from.
 999:    * @param begin Index of first character in <code>text</code> to measure.
1000:    * @param limit Index of last character in <code>text</code> to measure.
1001:    * @param rc Context for calculating precise glyph placement and hints.
1002:    *
1003:    * @return A new {@link LineMetrics} object.
1004:    *
1005:    * @throws IndexOutOfBoundsException if the range [begin, limit] is
1006:    * invalid in <code>ci</code>.
1007:    */
1008:   public LineMetrics getLineMetrics(CharacterIterator ci, int begin, 
1009:                                     int limit, FontRenderContext rc)
1010:   {
1011:     return peer.getLineMetrics(this, ci, begin, limit, rc);
1012:   }
1013: 
1014:   /**
1015:    * Returns the maximal bounding box of all the bounding boxes in this
1016:    * font, when the font's bounding boxes are evaluated in a given {@link
1017:    * FontRenderContext}
1018:    *
1019:    * @param rc Context in which to evaluate bounding boxes.
1020:    *
1021:    * @return The maximal bounding box.
1022:    */
1023:   public Rectangle2D getMaxCharBounds(FontRenderContext rc)
1024:   {
1025:     return peer.getMaxCharBounds(this, rc);
1026:   }
1027: 
1028:   /**
1029:    * Returns the glyph code this font uses to represent missing glyphs. This
1030:    * code will be present in glyph vectors when the font was unable to
1031:    * locate a glyph to represent a particular character code.
1032:    *
1033:    * @return The missing glyph code.
1034:    *
1035:    * @since 1.2
1036:    */
1037:   public int getMissingGlyphCode()
1038:   {
1039:     return peer.getMissingGlyphCode(this);
1040:   }
1041: 
1042:   /**
1043:    * Returns the overall number of glyphs in this font. This number is one
1044:    * more than the greatest glyph code used in any glyph vectors this font
1045:    * produces. In other words, glyph codes are taken from the range
1046:    * <code>[ 0, getNumGlyphs() - 1 ]</code>.
1047:    *
1048:    * @return The number of glyphs in this font.
1049:    * 
1050:    * @since 1.2
1051:    */
1052:   public int getNumGlyphs()
1053:   {
1054:     return peer.getNumGlyphs(this);
1055:   }
1056: 
1057:   /**
1058:    * Returns the PostScript Name of this font.   
1059:    *
1060:    * @return The PostScript Name of this font.
1061:    *
1062:    * @since 1.2
1063:    *
1064:    * @see #getName()
1065:    * @see #getFamily()
1066:    * @see #getFontName()
1067:    */
1068:   public String getPSName()
1069:   {
1070:     return peer.getPostScriptName(this);
1071:   }
1072: 
1073:   /**
1074:    * Returns the logical bounds of the specified string when rendered with this
1075:    * font in the specified {@link FontRenderContext}. This box will include the
1076:    * glyph origin, ascent, advance, height, and leading, but may not include all
1077:    * diacritics or accents. To get the complete visual bounding box of all the
1078:    * glyphs in a run of text, use the {@link TextLayout#getBounds} method of 
1079:    * {@link TextLayout}.
1080:    *
1081:    * @param str The string to measure.
1082:    * @param frc The context in which to make the precise glyph measurements.
1083:    * 
1084:    * @return A bounding box covering the logical bounds of the specified text.
1085:    *
1086:    * @see #createGlyphVector(FontRenderContext, String)
1087:    */
1088:   public Rectangle2D getStringBounds(String str, FontRenderContext frc)
1089:   {
1090:     char[] chars = str.toCharArray();
1091:     return getStringBounds(chars, 0, chars.length, frc);
1092:   }
1093: 
1094:   /**
1095:    * Returns the logical bounds of the specified string when rendered with this
1096:    * font in the specified {@link FontRenderContext}. This box will include the
1097:    * glyph origin, ascent, advance, height, and leading, but may not include all
1098:    * diacritics or accents. To get the complete visual bounding box of all the
1099:    * glyphs in a run of text, use the {@link TextLayout#getBounds} method of
1100:    * {@link TextLayout}.
1101:    *
1102:    * @param str The string to measure.
1103:    * @param begin Index of the first character in <code>str</code> to measure.
1104:    * @param limit Index of the last character in <code>str</code> to measure.
1105:    * @param frc The context in which to make the precise glyph measurements.
1106:    * 
1107:    * @return A bounding box covering the logical bounds of the specified text.
1108:    *
1109:    * @throws IndexOutOfBoundsException if the range [begin, limit] is
1110:    * invalid in <code>str</code>.
1111:    *
1112:    * @since 1.2
1113:    *
1114:    * @see #createGlyphVector(FontRenderContext, String)
1115:    */
1116:   public Rectangle2D getStringBounds(String str, int begin, 
1117:                                      int limit, FontRenderContext frc)
1118:   {
1119:     String sub = str.substring(begin, limit);
1120:     return getStringBounds(sub, frc);
1121:   }
1122: 
1123:   /**
1124:    * Returns the logical bounds of the specified string when rendered with this
1125:    * font in the specified {@link FontRenderContext}. This box will include the
1126:    * glyph origin, ascent, advance, height, and leading, but may not include all
1127:    * diacritics or accents. To get the complete visual bounding box of all the
1128:    * glyphs in a run of text, use the {@link TextLayout#getBounds} method of
1129:    * {@link TextLayout}.
1130:    *
1131:    * @param ci The text to measure.
1132:    * @param begin Index of the first character in <code>ci</code> to measure.
1133:    * @param limit Index of the last character in <code>ci</code> to measure.
1134:    * @param frc The context in which to make the precise glyph measurements.
1135:    * 
1136:    * @return A bounding box covering the logical bounds of the specified text.
1137:    *
1138:    * @throws IndexOutOfBoundsException if the range [begin, limit] is
1139:    * invalid in <code>ci</code>.
1140:    *
1141:    * @since 1.2
1142:    *
1143:    * @see #createGlyphVector(FontRenderContext, CharacterIterator)
1144:    */
1145:   public Rectangle2D getStringBounds(CharacterIterator ci, int begin, 
1146:                                      int limit, FontRenderContext frc)
1147:   {
1148:     int start = ci.getBeginIndex();
1149:     int end = ci.getEndIndex();
1150:     char[] chars = new char[limit - start];
1151:     ci.setIndex(start);
1152:     for (int index = 0; index < chars.length; index++)
1153:       {
1154:         chars[index] = ci.current();
1155:         ci.next();
1156:       }
1157:     return getStringBounds(chars, 0, chars.length, frc);
1158:   }
1159: 
1160:   /**
1161:    * Returns the logical bounds of the specified string when rendered with this
1162:    * font in the specified {@link FontRenderContext}. This box will include the
1163:    * glyph origin, ascent, advance, height, and leading, but may not include all
1164:    * diacritics or accents. To get the complete visual bounding box of all the
1165:    * glyphs in a run of text, use the {@link TextLayout#getBounds} method of
1166:    * {@link TextLayout}.
1167:    *
1168:    * @param chars The text to measure.
1169:    * @param begin Index of the first character in <code>ci</code> to measure.
1170:    * @param limit Index of the last character in <code>ci</code> to measure.
1171:    * @param frc The context in which to make the precise glyph measurements.
1172:    * 
1173:    * @return A bounding box covering the logical bounds of the specified text.
1174:    *
1175:    * @throws IndexOutOfBoundsException if the range [begin, limit] is
1176:    * invalid in <code>chars</code>.
1177:    *
1178:    * @since 1.2
1179:    *
1180:    * @see #createGlyphVector(FontRenderContext, char[])
1181:    */
1182:   public Rectangle2D getStringBounds(char[] chars, int begin, 
1183:                                      int limit, FontRenderContext frc)
1184:   {
1185:     String str = new String(chars, begin, limit - begin);
1186:     TextLayout layout = new TextLayout(str, this, frc);
1187:     return new Rectangle2D.Float(0, -layout.getAscent(), layout.getAdvance(),
1188:                                 layout.getDescent() + layout.getLeading());
1189:   }
1190: 
1191:   /**
1192:    * Returns a copy of the affine transformation this font is currently
1193:    * subject to, if any.
1194:    *
1195:    * @return The current transformation.
1196:    */
1197:   public AffineTransform getTransform()
1198:   {
1199:     return peer.getTransform(this);
1200:   }
1201: 
1202:   /**
1203:    * Indicates whether this font's line metrics are uniform. A font may be
1204:    * composed of several "subfonts", each covering a different code range,
1205:    * and each with their own line metrics. A font with no subfonts, or
1206:    * subfonts with identical line metrics, is said to have "uniform" line
1207:    * metrics.
1208:    *
1209:    * @return Whether this font has uniform line metrics.
1210:    *
1211:    * @see LineMetrics
1212:    * @see #getLineMetrics(String, FontRenderContext)
1213:    */
1214:   public boolean hasUniformLineMetrics()
1215:   {
1216:     return peer.hasUniformLineMetrics(this);
1217:   }
1218: 
1219:   /**
1220:    * Indicates whether this font is subject to a non-identity affine
1221:    * transformation.
1222:    *
1223:    * @return <code>true</code> iff the font has a non-identity affine
1224:    * transformation applied to it.
1225:    */
1226:   public boolean isTransformed()
1227:   {
1228:     return peer.isTransformed(this);
1229:   }
1230: 
1231:   /**
1232:    * Produces a glyph vector representing a full layout fo the specified
1233:    * text in this font. Full layouts may include complex shaping and
1234:    * reordering operations, for scripts such as Arabic or Hindi.
1235:    *
1236:    * Bidirectional (bidi) layout is not performed in this method; text
1237:    * should have its bidi direction specified with one of the flags {@link
1238:    * #LAYOUT_LEFT_TO_RIGHT} or {@link #LAYOUT_RIGHT_TO_LEFT}.
1239:    *
1240:    * Some types of layout (notably Arabic glyph shaping) may examine context
1241:    * characters beyond the bounds of the indicated range, in order to select
1242:    * an appropriate shape. The flags {@link #LAYOUT_NO_START_CONTEXT} and
1243:    * {@link #LAYOUT_NO_LIMIT_CONTEXT} can be provided to prevent these extra
1244:    * context areas from being examined, for instance if they contain invalid
1245:    * characters.
1246:    *
1247:    * @param frc Context in which to perform the layout.
1248:    * @param chars Text to perform layout on.
1249:    * @param start Index of first character to perform layout on.
1250:    * @param limit Index of last character to perform layout on.
1251:    * @param flags Combination of flags controlling layout.
1252:    *
1253:    * @return A new {@link GlyphVector} representing the specified text.
1254:    *
1255:    * @throws IndexOutOfBoundsException if the range [begin, limit] is
1256:    * invalid in <code>chars</code>. 
1257:    */
1258:   public GlyphVector layoutGlyphVector(FontRenderContext frc, 
1259:                                        char[] chars, int start, 
1260:                                        int limit, int flags)
1261:   {
1262:     return peer.layoutGlyphVector(this, frc, chars, start, limit, flags);
1263:   }
1264: 
1265: 
1266:   /**
1267:    * Returns a native peer object for this font.
1268:    *
1269:    * @return A native peer object for this font.
1270:    *
1271:    * @deprecated
1272:    */
1273:   public FontPeer getPeer()
1274:   {
1275:     return peer;
1276:   }
1277: 
1278: 
1279:   /**
1280:    * Returns a hash value for this font.
1281:    * 
1282:    * @return A hash for this font.
1283:    */
1284:   public int hashCode()
1285:   {
1286:     return this.toString().hashCode();
1287:   }
1288: 
1289: 
1290:   /**
1291:    * Tests whether or not the specified object is equal to this font.  This
1292:    * will be true if and only if:
1293:    * <P>
1294:    * <ul>
1295:    * <li>The object is not <code>null</code>.
1296:    * <li>The object is an instance of <code>Font</code>.
1297:    * <li>The object has the same names, style, size, and transform as this object.
1298:    * </ul>
1299:    *
1300:    * @return <code>true</code> if the specified object is equal to this
1301:    * object, <code>false</code> otherwise.
1302:    */
1303:   public boolean equals(Object obj)
1304:   {
1305:     if (obj == null)
1306:       return false;
1307: 
1308:     if (! (obj instanceof Font))
1309:       return false;
1310: 
1311:     Font f = (Font) obj;
1312: 
1313:     return (f.getName().equals(this.getName())
1314:             && f.getFamily().equals(this.getFamily())
1315:             && f.getFontName().equals(this.getFontName())
1316:             && f.getTransform().equals(this.getTransform ())
1317:             && f.getSize() == this.getSize()
1318:             && f.getStyle() == this.getStyle());
1319:   }
1320: 
1321:   /**
1322:    * Returns a string representation of this font.
1323:    *
1324:    * @return A string representation of this font.
1325:    */
1326:   public String toString()
1327:   {
1328:     String styleString = "";
1329: 
1330:     switch (getStyle())
1331:       {
1332:       case 0:
1333:         styleString = "plain";
1334:         break;
1335:       case 1:
1336:         styleString = "bold";
1337:         break;
1338:       case 2:
1339:         styleString = "italic";
1340:         break;
1341:       default:
1342:         styleString = "unknown";
1343:      }
1344:     
1345:     return getClass().getName() 
1346:              + "[family=" + getFamily ()
1347:              + ",name=" + getFontName ()
1348:              + ",style=" + styleString
1349:              + ",size=" + getSize () + "]";
1350:   }
1351: 
1352: 
1353:   /**
1354:    * Determines the line metrics for a run of text.
1355:    *
1356:    * @param str the text run to be measured.
1357:    *
1358:    * @param frc the font rendering parameters that are used for the
1359:    *        measurement. The exact placement and size of text slightly
1360:    *        depends on device-specific characteristics, for instance
1361:    *        the device resolution or anti-aliasing.  For this reason,
1362:    *        the returned measurement will only be accurate if the
1363:    *        passed <code>FontRenderContext</code> correctly reflects
1364:    *        the relevant parameters. Hence, <code>frc</code> should be
1365:    *        obtained from the same <code>Graphics2D</code> that will
1366:    *        be used for drawing, and any rendering hints should be set
1367:    *        to the desired values before obtaining <code>frc</code>.
1368:    *
1369:    * @see java.awt.Graphics2D#getFontRenderContext()
1370:    */
1371:   public LineMetrics getLineMetrics(String str, FontRenderContext frc)
1372:   {
1373:     return getLineMetrics(str, 0, str.length() - 1, frc);
1374:   }
1375: 
1376:   /**
1377:    * Reads the normal fields from the stream and then constructs the
1378:    * peer from the style and size through getPeerFromToolkit().
1379:    */
1380:   private void readObject(ObjectInputStream ois)
1381:     throws IOException, ClassNotFoundException
1382:   {
1383:     ois.defaultReadObject();
1384: 
1385:     HashMap attrs = new HashMap();
1386:     ClasspathFontPeer.copyStyleToAttrs(style, attrs);
1387:     ClasspathFontPeer.copySizeToAttrs(size, attrs);
1388:     peer = getPeerFromToolkit(name, attrs);
1389: 
1390:   }
1391: }