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