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