1 /* 2 * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.awt; 27 28 import java.awt.font.FontRenderContext; 29 import java.awt.font.GlyphVector; 30 import java.awt.font.LineMetrics; 31 import java.awt.font.TextAttribute; 32 import java.awt.font.TextLayout; 33 import java.awt.geom.AffineTransform; 34 import java.awt.geom.Point2D; 35 import java.awt.geom.Rectangle2D; 36 import java.awt.peer.FontPeer; 37 import java.io.*; 38 import java.lang.ref.SoftReference; 39 import java.nio.file.Files; 40 import java.security.AccessController; 41 import java.security.PrivilegedExceptionAction; 42 import java.text.AttributedCharacterIterator.Attribute; 43 import java.text.CharacterIterator; 44 import java.util.Hashtable; 45 import java.util.Locale; 46 import java.util.Map; 47 import sun.font.StandardGlyphVector; 48 49 import sun.font.AttributeMap; 50 import sun.font.AttributeValues; 51 import sun.font.CompositeFont; 52 import sun.font.CreatedFontTracker; 53 import sun.font.Font2D; 54 import sun.font.Font2DHandle; 55 import sun.font.FontAccess; 56 import sun.font.FontManager; 57 import sun.font.FontManagerFactory; 58 import sun.font.FontUtilities; 59 import sun.font.GlyphLayout; 60 import sun.font.FontLineMetrics; 61 import sun.font.CoreMetrics; 62 63 import static sun.font.EAttribute.*; 64 65 /** 66 * The <code>Font</code> class represents fonts, which are used to 67 * render text in a visible way. 68 * A font provides the information needed to map sequences of 69 * <em>characters</em> to sequences of <em>glyphs</em> 70 * and to render sequences of glyphs on <code>Graphics</code> and 71 * <code>Component</code> objects. 72 * 73 * <h3>Characters and Glyphs</h3> 74 * 75 * A <em>character</em> is a symbol that represents an item such as a letter, 76 * a digit, or punctuation in an abstract way. For example, <code>'g'</code>, 77 * LATIN SMALL LETTER G, is a character. 78 * <p> 79 * A <em>glyph</em> is a shape used to render a character or a sequence of 80 * characters. In simple writing systems, such as Latin, typically one glyph 81 * represents one character. In general, however, characters and glyphs do not 82 * have one-to-one correspondence. For example, the character 'á' 83 * LATIN SMALL LETTER A WITH ACUTE, can be represented by 84 * two glyphs: one for 'a' and one for '´'. On the other hand, the 85 * two-character string "fi" can be represented by a single glyph, an 86 * "fi" ligature. In complex writing systems, such as Arabic or the South 87 * and South-East Asian writing systems, the relationship between characters 88 * and glyphs can be more complicated and involve context-dependent selection 89 * of glyphs as well as glyph reordering. 90 * 91 * A font encapsulates the collection of glyphs needed to render a selected set 92 * of characters as well as the tables needed to map sequences of characters to 93 * corresponding sequences of glyphs. 94 * 95 * <h3>Physical and Logical Fonts</h3> 96 * 97 * The Java Platform distinguishes between two kinds of fonts: 98 * <em>physical</em> fonts and <em>logical</em> fonts. 99 * <p> 100 * <em>Physical</em> fonts are the actual font libraries containing glyph data 101 * and tables to map from character sequences to glyph sequences, using a font 102 * technology such as TrueType or PostScript Type 1. 103 * All implementations of the Java Platform must support TrueType fonts; 104 * support for other font technologies is implementation dependent. 105 * Physical fonts may use names such as Helvetica, Palatino, HonMincho, or 106 * any number of other font names. 107 * Typically, each physical font supports only a limited set of writing 108 * systems, for example, only Latin characters or only Japanese and Basic 109 * Latin. 110 * The set of available physical fonts varies between configurations. 111 * Applications that require specific fonts can bundle them and instantiate 112 * them using the {@link #createFont createFont} method. 113 * <p> 114 * <em>Logical</em> fonts are the five font families defined by the Java 115 * platform which must be supported by any Java runtime environment: 116 * Serif, SansSerif, Monospaced, Dialog, and DialogInput. 117 * These logical fonts are not actual font libraries. Instead, the logical 118 * font names are mapped to physical fonts by the Java runtime environment. 119 * The mapping is implementation and usually locale dependent, so the look 120 * and the metrics provided by them vary. 121 * Typically, each logical font name maps to several physical fonts in order to 122 * cover a large range of characters. 123 * <p> 124 * Peered AWT components, such as {@link Label Label} and 125 * {@link TextField TextField}, can only use logical fonts. 126 * <p> 127 * For a discussion of the relative advantages and disadvantages of using 128 * physical or logical fonts, see the 129 * <a href="http://www.oracle.com/technetwork/java/javase/tech/faq-jsp-138165.html">Internationalization FAQ</a> 130 * document. 131 * 132 * <h3>Font Faces and Names</h3> 133 * 134 * A <code>Font</code> 135 * can have many faces, such as heavy, medium, oblique, gothic and 136 * regular. All of these faces have similar typographic design. 137 * <p> 138 * There are three different names that you can get from a 139 * <code>Font</code> object. The <em>logical font name</em> is simply the 140 * name that was used to construct the font. 141 * The <em>font face name</em>, or just <em>font name</em> for 142 * short, is the name of a particular font face, like Helvetica Bold. The 143 * <em>family name</em> is the name of the font family that determines the 144 * typographic design across several faces, like Helvetica. 145 * <p> 146 * The <code>Font</code> class represents an instance of a font face from 147 * a collection of font faces that are present in the system resources 148 * of the host system. As examples, Arial Bold and Courier Bold Italic 149 * are font faces. There can be several <code>Font</code> objects 150 * associated with a font face, each differing in size, style, transform 151 * and font features. 152 * <p> 153 * The {@link GraphicsEnvironment#getAllFonts() getAllFonts} method 154 * of the <code>GraphicsEnvironment</code> class returns an 155 * array of all font faces available in the system. These font faces are 156 * returned as <code>Font</code> objects with a size of 1, identity 157 * transform and default font features. These 158 * base fonts can then be used to derive new <code>Font</code> objects 159 * with varying sizes, styles, transforms and font features via the 160 * <code>deriveFont</code> methods in this class. 161 * 162 * <h3>Font and TextAttribute</h3> 163 * 164 * <p><code>Font</code> supports most 165 * <code>TextAttribute</code>s. This makes some operations, such as 166 * rendering underlined text, convenient since it is not 167 * necessary to explicitly construct a <code>TextLayout</code> object. 168 * Attributes can be set on a Font by constructing or deriving it 169 * using a <code>Map</code> of <code>TextAttribute</code> values. 170 * 171 * <p>The values of some <code>TextAttributes</code> are not 172 * serializable, and therefore attempting to serialize an instance of 173 * <code>Font</code> that has such values will not serialize them. 174 * This means a Font deserialized from such a stream will not compare 175 * equal to the original Font that contained the non-serializable 176 * attributes. This should very rarely pose a problem 177 * since these attributes are typically used only in special 178 * circumstances and are unlikely to be serialized. 179 * 180 * <ul> 181 * <li><code>FOREGROUND</code> and <code>BACKGROUND</code> use 182 * <code>Paint</code> values. The subclass <code>Color</code> is 183 * serializable, while <code>GradientPaint</code> and 184 * <code>TexturePaint</code> are not.</li> 185 * <li><code>CHAR_REPLACEMENT</code> uses 186 * <code>GraphicAttribute</code> values. The subclasses 187 * <code>ShapeGraphicAttribute</code> and 188 * <code>ImageGraphicAttribute</code> are not serializable.</li> 189 * <li><code>INPUT_METHOD_HIGHLIGHT</code> uses 190 * <code>InputMethodHighlight</code> values, which are 191 * not serializable. See {@link java.awt.im.InputMethodHighlight}.</li> 192 * </ul> 193 * 194 * <p>Clients who create custom subclasses of <code>Paint</code> and 195 * <code>GraphicAttribute</code> can make them serializable and 196 * avoid this problem. Clients who use input method highlights can 197 * convert these to the platform-specific attributes for that 198 * highlight on the current platform and set them on the Font as 199 * a workaround. 200 * 201 * <p>The <code>Map</code>-based constructor and 202 * <code>deriveFont</code> APIs ignore the FONT attribute, and it is 203 * not retained by the Font; the static {@link #getFont} method should 204 * be used if the FONT attribute might be present. See {@link 205 * java.awt.font.TextAttribute#FONT} for more information.</p> 206 * 207 * <p>Several attributes will cause additional rendering overhead 208 * and potentially invoke layout. If a <code>Font</code> has such 209 * attributes, the <code>{@link #hasLayoutAttributes()}</code> method 210 * will return true.</p> 211 * 212 * <p>Note: Font rotations can cause text baselines to be rotated. In 213 * order to account for this (rare) possibility, font APIs are 214 * specified to return metrics and take parameters 'in 215 * baseline-relative coordinates'. This maps the 'x' coordinate to 216 * the advance along the baseline, (positive x is forward along the 217 * baseline), and the 'y' coordinate to a distance along the 218 * perpendicular to the baseline at 'x' (positive y is 90 degrees 219 * clockwise from the baseline vector). APIs for which this is 220 * especially important are called out as having 'baseline-relative 221 * coordinates.' 222 */ 223 public class Font implements java.io.Serializable 224 { 225 private static class FontAccessImpl extends FontAccess { 226 public Font2D getFont2D(Font font) { 227 return font.getFont2D(); 228 } 229 230 public void setFont2D(Font font, Font2DHandle handle) { 231 font.font2DHandle = handle; 232 } 233 234 public void setCreatedFont(Font font) { 235 font.createdFont = true; 236 } 237 238 public boolean isCreatedFont(Font font) { 239 return font.createdFont; 240 } 241 242 @Override 243 public FontPeer getFontPeer(final Font font) { 244 return font.getFontPeer(); 245 } 246 } 247 248 static { 249 /* ensure that the necessary native libraries are loaded */ 250 Toolkit.loadLibraries(); 251 initIDs(); 252 FontAccess.setFontAccess(new FontAccessImpl()); 253 } 254 255 /** 256 * This is now only used during serialization. Typically 257 * it is null. 258 * 259 * @serial 260 * @see #getAttributes() 261 */ 262 private Hashtable<Object, Object> fRequestedAttributes; 263 264 /* 265 * Constants to be used for logical font family names. 266 */ 267 268 /** 269 * A String constant for the canonical family name of the 270 * logical font "Dialog". It is useful in Font construction 271 * to provide compile-time verification of the name. 272 * @since 1.6 273 */ 274 public static final String DIALOG = "Dialog"; 275 276 /** 277 * A String constant for the canonical family name of the 278 * logical font "DialogInput". It is useful in Font construction 279 * to provide compile-time verification of the name. 280 * @since 1.6 281 */ 282 public static final String DIALOG_INPUT = "DialogInput"; 283 284 /** 285 * A String constant for the canonical family name of the 286 * logical font "SansSerif". It is useful in Font construction 287 * to provide compile-time verification of the name. 288 * @since 1.6 289 */ 290 public static final String SANS_SERIF = "SansSerif"; 291 292 /** 293 * A String constant for the canonical family name of the 294 * logical font "Serif". It is useful in Font construction 295 * to provide compile-time verification of the name. 296 * @since 1.6 297 */ 298 public static final String SERIF = "Serif"; 299 300 /** 301 * A String constant for the canonical family name of the 302 * logical font "Monospaced". It is useful in Font construction 303 * to provide compile-time verification of the name. 304 * @since 1.6 305 */ 306 public static final String MONOSPACED = "Monospaced"; 307 308 /* 309 * Constants to be used for styles. Can be combined to mix 310 * styles. 311 */ 312 313 /** 314 * The plain style constant. 315 */ 316 public static final int PLAIN = 0; 317 318 /** 319 * The bold style constant. This can be combined with the other style 320 * constants (except PLAIN) for mixed styles. 321 */ 322 public static final int BOLD = 1; 323 324 /** 325 * The italicized style constant. This can be combined with the other 326 * style constants (except PLAIN) for mixed styles. 327 */ 328 public static final int ITALIC = 2; 329 330 /** 331 * The baseline used in most Roman scripts when laying out text. 332 */ 333 public static final int ROMAN_BASELINE = 0; 334 335 /** 336 * The baseline used in ideographic scripts like Chinese, Japanese, 337 * and Korean when laying out text. 338 */ 339 public static final int CENTER_BASELINE = 1; 340 341 /** 342 * The baseline used in Devanagari and similar scripts when laying 343 * out text. 344 */ 345 public static final int HANGING_BASELINE = 2; 346 347 /** 348 * Identify a font resource of type TRUETYPE. 349 * Used to specify a TrueType font resource to the 350 * {@link #createFont} method. 351 * The TrueType format was extended to become the OpenType 352 * format, which adds support for fonts with Postscript outlines, 353 * this tag therefore references these fonts, as well as those 354 * with TrueType outlines. 355 * @since 1.3 356 */ 357 358 public static final int TRUETYPE_FONT = 0; 359 360 /** 361 * Identify a font resource of type TYPE1. 362 * Used to specify a Type1 font resource to the 363 * {@link #createFont} method. 364 * @since 1.5 365 */ 366 public static final int TYPE1_FONT = 1; 367 368 /** 369 * The logical name of this <code>Font</code>, as passed to the 370 * constructor. 371 * @since 1.0 372 * 373 * @serial 374 * @see #getName 375 */ 376 protected String name; 377 378 /** 379 * The style of this <code>Font</code>, as passed to the constructor. 380 * This style can be PLAIN, BOLD, ITALIC, or BOLD+ITALIC. 381 * @since 1.0 382 * 383 * @serial 384 * @see #getStyle() 385 */ 386 protected int style; 387 388 /** 389 * The point size of this <code>Font</code>, rounded to integer. 390 * @since 1.0 391 * 392 * @serial 393 * @see #getSize() 394 */ 395 protected int size; 396 397 /** 398 * The point size of this <code>Font</code> in <code>float</code>. 399 * 400 * @serial 401 * @see #getSize() 402 * @see #getSize2D() 403 */ 404 protected float pointSize; 405 406 /** 407 * The platform specific font information. 408 */ 409 private transient FontPeer peer; 410 private transient long pData; // native JDK1.1 font pointer 411 private transient Font2DHandle font2DHandle; 412 413 private transient AttributeValues values; 414 private transient boolean hasLayoutAttributes; 415 416 /* 417 * If the origin of a Font is a created font then this attribute 418 * must be set on all derived fonts too. 419 */ 420 private transient boolean createdFont = false; 421 422 /* 423 * This is true if the font transform is not identity. It 424 * is used to avoid unnecessary instantiation of an AffineTransform. 425 */ 426 private transient boolean nonIdentityTx; 427 428 /* 429 * A cached value used when a transform is required for internal 430 * use. This must not be exposed to callers since AffineTransform 431 * is mutable. 432 */ 433 private static final AffineTransform identityTx = new AffineTransform(); 434 435 /* 436 * JDK 1.1 serialVersionUID 437 */ 438 private static final long serialVersionUID = -4206021311591459213L; 439 440 /** 441 * Gets the peer of this {@code Font}. 442 * 443 * @return the peer of the {@code Font}. 444 */ 445 @SuppressWarnings("deprecation") 446 private FontPeer getFontPeer() { 447 if(peer == null) { 448 Toolkit tk = Toolkit.getDefaultToolkit(); 449 peer = tk.getFontPeer(name, style); 450 } 451 return peer; 452 } 453 454 /** 455 * Return the AttributeValues object associated with this 456 * font. Most of the time, the internal object is null. 457 * If required, it will be created from the 'standard' 458 * state on the font. Only non-default values will be 459 * set in the AttributeValues object. 460 * 461 * <p>Since the AttributeValues object is mutable, and it 462 * is cached in the font, care must be taken to ensure that 463 * it is not mutated. 464 */ 465 private AttributeValues getAttributeValues() { 466 if (values == null) { 467 AttributeValues valuesTmp = new AttributeValues(); 468 valuesTmp.setFamily(name); 469 valuesTmp.setSize(pointSize); // expects the float value. 470 471 if ((style & BOLD) != 0) { 472 valuesTmp.setWeight(2); // WEIGHT_BOLD 473 } 474 475 if ((style & ITALIC) != 0) { 476 valuesTmp.setPosture(.2f); // POSTURE_OBLIQUE 477 } 478 valuesTmp.defineAll(PRIMARY_MASK); // for streaming compatibility 479 values = valuesTmp; 480 } 481 482 return values; 483 } 484 485 private Font2D getFont2D() { 486 FontManager fm = FontManagerFactory.getInstance(); 487 if (fm.usingPerAppContextComposites() && 488 font2DHandle != null && 489 font2DHandle.font2D instanceof CompositeFont && 490 ((CompositeFont)(font2DHandle.font2D)).isStdComposite()) { 491 return fm.findFont2D(name, style, 492 FontManager.LOGICAL_FALLBACK); 493 } else if (font2DHandle == null) { 494 font2DHandle = 495 fm.findFont2D(name, style, 496 FontManager.LOGICAL_FALLBACK).handle; 497 } 498 /* Do not cache the de-referenced font2D. It must be explicitly 499 * de-referenced to pick up a valid font in the event that the 500 * original one is marked invalid 501 */ 502 return font2DHandle.font2D; 503 } 504 505 /** 506 * Creates a new <code>Font</code> from the specified name, style and 507 * point size. 508 * <p> 509 * The font name can be a font face name or a font family name. 510 * It is used together with the style to find an appropriate font face. 511 * When a font family name is specified, the style argument is used to 512 * select the most appropriate face from the family. When a font face 513 * name is specified, the face's style and the style argument are 514 * merged to locate the best matching font from the same family. 515 * For example if face name "Arial Bold" is specified with style 516 * <code>Font.ITALIC</code>, the font system looks for a face in the 517 * "Arial" family that is bold and italic, and may associate the font 518 * instance with the physical font face "Arial Bold Italic". 519 * The style argument is merged with the specified face's style, not 520 * added or subtracted. 521 * This means, specifying a bold face and a bold style does not 522 * double-embolden the font, and specifying a bold face and a plain 523 * style does not lighten the font. 524 * <p> 525 * If no face for the requested style can be found, the font system 526 * may apply algorithmic styling to achieve the desired style. 527 * For example, if <code>ITALIC</code> is requested, but no italic 528 * face is available, glyphs from the plain face may be algorithmically 529 * obliqued (slanted). 530 * <p> 531 * Font name lookup is case insensitive, using the case folding 532 * rules of the US locale. 533 * <p> 534 * If the <code>name</code> parameter represents something other than a 535 * logical font, i.e. is interpreted as a physical font face or family, and 536 * this cannot be mapped by the implementation to a physical font or a 537 * compatible alternative, then the font system will map the Font 538 * instance to "Dialog", such that for example, the family as reported 539 * by {@link #getFamily() getFamily} will be "Dialog". 540 * 541 * @param name the font name. This can be a font face name or a font 542 * family name, and may represent either a logical font or a physical 543 * font found in this {@code GraphicsEnvironment}. 544 * The family names for logical fonts are: Dialog, DialogInput, 545 * Monospaced, Serif, or SansSerif. Pre-defined String constants exist 546 * for all of these names, for example, {@code DIALOG}. If {@code name} is 547 * {@code null}, the <em>logical font name</em> of the new 548 * {@code Font} as returned by {@code getName()} is set to 549 * the name "Default". 550 * @param style the style constant for the {@code Font} 551 * The style argument is an integer bitmask that may 552 * be {@code PLAIN}, or a bitwise union of {@code BOLD} and/or 553 * {@code ITALIC} (for example, {@code ITALIC} or {@code BOLD|ITALIC}). 554 * If the style argument does not conform to one of the expected 555 * integer bitmasks then the style is set to {@code PLAIN}. 556 * @param size the point size of the {@code Font} 557 * @see GraphicsEnvironment#getAllFonts 558 * @see GraphicsEnvironment#getAvailableFontFamilyNames 559 * @since 1.0 560 */ 561 public Font(String name, int style, int size) { 562 this.name = (name != null) ? name : "Default"; 563 this.style = (style & ~0x03) == 0 ? style : 0; 564 this.size = size; 565 this.pointSize = size; 566 } 567 568 private Font(String name, int style, float sizePts) { 569 this.name = (name != null) ? name : "Default"; 570 this.style = (style & ~0x03) == 0 ? style : 0; 571 this.size = (int)(sizePts + 0.5); 572 this.pointSize = sizePts; 573 } 574 575 /* This constructor is used by deriveFont when attributes is null */ 576 private Font(String name, int style, float sizePts, 577 boolean created, Font2DHandle handle) { 578 this(name, style, sizePts); 579 this.createdFont = created; 580 /* Fonts created from a stream will use the same font2D instance 581 * as the parent. 582 * One exception is that if the derived font is requested to be 583 * in a different style, then also check if its a CompositeFont 584 * and if so build a new CompositeFont from components of that style. 585 * CompositeFonts can only be marked as "created" if they are used 586 * to add fall backs to a physical font. And non-composites are 587 * always from "Font.createFont()" and shouldn't get this treatment. 588 */ 589 if (created) { 590 if (handle.font2D instanceof CompositeFont && 591 handle.font2D.getStyle() != style) { 592 FontManager fm = FontManagerFactory.getInstance(); 593 this.font2DHandle = fm.getNewComposite(null, style, handle); 594 } else { 595 this.font2DHandle = handle; 596 } 597 } 598 } 599 600 /* used to implement Font.createFont */ 601 private Font(File fontFile, int fontFormat, 602 boolean isCopy, CreatedFontTracker tracker) 603 throws FontFormatException { 604 this.createdFont = true; 605 /* Font2D instances created by this method track their font file 606 * so that when the Font2D is GC'd it can also remove the file. 607 */ 608 FontManager fm = FontManagerFactory.getInstance(); 609 this.font2DHandle = fm.createFont2D(fontFile, fontFormat, isCopy, 610 tracker).handle; 611 this.name = this.font2DHandle.font2D.getFontName(Locale.getDefault()); 612 this.style = Font.PLAIN; 613 this.size = 1; 614 this.pointSize = 1f; 615 } 616 617 /* This constructor is used when one font is derived from another. 618 * Fonts created from a stream will use the same font2D instance as the 619 * parent. They can be distinguished because the "created" argument 620 * will be "true". Since there is no way to recreate these fonts they 621 * need to have the handle to the underlying font2D passed in. 622 * "created" is also true when a special composite is referenced by the 623 * handle for essentially the same reasons. 624 * But when deriving a font in these cases two particular attributes 625 * need special attention: family/face and style. 626 * The "composites" in these cases need to be recreated with optimal 627 * fonts for the new values of family and style. 628 * For fonts created with createFont() these are treated differently. 629 * JDK can often synthesise a different style (bold from plain 630 * for example). For fonts created with "createFont" this is a reasonable 631 * solution but its also possible (although rare) to derive a font with a 632 * different family attribute. In this case JDK needs 633 * to break the tie with the original Font2D and find a new Font. 634 * The oldName and oldStyle are supplied so they can be compared with 635 * what the Font2D and the values. To speed things along : 636 * oldName == null will be interpreted as the name is unchanged. 637 * oldStyle = -1 will be interpreted as the style is unchanged. 638 * In these cases there is no need to interrogate "values". 639 */ 640 private Font(AttributeValues values, String oldName, int oldStyle, 641 boolean created, Font2DHandle handle) { 642 643 this.createdFont = created; 644 if (created) { 645 this.font2DHandle = handle; 646 647 String newName = null; 648 if (oldName != null) { 649 newName = values.getFamily(); 650 if (oldName.equals(newName)) newName = null; 651 } 652 int newStyle = 0; 653 if (oldStyle == -1) { 654 newStyle = -1; 655 } else { 656 if (values.getWeight() >= 2f) newStyle = BOLD; 657 if (values.getPosture() >= .2f) newStyle |= ITALIC; 658 if (oldStyle == newStyle) newStyle = -1; 659 } 660 if (handle.font2D instanceof CompositeFont) { 661 if (newStyle != -1 || newName != null) { 662 FontManager fm = FontManagerFactory.getInstance(); 663 this.font2DHandle = 664 fm.getNewComposite(newName, newStyle, handle); 665 } 666 } else if (newName != null) { 667 this.createdFont = false; 668 this.font2DHandle = null; 669 } 670 } 671 initFromValues(values); 672 } 673 674 /** 675 * Creates a new <code>Font</code> with the specified attributes. 676 * Only keys defined in {@link java.awt.font.TextAttribute TextAttribute} 677 * are recognized. In addition the FONT attribute is 678 * not recognized by this constructor 679 * (see {@link #getAvailableAttributes}). Only attributes that have 680 * values of valid types will affect the new <code>Font</code>. 681 * <p> 682 * If <code>attributes</code> is <code>null</code>, a new 683 * <code>Font</code> is initialized with default values. 684 * @see java.awt.font.TextAttribute 685 * @param attributes the attributes to assign to the new 686 * <code>Font</code>, or <code>null</code> 687 */ 688 public Font(Map<? extends Attribute, ?> attributes) { 689 initFromValues(AttributeValues.fromMap(attributes, RECOGNIZED_MASK)); 690 } 691 692 /** 693 * Creates a new <code>Font</code> from the specified <code>font</code>. 694 * This constructor is intended for use by subclasses. 695 * @param font from which to create this <code>Font</code>. 696 * @throws NullPointerException if <code>font</code> is null 697 * @since 1.6 698 */ 699 protected Font(Font font) { 700 if (font.values != null) { 701 initFromValues(font.getAttributeValues().clone()); 702 } else { 703 this.name = font.name; 704 this.style = font.style; 705 this.size = font.size; 706 this.pointSize = font.pointSize; 707 } 708 this.font2DHandle = font.font2DHandle; 709 this.createdFont = font.createdFont; 710 } 711 712 /** 713 * Font recognizes all attributes except FONT. 714 */ 715 private static final int RECOGNIZED_MASK = AttributeValues.MASK_ALL 716 & ~AttributeValues.getMask(EFONT); 717 718 /** 719 * These attributes are considered primary by the FONT attribute. 720 */ 721 private static final int PRIMARY_MASK = 722 AttributeValues.getMask(EFAMILY, EWEIGHT, EWIDTH, EPOSTURE, ESIZE, 723 ETRANSFORM, ESUPERSCRIPT, ETRACKING); 724 725 /** 726 * These attributes are considered secondary by the FONT attribute. 727 */ 728 private static final int SECONDARY_MASK = 729 RECOGNIZED_MASK & ~PRIMARY_MASK; 730 731 /** 732 * These attributes are handled by layout. 733 */ 734 private static final int LAYOUT_MASK = 735 AttributeValues.getMask(ECHAR_REPLACEMENT, EFOREGROUND, EBACKGROUND, 736 EUNDERLINE, ESTRIKETHROUGH, ERUN_DIRECTION, 737 EBIDI_EMBEDDING, EJUSTIFICATION, 738 EINPUT_METHOD_HIGHLIGHT, EINPUT_METHOD_UNDERLINE, 739 ESWAP_COLORS, ENUMERIC_SHAPING, EKERNING, 740 ELIGATURES, ETRACKING, ESUPERSCRIPT); 741 742 private static final int EXTRA_MASK = 743 AttributeValues.getMask(ETRANSFORM, ESUPERSCRIPT, EWIDTH); 744 745 /** 746 * Initialize the standard Font fields from the values object. 747 */ 748 private void initFromValues(AttributeValues values) { 749 this.values = values; 750 values.defineAll(PRIMARY_MASK); // for 1.5 streaming compatibility 751 752 this.name = values.getFamily(); 753 this.pointSize = values.getSize(); 754 this.size = (int)(values.getSize() + 0.5); 755 if (values.getWeight() >= 2f) this.style |= BOLD; // not == 2f 756 if (values.getPosture() >= .2f) this.style |= ITALIC; // not == .2f 757 758 this.nonIdentityTx = values.anyNonDefault(EXTRA_MASK); 759 this.hasLayoutAttributes = values.anyNonDefault(LAYOUT_MASK); 760 } 761 762 /** 763 * Returns a <code>Font</code> appropriate to the attributes. 764 * If <code>attributes</code>contains a <code>FONT</code> attribute 765 * with a valid <code>Font</code> as its value, it will be 766 * merged with any remaining attributes. See 767 * {@link java.awt.font.TextAttribute#FONT} for more 768 * information. 769 * 770 * @param attributes the attributes to assign to the new 771 * <code>Font</code> 772 * @return a new <code>Font</code> created with the specified 773 * attributes 774 * @throws NullPointerException if <code>attributes</code> is null. 775 * @since 1.2 776 * @see java.awt.font.TextAttribute 777 */ 778 public static Font getFont(Map<? extends Attribute, ?> attributes) { 779 // optimize for two cases: 780 // 1) FONT attribute, and nothing else 781 // 2) attributes, but no FONT 782 783 // avoid turning the attributemap into a regular map for no reason 784 if (attributes instanceof AttributeMap && 785 ((AttributeMap)attributes).getValues() != null) { 786 AttributeValues values = ((AttributeMap)attributes).getValues(); 787 if (values.isNonDefault(EFONT)) { 788 Font font = values.getFont(); 789 if (!values.anyDefined(SECONDARY_MASK)) { 790 return font; 791 } 792 // merge 793 values = font.getAttributeValues().clone(); 794 values.merge(attributes, SECONDARY_MASK); 795 return new Font(values, font.name, font.style, 796 font.createdFont, font.font2DHandle); 797 } 798 return new Font(attributes); 799 } 800 801 Font font = (Font)attributes.get(TextAttribute.FONT); 802 if (font != null) { 803 if (attributes.size() > 1) { // oh well, check for anything else 804 AttributeValues values = font.getAttributeValues().clone(); 805 values.merge(attributes, SECONDARY_MASK); 806 return new Font(values, font.name, font.style, 807 font.createdFont, font.font2DHandle); 808 } 809 810 return font; 811 } 812 813 return new Font(attributes); 814 } 815 816 /** 817 * Used with the byte count tracker for fonts created from streams. 818 * If a thread can create temp files anyway, no point in counting 819 * font bytes. 820 */ 821 private static boolean hasTempPermission() { 822 823 if (System.getSecurityManager() == null) { 824 return true; 825 } 826 File f = null; 827 boolean hasPerm = false; 828 try { 829 f = Files.createTempFile("+~JT", ".tmp").toFile(); 830 f.delete(); 831 f = null; 832 hasPerm = true; 833 } catch (Throwable t) { 834 /* inc. any kind of SecurityException */ 835 } 836 return hasPerm; 837 } 838 839 /** 840 * Returns a new <code>Font</code> using the specified font type 841 * and input data. The new <code>Font</code> is 842 * created with a point size of 1 and style {@link #PLAIN PLAIN}. 843 * This base font can then be used with the <code>deriveFont</code> 844 * methods in this class to derive new <code>Font</code> objects with 845 * varying sizes, styles, transforms and font features. This 846 * method does not close the {@link InputStream}. 847 * <p> 848 * To make the <code>Font</code> available to Font constructors the 849 * returned <code>Font</code> must be registered in the 850 * <code>GraphicsEnvironment</code> by calling 851 * {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}. 852 * @param fontFormat the type of the <code>Font</code>, which is 853 * {@link #TRUETYPE_FONT TRUETYPE_FONT} if a TrueType resource is specified. 854 * or {@link #TYPE1_FONT TYPE1_FONT} if a Type 1 resource is specified. 855 * @param fontStream an <code>InputStream</code> object representing the 856 * input data for the font. 857 * @return a new <code>Font</code> created with the specified font type. 858 * @throws IllegalArgumentException if <code>fontFormat</code> is not 859 * <code>TRUETYPE_FONT</code>or<code>TYPE1_FONT</code>. 860 * @throws FontFormatException if the <code>fontStream</code> data does 861 * not contain the required font tables for the specified format. 862 * @throws IOException if the <code>fontStream</code> 863 * cannot be completely read. 864 * @see GraphicsEnvironment#registerFont(Font) 865 * @since 1.3 866 */ 867 public static Font createFont(int fontFormat, InputStream fontStream) 868 throws java.awt.FontFormatException, java.io.IOException { 869 870 if (hasTempPermission()) { 871 return createFont0(fontFormat, fontStream, null); 872 } 873 874 // Otherwise, be extra conscious of pending temp file creation and 875 // resourcefully handle the temp file resources, among other things. 876 CreatedFontTracker tracker = CreatedFontTracker.getTracker(); 877 boolean acquired = false; 878 try { 879 acquired = tracker.acquirePermit(); 880 if (!acquired) { 881 throw new IOException("Timed out waiting for resources."); 882 } 883 return createFont0(fontFormat, fontStream, tracker); 884 } catch (InterruptedException e) { 885 throw new IOException("Problem reading font data."); 886 } finally { 887 if (acquired) { 888 tracker.releasePermit(); 889 } 890 } 891 } 892 893 private static Font createFont0(int fontFormat, InputStream fontStream, 894 CreatedFontTracker tracker) 895 throws java.awt.FontFormatException, java.io.IOException { 896 897 if (fontFormat != Font.TRUETYPE_FONT && 898 fontFormat != Font.TYPE1_FONT) { 899 throw new IllegalArgumentException ("font format not recognized"); 900 } 901 boolean copiedFontData = false; 902 try { 903 final File tFile = AccessController.doPrivileged( 904 new PrivilegedExceptionAction<File>() { 905 public File run() throws IOException { 906 return Files.createTempFile("+~JF", ".tmp").toFile(); 907 } 908 } 909 ); 910 if (tracker != null) { 911 tracker.add(tFile); 912 } 913 914 int totalSize = 0; 915 try { 916 final OutputStream outStream = 917 AccessController.doPrivileged( 918 new PrivilegedExceptionAction<OutputStream>() { 919 public OutputStream run() throws IOException { 920 return new FileOutputStream(tFile); 921 } 922 } 923 ); 924 if (tracker != null) { 925 tracker.set(tFile, outStream); 926 } 927 try { 928 byte[] buf = new byte[8192]; 929 for (;;) { 930 int bytesRead = fontStream.read(buf); 931 if (bytesRead < 0) { 932 break; 933 } 934 if (tracker != null) { 935 if (totalSize+bytesRead > CreatedFontTracker.MAX_FILE_SIZE) { 936 throw new IOException("File too big."); 937 } 938 if (totalSize+tracker.getNumBytes() > 939 CreatedFontTracker.MAX_TOTAL_BYTES) 940 { 941 throw new IOException("Total files too big."); 942 } 943 totalSize += bytesRead; 944 tracker.addBytes(bytesRead); 945 } 946 outStream.write(buf, 0, bytesRead); 947 } 948 /* don't close the input stream */ 949 } finally { 950 outStream.close(); 951 } 952 /* After all references to a Font2D are dropped, the file 953 * will be removed. To support long-lived AppContexts, 954 * we need to then decrement the byte count by the size 955 * of the file. 956 * If the data isn't a valid font, the implementation will 957 * delete the tmp file and decrement the byte count 958 * in the tracker object before returning from the 959 * constructor, so we can set 'copiedFontData' to true here 960 * without waiting for the results of that constructor. 961 */ 962 copiedFontData = true; 963 Font font = new Font(tFile, fontFormat, true, tracker); 964 return font; 965 } finally { 966 if (tracker != null) { 967 tracker.remove(tFile); 968 } 969 if (!copiedFontData) { 970 if (tracker != null) { 971 tracker.subBytes(totalSize); 972 } 973 AccessController.doPrivileged( 974 new PrivilegedExceptionAction<Void>() { 975 public Void run() { 976 tFile.delete(); 977 return null; 978 } 979 } 980 ); 981 } 982 } 983 } catch (Throwable t) { 984 if (t instanceof FontFormatException) { 985 throw (FontFormatException)t; 986 } 987 if (t instanceof IOException) { 988 throw (IOException)t; 989 } 990 Throwable cause = t.getCause(); 991 if (cause instanceof FontFormatException) { 992 throw (FontFormatException)cause; 993 } 994 throw new IOException("Problem reading font data."); 995 } 996 } 997 998 /** 999 * Returns a new <code>Font</code> using the specified font type 1000 * and the specified font file. The new <code>Font</code> is 1001 * created with a point size of 1 and style {@link #PLAIN PLAIN}. 1002 * This base font can then be used with the <code>deriveFont</code> 1003 * methods in this class to derive new <code>Font</code> objects with 1004 * varying sizes, styles, transforms and font features. 1005 * @param fontFormat the type of the <code>Font</code>, which is 1006 * {@link #TRUETYPE_FONT TRUETYPE_FONT} if a TrueType resource is 1007 * specified or {@link #TYPE1_FONT TYPE1_FONT} if a Type 1 resource is 1008 * specified. 1009 * So long as the returned font, or its derived fonts are referenced 1010 * the implementation may continue to access <code>fontFile</code> 1011 * to retrieve font data. Thus the results are undefined if the file 1012 * is changed, or becomes inaccessible. 1013 * <p> 1014 * To make the <code>Font</code> available to Font constructors the 1015 * returned <code>Font</code> must be registered in the 1016 * <code>GraphicsEnvironment</code> by calling 1017 * {@link GraphicsEnvironment#registerFont(Font) registerFont(Font)}. 1018 * @param fontFile a <code>File</code> object representing the 1019 * input data for the font. 1020 * @return a new <code>Font</code> created with the specified font type. 1021 * @throws IllegalArgumentException if <code>fontFormat</code> is not 1022 * <code>TRUETYPE_FONT</code>or<code>TYPE1_FONT</code>. 1023 * @throws NullPointerException if <code>fontFile</code> is null. 1024 * @throws IOException if the <code>fontFile</code> cannot be read. 1025 * @throws FontFormatException if <code>fontFile</code> does 1026 * not contain the required font tables for the specified format. 1027 * @throws SecurityException if the executing code does not have 1028 * permission to read from the file. 1029 * @see GraphicsEnvironment#registerFont(Font) 1030 * @since 1.5 1031 */ 1032 public static Font createFont(int fontFormat, File fontFile) 1033 throws java.awt.FontFormatException, java.io.IOException { 1034 1035 fontFile = new File(fontFile.getPath()); 1036 1037 if (fontFormat != Font.TRUETYPE_FONT && 1038 fontFormat != Font.TYPE1_FONT) { 1039 throw new IllegalArgumentException ("font format not recognized"); 1040 } 1041 SecurityManager sm = System.getSecurityManager(); 1042 if (sm != null) { 1043 FilePermission filePermission = 1044 new FilePermission(fontFile.getPath(), "read"); 1045 sm.checkPermission(filePermission); 1046 } 1047 if (!fontFile.canRead()) { 1048 throw new IOException("Can't read " + fontFile); 1049 } 1050 return new Font(fontFile, fontFormat, false, null); 1051 } 1052 1053 /** 1054 * Returns a copy of the transform associated with this 1055 * <code>Font</code>. This transform is not necessarily the one 1056 * used to construct the font. If the font has algorithmic 1057 * superscripting or width adjustment, this will be incorporated 1058 * into the returned <code>AffineTransform</code>. 1059 * <p> 1060 * Typically, fonts will not be transformed. Clients generally 1061 * should call {@link #isTransformed} first, and only call this 1062 * method if <code>isTransformed</code> returns true. 1063 * 1064 * @return an {@link AffineTransform} object representing the 1065 * transform attribute of this <code>Font</code> object. 1066 */ 1067 public AffineTransform getTransform() { 1068 /* The most common case is the identity transform. Most callers 1069 * should call isTransformed() first, to decide if they need to 1070 * get the transform, but some may not. Here we check to see 1071 * if we have a nonidentity transform, and only do the work to 1072 * fetch and/or compute it if so, otherwise we return a new 1073 * identity transform. 1074 * 1075 * Note that the transform is _not_ necessarily the same as 1076 * the transform passed in as an Attribute in a Map, as the 1077 * transform returned will also reflect the effects of WIDTH and 1078 * SUPERSCRIPT attributes. Clients who want the actual transform 1079 * need to call getRequestedAttributes. 1080 */ 1081 if (nonIdentityTx) { 1082 AttributeValues values = getAttributeValues(); 1083 1084 AffineTransform at = values.isNonDefault(ETRANSFORM) 1085 ? new AffineTransform(values.getTransform()) 1086 : new AffineTransform(); 1087 1088 if (values.getSuperscript() != 0) { 1089 // can't get ascent and descent here, recursive call to this fn, 1090 // so use pointsize 1091 // let users combine super- and sub-scripting 1092 1093 int superscript = values.getSuperscript(); 1094 1095 double trans = 0; 1096 int n = 0; 1097 boolean up = superscript > 0; 1098 int sign = up ? -1 : 1; 1099 int ss = up ? superscript : -superscript; 1100 1101 while ((ss & 7) > n) { 1102 int newn = ss & 7; 1103 trans += sign * (ssinfo[newn] - ssinfo[n]); 1104 ss >>= 3; 1105 sign = -sign; 1106 n = newn; 1107 } 1108 trans *= pointSize; 1109 double scale = Math.pow(2./3., n); 1110 1111 at.preConcatenate(AffineTransform.getTranslateInstance(0, trans)); 1112 at.scale(scale, scale); 1113 1114 // note on placement and italics 1115 // We preconcatenate the transform because we don't want to translate along 1116 // the italic angle, but purely perpendicular to the baseline. While this 1117 // looks ok for superscripts, it can lead subscripts to stack on each other 1118 // and bring the following text too close. The way we deal with potential 1119 // collisions that can occur in the case of italics is by adjusting the 1120 // horizontal spacing of the adjacent glyphvectors. Examine the italic 1121 // angle of both vectors, if one is non-zero, compute the minimum ascent 1122 // and descent, and then the x position at each for each vector along its 1123 // italic angle starting from its (offset) baseline. Compute the difference 1124 // between the x positions and use the maximum difference to adjust the 1125 // position of the right gv. 1126 } 1127 1128 if (values.isNonDefault(EWIDTH)) { 1129 at.scale(values.getWidth(), 1f); 1130 } 1131 1132 return at; 1133 } 1134 1135 return new AffineTransform(); 1136 } 1137 1138 // x = r^0 + r^1 + r^2... r^n 1139 // rx = r^1 + r^2 + r^3... r^(n+1) 1140 // x - rx = r^0 - r^(n+1) 1141 // x (1 - r) = r^0 - r^(n+1) 1142 // x = (r^0 - r^(n+1)) / (1 - r) 1143 // x = (1 - r^(n+1)) / (1 - r) 1144 1145 // scale ratio is 2/3 1146 // trans = 1/2 of ascent * x 1147 // assume ascent is 3/4 of point size 1148 1149 private static final float[] ssinfo = { 1150 0.0f, 1151 0.375f, 1152 0.625f, 1153 0.7916667f, 1154 0.9027778f, 1155 0.9768519f, 1156 1.0262346f, 1157 1.0591564f, 1158 }; 1159 1160 /** 1161 * Returns the family name of this <code>Font</code>. 1162 * 1163 * <p>The family name of a font is font specific. Two fonts such as 1164 * Helvetica Italic and Helvetica Bold have the same family name, 1165 * <i>Helvetica</i>, whereas their font face names are 1166 * <i>Helvetica Bold</i> and <i>Helvetica Italic</i>. The list of 1167 * available family names may be obtained by using the 1168 * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method. 1169 * 1170 * <p>Use <code>getName</code> to get the logical name of the font. 1171 * Use <code>getFontName</code> to get the font face name of the font. 1172 * @return a <code>String</code> that is the family name of this 1173 * <code>Font</code>. 1174 * 1175 * @see #getName 1176 * @see #getFontName 1177 * @since 1.1 1178 */ 1179 public String getFamily() { 1180 return getFamily_NoClientCode(); 1181 } 1182 // NOTE: This method is called by privileged threads. 1183 // We implement this functionality in a package-private 1184 // method to insure that it cannot be overridden by client 1185 // subclasses. 1186 // DO NOT INVOKE CLIENT CODE ON THIS THREAD! 1187 final String getFamily_NoClientCode() { 1188 return getFamily(Locale.getDefault()); 1189 } 1190 1191 /** 1192 * Returns the family name of this <code>Font</code>, localized for 1193 * the specified locale. 1194 * 1195 * <p>The family name of a font is font specific. Two fonts such as 1196 * Helvetica Italic and Helvetica Bold have the same family name, 1197 * <i>Helvetica</i>, whereas their font face names are 1198 * <i>Helvetica Bold</i> and <i>Helvetica Italic</i>. The list of 1199 * available family names may be obtained by using the 1200 * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method. 1201 * 1202 * <p>Use <code>getFontName</code> to get the font face name of the font. 1203 * @param l locale for which to get the family name 1204 * @return a <code>String</code> representing the family name of the 1205 * font, localized for the specified locale. 1206 * @see #getFontName 1207 * @see java.util.Locale 1208 * @since 1.2 1209 */ 1210 public String getFamily(Locale l) { 1211 if (l == null) { 1212 throw new NullPointerException("null locale doesn't mean default"); 1213 } 1214 return getFont2D().getFamilyName(l); 1215 } 1216 1217 /** 1218 * Returns the postscript name of this <code>Font</code>. 1219 * Use <code>getFamily</code> to get the family name of the font. 1220 * Use <code>getFontName</code> to get the font face name of the font. 1221 * @return a <code>String</code> representing the postscript name of 1222 * this <code>Font</code>. 1223 * @since 1.2 1224 */ 1225 public String getPSName() { 1226 return getFont2D().getPostscriptName(); 1227 } 1228 1229 /** 1230 * Returns the logical name of this <code>Font</code>. 1231 * Use <code>getFamily</code> to get the family name of the font. 1232 * Use <code>getFontName</code> to get the font face name of the font. 1233 * @return a <code>String</code> representing the logical name of 1234 * this <code>Font</code>. 1235 * @see #getFamily 1236 * @see #getFontName 1237 * @since 1.0 1238 */ 1239 public String getName() { 1240 return name; 1241 } 1242 1243 /** 1244 * Returns the font face name of this <code>Font</code>. For example, 1245 * Helvetica Bold could be returned as a font face name. 1246 * Use <code>getFamily</code> to get the family name of the font. 1247 * Use <code>getName</code> to get the logical name of the font. 1248 * @return a <code>String</code> representing the font face name of 1249 * this <code>Font</code>. 1250 * @see #getFamily 1251 * @see #getName 1252 * @since 1.2 1253 */ 1254 public String getFontName() { 1255 return getFontName(Locale.getDefault()); 1256 } 1257 1258 /** 1259 * Returns the font face name of the <code>Font</code>, localized 1260 * for the specified locale. For example, Helvetica Fett could be 1261 * returned as the font face name. 1262 * Use <code>getFamily</code> to get the family name of the font. 1263 * @param l a locale for which to get the font face name 1264 * @return a <code>String</code> representing the font face name, 1265 * localized for the specified locale. 1266 * @see #getFamily 1267 * @see java.util.Locale 1268 */ 1269 public String getFontName(Locale l) { 1270 if (l == null) { 1271 throw new NullPointerException("null locale doesn't mean default"); 1272 } 1273 return getFont2D().getFontName(l); 1274 } 1275 1276 /** 1277 * Returns the style of this <code>Font</code>. The style can be 1278 * PLAIN, BOLD, ITALIC, or BOLD+ITALIC. 1279 * @return the style of this <code>Font</code> 1280 * @see #isPlain 1281 * @see #isBold 1282 * @see #isItalic 1283 * @since 1.0 1284 */ 1285 public int getStyle() { 1286 return style; 1287 } 1288 1289 /** 1290 * Returns the point size of this <code>Font</code>, rounded to 1291 * an integer. 1292 * Most users are familiar with the idea of using <i>point size</i> to 1293 * specify the size of glyphs in a font. This point size defines a 1294 * measurement between the baseline of one line to the baseline of the 1295 * following line in a single spaced text document. The point size is 1296 * based on <i>typographic points</i>, approximately 1/72 of an inch. 1297 * <p> 1298 * The Java(tm)2D API adopts the convention that one point is 1299 * equivalent to one unit in user coordinates. When using a 1300 * normalized transform for converting user space coordinates to 1301 * device space coordinates 72 user 1302 * space units equal 1 inch in device space. In this case one point 1303 * is 1/72 of an inch. 1304 * @return the point size of this <code>Font</code> in 1/72 of an 1305 * inch units. 1306 * @see #getSize2D 1307 * @see GraphicsConfiguration#getDefaultTransform 1308 * @see GraphicsConfiguration#getNormalizingTransform 1309 * @since 1.0 1310 */ 1311 public int getSize() { 1312 return size; 1313 } 1314 1315 /** 1316 * Returns the point size of this <code>Font</code> in 1317 * <code>float</code> value. 1318 * @return the point size of this <code>Font</code> as a 1319 * <code>float</code> value. 1320 * @see #getSize 1321 * @since 1.2 1322 */ 1323 public float getSize2D() { 1324 return pointSize; 1325 } 1326 1327 /** 1328 * Indicates whether or not this <code>Font</code> object's style is 1329 * PLAIN. 1330 * @return <code>true</code> if this <code>Font</code> has a 1331 * PLAIN style; 1332 * <code>false</code> otherwise. 1333 * @see java.awt.Font#getStyle 1334 * @since 1.0 1335 */ 1336 public boolean isPlain() { 1337 return style == 0; 1338 } 1339 1340 /** 1341 * Indicates whether or not this <code>Font</code> object's style is 1342 * BOLD. 1343 * @return <code>true</code> if this <code>Font</code> object's 1344 * style is BOLD; 1345 * <code>false</code> otherwise. 1346 * @see java.awt.Font#getStyle 1347 * @since 1.0 1348 */ 1349 public boolean isBold() { 1350 return (style & BOLD) != 0; 1351 } 1352 1353 /** 1354 * Indicates whether or not this <code>Font</code> object's style is 1355 * ITALIC. 1356 * @return <code>true</code> if this <code>Font</code> object's 1357 * style is ITALIC; 1358 * <code>false</code> otherwise. 1359 * @see java.awt.Font#getStyle 1360 * @since 1.0 1361 */ 1362 public boolean isItalic() { 1363 return (style & ITALIC) != 0; 1364 } 1365 1366 /** 1367 * Indicates whether or not this <code>Font</code> object has a 1368 * transform that affects its size in addition to the Size 1369 * attribute. 1370 * @return <code>true</code> if this <code>Font</code> object 1371 * has a non-identity AffineTransform attribute. 1372 * <code>false</code> otherwise. 1373 * @see java.awt.Font#getTransform 1374 * @since 1.4 1375 */ 1376 public boolean isTransformed() { 1377 return nonIdentityTx; 1378 } 1379 1380 /** 1381 * Return true if this Font contains attributes that require extra 1382 * layout processing. 1383 * @return true if the font has layout attributes 1384 * @since 1.6 1385 */ 1386 public boolean hasLayoutAttributes() { 1387 return hasLayoutAttributes; 1388 } 1389 1390 /** 1391 * Returns a <code>Font</code> object from the system properties list. 1392 * <code>nm</code> is treated as the name of a system property to be 1393 * obtained. The <code>String</code> value of this property is then 1394 * interpreted as a <code>Font</code> object according to the 1395 * specification of <code>Font.decode(String)</code> 1396 * If the specified property is not found, or the executing code does 1397 * not have permission to read the property, null is returned instead. 1398 * 1399 * @param nm the property name 1400 * @return a <code>Font</code> object that the property name 1401 * describes, or null if no such property exists. 1402 * @throws NullPointerException if nm is null. 1403 * @since 1.2 1404 * @see #decode(String) 1405 */ 1406 public static Font getFont(String nm) { 1407 return getFont(nm, null); 1408 } 1409 1410 /** 1411 * Returns the <code>Font</code> that the <code>str</code> 1412 * argument describes. 1413 * To ensure that this method returns the desired Font, 1414 * format the <code>str</code> parameter in 1415 * one of these ways 1416 * 1417 * <ul> 1418 * <li><em>fontname-style-pointsize</em> 1419 * <li><em>fontname-pointsize</em> 1420 * <li><em>fontname-style</em> 1421 * <li><em>fontname</em> 1422 * <li><em>fontname style pointsize</em> 1423 * <li><em>fontname pointsize</em> 1424 * <li><em>fontname style</em> 1425 * <li><em>fontname</em> 1426 * </ul> 1427 * in which <i>style</i> is one of the four 1428 * case-insensitive strings: 1429 * <code>"PLAIN"</code>, <code>"BOLD"</code>, <code>"BOLDITALIC"</code>, or 1430 * <code>"ITALIC"</code>, and pointsize is a positive decimal integer 1431 * representation of the point size. 1432 * For example, if you want a font that is Arial, bold, with 1433 * a point size of 18, you would call this method with: 1434 * "Arial-BOLD-18". 1435 * This is equivalent to calling the Font constructor : 1436 * <code>new Font("Arial", Font.BOLD, 18);</code> 1437 * and the values are interpreted as specified by that constructor. 1438 * <p> 1439 * A valid trailing decimal field is always interpreted as the pointsize. 1440 * Therefore a fontname containing a trailing decimal value should not 1441 * be used in the fontname only form. 1442 * <p> 1443 * If a style name field is not one of the valid style strings, it is 1444 * interpreted as part of the font name, and the default style is used. 1445 * <p> 1446 * Only one of ' ' or '-' may be used to separate fields in the input. 1447 * The identified separator is the one closest to the end of the string 1448 * which separates a valid pointsize, or a valid style name from 1449 * the rest of the string. 1450 * Null (empty) pointsize and style fields are treated 1451 * as valid fields with the default value for that field. 1452 *<p> 1453 * Some font names may include the separator characters ' ' or '-'. 1454 * If <code>str</code> is not formed with 3 components, e.g. such that 1455 * <code>style</code> or <code>pointsize</code> fields are not present in 1456 * <code>str</code>, and <code>fontname</code> also contains a 1457 * character determined to be the separator character 1458 * then these characters where they appear as intended to be part of 1459 * <code>fontname</code> may instead be interpreted as separators 1460 * so the font name may not be properly recognised. 1461 * 1462 * <p> 1463 * The default size is 12 and the default style is PLAIN. 1464 * If <code>str</code> does not specify a valid size, the returned 1465 * <code>Font</code> has a size of 12. If <code>str</code> does not 1466 * specify a valid style, the returned Font has a style of PLAIN. 1467 * If you do not specify a valid font name in 1468 * the <code>str</code> argument, this method will return 1469 * a font with the family name "Dialog". 1470 * To determine what font family names are available on 1471 * your system, use the 1472 * {@link GraphicsEnvironment#getAvailableFontFamilyNames()} method. 1473 * If <code>str</code> is <code>null</code>, a new <code>Font</code> 1474 * is returned with the family name "Dialog", a size of 12 and a 1475 * PLAIN style. 1476 * @param str the name of the font, or <code>null</code> 1477 * @return the <code>Font</code> object that <code>str</code> 1478 * describes, or a new default <code>Font</code> if 1479 * <code>str</code> is <code>null</code>. 1480 * @see #getFamily 1481 * @since 1.1 1482 */ 1483 public static Font decode(String str) { 1484 String fontName = str; 1485 String styleName = ""; 1486 int fontSize = 12; 1487 int fontStyle = Font.PLAIN; 1488 1489 if (str == null) { 1490 return new Font(DIALOG, fontStyle, fontSize); 1491 } 1492 1493 int lastHyphen = str.lastIndexOf('-'); 1494 int lastSpace = str.lastIndexOf(' '); 1495 char sepChar = (lastHyphen > lastSpace) ? '-' : ' '; 1496 int sizeIndex = str.lastIndexOf(sepChar); 1497 int styleIndex = str.lastIndexOf(sepChar, sizeIndex-1); 1498 int strlen = str.length(); 1499 1500 if (sizeIndex > 0 && sizeIndex+1 < strlen) { 1501 try { 1502 fontSize = 1503 Integer.valueOf(str.substring(sizeIndex+1)).intValue(); 1504 if (fontSize <= 0) { 1505 fontSize = 12; 1506 } 1507 } catch (NumberFormatException e) { 1508 /* It wasn't a valid size, if we didn't also find the 1509 * start of the style string perhaps this is the style */ 1510 styleIndex = sizeIndex; 1511 sizeIndex = strlen; 1512 if (str.charAt(sizeIndex-1) == sepChar) { 1513 sizeIndex--; 1514 } 1515 } 1516 } 1517 1518 if (styleIndex >= 0 && styleIndex+1 < strlen) { 1519 styleName = str.substring(styleIndex+1, sizeIndex); 1520 styleName = styleName.toLowerCase(Locale.ENGLISH); 1521 if (styleName.equals("bolditalic")) { 1522 fontStyle = Font.BOLD | Font.ITALIC; 1523 } else if (styleName.equals("italic")) { 1524 fontStyle = Font.ITALIC; 1525 } else if (styleName.equals("bold")) { 1526 fontStyle = Font.BOLD; 1527 } else if (styleName.equals("plain")) { 1528 fontStyle = Font.PLAIN; 1529 } else { 1530 /* this string isn't any of the expected styles, so 1531 * assume its part of the font name 1532 */ 1533 styleIndex = sizeIndex; 1534 if (str.charAt(styleIndex-1) == sepChar) { 1535 styleIndex--; 1536 } 1537 } 1538 fontName = str.substring(0, styleIndex); 1539 1540 } else { 1541 int fontEnd = strlen; 1542 if (styleIndex > 0) { 1543 fontEnd = styleIndex; 1544 } else if (sizeIndex > 0) { 1545 fontEnd = sizeIndex; 1546 } 1547 if (fontEnd > 0 && str.charAt(fontEnd-1) == sepChar) { 1548 fontEnd--; 1549 } 1550 fontName = str.substring(0, fontEnd); 1551 } 1552 1553 return new Font(fontName, fontStyle, fontSize); 1554 } 1555 1556 /** 1557 * Gets the specified <code>Font</code> from the system properties 1558 * list. As in the <code>getProperty</code> method of 1559 * <code>System</code>, the first 1560 * argument is treated as the name of a system property to be 1561 * obtained. The <code>String</code> value of this property is then 1562 * interpreted as a <code>Font</code> object. 1563 * <p> 1564 * The property value should be one of the forms accepted by 1565 * <code>Font.decode(String)</code> 1566 * If the specified property is not found, or the executing code does not 1567 * have permission to read the property, the <code>font</code> 1568 * argument is returned instead. 1569 * @param nm the case-insensitive property name 1570 * @param font a default <code>Font</code> to return if property 1571 * <code>nm</code> is not defined 1572 * @return the <code>Font</code> value of the property. 1573 * @throws NullPointerException if nm is null. 1574 * @see #decode(String) 1575 */ 1576 public static Font getFont(String nm, Font font) { 1577 String str = null; 1578 try { 1579 str =System.getProperty(nm); 1580 } catch(SecurityException e) { 1581 } 1582 if (str == null) { 1583 return font; 1584 } 1585 return decode ( str ); 1586 } 1587 1588 transient int hash; 1589 /** 1590 * Returns a hashcode for this <code>Font</code>. 1591 * @return a hashcode value for this <code>Font</code>. 1592 * @since 1.0 1593 */ 1594 public int hashCode() { 1595 if (hash == 0) { 1596 hash = name.hashCode() ^ style ^ size; 1597 /* It is possible many fonts differ only in transform. 1598 * So include the transform in the hash calculation. 1599 * nonIdentityTx is set whenever there is a transform in 1600 * 'values'. The tests for null are required because it can 1601 * also be set for other reasons. 1602 */ 1603 if (nonIdentityTx && 1604 values != null && values.getTransform() != null) { 1605 hash ^= values.getTransform().hashCode(); 1606 } 1607 } 1608 return hash; 1609 } 1610 1611 /** 1612 * Compares this <code>Font</code> object to the specified 1613 * <code>Object</code>. 1614 * @param obj the <code>Object</code> to compare 1615 * @return <code>true</code> if the objects are the same 1616 * or if the argument is a <code>Font</code> object 1617 * describing the same font as this object; 1618 * <code>false</code> otherwise. 1619 * @since 1.0 1620 */ 1621 public boolean equals(Object obj) { 1622 if (obj == this) { 1623 return true; 1624 } 1625 1626 if (obj != null) { 1627 try { 1628 Font font = (Font)obj; 1629 if (size == font.size && 1630 style == font.style && 1631 nonIdentityTx == font.nonIdentityTx && 1632 hasLayoutAttributes == font.hasLayoutAttributes && 1633 pointSize == font.pointSize && 1634 name.equals(font.name)) { 1635 1636 /* 'values' is usually initialized lazily, except when 1637 * the font is constructed from a Map, or derived using 1638 * a Map or other values. So if only one font has 1639 * the field initialized we need to initialize it in 1640 * the other instance and compare. 1641 */ 1642 if (values == null) { 1643 if (font.values == null) { 1644 return true; 1645 } else { 1646 return getAttributeValues().equals(font.values); 1647 } 1648 } else { 1649 return values.equals(font.getAttributeValues()); 1650 } 1651 } 1652 } 1653 catch (ClassCastException e) { 1654 } 1655 } 1656 return false; 1657 } 1658 1659 /** 1660 * Converts this <code>Font</code> object to a <code>String</code> 1661 * representation. 1662 * @return a <code>String</code> representation of this 1663 * <code>Font</code> object. 1664 * @since 1.0 1665 */ 1666 // NOTE: This method may be called by privileged threads. 1667 // DO NOT INVOKE CLIENT CODE ON THIS THREAD! 1668 public String toString() { 1669 String strStyle; 1670 1671 if (isBold()) { 1672 strStyle = isItalic() ? "bolditalic" : "bold"; 1673 } else { 1674 strStyle = isItalic() ? "italic" : "plain"; 1675 } 1676 1677 return getClass().getName() + "[family=" + getFamily() + ",name=" + name + ",style=" + 1678 strStyle + ",size=" + size + "]"; 1679 } // toString() 1680 1681 1682 /** Serialization support. A <code>readObject</code> 1683 * method is necessary because the constructor creates 1684 * the font's peer, and we can't serialize the peer. 1685 * Similarly the computed font "family" may be different 1686 * at <code>readObject</code> time than at 1687 * <code>writeObject</code> time. An integer version is 1688 * written so that future versions of this class will be 1689 * able to recognize serialized output from this one. 1690 */ 1691 /** 1692 * The <code>Font</code> Serializable Data Form. 1693 * 1694 * @serial 1695 */ 1696 private int fontSerializedDataVersion = 1; 1697 1698 /** 1699 * Writes default serializable fields to a stream. 1700 * 1701 * @param s the <code>ObjectOutputStream</code> to write 1702 * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener) 1703 * @see #readObject(java.io.ObjectInputStream) 1704 */ 1705 private void writeObject(java.io.ObjectOutputStream s) 1706 throws java.lang.ClassNotFoundException, 1707 java.io.IOException 1708 { 1709 if (values != null) { 1710 synchronized(values) { 1711 // transient 1712 fRequestedAttributes = values.toSerializableHashtable(); 1713 s.defaultWriteObject(); 1714 fRequestedAttributes = null; 1715 } 1716 } else { 1717 s.defaultWriteObject(); 1718 } 1719 } 1720 1721 /** 1722 * Reads the <code>ObjectInputStream</code>. 1723 * Unrecognized keys or values will be ignored. 1724 * 1725 * @param s the <code>ObjectInputStream</code> to read 1726 * @serial 1727 * @see #writeObject(java.io.ObjectOutputStream) 1728 */ 1729 private void readObject(java.io.ObjectInputStream s) 1730 throws java.lang.ClassNotFoundException, 1731 java.io.IOException 1732 { 1733 s.defaultReadObject(); 1734 if (pointSize == 0) { 1735 pointSize = (float)size; 1736 } 1737 1738 // Handle fRequestedAttributes. 1739 // in 1.5, we always streamed out the font values plus 1740 // TRANSFORM, SUPERSCRIPT, and WIDTH, regardless of whether the 1741 // values were default or not. In 1.6 we only stream out 1742 // defined values. So, 1.6 streams in from a 1.5 stream, 1743 // it check each of these values and 'undefines' it if the 1744 // value is the default. 1745 1746 if (fRequestedAttributes != null) { 1747 values = getAttributeValues(); // init 1748 AttributeValues extras = 1749 AttributeValues.fromSerializableHashtable(fRequestedAttributes); 1750 if (!AttributeValues.is16Hashtable(fRequestedAttributes)) { 1751 extras.unsetDefault(); // if legacy stream, undefine these 1752 } 1753 values = getAttributeValues().merge(extras); 1754 this.nonIdentityTx = values.anyNonDefault(EXTRA_MASK); 1755 this.hasLayoutAttributes = values.anyNonDefault(LAYOUT_MASK); 1756 1757 fRequestedAttributes = null; // don't need it any more 1758 } 1759 } 1760 1761 /** 1762 * Returns the number of glyphs in this <code>Font</code>. Glyph codes 1763 * for this <code>Font</code> range from 0 to 1764 * <code>getNumGlyphs()</code> - 1. 1765 * @return the number of glyphs in this <code>Font</code>. 1766 * @since 1.2 1767 */ 1768 public int getNumGlyphs() { 1769 return getFont2D().getNumGlyphs(); 1770 } 1771 1772 /** 1773 * Returns the glyphCode which is used when this <code>Font</code> 1774 * does not have a glyph for a specified unicode code point. 1775 * @return the glyphCode of this <code>Font</code>. 1776 * @since 1.2 1777 */ 1778 public int getMissingGlyphCode() { 1779 return getFont2D().getMissingGlyphCode(); 1780 } 1781 1782 /** 1783 * Returns the baseline appropriate for displaying this character. 1784 * <p> 1785 * Large fonts can support different writing systems, and each system can 1786 * use a different baseline. 1787 * The character argument determines the writing system to use. Clients 1788 * should not assume all characters use the same baseline. 1789 * 1790 * @param c a character used to identify the writing system 1791 * @return the baseline appropriate for the specified character. 1792 * @see LineMetrics#getBaselineOffsets 1793 * @see #ROMAN_BASELINE 1794 * @see #CENTER_BASELINE 1795 * @see #HANGING_BASELINE 1796 * @since 1.2 1797 */ 1798 public byte getBaselineFor(char c) { 1799 return getFont2D().getBaselineFor(c); 1800 } 1801 1802 /** 1803 * Returns a map of font attributes available in this 1804 * <code>Font</code>. Attributes include things like ligatures and 1805 * glyph substitution. 1806 * @return the attributes map of this <code>Font</code>. 1807 */ 1808 public Map<TextAttribute,?> getAttributes(){ 1809 return new AttributeMap(getAttributeValues()); 1810 } 1811 1812 /** 1813 * Returns the keys of all the attributes supported by this 1814 * <code>Font</code>. These attributes can be used to derive other 1815 * fonts. 1816 * @return an array containing the keys of all the attributes 1817 * supported by this <code>Font</code>. 1818 * @since 1.2 1819 */ 1820 public Attribute[] getAvailableAttributes() { 1821 // FONT is not supported by Font 1822 1823 Attribute attributes[] = { 1824 TextAttribute.FAMILY, 1825 TextAttribute.WEIGHT, 1826 TextAttribute.WIDTH, 1827 TextAttribute.POSTURE, 1828 TextAttribute.SIZE, 1829 TextAttribute.TRANSFORM, 1830 TextAttribute.SUPERSCRIPT, 1831 TextAttribute.CHAR_REPLACEMENT, 1832 TextAttribute.FOREGROUND, 1833 TextAttribute.BACKGROUND, 1834 TextAttribute.UNDERLINE, 1835 TextAttribute.STRIKETHROUGH, 1836 TextAttribute.RUN_DIRECTION, 1837 TextAttribute.BIDI_EMBEDDING, 1838 TextAttribute.JUSTIFICATION, 1839 TextAttribute.INPUT_METHOD_HIGHLIGHT, 1840 TextAttribute.INPUT_METHOD_UNDERLINE, 1841 TextAttribute.SWAP_COLORS, 1842 TextAttribute.NUMERIC_SHAPING, 1843 TextAttribute.KERNING, 1844 TextAttribute.LIGATURES, 1845 TextAttribute.TRACKING, 1846 }; 1847 1848 return attributes; 1849 } 1850 1851 /** 1852 * Creates a new <code>Font</code> object by replicating this 1853 * <code>Font</code> object and applying a new style and size. 1854 * @param style the style for the new <code>Font</code> 1855 * @param size the size for the new <code>Font</code> 1856 * @return a new <code>Font</code> object. 1857 * @since 1.2 1858 */ 1859 public Font deriveFont(int style, float size){ 1860 if (values == null) { 1861 return new Font(name, style, size, createdFont, font2DHandle); 1862 } 1863 AttributeValues newValues = getAttributeValues().clone(); 1864 int oldStyle = (this.style != style) ? this.style : -1; 1865 applyStyle(style, newValues); 1866 newValues.setSize(size); 1867 return new Font(newValues, null, oldStyle, createdFont, font2DHandle); 1868 } 1869 1870 /** 1871 * Creates a new <code>Font</code> object by replicating this 1872 * <code>Font</code> object and applying a new style and transform. 1873 * @param style the style for the new <code>Font</code> 1874 * @param trans the <code>AffineTransform</code> associated with the 1875 * new <code>Font</code> 1876 * @return a new <code>Font</code> object. 1877 * @throws IllegalArgumentException if <code>trans</code> is 1878 * <code>null</code> 1879 * @since 1.2 1880 */ 1881 public Font deriveFont(int style, AffineTransform trans){ 1882 AttributeValues newValues = getAttributeValues().clone(); 1883 int oldStyle = (this.style != style) ? this.style : -1; 1884 applyStyle(style, newValues); 1885 applyTransform(trans, newValues); 1886 return new Font(newValues, null, oldStyle, createdFont, font2DHandle); 1887 } 1888 1889 /** 1890 * Creates a new <code>Font</code> object by replicating the current 1891 * <code>Font</code> object and applying a new size to it. 1892 * @param size the size for the new <code>Font</code>. 1893 * @return a new <code>Font</code> object. 1894 * @since 1.2 1895 */ 1896 public Font deriveFont(float size){ 1897 if (values == null) { 1898 return new Font(name, style, size, createdFont, font2DHandle); 1899 } 1900 AttributeValues newValues = getAttributeValues().clone(); 1901 newValues.setSize(size); 1902 return new Font(newValues, null, -1, createdFont, font2DHandle); 1903 } 1904 1905 /** 1906 * Creates a new <code>Font</code> object by replicating the current 1907 * <code>Font</code> object and applying a new transform to it. 1908 * @param trans the <code>AffineTransform</code> associated with the 1909 * new <code>Font</code> 1910 * @return a new <code>Font</code> object. 1911 * @throws IllegalArgumentException if <code>trans</code> is 1912 * <code>null</code> 1913 * @since 1.2 1914 */ 1915 public Font deriveFont(AffineTransform trans){ 1916 AttributeValues newValues = getAttributeValues().clone(); 1917 applyTransform(trans, newValues); 1918 return new Font(newValues, null, -1, createdFont, font2DHandle); 1919 } 1920 1921 /** 1922 * Creates a new <code>Font</code> object by replicating the current 1923 * <code>Font</code> object and applying a new style to it. 1924 * @param style the style for the new <code>Font</code> 1925 * @return a new <code>Font</code> object. 1926 * @since 1.2 1927 */ 1928 public Font deriveFont(int style){ 1929 if (values == null) { 1930 return new Font(name, style, size, createdFont, font2DHandle); 1931 } 1932 AttributeValues newValues = getAttributeValues().clone(); 1933 int oldStyle = (this.style != style) ? this.style : -1; 1934 applyStyle(style, newValues); 1935 return new Font(newValues, null, oldStyle, createdFont, font2DHandle); 1936 } 1937 1938 /** 1939 * Creates a new <code>Font</code> object by replicating the current 1940 * <code>Font</code> object and applying a new set of font attributes 1941 * to it. 1942 * 1943 * @param attributes a map of attributes enabled for the new 1944 * <code>Font</code> 1945 * @return a new <code>Font</code> object. 1946 * @since 1.2 1947 */ 1948 public Font deriveFont(Map<? extends Attribute, ?> attributes) { 1949 if (attributes == null) { 1950 return this; 1951 } 1952 AttributeValues newValues = getAttributeValues().clone(); 1953 newValues.merge(attributes, RECOGNIZED_MASK); 1954 1955 return new Font(newValues, name, style, createdFont, font2DHandle); 1956 } 1957 1958 /** 1959 * Checks if this <code>Font</code> has a glyph for the specified 1960 * character. 1961 * 1962 * <p> <b>Note:</b> This method cannot handle <a 1963 * href="../../java/lang/Character.html#supplementary"> supplementary 1964 * characters</a>. To support all Unicode characters, including 1965 * supplementary characters, use the {@link #canDisplay(int)} 1966 * method or <code>canDisplayUpTo</code> methods. 1967 * 1968 * @param c the character for which a glyph is needed 1969 * @return <code>true</code> if this <code>Font</code> has a glyph for this 1970 * character; <code>false</code> otherwise. 1971 * @since 1.2 1972 */ 1973 public boolean canDisplay(char c){ 1974 return getFont2D().canDisplay(c); 1975 } 1976 1977 /** 1978 * Checks if this <code>Font</code> has a glyph for the specified 1979 * character. 1980 * 1981 * @param codePoint the character (Unicode code point) for which a glyph 1982 * is needed. 1983 * @return <code>true</code> if this <code>Font</code> has a glyph for the 1984 * character; <code>false</code> otherwise. 1985 * @throws IllegalArgumentException if the code point is not a valid Unicode 1986 * code point. 1987 * @see Character#isValidCodePoint(int) 1988 * @since 1.5 1989 */ 1990 public boolean canDisplay(int codePoint) { 1991 if (!Character.isValidCodePoint(codePoint)) { 1992 throw new IllegalArgumentException("invalid code point: " + 1993 Integer.toHexString(codePoint)); 1994 } 1995 return getFont2D().canDisplay(codePoint); 1996 } 1997 1998 /** 1999 * Indicates whether or not this <code>Font</code> can display a 2000 * specified <code>String</code>. For strings with Unicode encoding, 2001 * it is important to know if a particular font can display the 2002 * string. This method returns an offset into the <code>String</code> 2003 * <code>str</code> which is the first character this 2004 * <code>Font</code> cannot display without using the missing glyph 2005 * code. If the <code>Font</code> can display all characters, -1 is 2006 * returned. 2007 * @param str a <code>String</code> object 2008 * @return an offset into <code>str</code> that points 2009 * to the first character in <code>str</code> that this 2010 * <code>Font</code> cannot display; or <code>-1</code> if 2011 * this <code>Font</code> can display all characters in 2012 * <code>str</code>. 2013 * @since 1.2 2014 */ 2015 public int canDisplayUpTo(String str) { 2016 Font2D font2d = getFont2D(); 2017 int len = str.length(); 2018 for (int i = 0; i < len; i++) { 2019 char c = str.charAt(i); 2020 if (font2d.canDisplay(c)) { 2021 continue; 2022 } 2023 if (!Character.isHighSurrogate(c)) { 2024 return i; 2025 } 2026 if (!font2d.canDisplay(str.codePointAt(i))) { 2027 return i; 2028 } 2029 i++; 2030 } 2031 return -1; 2032 } 2033 2034 /** 2035 * Indicates whether or not this <code>Font</code> can display 2036 * the characters in the specified <code>text</code> 2037 * starting at <code>start</code> and ending at 2038 * <code>limit</code>. This method is a convenience overload. 2039 * @param text the specified array of <code>char</code> values 2040 * @param start the specified starting offset (in 2041 * <code>char</code>s) into the specified array of 2042 * <code>char</code> values 2043 * @param limit the specified ending offset (in 2044 * <code>char</code>s) into the specified array of 2045 * <code>char</code> values 2046 * @return an offset into <code>text</code> that points 2047 * to the first character in <code>text</code> that this 2048 * <code>Font</code> cannot display; or <code>-1</code> if 2049 * this <code>Font</code> can display all characters in 2050 * <code>text</code>. 2051 * @since 1.2 2052 */ 2053 public int canDisplayUpTo(char[] text, int start, int limit) { 2054 Font2D font2d = getFont2D(); 2055 for (int i = start; i < limit; i++) { 2056 char c = text[i]; 2057 if (font2d.canDisplay(c)) { 2058 continue; 2059 } 2060 if (!Character.isHighSurrogate(c)) { 2061 return i; 2062 } 2063 if (!font2d.canDisplay(Character.codePointAt(text, i, limit))) { 2064 return i; 2065 } 2066 i++; 2067 } 2068 return -1; 2069 } 2070 2071 /** 2072 * Indicates whether or not this <code>Font</code> can display the 2073 * text specified by the <code>iter</code> starting at 2074 * <code>start</code> and ending at <code>limit</code>. 2075 * 2076 * @param iter a {@link CharacterIterator} object 2077 * @param start the specified starting offset into the specified 2078 * <code>CharacterIterator</code>. 2079 * @param limit the specified ending offset into the specified 2080 * <code>CharacterIterator</code>. 2081 * @return an offset into <code>iter</code> that points 2082 * to the first character in <code>iter</code> that this 2083 * <code>Font</code> cannot display; or <code>-1</code> if 2084 * this <code>Font</code> can display all characters in 2085 * <code>iter</code>. 2086 * @since 1.2 2087 */ 2088 public int canDisplayUpTo(CharacterIterator iter, int start, int limit) { 2089 Font2D font2d = getFont2D(); 2090 char c = iter.setIndex(start); 2091 for (int i = start; i < limit; i++, c = iter.next()) { 2092 if (font2d.canDisplay(c)) { 2093 continue; 2094 } 2095 if (!Character.isHighSurrogate(c)) { 2096 return i; 2097 } 2098 char c2 = iter.next(); 2099 // c2 could be CharacterIterator.DONE which is not a low surrogate. 2100 if (!Character.isLowSurrogate(c2)) { 2101 return i; 2102 } 2103 if (!font2d.canDisplay(Character.toCodePoint(c, c2))) { 2104 return i; 2105 } 2106 i++; 2107 } 2108 return -1; 2109 } 2110 2111 /** 2112 * Returns the italic angle of this <code>Font</code>. The italic angle 2113 * is the inverse slope of the caret which best matches the posture of this 2114 * <code>Font</code>. 2115 * @see TextAttribute#POSTURE 2116 * @return the angle of the ITALIC style of this <code>Font</code>. 2117 */ 2118 public float getItalicAngle() { 2119 return getItalicAngle(null); 2120 } 2121 2122 /* The FRC hints don't affect the value of the italic angle but 2123 * we need to pass them in to look up a strike. 2124 * If we can pass in ones already being used it can prevent an extra 2125 * strike from being allocated. Note that since italic angle is 2126 * a property of the font, the font transform is needed not the 2127 * device transform. Finally, this is private but the only caller of this 2128 * in the JDK - and the only likely caller - is in this same class. 2129 */ 2130 private float getItalicAngle(FontRenderContext frc) { 2131 Object aa, fm; 2132 if (frc == null) { 2133 aa = RenderingHints.VALUE_TEXT_ANTIALIAS_OFF; 2134 fm = RenderingHints.VALUE_FRACTIONALMETRICS_OFF; 2135 } else { 2136 aa = frc.getAntiAliasingHint(); 2137 fm = frc.getFractionalMetricsHint(); 2138 } 2139 return getFont2D().getItalicAngle(this, identityTx, aa, fm); 2140 } 2141 2142 /** 2143 * Checks whether or not this <code>Font</code> has uniform 2144 * line metrics. A logical <code>Font</code> might be a 2145 * composite font, which means that it is composed of different 2146 * physical fonts to cover different code ranges. Each of these 2147 * fonts might have different <code>LineMetrics</code>. If the 2148 * logical <code>Font</code> is a single 2149 * font then the metrics would be uniform. 2150 * @return <code>true</code> if this <code>Font</code> has 2151 * uniform line metrics; <code>false</code> otherwise. 2152 */ 2153 public boolean hasUniformLineMetrics() { 2154 return false; // REMIND always safe, but prevents caller optimize 2155 } 2156 2157 private transient SoftReference<FontLineMetrics> flmref; 2158 private FontLineMetrics defaultLineMetrics(FontRenderContext frc) { 2159 FontLineMetrics flm = null; 2160 if (flmref == null 2161 || (flm = flmref.get()) == null 2162 || !flm.frc.equals(frc)) { 2163 2164 /* The device transform in the frc is not used in obtaining line 2165 * metrics, although it probably should be: REMIND find why not? 2166 * The font transform is used but its applied in getFontMetrics, so 2167 * just pass identity here 2168 */ 2169 float [] metrics = new float[8]; 2170 getFont2D().getFontMetrics(this, identityTx, 2171 frc.getAntiAliasingHint(), 2172 frc.getFractionalMetricsHint(), 2173 metrics); 2174 float ascent = metrics[0]; 2175 float descent = metrics[1]; 2176 float leading = metrics[2]; 2177 float ssOffset = 0; 2178 if (values != null && values.getSuperscript() != 0) { 2179 ssOffset = (float)getTransform().getTranslateY(); 2180 ascent -= ssOffset; 2181 descent += ssOffset; 2182 } 2183 float height = ascent + descent + leading; 2184 2185 int baselineIndex = 0; // need real index, assumes roman for everything 2186 // need real baselines eventually 2187 float[] baselineOffsets = { 0, (descent/2f - ascent) / 2f, -ascent }; 2188 2189 float strikethroughOffset = metrics[4]; 2190 float strikethroughThickness = metrics[5]; 2191 2192 float underlineOffset = metrics[6]; 2193 float underlineThickness = metrics[7]; 2194 2195 float italicAngle = getItalicAngle(frc); 2196 2197 if (isTransformed()) { 2198 AffineTransform ctx = values.getCharTransform(); // extract rotation 2199 if (ctx != null) { 2200 Point2D.Float pt = new Point2D.Float(); 2201 pt.setLocation(0, strikethroughOffset); 2202 ctx.deltaTransform(pt, pt); 2203 strikethroughOffset = pt.y; 2204 pt.setLocation(0, strikethroughThickness); 2205 ctx.deltaTransform(pt, pt); 2206 strikethroughThickness = pt.y; 2207 pt.setLocation(0, underlineOffset); 2208 ctx.deltaTransform(pt, pt); 2209 underlineOffset = pt.y; 2210 pt.setLocation(0, underlineThickness); 2211 ctx.deltaTransform(pt, pt); 2212 underlineThickness = pt.y; 2213 } 2214 } 2215 strikethroughOffset += ssOffset; 2216 underlineOffset += ssOffset; 2217 2218 CoreMetrics cm = new CoreMetrics(ascent, descent, leading, height, 2219 baselineIndex, baselineOffsets, 2220 strikethroughOffset, strikethroughThickness, 2221 underlineOffset, underlineThickness, 2222 ssOffset, italicAngle); 2223 2224 flm = new FontLineMetrics(0, cm, frc); 2225 flmref = new SoftReference<FontLineMetrics>(flm); 2226 } 2227 2228 return (FontLineMetrics)flm.clone(); 2229 } 2230 2231 /** 2232 * Returns a {@link LineMetrics} object created with the specified 2233 * <code>String</code> and {@link FontRenderContext}. 2234 * @param str the specified <code>String</code> 2235 * @param frc the specified <code>FontRenderContext</code> 2236 * @return a <code>LineMetrics</code> object created with the 2237 * specified <code>String</code> and {@link FontRenderContext}. 2238 */ 2239 public LineMetrics getLineMetrics( String str, FontRenderContext frc) { 2240 FontLineMetrics flm = defaultLineMetrics(frc); 2241 flm.numchars = str.length(); 2242 return flm; 2243 } 2244 2245 /** 2246 * Returns a <code>LineMetrics</code> object created with the 2247 * specified arguments. 2248 * @param str the specified <code>String</code> 2249 * @param beginIndex the initial offset of <code>str</code> 2250 * @param limit the end offset of <code>str</code> 2251 * @param frc the specified <code>FontRenderContext</code> 2252 * @return a <code>LineMetrics</code> object created with the 2253 * specified arguments. 2254 */ 2255 public LineMetrics getLineMetrics( String str, 2256 int beginIndex, int limit, 2257 FontRenderContext frc) { 2258 FontLineMetrics flm = defaultLineMetrics(frc); 2259 int numChars = limit - beginIndex; 2260 flm.numchars = (numChars < 0)? 0: numChars; 2261 return flm; 2262 } 2263 2264 /** 2265 * Returns a <code>LineMetrics</code> object created with the 2266 * specified arguments. 2267 * @param chars an array of characters 2268 * @param beginIndex the initial offset of <code>chars</code> 2269 * @param limit the end offset of <code>chars</code> 2270 * @param frc the specified <code>FontRenderContext</code> 2271 * @return a <code>LineMetrics</code> object created with the 2272 * specified arguments. 2273 */ 2274 public LineMetrics getLineMetrics(char [] chars, 2275 int beginIndex, int limit, 2276 FontRenderContext frc) { 2277 FontLineMetrics flm = defaultLineMetrics(frc); 2278 int numChars = limit - beginIndex; 2279 flm.numchars = (numChars < 0)? 0: numChars; 2280 return flm; 2281 } 2282 2283 /** 2284 * Returns a <code>LineMetrics</code> object created with the 2285 * specified arguments. 2286 * @param ci the specified <code>CharacterIterator</code> 2287 * @param beginIndex the initial offset in <code>ci</code> 2288 * @param limit the end offset of <code>ci</code> 2289 * @param frc the specified <code>FontRenderContext</code> 2290 * @return a <code>LineMetrics</code> object created with the 2291 * specified arguments. 2292 */ 2293 public LineMetrics getLineMetrics(CharacterIterator ci, 2294 int beginIndex, int limit, 2295 FontRenderContext frc) { 2296 FontLineMetrics flm = defaultLineMetrics(frc); 2297 int numChars = limit - beginIndex; 2298 flm.numchars = (numChars < 0)? 0: numChars; 2299 return flm; 2300 } 2301 2302 /** 2303 * Returns the logical bounds of the specified <code>String</code> in 2304 * the specified <code>FontRenderContext</code>. The logical bounds 2305 * contains the origin, ascent, advance, and height, which includes 2306 * the leading. The logical bounds does not always enclose all the 2307 * text. For example, in some languages and in some fonts, accent 2308 * marks can be positioned above the ascent or below the descent. 2309 * To obtain a visual bounding box, which encloses all the text, 2310 * use the {@link TextLayout#getBounds() getBounds} method of 2311 * <code>TextLayout</code>. 2312 * <p>Note: The returned bounds is in baseline-relative coordinates 2313 * (see {@link java.awt.Font class notes}). 2314 * @param str the specified <code>String</code> 2315 * @param frc the specified <code>FontRenderContext</code> 2316 * @return a {@link Rectangle2D} that is the bounding box of the 2317 * specified <code>String</code> in the specified 2318 * <code>FontRenderContext</code>. 2319 * @see FontRenderContext 2320 * @see Font#createGlyphVector 2321 * @since 1.2 2322 */ 2323 public Rectangle2D getStringBounds( String str, FontRenderContext frc) { 2324 char[] array = str.toCharArray(); 2325 return getStringBounds(array, 0, array.length, frc); 2326 } 2327 2328 /** 2329 * Returns the logical bounds of the specified <code>String</code> in 2330 * the specified <code>FontRenderContext</code>. The logical bounds 2331 * contains the origin, ascent, advance, and height, which includes 2332 * the leading. The logical bounds does not always enclose all the 2333 * text. For example, in some languages and in some fonts, accent 2334 * marks can be positioned above the ascent or below the descent. 2335 * To obtain a visual bounding box, which encloses all the text, 2336 * use the {@link TextLayout#getBounds() getBounds} method of 2337 * <code>TextLayout</code>. 2338 * <p>Note: The returned bounds is in baseline-relative coordinates 2339 * (see {@link java.awt.Font class notes}). 2340 * @param str the specified <code>String</code> 2341 * @param beginIndex the initial offset of <code>str</code> 2342 * @param limit the end offset of <code>str</code> 2343 * @param frc the specified <code>FontRenderContext</code> 2344 * @return a <code>Rectangle2D</code> that is the bounding box of the 2345 * specified <code>String</code> in the specified 2346 * <code>FontRenderContext</code>. 2347 * @throws IndexOutOfBoundsException if <code>beginIndex</code> is 2348 * less than zero, or <code>limit</code> is greater than the 2349 * length of <code>str</code>, or <code>beginIndex</code> 2350 * is greater than <code>limit</code>. 2351 * @see FontRenderContext 2352 * @see Font#createGlyphVector 2353 * @since 1.2 2354 */ 2355 public Rectangle2D getStringBounds( String str, 2356 int beginIndex, int limit, 2357 FontRenderContext frc) { 2358 String substr = str.substring(beginIndex, limit); 2359 return getStringBounds(substr, frc); 2360 } 2361 2362 /** 2363 * Returns the logical bounds of the specified array of characters 2364 * in the specified <code>FontRenderContext</code>. The logical 2365 * bounds contains the origin, ascent, advance, and height, which 2366 * includes the leading. The logical bounds does not always enclose 2367 * all the text. For example, in some languages and in some fonts, 2368 * accent marks can be positioned above the ascent or below the 2369 * descent. To obtain a visual bounding box, which encloses all the 2370 * text, use the {@link TextLayout#getBounds() getBounds} method of 2371 * <code>TextLayout</code>. 2372 * <p>Note: The returned bounds is in baseline-relative coordinates 2373 * (see {@link java.awt.Font class notes}). 2374 * @param chars an array of characters 2375 * @param beginIndex the initial offset in the array of 2376 * characters 2377 * @param limit the end offset in the array of characters 2378 * @param frc the specified <code>FontRenderContext</code> 2379 * @return a <code>Rectangle2D</code> that is the bounding box of the 2380 * specified array of characters in the specified 2381 * <code>FontRenderContext</code>. 2382 * @throws IndexOutOfBoundsException if <code>beginIndex</code> is 2383 * less than zero, or <code>limit</code> is greater than the 2384 * length of <code>chars</code>, or <code>beginIndex</code> 2385 * is greater than <code>limit</code>. 2386 * @see FontRenderContext 2387 * @see Font#createGlyphVector 2388 * @since 1.2 2389 */ 2390 public Rectangle2D getStringBounds(char [] chars, 2391 int beginIndex, int limit, 2392 FontRenderContext frc) { 2393 if (beginIndex < 0) { 2394 throw new IndexOutOfBoundsException("beginIndex: " + beginIndex); 2395 } 2396 if (limit > chars.length) { 2397 throw new IndexOutOfBoundsException("limit: " + limit); 2398 } 2399 if (beginIndex > limit) { 2400 throw new IndexOutOfBoundsException("range length: " + 2401 (limit - beginIndex)); 2402 } 2403 2404 // this code should be in textlayout 2405 // quick check for simple text, assume GV ok to use if simple 2406 2407 boolean simple = values == null || 2408 (values.getKerning() == 0 && values.getLigatures() == 0 && 2409 values.getBaselineTransform() == null); 2410 if (simple) { 2411 simple = ! FontUtilities.isComplexText(chars, beginIndex, limit); 2412 } 2413 2414 if (simple) { 2415 GlyphVector gv = new StandardGlyphVector(this, chars, beginIndex, 2416 limit - beginIndex, frc); 2417 return gv.getLogicalBounds(); 2418 } else { 2419 // need char array constructor on textlayout 2420 String str = new String(chars, beginIndex, limit - beginIndex); 2421 TextLayout tl = new TextLayout(str, this, frc); 2422 return new Rectangle2D.Float(0, -tl.getAscent(), tl.getAdvance(), 2423 tl.getAscent() + tl.getDescent() + 2424 tl.getLeading()); 2425 } 2426 } 2427 2428 /** 2429 * Returns the logical bounds of the characters indexed in the 2430 * specified {@link CharacterIterator} in the 2431 * specified <code>FontRenderContext</code>. The logical bounds 2432 * contains the origin, ascent, advance, and height, which includes 2433 * the leading. The logical bounds does not always enclose all the 2434 * text. For example, in some languages and in some fonts, accent 2435 * marks can be positioned above the ascent or below the descent. 2436 * To obtain a visual bounding box, which encloses all the text, 2437 * use the {@link TextLayout#getBounds() getBounds} method of 2438 * <code>TextLayout</code>. 2439 * <p>Note: The returned bounds is in baseline-relative coordinates 2440 * (see {@link java.awt.Font class notes}). 2441 * @param ci the specified <code>CharacterIterator</code> 2442 * @param beginIndex the initial offset in <code>ci</code> 2443 * @param limit the end offset in <code>ci</code> 2444 * @param frc the specified <code>FontRenderContext</code> 2445 * @return a <code>Rectangle2D</code> that is the bounding box of the 2446 * characters indexed in the specified <code>CharacterIterator</code> 2447 * in the specified <code>FontRenderContext</code>. 2448 * @see FontRenderContext 2449 * @see Font#createGlyphVector 2450 * @since 1.2 2451 * @throws IndexOutOfBoundsException if <code>beginIndex</code> is 2452 * less than the start index of <code>ci</code>, or 2453 * <code>limit</code> is greater than the end index of 2454 * <code>ci</code>, or <code>beginIndex</code> is greater 2455 * than <code>limit</code> 2456 */ 2457 public Rectangle2D getStringBounds(CharacterIterator ci, 2458 int beginIndex, int limit, 2459 FontRenderContext frc) { 2460 int start = ci.getBeginIndex(); 2461 int end = ci.getEndIndex(); 2462 2463 if (beginIndex < start) { 2464 throw new IndexOutOfBoundsException("beginIndex: " + beginIndex); 2465 } 2466 if (limit > end) { 2467 throw new IndexOutOfBoundsException("limit: " + limit); 2468 } 2469 if (beginIndex > limit) { 2470 throw new IndexOutOfBoundsException("range length: " + 2471 (limit - beginIndex)); 2472 } 2473 2474 char[] arr = new char[limit - beginIndex]; 2475 2476 ci.setIndex(beginIndex); 2477 for(int idx = 0; idx < arr.length; idx++) { 2478 arr[idx] = ci.current(); 2479 ci.next(); 2480 } 2481 2482 return getStringBounds(arr,0,arr.length,frc); 2483 } 2484 2485 /** 2486 * Returns the bounds for the character with the maximum 2487 * bounds as defined in the specified <code>FontRenderContext</code>. 2488 * <p>Note: The returned bounds is in baseline-relative coordinates 2489 * (see {@link java.awt.Font class notes}). 2490 * @param frc the specified <code>FontRenderContext</code> 2491 * @return a <code>Rectangle2D</code> that is the bounding box 2492 * for the character with the maximum bounds. 2493 */ 2494 public Rectangle2D getMaxCharBounds(FontRenderContext frc) { 2495 float [] metrics = new float[4]; 2496 2497 getFont2D().getFontMetrics(this, frc, metrics); 2498 2499 return new Rectangle2D.Float(0, -metrics[0], 2500 metrics[3], 2501 metrics[0] + metrics[1] + metrics[2]); 2502 } 2503 2504 /** 2505 * Creates a {@link java.awt.font.GlyphVector GlyphVector} by 2506 * mapping characters to glyphs one-to-one based on the 2507 * Unicode cmap in this <code>Font</code>. This method does no other 2508 * processing besides the mapping of glyphs to characters. This 2509 * means that this method is not useful for some scripts, such 2510 * as Arabic, Hebrew, Thai, and Indic, that require reordering, 2511 * shaping, or ligature substitution. 2512 * @param frc the specified <code>FontRenderContext</code> 2513 * @param str the specified <code>String</code> 2514 * @return a new <code>GlyphVector</code> created with the 2515 * specified <code>String</code> and the specified 2516 * <code>FontRenderContext</code>. 2517 */ 2518 public GlyphVector createGlyphVector(FontRenderContext frc, String str) 2519 { 2520 return (GlyphVector)new StandardGlyphVector(this, str, frc); 2521 } 2522 2523 /** 2524 * Creates a {@link java.awt.font.GlyphVector GlyphVector} by 2525 * mapping characters to glyphs one-to-one based on the 2526 * Unicode cmap in this <code>Font</code>. This method does no other 2527 * processing besides the mapping of glyphs to characters. This 2528 * means that this method is not useful for some scripts, such 2529 * as Arabic, Hebrew, Thai, and Indic, that require reordering, 2530 * shaping, or ligature substitution. 2531 * @param frc the specified <code>FontRenderContext</code> 2532 * @param chars the specified array of characters 2533 * @return a new <code>GlyphVector</code> created with the 2534 * specified array of characters and the specified 2535 * <code>FontRenderContext</code>. 2536 */ 2537 public GlyphVector createGlyphVector(FontRenderContext frc, char[] chars) 2538 { 2539 return (GlyphVector)new StandardGlyphVector(this, chars, frc); 2540 } 2541 2542 /** 2543 * Creates a {@link java.awt.font.GlyphVector GlyphVector} by 2544 * mapping the specified characters to glyphs one-to-one based on the 2545 * Unicode cmap in this <code>Font</code>. This method does no other 2546 * processing besides the mapping of glyphs to characters. This 2547 * means that this method is not useful for some scripts, such 2548 * as Arabic, Hebrew, Thai, and Indic, that require reordering, 2549 * shaping, or ligature substitution. 2550 * @param frc the specified <code>FontRenderContext</code> 2551 * @param ci the specified <code>CharacterIterator</code> 2552 * @return a new <code>GlyphVector</code> created with the 2553 * specified <code>CharacterIterator</code> and the specified 2554 * <code>FontRenderContext</code>. 2555 */ 2556 public GlyphVector createGlyphVector( FontRenderContext frc, 2557 CharacterIterator ci) 2558 { 2559 return (GlyphVector)new StandardGlyphVector(this, ci, frc); 2560 } 2561 2562 /** 2563 * Creates a {@link java.awt.font.GlyphVector GlyphVector} by 2564 * mapping characters to glyphs one-to-one based on the 2565 * Unicode cmap in this <code>Font</code>. This method does no other 2566 * processing besides the mapping of glyphs to characters. This 2567 * means that this method is not useful for some scripts, such 2568 * as Arabic, Hebrew, Thai, and Indic, that require reordering, 2569 * shaping, or ligature substitution. 2570 * @param frc the specified <code>FontRenderContext</code> 2571 * @param glyphCodes the specified integer array 2572 * @return a new <code>GlyphVector</code> created with the 2573 * specified integer array and the specified 2574 * <code>FontRenderContext</code>. 2575 */ 2576 public GlyphVector createGlyphVector( FontRenderContext frc, 2577 int [] glyphCodes) 2578 { 2579 return (GlyphVector)new StandardGlyphVector(this, glyphCodes, frc); 2580 } 2581 2582 /** 2583 * Returns a new <code>GlyphVector</code> object, performing full 2584 * layout of the text if possible. Full layout is required for 2585 * complex text, such as Arabic or Hindi. Support for different 2586 * scripts depends on the font and implementation. 2587 * <p> 2588 * Layout requires bidi analysis, as performed by 2589 * <code>Bidi</code>, and should only be performed on text that 2590 * has a uniform direction. The direction is indicated in the 2591 * flags parameter,by using LAYOUT_RIGHT_TO_LEFT to indicate a 2592 * right-to-left (Arabic and Hebrew) run direction, or 2593 * LAYOUT_LEFT_TO_RIGHT to indicate a left-to-right (English) 2594 * run direction. 2595 * <p> 2596 * In addition, some operations, such as Arabic shaping, require 2597 * context, so that the characters at the start and limit can have 2598 * the proper shapes. Sometimes the data in the buffer outside 2599 * the provided range does not have valid data. The values 2600 * LAYOUT_NO_START_CONTEXT and LAYOUT_NO_LIMIT_CONTEXT can be 2601 * added to the flags parameter to indicate that the text before 2602 * start, or after limit, respectively, should not be examined 2603 * for context. 2604 * <p> 2605 * All other values for the flags parameter are reserved. 2606 * 2607 * @param frc the specified <code>FontRenderContext</code> 2608 * @param text the text to layout 2609 * @param start the start of the text to use for the <code>GlyphVector</code> 2610 * @param limit the limit of the text to use for the <code>GlyphVector</code> 2611 * @param flags control flags as described above 2612 * @return a new <code>GlyphVector</code> representing the text between 2613 * start and limit, with glyphs chosen and positioned so as to best represent 2614 * the text 2615 * @throws ArrayIndexOutOfBoundsException if start or limit is 2616 * out of bounds 2617 * @see java.text.Bidi 2618 * @see #LAYOUT_LEFT_TO_RIGHT 2619 * @see #LAYOUT_RIGHT_TO_LEFT 2620 * @see #LAYOUT_NO_START_CONTEXT 2621 * @see #LAYOUT_NO_LIMIT_CONTEXT 2622 * @since 1.4 2623 */ 2624 public GlyphVector layoutGlyphVector(FontRenderContext frc, 2625 char[] text, 2626 int start, 2627 int limit, 2628 int flags) { 2629 2630 GlyphLayout gl = GlyphLayout.get(null); // !!! no custom layout engines 2631 StandardGlyphVector gv = gl.layout(this, frc, text, 2632 start, limit-start, flags, null); 2633 GlyphLayout.done(gl); 2634 return gv; 2635 } 2636 2637 /** 2638 * A flag to layoutGlyphVector indicating that text is left-to-right as 2639 * determined by Bidi analysis. 2640 */ 2641 public static final int LAYOUT_LEFT_TO_RIGHT = 0; 2642 2643 /** 2644 * A flag to layoutGlyphVector indicating that text is right-to-left as 2645 * determined by Bidi analysis. 2646 */ 2647 public static final int LAYOUT_RIGHT_TO_LEFT = 1; 2648 2649 /** 2650 * A flag to layoutGlyphVector indicating that text in the char array 2651 * before the indicated start should not be examined. 2652 */ 2653 public static final int LAYOUT_NO_START_CONTEXT = 2; 2654 2655 /** 2656 * A flag to layoutGlyphVector indicating that text in the char array 2657 * after the indicated limit should not be examined. 2658 */ 2659 public static final int LAYOUT_NO_LIMIT_CONTEXT = 4; 2660 2661 2662 private static void applyTransform(AffineTransform trans, AttributeValues values) { 2663 if (trans == null) { 2664 throw new IllegalArgumentException("transform must not be null"); 2665 } 2666 values.setTransform(trans); 2667 } 2668 2669 private static void applyStyle(int style, AttributeValues values) { 2670 // WEIGHT_BOLD, WEIGHT_REGULAR 2671 values.setWeight((style & BOLD) != 0 ? 2f : 1f); 2672 // POSTURE_OBLIQUE, POSTURE_REGULAR 2673 values.setPosture((style & ITALIC) != 0 ? .2f : 0f); 2674 } 2675 2676 /* 2677 * Initialize JNI field and method IDs 2678 */ 2679 private static native void initIDs(); 2680 }