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