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