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