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